webadmin.go 140 KB

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