webadmin.go 147 KB

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