webadmin.go 135 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159
  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. emailContentType := 0
  2158. if r.Form.Get("email_content_type") == "1" {
  2159. emailContentType = 1
  2160. }
  2161. options := dataprovider.BaseEventActionOptions{
  2162. HTTPConfig: dataprovider.EventActionHTTPConfig{
  2163. Endpoint: r.Form.Get("http_endpoint"),
  2164. Username: r.Form.Get("http_username"),
  2165. Password: getSecretFromFormField(r, "http_password"),
  2166. Headers: getKeyValsFromPostFields(r, "http_header_key", "http_header_val"),
  2167. Timeout: httpTimeout,
  2168. SkipTLSVerify: r.Form.Get("http_skip_tls_verify") != "",
  2169. Method: r.Form.Get("http_method"),
  2170. QueryParameters: getKeyValsFromPostFields(r, "http_query_key", "http_query_val"),
  2171. Body: r.Form.Get("http_body"),
  2172. Parts: getHTTPPartsFromPostFields(r),
  2173. },
  2174. CmdConfig: dataprovider.EventActionCommandConfig{
  2175. Cmd: r.Form.Get("cmd_path"),
  2176. Args: cmdArgs,
  2177. Timeout: cmdTimeout,
  2178. EnvVars: getKeyValsFromPostFields(r, "cmd_env_key", "cmd_env_val"),
  2179. },
  2180. EmailConfig: dataprovider.EventActionEmailConfig{
  2181. Recipients: getSliceFromDelimitedValues(r.Form.Get("email_recipients"), ","),
  2182. Bcc: getSliceFromDelimitedValues(r.Form.Get("email_bcc"), ","),
  2183. Subject: r.Form.Get("email_subject"),
  2184. ContentType: emailContentType,
  2185. Body: r.Form.Get("email_body"),
  2186. Attachments: emailAttachments,
  2187. },
  2188. RetentionConfig: dataprovider.EventActionDataRetentionConfig{
  2189. Folders: foldersRetention,
  2190. },
  2191. FsConfig: dataprovider.EventActionFilesystemConfig{
  2192. Type: fsActionType,
  2193. Renames: getKeyValsFromPostFields(r, "fs_rename_source", "fs_rename_target"),
  2194. Deletes: getSliceFromDelimitedValues(r.Form.Get("fs_delete_paths"), ","),
  2195. MkDirs: getSliceFromDelimitedValues(r.Form.Get("fs_mkdir_paths"), ","),
  2196. Exist: getSliceFromDelimitedValues(r.Form.Get("fs_exist_paths"), ","),
  2197. Copy: getKeyValsFromPostFields(r, "fs_copy_source", "fs_copy_target"),
  2198. Compress: dataprovider.EventActionFsCompress{
  2199. Name: r.Form.Get("fs_compress_name"),
  2200. Paths: getSliceFromDelimitedValues(r.Form.Get("fs_compress_paths"), ","),
  2201. },
  2202. },
  2203. PwdExpirationConfig: dataprovider.EventActionPasswordExpiration{
  2204. Threshold: pwdExpirationThreshold,
  2205. },
  2206. IDPConfig: dataprovider.EventActionIDPAccountCheck{
  2207. Mode: idpMode,
  2208. TemplateUser: strings.TrimSpace(r.Form.Get("idp_user")),
  2209. TemplateAdmin: strings.TrimSpace(r.Form.Get("idp_admin")),
  2210. },
  2211. }
  2212. return options, nil
  2213. }
  2214. func getEventActionFromPostFields(r *http.Request) (dataprovider.BaseEventAction, error) {
  2215. err := r.ParseForm()
  2216. if err != nil {
  2217. return dataprovider.BaseEventAction{}, err
  2218. }
  2219. actionType, err := strconv.Atoi(r.Form.Get("type"))
  2220. if err != nil {
  2221. return dataprovider.BaseEventAction{}, fmt.Errorf("invalid action type: %w", err)
  2222. }
  2223. options, err := getEventActionOptionsFromPostFields(r)
  2224. if err != nil {
  2225. return dataprovider.BaseEventAction{}, err
  2226. }
  2227. action := dataprovider.BaseEventAction{
  2228. Name: r.Form.Get("name"),
  2229. Description: r.Form.Get("description"),
  2230. Type: actionType,
  2231. Options: options,
  2232. }
  2233. return action, nil
  2234. }
  2235. func getIDPLoginEventFromPostField(r *http.Request) int {
  2236. switch r.Form.Get("idp_login_event") {
  2237. case "1":
  2238. return 1
  2239. case "2":
  2240. return 2
  2241. default:
  2242. return 0
  2243. }
  2244. }
  2245. func getEventRuleConditionsFromPostFields(r *http.Request) (dataprovider.EventConditions, error) {
  2246. var schedules []dataprovider.Schedule
  2247. var names, groupNames, roleNames, fsPaths []dataprovider.ConditionPattern
  2248. for k := range r.Form {
  2249. if strings.HasPrefix(k, "schedule_hour") {
  2250. hour := r.Form.Get(k)
  2251. if hour != "" {
  2252. idx := strings.TrimPrefix(k, "schedule_hour")
  2253. dayOfWeek := r.Form.Get(fmt.Sprintf("schedule_day_of_week%s", idx))
  2254. dayOfMonth := r.Form.Get(fmt.Sprintf("schedule_day_of_month%s", idx))
  2255. month := r.Form.Get(fmt.Sprintf("schedule_month%s", idx))
  2256. schedules = append(schedules, dataprovider.Schedule{
  2257. Hours: hour,
  2258. DayOfWeek: dayOfWeek,
  2259. DayOfMonth: dayOfMonth,
  2260. Month: month,
  2261. })
  2262. }
  2263. }
  2264. if strings.HasPrefix(k, "name_pattern") {
  2265. pattern := r.Form.Get(k)
  2266. if pattern != "" {
  2267. idx := strings.TrimPrefix(k, "name_pattern")
  2268. patternType := r.Form.Get(fmt.Sprintf("type_name_pattern%s", idx))
  2269. names = append(names, dataprovider.ConditionPattern{
  2270. Pattern: pattern,
  2271. InverseMatch: patternType == inversePatternType,
  2272. })
  2273. }
  2274. }
  2275. if strings.HasPrefix(k, "group_name_pattern") {
  2276. pattern := r.Form.Get(k)
  2277. if pattern != "" {
  2278. idx := strings.TrimPrefix(k, "group_name_pattern")
  2279. patternType := r.Form.Get(fmt.Sprintf("type_group_name_pattern%s", idx))
  2280. groupNames = append(groupNames, dataprovider.ConditionPattern{
  2281. Pattern: pattern,
  2282. InverseMatch: patternType == inversePatternType,
  2283. })
  2284. }
  2285. }
  2286. if strings.HasPrefix(k, "role_name_pattern") {
  2287. pattern := r.Form.Get(k)
  2288. if pattern != "" {
  2289. idx := strings.TrimPrefix(k, "role_name_pattern")
  2290. patternType := r.Form.Get(fmt.Sprintf("type_role_name_pattern%s", idx))
  2291. roleNames = append(roleNames, dataprovider.ConditionPattern{
  2292. Pattern: pattern,
  2293. InverseMatch: patternType == inversePatternType,
  2294. })
  2295. }
  2296. }
  2297. if strings.HasPrefix(k, "fs_path_pattern") {
  2298. pattern := r.Form.Get(k)
  2299. if pattern != "" {
  2300. idx := strings.TrimPrefix(k, "fs_path_pattern")
  2301. patternType := r.Form.Get(fmt.Sprintf("type_fs_path_pattern%s", idx))
  2302. fsPaths = append(fsPaths, dataprovider.ConditionPattern{
  2303. Pattern: pattern,
  2304. InverseMatch: patternType == inversePatternType,
  2305. })
  2306. }
  2307. }
  2308. }
  2309. minFileSize, err := util.ParseBytes(r.Form.Get("fs_min_size"))
  2310. if err != nil {
  2311. return dataprovider.EventConditions{}, fmt.Errorf("invalid min file size: %w", err)
  2312. }
  2313. maxFileSize, err := util.ParseBytes(r.Form.Get("fs_max_size"))
  2314. if err != nil {
  2315. return dataprovider.EventConditions{}, fmt.Errorf("invalid max file size: %w", err)
  2316. }
  2317. conditions := dataprovider.EventConditions{
  2318. FsEvents: r.Form["fs_events"],
  2319. ProviderEvents: r.Form["provider_events"],
  2320. IDPLoginEvent: getIDPLoginEventFromPostField(r),
  2321. Schedules: schedules,
  2322. Options: dataprovider.ConditionOptions{
  2323. Names: names,
  2324. GroupNames: groupNames,
  2325. RoleNames: roleNames,
  2326. FsPaths: fsPaths,
  2327. Protocols: r.Form["fs_protocols"],
  2328. ProviderObjects: r.Form["provider_objects"],
  2329. MinFileSize: minFileSize,
  2330. MaxFileSize: maxFileSize,
  2331. ConcurrentExecution: r.Form.Get("concurrent_execution") != "",
  2332. },
  2333. }
  2334. return conditions, nil
  2335. }
  2336. func getEventRuleActionsFromPostFields(r *http.Request) ([]dataprovider.EventAction, error) {
  2337. var actions []dataprovider.EventAction
  2338. for k := range r.Form {
  2339. if strings.HasPrefix(k, "action_name") {
  2340. name := r.Form.Get(k)
  2341. if name != "" {
  2342. idx := strings.TrimPrefix(k, "action_name")
  2343. order, err := strconv.Atoi(r.Form.Get(fmt.Sprintf("action_order%s", idx)))
  2344. if err != nil {
  2345. return actions, fmt.Errorf("invalid order: %w", err)
  2346. }
  2347. options := r.Form[fmt.Sprintf("action_options%s", idx)]
  2348. actions = append(actions, dataprovider.EventAction{
  2349. BaseEventAction: dataprovider.BaseEventAction{
  2350. Name: name,
  2351. },
  2352. Order: order + 1,
  2353. Options: dataprovider.EventActionOptions{
  2354. IsFailureAction: util.Contains(options, "1"),
  2355. StopOnFailure: util.Contains(options, "2"),
  2356. ExecuteSync: util.Contains(options, "3"),
  2357. },
  2358. })
  2359. }
  2360. }
  2361. }
  2362. return actions, nil
  2363. }
  2364. func getEventRuleFromPostFields(r *http.Request) (dataprovider.EventRule, error) {
  2365. err := r.ParseForm()
  2366. if err != nil {
  2367. return dataprovider.EventRule{}, err
  2368. }
  2369. status, err := strconv.Atoi(r.Form.Get("status"))
  2370. if err != nil {
  2371. return dataprovider.EventRule{}, fmt.Errorf("invalid status: %w", err)
  2372. }
  2373. trigger, err := strconv.Atoi(r.Form.Get("trigger"))
  2374. if err != nil {
  2375. return dataprovider.EventRule{}, fmt.Errorf("invalid trigger: %w", err)
  2376. }
  2377. conditions, err := getEventRuleConditionsFromPostFields(r)
  2378. if err != nil {
  2379. return dataprovider.EventRule{}, err
  2380. }
  2381. actions, err := getEventRuleActionsFromPostFields(r)
  2382. if err != nil {
  2383. return dataprovider.EventRule{}, err
  2384. }
  2385. rule := dataprovider.EventRule{
  2386. Name: r.Form.Get("name"),
  2387. Status: status,
  2388. Description: r.Form.Get("description"),
  2389. Trigger: trigger,
  2390. Conditions: conditions,
  2391. Actions: actions,
  2392. }
  2393. return rule, nil
  2394. }
  2395. func getRoleFromPostFields(r *http.Request) (dataprovider.Role, error) {
  2396. err := r.ParseForm()
  2397. if err != nil {
  2398. return dataprovider.Role{}, err
  2399. }
  2400. return dataprovider.Role{
  2401. Name: r.Form.Get("name"),
  2402. Description: r.Form.Get("description"),
  2403. }, nil
  2404. }
  2405. func getIPListEntryFromPostFields(r *http.Request, listType dataprovider.IPListType) (dataprovider.IPListEntry, error) {
  2406. err := r.ParseForm()
  2407. if err != nil {
  2408. return dataprovider.IPListEntry{}, err
  2409. }
  2410. var mode int
  2411. if listType == dataprovider.IPListTypeDefender {
  2412. mode, err = strconv.Atoi(r.Form.Get("mode"))
  2413. if err != nil {
  2414. return dataprovider.IPListEntry{}, fmt.Errorf("invalid mode: %w", err)
  2415. }
  2416. } else {
  2417. mode = 1
  2418. }
  2419. protocols := 0
  2420. for _, proto := range r.Form["protocols"] {
  2421. p, err := strconv.Atoi(proto)
  2422. if err == nil {
  2423. protocols += p
  2424. }
  2425. }
  2426. return dataprovider.IPListEntry{
  2427. IPOrNet: r.Form.Get("ipornet"),
  2428. Mode: mode,
  2429. Protocols: protocols,
  2430. Description: r.Form.Get("description"),
  2431. }, nil
  2432. }
  2433. func getSFTPConfigsFromPostFields(r *http.Request) *dataprovider.SFTPDConfigs {
  2434. return &dataprovider.SFTPDConfigs{
  2435. HostKeyAlgos: r.Form["sftp_host_key_algos"],
  2436. Moduli: getSliceFromDelimitedValues(r.Form.Get("sftp_moduli"), ","),
  2437. KexAlgorithms: r.Form["sftp_kex_algos"],
  2438. Ciphers: r.Form["sftp_ciphers"],
  2439. MACs: r.Form["sftp_macs"],
  2440. }
  2441. }
  2442. func getACMEConfigsFromPostFields(r *http.Request) *dataprovider.ACMEConfigs {
  2443. port, err := strconv.Atoi(r.Form.Get("acme_port"))
  2444. if err != nil {
  2445. port = 80
  2446. }
  2447. var protocols int
  2448. for _, val := range r.Form["acme_protocols"] {
  2449. switch val {
  2450. case "1":
  2451. protocols++
  2452. case "2":
  2453. protocols += 2
  2454. case "3":
  2455. protocols += 4
  2456. }
  2457. }
  2458. return &dataprovider.ACMEConfigs{
  2459. Domain: strings.TrimSpace(r.Form.Get("acme_domain")),
  2460. Email: strings.TrimSpace(r.Form.Get("acme_email")),
  2461. HTTP01Challenge: dataprovider.ACMEHTTP01Challenge{Port: port},
  2462. Protocols: protocols,
  2463. }
  2464. }
  2465. func getSMTPConfigsFromPostFields(r *http.Request) *dataprovider.SMTPConfigs {
  2466. port, err := strconv.Atoi(r.Form.Get("smtp_port"))
  2467. if err != nil {
  2468. port = 587
  2469. }
  2470. authType, err := strconv.Atoi(r.Form.Get("smtp_auth"))
  2471. if err != nil {
  2472. authType = 0
  2473. }
  2474. encryption, err := strconv.Atoi(r.Form.Get("smtp_encryption"))
  2475. if err != nil {
  2476. encryption = 0
  2477. }
  2478. return &dataprovider.SMTPConfigs{
  2479. Host: r.Form.Get("smtp_host"),
  2480. Port: port,
  2481. From: r.Form.Get("smtp_from"),
  2482. User: r.Form.Get("smtp_username"),
  2483. Password: getSecretFromFormField(r, "smtp_password"),
  2484. AuthType: authType,
  2485. Encryption: encryption,
  2486. Domain: r.Form.Get("smtp_domain"),
  2487. }
  2488. }
  2489. func (s *httpdServer) handleWebAdminForgotPwd(w http.ResponseWriter, r *http.Request) {
  2490. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2491. if !smtp.IsEnabled() {
  2492. s.renderNotFoundPage(w, r, errors.New("this page does not exist"))
  2493. return
  2494. }
  2495. s.renderForgotPwdPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr))
  2496. }
  2497. func (s *httpdServer) handleWebAdminForgotPwdPost(w http.ResponseWriter, r *http.Request) {
  2498. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2499. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2500. err := r.ParseForm()
  2501. if err != nil {
  2502. s.renderForgotPwdPage(w, err.Error(), ipAddr)
  2503. return
  2504. }
  2505. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2506. s.renderForbiddenPage(w, r, err.Error())
  2507. return
  2508. }
  2509. err = handleForgotPassword(r, r.Form.Get("username"), true)
  2510. if err != nil {
  2511. if e, ok := err.(*util.ValidationError); ok {
  2512. s.renderForgotPwdPage(w, e.GetErrorString(), ipAddr)
  2513. return
  2514. }
  2515. s.renderForgotPwdPage(w, err.Error(), ipAddr)
  2516. return
  2517. }
  2518. http.Redirect(w, r, webAdminResetPwdPath, http.StatusFound)
  2519. }
  2520. func (s *httpdServer) handleWebAdminPasswordReset(w http.ResponseWriter, r *http.Request) {
  2521. r.Body = http.MaxBytesReader(w, r.Body, maxLoginBodySize)
  2522. if !smtp.IsEnabled() {
  2523. s.renderNotFoundPage(w, r, errors.New("this page does not exist"))
  2524. return
  2525. }
  2526. s.renderResetPwdPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr))
  2527. }
  2528. func (s *httpdServer) handleWebAdminTwoFactor(w http.ResponseWriter, r *http.Request) {
  2529. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2530. s.renderTwoFactorPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr))
  2531. }
  2532. func (s *httpdServer) handleWebAdminTwoFactorRecovery(w http.ResponseWriter, r *http.Request) {
  2533. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2534. s.renderTwoFactorRecoveryPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr))
  2535. }
  2536. func (s *httpdServer) handleWebAdminMFA(w http.ResponseWriter, r *http.Request) {
  2537. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2538. s.renderMFAPage(w, r)
  2539. }
  2540. func (s *httpdServer) handleWebAdminProfile(w http.ResponseWriter, r *http.Request) {
  2541. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2542. s.renderProfilePage(w, r, "")
  2543. }
  2544. func (s *httpdServer) handleWebAdminChangePwd(w http.ResponseWriter, r *http.Request) {
  2545. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2546. s.renderChangePasswordPage(w, r, "")
  2547. }
  2548. func (s *httpdServer) handleWebAdminProfilePost(w http.ResponseWriter, r *http.Request) {
  2549. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2550. err := r.ParseForm()
  2551. if err != nil {
  2552. s.renderProfilePage(w, r, err.Error())
  2553. return
  2554. }
  2555. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2556. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2557. s.renderForbiddenPage(w, r, err.Error())
  2558. return
  2559. }
  2560. claims, err := getTokenClaims(r)
  2561. if err != nil || claims.Username == "" {
  2562. s.renderProfilePage(w, r, "Invalid token claims")
  2563. return
  2564. }
  2565. admin, err := dataprovider.AdminExists(claims.Username)
  2566. if err != nil {
  2567. s.renderProfilePage(w, r, err.Error())
  2568. return
  2569. }
  2570. admin.Filters.AllowAPIKeyAuth = r.Form.Get("allow_api_key_auth") != ""
  2571. admin.Email = r.Form.Get("email")
  2572. admin.Description = r.Form.Get("description")
  2573. err = dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, ipAddr, admin.Role)
  2574. if err != nil {
  2575. s.renderProfilePage(w, r, err.Error())
  2576. return
  2577. }
  2578. s.renderMessagePage(w, r, "Profile updated", "", http.StatusOK, nil,
  2579. "Your profile has been successfully updated")
  2580. }
  2581. func (s *httpdServer) handleWebMaintenance(w http.ResponseWriter, r *http.Request) {
  2582. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2583. s.renderMaintenancePage(w, r, "")
  2584. }
  2585. func (s *httpdServer) handleWebRestore(w http.ResponseWriter, r *http.Request) {
  2586. r.Body = http.MaxBytesReader(w, r.Body, MaxRestoreSize)
  2587. claims, err := getTokenClaims(r)
  2588. if err != nil || claims.Username == "" {
  2589. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2590. return
  2591. }
  2592. err = r.ParseMultipartForm(MaxRestoreSize)
  2593. if err != nil {
  2594. s.renderMaintenancePage(w, r, err.Error())
  2595. return
  2596. }
  2597. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  2598. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2599. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2600. s.renderForbiddenPage(w, r, err.Error())
  2601. return
  2602. }
  2603. restoreMode, err := strconv.Atoi(r.Form.Get("mode"))
  2604. if err != nil {
  2605. s.renderMaintenancePage(w, r, err.Error())
  2606. return
  2607. }
  2608. scanQuota, err := strconv.Atoi(r.Form.Get("quota"))
  2609. if err != nil {
  2610. s.renderMaintenancePage(w, r, err.Error())
  2611. return
  2612. }
  2613. backupFile, _, err := r.FormFile("backup_file")
  2614. if err != nil {
  2615. s.renderMaintenancePage(w, r, err.Error())
  2616. return
  2617. }
  2618. defer backupFile.Close()
  2619. backupContent, err := io.ReadAll(backupFile)
  2620. if err != nil || len(backupContent) == 0 {
  2621. if len(backupContent) == 0 {
  2622. err = errors.New("backup file size must be greater than 0")
  2623. }
  2624. s.renderMaintenancePage(w, r, err.Error())
  2625. return
  2626. }
  2627. if err := restoreBackup(backupContent, "", scanQuota, restoreMode, claims.Username, ipAddr, claims.Role); err != nil {
  2628. s.renderMaintenancePage(w, r, err.Error())
  2629. return
  2630. }
  2631. s.renderMessagePage(w, r, "Data restored", "", http.StatusOK, nil, "Your backup was successfully restored")
  2632. }
  2633. func (s *httpdServer) handleGetWebAdmins(w http.ResponseWriter, r *http.Request) {
  2634. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2635. limit := defaultQueryLimit
  2636. if _, ok := r.URL.Query()["qlimit"]; ok {
  2637. var err error
  2638. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  2639. if err != nil {
  2640. limit = defaultQueryLimit
  2641. }
  2642. }
  2643. admins := make([]dataprovider.Admin, 0, limit)
  2644. for {
  2645. a, err := dataprovider.GetAdmins(limit, len(admins), dataprovider.OrderASC)
  2646. if err != nil {
  2647. s.renderInternalServerErrorPage(w, r, err)
  2648. return
  2649. }
  2650. admins = append(admins, a...)
  2651. if len(a) < limit {
  2652. break
  2653. }
  2654. }
  2655. data := adminsPage{
  2656. basePage: s.getBasePageData(pageAdminsTitle, webAdminsPath, r),
  2657. Admins: admins,
  2658. }
  2659. renderAdminTemplate(w, templateAdmins, data)
  2660. }
  2661. func (s *httpdServer) handleWebAdminSetupGet(w http.ResponseWriter, r *http.Request) {
  2662. r.Body = http.MaxBytesReader(w, r.Body, maxLoginBodySize)
  2663. if dataprovider.HasAdmin() {
  2664. http.Redirect(w, r, webAdminLoginPath, http.StatusFound)
  2665. return
  2666. }
  2667. s.renderAdminSetupPage(w, r, "", "")
  2668. }
  2669. func (s *httpdServer) handleWebAddAdminGet(w http.ResponseWriter, r *http.Request) {
  2670. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2671. admin := &dataprovider.Admin{
  2672. Status: 1,
  2673. Permissions: []string{dataprovider.PermAdminAny},
  2674. }
  2675. s.renderAddUpdateAdminPage(w, r, admin, "", true)
  2676. }
  2677. func (s *httpdServer) handleWebUpdateAdminGet(w http.ResponseWriter, r *http.Request) {
  2678. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2679. username := getURLParam(r, "username")
  2680. admin, err := dataprovider.AdminExists(username)
  2681. if err == nil {
  2682. s.renderAddUpdateAdminPage(w, r, &admin, "", false)
  2683. } else if errors.Is(err, util.ErrNotFound) {
  2684. s.renderNotFoundPage(w, r, err)
  2685. } else {
  2686. s.renderInternalServerErrorPage(w, r, err)
  2687. }
  2688. }
  2689. func (s *httpdServer) handleWebAddAdminPost(w http.ResponseWriter, r *http.Request) {
  2690. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2691. claims, err := getTokenClaims(r)
  2692. if err != nil || claims.Username == "" {
  2693. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2694. return
  2695. }
  2696. admin, err := getAdminFromPostFields(r)
  2697. if err != nil {
  2698. s.renderAddUpdateAdminPage(w, r, &admin, err.Error(), true)
  2699. return
  2700. }
  2701. if admin.Password == "" && s.binding.isWebAdminLoginFormDisabled() {
  2702. admin.Password = util.GenerateUniqueID()
  2703. }
  2704. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2705. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2706. s.renderForbiddenPage(w, r, err.Error())
  2707. return
  2708. }
  2709. err = dataprovider.AddAdmin(&admin, claims.Username, ipAddr, claims.Role)
  2710. if err != nil {
  2711. s.renderAddUpdateAdminPage(w, r, &admin, err.Error(), true)
  2712. return
  2713. }
  2714. http.Redirect(w, r, webAdminsPath, http.StatusSeeOther)
  2715. }
  2716. func (s *httpdServer) handleWebUpdateAdminPost(w http.ResponseWriter, r *http.Request) {
  2717. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2718. username := getURLParam(r, "username")
  2719. admin, err := dataprovider.AdminExists(username)
  2720. if errors.Is(err, util.ErrNotFound) {
  2721. s.renderNotFoundPage(w, r, err)
  2722. return
  2723. } else if err != nil {
  2724. s.renderInternalServerErrorPage(w, r, err)
  2725. return
  2726. }
  2727. updatedAdmin, err := getAdminFromPostFields(r)
  2728. if err != nil {
  2729. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, err.Error(), false)
  2730. return
  2731. }
  2732. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2733. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2734. s.renderForbiddenPage(w, r, err.Error())
  2735. return
  2736. }
  2737. updatedAdmin.ID = admin.ID
  2738. updatedAdmin.Username = admin.Username
  2739. if updatedAdmin.Password == "" {
  2740. updatedAdmin.Password = admin.Password
  2741. }
  2742. updatedAdmin.Filters.TOTPConfig = admin.Filters.TOTPConfig
  2743. updatedAdmin.Filters.RecoveryCodes = admin.Filters.RecoveryCodes
  2744. claims, err := getTokenClaims(r)
  2745. if err != nil || claims.Username == "" {
  2746. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, "Invalid token claims", false)
  2747. return
  2748. }
  2749. if username == claims.Username {
  2750. if claims.isCriticalPermRemoved(updatedAdmin.Permissions) {
  2751. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, "You cannot remove these permissions to yourself", false)
  2752. return
  2753. }
  2754. if updatedAdmin.Status == 0 {
  2755. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, "You cannot disable yourself", false)
  2756. return
  2757. }
  2758. if updatedAdmin.Role != claims.Role {
  2759. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, "You cannot add/change your role", false)
  2760. return
  2761. }
  2762. }
  2763. err = dataprovider.UpdateAdmin(&updatedAdmin, claims.Username, ipAddr, claims.Role)
  2764. if err != nil {
  2765. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, err.Error(), false)
  2766. return
  2767. }
  2768. http.Redirect(w, r, webAdminsPath, http.StatusSeeOther)
  2769. }
  2770. func (s *httpdServer) handleWebDefenderPage(w http.ResponseWriter, r *http.Request) {
  2771. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2772. data := defenderHostsPage{
  2773. basePage: s.getBasePageData(pageDefenderTitle, webDefenderPath, r),
  2774. DefenderHostsURL: webDefenderHostsPath,
  2775. }
  2776. renderAdminTemplate(w, templateDefender, data)
  2777. }
  2778. func (s *httpdServer) handleGetWebUsers(w http.ResponseWriter, r *http.Request) {
  2779. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2780. claims, err := getTokenClaims(r)
  2781. if err != nil || claims.Username == "" {
  2782. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2783. return
  2784. }
  2785. var limit int
  2786. if _, ok := r.URL.Query()["qlimit"]; ok {
  2787. var err error
  2788. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  2789. if err != nil {
  2790. limit = defaultQueryLimit
  2791. }
  2792. } else {
  2793. limit = defaultQueryLimit
  2794. }
  2795. users := make([]dataprovider.User, 0, limit)
  2796. for {
  2797. u, err := dataprovider.GetUsers(limit, len(users), dataprovider.OrderASC, claims.Role)
  2798. if err != nil {
  2799. s.renderInternalServerErrorPage(w, r, err)
  2800. return
  2801. }
  2802. users = append(users, u...)
  2803. if len(u) < limit {
  2804. break
  2805. }
  2806. }
  2807. data := usersPage{
  2808. basePage: s.getBasePageData(pageUsersTitle, webUsersPath, r),
  2809. Users: users,
  2810. }
  2811. renderAdminTemplate(w, templateUsers, data)
  2812. }
  2813. func (s *httpdServer) handleWebTemplateFolderGet(w http.ResponseWriter, r *http.Request) {
  2814. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2815. if r.URL.Query().Get("from") != "" {
  2816. name := r.URL.Query().Get("from")
  2817. folder, err := dataprovider.GetFolderByName(name)
  2818. if err == nil {
  2819. folder.FsConfig.SetEmptySecrets()
  2820. s.renderFolderPage(w, r, folder, folderPageModeTemplate, "")
  2821. } else if errors.Is(err, util.ErrNotFound) {
  2822. s.renderNotFoundPage(w, r, err)
  2823. } else {
  2824. s.renderInternalServerErrorPage(w, r, err)
  2825. }
  2826. } else {
  2827. folder := vfs.BaseVirtualFolder{}
  2828. s.renderFolderPage(w, r, folder, folderPageModeTemplate, "")
  2829. }
  2830. }
  2831. func (s *httpdServer) handleWebTemplateFolderPost(w http.ResponseWriter, r *http.Request) {
  2832. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2833. claims, err := getTokenClaims(r)
  2834. if err != nil || claims.Username == "" {
  2835. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2836. return
  2837. }
  2838. templateFolder := vfs.BaseVirtualFolder{}
  2839. err = r.ParseMultipartForm(maxRequestSize)
  2840. if err != nil {
  2841. s.renderMessagePage(w, r, "Error parsing folders fields", "", http.StatusBadRequest, err, "")
  2842. return
  2843. }
  2844. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  2845. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2846. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2847. s.renderForbiddenPage(w, r, err.Error())
  2848. return
  2849. }
  2850. templateFolder.MappedPath = r.Form.Get("mapped_path")
  2851. templateFolder.Description = r.Form.Get("description")
  2852. fsConfig, err := getFsConfigFromPostFields(r)
  2853. if err != nil {
  2854. s.renderMessagePage(w, r, "Error parsing folders fields", "", http.StatusBadRequest, err, "")
  2855. return
  2856. }
  2857. templateFolder.FsConfig = fsConfig
  2858. var dump dataprovider.BackupData
  2859. dump.Version = dataprovider.DumpVersion
  2860. foldersFields := getFoldersForTemplate(r)
  2861. for _, tmpl := range foldersFields {
  2862. f := getFolderFromTemplate(templateFolder, tmpl)
  2863. if err := dataprovider.ValidateFolder(&f); err != nil {
  2864. s.renderMessagePage(w, r, "Folder validation error", fmt.Sprintf("Error validating folder %q", f.Name),
  2865. http.StatusBadRequest, err, "")
  2866. return
  2867. }
  2868. dump.Folders = append(dump.Folders, f)
  2869. }
  2870. if len(dump.Folders) == 0 {
  2871. s.renderMessagePage(w, r, "No folders defined", "No valid folders defined, unable to complete the requested action",
  2872. http.StatusBadRequest, nil, "")
  2873. return
  2874. }
  2875. if r.Form.Get("form_action") == "export_from_template" {
  2876. w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"sftpgo-%v-folders-from-template.json\"",
  2877. len(dump.Folders)))
  2878. render.JSON(w, r, dump)
  2879. return
  2880. }
  2881. if err = RestoreFolders(dump.Folders, "", 1, 0, claims.Username, ipAddr, claims.Role); err != nil {
  2882. s.renderMessagePage(w, r, "Unable to save folders", "Cannot save the defined folders:",
  2883. getRespStatus(err), err, "")
  2884. return
  2885. }
  2886. http.Redirect(w, r, webFoldersPath, http.StatusSeeOther)
  2887. }
  2888. func (s *httpdServer) handleWebTemplateUserGet(w http.ResponseWriter, r *http.Request) {
  2889. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2890. tokenAdmin := getAdminFromToken(r)
  2891. admin, err := dataprovider.AdminExists(tokenAdmin.Username)
  2892. if err != nil {
  2893. s.renderInternalServerErrorPage(w, r, fmt.Errorf("unable to get the admin %q: %w", tokenAdmin.Username, err))
  2894. return
  2895. }
  2896. if r.URL.Query().Get("from") != "" {
  2897. username := r.URL.Query().Get("from")
  2898. user, err := dataprovider.UserExists(username, admin.Role)
  2899. if err == nil {
  2900. user.SetEmptySecrets()
  2901. user.PublicKeys = nil
  2902. user.Email = ""
  2903. user.Description = ""
  2904. if user.ExpirationDate == 0 && admin.Filters.Preferences.DefaultUsersExpiration > 0 {
  2905. user.ExpirationDate = util.GetTimeAsMsSinceEpoch(time.Now().Add(24 * time.Hour * time.Duration(admin.Filters.Preferences.DefaultUsersExpiration)))
  2906. }
  2907. s.renderUserPage(w, r, &user, userPageModeTemplate, "", &admin)
  2908. } else if errors.Is(err, util.ErrNotFound) {
  2909. s.renderNotFoundPage(w, r, err)
  2910. } else {
  2911. s.renderInternalServerErrorPage(w, r, err)
  2912. }
  2913. } else {
  2914. user := dataprovider.User{BaseUser: sdk.BaseUser{
  2915. Status: 1,
  2916. Permissions: map[string][]string{
  2917. "/": {dataprovider.PermAny},
  2918. },
  2919. }}
  2920. if admin.Filters.Preferences.DefaultUsersExpiration > 0 {
  2921. user.ExpirationDate = util.GetTimeAsMsSinceEpoch(time.Now().Add(24 * time.Hour * time.Duration(admin.Filters.Preferences.DefaultUsersExpiration)))
  2922. }
  2923. s.renderUserPage(w, r, &user, userPageModeTemplate, "", &admin)
  2924. }
  2925. }
  2926. func (s *httpdServer) handleWebTemplateUserPost(w http.ResponseWriter, r *http.Request) {
  2927. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2928. claims, err := getTokenClaims(r)
  2929. if err != nil || claims.Username == "" {
  2930. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2931. return
  2932. }
  2933. templateUser, err := getUserFromPostFields(r)
  2934. if err != nil {
  2935. s.renderMessagePage(w, r, "Error parsing user fields", "", http.StatusBadRequest, err, "")
  2936. return
  2937. }
  2938. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2939. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2940. s.renderForbiddenPage(w, r, err.Error())
  2941. return
  2942. }
  2943. var dump dataprovider.BackupData
  2944. dump.Version = dataprovider.DumpVersion
  2945. userTmplFields := getUsersForTemplate(r)
  2946. for _, tmpl := range userTmplFields {
  2947. u := getUserFromTemplate(templateUser, tmpl)
  2948. if err := dataprovider.ValidateUser(&u); err != nil {
  2949. s.renderMessagePage(w, r, "User validation error", fmt.Sprintf("Error validating user %q", u.Username),
  2950. http.StatusBadRequest, err, "")
  2951. return
  2952. }
  2953. // to create a template the "manage_system" permission is required, so role admins cannot use
  2954. // this method, we don't need to force the role
  2955. dump.Users = append(dump.Users, u)
  2956. for _, folder := range u.VirtualFolders {
  2957. if !dump.HasFolder(folder.Name) {
  2958. dump.Folders = append(dump.Folders, folder.BaseVirtualFolder)
  2959. }
  2960. }
  2961. }
  2962. if len(dump.Users) == 0 {
  2963. s.renderMessagePage(w, r, "No users defined", "No valid users defined, unable to complete the requested action",
  2964. http.StatusBadRequest, nil, "")
  2965. return
  2966. }
  2967. if r.Form.Get("form_action") == "export_from_template" {
  2968. w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"sftpgo-%v-users-from-template.json\"",
  2969. len(dump.Users)))
  2970. render.JSON(w, r, dump)
  2971. return
  2972. }
  2973. if err = RestoreUsers(dump.Users, "", 1, 0, claims.Username, ipAddr, claims.Role); err != nil {
  2974. s.renderMessagePage(w, r, "Unable to save users", "Cannot save the defined users:",
  2975. getRespStatus(err), err, "")
  2976. return
  2977. }
  2978. http.Redirect(w, r, webUsersPath, http.StatusSeeOther)
  2979. }
  2980. func (s *httpdServer) handleWebAddUserGet(w http.ResponseWriter, r *http.Request) {
  2981. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2982. tokenAdmin := getAdminFromToken(r)
  2983. admin, err := dataprovider.AdminExists(tokenAdmin.Username)
  2984. if err != nil {
  2985. s.renderInternalServerErrorPage(w, r, fmt.Errorf("unable to get the admin %q: %w", tokenAdmin.Username, err))
  2986. return
  2987. }
  2988. user := dataprovider.User{BaseUser: sdk.BaseUser{
  2989. Status: 1,
  2990. Permissions: map[string][]string{
  2991. "/": {dataprovider.PermAny},
  2992. }},
  2993. }
  2994. if admin.Filters.Preferences.DefaultUsersExpiration > 0 {
  2995. user.ExpirationDate = util.GetTimeAsMsSinceEpoch(time.Now().Add(24 * time.Hour * time.Duration(admin.Filters.Preferences.DefaultUsersExpiration)))
  2996. }
  2997. s.renderUserPage(w, r, &user, userPageModeAdd, "", &admin)
  2998. }
  2999. func (s *httpdServer) handleWebUpdateUserGet(w http.ResponseWriter, r *http.Request) {
  3000. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3001. claims, err := getTokenClaims(r)
  3002. if err != nil || claims.Username == "" {
  3003. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3004. return
  3005. }
  3006. username := getURLParam(r, "username")
  3007. user, err := dataprovider.UserExists(username, claims.Role)
  3008. if err == nil {
  3009. s.renderUserPage(w, r, &user, userPageModeUpdate, "", nil)
  3010. } else if errors.Is(err, util.ErrNotFound) {
  3011. s.renderNotFoundPage(w, r, err)
  3012. } else {
  3013. s.renderInternalServerErrorPage(w, r, err)
  3014. }
  3015. }
  3016. func (s *httpdServer) handleWebAddUserPost(w http.ResponseWriter, r *http.Request) {
  3017. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3018. claims, err := getTokenClaims(r)
  3019. if err != nil || claims.Username == "" {
  3020. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3021. return
  3022. }
  3023. user, err := getUserFromPostFields(r)
  3024. if err != nil {
  3025. s.renderUserPage(w, r, &user, userPageModeAdd, err.Error(), nil)
  3026. return
  3027. }
  3028. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3029. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3030. s.renderForbiddenPage(w, r, err.Error())
  3031. return
  3032. }
  3033. user = getUserFromTemplate(user, userTemplateFields{
  3034. Username: user.Username,
  3035. Password: user.Password,
  3036. PublicKeys: user.PublicKeys,
  3037. })
  3038. if claims.Role != "" {
  3039. user.Role = claims.Role
  3040. }
  3041. user.Filters.RecoveryCodes = nil
  3042. user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
  3043. Enabled: false,
  3044. }
  3045. err = dataprovider.AddUser(&user, claims.Username, ipAddr, claims.Role)
  3046. if err != nil {
  3047. s.renderUserPage(w, r, &user, userPageModeAdd, err.Error(), nil)
  3048. return
  3049. }
  3050. http.Redirect(w, r, webUsersPath, http.StatusSeeOther)
  3051. }
  3052. func (s *httpdServer) handleWebUpdateUserPost(w http.ResponseWriter, r *http.Request) {
  3053. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3054. claims, err := getTokenClaims(r)
  3055. if err != nil || claims.Username == "" {
  3056. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3057. return
  3058. }
  3059. username := getURLParam(r, "username")
  3060. user, err := dataprovider.UserExists(username, claims.Role)
  3061. if errors.Is(err, util.ErrNotFound) {
  3062. s.renderNotFoundPage(w, r, err)
  3063. return
  3064. } else if err != nil {
  3065. s.renderInternalServerErrorPage(w, r, err)
  3066. return
  3067. }
  3068. updatedUser, err := getUserFromPostFields(r)
  3069. if err != nil {
  3070. s.renderUserPage(w, r, &user, userPageModeUpdate, err.Error(), nil)
  3071. return
  3072. }
  3073. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3074. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3075. s.renderForbiddenPage(w, r, err.Error())
  3076. return
  3077. }
  3078. updatedUser.ID = user.ID
  3079. updatedUser.Username = user.Username
  3080. updatedUser.Filters.RecoveryCodes = user.Filters.RecoveryCodes
  3081. updatedUser.Filters.TOTPConfig = user.Filters.TOTPConfig
  3082. updatedUser.LastPasswordChange = user.LastPasswordChange
  3083. updatedUser.SetEmptySecretsIfNil()
  3084. if updatedUser.Password == redactedSecret {
  3085. updatedUser.Password = user.Password
  3086. }
  3087. updateEncryptedSecrets(&updatedUser.FsConfig, user.FsConfig.S3Config.AccessSecret, user.FsConfig.AzBlobConfig.AccountKey,
  3088. user.FsConfig.AzBlobConfig.SASURL, user.FsConfig.GCSConfig.Credentials, user.FsConfig.CryptConfig.Passphrase,
  3089. user.FsConfig.SFTPConfig.Password, user.FsConfig.SFTPConfig.PrivateKey, user.FsConfig.SFTPConfig.KeyPassphrase,
  3090. user.FsConfig.HTTPConfig.Password, user.FsConfig.HTTPConfig.APIKey)
  3091. updatedUser = getUserFromTemplate(updatedUser, userTemplateFields{
  3092. Username: updatedUser.Username,
  3093. Password: updatedUser.Password,
  3094. PublicKeys: updatedUser.PublicKeys,
  3095. })
  3096. if claims.Role != "" {
  3097. updatedUser.Role = claims.Role
  3098. }
  3099. err = dataprovider.UpdateUser(&updatedUser, claims.Username, ipAddr, claims.Role)
  3100. if err != nil {
  3101. s.renderUserPage(w, r, &updatedUser, userPageModeUpdate, err.Error(), nil)
  3102. return
  3103. }
  3104. if r.Form.Get("disconnect") != "" {
  3105. disconnectUser(user.Username, claims.Username, claims.Role)
  3106. }
  3107. http.Redirect(w, r, webUsersPath, http.StatusSeeOther)
  3108. }
  3109. func (s *httpdServer) handleWebGetStatus(w http.ResponseWriter, r *http.Request) {
  3110. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3111. data := statusPage{
  3112. basePage: s.getBasePageData(pageStatusTitle, webStatusPath, r),
  3113. Status: getServicesStatus(),
  3114. }
  3115. renderAdminTemplate(w, templateStatus, data)
  3116. }
  3117. func (s *httpdServer) handleWebGetConnections(w http.ResponseWriter, r *http.Request) {
  3118. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3119. claims, err := getTokenClaims(r)
  3120. if err != nil || claims.Username == "" {
  3121. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3122. return
  3123. }
  3124. connectionStats := common.Connections.GetStats(claims.Role)
  3125. connectionStats = append(connectionStats, getNodesConnections(claims.Username, claims.Role)...)
  3126. data := connectionsPage{
  3127. basePage: s.getBasePageData(pageConnectionsTitle, webConnectionsPath, r),
  3128. Connections: connectionStats,
  3129. }
  3130. renderAdminTemplate(w, templateConnections, data)
  3131. }
  3132. func (s *httpdServer) handleWebAddFolderGet(w http.ResponseWriter, r *http.Request) {
  3133. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3134. s.renderFolderPage(w, r, vfs.BaseVirtualFolder{}, folderPageModeAdd, "")
  3135. }
  3136. func (s *httpdServer) handleWebAddFolderPost(w http.ResponseWriter, r *http.Request) {
  3137. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3138. claims, err := getTokenClaims(r)
  3139. if err != nil || claims.Username == "" {
  3140. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3141. return
  3142. }
  3143. folder := vfs.BaseVirtualFolder{}
  3144. err = r.ParseMultipartForm(maxRequestSize)
  3145. if err != nil {
  3146. s.renderFolderPage(w, r, folder, folderPageModeAdd, err.Error())
  3147. return
  3148. }
  3149. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  3150. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3151. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3152. s.renderForbiddenPage(w, r, err.Error())
  3153. return
  3154. }
  3155. folder.MappedPath = r.Form.Get("mapped_path")
  3156. folder.Name = r.Form.Get("name")
  3157. folder.Description = r.Form.Get("description")
  3158. fsConfig, err := getFsConfigFromPostFields(r)
  3159. if err != nil {
  3160. s.renderFolderPage(w, r, folder, folderPageModeAdd, err.Error())
  3161. return
  3162. }
  3163. folder.FsConfig = fsConfig
  3164. folder = getFolderFromTemplate(folder, folder.Name)
  3165. err = dataprovider.AddFolder(&folder, claims.Username, ipAddr, claims.Role)
  3166. if err == nil {
  3167. http.Redirect(w, r, webFoldersPath, http.StatusSeeOther)
  3168. } else {
  3169. s.renderFolderPage(w, r, folder, folderPageModeAdd, err.Error())
  3170. }
  3171. }
  3172. func (s *httpdServer) handleWebUpdateFolderGet(w http.ResponseWriter, r *http.Request) {
  3173. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3174. name := getURLParam(r, "name")
  3175. folder, err := dataprovider.GetFolderByName(name)
  3176. if err == nil {
  3177. s.renderFolderPage(w, r, folder, folderPageModeUpdate, "")
  3178. } else if errors.Is(err, util.ErrNotFound) {
  3179. s.renderNotFoundPage(w, r, err)
  3180. } else {
  3181. s.renderInternalServerErrorPage(w, r, err)
  3182. }
  3183. }
  3184. func (s *httpdServer) handleWebUpdateFolderPost(w http.ResponseWriter, r *http.Request) {
  3185. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3186. claims, err := getTokenClaims(r)
  3187. if err != nil || claims.Username == "" {
  3188. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3189. return
  3190. }
  3191. name := getURLParam(r, "name")
  3192. folder, err := dataprovider.GetFolderByName(name)
  3193. if errors.Is(err, util.ErrNotFound) {
  3194. s.renderNotFoundPage(w, r, err)
  3195. return
  3196. } else if err != nil {
  3197. s.renderInternalServerErrorPage(w, r, err)
  3198. return
  3199. }
  3200. err = r.ParseMultipartForm(maxRequestSize)
  3201. if err != nil {
  3202. s.renderFolderPage(w, r, folder, folderPageModeUpdate, err.Error())
  3203. return
  3204. }
  3205. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  3206. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3207. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3208. s.renderForbiddenPage(w, r, err.Error())
  3209. return
  3210. }
  3211. fsConfig, err := getFsConfigFromPostFields(r)
  3212. if err != nil {
  3213. s.renderFolderPage(w, r, folder, folderPageModeUpdate, err.Error())
  3214. return
  3215. }
  3216. updatedFolder := vfs.BaseVirtualFolder{
  3217. MappedPath: r.Form.Get("mapped_path"),
  3218. Description: r.Form.Get("description"),
  3219. }
  3220. updatedFolder.ID = folder.ID
  3221. updatedFolder.Name = folder.Name
  3222. updatedFolder.FsConfig = fsConfig
  3223. updatedFolder.FsConfig.SetEmptySecretsIfNil()
  3224. updateEncryptedSecrets(&updatedFolder.FsConfig, folder.FsConfig.S3Config.AccessSecret, folder.FsConfig.AzBlobConfig.AccountKey,
  3225. folder.FsConfig.AzBlobConfig.SASURL, folder.FsConfig.GCSConfig.Credentials, folder.FsConfig.CryptConfig.Passphrase,
  3226. folder.FsConfig.SFTPConfig.Password, folder.FsConfig.SFTPConfig.PrivateKey, folder.FsConfig.SFTPConfig.KeyPassphrase,
  3227. folder.FsConfig.HTTPConfig.Password, folder.FsConfig.HTTPConfig.APIKey)
  3228. updatedFolder = getFolderFromTemplate(updatedFolder, updatedFolder.Name)
  3229. err = dataprovider.UpdateFolder(&updatedFolder, folder.Users, folder.Groups, claims.Username, ipAddr, claims.Role)
  3230. if err != nil {
  3231. s.renderFolderPage(w, r, updatedFolder, folderPageModeUpdate, err.Error())
  3232. return
  3233. }
  3234. http.Redirect(w, r, webFoldersPath, http.StatusSeeOther)
  3235. }
  3236. func (s *httpdServer) getWebVirtualFolders(w http.ResponseWriter, r *http.Request, limit int, minimal bool) ([]vfs.BaseVirtualFolder, error) {
  3237. folders := make([]vfs.BaseVirtualFolder, 0, limit)
  3238. for {
  3239. f, err := dataprovider.GetFolders(limit, len(folders), dataprovider.OrderASC, minimal)
  3240. if err != nil {
  3241. s.renderInternalServerErrorPage(w, r, err)
  3242. return folders, err
  3243. }
  3244. folders = append(folders, f...)
  3245. if len(f) < limit {
  3246. break
  3247. }
  3248. }
  3249. return folders, nil
  3250. }
  3251. func (s *httpdServer) handleWebGetFolders(w http.ResponseWriter, r *http.Request) {
  3252. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3253. limit := defaultQueryLimit
  3254. if _, ok := r.URL.Query()["qlimit"]; ok {
  3255. var err error
  3256. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  3257. if err != nil {
  3258. limit = defaultQueryLimit
  3259. }
  3260. }
  3261. folders, err := s.getWebVirtualFolders(w, r, limit, false)
  3262. if err != nil {
  3263. return
  3264. }
  3265. data := foldersPage{
  3266. basePage: s.getBasePageData(pageFoldersTitle, webFoldersPath, r),
  3267. Folders: folders,
  3268. }
  3269. renderAdminTemplate(w, templateFolders, data)
  3270. }
  3271. func (s *httpdServer) getWebGroups(w http.ResponseWriter, r *http.Request, limit int, minimal bool) ([]dataprovider.Group, error) {
  3272. groups := make([]dataprovider.Group, 0, limit)
  3273. for {
  3274. f, err := dataprovider.GetGroups(limit, len(groups), dataprovider.OrderASC, minimal)
  3275. if err != nil {
  3276. s.renderInternalServerErrorPage(w, r, err)
  3277. return groups, err
  3278. }
  3279. groups = append(groups, f...)
  3280. if len(f) < limit {
  3281. break
  3282. }
  3283. }
  3284. return groups, nil
  3285. }
  3286. func (s *httpdServer) handleWebGetGroups(w http.ResponseWriter, r *http.Request) {
  3287. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3288. limit := defaultQueryLimit
  3289. if _, ok := r.URL.Query()["qlimit"]; ok {
  3290. var err error
  3291. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  3292. if err != nil {
  3293. limit = defaultQueryLimit
  3294. }
  3295. }
  3296. groups, err := s.getWebGroups(w, r, limit, false)
  3297. if err != nil {
  3298. return
  3299. }
  3300. data := groupsPage{
  3301. basePage: s.getBasePageData(pageGroupsTitle, webGroupsPath, r),
  3302. Groups: groups,
  3303. }
  3304. renderAdminTemplate(w, templateGroups, data)
  3305. }
  3306. func (s *httpdServer) handleWebAddGroupGet(w http.ResponseWriter, r *http.Request) {
  3307. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3308. s.renderGroupPage(w, r, dataprovider.Group{}, genericPageModeAdd, "")
  3309. }
  3310. func (s *httpdServer) handleWebAddGroupPost(w http.ResponseWriter, r *http.Request) {
  3311. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3312. claims, err := getTokenClaims(r)
  3313. if err != nil || claims.Username == "" {
  3314. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3315. return
  3316. }
  3317. group, err := getGroupFromPostFields(r)
  3318. if err != nil {
  3319. s.renderGroupPage(w, r, group, genericPageModeAdd, err.Error())
  3320. return
  3321. }
  3322. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3323. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3324. s.renderForbiddenPage(w, r, err.Error())
  3325. return
  3326. }
  3327. err = dataprovider.AddGroup(&group, claims.Username, ipAddr, claims.Role)
  3328. if err != nil {
  3329. s.renderGroupPage(w, r, group, genericPageModeAdd, err.Error())
  3330. return
  3331. }
  3332. http.Redirect(w, r, webGroupsPath, http.StatusSeeOther)
  3333. }
  3334. func (s *httpdServer) handleWebUpdateGroupGet(w http.ResponseWriter, r *http.Request) {
  3335. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3336. name := getURLParam(r, "name")
  3337. group, err := dataprovider.GroupExists(name)
  3338. if err == nil {
  3339. s.renderGroupPage(w, r, group, genericPageModeUpdate, "")
  3340. } else if errors.Is(err, util.ErrNotFound) {
  3341. s.renderNotFoundPage(w, r, err)
  3342. } else {
  3343. s.renderInternalServerErrorPage(w, r, err)
  3344. }
  3345. }
  3346. func (s *httpdServer) handleWebUpdateGroupPost(w http.ResponseWriter, r *http.Request) {
  3347. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3348. claims, err := getTokenClaims(r)
  3349. if err != nil || claims.Username == "" {
  3350. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3351. return
  3352. }
  3353. name := getURLParam(r, "name")
  3354. group, err := dataprovider.GroupExists(name)
  3355. if errors.Is(err, util.ErrNotFound) {
  3356. s.renderNotFoundPage(w, r, err)
  3357. return
  3358. } else if err != nil {
  3359. s.renderInternalServerErrorPage(w, r, err)
  3360. return
  3361. }
  3362. updatedGroup, err := getGroupFromPostFields(r)
  3363. if err != nil {
  3364. s.renderGroupPage(w, r, group, genericPageModeUpdate, err.Error())
  3365. return
  3366. }
  3367. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3368. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3369. s.renderForbiddenPage(w, r, err.Error())
  3370. return
  3371. }
  3372. updatedGroup.ID = group.ID
  3373. updatedGroup.Name = group.Name
  3374. updatedGroup.SetEmptySecretsIfNil()
  3375. updateEncryptedSecrets(&updatedGroup.UserSettings.FsConfig, group.UserSettings.FsConfig.S3Config.AccessSecret,
  3376. group.UserSettings.FsConfig.AzBlobConfig.AccountKey, group.UserSettings.FsConfig.AzBlobConfig.SASURL,
  3377. group.UserSettings.FsConfig.GCSConfig.Credentials, group.UserSettings.FsConfig.CryptConfig.Passphrase,
  3378. group.UserSettings.FsConfig.SFTPConfig.Password, group.UserSettings.FsConfig.SFTPConfig.PrivateKey,
  3379. group.UserSettings.FsConfig.SFTPConfig.KeyPassphrase, group.UserSettings.FsConfig.HTTPConfig.Password,
  3380. group.UserSettings.FsConfig.HTTPConfig.APIKey)
  3381. err = dataprovider.UpdateGroup(&updatedGroup, group.Users, claims.Username, ipAddr, claims.Role)
  3382. if err != nil {
  3383. s.renderGroupPage(w, r, updatedGroup, genericPageModeUpdate, err.Error())
  3384. return
  3385. }
  3386. http.Redirect(w, r, webGroupsPath, http.StatusSeeOther)
  3387. }
  3388. func (s *httpdServer) getWebEventActions(w http.ResponseWriter, r *http.Request, limit int, minimal bool,
  3389. ) ([]dataprovider.BaseEventAction, error) {
  3390. actions := make([]dataprovider.BaseEventAction, 0, limit)
  3391. for {
  3392. res, err := dataprovider.GetEventActions(limit, len(actions), dataprovider.OrderASC, minimal)
  3393. if err != nil {
  3394. s.renderInternalServerErrorPage(w, r, err)
  3395. return actions, err
  3396. }
  3397. actions = append(actions, res...)
  3398. if len(res) < limit {
  3399. break
  3400. }
  3401. }
  3402. return actions, nil
  3403. }
  3404. func (s *httpdServer) handleWebGetEventActions(w http.ResponseWriter, r *http.Request) {
  3405. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3406. limit := defaultQueryLimit
  3407. if _, ok := r.URL.Query()["qlimit"]; ok {
  3408. var err error
  3409. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  3410. if err != nil {
  3411. limit = defaultQueryLimit
  3412. }
  3413. }
  3414. actions, err := s.getWebEventActions(w, r, limit, false)
  3415. if err != nil {
  3416. return
  3417. }
  3418. data := eventActionsPage{
  3419. basePage: s.getBasePageData(pageEventActionsTitle, webAdminEventActionsPath, r),
  3420. Actions: actions,
  3421. }
  3422. renderAdminTemplate(w, templateEventActions, data)
  3423. }
  3424. func (s *httpdServer) handleWebAddEventActionGet(w http.ResponseWriter, r *http.Request) {
  3425. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3426. action := dataprovider.BaseEventAction{
  3427. Type: dataprovider.ActionTypeHTTP,
  3428. }
  3429. s.renderEventActionPage(w, r, action, genericPageModeAdd, "")
  3430. }
  3431. func (s *httpdServer) handleWebAddEventActionPost(w http.ResponseWriter, r *http.Request) {
  3432. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3433. claims, err := getTokenClaims(r)
  3434. if err != nil || claims.Username == "" {
  3435. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3436. return
  3437. }
  3438. action, err := getEventActionFromPostFields(r)
  3439. if err != nil {
  3440. s.renderEventActionPage(w, r, action, genericPageModeAdd, err.Error())
  3441. return
  3442. }
  3443. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3444. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3445. s.renderForbiddenPage(w, r, err.Error())
  3446. return
  3447. }
  3448. if err = dataprovider.AddEventAction(&action, claims.Username, ipAddr, claims.Role); err != nil {
  3449. s.renderEventActionPage(w, r, action, genericPageModeAdd, err.Error())
  3450. return
  3451. }
  3452. http.Redirect(w, r, webAdminEventActionsPath, http.StatusSeeOther)
  3453. }
  3454. func (s *httpdServer) handleWebUpdateEventActionGet(w http.ResponseWriter, r *http.Request) {
  3455. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3456. name := getURLParam(r, "name")
  3457. action, err := dataprovider.EventActionExists(name)
  3458. if err == nil {
  3459. s.renderEventActionPage(w, r, action, genericPageModeUpdate, "")
  3460. } else if errors.Is(err, util.ErrNotFound) {
  3461. s.renderNotFoundPage(w, r, err)
  3462. } else {
  3463. s.renderInternalServerErrorPage(w, r, err)
  3464. }
  3465. }
  3466. func (s *httpdServer) handleWebUpdateEventActionPost(w http.ResponseWriter, r *http.Request) {
  3467. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3468. claims, err := getTokenClaims(r)
  3469. if err != nil || claims.Username == "" {
  3470. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3471. return
  3472. }
  3473. name := getURLParam(r, "name")
  3474. action, err := dataprovider.EventActionExists(name)
  3475. if errors.Is(err, util.ErrNotFound) {
  3476. s.renderNotFoundPage(w, r, err)
  3477. return
  3478. } else if err != nil {
  3479. s.renderInternalServerErrorPage(w, r, err)
  3480. return
  3481. }
  3482. updatedAction, err := getEventActionFromPostFields(r)
  3483. if err != nil {
  3484. s.renderEventActionPage(w, r, updatedAction, genericPageModeUpdate, err.Error())
  3485. return
  3486. }
  3487. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3488. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3489. s.renderForbiddenPage(w, r, err.Error())
  3490. return
  3491. }
  3492. updatedAction.ID = action.ID
  3493. updatedAction.Name = action.Name
  3494. updatedAction.Options.SetEmptySecretsIfNil()
  3495. switch updatedAction.Type {
  3496. case dataprovider.ActionTypeHTTP:
  3497. if updatedAction.Options.HTTPConfig.Password.IsNotPlainAndNotEmpty() {
  3498. updatedAction.Options.HTTPConfig.Password = action.Options.HTTPConfig.Password
  3499. }
  3500. }
  3501. err = dataprovider.UpdateEventAction(&updatedAction, claims.Username, ipAddr, claims.Role)
  3502. if err != nil {
  3503. s.renderEventActionPage(w, r, updatedAction, genericPageModeUpdate, err.Error())
  3504. return
  3505. }
  3506. http.Redirect(w, r, webAdminEventActionsPath, http.StatusSeeOther)
  3507. }
  3508. func (s *httpdServer) handleWebGetEventRules(w http.ResponseWriter, r *http.Request) {
  3509. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3510. limit := defaultQueryLimit
  3511. if _, ok := r.URL.Query()["qlimit"]; ok {
  3512. if lim, err := strconv.Atoi(r.URL.Query().Get("qlimit")); err == nil {
  3513. limit = lim
  3514. }
  3515. }
  3516. rules := make([]dataprovider.EventRule, 0, limit)
  3517. for {
  3518. res, err := dataprovider.GetEventRules(limit, len(rules), dataprovider.OrderASC)
  3519. if err != nil {
  3520. s.renderInternalServerErrorPage(w, r, err)
  3521. return
  3522. }
  3523. rules = append(rules, res...)
  3524. if len(res) < limit {
  3525. break
  3526. }
  3527. }
  3528. data := eventRulesPage{
  3529. basePage: s.getBasePageData(pageEventRulesTitle, webAdminEventRulesPath, r),
  3530. Rules: rules,
  3531. }
  3532. renderAdminTemplate(w, templateEventRules, data)
  3533. }
  3534. func (s *httpdServer) handleWebAddEventRuleGet(w http.ResponseWriter, r *http.Request) {
  3535. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3536. rule := dataprovider.EventRule{
  3537. Status: 1,
  3538. Trigger: dataprovider.EventTriggerFsEvent,
  3539. }
  3540. s.renderEventRulePage(w, r, rule, genericPageModeAdd, "")
  3541. }
  3542. func (s *httpdServer) handleWebAddEventRulePost(w http.ResponseWriter, r *http.Request) {
  3543. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3544. claims, err := getTokenClaims(r)
  3545. if err != nil || claims.Username == "" {
  3546. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3547. return
  3548. }
  3549. rule, err := getEventRuleFromPostFields(r)
  3550. if err != nil {
  3551. s.renderEventRulePage(w, r, rule, genericPageModeAdd, err.Error())
  3552. return
  3553. }
  3554. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3555. err = verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr)
  3556. if err != nil {
  3557. s.renderForbiddenPage(w, r, err.Error())
  3558. return
  3559. }
  3560. if err = dataprovider.AddEventRule(&rule, claims.Username, ipAddr, claims.Role); err != nil {
  3561. s.renderEventRulePage(w, r, rule, genericPageModeAdd, err.Error())
  3562. return
  3563. }
  3564. http.Redirect(w, r, webAdminEventRulesPath, http.StatusSeeOther)
  3565. }
  3566. func (s *httpdServer) handleWebUpdateEventRuleGet(w http.ResponseWriter, r *http.Request) {
  3567. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3568. name := getURLParam(r, "name")
  3569. rule, err := dataprovider.EventRuleExists(name)
  3570. if err == nil {
  3571. s.renderEventRulePage(w, r, rule, genericPageModeUpdate, "")
  3572. } else if errors.Is(err, util.ErrNotFound) {
  3573. s.renderNotFoundPage(w, r, err)
  3574. } else {
  3575. s.renderInternalServerErrorPage(w, r, err)
  3576. }
  3577. }
  3578. func (s *httpdServer) handleWebUpdateEventRulePost(w http.ResponseWriter, r *http.Request) {
  3579. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3580. claims, err := getTokenClaims(r)
  3581. if err != nil || claims.Username == "" {
  3582. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3583. return
  3584. }
  3585. name := getURLParam(r, "name")
  3586. rule, err := dataprovider.EventRuleExists(name)
  3587. if errors.Is(err, util.ErrNotFound) {
  3588. s.renderNotFoundPage(w, r, err)
  3589. return
  3590. } else if err != nil {
  3591. s.renderInternalServerErrorPage(w, r, err)
  3592. return
  3593. }
  3594. updatedRule, err := getEventRuleFromPostFields(r)
  3595. if err != nil {
  3596. s.renderEventRulePage(w, r, updatedRule, genericPageModeUpdate, err.Error())
  3597. return
  3598. }
  3599. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3600. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3601. s.renderForbiddenPage(w, r, err.Error())
  3602. return
  3603. }
  3604. updatedRule.ID = rule.ID
  3605. updatedRule.Name = rule.Name
  3606. err = dataprovider.UpdateEventRule(&updatedRule, claims.Username, ipAddr, claims.Role)
  3607. if err != nil {
  3608. s.renderEventRulePage(w, r, updatedRule, genericPageModeUpdate, err.Error())
  3609. return
  3610. }
  3611. http.Redirect(w, r, webAdminEventRulesPath, http.StatusSeeOther)
  3612. }
  3613. func (s *httpdServer) getWebRoles(w http.ResponseWriter, r *http.Request, limit int, minimal bool) ([]dataprovider.Role, error) {
  3614. roles := make([]dataprovider.Role, 0, limit)
  3615. for {
  3616. res, err := dataprovider.GetRoles(limit, len(roles), dataprovider.OrderASC, minimal)
  3617. if err != nil {
  3618. s.renderInternalServerErrorPage(w, r, err)
  3619. return roles, err
  3620. }
  3621. roles = append(roles, res...)
  3622. if len(res) < limit {
  3623. break
  3624. }
  3625. }
  3626. return roles, nil
  3627. }
  3628. func (s *httpdServer) handleWebGetRoles(w http.ResponseWriter, r *http.Request) {
  3629. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3630. roles, err := s.getWebRoles(w, r, 10, false)
  3631. if err != nil {
  3632. return
  3633. }
  3634. data := rolesPage{
  3635. basePage: s.getBasePageData(pageRolesTitle, webAdminRolesPath, r),
  3636. Roles: roles,
  3637. }
  3638. renderAdminTemplate(w, templateRoles, data)
  3639. }
  3640. func (s *httpdServer) handleWebAddRoleGet(w http.ResponseWriter, r *http.Request) {
  3641. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3642. s.renderRolePage(w, r, dataprovider.Role{}, genericPageModeAdd, "")
  3643. }
  3644. func (s *httpdServer) handleWebAddRolePost(w http.ResponseWriter, r *http.Request) {
  3645. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3646. role, err := getRoleFromPostFields(r)
  3647. if err != nil {
  3648. s.renderRolePage(w, r, role, genericPageModeAdd, err.Error())
  3649. return
  3650. }
  3651. claims, err := getTokenClaims(r)
  3652. if err != nil || claims.Username == "" {
  3653. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3654. return
  3655. }
  3656. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3657. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3658. s.renderForbiddenPage(w, r, err.Error())
  3659. return
  3660. }
  3661. err = dataprovider.AddRole(&role, claims.Username, ipAddr, claims.Role)
  3662. if err != nil {
  3663. s.renderRolePage(w, r, role, genericPageModeAdd, err.Error())
  3664. return
  3665. }
  3666. http.Redirect(w, r, webAdminRolesPath, http.StatusSeeOther)
  3667. }
  3668. func (s *httpdServer) handleWebUpdateRoleGet(w http.ResponseWriter, r *http.Request) {
  3669. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3670. role, err := dataprovider.RoleExists(getURLParam(r, "name"))
  3671. if err == nil {
  3672. s.renderRolePage(w, r, role, genericPageModeUpdate, "")
  3673. } else if errors.Is(err, util.ErrNotFound) {
  3674. s.renderNotFoundPage(w, r, err)
  3675. } else {
  3676. s.renderInternalServerErrorPage(w, r, err)
  3677. }
  3678. }
  3679. func (s *httpdServer) handleWebUpdateRolePost(w http.ResponseWriter, r *http.Request) {
  3680. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3681. claims, err := getTokenClaims(r)
  3682. if err != nil || claims.Username == "" {
  3683. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3684. return
  3685. }
  3686. role, err := dataprovider.RoleExists(getURLParam(r, "name"))
  3687. if errors.Is(err, util.ErrNotFound) {
  3688. s.renderNotFoundPage(w, r, err)
  3689. return
  3690. } else if err != nil {
  3691. s.renderInternalServerErrorPage(w, r, err)
  3692. return
  3693. }
  3694. updatedRole, err := getRoleFromPostFields(r)
  3695. if err != nil {
  3696. s.renderRolePage(w, r, role, genericPageModeUpdate, err.Error())
  3697. return
  3698. }
  3699. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3700. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3701. s.renderForbiddenPage(w, r, err.Error())
  3702. return
  3703. }
  3704. updatedRole.ID = role.ID
  3705. updatedRole.Name = role.Name
  3706. err = dataprovider.UpdateRole(&updatedRole, claims.Username, ipAddr, claims.Role)
  3707. if err != nil {
  3708. s.renderRolePage(w, r, updatedRole, genericPageModeUpdate, err.Error())
  3709. return
  3710. }
  3711. http.Redirect(w, r, webAdminRolesPath, http.StatusSeeOther)
  3712. }
  3713. func (s *httpdServer) handleWebGetEvents(w http.ResponseWriter, r *http.Request) {
  3714. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3715. data := eventsPage{
  3716. basePage: s.getBasePageData(pageEventsTitle, webEventsPath, r),
  3717. FsEventsSearchURL: webEventsFsSearchPath,
  3718. ProviderEventsSearchURL: webEventsProviderSearchPath,
  3719. LogEventsSearchURL: webEventsLogSearchPath,
  3720. }
  3721. renderAdminTemplate(w, templateEvents, data)
  3722. }
  3723. func (s *httpdServer) handleWebIPListsPage(w http.ResponseWriter, r *http.Request) {
  3724. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3725. rtlStatus, rtlProtocols := common.Config.GetRateLimitersStatus()
  3726. data := ipListsPage{
  3727. basePage: s.getBasePageData(pageIPListsTitle, webIPListsPath, r),
  3728. RateLimitersStatus: rtlStatus,
  3729. RateLimitersProtocols: strings.Join(rtlProtocols, ", "),
  3730. IsAllowListEnabled: common.Config.IsAllowListEnabled(),
  3731. }
  3732. renderAdminTemplate(w, templateIPLists, data)
  3733. }
  3734. func (s *httpdServer) handleWebAddIPListEntryGet(w http.ResponseWriter, r *http.Request) {
  3735. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3736. listType, _, err := getIPListPathParams(r)
  3737. if err != nil {
  3738. s.renderBadRequestPage(w, r, err)
  3739. return
  3740. }
  3741. s.renderIPListPage(w, r, dataprovider.IPListEntry{Type: listType}, genericPageModeAdd, "")
  3742. }
  3743. func (s *httpdServer) handleWebAddIPListEntryPost(w http.ResponseWriter, r *http.Request) {
  3744. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3745. listType, _, err := getIPListPathParams(r)
  3746. if err != nil {
  3747. s.renderBadRequestPage(w, r, err)
  3748. return
  3749. }
  3750. entry, err := getIPListEntryFromPostFields(r, listType)
  3751. if err != nil {
  3752. s.renderIPListPage(w, r, entry, genericPageModeAdd, err.Error())
  3753. return
  3754. }
  3755. entry.Type = listType
  3756. claims, err := getTokenClaims(r)
  3757. if err != nil || claims.Username == "" {
  3758. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3759. return
  3760. }
  3761. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3762. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3763. s.renderForbiddenPage(w, r, err.Error())
  3764. return
  3765. }
  3766. err = dataprovider.AddIPListEntry(&entry, claims.Username, ipAddr, claims.Role)
  3767. if err != nil {
  3768. s.renderIPListPage(w, r, entry, genericPageModeAdd, err.Error())
  3769. return
  3770. }
  3771. http.Redirect(w, r, webIPListsPath, http.StatusSeeOther)
  3772. }
  3773. func (s *httpdServer) handleWebUpdateIPListEntryGet(w http.ResponseWriter, r *http.Request) {
  3774. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3775. listType, ipOrNet, err := getIPListPathParams(r)
  3776. if err != nil {
  3777. s.renderBadRequestPage(w, r, err)
  3778. return
  3779. }
  3780. entry, err := dataprovider.IPListEntryExists(ipOrNet, listType)
  3781. if err == nil {
  3782. s.renderIPListPage(w, r, entry, genericPageModeUpdate, "")
  3783. } else if errors.Is(err, util.ErrNotFound) {
  3784. s.renderNotFoundPage(w, r, err)
  3785. } else {
  3786. s.renderInternalServerErrorPage(w, r, err)
  3787. }
  3788. }
  3789. func (s *httpdServer) handleWebUpdateIPListEntryPost(w http.ResponseWriter, r *http.Request) {
  3790. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3791. claims, err := getTokenClaims(r)
  3792. if err != nil || claims.Username == "" {
  3793. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3794. return
  3795. }
  3796. listType, ipOrNet, err := getIPListPathParams(r)
  3797. if err != nil {
  3798. s.renderBadRequestPage(w, r, err)
  3799. return
  3800. }
  3801. entry, err := dataprovider.IPListEntryExists(ipOrNet, listType)
  3802. if errors.Is(err, util.ErrNotFound) {
  3803. s.renderNotFoundPage(w, r, err)
  3804. return
  3805. } else if err != nil {
  3806. s.renderInternalServerErrorPage(w, r, err)
  3807. return
  3808. }
  3809. updatedEntry, err := getIPListEntryFromPostFields(r, listType)
  3810. if err != nil {
  3811. s.renderIPListPage(w, r, entry, genericPageModeUpdate, err.Error())
  3812. return
  3813. }
  3814. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3815. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3816. s.renderForbiddenPage(w, r, err.Error())
  3817. return
  3818. }
  3819. updatedEntry.Type = listType
  3820. updatedEntry.IPOrNet = ipOrNet
  3821. err = dataprovider.UpdateIPListEntry(&updatedEntry, claims.Username, ipAddr, claims.Role)
  3822. if err != nil {
  3823. s.renderIPListPage(w, r, entry, genericPageModeUpdate, err.Error())
  3824. return
  3825. }
  3826. http.Redirect(w, r, webIPListsPath, http.StatusSeeOther)
  3827. }
  3828. func (s *httpdServer) handleWebConfigs(w http.ResponseWriter, r *http.Request) {
  3829. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3830. configs, err := dataprovider.GetConfigs()
  3831. if err != nil {
  3832. s.renderInternalServerErrorPage(w, r, err)
  3833. return
  3834. }
  3835. s.renderConfigsPage(w, r, configs, "", 0)
  3836. }
  3837. func (s *httpdServer) handleWebConfigsPost(w http.ResponseWriter, r *http.Request) {
  3838. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3839. claims, err := getTokenClaims(r)
  3840. if err != nil || claims.Username == "" {
  3841. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3842. return
  3843. }
  3844. configs, err := dataprovider.GetConfigs()
  3845. if err != nil {
  3846. s.renderInternalServerErrorPage(w, r, err)
  3847. return
  3848. }
  3849. err = r.ParseForm()
  3850. if err != nil {
  3851. s.renderBadRequestPage(w, r, err)
  3852. return
  3853. }
  3854. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3855. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3856. s.renderForbiddenPage(w, r, err.Error())
  3857. return
  3858. }
  3859. var configSection int
  3860. switch r.Form.Get("form_action") {
  3861. case "sftp_submit":
  3862. configSection = 1
  3863. sftpConfigs := getSFTPConfigsFromPostFields(r)
  3864. configs.SFTPD = sftpConfigs
  3865. case "acme_submit":
  3866. configSection = 2
  3867. acmeConfigs := getACMEConfigsFromPostFields(r)
  3868. configs.ACME = acmeConfigs
  3869. if err := acme.GetCertificatesForConfig(acmeConfigs, configurationDir); err != nil {
  3870. s.renderConfigsPage(w, r, configs, err.Error(), configSection)
  3871. return
  3872. }
  3873. case "smtp_submit":
  3874. configSection = 3
  3875. smtpConfigs := getSMTPConfigsFromPostFields(r)
  3876. if smtpConfigs.Password.IsNotPlainAndNotEmpty() {
  3877. smtpConfigs.Password = configs.SMTP.Password
  3878. }
  3879. configs.SMTP = smtpConfigs
  3880. default:
  3881. s.renderBadRequestPage(w, r, errors.New("unsupported form action"))
  3882. return
  3883. }
  3884. err = dataprovider.UpdateConfigs(&configs, claims.Username, ipAddr, claims.Role)
  3885. if err != nil {
  3886. s.renderConfigsPage(w, r, configs, err.Error(), configSection)
  3887. return
  3888. }
  3889. if configSection == 3 {
  3890. err := configs.SMTP.Password.TryDecrypt()
  3891. if err == nil {
  3892. smtp.Activate(configs.SMTP)
  3893. } else {
  3894. logger.Error(logSender, "", "unable to decrypt SMTP password, cannot activate configuration")
  3895. }
  3896. }
  3897. s.renderMessagePage(w, r, "Configurations updated", "", http.StatusOK, nil,
  3898. "Configurations has been successfully updated")
  3899. }