webadmin.go 138 KB

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