webadmin.go 143 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221
  1. // Copyright (C) 2019 Nicola Murino
  2. //
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU Affero General Public License as published
  5. // by the Free Software Foundation, version 3.
  6. //
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU Affero General Public License for more details.
  11. //
  12. // You should have received a copy of the GNU Affero General Public License
  13. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. package httpd
  15. import (
  16. "context"
  17. "errors"
  18. "fmt"
  19. "html/template"
  20. "io"
  21. "net/http"
  22. "net/url"
  23. "os"
  24. "path/filepath"
  25. "sort"
  26. "strconv"
  27. "strings"
  28. "time"
  29. "github.com/go-chi/render"
  30. "github.com/sftpgo/sdk"
  31. sdkkms "github.com/sftpgo/sdk/kms"
  32. "github.com/drakkan/sftpgo/v2/internal/acme"
  33. "github.com/drakkan/sftpgo/v2/internal/common"
  34. "github.com/drakkan/sftpgo/v2/internal/dataprovider"
  35. "github.com/drakkan/sftpgo/v2/internal/kms"
  36. "github.com/drakkan/sftpgo/v2/internal/logger"
  37. "github.com/drakkan/sftpgo/v2/internal/mfa"
  38. "github.com/drakkan/sftpgo/v2/internal/plugin"
  39. "github.com/drakkan/sftpgo/v2/internal/smtp"
  40. "github.com/drakkan/sftpgo/v2/internal/util"
  41. "github.com/drakkan/sftpgo/v2/internal/vfs"
  42. )
  43. type userPageMode int
  44. const (
  45. userPageModeAdd userPageMode = iota + 1
  46. userPageModeUpdate
  47. userPageModeTemplate
  48. )
  49. type folderPageMode int
  50. const (
  51. folderPageModeAdd folderPageMode = iota + 1
  52. folderPageModeUpdate
  53. folderPageModeTemplate
  54. )
  55. type genericPageMode int
  56. const (
  57. genericPageModeAdd genericPageMode = iota + 1
  58. genericPageModeUpdate
  59. )
  60. const (
  61. templateAdminDir = "webadmin"
  62. templateBase = "base.html"
  63. templateFsConfig = "fsconfig.html"
  64. templateSharedComponents = "sharedcomponents.html"
  65. templateUsers = "users.html"
  66. templateUser = "user.html"
  67. templateAdmins = "admins.html"
  68. templateAdmin = "admin.html"
  69. templateConnections = "connections.html"
  70. templateGroups = "groups.html"
  71. templateGroup = "group.html"
  72. templateFolders = "folders.html"
  73. templateFolder = "folder.html"
  74. templateEventRules = "eventrules.html"
  75. templateEventRule = "eventrule.html"
  76. templateEventActions = "eventactions.html"
  77. templateEventAction = "eventaction.html"
  78. templateRoles = "roles.html"
  79. templateRole = "role.html"
  80. templateEvents = "events.html"
  81. templateStatus = "status.html"
  82. templateDefender = "defender.html"
  83. templateIPLists = "iplists.html"
  84. templateIPList = "iplist.html"
  85. templateConfigs = "configs.html"
  86. templateProfile = "profile.html"
  87. templateMaintenance = "maintenance.html"
  88. templateMFA = "mfa.html"
  89. templateSetup = "adminsetup.html"
  90. pageEventRulesTitle = "Event rules"
  91. pageEventActionsTitle = "Event actions"
  92. pageEventsTitle = "Logs"
  93. pageConfigsTitle = "Configurations"
  94. defaultQueryLimit = 1000
  95. inversePatternType = "inverse"
  96. )
  97. var (
  98. adminTemplates = make(map[string]*template.Template)
  99. )
  100. type basePage struct {
  101. commonBasePage
  102. Title string
  103. CurrentURL string
  104. UsersURL string
  105. UserURL string
  106. UserTemplateURL string
  107. AdminsURL string
  108. AdminURL string
  109. QuotaScanURL string
  110. ConnectionsURL string
  111. GroupsURL string
  112. GroupURL string
  113. FoldersURL string
  114. FolderURL string
  115. FolderTemplateURL string
  116. DefenderURL string
  117. IPListsURL string
  118. IPListURL string
  119. EventsURL string
  120. ConfigsURL string
  121. LogoutURL string
  122. LoginURL string
  123. ProfileURL string
  124. ChangePwdURL string
  125. MFAURL string
  126. EventRulesURL string
  127. EventRuleURL string
  128. EventActionsURL string
  129. EventActionURL string
  130. RolesURL string
  131. RoleURL string
  132. FolderQuotaScanURL string
  133. StatusURL string
  134. MaintenanceURL string
  135. CSRFToken string
  136. IsEventManagerPage bool
  137. IsIPManagerPage bool
  138. IsServerManagerPage bool
  139. HasDefender bool
  140. HasSearcher bool
  141. HasExternalLogin bool
  142. LoggedUser *dataprovider.Admin
  143. Branding UIBranding
  144. }
  145. type eventRulesPage struct {
  146. basePage
  147. Rules []dataprovider.EventRule
  148. }
  149. type eventActionsPage struct {
  150. basePage
  151. Actions []dataprovider.BaseEventAction
  152. }
  153. type statusPage struct {
  154. basePage
  155. Status *ServicesStatus
  156. }
  157. type fsWrapper struct {
  158. vfs.Filesystem
  159. IsUserPage bool
  160. IsGroupPage bool
  161. IsHidden bool
  162. HasUsersBaseDir bool
  163. DirPath string
  164. }
  165. type userPage struct {
  166. basePage
  167. User *dataprovider.User
  168. RootPerms []string
  169. Error *util.I18nError
  170. ValidPerms []string
  171. ValidLoginMethods []string
  172. ValidProtocols []string
  173. TwoFactorProtocols []string
  174. WebClientOptions []string
  175. RootDirPerms []string
  176. Mode userPageMode
  177. VirtualFolders []vfs.BaseVirtualFolder
  178. Groups []dataprovider.Group
  179. Roles []dataprovider.Role
  180. CanImpersonate bool
  181. FsWrapper fsWrapper
  182. }
  183. type adminPage struct {
  184. basePage
  185. Admin *dataprovider.Admin
  186. Groups []dataprovider.Group
  187. Roles []dataprovider.Role
  188. Error *util.I18nError
  189. IsAdd bool
  190. }
  191. type profilePage struct {
  192. basePage
  193. Error *util.I18nError
  194. AllowAPIKeyAuth bool
  195. Email string
  196. Description string
  197. }
  198. type changePasswordPage struct {
  199. basePage
  200. Error *util.I18nError
  201. }
  202. type mfaPage struct {
  203. basePage
  204. TOTPConfigs []string
  205. TOTPConfig dataprovider.AdminTOTPConfig
  206. GenerateTOTPURL string
  207. ValidateTOTPURL string
  208. SaveTOTPURL string
  209. RecCodesURL string
  210. }
  211. type maintenancePage struct {
  212. basePage
  213. BackupPath string
  214. RestorePath string
  215. Error *util.I18nError
  216. }
  217. type defenderHostsPage struct {
  218. basePage
  219. DefenderHostsURL string
  220. }
  221. type ipListsPage struct {
  222. basePage
  223. IPListsSearchURL string
  224. RateLimitersStatus bool
  225. RateLimitersProtocols string
  226. IsAllowListEnabled bool
  227. }
  228. type ipListPage struct {
  229. basePage
  230. Entry *dataprovider.IPListEntry
  231. Error *util.I18nError
  232. Mode genericPageMode
  233. }
  234. type setupPage struct {
  235. commonBasePage
  236. CurrentURL string
  237. Error *util.I18nError
  238. CSRFToken string
  239. Username string
  240. HasInstallationCode bool
  241. InstallationCodeHint string
  242. HideSupportLink bool
  243. Title string
  244. Branding UIBranding
  245. }
  246. type folderPage struct {
  247. basePage
  248. Folder vfs.BaseVirtualFolder
  249. Error *util.I18nError
  250. Mode folderPageMode
  251. FsWrapper fsWrapper
  252. }
  253. type groupPage struct {
  254. basePage
  255. Group *dataprovider.Group
  256. Error *util.I18nError
  257. Mode genericPageMode
  258. ValidPerms []string
  259. ValidLoginMethods []string
  260. ValidProtocols []string
  261. TwoFactorProtocols []string
  262. WebClientOptions []string
  263. VirtualFolders []vfs.BaseVirtualFolder
  264. FsWrapper fsWrapper
  265. }
  266. type rolePage struct {
  267. basePage
  268. Role *dataprovider.Role
  269. Error *util.I18nError
  270. Mode genericPageMode
  271. }
  272. type eventActionPage struct {
  273. basePage
  274. Action dataprovider.BaseEventAction
  275. ActionTypes []dataprovider.EnumMapping
  276. FsActions []dataprovider.EnumMapping
  277. HTTPMethods []string
  278. RedactedSecret string
  279. Error string
  280. Mode genericPageMode
  281. }
  282. type eventRulePage struct {
  283. basePage
  284. Rule dataprovider.EventRule
  285. TriggerTypes []dataprovider.EnumMapping
  286. Actions []dataprovider.BaseEventAction
  287. FsEvents []string
  288. Protocols []string
  289. ProviderEvents []string
  290. ProviderObjects []string
  291. Error string
  292. Mode genericPageMode
  293. IsShared bool
  294. }
  295. type eventsPage struct {
  296. basePage
  297. FsEventsSearchURL string
  298. ProviderEventsSearchURL string
  299. LogEventsSearchURL string
  300. }
  301. type configsPage struct {
  302. basePage
  303. Configs dataprovider.Configs
  304. ConfigSection int
  305. RedactedSecret string
  306. OAuth2TokenURL string
  307. OAuth2RedirectURL string
  308. Error string
  309. }
  310. type messagePage struct {
  311. basePage
  312. Error *util.I18nError
  313. Success string
  314. Text string
  315. }
  316. type userTemplateFields struct {
  317. Username string
  318. Password string
  319. PublicKeys []string
  320. }
  321. func loadAdminTemplates(templatesPath string) {
  322. usersPaths := []string{
  323. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  324. filepath.Join(templatesPath, templateAdminDir, templateBase),
  325. filepath.Join(templatesPath, templateAdminDir, templateUsers),
  326. }
  327. userPaths := []string{
  328. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  329. filepath.Join(templatesPath, templateAdminDir, templateBase),
  330. filepath.Join(templatesPath, templateAdminDir, templateFsConfig),
  331. filepath.Join(templatesPath, templateAdminDir, templateUser),
  332. }
  333. adminsPaths := []string{
  334. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  335. filepath.Join(templatesPath, templateAdminDir, templateBase),
  336. filepath.Join(templatesPath, templateAdminDir, templateAdmins),
  337. }
  338. adminPaths := []string{
  339. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  340. filepath.Join(templatesPath, templateAdminDir, templateBase),
  341. filepath.Join(templatesPath, templateAdminDir, templateAdmin),
  342. }
  343. profilePaths := []string{
  344. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  345. filepath.Join(templatesPath, templateAdminDir, templateBase),
  346. filepath.Join(templatesPath, templateAdminDir, templateProfile),
  347. }
  348. changePwdPaths := []string{
  349. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  350. filepath.Join(templatesPath, templateAdminDir, templateBase),
  351. filepath.Join(templatesPath, templateCommonDir, templateChangePwd),
  352. }
  353. connectionsPaths := []string{
  354. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  355. filepath.Join(templatesPath, templateAdminDir, templateBase),
  356. filepath.Join(templatesPath, templateAdminDir, templateConnections),
  357. }
  358. messagePaths := []string{
  359. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  360. filepath.Join(templatesPath, templateAdminDir, templateBase),
  361. filepath.Join(templatesPath, templateCommonDir, templateMessage),
  362. }
  363. foldersPaths := []string{
  364. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  365. filepath.Join(templatesPath, templateAdminDir, templateBase),
  366. filepath.Join(templatesPath, templateAdminDir, templateFolders),
  367. }
  368. folderPaths := []string{
  369. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  370. filepath.Join(templatesPath, templateAdminDir, templateBase),
  371. filepath.Join(templatesPath, templateAdminDir, templateFsConfig),
  372. filepath.Join(templatesPath, templateAdminDir, templateFolder),
  373. }
  374. groupsPaths := []string{
  375. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  376. filepath.Join(templatesPath, templateAdminDir, templateBase),
  377. filepath.Join(templatesPath, templateAdminDir, templateGroups),
  378. }
  379. groupPaths := []string{
  380. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  381. filepath.Join(templatesPath, templateAdminDir, templateBase),
  382. filepath.Join(templatesPath, templateAdminDir, templateFsConfig),
  383. filepath.Join(templatesPath, templateAdminDir, templateGroup),
  384. }
  385. eventRulesPaths := []string{
  386. filepath.Join(templatesPath, templateCommonDir, templateCommonCSS),
  387. filepath.Join(templatesPath, templateAdminDir, templateBase),
  388. filepath.Join(templatesPath, templateAdminDir, templateEventRules),
  389. }
  390. eventRulePaths := []string{
  391. filepath.Join(templatesPath, templateCommonDir, templateCommonCSS),
  392. filepath.Join(templatesPath, templateAdminDir, templateBase),
  393. filepath.Join(templatesPath, templateAdminDir, templateEventRule),
  394. }
  395. eventActionsPaths := []string{
  396. filepath.Join(templatesPath, templateCommonDir, templateCommonCSS),
  397. filepath.Join(templatesPath, templateAdminDir, templateBase),
  398. filepath.Join(templatesPath, templateAdminDir, templateEventActions),
  399. }
  400. eventActionPaths := []string{
  401. filepath.Join(templatesPath, templateCommonDir, templateCommonCSS),
  402. filepath.Join(templatesPath, templateAdminDir, templateBase),
  403. filepath.Join(templatesPath, templateAdminDir, templateEventAction),
  404. }
  405. statusPaths := []string{
  406. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  407. filepath.Join(templatesPath, templateAdminDir, templateBase),
  408. filepath.Join(templatesPath, templateAdminDir, templateStatus),
  409. }
  410. loginPaths := []string{
  411. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  412. filepath.Join(templatesPath, templateCommonDir, templateCommonBaseLogin),
  413. filepath.Join(templatesPath, templateCommonDir, templateCommonLogin),
  414. }
  415. maintenancePaths := []string{
  416. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  417. filepath.Join(templatesPath, templateAdminDir, templateBase),
  418. filepath.Join(templatesPath, templateAdminDir, templateMaintenance),
  419. }
  420. defenderPaths := []string{
  421. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  422. filepath.Join(templatesPath, templateAdminDir, templateBase),
  423. filepath.Join(templatesPath, templateAdminDir, templateDefender),
  424. }
  425. ipListsPaths := []string{
  426. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  427. filepath.Join(templatesPath, templateAdminDir, templateBase),
  428. filepath.Join(templatesPath, templateAdminDir, templateIPLists),
  429. }
  430. ipListPaths := []string{
  431. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  432. filepath.Join(templatesPath, templateAdminDir, templateBase),
  433. filepath.Join(templatesPath, templateAdminDir, templateIPList),
  434. }
  435. mfaPaths := []string{
  436. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  437. filepath.Join(templatesPath, templateAdminDir, templateBase),
  438. filepath.Join(templatesPath, templateAdminDir, templateMFA),
  439. }
  440. twoFactorPaths := []string{
  441. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  442. filepath.Join(templatesPath, templateCommonDir, templateCommonBaseLogin),
  443. filepath.Join(templatesPath, templateCommonDir, templateTwoFactor),
  444. }
  445. twoFactorRecoveryPaths := []string{
  446. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  447. filepath.Join(templatesPath, templateCommonDir, templateCommonBaseLogin),
  448. filepath.Join(templatesPath, templateCommonDir, templateTwoFactorRecovery),
  449. }
  450. setupPaths := []string{
  451. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  452. filepath.Join(templatesPath, templateCommonDir, templateCommonBaseLogin),
  453. filepath.Join(templatesPath, templateAdminDir, templateSetup),
  454. }
  455. forgotPwdPaths := []string{
  456. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  457. filepath.Join(templatesPath, templateCommonDir, templateCommonBaseLogin),
  458. filepath.Join(templatesPath, templateCommonDir, templateForgotPassword),
  459. }
  460. resetPwdPaths := []string{
  461. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  462. filepath.Join(templatesPath, templateCommonDir, templateCommonBaseLogin),
  463. filepath.Join(templatesPath, templateCommonDir, templateResetPassword),
  464. }
  465. rolesPaths := []string{
  466. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  467. filepath.Join(templatesPath, templateAdminDir, templateBase),
  468. filepath.Join(templatesPath, templateAdminDir, templateRoles),
  469. }
  470. rolePaths := []string{
  471. filepath.Join(templatesPath, templateCommonDir, templateCommonBase),
  472. filepath.Join(templatesPath, templateAdminDir, templateBase),
  473. filepath.Join(templatesPath, templateAdminDir, templateRole),
  474. }
  475. eventsPaths := []string{
  476. filepath.Join(templatesPath, templateCommonDir, templateCommonCSS),
  477. filepath.Join(templatesPath, templateAdminDir, templateBase),
  478. filepath.Join(templatesPath, templateAdminDir, templateEvents),
  479. }
  480. configsPaths := []string{
  481. filepath.Join(templatesPath, templateCommonDir, templateCommonCSS),
  482. filepath.Join(templatesPath, templateAdminDir, templateBase),
  483. filepath.Join(templatesPath, templateAdminDir, templateConfigs),
  484. }
  485. fsBaseTpl := template.New("fsBaseTemplate").Funcs(template.FuncMap{
  486. "ListFSProviders": func() []dataprovider.FilesystemProvider {
  487. return []dataprovider.FilesystemProvider{
  488. {FilesystemProvider: sdk.LocalFilesystemProvider},
  489. {FilesystemProvider: sdk.CryptedFilesystemProvider},
  490. {FilesystemProvider: sdk.S3FilesystemProvider},
  491. {FilesystemProvider: sdk.GCSFilesystemProvider},
  492. {FilesystemProvider: sdk.AzureBlobFilesystemProvider},
  493. {FilesystemProvider: sdk.SFTPFilesystemProvider},
  494. {FilesystemProvider: sdk.HTTPFilesystemProvider},
  495. }
  496. },
  497. "HumanizeBytes": util.ByteCountSI,
  498. })
  499. usersTmpl := util.LoadTemplate(nil, usersPaths...)
  500. userTmpl := util.LoadTemplate(fsBaseTpl, userPaths...)
  501. adminsTmpl := util.LoadTemplate(nil, adminsPaths...)
  502. adminTmpl := util.LoadTemplate(nil, adminPaths...)
  503. connectionsTmpl := util.LoadTemplate(nil, connectionsPaths...)
  504. messageTmpl := util.LoadTemplate(nil, messagePaths...)
  505. groupsTmpl := util.LoadTemplate(nil, groupsPaths...)
  506. groupTmpl := util.LoadTemplate(fsBaseTpl, groupPaths...)
  507. foldersTmpl := util.LoadTemplate(nil, foldersPaths...)
  508. folderTmpl := util.LoadTemplate(fsBaseTpl, folderPaths...)
  509. eventRulesTmpl := util.LoadTemplate(nil, eventRulesPaths...)
  510. eventRuleTmpl := util.LoadTemplate(fsBaseTpl, eventRulePaths...)
  511. eventActionsTmpl := util.LoadTemplate(nil, eventActionsPaths...)
  512. eventActionTmpl := util.LoadTemplate(nil, eventActionPaths...)
  513. statusTmpl := util.LoadTemplate(nil, statusPaths...)
  514. loginTmpl := util.LoadTemplate(nil, loginPaths...)
  515. profileTmpl := util.LoadTemplate(nil, profilePaths...)
  516. changePwdTmpl := util.LoadTemplate(nil, changePwdPaths...)
  517. maintenanceTmpl := util.LoadTemplate(nil, maintenancePaths...)
  518. defenderTmpl := util.LoadTemplate(nil, defenderPaths...)
  519. ipListsTmpl := util.LoadTemplate(nil, ipListsPaths...)
  520. ipListTmpl := util.LoadTemplate(nil, ipListPaths...)
  521. mfaTmpl := util.LoadTemplate(nil, mfaPaths...)
  522. twoFactorTmpl := util.LoadTemplate(nil, twoFactorPaths...)
  523. twoFactorRecoveryTmpl := util.LoadTemplate(nil, twoFactorRecoveryPaths...)
  524. setupTmpl := util.LoadTemplate(nil, setupPaths...)
  525. forgotPwdTmpl := util.LoadTemplate(nil, forgotPwdPaths...)
  526. resetPwdTmpl := util.LoadTemplate(nil, resetPwdPaths...)
  527. rolesTmpl := util.LoadTemplate(nil, rolesPaths...)
  528. roleTmpl := util.LoadTemplate(nil, rolePaths...)
  529. eventsTmpl := util.LoadTemplate(nil, eventsPaths...)
  530. configsTmpl := util.LoadTemplate(nil, configsPaths...)
  531. adminTemplates[templateUsers] = usersTmpl
  532. adminTemplates[templateUser] = userTmpl
  533. adminTemplates[templateAdmins] = adminsTmpl
  534. adminTemplates[templateAdmin] = adminTmpl
  535. adminTemplates[templateConnections] = connectionsTmpl
  536. adminTemplates[templateMessage] = messageTmpl
  537. adminTemplates[templateGroups] = groupsTmpl
  538. adminTemplates[templateGroup] = groupTmpl
  539. adminTemplates[templateFolders] = foldersTmpl
  540. adminTemplates[templateFolder] = folderTmpl
  541. adminTemplates[templateEventRules] = eventRulesTmpl
  542. adminTemplates[templateEventRule] = eventRuleTmpl
  543. adminTemplates[templateEventActions] = eventActionsTmpl
  544. adminTemplates[templateEventAction] = eventActionTmpl
  545. adminTemplates[templateStatus] = statusTmpl
  546. adminTemplates[templateCommonLogin] = loginTmpl
  547. adminTemplates[templateProfile] = profileTmpl
  548. adminTemplates[templateChangePwd] = changePwdTmpl
  549. adminTemplates[templateMaintenance] = maintenanceTmpl
  550. adminTemplates[templateDefender] = defenderTmpl
  551. adminTemplates[templateIPLists] = ipListsTmpl
  552. adminTemplates[templateIPList] = ipListTmpl
  553. adminTemplates[templateMFA] = mfaTmpl
  554. adminTemplates[templateTwoFactor] = twoFactorTmpl
  555. adminTemplates[templateTwoFactorRecovery] = twoFactorRecoveryTmpl
  556. adminTemplates[templateSetup] = setupTmpl
  557. adminTemplates[templateForgotPassword] = forgotPwdTmpl
  558. adminTemplates[templateResetPassword] = resetPwdTmpl
  559. adminTemplates[templateRoles] = rolesTmpl
  560. adminTemplates[templateRole] = roleTmpl
  561. adminTemplates[templateEvents] = eventsTmpl
  562. adminTemplates[templateConfigs] = configsTmpl
  563. }
  564. func isEventManagerResource(currentURL string) bool {
  565. if currentURL == webAdminEventRulesPath {
  566. return true
  567. }
  568. if currentURL == webAdminEventActionsPath {
  569. return true
  570. }
  571. if currentURL == webAdminEventRulePath || strings.HasPrefix(currentURL, webAdminEventRulePath+"/") {
  572. return true
  573. }
  574. if currentURL == webAdminEventActionPath || strings.HasPrefix(currentURL, webAdminEventActionPath+"/") {
  575. return true
  576. }
  577. return false
  578. }
  579. func isIPListsResource(currentURL string) bool {
  580. if currentURL == webDefenderPath {
  581. return true
  582. }
  583. if currentURL == webIPListsPath {
  584. return true
  585. }
  586. if strings.HasPrefix(currentURL, webIPListPath+"/") {
  587. return true
  588. }
  589. return false
  590. }
  591. func isServerManagerResource(currentURL string) bool {
  592. return currentURL == webEventsPath || currentURL == webStatusPath || currentURL == webMaintenancePath ||
  593. currentURL == webConfigsPath
  594. }
  595. func (s *httpdServer) getBasePageData(title, currentURL string, r *http.Request) basePage {
  596. var csrfToken string
  597. if currentURL != "" {
  598. csrfToken = createCSRFToken(util.GetIPFromRemoteAddress(r.RemoteAddr))
  599. }
  600. return basePage{
  601. commonBasePage: getCommonBasePage(r),
  602. Title: title,
  603. CurrentURL: currentURL,
  604. UsersURL: webUsersPath,
  605. UserURL: webUserPath,
  606. UserTemplateURL: webTemplateUser,
  607. AdminsURL: webAdminsPath,
  608. AdminURL: webAdminPath,
  609. GroupsURL: webGroupsPath,
  610. GroupURL: webGroupPath,
  611. FoldersURL: webFoldersPath,
  612. FolderURL: webFolderPath,
  613. FolderTemplateURL: webTemplateFolder,
  614. DefenderURL: webDefenderPath,
  615. IPListsURL: webIPListsPath,
  616. IPListURL: webIPListPath,
  617. EventsURL: webEventsPath,
  618. ConfigsURL: webConfigsPath,
  619. LogoutURL: webLogoutPath,
  620. LoginURL: webAdminLoginPath,
  621. ProfileURL: webAdminProfilePath,
  622. ChangePwdURL: webChangeAdminPwdPath,
  623. MFAURL: webAdminMFAPath,
  624. EventRulesURL: webAdminEventRulesPath,
  625. EventRuleURL: webAdminEventRulePath,
  626. EventActionsURL: webAdminEventActionsPath,
  627. EventActionURL: webAdminEventActionPath,
  628. RolesURL: webAdminRolesPath,
  629. RoleURL: webAdminRolePath,
  630. QuotaScanURL: webQuotaScanPath,
  631. ConnectionsURL: webConnectionsPath,
  632. StatusURL: webStatusPath,
  633. FolderQuotaScanURL: webScanVFolderPath,
  634. MaintenanceURL: webMaintenancePath,
  635. LoggedUser: getAdminFromToken(r),
  636. IsEventManagerPage: isEventManagerResource(currentURL),
  637. IsIPManagerPage: isIPListsResource(currentURL),
  638. IsServerManagerPage: isServerManagerResource(currentURL),
  639. HasDefender: common.Config.DefenderConfig.Enabled,
  640. HasSearcher: plugin.Handler.HasSearcher(),
  641. HasExternalLogin: isLoggedInWithOIDC(r),
  642. CSRFToken: csrfToken,
  643. Branding: s.binding.Branding.WebAdmin,
  644. }
  645. }
  646. func renderAdminTemplate(w http.ResponseWriter, tmplName string, data any) {
  647. err := adminTemplates[tmplName].ExecuteTemplate(w, tmplName, data)
  648. if err != nil {
  649. http.Error(w, err.Error(), http.StatusInternalServerError)
  650. }
  651. }
  652. func (s *httpdServer) renderMessagePageWithString(w http.ResponseWriter, r *http.Request, title string, statusCode int,
  653. err error, message, text string,
  654. ) {
  655. data := messagePage{
  656. basePage: s.getBasePageData(title, "", r),
  657. Error: getI18nError(err),
  658. Success: message,
  659. Text: text,
  660. }
  661. w.WriteHeader(statusCode)
  662. renderAdminTemplate(w, templateMessage, data)
  663. }
  664. func (s *httpdServer) renderMessagePage(w http.ResponseWriter, r *http.Request, title string, statusCode int,
  665. err error, message string,
  666. ) {
  667. s.renderMessagePageWithString(w, r, title, statusCode, err, message, "")
  668. }
  669. func (s *httpdServer) renderInternalServerErrorPage(w http.ResponseWriter, r *http.Request, err error) {
  670. s.renderMessagePage(w, r, util.I18nError500Title, http.StatusInternalServerError,
  671. util.NewI18nError(err, util.I18nError500Message), "")
  672. }
  673. func (s *httpdServer) renderBadRequestPage(w http.ResponseWriter, r *http.Request, err error) {
  674. s.renderMessagePage(w, r, util.I18nError400Title, http.StatusBadRequest,
  675. util.NewI18nError(err, util.I18nError400Message), "")
  676. }
  677. func (s *httpdServer) renderForbiddenPage(w http.ResponseWriter, r *http.Request, err error) {
  678. s.renderMessagePage(w, r, util.I18nError403Title, http.StatusForbidden,
  679. util.NewI18nError(err, util.I18nError403Message), "")
  680. }
  681. func (s *httpdServer) renderNotFoundPage(w http.ResponseWriter, r *http.Request, err error) {
  682. s.renderMessagePage(w, r, util.I18nError404Title, http.StatusNotFound,
  683. util.NewI18nError(err, util.I18nError404Message), "")
  684. }
  685. func (s *httpdServer) renderForgotPwdPage(w http.ResponseWriter, r *http.Request, err *util.I18nError, ip string) {
  686. data := forgotPwdPage{
  687. commonBasePage: getCommonBasePage(r),
  688. CurrentURL: webAdminForgotPwdPath,
  689. Error: err,
  690. CSRFToken: createCSRFToken(ip),
  691. LoginURL: webAdminLoginPath,
  692. Title: util.I18nForgotPwdTitle,
  693. Branding: s.binding.Branding.WebAdmin,
  694. }
  695. renderAdminTemplate(w, templateForgotPassword, data)
  696. }
  697. func (s *httpdServer) renderResetPwdPage(w http.ResponseWriter, r *http.Request, err *util.I18nError, ip string) {
  698. data := resetPwdPage{
  699. commonBasePage: getCommonBasePage(r),
  700. CurrentURL: webAdminResetPwdPath,
  701. Error: err,
  702. CSRFToken: createCSRFToken(ip),
  703. LoginURL: webAdminLoginPath,
  704. Title: util.I18nResetPwdTitle,
  705. Branding: s.binding.Branding.WebAdmin,
  706. }
  707. renderAdminTemplate(w, templateResetPassword, data)
  708. }
  709. func (s *httpdServer) renderTwoFactorPage(w http.ResponseWriter, r *http.Request, err *util.I18nError, ip string) {
  710. data := twoFactorPage{
  711. commonBasePage: getCommonBasePage(r),
  712. Title: pageTwoFactorTitle,
  713. CurrentURL: webAdminTwoFactorPath,
  714. Error: err,
  715. CSRFToken: createCSRFToken(ip),
  716. RecoveryURL: webAdminTwoFactorRecoveryPath,
  717. Branding: s.binding.Branding.WebAdmin,
  718. }
  719. renderAdminTemplate(w, templateTwoFactor, data)
  720. }
  721. func (s *httpdServer) renderTwoFactorRecoveryPage(w http.ResponseWriter, r *http.Request, err *util.I18nError, ip string) {
  722. data := twoFactorPage{
  723. commonBasePage: getCommonBasePage(r),
  724. Title: pageTwoFactorRecoveryTitle,
  725. CurrentURL: webAdminTwoFactorRecoveryPath,
  726. Error: err,
  727. CSRFToken: createCSRFToken(ip),
  728. Branding: s.binding.Branding.WebAdmin,
  729. }
  730. renderAdminTemplate(w, templateTwoFactorRecovery, data)
  731. }
  732. func (s *httpdServer) renderMFAPage(w http.ResponseWriter, r *http.Request) {
  733. data := mfaPage{
  734. basePage: s.getBasePageData(pageMFATitle, webAdminMFAPath, r),
  735. TOTPConfigs: mfa.GetAvailableTOTPConfigNames(),
  736. GenerateTOTPURL: webAdminTOTPGeneratePath,
  737. ValidateTOTPURL: webAdminTOTPValidatePath,
  738. SaveTOTPURL: webAdminTOTPSavePath,
  739. RecCodesURL: webAdminRecoveryCodesPath,
  740. }
  741. admin, err := dataprovider.AdminExists(data.LoggedUser.Username)
  742. if err != nil {
  743. s.renderInternalServerErrorPage(w, r, err)
  744. return
  745. }
  746. data.TOTPConfig = admin.Filters.TOTPConfig
  747. renderAdminTemplate(w, templateMFA, data)
  748. }
  749. func (s *httpdServer) renderProfilePage(w http.ResponseWriter, r *http.Request, err error) {
  750. data := profilePage{
  751. basePage: s.getBasePageData(util.I18nProfileTitle, webAdminProfilePath, r),
  752. Error: getI18nError(err),
  753. }
  754. admin, err := dataprovider.AdminExists(data.LoggedUser.Username)
  755. if err != nil {
  756. s.renderInternalServerErrorPage(w, r, err)
  757. return
  758. }
  759. data.AllowAPIKeyAuth = admin.Filters.AllowAPIKeyAuth
  760. data.Email = admin.Email
  761. data.Description = admin.Description
  762. renderAdminTemplate(w, templateProfile, data)
  763. }
  764. func (s *httpdServer) renderChangePasswordPage(w http.ResponseWriter, r *http.Request, err *util.I18nError) {
  765. data := changePasswordPage{
  766. basePage: s.getBasePageData(util.I18nChangePwdTitle, webChangeAdminPwdPath, r),
  767. Error: err,
  768. }
  769. renderAdminTemplate(w, templateChangePwd, data)
  770. }
  771. func (s *httpdServer) renderMaintenancePage(w http.ResponseWriter, r *http.Request, err error) {
  772. data := maintenancePage{
  773. basePage: s.getBasePageData(util.I18nMaintenanceTitle, webMaintenancePath, r),
  774. BackupPath: webBackupPath,
  775. RestorePath: webRestorePath,
  776. Error: getI18nError(err),
  777. }
  778. renderAdminTemplate(w, templateMaintenance, data)
  779. }
  780. func (s *httpdServer) renderConfigsPage(w http.ResponseWriter, r *http.Request, configs dataprovider.Configs,
  781. error string, section int,
  782. ) {
  783. configs.SetNilsToEmpty()
  784. if configs.SMTP.Port == 0 {
  785. configs.SMTP.Port = 587
  786. configs.SMTP.AuthType = 1
  787. configs.SMTP.Encryption = 2
  788. }
  789. if configs.ACME.HTTP01Challenge.Port == 0 {
  790. configs.ACME.HTTP01Challenge.Port = 80
  791. }
  792. data := configsPage{
  793. basePage: s.getBasePageData(pageConfigsTitle, webConfigsPath, r),
  794. Configs: configs,
  795. ConfigSection: section,
  796. RedactedSecret: redactedSecret,
  797. OAuth2TokenURL: webOAuth2TokenPath,
  798. OAuth2RedirectURL: webOAuth2RedirectPath,
  799. Error: error,
  800. }
  801. renderAdminTemplate(w, templateConfigs, data)
  802. }
  803. func (s *httpdServer) renderAdminSetupPage(w http.ResponseWriter, r *http.Request, username, ip string, err *util.I18nError) {
  804. data := setupPage{
  805. commonBasePage: getCommonBasePage(r),
  806. Title: util.I18nSetupTitle,
  807. CurrentURL: webAdminSetupPath,
  808. CSRFToken: createCSRFToken(ip),
  809. Username: username,
  810. HasInstallationCode: installationCode != "",
  811. InstallationCodeHint: installationCodeHint,
  812. HideSupportLink: hideSupportLink,
  813. Error: err,
  814. Branding: s.binding.Branding.WebAdmin,
  815. }
  816. renderAdminTemplate(w, templateSetup, data)
  817. }
  818. func (s *httpdServer) renderAddUpdateAdminPage(w http.ResponseWriter, r *http.Request, admin *dataprovider.Admin,
  819. err error, isAdd bool) {
  820. groups, errGroups := s.getWebGroups(w, r, defaultQueryLimit, true)
  821. if errGroups != nil {
  822. return
  823. }
  824. roles, errRoles := s.getWebRoles(w, r, 10, true)
  825. if errRoles != nil {
  826. return
  827. }
  828. currentURL := webAdminPath
  829. title := util.I18nAddAdminTitle
  830. if !isAdd {
  831. currentURL = fmt.Sprintf("%v/%v", webAdminPath, url.PathEscape(admin.Username))
  832. title = util.I18nUpdateAdminTitle
  833. }
  834. data := adminPage{
  835. basePage: s.getBasePageData(title, currentURL, r),
  836. Admin: admin,
  837. Groups: groups,
  838. Roles: roles,
  839. Error: getI18nError(err),
  840. IsAdd: isAdd,
  841. }
  842. renderAdminTemplate(w, templateAdmin, data)
  843. }
  844. func (s *httpdServer) getUserPageTitleAndURL(mode userPageMode, username string) (string, string) {
  845. var title, currentURL string
  846. switch mode {
  847. case userPageModeAdd:
  848. title = util.I18nAddUserTitle
  849. currentURL = webUserPath
  850. case userPageModeUpdate:
  851. title = util.I18nUpdateUserTitle
  852. currentURL = fmt.Sprintf("%v/%v", webUserPath, url.PathEscape(username))
  853. case userPageModeTemplate:
  854. title = util.I18nTemplateUserTitle
  855. currentURL = webTemplateUser
  856. }
  857. return title, currentURL
  858. }
  859. func (s *httpdServer) renderUserPage(w http.ResponseWriter, r *http.Request, user *dataprovider.User,
  860. mode userPageMode, err error, admin *dataprovider.Admin,
  861. ) {
  862. user.SetEmptySecretsIfNil()
  863. title, currentURL := s.getUserPageTitleAndURL(mode, user.Username)
  864. if user.Password != "" && user.IsPasswordHashed() {
  865. switch mode {
  866. case userPageModeUpdate:
  867. user.Password = redactedSecret
  868. default:
  869. user.Password = ""
  870. }
  871. }
  872. user.FsConfig.RedactedSecret = redactedSecret
  873. basePage := s.getBasePageData(title, currentURL, r)
  874. if (mode == userPageModeAdd || mode == userPageModeTemplate) && len(user.Groups) == 0 && admin != nil {
  875. for _, group := range admin.Groups {
  876. user.Groups = append(user.Groups, sdk.GroupMapping{
  877. Name: group.Name,
  878. Type: group.Options.GetUserGroupType(),
  879. })
  880. }
  881. }
  882. var roles []dataprovider.Role
  883. if basePage.LoggedUser.Role == "" {
  884. var errRoles error
  885. roles, errRoles = s.getWebRoles(w, r, 10, true)
  886. if errRoles != nil {
  887. return
  888. }
  889. }
  890. folders, errFolders := s.getWebVirtualFolders(w, r, defaultQueryLimit, true)
  891. if errFolders != nil {
  892. return
  893. }
  894. groups, errGroups := s.getWebGroups(w, r, defaultQueryLimit, true)
  895. if errGroups != nil {
  896. return
  897. }
  898. data := userPage{
  899. basePage: basePage,
  900. Mode: mode,
  901. Error: getI18nError(err),
  902. User: user,
  903. ValidPerms: dataprovider.ValidPerms,
  904. ValidLoginMethods: dataprovider.ValidLoginMethods,
  905. ValidProtocols: dataprovider.ValidProtocols,
  906. TwoFactorProtocols: dataprovider.MFAProtocols,
  907. WebClientOptions: sdk.WebClientOptions,
  908. RootDirPerms: user.GetPermissionsForPath("/"),
  909. VirtualFolders: folders,
  910. Groups: groups,
  911. Roles: roles,
  912. CanImpersonate: os.Getuid() == 0,
  913. FsWrapper: fsWrapper{
  914. Filesystem: user.FsConfig,
  915. IsUserPage: true,
  916. IsGroupPage: false,
  917. IsHidden: basePage.LoggedUser.Filters.Preferences.HideFilesystem(),
  918. HasUsersBaseDir: dataprovider.HasUsersBaseDir(),
  919. DirPath: user.HomeDir,
  920. },
  921. }
  922. renderAdminTemplate(w, templateUser, data)
  923. }
  924. func (s *httpdServer) renderIPListPage(w http.ResponseWriter, r *http.Request, entry dataprovider.IPListEntry,
  925. mode genericPageMode, err error,
  926. ) {
  927. var title, currentURL string
  928. switch mode {
  929. case genericPageModeAdd:
  930. title = util.I18nAddIPListTitle
  931. currentURL = fmt.Sprintf("%s/%d", webIPListPath, entry.Type)
  932. case genericPageModeUpdate:
  933. title = util.I18nUpdateIPListTitle
  934. currentURL = fmt.Sprintf("%s/%d/%s", webIPListPath, entry.Type, url.PathEscape(entry.IPOrNet))
  935. }
  936. data := ipListPage{
  937. basePage: s.getBasePageData(title, currentURL, r),
  938. Error: getI18nError(err),
  939. Entry: &entry,
  940. Mode: mode,
  941. }
  942. renderAdminTemplate(w, templateIPList, data)
  943. }
  944. func (s *httpdServer) renderRolePage(w http.ResponseWriter, r *http.Request, role dataprovider.Role,
  945. mode genericPageMode, err error,
  946. ) {
  947. var title, currentURL string
  948. switch mode {
  949. case genericPageModeAdd:
  950. title = util.I18nRoleAddTitle
  951. currentURL = webAdminRolePath
  952. case genericPageModeUpdate:
  953. title = util.I18nRoleUpdateTitle
  954. currentURL = fmt.Sprintf("%s/%s", webAdminRolePath, url.PathEscape(role.Name))
  955. }
  956. data := rolePage{
  957. basePage: s.getBasePageData(title, currentURL, r),
  958. Error: getI18nError(err),
  959. Role: &role,
  960. Mode: mode,
  961. }
  962. renderAdminTemplate(w, templateRole, data)
  963. }
  964. func (s *httpdServer) renderGroupPage(w http.ResponseWriter, r *http.Request, group dataprovider.Group,
  965. mode genericPageMode, err error,
  966. ) {
  967. folders, errFolders := s.getWebVirtualFolders(w, r, defaultQueryLimit, true)
  968. if errFolders != nil {
  969. return
  970. }
  971. group.SetEmptySecretsIfNil()
  972. group.UserSettings.FsConfig.RedactedSecret = redactedSecret
  973. var title, currentURL string
  974. switch mode {
  975. case genericPageModeAdd:
  976. title = util.I18nAddGroupTitle
  977. currentURL = webGroupPath
  978. case genericPageModeUpdate:
  979. title = util.I18nUpdateGroupTitle
  980. currentURL = fmt.Sprintf("%v/%v", webGroupPath, url.PathEscape(group.Name))
  981. }
  982. group.UserSettings.FsConfig.RedactedSecret = redactedSecret
  983. group.UserSettings.FsConfig.SetEmptySecretsIfNil()
  984. data := groupPage{
  985. basePage: s.getBasePageData(title, currentURL, r),
  986. Error: getI18nError(err),
  987. Group: &group,
  988. Mode: mode,
  989. ValidPerms: dataprovider.ValidPerms,
  990. ValidLoginMethods: dataprovider.ValidLoginMethods,
  991. ValidProtocols: dataprovider.ValidProtocols,
  992. TwoFactorProtocols: dataprovider.MFAProtocols,
  993. WebClientOptions: sdk.WebClientOptions,
  994. VirtualFolders: folders,
  995. FsWrapper: fsWrapper{
  996. Filesystem: group.UserSettings.FsConfig,
  997. IsUserPage: false,
  998. IsGroupPage: true,
  999. HasUsersBaseDir: false,
  1000. DirPath: group.UserSettings.HomeDir,
  1001. },
  1002. }
  1003. renderAdminTemplate(w, templateGroup, data)
  1004. }
  1005. func (s *httpdServer) renderEventActionPage(w http.ResponseWriter, r *http.Request, action dataprovider.BaseEventAction,
  1006. mode genericPageMode, error string,
  1007. ) {
  1008. action.Options.SetEmptySecretsIfNil()
  1009. var title, currentURL string
  1010. switch mode {
  1011. case genericPageModeAdd:
  1012. title = "Add a new event action"
  1013. currentURL = webAdminEventActionPath
  1014. case genericPageModeUpdate:
  1015. title = "Update event action"
  1016. currentURL = fmt.Sprintf("%s/%s", webAdminEventActionPath, url.PathEscape(action.Name))
  1017. }
  1018. if action.Options.HTTPConfig.Timeout == 0 {
  1019. action.Options.HTTPConfig.Timeout = 20
  1020. }
  1021. if action.Options.CmdConfig.Timeout == 0 {
  1022. action.Options.CmdConfig.Timeout = 20
  1023. }
  1024. if action.Options.PwdExpirationConfig.Threshold == 0 {
  1025. action.Options.PwdExpirationConfig.Threshold = 10
  1026. }
  1027. data := eventActionPage{
  1028. basePage: s.getBasePageData(title, currentURL, r),
  1029. Action: action,
  1030. ActionTypes: dataprovider.EventActionTypes,
  1031. FsActions: dataprovider.FsActionTypes,
  1032. HTTPMethods: dataprovider.SupportedHTTPActionMethods,
  1033. RedactedSecret: redactedSecret,
  1034. Error: error,
  1035. Mode: mode,
  1036. }
  1037. renderAdminTemplate(w, templateEventAction, data)
  1038. }
  1039. func (s *httpdServer) renderEventRulePage(w http.ResponseWriter, r *http.Request, rule dataprovider.EventRule,
  1040. mode genericPageMode, error string,
  1041. ) {
  1042. actions, err := s.getWebEventActions(w, r, defaultQueryLimit, true)
  1043. if err != nil {
  1044. return
  1045. }
  1046. var title, currentURL string
  1047. switch mode {
  1048. case genericPageModeAdd:
  1049. title = "Add new event rules"
  1050. currentURL = webAdminEventRulePath
  1051. case genericPageModeUpdate:
  1052. title = "Update event rules"
  1053. currentURL = fmt.Sprintf("%v/%v", webAdminEventRulePath, url.PathEscape(rule.Name))
  1054. }
  1055. data := eventRulePage{
  1056. basePage: s.getBasePageData(title, currentURL, r),
  1057. Rule: rule,
  1058. TriggerTypes: dataprovider.EventTriggerTypes,
  1059. Actions: actions,
  1060. FsEvents: dataprovider.SupportedFsEvents,
  1061. Protocols: dataprovider.SupportedRuleConditionProtocols,
  1062. ProviderEvents: dataprovider.SupportedProviderEvents,
  1063. ProviderObjects: dataprovider.SupporteRuleConditionProviderObjects,
  1064. Error: error,
  1065. Mode: mode,
  1066. IsShared: s.isShared > 0,
  1067. }
  1068. renderAdminTemplate(w, templateEventRule, data)
  1069. }
  1070. func (s *httpdServer) renderFolderPage(w http.ResponseWriter, r *http.Request, folder vfs.BaseVirtualFolder,
  1071. mode folderPageMode, err error,
  1072. ) {
  1073. var title, currentURL string
  1074. switch mode {
  1075. case folderPageModeAdd:
  1076. title = util.I18nAddFolderTitle
  1077. currentURL = webFolderPath
  1078. case folderPageModeUpdate:
  1079. title = util.I18nUpdateFolderTitle
  1080. currentURL = fmt.Sprintf("%v/%v", webFolderPath, url.PathEscape(folder.Name))
  1081. case folderPageModeTemplate:
  1082. title = util.I18nTemplateFolderTitle
  1083. currentURL = webTemplateFolder
  1084. }
  1085. folder.FsConfig.RedactedSecret = redactedSecret
  1086. folder.FsConfig.SetEmptySecretsIfNil()
  1087. data := folderPage{
  1088. basePage: s.getBasePageData(title, currentURL, r),
  1089. Error: getI18nError(err),
  1090. Folder: folder,
  1091. Mode: mode,
  1092. FsWrapper: fsWrapper{
  1093. Filesystem: folder.FsConfig,
  1094. IsUserPage: false,
  1095. IsGroupPage: false,
  1096. HasUsersBaseDir: false,
  1097. DirPath: folder.MappedPath,
  1098. },
  1099. }
  1100. renderAdminTemplate(w, templateFolder, data)
  1101. }
  1102. func getFoldersForTemplate(r *http.Request) []string {
  1103. var res []string
  1104. for k := range r.Form {
  1105. if hasPrefixAndSuffix(k, "template_folders[", "][tpl_foldername]") {
  1106. r.Form.Add("tpl_foldername", r.Form.Get(k))
  1107. }
  1108. }
  1109. folderNames := r.Form["tpl_foldername"]
  1110. folders := make(map[string]bool)
  1111. for _, name := range folderNames {
  1112. name = strings.TrimSpace(name)
  1113. if name == "" {
  1114. continue
  1115. }
  1116. if _, ok := folders[name]; ok {
  1117. continue
  1118. }
  1119. folders[name] = true
  1120. res = append(res, name)
  1121. }
  1122. return res
  1123. }
  1124. func getUsersForTemplate(r *http.Request) []userTemplateFields {
  1125. var res []userTemplateFields
  1126. tplUsernames := r.Form["tpl_username"]
  1127. tplPasswords := r.Form["tpl_password"]
  1128. tplPublicKeys := r.Form["tpl_public_keys"]
  1129. users := make(map[string]bool)
  1130. for idx := range tplUsernames {
  1131. username := tplUsernames[idx]
  1132. password := ""
  1133. publicKey := ""
  1134. if len(tplPasswords) > idx {
  1135. password = strings.TrimSpace(tplPasswords[idx])
  1136. }
  1137. if len(tplPublicKeys) > idx {
  1138. publicKey = strings.TrimSpace(tplPublicKeys[idx])
  1139. }
  1140. if username == "" {
  1141. continue
  1142. }
  1143. if _, ok := users[username]; ok {
  1144. continue
  1145. }
  1146. users[username] = true
  1147. res = append(res, userTemplateFields{
  1148. Username: username,
  1149. Password: password,
  1150. PublicKeys: []string{publicKey},
  1151. })
  1152. }
  1153. return res
  1154. }
  1155. func getVirtualFoldersFromPostFields(r *http.Request) []vfs.VirtualFolder {
  1156. var virtualFolders []vfs.VirtualFolder
  1157. folderPaths := r.Form["vfolder_path"]
  1158. folderNames := r.Form["vfolder_name"]
  1159. folderQuotaSizes := r.Form["vfolder_quota_size"]
  1160. folderQuotaFiles := r.Form["vfolder_quota_files"]
  1161. for idx, p := range folderPaths {
  1162. name := ""
  1163. if len(folderNames) > idx {
  1164. name = folderNames[idx]
  1165. }
  1166. if p != "" && name != "" {
  1167. vfolder := vfs.VirtualFolder{
  1168. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1169. Name: name,
  1170. },
  1171. VirtualPath: p,
  1172. QuotaFiles: -1,
  1173. QuotaSize: -1,
  1174. }
  1175. if len(folderQuotaSizes) > idx {
  1176. quotaSize, err := util.ParseBytes(folderQuotaSizes[idx])
  1177. if err == nil {
  1178. vfolder.QuotaSize = quotaSize
  1179. }
  1180. }
  1181. if len(folderQuotaFiles) > idx {
  1182. quotaFiles, err := strconv.Atoi(folderQuotaFiles[idx])
  1183. if err == nil {
  1184. vfolder.QuotaFiles = quotaFiles
  1185. }
  1186. }
  1187. virtualFolders = append(virtualFolders, vfolder)
  1188. }
  1189. }
  1190. return virtualFolders
  1191. }
  1192. func getSubDirPermissionsFromPostFields(r *http.Request) map[string][]string {
  1193. permissions := make(map[string][]string)
  1194. for idx, p := range r.Form["sub_perm_path"] {
  1195. if p != "" {
  1196. permissions[p] = r.Form["sub_perm_permissions"+strconv.Itoa(idx)]
  1197. }
  1198. }
  1199. return permissions
  1200. }
  1201. func getUserPermissionsFromPostFields(r *http.Request) map[string][]string {
  1202. permissions := getSubDirPermissionsFromPostFields(r)
  1203. permissions["/"] = r.Form["permissions"]
  1204. return permissions
  1205. }
  1206. func getBandwidthLimitsFromPostFields(r *http.Request) ([]sdk.BandwidthLimit, error) {
  1207. var result []sdk.BandwidthLimit
  1208. bwSources := r.Form["bandwidth_limit_sources"]
  1209. uploadSources := r.Form["upload_bandwidth_source"]
  1210. downloadSources := r.Form["download_bandwidth_source"]
  1211. for idx, bwSource := range bwSources {
  1212. sources := getSliceFromDelimitedValues(bwSource, ",")
  1213. if len(sources) > 0 {
  1214. bwLimit := sdk.BandwidthLimit{
  1215. Sources: sources,
  1216. }
  1217. ul := ""
  1218. dl := ""
  1219. if len(uploadSources) > idx {
  1220. ul = uploadSources[idx]
  1221. }
  1222. if len(downloadSources) > idx {
  1223. dl = downloadSources[idx]
  1224. }
  1225. if ul != "" {
  1226. bandwidthUL, err := strconv.ParseInt(ul, 10, 64)
  1227. if err != nil {
  1228. return result, fmt.Errorf("invalid upload_bandwidth_source%v %q: %w", idx, ul, err)
  1229. }
  1230. bwLimit.UploadBandwidth = bandwidthUL
  1231. }
  1232. if dl != "" {
  1233. bandwidthDL, err := strconv.ParseInt(dl, 10, 64)
  1234. if err != nil {
  1235. return result, fmt.Errorf("invalid download_bandwidth_source%v %q: %w", idx, ul, err)
  1236. }
  1237. bwLimit.DownloadBandwidth = bandwidthDL
  1238. }
  1239. result = append(result, bwLimit)
  1240. }
  1241. }
  1242. return result, nil
  1243. }
  1244. func getPatterDenyPolicyFromString(policy string) int {
  1245. denyPolicy := sdk.DenyPolicyDefault
  1246. if policy == "1" {
  1247. denyPolicy = sdk.DenyPolicyHide
  1248. }
  1249. return denyPolicy
  1250. }
  1251. func getFilePatternsFromPostField(r *http.Request) []sdk.PatternsFilter {
  1252. var result []sdk.PatternsFilter
  1253. patternPaths := r.Form["pattern_path"]
  1254. patterns := r.Form["patterns"]
  1255. patternTypes := r.Form["pattern_type"]
  1256. policies := r.Form["pattern_policy"]
  1257. allowedPatterns := make(map[string][]string)
  1258. deniedPatterns := make(map[string][]string)
  1259. patternPolicies := make(map[string]string)
  1260. for idx := range patternPaths {
  1261. p := patternPaths[idx]
  1262. filters := strings.ReplaceAll(patterns[idx], " ", "")
  1263. patternType := patternTypes[idx]
  1264. patternPolicy := policies[idx]
  1265. if p != "" && filters != "" {
  1266. if patternType == "allowed" {
  1267. allowedPatterns[p] = append(allowedPatterns[p], strings.Split(filters, ",")...)
  1268. } else {
  1269. deniedPatterns[p] = append(deniedPatterns[p], strings.Split(filters, ",")...)
  1270. }
  1271. if patternPolicy != "" && patternPolicy != "0" {
  1272. patternPolicies[p] = patternPolicy
  1273. }
  1274. }
  1275. }
  1276. for dirAllowed, allowPatterns := range allowedPatterns {
  1277. filter := sdk.PatternsFilter{
  1278. Path: dirAllowed,
  1279. AllowedPatterns: allowPatterns,
  1280. DenyPolicy: getPatterDenyPolicyFromString(patternPolicies[dirAllowed]),
  1281. }
  1282. for dirDenied, denPatterns := range deniedPatterns {
  1283. if dirAllowed == dirDenied {
  1284. filter.DeniedPatterns = denPatterns
  1285. break
  1286. }
  1287. }
  1288. result = append(result, filter)
  1289. }
  1290. for dirDenied, denPatterns := range deniedPatterns {
  1291. found := false
  1292. for _, res := range result {
  1293. if res.Path == dirDenied {
  1294. found = true
  1295. break
  1296. }
  1297. }
  1298. if !found {
  1299. result = append(result, sdk.PatternsFilter{
  1300. Path: dirDenied,
  1301. DeniedPatterns: denPatterns,
  1302. DenyPolicy: getPatterDenyPolicyFromString(patternPolicies[dirDenied]),
  1303. })
  1304. }
  1305. }
  1306. return result
  1307. }
  1308. func getGroupsFromUserPostFields(r *http.Request) []sdk.GroupMapping {
  1309. var groups []sdk.GroupMapping
  1310. primaryGroup := strings.TrimSpace(r.Form.Get("primary_group"))
  1311. if primaryGroup != "" {
  1312. groups = append(groups, sdk.GroupMapping{
  1313. Name: primaryGroup,
  1314. Type: sdk.GroupTypePrimary,
  1315. })
  1316. }
  1317. secondaryGroups := r.Form["secondary_groups"]
  1318. for _, name := range secondaryGroups {
  1319. groups = append(groups, sdk.GroupMapping{
  1320. Name: strings.TrimSpace(name),
  1321. Type: sdk.GroupTypeSecondary,
  1322. })
  1323. }
  1324. membershipGroups := r.Form["membership_groups"]
  1325. for _, name := range membershipGroups {
  1326. groups = append(groups, sdk.GroupMapping{
  1327. Name: strings.TrimSpace(name),
  1328. Type: sdk.GroupTypeMembership,
  1329. })
  1330. }
  1331. return groups
  1332. }
  1333. func getFiltersFromUserPostFields(r *http.Request) (sdk.BaseUserFilters, error) {
  1334. var filters sdk.BaseUserFilters
  1335. bwLimits, err := getBandwidthLimitsFromPostFields(r)
  1336. if err != nil {
  1337. return filters, err
  1338. }
  1339. maxFileSize, err := util.ParseBytes(r.Form.Get("max_upload_file_size"))
  1340. if err != nil {
  1341. return filters, util.NewI18nError(fmt.Errorf("invalid max upload file size: %w", err), util.I18nErrorInvalidMaxFilesize)
  1342. }
  1343. defaultSharesExpiration, err := strconv.Atoi(r.Form.Get("default_shares_expiration"))
  1344. if err != nil {
  1345. return filters, fmt.Errorf("invalid default shares expiration: %w", err)
  1346. }
  1347. maxSharesExpiration, err := strconv.Atoi(r.Form.Get("max_shares_expiration"))
  1348. if err != nil {
  1349. return filters, fmt.Errorf("invalid max shares expiration: %w", err)
  1350. }
  1351. passwordExpiration, err := strconv.Atoi(r.Form.Get("password_expiration"))
  1352. if err != nil {
  1353. return filters, fmt.Errorf("invalid password expiration: %w", err)
  1354. }
  1355. passwordStrength, err := strconv.Atoi(r.Form.Get("password_strength"))
  1356. if err != nil {
  1357. return filters, fmt.Errorf("invalid password strength: %w", err)
  1358. }
  1359. if r.Form.Get("ftp_security") == "1" {
  1360. filters.FTPSecurity = 1
  1361. }
  1362. filters.BandwidthLimits = bwLimits
  1363. filters.AllowedIP = getSliceFromDelimitedValues(r.Form.Get("allowed_ip"), ",")
  1364. filters.DeniedIP = getSliceFromDelimitedValues(r.Form.Get("denied_ip"), ",")
  1365. filters.DeniedLoginMethods = r.Form["denied_login_methods"]
  1366. filters.DeniedProtocols = r.Form["denied_protocols"]
  1367. filters.TwoFactorAuthProtocols = r.Form["required_two_factor_protocols"]
  1368. filters.FilePatterns = getFilePatternsFromPostField(r)
  1369. filters.TLSUsername = sdk.TLSUsername(strings.TrimSpace(r.Form.Get("tls_username")))
  1370. filters.WebClient = r.Form["web_client_options"]
  1371. filters.DefaultSharesExpiration = defaultSharesExpiration
  1372. filters.MaxSharesExpiration = maxSharesExpiration
  1373. filters.PasswordExpiration = passwordExpiration
  1374. filters.PasswordStrength = passwordStrength
  1375. hooks := r.Form["hooks"]
  1376. if util.Contains(hooks, "external_auth_disabled") {
  1377. filters.Hooks.ExternalAuthDisabled = true
  1378. }
  1379. if util.Contains(hooks, "pre_login_disabled") {
  1380. filters.Hooks.PreLoginDisabled = true
  1381. }
  1382. if util.Contains(hooks, "check_password_disabled") {
  1383. filters.Hooks.CheckPasswordDisabled = true
  1384. }
  1385. filters.IsAnonymous = r.Form.Get("is_anonymous") != ""
  1386. filters.DisableFsChecks = r.Form.Get("disable_fs_checks") != ""
  1387. filters.AllowAPIKeyAuth = r.Form.Get("allow_api_key_auth") != ""
  1388. filters.StartDirectory = strings.TrimSpace(r.Form.Get("start_directory"))
  1389. filters.MaxUploadFileSize = maxFileSize
  1390. filters.ExternalAuthCacheTime, err = strconv.ParseInt(r.Form.Get("external_auth_cache_time"), 10, 64)
  1391. if err != nil {
  1392. return filters, fmt.Errorf("invalid external auth cache time: %w", err)
  1393. }
  1394. return filters, nil
  1395. }
  1396. func getSecretFromFormField(r *http.Request, field string) *kms.Secret {
  1397. secret := kms.NewPlainSecret(r.Form.Get(field))
  1398. if strings.TrimSpace(secret.GetPayload()) == redactedSecret {
  1399. secret.SetStatus(sdkkms.SecretStatusRedacted)
  1400. }
  1401. if strings.TrimSpace(secret.GetPayload()) == "" {
  1402. secret.SetStatus("")
  1403. }
  1404. return secret
  1405. }
  1406. func getS3Config(r *http.Request) (vfs.S3FsConfig, error) {
  1407. var err error
  1408. config := vfs.S3FsConfig{}
  1409. config.Bucket = strings.TrimSpace(r.Form.Get("s3_bucket"))
  1410. config.Region = strings.TrimSpace(r.Form.Get("s3_region"))
  1411. config.AccessKey = strings.TrimSpace(r.Form.Get("s3_access_key"))
  1412. config.RoleARN = strings.TrimSpace(r.Form.Get("s3_role_arn"))
  1413. config.AccessSecret = getSecretFromFormField(r, "s3_access_secret")
  1414. config.Endpoint = strings.TrimSpace(r.Form.Get("s3_endpoint"))
  1415. config.StorageClass = strings.TrimSpace(r.Form.Get("s3_storage_class"))
  1416. config.ACL = strings.TrimSpace(r.Form.Get("s3_acl"))
  1417. config.KeyPrefix = strings.TrimSpace(strings.TrimPrefix(r.Form.Get("s3_key_prefix"), "/"))
  1418. config.UploadPartSize, err = strconv.ParseInt(r.Form.Get("s3_upload_part_size"), 10, 64)
  1419. if err != nil {
  1420. return config, fmt.Errorf("invalid s3 upload part size: %w", err)
  1421. }
  1422. config.UploadConcurrency, err = strconv.Atoi(r.Form.Get("s3_upload_concurrency"))
  1423. if err != nil {
  1424. return config, fmt.Errorf("invalid s3 upload concurrency: %w", err)
  1425. }
  1426. config.DownloadPartSize, err = strconv.ParseInt(r.Form.Get("s3_download_part_size"), 10, 64)
  1427. if err != nil {
  1428. return config, fmt.Errorf("invalid s3 download part size: %w", err)
  1429. }
  1430. config.DownloadConcurrency, err = strconv.Atoi(r.Form.Get("s3_download_concurrency"))
  1431. if err != nil {
  1432. return config, fmt.Errorf("invalid s3 download concurrency: %w", err)
  1433. }
  1434. config.ForcePathStyle = r.Form.Get("s3_force_path_style") != ""
  1435. config.SkipTLSVerify = r.Form.Get("s3_skip_tls_verify") != ""
  1436. config.DownloadPartMaxTime, err = strconv.Atoi(r.Form.Get("s3_download_part_max_time"))
  1437. if err != nil {
  1438. return config, fmt.Errorf("invalid s3 download part max time: %w", err)
  1439. }
  1440. config.UploadPartMaxTime, err = strconv.Atoi(r.Form.Get("s3_upload_part_max_time"))
  1441. if err != nil {
  1442. return config, fmt.Errorf("invalid s3 upload part max time: %w", err)
  1443. }
  1444. return config, nil
  1445. }
  1446. func getGCSConfig(r *http.Request) (vfs.GCSFsConfig, error) {
  1447. var err error
  1448. config := vfs.GCSFsConfig{}
  1449. config.Bucket = strings.TrimSpace(r.Form.Get("gcs_bucket"))
  1450. config.StorageClass = strings.TrimSpace(r.Form.Get("gcs_storage_class"))
  1451. config.ACL = strings.TrimSpace(r.Form.Get("gcs_acl"))
  1452. config.KeyPrefix = strings.TrimSpace(strings.TrimPrefix(r.Form.Get("gcs_key_prefix"), "/"))
  1453. uploadPartSize, err := strconv.ParseInt(r.Form.Get("gcs_upload_part_size"), 10, 64)
  1454. if err == nil {
  1455. config.UploadPartSize = uploadPartSize
  1456. }
  1457. uploadPartMaxTime, err := strconv.Atoi(r.Form.Get("gcs_upload_part_max_time"))
  1458. if err == nil {
  1459. config.UploadPartMaxTime = uploadPartMaxTime
  1460. }
  1461. autoCredentials := r.Form.Get("gcs_auto_credentials")
  1462. if autoCredentials != "" {
  1463. config.AutomaticCredentials = 1
  1464. } else {
  1465. config.AutomaticCredentials = 0
  1466. }
  1467. credentials, _, err := r.FormFile("gcs_credential_file")
  1468. if err == http.ErrMissingFile {
  1469. return config, nil
  1470. }
  1471. if err != nil {
  1472. return config, err
  1473. }
  1474. defer credentials.Close()
  1475. fileBytes, err := io.ReadAll(credentials)
  1476. if err != nil || len(fileBytes) == 0 {
  1477. if len(fileBytes) == 0 {
  1478. err = errors.New("credentials file size must be greater than 0")
  1479. }
  1480. return config, err
  1481. }
  1482. config.Credentials = kms.NewPlainSecret(string(fileBytes))
  1483. config.AutomaticCredentials = 0
  1484. return config, err
  1485. }
  1486. func getSFTPConfig(r *http.Request) (vfs.SFTPFsConfig, error) {
  1487. var err error
  1488. config := vfs.SFTPFsConfig{}
  1489. config.Endpoint = strings.TrimSpace(r.Form.Get("sftp_endpoint"))
  1490. config.Username = strings.TrimSpace(r.Form.Get("sftp_username"))
  1491. config.Password = getSecretFromFormField(r, "sftp_password")
  1492. config.PrivateKey = getSecretFromFormField(r, "sftp_private_key")
  1493. config.KeyPassphrase = getSecretFromFormField(r, "sftp_key_passphrase")
  1494. fingerprintsFormValue := r.Form.Get("sftp_fingerprints")
  1495. config.Fingerprints = getSliceFromDelimitedValues(fingerprintsFormValue, "\n")
  1496. config.Prefix = strings.TrimSpace(r.Form.Get("sftp_prefix"))
  1497. config.DisableCouncurrentReads = r.Form.Get("sftp_disable_concurrent_reads") != ""
  1498. config.BufferSize, err = strconv.ParseInt(r.Form.Get("sftp_buffer_size"), 10, 64)
  1499. if r.Form.Get("sftp_equality_check_mode") != "" {
  1500. config.EqualityCheckMode = 1
  1501. } else {
  1502. config.EqualityCheckMode = 0
  1503. }
  1504. if err != nil {
  1505. return config, fmt.Errorf("invalid SFTP buffer size: %w", err)
  1506. }
  1507. return config, nil
  1508. }
  1509. func getHTTPFsConfig(r *http.Request) vfs.HTTPFsConfig {
  1510. config := vfs.HTTPFsConfig{}
  1511. config.Endpoint = strings.TrimSpace(r.Form.Get("http_endpoint"))
  1512. config.Username = strings.TrimSpace(r.Form.Get("http_username"))
  1513. config.SkipTLSVerify = r.Form.Get("http_skip_tls_verify") != ""
  1514. config.Password = getSecretFromFormField(r, "http_password")
  1515. config.APIKey = getSecretFromFormField(r, "http_api_key")
  1516. if r.Form.Get("http_equality_check_mode") != "" {
  1517. config.EqualityCheckMode = 1
  1518. } else {
  1519. config.EqualityCheckMode = 0
  1520. }
  1521. return config
  1522. }
  1523. func getAzureConfig(r *http.Request) (vfs.AzBlobFsConfig, error) {
  1524. var err error
  1525. config := vfs.AzBlobFsConfig{}
  1526. config.Container = strings.TrimSpace(r.Form.Get("az_container"))
  1527. config.AccountName = strings.TrimSpace(r.Form.Get("az_account_name"))
  1528. config.AccountKey = getSecretFromFormField(r, "az_account_key")
  1529. config.SASURL = getSecretFromFormField(r, "az_sas_url")
  1530. config.Endpoint = strings.TrimSpace(r.Form.Get("az_endpoint"))
  1531. config.KeyPrefix = strings.TrimSpace(strings.TrimPrefix(r.Form.Get("az_key_prefix"), "/"))
  1532. config.AccessTier = strings.TrimSpace(r.Form.Get("az_access_tier"))
  1533. config.UseEmulator = r.Form.Get("az_use_emulator") != ""
  1534. config.UploadPartSize, err = strconv.ParseInt(r.Form.Get("az_upload_part_size"), 10, 64)
  1535. if err != nil {
  1536. return config, fmt.Errorf("invalid azure upload part size: %w", err)
  1537. }
  1538. config.UploadConcurrency, err = strconv.Atoi(r.Form.Get("az_upload_concurrency"))
  1539. if err != nil {
  1540. return config, fmt.Errorf("invalid azure upload concurrency: %w", err)
  1541. }
  1542. config.DownloadPartSize, err = strconv.ParseInt(r.Form.Get("az_download_part_size"), 10, 64)
  1543. if err != nil {
  1544. return config, fmt.Errorf("invalid azure download part size: %w", err)
  1545. }
  1546. config.DownloadConcurrency, err = strconv.Atoi(r.Form.Get("az_download_concurrency"))
  1547. if err != nil {
  1548. return config, fmt.Errorf("invalid azure download concurrency: %w", err)
  1549. }
  1550. return config, nil
  1551. }
  1552. func getOsConfigFromPostFields(r *http.Request, readBufferField, writeBufferField string) sdk.OSFsConfig {
  1553. config := sdk.OSFsConfig{}
  1554. readBuffer, err := strconv.Atoi(r.Form.Get(readBufferField))
  1555. if err == nil {
  1556. config.ReadBufferSize = readBuffer
  1557. }
  1558. writeBuffer, err := strconv.Atoi(r.Form.Get(writeBufferField))
  1559. if err == nil {
  1560. config.WriteBufferSize = writeBuffer
  1561. }
  1562. return config
  1563. }
  1564. func getFsConfigFromPostFields(r *http.Request) (vfs.Filesystem, error) {
  1565. var fs vfs.Filesystem
  1566. fs.Provider = sdk.GetProviderByName(r.Form.Get("fs_provider"))
  1567. switch fs.Provider {
  1568. case sdk.LocalFilesystemProvider:
  1569. fs.OSConfig = getOsConfigFromPostFields(r, "osfs_read_buffer_size", "osfs_write_buffer_size")
  1570. case sdk.S3FilesystemProvider:
  1571. config, err := getS3Config(r)
  1572. if err != nil {
  1573. return fs, err
  1574. }
  1575. fs.S3Config = config
  1576. case sdk.AzureBlobFilesystemProvider:
  1577. config, err := getAzureConfig(r)
  1578. if err != nil {
  1579. return fs, err
  1580. }
  1581. fs.AzBlobConfig = config
  1582. case sdk.GCSFilesystemProvider:
  1583. config, err := getGCSConfig(r)
  1584. if err != nil {
  1585. return fs, err
  1586. }
  1587. fs.GCSConfig = config
  1588. case sdk.CryptedFilesystemProvider:
  1589. fs.CryptConfig.Passphrase = getSecretFromFormField(r, "crypt_passphrase")
  1590. fs.CryptConfig.OSFsConfig = getOsConfigFromPostFields(r, "cryptfs_read_buffer_size", "cryptfs_write_buffer_size")
  1591. case sdk.SFTPFilesystemProvider:
  1592. config, err := getSFTPConfig(r)
  1593. if err != nil {
  1594. return fs, err
  1595. }
  1596. fs.SFTPConfig = config
  1597. case sdk.HTTPFilesystemProvider:
  1598. fs.HTTPConfig = getHTTPFsConfig(r)
  1599. }
  1600. return fs, nil
  1601. }
  1602. func getAdminHiddenUserPageSections(r *http.Request) int {
  1603. var result int
  1604. for _, val := range r.Form["user_page_hidden_sections"] {
  1605. switch val {
  1606. case "1":
  1607. result++
  1608. case "2":
  1609. result += 2
  1610. case "3":
  1611. result += 4
  1612. case "4":
  1613. result += 8
  1614. case "5":
  1615. result += 16
  1616. case "6":
  1617. result += 32
  1618. case "7":
  1619. result += 64
  1620. }
  1621. }
  1622. return result
  1623. }
  1624. func getAdminFromPostFields(r *http.Request) (dataprovider.Admin, error) {
  1625. var admin dataprovider.Admin
  1626. err := r.ParseForm()
  1627. if err != nil {
  1628. return admin, util.NewI18nError(err, util.I18nErrorInvalidForm)
  1629. }
  1630. status, err := strconv.Atoi(r.Form.Get("status"))
  1631. if err != nil {
  1632. return admin, fmt.Errorf("invalid status: %w", err)
  1633. }
  1634. admin.Username = strings.TrimSpace(r.Form.Get("username"))
  1635. admin.Password = strings.TrimSpace(r.Form.Get("password"))
  1636. admin.Permissions = r.Form["permissions"]
  1637. admin.Email = strings.TrimSpace(r.Form.Get("email"))
  1638. admin.Status = status
  1639. admin.Role = strings.TrimSpace(r.Form.Get("role"))
  1640. admin.Filters.AllowList = getSliceFromDelimitedValues(r.Form.Get("allowed_ip"), ",")
  1641. admin.Filters.AllowAPIKeyAuth = r.Form.Get("allow_api_key_auth") != ""
  1642. admin.AdditionalInfo = r.Form.Get("additional_info")
  1643. admin.Description = r.Form.Get("description")
  1644. admin.Filters.Preferences.HideUserPageSections = getAdminHiddenUserPageSections(r)
  1645. admin.Filters.Preferences.DefaultUsersExpiration = 0
  1646. if val := r.Form.Get("default_users_expiration"); val != "" {
  1647. defaultUsersExpiration, err := strconv.Atoi(r.Form.Get("default_users_expiration"))
  1648. if err != nil {
  1649. return admin, fmt.Errorf("invalid default users expiration: %w", err)
  1650. }
  1651. admin.Filters.Preferences.DefaultUsersExpiration = defaultUsersExpiration
  1652. }
  1653. for k := range r.Form {
  1654. if hasPrefixAndSuffix(k, "groups[", "][group]") {
  1655. groupName := strings.TrimSpace(r.Form.Get(k))
  1656. if groupName != "" {
  1657. group := dataprovider.AdminGroupMapping{
  1658. Name: groupName,
  1659. }
  1660. base, _ := strings.CutSuffix(k, "[group]")
  1661. addAsGroupType := strings.TrimSpace(r.Form.Get(base + "[group_type]"))
  1662. switch addAsGroupType {
  1663. case "1":
  1664. group.Options.AddToUsersAs = dataprovider.GroupAddToUsersAsPrimary
  1665. case "2":
  1666. group.Options.AddToUsersAs = dataprovider.GroupAddToUsersAsSecondary
  1667. default:
  1668. group.Options.AddToUsersAs = dataprovider.GroupAddToUsersAsMembership
  1669. }
  1670. admin.Groups = append(admin.Groups, group)
  1671. }
  1672. }
  1673. }
  1674. return admin, nil
  1675. }
  1676. func replacePlaceholders(field string, replacements map[string]string) string {
  1677. for k, v := range replacements {
  1678. field = strings.ReplaceAll(field, k, v)
  1679. }
  1680. return field
  1681. }
  1682. func getFolderFromTemplate(folder vfs.BaseVirtualFolder, name string) vfs.BaseVirtualFolder {
  1683. folder.Name = name
  1684. replacements := make(map[string]string)
  1685. replacements["%name%"] = folder.Name
  1686. folder.MappedPath = replacePlaceholders(folder.MappedPath, replacements)
  1687. folder.Description = replacePlaceholders(folder.Description, replacements)
  1688. switch folder.FsConfig.Provider {
  1689. case sdk.CryptedFilesystemProvider:
  1690. folder.FsConfig.CryptConfig = getCryptFsFromTemplate(folder.FsConfig.CryptConfig, replacements)
  1691. case sdk.S3FilesystemProvider:
  1692. folder.FsConfig.S3Config = getS3FsFromTemplate(folder.FsConfig.S3Config, replacements)
  1693. case sdk.GCSFilesystemProvider:
  1694. folder.FsConfig.GCSConfig = getGCSFsFromTemplate(folder.FsConfig.GCSConfig, replacements)
  1695. case sdk.AzureBlobFilesystemProvider:
  1696. folder.FsConfig.AzBlobConfig = getAzBlobFsFromTemplate(folder.FsConfig.AzBlobConfig, replacements)
  1697. case sdk.SFTPFilesystemProvider:
  1698. folder.FsConfig.SFTPConfig = getSFTPFsFromTemplate(folder.FsConfig.SFTPConfig, replacements)
  1699. case sdk.HTTPFilesystemProvider:
  1700. folder.FsConfig.HTTPConfig = getHTTPFsFromTemplate(folder.FsConfig.HTTPConfig, replacements)
  1701. }
  1702. return folder
  1703. }
  1704. func getCryptFsFromTemplate(fsConfig vfs.CryptFsConfig, replacements map[string]string) vfs.CryptFsConfig {
  1705. if fsConfig.Passphrase != nil {
  1706. if fsConfig.Passphrase.IsPlain() {
  1707. payload := replacePlaceholders(fsConfig.Passphrase.GetPayload(), replacements)
  1708. fsConfig.Passphrase = kms.NewPlainSecret(payload)
  1709. }
  1710. }
  1711. return fsConfig
  1712. }
  1713. func getS3FsFromTemplate(fsConfig vfs.S3FsConfig, replacements map[string]string) vfs.S3FsConfig {
  1714. fsConfig.KeyPrefix = replacePlaceholders(fsConfig.KeyPrefix, replacements)
  1715. fsConfig.AccessKey = replacePlaceholders(fsConfig.AccessKey, replacements)
  1716. if fsConfig.AccessSecret != nil && fsConfig.AccessSecret.IsPlain() {
  1717. payload := replacePlaceholders(fsConfig.AccessSecret.GetPayload(), replacements)
  1718. fsConfig.AccessSecret = kms.NewPlainSecret(payload)
  1719. }
  1720. return fsConfig
  1721. }
  1722. func getGCSFsFromTemplate(fsConfig vfs.GCSFsConfig, replacements map[string]string) vfs.GCSFsConfig {
  1723. fsConfig.KeyPrefix = replacePlaceholders(fsConfig.KeyPrefix, replacements)
  1724. return fsConfig
  1725. }
  1726. func getAzBlobFsFromTemplate(fsConfig vfs.AzBlobFsConfig, replacements map[string]string) vfs.AzBlobFsConfig {
  1727. fsConfig.KeyPrefix = replacePlaceholders(fsConfig.KeyPrefix, replacements)
  1728. fsConfig.AccountName = replacePlaceholders(fsConfig.AccountName, replacements)
  1729. if fsConfig.AccountKey != nil && fsConfig.AccountKey.IsPlain() {
  1730. payload := replacePlaceholders(fsConfig.AccountKey.GetPayload(), replacements)
  1731. fsConfig.AccountKey = kms.NewPlainSecret(payload)
  1732. }
  1733. return fsConfig
  1734. }
  1735. func getSFTPFsFromTemplate(fsConfig vfs.SFTPFsConfig, replacements map[string]string) vfs.SFTPFsConfig {
  1736. fsConfig.Prefix = replacePlaceholders(fsConfig.Prefix, replacements)
  1737. fsConfig.Username = replacePlaceholders(fsConfig.Username, replacements)
  1738. if fsConfig.Password != nil && fsConfig.Password.IsPlain() {
  1739. payload := replacePlaceholders(fsConfig.Password.GetPayload(), replacements)
  1740. fsConfig.Password = kms.NewPlainSecret(payload)
  1741. }
  1742. return fsConfig
  1743. }
  1744. func getHTTPFsFromTemplate(fsConfig vfs.HTTPFsConfig, replacements map[string]string) vfs.HTTPFsConfig {
  1745. fsConfig.Username = replacePlaceholders(fsConfig.Username, replacements)
  1746. return fsConfig
  1747. }
  1748. func getUserFromTemplate(user dataprovider.User, template userTemplateFields) dataprovider.User {
  1749. user.Username = template.Username
  1750. user.Password = template.Password
  1751. user.PublicKeys = template.PublicKeys
  1752. replacements := make(map[string]string)
  1753. replacements["%username%"] = user.Username
  1754. if user.Password != "" && !user.IsPasswordHashed() {
  1755. user.Password = replacePlaceholders(user.Password, replacements)
  1756. replacements["%password%"] = user.Password
  1757. }
  1758. user.HomeDir = replacePlaceholders(user.HomeDir, replacements)
  1759. var vfolders []vfs.VirtualFolder
  1760. for _, vfolder := range user.VirtualFolders {
  1761. vfolder.Name = replacePlaceholders(vfolder.Name, replacements)
  1762. vfolder.VirtualPath = replacePlaceholders(vfolder.VirtualPath, replacements)
  1763. vfolders = append(vfolders, vfolder)
  1764. }
  1765. user.VirtualFolders = vfolders
  1766. user.Description = replacePlaceholders(user.Description, replacements)
  1767. user.AdditionalInfo = replacePlaceholders(user.AdditionalInfo, replacements)
  1768. user.Filters.StartDirectory = replacePlaceholders(user.Filters.StartDirectory, replacements)
  1769. switch user.FsConfig.Provider {
  1770. case sdk.CryptedFilesystemProvider:
  1771. user.FsConfig.CryptConfig = getCryptFsFromTemplate(user.FsConfig.CryptConfig, replacements)
  1772. case sdk.S3FilesystemProvider:
  1773. user.FsConfig.S3Config = getS3FsFromTemplate(user.FsConfig.S3Config, replacements)
  1774. case sdk.GCSFilesystemProvider:
  1775. user.FsConfig.GCSConfig = getGCSFsFromTemplate(user.FsConfig.GCSConfig, replacements)
  1776. case sdk.AzureBlobFilesystemProvider:
  1777. user.FsConfig.AzBlobConfig = getAzBlobFsFromTemplate(user.FsConfig.AzBlobConfig, replacements)
  1778. case sdk.SFTPFilesystemProvider:
  1779. user.FsConfig.SFTPConfig = getSFTPFsFromTemplate(user.FsConfig.SFTPConfig, replacements)
  1780. case sdk.HTTPFilesystemProvider:
  1781. user.FsConfig.HTTPConfig = getHTTPFsFromTemplate(user.FsConfig.HTTPConfig, replacements)
  1782. }
  1783. return user
  1784. }
  1785. func getTransferLimits(r *http.Request) (int64, int64, int64, error) {
  1786. dataTransferUL, err := strconv.ParseInt(r.Form.Get("upload_data_transfer"), 10, 64)
  1787. if err != nil {
  1788. return 0, 0, 0, fmt.Errorf("invalid upload data transfer: %w", err)
  1789. }
  1790. dataTransferDL, err := strconv.ParseInt(r.Form.Get("download_data_transfer"), 10, 64)
  1791. if err != nil {
  1792. return 0, 0, 0, fmt.Errorf("invalid download data transfer: %w", err)
  1793. }
  1794. dataTransferTotal, err := strconv.ParseInt(r.Form.Get("total_data_transfer"), 10, 64)
  1795. if err != nil {
  1796. return 0, 0, 0, fmt.Errorf("invalid total data transfer: %w", err)
  1797. }
  1798. return dataTransferUL, dataTransferDL, dataTransferTotal, nil
  1799. }
  1800. func getQuotaLimits(r *http.Request) (int64, int, error) {
  1801. quotaSize, err := util.ParseBytes(r.Form.Get("quota_size"))
  1802. if err != nil {
  1803. return 0, 0, util.NewI18nError(fmt.Errorf("invalid quota size: %w", err), util.I18nErrorInvalidQuotaSize)
  1804. }
  1805. quotaFiles, err := strconv.Atoi(r.Form.Get("quota_files"))
  1806. if err != nil {
  1807. return 0, 0, fmt.Errorf("invalid quota files: %w", err)
  1808. }
  1809. return quotaSize, quotaFiles, nil
  1810. }
  1811. func updateRepeaterFormFields(r *http.Request) {
  1812. for k := range r.Form {
  1813. if hasPrefixAndSuffix(k, "public_keys[", "][public_key]") {
  1814. key := r.Form.Get(k)
  1815. if strings.TrimSpace(key) != "" {
  1816. r.Form.Add("public_keys", key)
  1817. }
  1818. continue
  1819. }
  1820. if hasPrefixAndSuffix(k, "tls_certs[", "][tls_cert]") {
  1821. cert := strings.TrimSpace(r.Form.Get(k))
  1822. if cert != "" {
  1823. r.Form.Add("tls_certs", cert)
  1824. }
  1825. continue
  1826. }
  1827. if hasPrefixAndSuffix(k, "virtual_folders[", "][vfolder_path]") {
  1828. base, _ := strings.CutSuffix(k, "[vfolder_path]")
  1829. r.Form.Add("vfolder_path", strings.TrimSpace(r.Form.Get(k)))
  1830. r.Form.Add("vfolder_name", strings.TrimSpace(r.Form.Get(base+"[vfolder_name]")))
  1831. r.Form.Add("vfolder_quota_files", strings.TrimSpace(r.Form.Get(base+"[vfolder_quota_files]")))
  1832. r.Form.Add("vfolder_quota_size", strings.TrimSpace(r.Form.Get(base+"[vfolder_quota_size]")))
  1833. continue
  1834. }
  1835. if hasPrefixAndSuffix(k, "directory_permissions[", "][sub_perm_path]") {
  1836. base, _ := strings.CutSuffix(k, "[sub_perm_path]")
  1837. r.Form.Add("sub_perm_path", strings.TrimSpace(r.Form.Get(k)))
  1838. r.Form["sub_perm_permissions"+strconv.Itoa(len(r.Form["sub_perm_path"])-1)] = r.Form[base+"[sub_perm_permissions][]"]
  1839. continue
  1840. }
  1841. if hasPrefixAndSuffix(k, "directory_patterns[", "][pattern_path]") {
  1842. base, _ := strings.CutSuffix(k, "[pattern_path]")
  1843. r.Form.Add("pattern_path", strings.TrimSpace(r.Form.Get(k)))
  1844. r.Form.Add("patterns", strings.TrimSpace(r.Form.Get(base+"[patterns]")))
  1845. r.Form.Add("pattern_type", strings.TrimSpace(r.Form.Get(base+"[pattern_type]")))
  1846. r.Form.Add("pattern_policy", strings.TrimSpace(r.Form.Get(base+"[pattern_policy]")))
  1847. continue
  1848. }
  1849. if hasPrefixAndSuffix(k, "src_bandwidth_limits[", "][bandwidth_limit_sources]") {
  1850. base, _ := strings.CutSuffix(k, "[bandwidth_limit_sources]")
  1851. r.Form.Add("bandwidth_limit_sources", r.Form.Get(k))
  1852. r.Form.Add("upload_bandwidth_source", strings.TrimSpace(r.Form.Get(base+"[upload_bandwidth_source]")))
  1853. r.Form.Add("download_bandwidth_source", strings.TrimSpace(r.Form.Get(base+"[download_bandwidth_source]")))
  1854. continue
  1855. }
  1856. if hasPrefixAndSuffix(k, "template_users[", "][tpl_username]") {
  1857. base, _ := strings.CutSuffix(k, "[tpl_username]")
  1858. r.Form.Add("tpl_username", strings.TrimSpace(r.Form.Get(k)))
  1859. r.Form.Add("tpl_password", strings.TrimSpace(r.Form.Get(base+"[tpl_password]")))
  1860. r.Form.Add("tpl_public_keys", strings.TrimSpace(r.Form.Get(base+"[tpl_public_keys]")))
  1861. continue
  1862. }
  1863. }
  1864. }
  1865. func getUserFromPostFields(r *http.Request) (dataprovider.User, error) {
  1866. user := dataprovider.User{}
  1867. err := r.ParseMultipartForm(maxRequestSize)
  1868. if err != nil {
  1869. return user, util.NewI18nError(err, util.I18nErrorInvalidForm)
  1870. }
  1871. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  1872. updateRepeaterFormFields(r)
  1873. uid, err := strconv.Atoi(r.Form.Get("uid"))
  1874. if err != nil {
  1875. return user, fmt.Errorf("invalid uid: %w", err)
  1876. }
  1877. gid, err := strconv.Atoi(r.Form.Get("gid"))
  1878. if err != nil {
  1879. return user, fmt.Errorf("invalid uid: %w", err)
  1880. }
  1881. maxSessions, err := strconv.Atoi(r.Form.Get("max_sessions"))
  1882. if err != nil {
  1883. return user, fmt.Errorf("invalid max sessions: %w", err)
  1884. }
  1885. quotaSize, quotaFiles, err := getQuotaLimits(r)
  1886. if err != nil {
  1887. return user, err
  1888. }
  1889. bandwidthUL, err := strconv.ParseInt(r.Form.Get("upload_bandwidth"), 10, 64)
  1890. if err != nil {
  1891. return user, fmt.Errorf("invalid upload bandwidth: %w", err)
  1892. }
  1893. bandwidthDL, err := strconv.ParseInt(r.Form.Get("download_bandwidth"), 10, 64)
  1894. if err != nil {
  1895. return user, fmt.Errorf("invalid download bandwidth: %w", err)
  1896. }
  1897. dataTransferUL, dataTransferDL, dataTransferTotal, err := getTransferLimits(r)
  1898. if err != nil {
  1899. return user, err
  1900. }
  1901. status, err := strconv.Atoi(r.Form.Get("status"))
  1902. if err != nil {
  1903. return user, fmt.Errorf("invalid status: %w", err)
  1904. }
  1905. expirationDateMillis := int64(0)
  1906. expirationDateString := r.Form.Get("expiration_date")
  1907. if strings.TrimSpace(expirationDateString) != "" {
  1908. expirationDate, err := time.Parse(webDateTimeFormat, expirationDateString)
  1909. if err != nil {
  1910. return user, err
  1911. }
  1912. expirationDateMillis = util.GetTimeAsMsSinceEpoch(expirationDate)
  1913. }
  1914. fsConfig, err := getFsConfigFromPostFields(r)
  1915. if err != nil {
  1916. return user, err
  1917. }
  1918. filters, err := getFiltersFromUserPostFields(r)
  1919. if err != nil {
  1920. return user, err
  1921. }
  1922. filters.TLSCerts = r.Form["tls_certs"]
  1923. user = dataprovider.User{
  1924. BaseUser: sdk.BaseUser{
  1925. Username: strings.TrimSpace(r.Form.Get("username")),
  1926. Email: strings.TrimSpace(r.Form.Get("email")),
  1927. Password: strings.TrimSpace(r.Form.Get("password")),
  1928. PublicKeys: r.Form["public_keys"],
  1929. HomeDir: strings.TrimSpace(r.Form.Get("home_dir")),
  1930. UID: uid,
  1931. GID: gid,
  1932. Permissions: getUserPermissionsFromPostFields(r),
  1933. MaxSessions: maxSessions,
  1934. QuotaSize: quotaSize,
  1935. QuotaFiles: quotaFiles,
  1936. UploadBandwidth: bandwidthUL,
  1937. DownloadBandwidth: bandwidthDL,
  1938. UploadDataTransfer: dataTransferUL,
  1939. DownloadDataTransfer: dataTransferDL,
  1940. TotalDataTransfer: dataTransferTotal,
  1941. Status: status,
  1942. ExpirationDate: expirationDateMillis,
  1943. AdditionalInfo: r.Form.Get("additional_info"),
  1944. Description: r.Form.Get("description"),
  1945. Role: strings.TrimSpace(r.Form.Get("role")),
  1946. },
  1947. Filters: dataprovider.UserFilters{
  1948. BaseUserFilters: filters,
  1949. RequirePasswordChange: r.Form.Get("require_password_change") != "",
  1950. },
  1951. VirtualFolders: getVirtualFoldersFromPostFields(r),
  1952. FsConfig: fsConfig,
  1953. Groups: getGroupsFromUserPostFields(r),
  1954. }
  1955. return user, nil
  1956. }
  1957. func getGroupFromPostFields(r *http.Request) (dataprovider.Group, error) {
  1958. group := dataprovider.Group{}
  1959. err := r.ParseMultipartForm(maxRequestSize)
  1960. if err != nil {
  1961. return group, util.NewI18nError(err, util.I18nErrorInvalidForm)
  1962. }
  1963. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  1964. updateRepeaterFormFields(r)
  1965. maxSessions, err := strconv.Atoi(r.Form.Get("max_sessions"))
  1966. if err != nil {
  1967. return group, fmt.Errorf("invalid max sessions: %w", err)
  1968. }
  1969. quotaSize, quotaFiles, err := getQuotaLimits(r)
  1970. if err != nil {
  1971. return group, err
  1972. }
  1973. bandwidthUL, err := strconv.ParseInt(r.Form.Get("upload_bandwidth"), 10, 64)
  1974. if err != nil {
  1975. return group, fmt.Errorf("invalid upload bandwidth: %w", err)
  1976. }
  1977. bandwidthDL, err := strconv.ParseInt(r.Form.Get("download_bandwidth"), 10, 64)
  1978. if err != nil {
  1979. return group, fmt.Errorf("invalid download bandwidth: %w", err)
  1980. }
  1981. dataTransferUL, dataTransferDL, dataTransferTotal, err := getTransferLimits(r)
  1982. if err != nil {
  1983. return group, err
  1984. }
  1985. expiresIn, err := strconv.Atoi(r.Form.Get("expires_in"))
  1986. if err != nil {
  1987. return group, fmt.Errorf("invalid expires in: %w", err)
  1988. }
  1989. fsConfig, err := getFsConfigFromPostFields(r)
  1990. if err != nil {
  1991. return group, err
  1992. }
  1993. filters, err := getFiltersFromUserPostFields(r)
  1994. if err != nil {
  1995. return group, err
  1996. }
  1997. group = dataprovider.Group{
  1998. BaseGroup: sdk.BaseGroup{
  1999. Name: strings.TrimSpace(r.Form.Get("name")),
  2000. Description: r.Form.Get("description"),
  2001. },
  2002. UserSettings: dataprovider.GroupUserSettings{
  2003. BaseGroupUserSettings: sdk.BaseGroupUserSettings{
  2004. HomeDir: strings.TrimSpace(r.Form.Get("home_dir")),
  2005. MaxSessions: maxSessions,
  2006. QuotaSize: quotaSize,
  2007. QuotaFiles: quotaFiles,
  2008. Permissions: getSubDirPermissionsFromPostFields(r),
  2009. UploadBandwidth: bandwidthUL,
  2010. DownloadBandwidth: bandwidthDL,
  2011. UploadDataTransfer: dataTransferUL,
  2012. DownloadDataTransfer: dataTransferDL,
  2013. TotalDataTransfer: dataTransferTotal,
  2014. ExpiresIn: expiresIn,
  2015. Filters: filters,
  2016. },
  2017. FsConfig: fsConfig,
  2018. },
  2019. VirtualFolders: getVirtualFoldersFromPostFields(r),
  2020. }
  2021. return group, nil
  2022. }
  2023. func getKeyValsFromPostFields(r *http.Request, key, val string) []dataprovider.KeyValue {
  2024. var res []dataprovider.KeyValue
  2025. for k := range r.Form {
  2026. if strings.HasPrefix(k, key) {
  2027. formKey := r.Form.Get(k)
  2028. idx := strings.TrimPrefix(k, key)
  2029. formVal := strings.TrimSpace(r.Form.Get(fmt.Sprintf("%s%s", val, idx)))
  2030. if formKey != "" && formVal != "" {
  2031. res = append(res, dataprovider.KeyValue{
  2032. Key: formKey,
  2033. Value: formVal,
  2034. })
  2035. }
  2036. }
  2037. }
  2038. return res
  2039. }
  2040. func getFoldersRetentionFromPostFields(r *http.Request) ([]dataprovider.FolderRetention, error) {
  2041. var res []dataprovider.FolderRetention
  2042. for k := range r.Form {
  2043. if strings.HasPrefix(k, "folder_retention_path") {
  2044. folderPath := strings.TrimSpace(r.Form.Get(k))
  2045. if folderPath != "" {
  2046. idx := strings.TrimPrefix(k, "folder_retention_path")
  2047. retention, err := strconv.Atoi(r.Form.Get(fmt.Sprintf("folder_retention_val%s", idx)))
  2048. if err != nil {
  2049. return nil, fmt.Errorf("invalid retention for path %q: %w", folderPath, err)
  2050. }
  2051. options := r.Form[fmt.Sprintf("folder_retention_options%s", idx)]
  2052. res = append(res, dataprovider.FolderRetention{
  2053. Path: folderPath,
  2054. Retention: retention,
  2055. DeleteEmptyDirs: util.Contains(options, "1"),
  2056. IgnoreUserPermissions: util.Contains(options, "2"),
  2057. })
  2058. }
  2059. }
  2060. }
  2061. return res, nil
  2062. }
  2063. func getHTTPPartsFromPostFields(r *http.Request) []dataprovider.HTTPPart {
  2064. var result []dataprovider.HTTPPart
  2065. for k := range r.Form {
  2066. if strings.HasPrefix(k, "http_part_name") {
  2067. partName := strings.TrimSpace(r.Form.Get(k))
  2068. if partName != "" {
  2069. idx := strings.TrimPrefix(k, "http_part_name")
  2070. order, err := strconv.Atoi(idx)
  2071. if err != nil {
  2072. continue
  2073. }
  2074. filePath := strings.TrimSpace(r.Form.Get(fmt.Sprintf("http_part_file%s", idx)))
  2075. body := r.Form.Get(fmt.Sprintf("http_part_body%s", idx))
  2076. concatHeaders := getSliceFromDelimitedValues(r.Form.Get(fmt.Sprintf("http_part_headers%s", idx)), "\n")
  2077. var headers []dataprovider.KeyValue
  2078. for _, h := range concatHeaders {
  2079. values := strings.SplitN(h, ":", 2)
  2080. if len(values) > 1 {
  2081. headers = append(headers, dataprovider.KeyValue{
  2082. Key: strings.TrimSpace(values[0]),
  2083. Value: strings.TrimSpace(values[1]),
  2084. })
  2085. }
  2086. }
  2087. result = append(result, dataprovider.HTTPPart{
  2088. Name: partName,
  2089. Filepath: filePath,
  2090. Headers: headers,
  2091. Body: body,
  2092. Order: order,
  2093. })
  2094. }
  2095. }
  2096. }
  2097. sort.Slice(result, func(i, j int) bool {
  2098. return result[i].Order < result[j].Order
  2099. })
  2100. return result
  2101. }
  2102. func getEventActionOptionsFromPostFields(r *http.Request) (dataprovider.BaseEventActionOptions, error) {
  2103. httpTimeout, err := strconv.Atoi(r.Form.Get("http_timeout"))
  2104. if err != nil {
  2105. return dataprovider.BaseEventActionOptions{}, fmt.Errorf("invalid http timeout: %w", err)
  2106. }
  2107. cmdTimeout, err := strconv.Atoi(r.Form.Get("cmd_timeout"))
  2108. if err != nil {
  2109. return dataprovider.BaseEventActionOptions{}, fmt.Errorf("invalid command timeout: %w", err)
  2110. }
  2111. foldersRetention, err := getFoldersRetentionFromPostFields(r)
  2112. if err != nil {
  2113. return dataprovider.BaseEventActionOptions{}, err
  2114. }
  2115. fsActionType, err := strconv.Atoi(r.Form.Get("fs_action_type"))
  2116. if err != nil {
  2117. return dataprovider.BaseEventActionOptions{}, fmt.Errorf("invalid fs action type: %w", err)
  2118. }
  2119. pwdExpirationThreshold, err := strconv.Atoi(r.Form.Get("pwd_expiration_threshold"))
  2120. if err != nil {
  2121. return dataprovider.BaseEventActionOptions{}, fmt.Errorf("invalid password expiration threshold: %w", err)
  2122. }
  2123. var emailAttachments []string
  2124. if r.Form.Get("email_attachments") != "" {
  2125. emailAttachments = getSliceFromDelimitedValues(r.Form.Get("email_attachments"), ",")
  2126. }
  2127. var cmdArgs []string
  2128. if r.Form.Get("cmd_arguments") != "" {
  2129. cmdArgs = getSliceFromDelimitedValues(r.Form.Get("cmd_arguments"), ",")
  2130. }
  2131. idpMode := 0
  2132. if r.Form.Get("idp_mode") == "1" {
  2133. idpMode = 1
  2134. }
  2135. emailContentType := 0
  2136. if r.Form.Get("email_content_type") == "1" {
  2137. emailContentType = 1
  2138. }
  2139. options := dataprovider.BaseEventActionOptions{
  2140. HTTPConfig: dataprovider.EventActionHTTPConfig{
  2141. Endpoint: strings.TrimSpace(r.Form.Get("http_endpoint")),
  2142. Username: strings.TrimSpace(r.Form.Get("http_username")),
  2143. Password: getSecretFromFormField(r, "http_password"),
  2144. Headers: getKeyValsFromPostFields(r, "http_header_key", "http_header_val"),
  2145. Timeout: httpTimeout,
  2146. SkipTLSVerify: r.Form.Get("http_skip_tls_verify") != "",
  2147. Method: r.Form.Get("http_method"),
  2148. QueryParameters: getKeyValsFromPostFields(r, "http_query_key", "http_query_val"),
  2149. Body: r.Form.Get("http_body"),
  2150. Parts: getHTTPPartsFromPostFields(r),
  2151. },
  2152. CmdConfig: dataprovider.EventActionCommandConfig{
  2153. Cmd: strings.TrimSpace(r.Form.Get("cmd_path")),
  2154. Args: cmdArgs,
  2155. Timeout: cmdTimeout,
  2156. EnvVars: getKeyValsFromPostFields(r, "cmd_env_key", "cmd_env_val"),
  2157. },
  2158. EmailConfig: dataprovider.EventActionEmailConfig{
  2159. Recipients: getSliceFromDelimitedValues(r.Form.Get("email_recipients"), ","),
  2160. Bcc: getSliceFromDelimitedValues(r.Form.Get("email_bcc"), ","),
  2161. Subject: r.Form.Get("email_subject"),
  2162. ContentType: emailContentType,
  2163. Body: r.Form.Get("email_body"),
  2164. Attachments: emailAttachments,
  2165. },
  2166. RetentionConfig: dataprovider.EventActionDataRetentionConfig{
  2167. Folders: foldersRetention,
  2168. },
  2169. FsConfig: dataprovider.EventActionFilesystemConfig{
  2170. Type: fsActionType,
  2171. Renames: getKeyValsFromPostFields(r, "fs_rename_source", "fs_rename_target"),
  2172. Deletes: getSliceFromDelimitedValues(r.Form.Get("fs_delete_paths"), ","),
  2173. MkDirs: getSliceFromDelimitedValues(r.Form.Get("fs_mkdir_paths"), ","),
  2174. Exist: getSliceFromDelimitedValues(r.Form.Get("fs_exist_paths"), ","),
  2175. Copy: getKeyValsFromPostFields(r, "fs_copy_source", "fs_copy_target"),
  2176. Compress: dataprovider.EventActionFsCompress{
  2177. Name: strings.TrimSpace(r.Form.Get("fs_compress_name")),
  2178. Paths: getSliceFromDelimitedValues(r.Form.Get("fs_compress_paths"), ","),
  2179. },
  2180. },
  2181. PwdExpirationConfig: dataprovider.EventActionPasswordExpiration{
  2182. Threshold: pwdExpirationThreshold,
  2183. },
  2184. IDPConfig: dataprovider.EventActionIDPAccountCheck{
  2185. Mode: idpMode,
  2186. TemplateUser: strings.TrimSpace(r.Form.Get("idp_user")),
  2187. TemplateAdmin: strings.TrimSpace(r.Form.Get("idp_admin")),
  2188. },
  2189. }
  2190. return options, nil
  2191. }
  2192. func getEventActionFromPostFields(r *http.Request) (dataprovider.BaseEventAction, error) {
  2193. err := r.ParseForm()
  2194. if err != nil {
  2195. return dataprovider.BaseEventAction{}, util.NewI18nError(err, util.I18nErrorInvalidForm)
  2196. }
  2197. actionType, err := strconv.Atoi(r.Form.Get("type"))
  2198. if err != nil {
  2199. return dataprovider.BaseEventAction{}, fmt.Errorf("invalid action type: %w", err)
  2200. }
  2201. options, err := getEventActionOptionsFromPostFields(r)
  2202. if err != nil {
  2203. return dataprovider.BaseEventAction{}, err
  2204. }
  2205. action := dataprovider.BaseEventAction{
  2206. Name: strings.TrimSpace(r.Form.Get("name")),
  2207. Description: r.Form.Get("description"),
  2208. Type: actionType,
  2209. Options: options,
  2210. }
  2211. return action, nil
  2212. }
  2213. func getIDPLoginEventFromPostField(r *http.Request) int {
  2214. switch r.Form.Get("idp_login_event") {
  2215. case "1":
  2216. return 1
  2217. case "2":
  2218. return 2
  2219. default:
  2220. return 0
  2221. }
  2222. }
  2223. func getEventRuleConditionsFromPostFields(r *http.Request) (dataprovider.EventConditions, error) {
  2224. var schedules []dataprovider.Schedule
  2225. var names, groupNames, roleNames, fsPaths []dataprovider.ConditionPattern
  2226. for k := range r.Form {
  2227. if strings.HasPrefix(k, "schedule_hour") {
  2228. hour := strings.TrimSpace(r.Form.Get(k))
  2229. if hour != "" {
  2230. idx := strings.TrimPrefix(k, "schedule_hour")
  2231. dayOfWeek := strings.TrimSpace(r.Form.Get(fmt.Sprintf("schedule_day_of_week%s", idx)))
  2232. dayOfMonth := strings.TrimSpace(r.Form.Get(fmt.Sprintf("schedule_day_of_month%s", idx)))
  2233. month := strings.TrimSpace(r.Form.Get(fmt.Sprintf("schedule_month%s", idx)))
  2234. schedules = append(schedules, dataprovider.Schedule{
  2235. Hours: hour,
  2236. DayOfWeek: dayOfWeek,
  2237. DayOfMonth: dayOfMonth,
  2238. Month: month,
  2239. })
  2240. }
  2241. }
  2242. if strings.HasPrefix(k, "name_pattern") {
  2243. pattern := strings.TrimSpace(r.Form.Get(k))
  2244. if pattern != "" {
  2245. idx := strings.TrimPrefix(k, "name_pattern")
  2246. patternType := r.Form.Get(fmt.Sprintf("type_name_pattern%s", idx))
  2247. names = append(names, dataprovider.ConditionPattern{
  2248. Pattern: pattern,
  2249. InverseMatch: patternType == inversePatternType,
  2250. })
  2251. }
  2252. }
  2253. if strings.HasPrefix(k, "group_name_pattern") {
  2254. pattern := strings.TrimSpace(r.Form.Get(k))
  2255. if pattern != "" {
  2256. idx := strings.TrimPrefix(k, "group_name_pattern")
  2257. patternType := r.Form.Get(fmt.Sprintf("type_group_name_pattern%s", idx))
  2258. groupNames = append(groupNames, dataprovider.ConditionPattern{
  2259. Pattern: pattern,
  2260. InverseMatch: patternType == inversePatternType,
  2261. })
  2262. }
  2263. }
  2264. if strings.HasPrefix(k, "role_name_pattern") {
  2265. pattern := strings.TrimSpace(r.Form.Get(k))
  2266. if pattern != "" {
  2267. idx := strings.TrimPrefix(k, "role_name_pattern")
  2268. patternType := r.Form.Get(fmt.Sprintf("type_role_name_pattern%s", idx))
  2269. roleNames = append(roleNames, dataprovider.ConditionPattern{
  2270. Pattern: pattern,
  2271. InverseMatch: patternType == inversePatternType,
  2272. })
  2273. }
  2274. }
  2275. if strings.HasPrefix(k, "fs_path_pattern") {
  2276. pattern := strings.TrimSpace(r.Form.Get(k))
  2277. if pattern != "" {
  2278. idx := strings.TrimPrefix(k, "fs_path_pattern")
  2279. patternType := r.Form.Get(fmt.Sprintf("type_fs_path_pattern%s", idx))
  2280. fsPaths = append(fsPaths, dataprovider.ConditionPattern{
  2281. Pattern: pattern,
  2282. InverseMatch: patternType == inversePatternType,
  2283. })
  2284. }
  2285. }
  2286. }
  2287. minFileSize, err := util.ParseBytes(r.Form.Get("fs_min_size"))
  2288. if err != nil {
  2289. return dataprovider.EventConditions{}, fmt.Errorf("invalid min file size: %w", err)
  2290. }
  2291. maxFileSize, err := util.ParseBytes(r.Form.Get("fs_max_size"))
  2292. if err != nil {
  2293. return dataprovider.EventConditions{}, fmt.Errorf("invalid max file size: %w", err)
  2294. }
  2295. conditions := dataprovider.EventConditions{
  2296. FsEvents: r.Form["fs_events"],
  2297. ProviderEvents: r.Form["provider_events"],
  2298. IDPLoginEvent: getIDPLoginEventFromPostField(r),
  2299. Schedules: schedules,
  2300. Options: dataprovider.ConditionOptions{
  2301. Names: names,
  2302. GroupNames: groupNames,
  2303. RoleNames: roleNames,
  2304. FsPaths: fsPaths,
  2305. Protocols: r.Form["fs_protocols"],
  2306. ProviderObjects: r.Form["provider_objects"],
  2307. MinFileSize: minFileSize,
  2308. MaxFileSize: maxFileSize,
  2309. ConcurrentExecution: r.Form.Get("concurrent_execution") != "",
  2310. },
  2311. }
  2312. return conditions, nil
  2313. }
  2314. func getEventRuleActionsFromPostFields(r *http.Request) ([]dataprovider.EventAction, error) {
  2315. var actions []dataprovider.EventAction
  2316. for k := range r.Form {
  2317. if strings.HasPrefix(k, "action_name") {
  2318. name := strings.TrimSpace(r.Form.Get(k))
  2319. if name != "" {
  2320. idx := strings.TrimPrefix(k, "action_name")
  2321. order, err := strconv.Atoi(r.Form.Get(fmt.Sprintf("action_order%s", idx)))
  2322. if err != nil {
  2323. return actions, fmt.Errorf("invalid order: %w", err)
  2324. }
  2325. options := r.Form[fmt.Sprintf("action_options%s", idx)]
  2326. actions = append(actions, dataprovider.EventAction{
  2327. BaseEventAction: dataprovider.BaseEventAction{
  2328. Name: name,
  2329. },
  2330. Order: order + 1,
  2331. Options: dataprovider.EventActionOptions{
  2332. IsFailureAction: util.Contains(options, "1"),
  2333. StopOnFailure: util.Contains(options, "2"),
  2334. ExecuteSync: util.Contains(options, "3"),
  2335. },
  2336. })
  2337. }
  2338. }
  2339. }
  2340. return actions, nil
  2341. }
  2342. func getEventRuleFromPostFields(r *http.Request) (dataprovider.EventRule, error) {
  2343. err := r.ParseForm()
  2344. if err != nil {
  2345. return dataprovider.EventRule{}, util.NewI18nError(err, util.I18nErrorInvalidForm)
  2346. }
  2347. status, err := strconv.Atoi(r.Form.Get("status"))
  2348. if err != nil {
  2349. return dataprovider.EventRule{}, fmt.Errorf("invalid status: %w", err)
  2350. }
  2351. trigger, err := strconv.Atoi(r.Form.Get("trigger"))
  2352. if err != nil {
  2353. return dataprovider.EventRule{}, fmt.Errorf("invalid trigger: %w", err)
  2354. }
  2355. conditions, err := getEventRuleConditionsFromPostFields(r)
  2356. if err != nil {
  2357. return dataprovider.EventRule{}, err
  2358. }
  2359. actions, err := getEventRuleActionsFromPostFields(r)
  2360. if err != nil {
  2361. return dataprovider.EventRule{}, err
  2362. }
  2363. rule := dataprovider.EventRule{
  2364. Name: strings.TrimSpace(r.Form.Get("name")),
  2365. Status: status,
  2366. Description: r.Form.Get("description"),
  2367. Trigger: trigger,
  2368. Conditions: conditions,
  2369. Actions: actions,
  2370. }
  2371. return rule, nil
  2372. }
  2373. func getRoleFromPostFields(r *http.Request) (dataprovider.Role, error) {
  2374. err := r.ParseForm()
  2375. if err != nil {
  2376. return dataprovider.Role{}, util.NewI18nError(err, util.I18nErrorInvalidForm)
  2377. }
  2378. return dataprovider.Role{
  2379. Name: strings.TrimSpace(r.Form.Get("name")),
  2380. Description: r.Form.Get("description"),
  2381. }, nil
  2382. }
  2383. func getIPListEntryFromPostFields(r *http.Request, listType dataprovider.IPListType) (dataprovider.IPListEntry, error) {
  2384. err := r.ParseForm()
  2385. if err != nil {
  2386. return dataprovider.IPListEntry{}, util.NewI18nError(err, util.I18nErrorInvalidForm)
  2387. }
  2388. var mode int
  2389. if listType == dataprovider.IPListTypeDefender {
  2390. mode, err = strconv.Atoi(r.Form.Get("mode"))
  2391. if err != nil {
  2392. return dataprovider.IPListEntry{}, fmt.Errorf("invalid mode: %w", err)
  2393. }
  2394. } else {
  2395. mode = 1
  2396. }
  2397. protocols := 0
  2398. for _, proto := range r.Form["protocols"] {
  2399. p, err := strconv.Atoi(proto)
  2400. if err == nil {
  2401. protocols += p
  2402. }
  2403. }
  2404. return dataprovider.IPListEntry{
  2405. IPOrNet: strings.TrimSpace(r.Form.Get("ipornet")),
  2406. Mode: mode,
  2407. Protocols: protocols,
  2408. Description: r.Form.Get("description"),
  2409. }, nil
  2410. }
  2411. func getSFTPConfigsFromPostFields(r *http.Request) *dataprovider.SFTPDConfigs {
  2412. return &dataprovider.SFTPDConfigs{
  2413. HostKeyAlgos: r.Form["sftp_host_key_algos"],
  2414. PublicKeyAlgos: r.Form["sftp_pub_key_algos"],
  2415. Moduli: getSliceFromDelimitedValues(r.Form.Get("sftp_moduli"), ","),
  2416. KexAlgorithms: r.Form["sftp_kex_algos"],
  2417. Ciphers: r.Form["sftp_ciphers"],
  2418. MACs: r.Form["sftp_macs"],
  2419. }
  2420. }
  2421. func getACMEConfigsFromPostFields(r *http.Request) *dataprovider.ACMEConfigs {
  2422. port, err := strconv.Atoi(r.Form.Get("acme_port"))
  2423. if err != nil {
  2424. port = 80
  2425. }
  2426. var protocols int
  2427. for _, val := range r.Form["acme_protocols"] {
  2428. switch val {
  2429. case "1":
  2430. protocols++
  2431. case "2":
  2432. protocols += 2
  2433. case "3":
  2434. protocols += 4
  2435. }
  2436. }
  2437. return &dataprovider.ACMEConfigs{
  2438. Domain: strings.TrimSpace(r.Form.Get("acme_domain")),
  2439. Email: strings.TrimSpace(r.Form.Get("acme_email")),
  2440. HTTP01Challenge: dataprovider.ACMEHTTP01Challenge{Port: port},
  2441. Protocols: protocols,
  2442. }
  2443. }
  2444. func getSMTPConfigsFromPostFields(r *http.Request) *dataprovider.SMTPConfigs {
  2445. port, err := strconv.Atoi(r.Form.Get("smtp_port"))
  2446. if err != nil {
  2447. port = 587
  2448. }
  2449. authType, err := strconv.Atoi(r.Form.Get("smtp_auth"))
  2450. if err != nil {
  2451. authType = 0
  2452. }
  2453. encryption, err := strconv.Atoi(r.Form.Get("smtp_encryption"))
  2454. if err != nil {
  2455. encryption = 0
  2456. }
  2457. debug := 0
  2458. if r.Form.Get("smtp_debug") != "" {
  2459. debug = 1
  2460. }
  2461. oauth2Provider := 0
  2462. if r.Form.Get("smtp_oauth2_provider") == "1" {
  2463. oauth2Provider = 1
  2464. }
  2465. return &dataprovider.SMTPConfigs{
  2466. Host: strings.TrimSpace(r.Form.Get("smtp_host")),
  2467. Port: port,
  2468. From: strings.TrimSpace(r.Form.Get("smtp_from")),
  2469. User: strings.TrimSpace(r.Form.Get("smtp_username")),
  2470. Password: getSecretFromFormField(r, "smtp_password"),
  2471. AuthType: authType,
  2472. Encryption: encryption,
  2473. Domain: strings.TrimSpace(r.Form.Get("smtp_domain")),
  2474. Debug: debug,
  2475. OAuth2: dataprovider.SMTPOAuth2{
  2476. Provider: oauth2Provider,
  2477. Tenant: strings.TrimSpace(r.Form.Get("smtp_oauth2_tenant")),
  2478. ClientID: strings.TrimSpace(r.Form.Get("smtp_oauth2_client_id")),
  2479. ClientSecret: getSecretFromFormField(r, "smtp_oauth2_client_secret"),
  2480. RefreshToken: getSecretFromFormField(r, "smtp_oauth2_refresh_token"),
  2481. },
  2482. }
  2483. }
  2484. func (s *httpdServer) handleWebAdminForgotPwd(w http.ResponseWriter, r *http.Request) {
  2485. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2486. if !smtp.IsEnabled() {
  2487. s.renderNotFoundPage(w, r, errors.New("this page does not exist"))
  2488. return
  2489. }
  2490. s.renderForgotPwdPage(w, r, nil, util.GetIPFromRemoteAddress(r.RemoteAddr))
  2491. }
  2492. func (s *httpdServer) handleWebAdminForgotPwdPost(w http.ResponseWriter, r *http.Request) {
  2493. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2494. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2495. err := r.ParseForm()
  2496. if err != nil {
  2497. s.renderForgotPwdPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidForm), ipAddr)
  2498. return
  2499. }
  2500. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2501. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  2502. return
  2503. }
  2504. err = handleForgotPassword(r, r.Form.Get("username"), true)
  2505. if err != nil {
  2506. s.renderForgotPwdPage(w, r, util.NewI18nError(err, util.I18nErrorPwdResetGeneric), ipAddr)
  2507. return
  2508. }
  2509. http.Redirect(w, r, webAdminResetPwdPath, http.StatusFound)
  2510. }
  2511. func (s *httpdServer) handleWebAdminPasswordReset(w http.ResponseWriter, r *http.Request) {
  2512. r.Body = http.MaxBytesReader(w, r.Body, maxLoginBodySize)
  2513. if !smtp.IsEnabled() {
  2514. s.renderNotFoundPage(w, r, errors.New("this page does not exist"))
  2515. return
  2516. }
  2517. s.renderResetPwdPage(w, r, nil, util.GetIPFromRemoteAddress(r.RemoteAddr))
  2518. }
  2519. func (s *httpdServer) handleWebAdminTwoFactor(w http.ResponseWriter, r *http.Request) {
  2520. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2521. s.renderTwoFactorPage(w, r, nil, util.GetIPFromRemoteAddress(r.RemoteAddr))
  2522. }
  2523. func (s *httpdServer) handleWebAdminTwoFactorRecovery(w http.ResponseWriter, r *http.Request) {
  2524. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2525. s.renderTwoFactorRecoveryPage(w, r, nil, util.GetIPFromRemoteAddress(r.RemoteAddr))
  2526. }
  2527. func (s *httpdServer) handleWebAdminMFA(w http.ResponseWriter, r *http.Request) {
  2528. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2529. s.renderMFAPage(w, r)
  2530. }
  2531. func (s *httpdServer) handleWebAdminProfile(w http.ResponseWriter, r *http.Request) {
  2532. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2533. s.renderProfilePage(w, r, nil)
  2534. }
  2535. func (s *httpdServer) handleWebAdminChangePwd(w http.ResponseWriter, r *http.Request) {
  2536. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2537. s.renderChangePasswordPage(w, r, nil)
  2538. }
  2539. func (s *httpdServer) handleWebAdminProfilePost(w http.ResponseWriter, r *http.Request) {
  2540. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2541. err := r.ParseForm()
  2542. if err != nil {
  2543. s.renderProfilePage(w, r, util.NewI18nError(err, util.I18nErrorInvalidForm))
  2544. return
  2545. }
  2546. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2547. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2548. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  2549. return
  2550. }
  2551. claims, err := getTokenClaims(r)
  2552. if err != nil || claims.Username == "" {
  2553. s.renderProfilePage(w, r, util.NewI18nError(err, util.I18nErrorInvalidToken))
  2554. return
  2555. }
  2556. admin, err := dataprovider.AdminExists(claims.Username)
  2557. if err != nil {
  2558. s.renderProfilePage(w, r, err)
  2559. return
  2560. }
  2561. admin.Filters.AllowAPIKeyAuth = r.Form.Get("allow_api_key_auth") != ""
  2562. admin.Email = r.Form.Get("email")
  2563. admin.Description = r.Form.Get("description")
  2564. err = dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, ipAddr, admin.Role)
  2565. if err != nil {
  2566. s.renderProfilePage(w, r, err)
  2567. return
  2568. }
  2569. s.renderMessagePage(w, r, util.I18nProfileTitle, http.StatusOK, nil, util.I18nProfileUpdated)
  2570. }
  2571. func (s *httpdServer) handleWebMaintenance(w http.ResponseWriter, r *http.Request) {
  2572. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2573. s.renderMaintenancePage(w, r, nil)
  2574. }
  2575. func (s *httpdServer) handleWebRestore(w http.ResponseWriter, r *http.Request) {
  2576. r.Body = http.MaxBytesReader(w, r.Body, MaxRestoreSize)
  2577. claims, err := getTokenClaims(r)
  2578. if err != nil || claims.Username == "" {
  2579. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  2580. return
  2581. }
  2582. err = r.ParseMultipartForm(MaxRestoreSize)
  2583. if err != nil {
  2584. s.renderMaintenancePage(w, r, util.NewI18nError(err, util.I18nErrorInvalidForm))
  2585. return
  2586. }
  2587. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  2588. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2589. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2590. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  2591. return
  2592. }
  2593. restoreMode, err := strconv.Atoi(r.Form.Get("mode"))
  2594. if err != nil {
  2595. s.renderMaintenancePage(w, r, err)
  2596. return
  2597. }
  2598. scanQuota, err := strconv.Atoi(r.Form.Get("quota"))
  2599. if err != nil {
  2600. s.renderMaintenancePage(w, r, err)
  2601. return
  2602. }
  2603. backupFile, _, err := r.FormFile("backup_file")
  2604. if err != nil {
  2605. s.renderMaintenancePage(w, r, util.NewI18nError(err, util.I18nErrorBackupFile))
  2606. return
  2607. }
  2608. defer backupFile.Close()
  2609. backupContent, err := io.ReadAll(backupFile)
  2610. if err != nil || len(backupContent) == 0 {
  2611. if len(backupContent) == 0 {
  2612. err = errors.New("backup file size must be greater than 0")
  2613. }
  2614. s.renderMaintenancePage(w, r, util.NewI18nError(err, util.I18nErrorBackupFile))
  2615. return
  2616. }
  2617. if err := restoreBackup(backupContent, "", scanQuota, restoreMode, claims.Username, ipAddr, claims.Role); err != nil {
  2618. s.renderMaintenancePage(w, r, util.NewI18nError(err, util.I18nErrorRestore))
  2619. return
  2620. }
  2621. s.renderMessagePage(w, r, util.I18nMaintenanceTitle, http.StatusOK, nil, util.I18nBackupOK)
  2622. }
  2623. func getAllAdmins(w http.ResponseWriter, r *http.Request) {
  2624. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2625. claims, err := getTokenClaims(r)
  2626. if err != nil || claims.Username == "" {
  2627. sendAPIResponse(w, r, nil, util.I18nErrorDirList403, http.StatusForbidden)
  2628. return
  2629. }
  2630. admins := make([]dataprovider.Admin, 0, 50)
  2631. for {
  2632. a, err := dataprovider.GetAdmins(defaultQueryLimit, len(admins), dataprovider.OrderASC)
  2633. if err != nil {
  2634. sendAPIResponse(w, r, err, getI18NErrorString(err, util.I18nError500Message), http.StatusInternalServerError)
  2635. return
  2636. }
  2637. admins = append(admins, a...)
  2638. if len(a) < defaultQueryLimit {
  2639. break
  2640. }
  2641. }
  2642. render.JSON(w, r, admins)
  2643. }
  2644. func (s *httpdServer) handleGetWebAdmins(w http.ResponseWriter, r *http.Request) {
  2645. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2646. data := s.getBasePageData(util.I18nAdminsTitle, webAdminsPath, r)
  2647. renderAdminTemplate(w, templateAdmins, data)
  2648. }
  2649. func (s *httpdServer) handleWebAdminSetupGet(w http.ResponseWriter, r *http.Request) {
  2650. r.Body = http.MaxBytesReader(w, r.Body, maxLoginBodySize)
  2651. if dataprovider.HasAdmin() {
  2652. http.Redirect(w, r, webAdminLoginPath, http.StatusFound)
  2653. return
  2654. }
  2655. s.renderAdminSetupPage(w, r, "", util.GetIPFromRemoteAddress(r.RemoteAddr), nil)
  2656. }
  2657. func (s *httpdServer) handleWebAddAdminGet(w http.ResponseWriter, r *http.Request) {
  2658. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2659. admin := &dataprovider.Admin{
  2660. Status: 1,
  2661. Permissions: []string{dataprovider.PermAdminAny},
  2662. }
  2663. s.renderAddUpdateAdminPage(w, r, admin, nil, true)
  2664. }
  2665. func (s *httpdServer) handleWebUpdateAdminGet(w http.ResponseWriter, r *http.Request) {
  2666. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2667. username := getURLParam(r, "username")
  2668. admin, err := dataprovider.AdminExists(username)
  2669. if err == nil {
  2670. s.renderAddUpdateAdminPage(w, r, &admin, nil, false)
  2671. } else if errors.Is(err, util.ErrNotFound) {
  2672. s.renderNotFoundPage(w, r, err)
  2673. } else {
  2674. s.renderInternalServerErrorPage(w, r, err)
  2675. }
  2676. }
  2677. func (s *httpdServer) handleWebAddAdminPost(w http.ResponseWriter, r *http.Request) {
  2678. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2679. claims, err := getTokenClaims(r)
  2680. if err != nil || claims.Username == "" {
  2681. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  2682. return
  2683. }
  2684. admin, err := getAdminFromPostFields(r)
  2685. if err != nil {
  2686. s.renderAddUpdateAdminPage(w, r, &admin, err, true)
  2687. return
  2688. }
  2689. if admin.Password == "" && s.binding.isWebAdminLoginFormDisabled() {
  2690. admin.Password = util.GenerateUniqueID()
  2691. }
  2692. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2693. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2694. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  2695. return
  2696. }
  2697. err = dataprovider.AddAdmin(&admin, claims.Username, ipAddr, claims.Role)
  2698. if err != nil {
  2699. s.renderAddUpdateAdminPage(w, r, &admin, err, true)
  2700. return
  2701. }
  2702. http.Redirect(w, r, webAdminsPath, http.StatusSeeOther)
  2703. }
  2704. func (s *httpdServer) handleWebUpdateAdminPost(w http.ResponseWriter, r *http.Request) {
  2705. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2706. username := getURLParam(r, "username")
  2707. admin, err := dataprovider.AdminExists(username)
  2708. if errors.Is(err, util.ErrNotFound) {
  2709. s.renderNotFoundPage(w, r, err)
  2710. return
  2711. } else if err != nil {
  2712. s.renderInternalServerErrorPage(w, r, err)
  2713. return
  2714. }
  2715. updatedAdmin, err := getAdminFromPostFields(r)
  2716. if err != nil {
  2717. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, err, false)
  2718. return
  2719. }
  2720. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2721. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2722. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  2723. return
  2724. }
  2725. updatedAdmin.ID = admin.ID
  2726. updatedAdmin.Username = admin.Username
  2727. if updatedAdmin.Password == "" {
  2728. updatedAdmin.Password = admin.Password
  2729. }
  2730. updatedAdmin.Filters.TOTPConfig = admin.Filters.TOTPConfig
  2731. updatedAdmin.Filters.RecoveryCodes = admin.Filters.RecoveryCodes
  2732. claims, err := getTokenClaims(r)
  2733. if err != nil || claims.Username == "" {
  2734. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken), false)
  2735. return
  2736. }
  2737. if username == claims.Username {
  2738. if claims.isCriticalPermRemoved(updatedAdmin.Permissions) {
  2739. s.renderAddUpdateAdminPage(w, r, &updatedAdmin,
  2740. util.NewI18nError(errors.New("you cannot remove these permissions to yourself"),
  2741. util.I18nErrorAdminSelfPerms,
  2742. ), false)
  2743. return
  2744. }
  2745. if updatedAdmin.Status == 0 {
  2746. s.renderAddUpdateAdminPage(w, r, &updatedAdmin,
  2747. util.NewI18nError(errors.New("you cannot disable yourself"),
  2748. util.I18nErrorAdminSelfDisable,
  2749. ), false)
  2750. return
  2751. }
  2752. if updatedAdmin.Role != claims.Role {
  2753. s.renderAddUpdateAdminPage(w, r, &updatedAdmin,
  2754. util.NewI18nError(
  2755. errors.New("you cannot add/change your role"),
  2756. util.I18nErrorAdminSelfRole,
  2757. ), false)
  2758. return
  2759. }
  2760. }
  2761. err = dataprovider.UpdateAdmin(&updatedAdmin, claims.Username, ipAddr, claims.Role)
  2762. if err != nil {
  2763. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, err, false)
  2764. return
  2765. }
  2766. http.Redirect(w, r, webAdminsPath, http.StatusSeeOther)
  2767. }
  2768. func (s *httpdServer) handleWebDefenderPage(w http.ResponseWriter, r *http.Request) {
  2769. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2770. data := defenderHostsPage{
  2771. basePage: s.getBasePageData(util.I18nDefenderTitle, webDefenderPath, r),
  2772. DefenderHostsURL: webDefenderHostsPath,
  2773. }
  2774. renderAdminTemplate(w, templateDefender, data)
  2775. }
  2776. func getAllUsers(w http.ResponseWriter, r *http.Request) {
  2777. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2778. claims, err := getTokenClaims(r)
  2779. if err != nil || claims.Username == "" {
  2780. sendAPIResponse(w, r, nil, util.I18nErrorDirList403, http.StatusForbidden)
  2781. return
  2782. }
  2783. users := make([]dataprovider.User, 0, 100)
  2784. for {
  2785. u, err := dataprovider.GetUsers(defaultQueryLimit, len(users), dataprovider.OrderASC, claims.Role)
  2786. if err != nil {
  2787. sendAPIResponse(w, r, err, getI18NErrorString(err, util.I18nError500Message), http.StatusInternalServerError)
  2788. return
  2789. }
  2790. users = append(users, u...)
  2791. if len(u) < defaultQueryLimit {
  2792. break
  2793. }
  2794. }
  2795. render.JSON(w, r, users)
  2796. }
  2797. func (s *httpdServer) handleGetWebUsers(w http.ResponseWriter, r *http.Request) {
  2798. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2799. claims, err := getTokenClaims(r)
  2800. if err != nil || claims.Username == "" {
  2801. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  2802. return
  2803. }
  2804. data := s.getBasePageData(util.I18nUsersTitle, webUsersPath, r)
  2805. renderAdminTemplate(w, templateUsers, data)
  2806. }
  2807. func (s *httpdServer) handleWebTemplateFolderGet(w http.ResponseWriter, r *http.Request) {
  2808. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2809. if r.URL.Query().Get("from") != "" {
  2810. name := r.URL.Query().Get("from")
  2811. folder, err := dataprovider.GetFolderByName(name)
  2812. if err == nil {
  2813. folder.FsConfig.SetEmptySecrets()
  2814. s.renderFolderPage(w, r, folder, folderPageModeTemplate, nil)
  2815. } else if errors.Is(err, util.ErrNotFound) {
  2816. s.renderNotFoundPage(w, r, err)
  2817. } else {
  2818. s.renderInternalServerErrorPage(w, r, err)
  2819. }
  2820. } else {
  2821. folder := vfs.BaseVirtualFolder{}
  2822. s.renderFolderPage(w, r, folder, folderPageModeTemplate, nil)
  2823. }
  2824. }
  2825. func (s *httpdServer) handleWebTemplateFolderPost(w http.ResponseWriter, r *http.Request) {
  2826. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2827. claims, err := getTokenClaims(r)
  2828. if err != nil || claims.Username == "" {
  2829. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  2830. return
  2831. }
  2832. templateFolder := vfs.BaseVirtualFolder{}
  2833. err = r.ParseMultipartForm(maxRequestSize)
  2834. if err != nil {
  2835. s.renderMessagePage(w, r, util.I18nTemplateFolderTitle, http.StatusBadRequest, util.NewI18nError(err, util.I18nErrorInvalidForm), "")
  2836. return
  2837. }
  2838. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  2839. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2840. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2841. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  2842. return
  2843. }
  2844. templateFolder.MappedPath = r.Form.Get("mapped_path")
  2845. templateFolder.Description = r.Form.Get("description")
  2846. fsConfig, err := getFsConfigFromPostFields(r)
  2847. if err != nil {
  2848. s.renderMessagePage(w, r, util.I18nTemplateFolderTitle, http.StatusBadRequest, err, "")
  2849. return
  2850. }
  2851. templateFolder.FsConfig = fsConfig
  2852. var dump dataprovider.BackupData
  2853. dump.Version = dataprovider.DumpVersion
  2854. foldersFields := getFoldersForTemplate(r)
  2855. for _, tmpl := range foldersFields {
  2856. f := getFolderFromTemplate(templateFolder, tmpl)
  2857. if err := dataprovider.ValidateFolder(&f); err != nil {
  2858. s.renderMessagePage(w, r, util.I18nTemplateFolderTitle, http.StatusBadRequest, err, "")
  2859. return
  2860. }
  2861. dump.Folders = append(dump.Folders, f)
  2862. }
  2863. if len(dump.Folders) == 0 {
  2864. s.renderMessagePage(w, r, util.I18nTemplateFolderTitle, http.StatusBadRequest,
  2865. util.NewI18nError(
  2866. errors.New("no valid folder defined, unable to complete the requested action"),
  2867. util.I18nErrorFolderTemplate,
  2868. ), "")
  2869. return
  2870. }
  2871. if r.Form.Get("form_action") == "export_from_template" {
  2872. w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"sftpgo-%v-folders-from-template.json\"",
  2873. len(dump.Folders)))
  2874. render.JSON(w, r, dump)
  2875. return
  2876. }
  2877. if err = RestoreFolders(dump.Folders, "", 1, 0, claims.Username, ipAddr, claims.Role); err != nil {
  2878. s.renderMessagePage(w, r, util.I18nTemplateFolderTitle, getRespStatus(err), err, "")
  2879. return
  2880. }
  2881. http.Redirect(w, r, webFoldersPath, http.StatusSeeOther)
  2882. }
  2883. func (s *httpdServer) handleWebTemplateUserGet(w http.ResponseWriter, r *http.Request) {
  2884. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2885. tokenAdmin := getAdminFromToken(r)
  2886. admin, err := dataprovider.AdminExists(tokenAdmin.Username)
  2887. if err != nil {
  2888. s.renderInternalServerErrorPage(w, r, fmt.Errorf("unable to get the admin %q: %w", tokenAdmin.Username, err))
  2889. return
  2890. }
  2891. if r.URL.Query().Get("from") != "" {
  2892. username := r.URL.Query().Get("from")
  2893. user, err := dataprovider.UserExists(username, admin.Role)
  2894. if err == nil {
  2895. user.SetEmptySecrets()
  2896. user.PublicKeys = nil
  2897. user.Email = ""
  2898. user.Description = ""
  2899. if user.ExpirationDate == 0 && admin.Filters.Preferences.DefaultUsersExpiration > 0 {
  2900. user.ExpirationDate = util.GetTimeAsMsSinceEpoch(time.Now().Add(24 * time.Hour * time.Duration(admin.Filters.Preferences.DefaultUsersExpiration)))
  2901. }
  2902. s.renderUserPage(w, r, &user, userPageModeTemplate, nil, &admin)
  2903. } else if errors.Is(err, util.ErrNotFound) {
  2904. s.renderNotFoundPage(w, r, err)
  2905. } else {
  2906. s.renderInternalServerErrorPage(w, r, err)
  2907. }
  2908. } else {
  2909. user := dataprovider.User{BaseUser: sdk.BaseUser{
  2910. Status: 1,
  2911. Permissions: map[string][]string{
  2912. "/": {dataprovider.PermAny},
  2913. },
  2914. }}
  2915. if admin.Filters.Preferences.DefaultUsersExpiration > 0 {
  2916. user.ExpirationDate = util.GetTimeAsMsSinceEpoch(time.Now().Add(24 * time.Hour * time.Duration(admin.Filters.Preferences.DefaultUsersExpiration)))
  2917. }
  2918. s.renderUserPage(w, r, &user, userPageModeTemplate, nil, &admin)
  2919. }
  2920. }
  2921. func (s *httpdServer) handleWebTemplateUserPost(w http.ResponseWriter, r *http.Request) {
  2922. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2923. claims, err := getTokenClaims(r)
  2924. if err != nil || claims.Username == "" {
  2925. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  2926. return
  2927. }
  2928. templateUser, err := getUserFromPostFields(r)
  2929. if err != nil {
  2930. s.renderMessagePage(w, r, util.I18nTemplateUserTitle, http.StatusBadRequest, err, "")
  2931. return
  2932. }
  2933. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2934. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2935. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  2936. return
  2937. }
  2938. var dump dataprovider.BackupData
  2939. dump.Version = dataprovider.DumpVersion
  2940. userTmplFields := getUsersForTemplate(r)
  2941. for _, tmpl := range userTmplFields {
  2942. u := getUserFromTemplate(templateUser, tmpl)
  2943. if err := dataprovider.ValidateUser(&u); err != nil {
  2944. s.renderMessagePage(w, r, util.I18nTemplateUserTitle, http.StatusBadRequest, err, "")
  2945. return
  2946. }
  2947. // to create a template the "manage_system" permission is required, so role admins cannot use
  2948. // this method, we don't need to force the role
  2949. dump.Users = append(dump.Users, u)
  2950. for _, folder := range u.VirtualFolders {
  2951. if !dump.HasFolder(folder.Name) {
  2952. dump.Folders = append(dump.Folders, folder.BaseVirtualFolder)
  2953. }
  2954. }
  2955. }
  2956. if len(dump.Users) == 0 {
  2957. s.renderMessagePage(w, r, util.I18nTemplateUserTitle,
  2958. http.StatusBadRequest, util.NewI18nError(
  2959. errors.New("no valid user defined, unable to complete the requested action"),
  2960. util.I18nErrorUserTemplate,
  2961. ), "")
  2962. return
  2963. }
  2964. if r.Form.Get("form_action") == "export_from_template" {
  2965. w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"sftpgo-%v-users-from-template.json\"",
  2966. len(dump.Users)))
  2967. render.JSON(w, r, dump)
  2968. return
  2969. }
  2970. if err = RestoreUsers(dump.Users, "", 1, 0, claims.Username, ipAddr, claims.Role); err != nil {
  2971. s.renderMessagePage(w, r, util.I18nTemplateUserTitle, getRespStatus(err), err, "")
  2972. return
  2973. }
  2974. http.Redirect(w, r, webUsersPath, http.StatusSeeOther)
  2975. }
  2976. func (s *httpdServer) handleWebAddUserGet(w http.ResponseWriter, r *http.Request) {
  2977. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2978. tokenAdmin := getAdminFromToken(r)
  2979. admin, err := dataprovider.AdminExists(tokenAdmin.Username)
  2980. if err != nil {
  2981. s.renderInternalServerErrorPage(w, r, fmt.Errorf("unable to get the admin %q: %w", tokenAdmin.Username, err))
  2982. return
  2983. }
  2984. user := dataprovider.User{BaseUser: sdk.BaseUser{
  2985. Status: 1,
  2986. Permissions: map[string][]string{
  2987. "/": {dataprovider.PermAny},
  2988. }},
  2989. }
  2990. if admin.Filters.Preferences.DefaultUsersExpiration > 0 {
  2991. user.ExpirationDate = util.GetTimeAsMsSinceEpoch(time.Now().Add(24 * time.Hour * time.Duration(admin.Filters.Preferences.DefaultUsersExpiration)))
  2992. }
  2993. s.renderUserPage(w, r, &user, userPageModeAdd, nil, &admin)
  2994. }
  2995. func (s *httpdServer) handleWebUpdateUserGet(w http.ResponseWriter, r *http.Request) {
  2996. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2997. claims, err := getTokenClaims(r)
  2998. if err != nil || claims.Username == "" {
  2999. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  3000. return
  3001. }
  3002. username := getURLParam(r, "username")
  3003. user, err := dataprovider.UserExists(username, claims.Role)
  3004. if err == nil {
  3005. s.renderUserPage(w, r, &user, userPageModeUpdate, nil, nil)
  3006. } else if errors.Is(err, util.ErrNotFound) {
  3007. s.renderNotFoundPage(w, r, err)
  3008. } else {
  3009. s.renderInternalServerErrorPage(w, r, err)
  3010. }
  3011. }
  3012. func (s *httpdServer) handleWebAddUserPost(w http.ResponseWriter, r *http.Request) {
  3013. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3014. claims, err := getTokenClaims(r)
  3015. if err != nil || claims.Username == "" {
  3016. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  3017. return
  3018. }
  3019. user, err := getUserFromPostFields(r)
  3020. if err != nil {
  3021. s.renderUserPage(w, r, &user, userPageModeAdd, err, nil)
  3022. return
  3023. }
  3024. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3025. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3026. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  3027. return
  3028. }
  3029. user = getUserFromTemplate(user, userTemplateFields{
  3030. Username: user.Username,
  3031. Password: user.Password,
  3032. PublicKeys: user.PublicKeys,
  3033. })
  3034. if claims.Role != "" {
  3035. user.Role = claims.Role
  3036. }
  3037. user.Filters.RecoveryCodes = nil
  3038. user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
  3039. Enabled: false,
  3040. }
  3041. err = dataprovider.AddUser(&user, claims.Username, ipAddr, claims.Role)
  3042. if err != nil {
  3043. s.renderUserPage(w, r, &user, userPageModeAdd, err, nil)
  3044. return
  3045. }
  3046. http.Redirect(w, r, webUsersPath, http.StatusSeeOther)
  3047. }
  3048. func (s *httpdServer) handleWebUpdateUserPost(w http.ResponseWriter, r *http.Request) {
  3049. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3050. claims, err := getTokenClaims(r)
  3051. if err != nil || claims.Username == "" {
  3052. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  3053. return
  3054. }
  3055. username := getURLParam(r, "username")
  3056. user, err := dataprovider.UserExists(username, claims.Role)
  3057. if errors.Is(err, util.ErrNotFound) {
  3058. s.renderNotFoundPage(w, r, err)
  3059. return
  3060. } else if err != nil {
  3061. s.renderInternalServerErrorPage(w, r, err)
  3062. return
  3063. }
  3064. updatedUser, err := getUserFromPostFields(r)
  3065. if err != nil {
  3066. s.renderUserPage(w, r, &user, userPageModeUpdate, err, nil)
  3067. return
  3068. }
  3069. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3070. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3071. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  3072. return
  3073. }
  3074. updatedUser.ID = user.ID
  3075. updatedUser.Username = user.Username
  3076. updatedUser.Filters.RecoveryCodes = user.Filters.RecoveryCodes
  3077. updatedUser.Filters.TOTPConfig = user.Filters.TOTPConfig
  3078. updatedUser.LastPasswordChange = user.LastPasswordChange
  3079. updatedUser.SetEmptySecretsIfNil()
  3080. if updatedUser.Password == redactedSecret {
  3081. updatedUser.Password = user.Password
  3082. }
  3083. updateEncryptedSecrets(&updatedUser.FsConfig, user.FsConfig.S3Config.AccessSecret, user.FsConfig.AzBlobConfig.AccountKey,
  3084. user.FsConfig.AzBlobConfig.SASURL, user.FsConfig.GCSConfig.Credentials, user.FsConfig.CryptConfig.Passphrase,
  3085. user.FsConfig.SFTPConfig.Password, user.FsConfig.SFTPConfig.PrivateKey, user.FsConfig.SFTPConfig.KeyPassphrase,
  3086. user.FsConfig.HTTPConfig.Password, user.FsConfig.HTTPConfig.APIKey)
  3087. updatedUser = getUserFromTemplate(updatedUser, userTemplateFields{
  3088. Username: updatedUser.Username,
  3089. Password: updatedUser.Password,
  3090. PublicKeys: updatedUser.PublicKeys,
  3091. })
  3092. if claims.Role != "" {
  3093. updatedUser.Role = claims.Role
  3094. }
  3095. err = dataprovider.UpdateUser(&updatedUser, claims.Username, ipAddr, claims.Role)
  3096. if err != nil {
  3097. s.renderUserPage(w, r, &updatedUser, userPageModeUpdate, err, nil)
  3098. return
  3099. }
  3100. if r.Form.Get("disconnect") != "" {
  3101. disconnectUser(user.Username, claims.Username, claims.Role)
  3102. }
  3103. http.Redirect(w, r, webUsersPath, http.StatusSeeOther)
  3104. }
  3105. func (s *httpdServer) handleWebGetStatus(w http.ResponseWriter, r *http.Request) {
  3106. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3107. data := statusPage{
  3108. basePage: s.getBasePageData(util.I18nStatusTitle, webStatusPath, r),
  3109. Status: getServicesStatus(),
  3110. }
  3111. renderAdminTemplate(w, templateStatus, data)
  3112. }
  3113. func (s *httpdServer) handleWebGetConnections(w http.ResponseWriter, r *http.Request) {
  3114. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3115. claims, err := getTokenClaims(r)
  3116. if err != nil || claims.Username == "" {
  3117. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  3118. return
  3119. }
  3120. data := s.getBasePageData(util.I18nSessionsTitle, webConnectionsPath, r)
  3121. renderAdminTemplate(w, templateConnections, data)
  3122. }
  3123. func (s *httpdServer) handleWebAddFolderGet(w http.ResponseWriter, r *http.Request) {
  3124. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3125. s.renderFolderPage(w, r, vfs.BaseVirtualFolder{}, folderPageModeAdd, nil)
  3126. }
  3127. func (s *httpdServer) handleWebAddFolderPost(w http.ResponseWriter, r *http.Request) {
  3128. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3129. claims, err := getTokenClaims(r)
  3130. if err != nil || claims.Username == "" {
  3131. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  3132. return
  3133. }
  3134. folder := vfs.BaseVirtualFolder{}
  3135. err = r.ParseMultipartForm(maxRequestSize)
  3136. if err != nil {
  3137. s.renderFolderPage(w, r, folder, folderPageModeAdd, util.NewI18nError(err, util.I18nErrorInvalidForm))
  3138. return
  3139. }
  3140. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  3141. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3142. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3143. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  3144. return
  3145. }
  3146. folder.MappedPath = strings.TrimSpace(r.Form.Get("mapped_path"))
  3147. folder.Name = strings.TrimSpace(r.Form.Get("name"))
  3148. folder.Description = r.Form.Get("description")
  3149. fsConfig, err := getFsConfigFromPostFields(r)
  3150. if err != nil {
  3151. s.renderFolderPage(w, r, folder, folderPageModeAdd, err)
  3152. return
  3153. }
  3154. folder.FsConfig = fsConfig
  3155. folder = getFolderFromTemplate(folder, folder.Name)
  3156. err = dataprovider.AddFolder(&folder, claims.Username, ipAddr, claims.Role)
  3157. if err == nil {
  3158. http.Redirect(w, r, webFoldersPath, http.StatusSeeOther)
  3159. } else {
  3160. s.renderFolderPage(w, r, folder, folderPageModeAdd, err)
  3161. }
  3162. }
  3163. func (s *httpdServer) handleWebUpdateFolderGet(w http.ResponseWriter, r *http.Request) {
  3164. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3165. name := getURLParam(r, "name")
  3166. folder, err := dataprovider.GetFolderByName(name)
  3167. if err == nil {
  3168. s.renderFolderPage(w, r, folder, folderPageModeUpdate, nil)
  3169. } else if errors.Is(err, util.ErrNotFound) {
  3170. s.renderNotFoundPage(w, r, err)
  3171. } else {
  3172. s.renderInternalServerErrorPage(w, r, err)
  3173. }
  3174. }
  3175. func (s *httpdServer) handleWebUpdateFolderPost(w http.ResponseWriter, r *http.Request) {
  3176. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3177. claims, err := getTokenClaims(r)
  3178. if err != nil || claims.Username == "" {
  3179. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  3180. return
  3181. }
  3182. name := getURLParam(r, "name")
  3183. folder, err := dataprovider.GetFolderByName(name)
  3184. if errors.Is(err, util.ErrNotFound) {
  3185. s.renderNotFoundPage(w, r, err)
  3186. return
  3187. } else if err != nil {
  3188. s.renderInternalServerErrorPage(w, r, err)
  3189. return
  3190. }
  3191. err = r.ParseMultipartForm(maxRequestSize)
  3192. if err != nil {
  3193. s.renderFolderPage(w, r, folder, folderPageModeUpdate, util.NewI18nError(err, util.I18nErrorInvalidForm))
  3194. return
  3195. }
  3196. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  3197. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3198. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3199. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  3200. return
  3201. }
  3202. fsConfig, err := getFsConfigFromPostFields(r)
  3203. if err != nil {
  3204. s.renderFolderPage(w, r, folder, folderPageModeUpdate, err)
  3205. return
  3206. }
  3207. updatedFolder := vfs.BaseVirtualFolder{
  3208. MappedPath: strings.TrimSpace(r.Form.Get("mapped_path")),
  3209. Description: r.Form.Get("description"),
  3210. }
  3211. updatedFolder.ID = folder.ID
  3212. updatedFolder.Name = folder.Name
  3213. updatedFolder.FsConfig = fsConfig
  3214. updatedFolder.FsConfig.SetEmptySecretsIfNil()
  3215. updateEncryptedSecrets(&updatedFolder.FsConfig, folder.FsConfig.S3Config.AccessSecret, folder.FsConfig.AzBlobConfig.AccountKey,
  3216. folder.FsConfig.AzBlobConfig.SASURL, folder.FsConfig.GCSConfig.Credentials, folder.FsConfig.CryptConfig.Passphrase,
  3217. folder.FsConfig.SFTPConfig.Password, folder.FsConfig.SFTPConfig.PrivateKey, folder.FsConfig.SFTPConfig.KeyPassphrase,
  3218. folder.FsConfig.HTTPConfig.Password, folder.FsConfig.HTTPConfig.APIKey)
  3219. updatedFolder = getFolderFromTemplate(updatedFolder, updatedFolder.Name)
  3220. err = dataprovider.UpdateFolder(&updatedFolder, folder.Users, folder.Groups, claims.Username, ipAddr, claims.Role)
  3221. if err != nil {
  3222. s.renderFolderPage(w, r, updatedFolder, folderPageModeUpdate, err)
  3223. return
  3224. }
  3225. http.Redirect(w, r, webFoldersPath, http.StatusSeeOther)
  3226. }
  3227. func (s *httpdServer) getWebVirtualFolders(w http.ResponseWriter, r *http.Request, limit int, minimal bool) ([]vfs.BaseVirtualFolder, error) {
  3228. folders := make([]vfs.BaseVirtualFolder, 0, 50)
  3229. for {
  3230. f, err := dataprovider.GetFolders(limit, len(folders), dataprovider.OrderASC, minimal)
  3231. if err != nil {
  3232. s.renderInternalServerErrorPage(w, r, err)
  3233. return folders, err
  3234. }
  3235. folders = append(folders, f...)
  3236. if len(f) < limit {
  3237. break
  3238. }
  3239. }
  3240. return folders, nil
  3241. }
  3242. func getAllFolders(w http.ResponseWriter, r *http.Request) {
  3243. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3244. folders := make([]vfs.BaseVirtualFolder, 0, 50)
  3245. for {
  3246. f, err := dataprovider.GetFolders(defaultQueryLimit, len(folders), dataprovider.OrderASC, false)
  3247. if err != nil {
  3248. sendAPIResponse(w, r, err, getI18NErrorString(err, util.I18nError500Message), http.StatusInternalServerError)
  3249. return
  3250. }
  3251. folders = append(folders, f...)
  3252. if len(f) < defaultQueryLimit {
  3253. break
  3254. }
  3255. }
  3256. render.JSON(w, r, folders)
  3257. }
  3258. func (s *httpdServer) handleWebGetFolders(w http.ResponseWriter, r *http.Request) {
  3259. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3260. data := s.getBasePageData(util.I18nFoldersTitle, webFoldersPath, r)
  3261. renderAdminTemplate(w, templateFolders, data)
  3262. }
  3263. func (s *httpdServer) getWebGroups(w http.ResponseWriter, r *http.Request, limit int, minimal bool) ([]dataprovider.Group, error) {
  3264. groups := make([]dataprovider.Group, 0, 50)
  3265. for {
  3266. f, err := dataprovider.GetGroups(limit, len(groups), dataprovider.OrderASC, minimal)
  3267. if err != nil {
  3268. s.renderInternalServerErrorPage(w, r, err)
  3269. return groups, err
  3270. }
  3271. groups = append(groups, f...)
  3272. if len(f) < limit {
  3273. break
  3274. }
  3275. }
  3276. return groups, nil
  3277. }
  3278. func getAllGroups(w http.ResponseWriter, r *http.Request) {
  3279. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3280. groups := make([]dataprovider.Group, 0, 50)
  3281. for {
  3282. f, err := dataprovider.GetGroups(defaultQueryLimit, len(groups), dataprovider.OrderASC, false)
  3283. if err != nil {
  3284. sendAPIResponse(w, r, err, getI18NErrorString(err, util.I18nError500Message), http.StatusInternalServerError)
  3285. return
  3286. }
  3287. groups = append(groups, f...)
  3288. if len(f) < defaultQueryLimit {
  3289. break
  3290. }
  3291. }
  3292. render.JSON(w, r, groups)
  3293. }
  3294. func (s *httpdServer) handleWebGetGroups(w http.ResponseWriter, r *http.Request) {
  3295. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3296. data := s.getBasePageData(util.I18nGroupsTitle, webGroupsPath, r)
  3297. renderAdminTemplate(w, templateGroups, data)
  3298. }
  3299. func (s *httpdServer) handleWebAddGroupGet(w http.ResponseWriter, r *http.Request) {
  3300. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3301. s.renderGroupPage(w, r, dataprovider.Group{}, genericPageModeAdd, nil)
  3302. }
  3303. func (s *httpdServer) handleWebAddGroupPost(w http.ResponseWriter, r *http.Request) {
  3304. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3305. claims, err := getTokenClaims(r)
  3306. if err != nil || claims.Username == "" {
  3307. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  3308. return
  3309. }
  3310. group, err := getGroupFromPostFields(r)
  3311. if err != nil {
  3312. s.renderGroupPage(w, r, group, genericPageModeAdd, err)
  3313. return
  3314. }
  3315. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3316. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3317. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  3318. return
  3319. }
  3320. err = dataprovider.AddGroup(&group, claims.Username, ipAddr, claims.Role)
  3321. if err != nil {
  3322. s.renderGroupPage(w, r, group, genericPageModeAdd, err)
  3323. return
  3324. }
  3325. http.Redirect(w, r, webGroupsPath, http.StatusSeeOther)
  3326. }
  3327. func (s *httpdServer) handleWebUpdateGroupGet(w http.ResponseWriter, r *http.Request) {
  3328. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3329. name := getURLParam(r, "name")
  3330. group, err := dataprovider.GroupExists(name)
  3331. if err == nil {
  3332. s.renderGroupPage(w, r, group, genericPageModeUpdate, nil)
  3333. } else if errors.Is(err, util.ErrNotFound) {
  3334. s.renderNotFoundPage(w, r, err)
  3335. } else {
  3336. s.renderInternalServerErrorPage(w, r, err)
  3337. }
  3338. }
  3339. func (s *httpdServer) handleWebUpdateGroupPost(w http.ResponseWriter, r *http.Request) {
  3340. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3341. claims, err := getTokenClaims(r)
  3342. if err != nil || claims.Username == "" {
  3343. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  3344. return
  3345. }
  3346. name := getURLParam(r, "name")
  3347. group, err := dataprovider.GroupExists(name)
  3348. if errors.Is(err, util.ErrNotFound) {
  3349. s.renderNotFoundPage(w, r, err)
  3350. return
  3351. } else if err != nil {
  3352. s.renderInternalServerErrorPage(w, r, err)
  3353. return
  3354. }
  3355. updatedGroup, err := getGroupFromPostFields(r)
  3356. if err != nil {
  3357. s.renderGroupPage(w, r, group, genericPageModeUpdate, err)
  3358. return
  3359. }
  3360. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3361. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3362. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  3363. return
  3364. }
  3365. updatedGroup.ID = group.ID
  3366. updatedGroup.Name = group.Name
  3367. updatedGroup.SetEmptySecretsIfNil()
  3368. updateEncryptedSecrets(&updatedGroup.UserSettings.FsConfig, group.UserSettings.FsConfig.S3Config.AccessSecret,
  3369. group.UserSettings.FsConfig.AzBlobConfig.AccountKey, group.UserSettings.FsConfig.AzBlobConfig.SASURL,
  3370. group.UserSettings.FsConfig.GCSConfig.Credentials, group.UserSettings.FsConfig.CryptConfig.Passphrase,
  3371. group.UserSettings.FsConfig.SFTPConfig.Password, group.UserSettings.FsConfig.SFTPConfig.PrivateKey,
  3372. group.UserSettings.FsConfig.SFTPConfig.KeyPassphrase, group.UserSettings.FsConfig.HTTPConfig.Password,
  3373. group.UserSettings.FsConfig.HTTPConfig.APIKey)
  3374. err = dataprovider.UpdateGroup(&updatedGroup, group.Users, claims.Username, ipAddr, claims.Role)
  3375. if err != nil {
  3376. s.renderGroupPage(w, r, updatedGroup, genericPageModeUpdate, err)
  3377. return
  3378. }
  3379. http.Redirect(w, r, webGroupsPath, http.StatusSeeOther)
  3380. }
  3381. func (s *httpdServer) getWebEventActions(w http.ResponseWriter, r *http.Request, limit int, minimal bool,
  3382. ) ([]dataprovider.BaseEventAction, error) {
  3383. actions := make([]dataprovider.BaseEventAction, 0, limit)
  3384. for {
  3385. res, err := dataprovider.GetEventActions(limit, len(actions), dataprovider.OrderASC, minimal)
  3386. if err != nil {
  3387. s.renderInternalServerErrorPage(w, r, err)
  3388. return actions, err
  3389. }
  3390. actions = append(actions, res...)
  3391. if len(res) < limit {
  3392. break
  3393. }
  3394. }
  3395. return actions, nil
  3396. }
  3397. func (s *httpdServer) handleWebGetEventActions(w http.ResponseWriter, r *http.Request) {
  3398. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3399. limit := defaultQueryLimit
  3400. if _, ok := r.URL.Query()["qlimit"]; ok {
  3401. var err error
  3402. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  3403. if err != nil {
  3404. limit = defaultQueryLimit
  3405. }
  3406. }
  3407. actions, err := s.getWebEventActions(w, r, limit, false)
  3408. if err != nil {
  3409. return
  3410. }
  3411. data := eventActionsPage{
  3412. basePage: s.getBasePageData(pageEventActionsTitle, webAdminEventActionsPath, r),
  3413. Actions: actions,
  3414. }
  3415. renderAdminTemplate(w, templateEventActions, data)
  3416. }
  3417. func (s *httpdServer) handleWebAddEventActionGet(w http.ResponseWriter, r *http.Request) {
  3418. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3419. action := dataprovider.BaseEventAction{
  3420. Type: dataprovider.ActionTypeHTTP,
  3421. }
  3422. s.renderEventActionPage(w, r, action, genericPageModeAdd, "")
  3423. }
  3424. func (s *httpdServer) handleWebAddEventActionPost(w http.ResponseWriter, r *http.Request) {
  3425. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3426. claims, err := getTokenClaims(r)
  3427. if err != nil || claims.Username == "" {
  3428. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  3429. return
  3430. }
  3431. action, err := getEventActionFromPostFields(r)
  3432. if err != nil {
  3433. s.renderEventActionPage(w, r, action, genericPageModeAdd, err.Error())
  3434. return
  3435. }
  3436. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3437. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3438. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  3439. return
  3440. }
  3441. if err = dataprovider.AddEventAction(&action, claims.Username, ipAddr, claims.Role); err != nil {
  3442. s.renderEventActionPage(w, r, action, genericPageModeAdd, err.Error())
  3443. return
  3444. }
  3445. http.Redirect(w, r, webAdminEventActionsPath, http.StatusSeeOther)
  3446. }
  3447. func (s *httpdServer) handleWebUpdateEventActionGet(w http.ResponseWriter, r *http.Request) {
  3448. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3449. name := getURLParam(r, "name")
  3450. action, err := dataprovider.EventActionExists(name)
  3451. if err == nil {
  3452. s.renderEventActionPage(w, r, action, genericPageModeUpdate, "")
  3453. } else if errors.Is(err, util.ErrNotFound) {
  3454. s.renderNotFoundPage(w, r, err)
  3455. } else {
  3456. s.renderInternalServerErrorPage(w, r, err)
  3457. }
  3458. }
  3459. func (s *httpdServer) handleWebUpdateEventActionPost(w http.ResponseWriter, r *http.Request) {
  3460. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3461. claims, err := getTokenClaims(r)
  3462. if err != nil || claims.Username == "" {
  3463. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  3464. return
  3465. }
  3466. name := getURLParam(r, "name")
  3467. action, err := dataprovider.EventActionExists(name)
  3468. if errors.Is(err, util.ErrNotFound) {
  3469. s.renderNotFoundPage(w, r, err)
  3470. return
  3471. } else if err != nil {
  3472. s.renderInternalServerErrorPage(w, r, err)
  3473. return
  3474. }
  3475. updatedAction, err := getEventActionFromPostFields(r)
  3476. if err != nil {
  3477. s.renderEventActionPage(w, r, updatedAction, genericPageModeUpdate, err.Error())
  3478. return
  3479. }
  3480. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3481. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3482. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  3483. return
  3484. }
  3485. updatedAction.ID = action.ID
  3486. updatedAction.Name = action.Name
  3487. updatedAction.Options.SetEmptySecretsIfNil()
  3488. switch updatedAction.Type {
  3489. case dataprovider.ActionTypeHTTP:
  3490. if updatedAction.Options.HTTPConfig.Password.IsNotPlainAndNotEmpty() {
  3491. updatedAction.Options.HTTPConfig.Password = action.Options.HTTPConfig.Password
  3492. }
  3493. }
  3494. err = dataprovider.UpdateEventAction(&updatedAction, claims.Username, ipAddr, claims.Role)
  3495. if err != nil {
  3496. s.renderEventActionPage(w, r, updatedAction, genericPageModeUpdate, err.Error())
  3497. return
  3498. }
  3499. http.Redirect(w, r, webAdminEventActionsPath, http.StatusSeeOther)
  3500. }
  3501. func (s *httpdServer) handleWebGetEventRules(w http.ResponseWriter, r *http.Request) {
  3502. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3503. limit := defaultQueryLimit
  3504. if _, ok := r.URL.Query()["qlimit"]; ok {
  3505. if lim, err := strconv.Atoi(r.URL.Query().Get("qlimit")); err == nil {
  3506. limit = lim
  3507. }
  3508. }
  3509. rules := make([]dataprovider.EventRule, 0, limit)
  3510. for {
  3511. res, err := dataprovider.GetEventRules(limit, len(rules), dataprovider.OrderASC)
  3512. if err != nil {
  3513. s.renderInternalServerErrorPage(w, r, err)
  3514. return
  3515. }
  3516. rules = append(rules, res...)
  3517. if len(res) < limit {
  3518. break
  3519. }
  3520. }
  3521. data := eventRulesPage{
  3522. basePage: s.getBasePageData(pageEventRulesTitle, webAdminEventRulesPath, r),
  3523. Rules: rules,
  3524. }
  3525. renderAdminTemplate(w, templateEventRules, data)
  3526. }
  3527. func (s *httpdServer) handleWebAddEventRuleGet(w http.ResponseWriter, r *http.Request) {
  3528. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3529. rule := dataprovider.EventRule{
  3530. Status: 1,
  3531. Trigger: dataprovider.EventTriggerFsEvent,
  3532. }
  3533. s.renderEventRulePage(w, r, rule, genericPageModeAdd, "")
  3534. }
  3535. func (s *httpdServer) handleWebAddEventRulePost(w http.ResponseWriter, r *http.Request) {
  3536. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3537. claims, err := getTokenClaims(r)
  3538. if err != nil || claims.Username == "" {
  3539. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  3540. return
  3541. }
  3542. rule, err := getEventRuleFromPostFields(r)
  3543. if err != nil {
  3544. s.renderEventRulePage(w, r, rule, genericPageModeAdd, err.Error())
  3545. return
  3546. }
  3547. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3548. err = verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr)
  3549. if err != nil {
  3550. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  3551. return
  3552. }
  3553. if err = dataprovider.AddEventRule(&rule, claims.Username, ipAddr, claims.Role); err != nil {
  3554. s.renderEventRulePage(w, r, rule, genericPageModeAdd, err.Error())
  3555. return
  3556. }
  3557. http.Redirect(w, r, webAdminEventRulesPath, http.StatusSeeOther)
  3558. }
  3559. func (s *httpdServer) handleWebUpdateEventRuleGet(w http.ResponseWriter, r *http.Request) {
  3560. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3561. name := getURLParam(r, "name")
  3562. rule, err := dataprovider.EventRuleExists(name)
  3563. if err == nil {
  3564. s.renderEventRulePage(w, r, rule, genericPageModeUpdate, "")
  3565. } else if errors.Is(err, util.ErrNotFound) {
  3566. s.renderNotFoundPage(w, r, err)
  3567. } else {
  3568. s.renderInternalServerErrorPage(w, r, err)
  3569. }
  3570. }
  3571. func (s *httpdServer) handleWebUpdateEventRulePost(w http.ResponseWriter, r *http.Request) {
  3572. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3573. claims, err := getTokenClaims(r)
  3574. if err != nil || claims.Username == "" {
  3575. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  3576. return
  3577. }
  3578. name := getURLParam(r, "name")
  3579. rule, err := dataprovider.EventRuleExists(name)
  3580. if errors.Is(err, util.ErrNotFound) {
  3581. s.renderNotFoundPage(w, r, err)
  3582. return
  3583. } else if err != nil {
  3584. s.renderInternalServerErrorPage(w, r, err)
  3585. return
  3586. }
  3587. updatedRule, err := getEventRuleFromPostFields(r)
  3588. if err != nil {
  3589. s.renderEventRulePage(w, r, updatedRule, genericPageModeUpdate, err.Error())
  3590. return
  3591. }
  3592. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3593. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3594. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  3595. return
  3596. }
  3597. updatedRule.ID = rule.ID
  3598. updatedRule.Name = rule.Name
  3599. err = dataprovider.UpdateEventRule(&updatedRule, claims.Username, ipAddr, claims.Role)
  3600. if err != nil {
  3601. s.renderEventRulePage(w, r, updatedRule, genericPageModeUpdate, err.Error())
  3602. return
  3603. }
  3604. http.Redirect(w, r, webAdminEventRulesPath, http.StatusSeeOther)
  3605. }
  3606. func (s *httpdServer) getWebRoles(w http.ResponseWriter, r *http.Request, limit int, minimal bool) ([]dataprovider.Role, error) {
  3607. roles := make([]dataprovider.Role, 0, 10)
  3608. for {
  3609. res, err := dataprovider.GetRoles(limit, len(roles), dataprovider.OrderASC, minimal)
  3610. if err != nil {
  3611. s.renderInternalServerErrorPage(w, r, err)
  3612. return roles, err
  3613. }
  3614. roles = append(roles, res...)
  3615. if len(res) < limit {
  3616. break
  3617. }
  3618. }
  3619. return roles, nil
  3620. }
  3621. func getAllRoles(w http.ResponseWriter, r *http.Request) {
  3622. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3623. roles := make([]dataprovider.Role, 0, 10)
  3624. for {
  3625. res, err := dataprovider.GetRoles(defaultQueryLimit, len(roles), dataprovider.OrderASC, false)
  3626. if err != nil {
  3627. sendAPIResponse(w, r, err, getI18NErrorString(err, util.I18nError500Message), http.StatusInternalServerError)
  3628. return
  3629. }
  3630. roles = append(roles, res...)
  3631. if len(res) < defaultQueryLimit {
  3632. break
  3633. }
  3634. }
  3635. render.JSON(w, r, roles)
  3636. }
  3637. func (s *httpdServer) handleWebGetRoles(w http.ResponseWriter, r *http.Request) {
  3638. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3639. data := s.getBasePageData(util.I18nRolesTitle, webAdminRolesPath, r)
  3640. renderAdminTemplate(w, templateRoles, data)
  3641. }
  3642. func (s *httpdServer) handleWebAddRoleGet(w http.ResponseWriter, r *http.Request) {
  3643. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3644. s.renderRolePage(w, r, dataprovider.Role{}, genericPageModeAdd, nil)
  3645. }
  3646. func (s *httpdServer) handleWebAddRolePost(w http.ResponseWriter, r *http.Request) {
  3647. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3648. role, err := getRoleFromPostFields(r)
  3649. if err != nil {
  3650. s.renderRolePage(w, r, role, genericPageModeAdd, err)
  3651. return
  3652. }
  3653. claims, err := getTokenClaims(r)
  3654. if err != nil || claims.Username == "" {
  3655. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  3656. return
  3657. }
  3658. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3659. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3660. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  3661. return
  3662. }
  3663. err = dataprovider.AddRole(&role, claims.Username, ipAddr, claims.Role)
  3664. if err != nil {
  3665. s.renderRolePage(w, r, role, genericPageModeAdd, err)
  3666. return
  3667. }
  3668. http.Redirect(w, r, webAdminRolesPath, http.StatusSeeOther)
  3669. }
  3670. func (s *httpdServer) handleWebUpdateRoleGet(w http.ResponseWriter, r *http.Request) {
  3671. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3672. role, err := dataprovider.RoleExists(getURLParam(r, "name"))
  3673. if err == nil {
  3674. s.renderRolePage(w, r, role, genericPageModeUpdate, nil)
  3675. } else if errors.Is(err, util.ErrNotFound) {
  3676. s.renderNotFoundPage(w, r, err)
  3677. } else {
  3678. s.renderInternalServerErrorPage(w, r, err)
  3679. }
  3680. }
  3681. func (s *httpdServer) handleWebUpdateRolePost(w http.ResponseWriter, r *http.Request) {
  3682. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3683. claims, err := getTokenClaims(r)
  3684. if err != nil || claims.Username == "" {
  3685. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  3686. return
  3687. }
  3688. role, err := dataprovider.RoleExists(getURLParam(r, "name"))
  3689. if errors.Is(err, util.ErrNotFound) {
  3690. s.renderNotFoundPage(w, r, err)
  3691. return
  3692. } else if err != nil {
  3693. s.renderInternalServerErrorPage(w, r, err)
  3694. return
  3695. }
  3696. updatedRole, err := getRoleFromPostFields(r)
  3697. if err != nil {
  3698. s.renderRolePage(w, r, role, genericPageModeUpdate, err)
  3699. return
  3700. }
  3701. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3702. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3703. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  3704. return
  3705. }
  3706. updatedRole.ID = role.ID
  3707. updatedRole.Name = role.Name
  3708. err = dataprovider.UpdateRole(&updatedRole, claims.Username, ipAddr, claims.Role)
  3709. if err != nil {
  3710. s.renderRolePage(w, r, updatedRole, genericPageModeUpdate, err)
  3711. return
  3712. }
  3713. http.Redirect(w, r, webAdminRolesPath, http.StatusSeeOther)
  3714. }
  3715. func (s *httpdServer) handleWebGetEvents(w http.ResponseWriter, r *http.Request) {
  3716. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3717. data := eventsPage{
  3718. basePage: s.getBasePageData(pageEventsTitle, webEventsPath, r),
  3719. FsEventsSearchURL: webEventsFsSearchPath,
  3720. ProviderEventsSearchURL: webEventsProviderSearchPath,
  3721. LogEventsSearchURL: webEventsLogSearchPath,
  3722. }
  3723. renderAdminTemplate(w, templateEvents, data)
  3724. }
  3725. func (s *httpdServer) handleWebIPListsPage(w http.ResponseWriter, r *http.Request) {
  3726. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3727. rtlStatus, rtlProtocols := common.Config.GetRateLimitersStatus()
  3728. data := ipListsPage{
  3729. basePage: s.getBasePageData(util.I18nIPListsTitle, webIPListsPath, r),
  3730. RateLimitersStatus: rtlStatus,
  3731. RateLimitersProtocols: strings.Join(rtlProtocols, ", "),
  3732. IsAllowListEnabled: common.Config.IsAllowListEnabled(),
  3733. }
  3734. renderAdminTemplate(w, templateIPLists, data)
  3735. }
  3736. func (s *httpdServer) handleWebAddIPListEntryGet(w http.ResponseWriter, r *http.Request) {
  3737. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3738. listType, _, err := getIPListPathParams(r)
  3739. if err != nil {
  3740. s.renderBadRequestPage(w, r, err)
  3741. return
  3742. }
  3743. s.renderIPListPage(w, r, dataprovider.IPListEntry{Type: listType}, genericPageModeAdd, nil)
  3744. }
  3745. func (s *httpdServer) handleWebAddIPListEntryPost(w http.ResponseWriter, r *http.Request) {
  3746. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3747. listType, _, err := getIPListPathParams(r)
  3748. if err != nil {
  3749. s.renderBadRequestPage(w, r, err)
  3750. return
  3751. }
  3752. entry, err := getIPListEntryFromPostFields(r, listType)
  3753. if err != nil {
  3754. s.renderIPListPage(w, r, entry, genericPageModeAdd, err)
  3755. return
  3756. }
  3757. entry.Type = listType
  3758. claims, err := getTokenClaims(r)
  3759. if err != nil || claims.Username == "" {
  3760. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  3761. return
  3762. }
  3763. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3764. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3765. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  3766. return
  3767. }
  3768. err = dataprovider.AddIPListEntry(&entry, claims.Username, ipAddr, claims.Role)
  3769. if err != nil {
  3770. s.renderIPListPage(w, r, entry, genericPageModeAdd, err)
  3771. return
  3772. }
  3773. http.Redirect(w, r, webIPListsPath, http.StatusSeeOther)
  3774. }
  3775. func (s *httpdServer) handleWebUpdateIPListEntryGet(w http.ResponseWriter, r *http.Request) {
  3776. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3777. listType, ipOrNet, err := getIPListPathParams(r)
  3778. if err != nil {
  3779. s.renderBadRequestPage(w, r, err)
  3780. return
  3781. }
  3782. entry, err := dataprovider.IPListEntryExists(ipOrNet, listType)
  3783. if err == nil {
  3784. s.renderIPListPage(w, r, entry, genericPageModeUpdate, nil)
  3785. } else if errors.Is(err, util.ErrNotFound) {
  3786. s.renderNotFoundPage(w, r, err)
  3787. } else {
  3788. s.renderInternalServerErrorPage(w, r, err)
  3789. }
  3790. }
  3791. func (s *httpdServer) handleWebUpdateIPListEntryPost(w http.ResponseWriter, r *http.Request) {
  3792. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3793. claims, err := getTokenClaims(r)
  3794. if err != nil || claims.Username == "" {
  3795. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  3796. return
  3797. }
  3798. listType, ipOrNet, err := getIPListPathParams(r)
  3799. if err != nil {
  3800. s.renderBadRequestPage(w, r, err)
  3801. return
  3802. }
  3803. entry, err := dataprovider.IPListEntryExists(ipOrNet, listType)
  3804. if errors.Is(err, util.ErrNotFound) {
  3805. s.renderNotFoundPage(w, r, err)
  3806. return
  3807. } else if err != nil {
  3808. s.renderInternalServerErrorPage(w, r, err)
  3809. return
  3810. }
  3811. updatedEntry, err := getIPListEntryFromPostFields(r, listType)
  3812. if err != nil {
  3813. s.renderIPListPage(w, r, entry, genericPageModeUpdate, err)
  3814. return
  3815. }
  3816. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3817. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3818. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  3819. return
  3820. }
  3821. updatedEntry.Type = listType
  3822. updatedEntry.IPOrNet = ipOrNet
  3823. err = dataprovider.UpdateIPListEntry(&updatedEntry, claims.Username, ipAddr, claims.Role)
  3824. if err != nil {
  3825. s.renderIPListPage(w, r, entry, genericPageModeUpdate, err)
  3826. return
  3827. }
  3828. http.Redirect(w, r, webIPListsPath, http.StatusSeeOther)
  3829. }
  3830. func (s *httpdServer) handleWebConfigs(w http.ResponseWriter, r *http.Request) {
  3831. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3832. configs, err := dataprovider.GetConfigs()
  3833. if err != nil {
  3834. s.renderInternalServerErrorPage(w, r, err)
  3835. return
  3836. }
  3837. s.renderConfigsPage(w, r, configs, "", 0)
  3838. }
  3839. func (s *httpdServer) handleWebConfigsPost(w http.ResponseWriter, r *http.Request) {
  3840. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3841. claims, err := getTokenClaims(r)
  3842. if err != nil || claims.Username == "" {
  3843. s.renderForbiddenPage(w, r, util.NewI18nError(errInvalidTokenClaims, util.I18nErrorInvalidToken))
  3844. return
  3845. }
  3846. configs, err := dataprovider.GetConfigs()
  3847. if err != nil {
  3848. s.renderInternalServerErrorPage(w, r, err)
  3849. return
  3850. }
  3851. err = r.ParseForm()
  3852. if err != nil {
  3853. s.renderBadRequestPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidForm))
  3854. return
  3855. }
  3856. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3857. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3858. s.renderForbiddenPage(w, r, util.NewI18nError(err, util.I18nErrorInvalidCSRF))
  3859. return
  3860. }
  3861. var configSection int
  3862. switch r.Form.Get("form_action") {
  3863. case "sftp_submit":
  3864. configSection = 1
  3865. sftpConfigs := getSFTPConfigsFromPostFields(r)
  3866. configs.SFTPD = sftpConfigs
  3867. case "acme_submit":
  3868. configSection = 2
  3869. acmeConfigs := getACMEConfigsFromPostFields(r)
  3870. configs.ACME = acmeConfigs
  3871. if err := acme.GetCertificatesForConfig(acmeConfigs, configurationDir); err != nil {
  3872. s.renderConfigsPage(w, r, configs, err.Error(), configSection)
  3873. return
  3874. }
  3875. case "smtp_submit":
  3876. configSection = 3
  3877. smtpConfigs := getSMTPConfigsFromPostFields(r)
  3878. updateSMTPSecrets(smtpConfigs, configs.SMTP)
  3879. configs.SMTP = smtpConfigs
  3880. default:
  3881. s.renderBadRequestPage(w, r, errors.New("unsupported form action"))
  3882. return
  3883. }
  3884. err = dataprovider.UpdateConfigs(&configs, claims.Username, ipAddr, claims.Role)
  3885. if err != nil {
  3886. s.renderConfigsPage(w, r, configs, err.Error(), configSection)
  3887. return
  3888. }
  3889. if configSection == 3 {
  3890. err := configs.SMTP.TryDecrypt()
  3891. if err == nil {
  3892. smtp.Activate(configs.SMTP)
  3893. } else {
  3894. logger.Error(logSender, "", "unable to decrypt SMTP configuration, cannot activate configuration: %v", err)
  3895. }
  3896. }
  3897. s.renderMessagePage(w, r, util.I18nConfigsTitle, http.StatusOK, nil, util.I18nConfigsOK)
  3898. }
  3899. func (s *httpdServer) handleOAuth2TokenRedirect(w http.ResponseWriter, r *http.Request) {
  3900. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3901. stateToken := r.URL.Query().Get("state")
  3902. state, err := verifyOAuth2Token(stateToken, util.GetIPFromRemoteAddress(r.RemoteAddr))
  3903. if err != nil {
  3904. s.renderMessagePage(w, r, util.I18nOAuth2ErrorTitle, http.StatusBadRequest, err, "")
  3905. return
  3906. }
  3907. defer oauth2Mgr.removePendingAuth(state)
  3908. pendingAuth, err := oauth2Mgr.getPendingAuth(state)
  3909. if err != nil {
  3910. s.renderMessagePage(w, r, util.I18nOAuth2ErrorTitle, http.StatusInternalServerError,
  3911. util.NewI18nError(err, util.I18nOAuth2ErrorValidateState), "")
  3912. return
  3913. }
  3914. oauth2Config := smtp.OAuth2Config{
  3915. Provider: pendingAuth.Provider,
  3916. ClientID: pendingAuth.ClientID,
  3917. ClientSecret: pendingAuth.ClientSecret.GetPayload(),
  3918. }
  3919. ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
  3920. defer cancel()
  3921. cfg := oauth2Config.GetOAuth2()
  3922. cfg.RedirectURL = pendingAuth.RedirectURL
  3923. token, err := cfg.Exchange(ctx, r.URL.Query().Get("code"))
  3924. if err != nil {
  3925. s.renderMessagePage(w, r, util.I18nOAuth2ErrorTitle, http.StatusInternalServerError,
  3926. util.NewI18nError(err, util.I18nOAuth2ErrTokenExchange), "")
  3927. return
  3928. }
  3929. if token.RefreshToken == "" {
  3930. errTxt := "the OAuth2 provider returned an empty token. " +
  3931. "Some providers only return the token when the user first authorizes. " +
  3932. "If you have already registered SFTPGo with this user in the past, revoke access and try again. " +
  3933. "This way you will invalidate the previous token"
  3934. s.renderMessagePage(w, r, util.I18nOAuth2ErrorTitle, http.StatusBadRequest,
  3935. util.NewI18nError(errors.New(errTxt), util.I18nOAuth2ErrNoRefreshToken), "")
  3936. return
  3937. }
  3938. s.renderMessagePageWithString(w, r, util.I18nOAuth2Title, http.StatusOK, nil, util.I18nOAuth2OK,
  3939. fmt.Sprintf("%q", token.RefreshToken))
  3940. }
  3941. func updateSMTPSecrets(newConfigs, currentConfigs *dataprovider.SMTPConfigs) {
  3942. if newConfigs.Password.IsNotPlainAndNotEmpty() {
  3943. newConfigs.Password = currentConfigs.Password
  3944. }
  3945. if newConfigs.OAuth2.ClientSecret.IsNotPlainAndNotEmpty() {
  3946. newConfigs.OAuth2.ClientSecret = currentConfigs.OAuth2.ClientSecret
  3947. }
  3948. if newConfigs.OAuth2.RefreshToken.IsNotPlainAndNotEmpty() {
  3949. newConfigs.OAuth2.RefreshToken = currentConfigs.OAuth2.RefreshToken
  3950. }
  3951. }