webadmin.go 128 KB

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