webadmin.go 135 KB

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