webadmin.go 134 KB

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