webadmin.go 134 KB

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