webadmin.go 139 KB

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