webadmin.go 138 KB

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