webadmin.go 122 KB

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