webadmin.go 145 KB

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