webadmin.go 135 KB

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