webadmin.go 122 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697
  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. trigger, err := strconv.Atoi(r.Form.Get("trigger"))
  2201. if err != nil {
  2202. return dataprovider.EventRule{}, fmt.Errorf("invalid trigger: %w", err)
  2203. }
  2204. conditions, err := getEventRuleConditionsFromPostFields(r)
  2205. if err != nil {
  2206. return dataprovider.EventRule{}, err
  2207. }
  2208. actions, err := getEventRuleActionsFromPostFields(r)
  2209. if err != nil {
  2210. return dataprovider.EventRule{}, err
  2211. }
  2212. rule := dataprovider.EventRule{
  2213. Name: r.Form.Get("name"),
  2214. Description: r.Form.Get("description"),
  2215. Trigger: trigger,
  2216. Conditions: conditions,
  2217. Actions: actions,
  2218. }
  2219. return rule, nil
  2220. }
  2221. func getRoleFromPostFields(r *http.Request) (dataprovider.Role, error) {
  2222. err := r.ParseForm()
  2223. if err != nil {
  2224. return dataprovider.Role{}, err
  2225. }
  2226. return dataprovider.Role{
  2227. Name: r.Form.Get("name"),
  2228. Description: r.Form.Get("description"),
  2229. }, nil
  2230. }
  2231. func (s *httpdServer) handleWebAdminForgotPwd(w http.ResponseWriter, r *http.Request) {
  2232. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2233. if !smtp.IsEnabled() {
  2234. s.renderNotFoundPage(w, r, errors.New("this page does not exist"))
  2235. return
  2236. }
  2237. s.renderForgotPwdPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr))
  2238. }
  2239. func (s *httpdServer) handleWebAdminForgotPwdPost(w http.ResponseWriter, r *http.Request) {
  2240. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2241. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2242. err := r.ParseForm()
  2243. if err != nil {
  2244. s.renderForgotPwdPage(w, err.Error(), ipAddr)
  2245. return
  2246. }
  2247. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2248. s.renderForbiddenPage(w, r, err.Error())
  2249. return
  2250. }
  2251. err = handleForgotPassword(r, r.Form.Get("username"), true)
  2252. if err != nil {
  2253. if e, ok := err.(*util.ValidationError); ok {
  2254. s.renderForgotPwdPage(w, e.GetErrorString(), ipAddr)
  2255. return
  2256. }
  2257. s.renderForgotPwdPage(w, err.Error(), ipAddr)
  2258. return
  2259. }
  2260. http.Redirect(w, r, webAdminResetPwdPath, http.StatusFound)
  2261. }
  2262. func (s *httpdServer) handleWebAdminPasswordReset(w http.ResponseWriter, r *http.Request) {
  2263. r.Body = http.MaxBytesReader(w, r.Body, maxLoginBodySize)
  2264. if !smtp.IsEnabled() {
  2265. s.renderNotFoundPage(w, r, errors.New("this page does not exist"))
  2266. return
  2267. }
  2268. s.renderResetPwdPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr))
  2269. }
  2270. func (s *httpdServer) handleWebAdminTwoFactor(w http.ResponseWriter, r *http.Request) {
  2271. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2272. s.renderTwoFactorPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr))
  2273. }
  2274. func (s *httpdServer) handleWebAdminTwoFactorRecovery(w http.ResponseWriter, r *http.Request) {
  2275. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2276. s.renderTwoFactorRecoveryPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr))
  2277. }
  2278. func (s *httpdServer) handleWebAdminMFA(w http.ResponseWriter, r *http.Request) {
  2279. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2280. s.renderMFAPage(w, r)
  2281. }
  2282. func (s *httpdServer) handleWebAdminProfile(w http.ResponseWriter, r *http.Request) {
  2283. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2284. s.renderProfilePage(w, r, "")
  2285. }
  2286. func (s *httpdServer) handleWebAdminChangePwd(w http.ResponseWriter, r *http.Request) {
  2287. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2288. s.renderChangePasswordPage(w, r, "")
  2289. }
  2290. func (s *httpdServer) handleWebAdminProfilePost(w http.ResponseWriter, r *http.Request) {
  2291. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2292. err := r.ParseForm()
  2293. if err != nil {
  2294. s.renderProfilePage(w, r, err.Error())
  2295. return
  2296. }
  2297. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2298. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2299. s.renderForbiddenPage(w, r, err.Error())
  2300. return
  2301. }
  2302. claims, err := getTokenClaims(r)
  2303. if err != nil || claims.Username == "" {
  2304. s.renderProfilePage(w, r, "Invalid token claims")
  2305. return
  2306. }
  2307. admin, err := dataprovider.AdminExists(claims.Username)
  2308. if err != nil {
  2309. s.renderProfilePage(w, r, err.Error())
  2310. return
  2311. }
  2312. admin.Filters.AllowAPIKeyAuth = r.Form.Get("allow_api_key_auth") != ""
  2313. admin.Email = r.Form.Get("email")
  2314. admin.Description = r.Form.Get("description")
  2315. err = dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, ipAddr, admin.Role)
  2316. if err != nil {
  2317. s.renderProfilePage(w, r, err.Error())
  2318. return
  2319. }
  2320. s.renderMessagePage(w, r, "Profile updated", "", http.StatusOK, nil,
  2321. "Your profile has been successfully updated")
  2322. }
  2323. func (s *httpdServer) handleWebMaintenance(w http.ResponseWriter, r *http.Request) {
  2324. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2325. s.renderMaintenancePage(w, r, "")
  2326. }
  2327. func (s *httpdServer) handleWebRestore(w http.ResponseWriter, r *http.Request) {
  2328. r.Body = http.MaxBytesReader(w, r.Body, MaxRestoreSize)
  2329. claims, err := getTokenClaims(r)
  2330. if err != nil || claims.Username == "" {
  2331. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2332. return
  2333. }
  2334. err = r.ParseMultipartForm(MaxRestoreSize)
  2335. if err != nil {
  2336. s.renderMaintenancePage(w, r, err.Error())
  2337. return
  2338. }
  2339. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  2340. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2341. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2342. s.renderForbiddenPage(w, r, err.Error())
  2343. return
  2344. }
  2345. restoreMode, err := strconv.Atoi(r.Form.Get("mode"))
  2346. if err != nil {
  2347. s.renderMaintenancePage(w, r, err.Error())
  2348. return
  2349. }
  2350. scanQuota, err := strconv.Atoi(r.Form.Get("quota"))
  2351. if err != nil {
  2352. s.renderMaintenancePage(w, r, err.Error())
  2353. return
  2354. }
  2355. backupFile, _, err := r.FormFile("backup_file")
  2356. if err != nil {
  2357. s.renderMaintenancePage(w, r, err.Error())
  2358. return
  2359. }
  2360. defer backupFile.Close()
  2361. backupContent, err := io.ReadAll(backupFile)
  2362. if err != nil || len(backupContent) == 0 {
  2363. if len(backupContent) == 0 {
  2364. err = errors.New("backup file size must be greater than 0")
  2365. }
  2366. s.renderMaintenancePage(w, r, err.Error())
  2367. return
  2368. }
  2369. if err := restoreBackup(backupContent, "", scanQuota, restoreMode, claims.Username, ipAddr, claims.Role); err != nil {
  2370. s.renderMaintenancePage(w, r, err.Error())
  2371. return
  2372. }
  2373. s.renderMessagePage(w, r, "Data restored", "", http.StatusOK, nil, "Your backup was successfully restored")
  2374. }
  2375. func (s *httpdServer) handleGetWebAdmins(w http.ResponseWriter, r *http.Request) {
  2376. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2377. limit := defaultQueryLimit
  2378. if _, ok := r.URL.Query()["qlimit"]; ok {
  2379. var err error
  2380. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  2381. if err != nil {
  2382. limit = defaultQueryLimit
  2383. }
  2384. }
  2385. admins := make([]dataprovider.Admin, 0, limit)
  2386. for {
  2387. a, err := dataprovider.GetAdmins(limit, len(admins), dataprovider.OrderASC)
  2388. if err != nil {
  2389. s.renderInternalServerErrorPage(w, r, err)
  2390. return
  2391. }
  2392. admins = append(admins, a...)
  2393. if len(a) < limit {
  2394. break
  2395. }
  2396. }
  2397. data := adminsPage{
  2398. basePage: s.getBasePageData(pageAdminsTitle, webAdminsPath, r),
  2399. Admins: admins,
  2400. }
  2401. renderAdminTemplate(w, templateAdmins, data)
  2402. }
  2403. func (s *httpdServer) handleWebAdminSetupGet(w http.ResponseWriter, r *http.Request) {
  2404. r.Body = http.MaxBytesReader(w, r.Body, maxLoginBodySize)
  2405. if dataprovider.HasAdmin() {
  2406. http.Redirect(w, r, webAdminLoginPath, http.StatusFound)
  2407. return
  2408. }
  2409. s.renderAdminSetupPage(w, r, "", "")
  2410. }
  2411. func (s *httpdServer) handleWebAddAdminGet(w http.ResponseWriter, r *http.Request) {
  2412. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2413. admin := &dataprovider.Admin{
  2414. Status: 1,
  2415. Permissions: []string{dataprovider.PermAdminAny},
  2416. }
  2417. s.renderAddUpdateAdminPage(w, r, admin, "", true)
  2418. }
  2419. func (s *httpdServer) handleWebUpdateAdminGet(w http.ResponseWriter, r *http.Request) {
  2420. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2421. username := getURLParam(r, "username")
  2422. admin, err := dataprovider.AdminExists(username)
  2423. if err == nil {
  2424. s.renderAddUpdateAdminPage(w, r, &admin, "", false)
  2425. } else if _, ok := err.(*util.RecordNotFoundError); ok {
  2426. s.renderNotFoundPage(w, r, err)
  2427. } else {
  2428. s.renderInternalServerErrorPage(w, r, err)
  2429. }
  2430. }
  2431. func (s *httpdServer) handleWebAddAdminPost(w http.ResponseWriter, r *http.Request) {
  2432. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2433. claims, err := getTokenClaims(r)
  2434. if err != nil || claims.Username == "" {
  2435. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2436. return
  2437. }
  2438. admin, err := getAdminFromPostFields(r)
  2439. if err != nil {
  2440. s.renderAddUpdateAdminPage(w, r, &admin, err.Error(), true)
  2441. return
  2442. }
  2443. if admin.Password == "" && s.binding.isWebAdminLoginFormDisabled() {
  2444. admin.Password = util.GenerateUniqueID()
  2445. }
  2446. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2447. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2448. s.renderForbiddenPage(w, r, err.Error())
  2449. return
  2450. }
  2451. err = dataprovider.AddAdmin(&admin, claims.Username, ipAddr, claims.Role)
  2452. if err != nil {
  2453. s.renderAddUpdateAdminPage(w, r, &admin, err.Error(), true)
  2454. return
  2455. }
  2456. http.Redirect(w, r, webAdminsPath, http.StatusSeeOther)
  2457. }
  2458. func (s *httpdServer) handleWebUpdateAdminPost(w http.ResponseWriter, r *http.Request) {
  2459. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2460. username := getURLParam(r, "username")
  2461. admin, err := dataprovider.AdminExists(username)
  2462. if _, ok := err.(*util.RecordNotFoundError); ok {
  2463. s.renderNotFoundPage(w, r, err)
  2464. return
  2465. } else if err != nil {
  2466. s.renderInternalServerErrorPage(w, r, err)
  2467. return
  2468. }
  2469. updatedAdmin, err := getAdminFromPostFields(r)
  2470. if err != nil {
  2471. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, err.Error(), false)
  2472. return
  2473. }
  2474. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2475. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2476. s.renderForbiddenPage(w, r, err.Error())
  2477. return
  2478. }
  2479. updatedAdmin.ID = admin.ID
  2480. updatedAdmin.Username = admin.Username
  2481. if updatedAdmin.Password == "" {
  2482. updatedAdmin.Password = admin.Password
  2483. }
  2484. updatedAdmin.Filters.TOTPConfig = admin.Filters.TOTPConfig
  2485. updatedAdmin.Filters.RecoveryCodes = admin.Filters.RecoveryCodes
  2486. claims, err := getTokenClaims(r)
  2487. if err != nil || claims.Username == "" {
  2488. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, "Invalid token claims", false)
  2489. return
  2490. }
  2491. if username == claims.Username {
  2492. if claims.isCriticalPermRemoved(updatedAdmin.Permissions) {
  2493. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, "You cannot remove these permissions to yourself", false)
  2494. return
  2495. }
  2496. if updatedAdmin.Status == 0 {
  2497. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, "You cannot disable yourself", false)
  2498. return
  2499. }
  2500. if updatedAdmin.Role != claims.Role {
  2501. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, "You cannot add/change your role", false)
  2502. return
  2503. }
  2504. }
  2505. err = dataprovider.UpdateAdmin(&updatedAdmin, claims.Username, ipAddr, claims.Role)
  2506. if err != nil {
  2507. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, err.Error(), false)
  2508. return
  2509. }
  2510. http.Redirect(w, r, webAdminsPath, http.StatusSeeOther)
  2511. }
  2512. func (s *httpdServer) handleWebDefenderPage(w http.ResponseWriter, r *http.Request) {
  2513. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2514. data := defenderHostsPage{
  2515. basePage: s.getBasePageData(pageDefenderTitle, webDefenderPath, r),
  2516. DefenderHostsURL: webDefenderHostsPath,
  2517. }
  2518. renderAdminTemplate(w, templateDefender, data)
  2519. }
  2520. func (s *httpdServer) handleGetWebUsers(w http.ResponseWriter, r *http.Request) {
  2521. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2522. claims, err := getTokenClaims(r)
  2523. if err != nil || claims.Username == "" {
  2524. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2525. return
  2526. }
  2527. var limit int
  2528. if _, ok := r.URL.Query()["qlimit"]; ok {
  2529. var err error
  2530. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  2531. if err != nil {
  2532. limit = defaultQueryLimit
  2533. }
  2534. } else {
  2535. limit = defaultQueryLimit
  2536. }
  2537. users := make([]dataprovider.User, 0, limit)
  2538. for {
  2539. u, err := dataprovider.GetUsers(limit, len(users), dataprovider.OrderASC, claims.Role)
  2540. if err != nil {
  2541. s.renderInternalServerErrorPage(w, r, err)
  2542. return
  2543. }
  2544. users = append(users, u...)
  2545. if len(u) < limit {
  2546. break
  2547. }
  2548. }
  2549. data := usersPage{
  2550. basePage: s.getBasePageData(pageUsersTitle, webUsersPath, r),
  2551. Users: users,
  2552. }
  2553. renderAdminTemplate(w, templateUsers, data)
  2554. }
  2555. func (s *httpdServer) handleWebTemplateFolderGet(w http.ResponseWriter, r *http.Request) {
  2556. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2557. if r.URL.Query().Get("from") != "" {
  2558. name := r.URL.Query().Get("from")
  2559. folder, err := dataprovider.GetFolderByName(name)
  2560. if err == nil {
  2561. folder.FsConfig.SetEmptySecrets()
  2562. s.renderFolderPage(w, r, folder, folderPageModeTemplate, "")
  2563. } else if _, ok := err.(*util.RecordNotFoundError); ok {
  2564. s.renderNotFoundPage(w, r, err)
  2565. } else {
  2566. s.renderInternalServerErrorPage(w, r, err)
  2567. }
  2568. } else {
  2569. folder := vfs.BaseVirtualFolder{}
  2570. s.renderFolderPage(w, r, folder, folderPageModeTemplate, "")
  2571. }
  2572. }
  2573. func (s *httpdServer) handleWebTemplateFolderPost(w http.ResponseWriter, r *http.Request) {
  2574. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2575. claims, err := getTokenClaims(r)
  2576. if err != nil || claims.Username == "" {
  2577. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2578. return
  2579. }
  2580. templateFolder := vfs.BaseVirtualFolder{}
  2581. err = r.ParseMultipartForm(maxRequestSize)
  2582. if err != nil {
  2583. s.renderMessagePage(w, r, "Error parsing folders fields", "", http.StatusBadRequest, err, "")
  2584. return
  2585. }
  2586. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  2587. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2588. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2589. s.renderForbiddenPage(w, r, err.Error())
  2590. return
  2591. }
  2592. templateFolder.MappedPath = r.Form.Get("mapped_path")
  2593. templateFolder.Description = r.Form.Get("description")
  2594. fsConfig, err := getFsConfigFromPostFields(r)
  2595. if err != nil {
  2596. s.renderMessagePage(w, r, "Error parsing folders fields", "", http.StatusBadRequest, err, "")
  2597. return
  2598. }
  2599. templateFolder.FsConfig = fsConfig
  2600. var dump dataprovider.BackupData
  2601. dump.Version = dataprovider.DumpVersion
  2602. foldersFields := getFoldersForTemplate(r)
  2603. for _, tmpl := range foldersFields {
  2604. f := getFolderFromTemplate(templateFolder, tmpl)
  2605. if err := dataprovider.ValidateFolder(&f); err != nil {
  2606. s.renderMessagePage(w, r, "Folder validation error", fmt.Sprintf("Error validating folder %#v", f.Name),
  2607. http.StatusBadRequest, err, "")
  2608. return
  2609. }
  2610. dump.Folders = append(dump.Folders, f)
  2611. }
  2612. if len(dump.Folders) == 0 {
  2613. s.renderMessagePage(w, r, "No folders defined", "No valid folders defined, unable to complete the requested action",
  2614. http.StatusBadRequest, nil, "")
  2615. return
  2616. }
  2617. if r.Form.Get("form_action") == "export_from_template" {
  2618. w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"sftpgo-%v-folders-from-template.json\"",
  2619. len(dump.Folders)))
  2620. render.JSON(w, r, dump)
  2621. return
  2622. }
  2623. if err = RestoreFolders(dump.Folders, "", 1, 0, claims.Username, ipAddr, claims.Role); err != nil {
  2624. s.renderMessagePage(w, r, "Unable to save folders", "Cannot save the defined folders:",
  2625. getRespStatus(err), err, "")
  2626. return
  2627. }
  2628. http.Redirect(w, r, webFoldersPath, http.StatusSeeOther)
  2629. }
  2630. func (s *httpdServer) handleWebTemplateUserGet(w http.ResponseWriter, r *http.Request) {
  2631. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2632. tokenAdmin := getAdminFromToken(r)
  2633. admin, err := dataprovider.AdminExists(tokenAdmin.Username)
  2634. if err != nil {
  2635. s.renderInternalServerErrorPage(w, r, fmt.Errorf("unable to get the admin %q: %w", tokenAdmin.Username, err))
  2636. return
  2637. }
  2638. if r.URL.Query().Get("from") != "" {
  2639. username := r.URL.Query().Get("from")
  2640. user, err := dataprovider.UserExists(username, admin.Role)
  2641. if err == nil {
  2642. user.SetEmptySecrets()
  2643. user.PublicKeys = nil
  2644. user.Email = ""
  2645. user.Description = ""
  2646. if user.ExpirationDate == 0 && admin.Filters.Preferences.DefaultUsersExpiration > 0 {
  2647. user.ExpirationDate = util.GetTimeAsMsSinceEpoch(time.Now().Add(24 * time.Hour * time.Duration(admin.Filters.Preferences.DefaultUsersExpiration)))
  2648. }
  2649. s.renderUserPage(w, r, &user, userPageModeTemplate, "", &admin)
  2650. } else if _, ok := err.(*util.RecordNotFoundError); ok {
  2651. s.renderNotFoundPage(w, r, err)
  2652. } else {
  2653. s.renderInternalServerErrorPage(w, r, err)
  2654. }
  2655. } else {
  2656. user := dataprovider.User{BaseUser: sdk.BaseUser{
  2657. Status: 1,
  2658. Permissions: map[string][]string{
  2659. "/": {dataprovider.PermAny},
  2660. },
  2661. }}
  2662. if admin.Filters.Preferences.DefaultUsersExpiration > 0 {
  2663. user.ExpirationDate = util.GetTimeAsMsSinceEpoch(time.Now().Add(24 * time.Hour * time.Duration(admin.Filters.Preferences.DefaultUsersExpiration)))
  2664. }
  2665. s.renderUserPage(w, r, &user, userPageModeTemplate, "", &admin)
  2666. }
  2667. }
  2668. func (s *httpdServer) handleWebTemplateUserPost(w http.ResponseWriter, r *http.Request) {
  2669. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2670. claims, err := getTokenClaims(r)
  2671. if err != nil || claims.Username == "" {
  2672. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2673. return
  2674. }
  2675. templateUser, err := getUserFromPostFields(r)
  2676. if err != nil {
  2677. s.renderMessagePage(w, r, "Error parsing user fields", "", http.StatusBadRequest, err, "")
  2678. return
  2679. }
  2680. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2681. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2682. s.renderForbiddenPage(w, r, err.Error())
  2683. return
  2684. }
  2685. var dump dataprovider.BackupData
  2686. dump.Version = dataprovider.DumpVersion
  2687. userTmplFields := getUsersForTemplate(r)
  2688. for _, tmpl := range userTmplFields {
  2689. u := getUserFromTemplate(templateUser, tmpl)
  2690. if err := dataprovider.ValidateUser(&u); err != nil {
  2691. s.renderMessagePage(w, r, "User validation error", fmt.Sprintf("Error validating user %#v", u.Username),
  2692. http.StatusBadRequest, err, "")
  2693. return
  2694. }
  2695. // to create a template the "manage_system" permission is required, so role admins cannot use
  2696. // this method, we don't need to force the role
  2697. dump.Users = append(dump.Users, u)
  2698. for _, folder := range u.VirtualFolders {
  2699. if !dump.HasFolder(folder.Name) {
  2700. dump.Folders = append(dump.Folders, folder.BaseVirtualFolder)
  2701. }
  2702. }
  2703. }
  2704. if len(dump.Users) == 0 {
  2705. s.renderMessagePage(w, r, "No users defined", "No valid users defined, unable to complete the requested action",
  2706. http.StatusBadRequest, nil, "")
  2707. return
  2708. }
  2709. if r.Form.Get("form_action") == "export_from_template" {
  2710. w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"sftpgo-%v-users-from-template.json\"",
  2711. len(dump.Users)))
  2712. render.JSON(w, r, dump)
  2713. return
  2714. }
  2715. if err = RestoreUsers(dump.Users, "", 1, 0, claims.Username, ipAddr, claims.Role); err != nil {
  2716. s.renderMessagePage(w, r, "Unable to save users", "Cannot save the defined users:",
  2717. getRespStatus(err), err, "")
  2718. return
  2719. }
  2720. http.Redirect(w, r, webUsersPath, http.StatusSeeOther)
  2721. }
  2722. func (s *httpdServer) handleWebAddUserGet(w http.ResponseWriter, r *http.Request) {
  2723. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2724. tokenAdmin := getAdminFromToken(r)
  2725. admin, err := dataprovider.AdminExists(tokenAdmin.Username)
  2726. if err != nil {
  2727. s.renderInternalServerErrorPage(w, r, fmt.Errorf("unable to get the admin %q: %w", tokenAdmin.Username, err))
  2728. return
  2729. }
  2730. user := dataprovider.User{BaseUser: sdk.BaseUser{
  2731. Status: 1,
  2732. Permissions: map[string][]string{
  2733. "/": {dataprovider.PermAny},
  2734. }},
  2735. }
  2736. if admin.Filters.Preferences.DefaultUsersExpiration > 0 {
  2737. user.ExpirationDate = util.GetTimeAsMsSinceEpoch(time.Now().Add(24 * time.Hour * time.Duration(admin.Filters.Preferences.DefaultUsersExpiration)))
  2738. }
  2739. s.renderUserPage(w, r, &user, userPageModeAdd, "", &admin)
  2740. }
  2741. func (s *httpdServer) handleWebUpdateUserGet(w http.ResponseWriter, r *http.Request) {
  2742. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2743. claims, err := getTokenClaims(r)
  2744. if err != nil || claims.Username == "" {
  2745. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2746. return
  2747. }
  2748. username := getURLParam(r, "username")
  2749. user, err := dataprovider.UserExists(username, claims.Role)
  2750. if err == nil {
  2751. s.renderUserPage(w, r, &user, userPageModeUpdate, "", nil)
  2752. } else if _, ok := err.(*util.RecordNotFoundError); ok {
  2753. s.renderNotFoundPage(w, r, err)
  2754. } else {
  2755. s.renderInternalServerErrorPage(w, r, err)
  2756. }
  2757. }
  2758. func (s *httpdServer) handleWebAddUserPost(w http.ResponseWriter, r *http.Request) {
  2759. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2760. claims, err := getTokenClaims(r)
  2761. if err != nil || claims.Username == "" {
  2762. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2763. return
  2764. }
  2765. user, err := getUserFromPostFields(r)
  2766. if err != nil {
  2767. s.renderUserPage(w, r, &user, userPageModeAdd, err.Error(), nil)
  2768. return
  2769. }
  2770. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2771. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2772. s.renderForbiddenPage(w, r, err.Error())
  2773. return
  2774. }
  2775. user = getUserFromTemplate(user, userTemplateFields{
  2776. Username: user.Username,
  2777. Password: user.Password,
  2778. PublicKeys: user.PublicKeys,
  2779. })
  2780. if claims.Role != "" {
  2781. user.Role = claims.Role
  2782. }
  2783. user.Filters.RecoveryCodes = nil
  2784. user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
  2785. Enabled: false,
  2786. }
  2787. err = dataprovider.AddUser(&user, claims.Username, ipAddr, claims.Role)
  2788. if err != nil {
  2789. s.renderUserPage(w, r, &user, userPageModeAdd, err.Error(), nil)
  2790. return
  2791. }
  2792. http.Redirect(w, r, webUsersPath, http.StatusSeeOther)
  2793. }
  2794. func (s *httpdServer) handleWebUpdateUserPost(w http.ResponseWriter, r *http.Request) {
  2795. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2796. claims, err := getTokenClaims(r)
  2797. if err != nil || claims.Username == "" {
  2798. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2799. return
  2800. }
  2801. username := getURLParam(r, "username")
  2802. user, err := dataprovider.UserExists(username, claims.Role)
  2803. if _, ok := err.(*util.RecordNotFoundError); ok {
  2804. s.renderNotFoundPage(w, r, err)
  2805. return
  2806. } else if err != nil {
  2807. s.renderInternalServerErrorPage(w, r, err)
  2808. return
  2809. }
  2810. updatedUser, err := getUserFromPostFields(r)
  2811. if err != nil {
  2812. s.renderUserPage(w, r, &user, userPageModeUpdate, err.Error(), nil)
  2813. return
  2814. }
  2815. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2816. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2817. s.renderForbiddenPage(w, r, err.Error())
  2818. return
  2819. }
  2820. updatedUser.ID = user.ID
  2821. updatedUser.Username = user.Username
  2822. updatedUser.Filters.RecoveryCodes = user.Filters.RecoveryCodes
  2823. updatedUser.Filters.TOTPConfig = user.Filters.TOTPConfig
  2824. updatedUser.LastPasswordChange = user.LastPasswordChange
  2825. updatedUser.SetEmptySecretsIfNil()
  2826. if updatedUser.Password == redactedSecret {
  2827. updatedUser.Password = user.Password
  2828. }
  2829. updateEncryptedSecrets(&updatedUser.FsConfig, user.FsConfig.S3Config.AccessSecret, user.FsConfig.AzBlobConfig.AccountKey,
  2830. user.FsConfig.AzBlobConfig.SASURL, user.FsConfig.GCSConfig.Credentials, user.FsConfig.CryptConfig.Passphrase,
  2831. user.FsConfig.SFTPConfig.Password, user.FsConfig.SFTPConfig.PrivateKey, user.FsConfig.SFTPConfig.KeyPassphrase,
  2832. user.FsConfig.HTTPConfig.Password, user.FsConfig.HTTPConfig.APIKey)
  2833. updatedUser = getUserFromTemplate(updatedUser, userTemplateFields{
  2834. Username: updatedUser.Username,
  2835. Password: updatedUser.Password,
  2836. PublicKeys: updatedUser.PublicKeys,
  2837. })
  2838. if claims.Role != "" {
  2839. updatedUser.Role = claims.Role
  2840. }
  2841. err = dataprovider.UpdateUser(&updatedUser, claims.Username, ipAddr, claims.Role)
  2842. if err != nil {
  2843. s.renderUserPage(w, r, &updatedUser, userPageModeUpdate, err.Error(), nil)
  2844. return
  2845. }
  2846. if r.Form.Get("disconnect") != "" {
  2847. disconnectUser(user.Username)
  2848. }
  2849. http.Redirect(w, r, webUsersPath, http.StatusSeeOther)
  2850. }
  2851. func (s *httpdServer) handleWebGetStatus(w http.ResponseWriter, r *http.Request) {
  2852. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2853. data := statusPage{
  2854. basePage: s.getBasePageData(pageStatusTitle, webStatusPath, r),
  2855. Status: getServicesStatus(),
  2856. }
  2857. renderAdminTemplate(w, templateStatus, data)
  2858. }
  2859. func (s *httpdServer) handleWebGetConnections(w http.ResponseWriter, r *http.Request) {
  2860. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2861. claims, err := getTokenClaims(r)
  2862. if err != nil || claims.Username == "" {
  2863. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2864. return
  2865. }
  2866. connectionStats := common.Connections.GetStats(claims.Role)
  2867. connectionStats = append(connectionStats, getNodesConnections(claims.Username, claims.Role)...)
  2868. data := connectionsPage{
  2869. basePage: s.getBasePageData(pageConnectionsTitle, webConnectionsPath, r),
  2870. Connections: connectionStats,
  2871. }
  2872. renderAdminTemplate(w, templateConnections, data)
  2873. }
  2874. func (s *httpdServer) handleWebAddFolderGet(w http.ResponseWriter, r *http.Request) {
  2875. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2876. s.renderFolderPage(w, r, vfs.BaseVirtualFolder{}, folderPageModeAdd, "")
  2877. }
  2878. func (s *httpdServer) handleWebAddFolderPost(w http.ResponseWriter, r *http.Request) {
  2879. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2880. claims, err := getTokenClaims(r)
  2881. if err != nil || claims.Username == "" {
  2882. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2883. return
  2884. }
  2885. folder := vfs.BaseVirtualFolder{}
  2886. err = r.ParseMultipartForm(maxRequestSize)
  2887. if err != nil {
  2888. s.renderFolderPage(w, r, folder, folderPageModeAdd, err.Error())
  2889. return
  2890. }
  2891. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  2892. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2893. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2894. s.renderForbiddenPage(w, r, err.Error())
  2895. return
  2896. }
  2897. folder.MappedPath = r.Form.Get("mapped_path")
  2898. folder.Name = r.Form.Get("name")
  2899. folder.Description = r.Form.Get("description")
  2900. fsConfig, err := getFsConfigFromPostFields(r)
  2901. if err != nil {
  2902. s.renderFolderPage(w, r, folder, folderPageModeAdd, err.Error())
  2903. return
  2904. }
  2905. folder.FsConfig = fsConfig
  2906. folder = getFolderFromTemplate(folder, folder.Name)
  2907. err = dataprovider.AddFolder(&folder, claims.Username, ipAddr, claims.Role)
  2908. if err == nil {
  2909. http.Redirect(w, r, webFoldersPath, http.StatusSeeOther)
  2910. } else {
  2911. s.renderFolderPage(w, r, folder, folderPageModeAdd, err.Error())
  2912. }
  2913. }
  2914. func (s *httpdServer) handleWebUpdateFolderGet(w http.ResponseWriter, r *http.Request) {
  2915. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2916. name := getURLParam(r, "name")
  2917. folder, err := dataprovider.GetFolderByName(name)
  2918. if err == nil {
  2919. s.renderFolderPage(w, r, folder, folderPageModeUpdate, "")
  2920. } else if _, ok := err.(*util.RecordNotFoundError); ok {
  2921. s.renderNotFoundPage(w, r, err)
  2922. } else {
  2923. s.renderInternalServerErrorPage(w, r, err)
  2924. }
  2925. }
  2926. func (s *httpdServer) handleWebUpdateFolderPost(w http.ResponseWriter, r *http.Request) {
  2927. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2928. claims, err := getTokenClaims(r)
  2929. if err != nil || claims.Username == "" {
  2930. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2931. return
  2932. }
  2933. name := getURLParam(r, "name")
  2934. folder, err := dataprovider.GetFolderByName(name)
  2935. if _, ok := err.(*util.RecordNotFoundError); ok {
  2936. s.renderNotFoundPage(w, r, err)
  2937. return
  2938. } else if err != nil {
  2939. s.renderInternalServerErrorPage(w, r, err)
  2940. return
  2941. }
  2942. err = r.ParseMultipartForm(maxRequestSize)
  2943. if err != nil {
  2944. s.renderFolderPage(w, r, folder, folderPageModeUpdate, err.Error())
  2945. return
  2946. }
  2947. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  2948. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2949. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2950. s.renderForbiddenPage(w, r, err.Error())
  2951. return
  2952. }
  2953. fsConfig, err := getFsConfigFromPostFields(r)
  2954. if err != nil {
  2955. s.renderFolderPage(w, r, folder, folderPageModeUpdate, err.Error())
  2956. return
  2957. }
  2958. updatedFolder := vfs.BaseVirtualFolder{
  2959. MappedPath: r.Form.Get("mapped_path"),
  2960. Description: r.Form.Get("description"),
  2961. }
  2962. updatedFolder.ID = folder.ID
  2963. updatedFolder.Name = folder.Name
  2964. updatedFolder.FsConfig = fsConfig
  2965. updatedFolder.FsConfig.SetEmptySecretsIfNil()
  2966. updateEncryptedSecrets(&updatedFolder.FsConfig, folder.FsConfig.S3Config.AccessSecret, folder.FsConfig.AzBlobConfig.AccountKey,
  2967. folder.FsConfig.AzBlobConfig.SASURL, folder.FsConfig.GCSConfig.Credentials, folder.FsConfig.CryptConfig.Passphrase,
  2968. folder.FsConfig.SFTPConfig.Password, folder.FsConfig.SFTPConfig.PrivateKey, folder.FsConfig.SFTPConfig.KeyPassphrase,
  2969. folder.FsConfig.HTTPConfig.Password, folder.FsConfig.HTTPConfig.APIKey)
  2970. updatedFolder = getFolderFromTemplate(updatedFolder, updatedFolder.Name)
  2971. err = dataprovider.UpdateFolder(&updatedFolder, folder.Users, folder.Groups, claims.Username, ipAddr, claims.Role)
  2972. if err != nil {
  2973. s.renderFolderPage(w, r, updatedFolder, folderPageModeUpdate, err.Error())
  2974. return
  2975. }
  2976. http.Redirect(w, r, webFoldersPath, http.StatusSeeOther)
  2977. }
  2978. func (s *httpdServer) getWebVirtualFolders(w http.ResponseWriter, r *http.Request, limit int, minimal bool) ([]vfs.BaseVirtualFolder, error) {
  2979. folders := make([]vfs.BaseVirtualFolder, 0, limit)
  2980. for {
  2981. f, err := dataprovider.GetFolders(limit, len(folders), dataprovider.OrderASC, minimal)
  2982. if err != nil {
  2983. s.renderInternalServerErrorPage(w, r, err)
  2984. return folders, err
  2985. }
  2986. folders = append(folders, f...)
  2987. if len(f) < limit {
  2988. break
  2989. }
  2990. }
  2991. return folders, nil
  2992. }
  2993. func (s *httpdServer) handleWebGetFolders(w http.ResponseWriter, r *http.Request) {
  2994. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2995. limit := defaultQueryLimit
  2996. if _, ok := r.URL.Query()["qlimit"]; ok {
  2997. var err error
  2998. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  2999. if err != nil {
  3000. limit = defaultQueryLimit
  3001. }
  3002. }
  3003. folders, err := s.getWebVirtualFolders(w, r, limit, false)
  3004. if err != nil {
  3005. return
  3006. }
  3007. data := foldersPage{
  3008. basePage: s.getBasePageData(pageFoldersTitle, webFoldersPath, r),
  3009. Folders: folders,
  3010. }
  3011. renderAdminTemplate(w, templateFolders, data)
  3012. }
  3013. func (s *httpdServer) getWebGroups(w http.ResponseWriter, r *http.Request, limit int, minimal bool) ([]dataprovider.Group, error) {
  3014. groups := make([]dataprovider.Group, 0, limit)
  3015. for {
  3016. f, err := dataprovider.GetGroups(limit, len(groups), dataprovider.OrderASC, minimal)
  3017. if err != nil {
  3018. s.renderInternalServerErrorPage(w, r, err)
  3019. return groups, err
  3020. }
  3021. groups = append(groups, f...)
  3022. if len(f) < limit {
  3023. break
  3024. }
  3025. }
  3026. return groups, nil
  3027. }
  3028. func (s *httpdServer) handleWebGetGroups(w http.ResponseWriter, r *http.Request) {
  3029. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3030. limit := defaultQueryLimit
  3031. if _, ok := r.URL.Query()["qlimit"]; ok {
  3032. var err error
  3033. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  3034. if err != nil {
  3035. limit = defaultQueryLimit
  3036. }
  3037. }
  3038. groups, err := s.getWebGroups(w, r, limit, false)
  3039. if err != nil {
  3040. return
  3041. }
  3042. data := groupsPage{
  3043. basePage: s.getBasePageData(pageGroupsTitle, webGroupsPath, r),
  3044. Groups: groups,
  3045. }
  3046. renderAdminTemplate(w, templateGroups, data)
  3047. }
  3048. func (s *httpdServer) handleWebAddGroupGet(w http.ResponseWriter, r *http.Request) {
  3049. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3050. s.renderGroupPage(w, r, dataprovider.Group{}, genericPageModeAdd, "")
  3051. }
  3052. func (s *httpdServer) handleWebAddGroupPost(w http.ResponseWriter, r *http.Request) {
  3053. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3054. claims, err := getTokenClaims(r)
  3055. if err != nil || claims.Username == "" {
  3056. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3057. return
  3058. }
  3059. group, err := getGroupFromPostFields(r)
  3060. if err != nil {
  3061. s.renderGroupPage(w, r, group, genericPageModeAdd, err.Error())
  3062. return
  3063. }
  3064. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3065. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3066. s.renderForbiddenPage(w, r, err.Error())
  3067. return
  3068. }
  3069. err = dataprovider.AddGroup(&group, claims.Username, ipAddr, claims.Role)
  3070. if err != nil {
  3071. s.renderGroupPage(w, r, group, genericPageModeAdd, err.Error())
  3072. return
  3073. }
  3074. http.Redirect(w, r, webGroupsPath, http.StatusSeeOther)
  3075. }
  3076. func (s *httpdServer) handleWebUpdateGroupGet(w http.ResponseWriter, r *http.Request) {
  3077. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3078. name := getURLParam(r, "name")
  3079. group, err := dataprovider.GroupExists(name)
  3080. if err == nil {
  3081. s.renderGroupPage(w, r, group, genericPageModeUpdate, "")
  3082. } else if _, ok := err.(*util.RecordNotFoundError); ok {
  3083. s.renderNotFoundPage(w, r, err)
  3084. } else {
  3085. s.renderInternalServerErrorPage(w, r, err)
  3086. }
  3087. }
  3088. func (s *httpdServer) handleWebUpdateGroupPost(w http.ResponseWriter, r *http.Request) {
  3089. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3090. claims, err := getTokenClaims(r)
  3091. if err != nil || claims.Username == "" {
  3092. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3093. return
  3094. }
  3095. name := getURLParam(r, "name")
  3096. group, err := dataprovider.GroupExists(name)
  3097. if _, ok := err.(*util.RecordNotFoundError); ok {
  3098. s.renderNotFoundPage(w, r, err)
  3099. return
  3100. } else if err != nil {
  3101. s.renderInternalServerErrorPage(w, r, err)
  3102. return
  3103. }
  3104. updatedGroup, err := getGroupFromPostFields(r)
  3105. if err != nil {
  3106. s.renderGroupPage(w, r, group, genericPageModeUpdate, err.Error())
  3107. return
  3108. }
  3109. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3110. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3111. s.renderForbiddenPage(w, r, err.Error())
  3112. return
  3113. }
  3114. updatedGroup.ID = group.ID
  3115. updatedGroup.Name = group.Name
  3116. updatedGroup.SetEmptySecretsIfNil()
  3117. updateEncryptedSecrets(&updatedGroup.UserSettings.FsConfig, group.UserSettings.FsConfig.S3Config.AccessSecret,
  3118. group.UserSettings.FsConfig.AzBlobConfig.AccountKey, group.UserSettings.FsConfig.AzBlobConfig.SASURL,
  3119. group.UserSettings.FsConfig.GCSConfig.Credentials, group.UserSettings.FsConfig.CryptConfig.Passphrase,
  3120. group.UserSettings.FsConfig.SFTPConfig.Password, group.UserSettings.FsConfig.SFTPConfig.PrivateKey,
  3121. group.UserSettings.FsConfig.SFTPConfig.KeyPassphrase, group.UserSettings.FsConfig.HTTPConfig.Password,
  3122. group.UserSettings.FsConfig.HTTPConfig.APIKey)
  3123. err = dataprovider.UpdateGroup(&updatedGroup, group.Users, claims.Username, ipAddr, claims.Role)
  3124. if err != nil {
  3125. s.renderGroupPage(w, r, updatedGroup, genericPageModeUpdate, err.Error())
  3126. return
  3127. }
  3128. http.Redirect(w, r, webGroupsPath, http.StatusSeeOther)
  3129. }
  3130. func (s *httpdServer) getWebEventActions(w http.ResponseWriter, r *http.Request, limit int, minimal bool,
  3131. ) ([]dataprovider.BaseEventAction, error) {
  3132. actions := make([]dataprovider.BaseEventAction, 0, limit)
  3133. for {
  3134. res, err := dataprovider.GetEventActions(limit, len(actions), dataprovider.OrderASC, minimal)
  3135. if err != nil {
  3136. s.renderInternalServerErrorPage(w, r, err)
  3137. return actions, err
  3138. }
  3139. actions = append(actions, res...)
  3140. if len(res) < limit {
  3141. break
  3142. }
  3143. }
  3144. return actions, nil
  3145. }
  3146. func (s *httpdServer) handleWebGetEventActions(w http.ResponseWriter, r *http.Request) {
  3147. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3148. limit := defaultQueryLimit
  3149. if _, ok := r.URL.Query()["qlimit"]; ok {
  3150. var err error
  3151. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  3152. if err != nil {
  3153. limit = defaultQueryLimit
  3154. }
  3155. }
  3156. actions, err := s.getWebEventActions(w, r, limit, false)
  3157. if err != nil {
  3158. return
  3159. }
  3160. data := eventActionsPage{
  3161. basePage: s.getBasePageData(pageEventActionsTitle, webAdminEventActionsPath, r),
  3162. Actions: actions,
  3163. }
  3164. renderAdminTemplate(w, templateEventActions, data)
  3165. }
  3166. func (s *httpdServer) handleWebAddEventActionGet(w http.ResponseWriter, r *http.Request) {
  3167. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3168. action := dataprovider.BaseEventAction{
  3169. Type: dataprovider.ActionTypeHTTP,
  3170. }
  3171. s.renderEventActionPage(w, r, action, genericPageModeAdd, "")
  3172. }
  3173. func (s *httpdServer) handleWebAddEventActionPost(w http.ResponseWriter, r *http.Request) {
  3174. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3175. claims, err := getTokenClaims(r)
  3176. if err != nil || claims.Username == "" {
  3177. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3178. return
  3179. }
  3180. action, err := getEventActionFromPostFields(r)
  3181. if err != nil {
  3182. s.renderEventActionPage(w, r, action, genericPageModeAdd, err.Error())
  3183. return
  3184. }
  3185. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3186. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3187. s.renderForbiddenPage(w, r, err.Error())
  3188. return
  3189. }
  3190. if err = dataprovider.AddEventAction(&action, claims.Username, ipAddr, claims.Role); err != nil {
  3191. s.renderEventActionPage(w, r, action, genericPageModeAdd, err.Error())
  3192. return
  3193. }
  3194. http.Redirect(w, r, webAdminEventActionsPath, http.StatusSeeOther)
  3195. }
  3196. func (s *httpdServer) handleWebUpdateEventActionGet(w http.ResponseWriter, r *http.Request) {
  3197. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3198. name := getURLParam(r, "name")
  3199. action, err := dataprovider.EventActionExists(name)
  3200. if err == nil {
  3201. s.renderEventActionPage(w, r, action, genericPageModeUpdate, "")
  3202. } else if _, ok := err.(*util.RecordNotFoundError); ok {
  3203. s.renderNotFoundPage(w, r, err)
  3204. } else {
  3205. s.renderInternalServerErrorPage(w, r, err)
  3206. }
  3207. }
  3208. func (s *httpdServer) handleWebUpdateEventActionPost(w http.ResponseWriter, r *http.Request) {
  3209. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3210. claims, err := getTokenClaims(r)
  3211. if err != nil || claims.Username == "" {
  3212. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3213. return
  3214. }
  3215. name := getURLParam(r, "name")
  3216. action, err := dataprovider.EventActionExists(name)
  3217. if _, ok := err.(*util.RecordNotFoundError); ok {
  3218. s.renderNotFoundPage(w, r, err)
  3219. return
  3220. } else if err != nil {
  3221. s.renderInternalServerErrorPage(w, r, err)
  3222. return
  3223. }
  3224. updatedAction, err := getEventActionFromPostFields(r)
  3225. if err != nil {
  3226. s.renderEventActionPage(w, r, updatedAction, genericPageModeUpdate, err.Error())
  3227. return
  3228. }
  3229. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3230. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3231. s.renderForbiddenPage(w, r, err.Error())
  3232. return
  3233. }
  3234. updatedAction.ID = action.ID
  3235. updatedAction.Name = action.Name
  3236. updatedAction.Options.SetEmptySecretsIfNil()
  3237. switch updatedAction.Type {
  3238. case dataprovider.ActionTypeHTTP:
  3239. if updatedAction.Options.HTTPConfig.Password.IsNotPlainAndNotEmpty() {
  3240. updatedAction.Options.HTTPConfig.Password = action.Options.HTTPConfig.Password
  3241. }
  3242. }
  3243. err = dataprovider.UpdateEventAction(&updatedAction, claims.Username, ipAddr, claims.Role)
  3244. if err != nil {
  3245. s.renderEventActionPage(w, r, updatedAction, genericPageModeUpdate, err.Error())
  3246. return
  3247. }
  3248. http.Redirect(w, r, webAdminEventActionsPath, http.StatusSeeOther)
  3249. }
  3250. func (s *httpdServer) handleWebGetEventRules(w http.ResponseWriter, r *http.Request) {
  3251. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3252. limit := defaultQueryLimit
  3253. if _, ok := r.URL.Query()["qlimit"]; ok {
  3254. if lim, err := strconv.Atoi(r.URL.Query().Get("qlimit")); err == nil {
  3255. limit = lim
  3256. }
  3257. }
  3258. rules := make([]dataprovider.EventRule, 0, limit)
  3259. for {
  3260. res, err := dataprovider.GetEventRules(limit, len(rules), dataprovider.OrderASC)
  3261. if err != nil {
  3262. s.renderInternalServerErrorPage(w, r, err)
  3263. return
  3264. }
  3265. rules = append(rules, res...)
  3266. if len(res) < limit {
  3267. break
  3268. }
  3269. }
  3270. data := eventRulesPage{
  3271. basePage: s.getBasePageData(pageEventRulesTitle, webAdminEventRulesPath, r),
  3272. Rules: rules,
  3273. }
  3274. renderAdminTemplate(w, templateEventRules, data)
  3275. }
  3276. func (s *httpdServer) handleWebAddEventRuleGet(w http.ResponseWriter, r *http.Request) {
  3277. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3278. rule := dataprovider.EventRule{
  3279. Trigger: dataprovider.EventTriggerFsEvent,
  3280. }
  3281. s.renderEventRulePage(w, r, rule, genericPageModeAdd, "")
  3282. }
  3283. func (s *httpdServer) handleWebAddEventRulePost(w http.ResponseWriter, r *http.Request) {
  3284. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3285. claims, err := getTokenClaims(r)
  3286. if err != nil || claims.Username == "" {
  3287. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3288. return
  3289. }
  3290. rule, err := getEventRuleFromPostFields(r)
  3291. if err != nil {
  3292. s.renderEventRulePage(w, r, rule, genericPageModeAdd, err.Error())
  3293. return
  3294. }
  3295. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3296. err = verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr)
  3297. if err != nil {
  3298. s.renderForbiddenPage(w, r, err.Error())
  3299. return
  3300. }
  3301. if err = dataprovider.AddEventRule(&rule, claims.Username, ipAddr, claims.Role); err != nil {
  3302. s.renderEventRulePage(w, r, rule, genericPageModeAdd, err.Error())
  3303. return
  3304. }
  3305. http.Redirect(w, r, webAdminEventRulesPath, http.StatusSeeOther)
  3306. }
  3307. func (s *httpdServer) handleWebUpdateEventRuleGet(w http.ResponseWriter, r *http.Request) {
  3308. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3309. name := getURLParam(r, "name")
  3310. rule, err := dataprovider.EventRuleExists(name)
  3311. if err == nil {
  3312. s.renderEventRulePage(w, r, rule, genericPageModeUpdate, "")
  3313. } else if _, ok := err.(*util.RecordNotFoundError); ok {
  3314. s.renderNotFoundPage(w, r, err)
  3315. } else {
  3316. s.renderInternalServerErrorPage(w, r, err)
  3317. }
  3318. }
  3319. func (s *httpdServer) handleWebUpdateEventRulePost(w http.ResponseWriter, r *http.Request) {
  3320. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3321. claims, err := getTokenClaims(r)
  3322. if err != nil || claims.Username == "" {
  3323. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3324. return
  3325. }
  3326. name := getURLParam(r, "name")
  3327. rule, err := dataprovider.EventRuleExists(name)
  3328. if _, ok := err.(*util.RecordNotFoundError); ok {
  3329. s.renderNotFoundPage(w, r, err)
  3330. return
  3331. } else if err != nil {
  3332. s.renderInternalServerErrorPage(w, r, err)
  3333. return
  3334. }
  3335. updatedRule, err := getEventRuleFromPostFields(r)
  3336. if err != nil {
  3337. s.renderEventRulePage(w, r, updatedRule, genericPageModeUpdate, err.Error())
  3338. return
  3339. }
  3340. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3341. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3342. s.renderForbiddenPage(w, r, err.Error())
  3343. return
  3344. }
  3345. updatedRule.ID = rule.ID
  3346. updatedRule.Name = rule.Name
  3347. err = dataprovider.UpdateEventRule(&updatedRule, claims.Username, ipAddr, claims.Role)
  3348. if err != nil {
  3349. s.renderEventRulePage(w, r, updatedRule, genericPageModeUpdate, err.Error())
  3350. return
  3351. }
  3352. http.Redirect(w, r, webAdminEventRulesPath, http.StatusSeeOther)
  3353. }
  3354. func (s *httpdServer) getWebRoles(w http.ResponseWriter, r *http.Request, limit int, minimal bool) ([]dataprovider.Role, error) {
  3355. roles := make([]dataprovider.Role, 0, limit)
  3356. for {
  3357. res, err := dataprovider.GetRoles(limit, len(roles), dataprovider.OrderASC, minimal)
  3358. if err != nil {
  3359. s.renderInternalServerErrorPage(w, r, err)
  3360. return roles, err
  3361. }
  3362. roles = append(roles, res...)
  3363. if len(res) < limit {
  3364. break
  3365. }
  3366. }
  3367. return roles, nil
  3368. }
  3369. func (s *httpdServer) handleWebGetRoles(w http.ResponseWriter, r *http.Request) {
  3370. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3371. roles, err := s.getWebRoles(w, r, 10, false)
  3372. if err != nil {
  3373. return
  3374. }
  3375. data := rolesPage{
  3376. basePage: s.getBasePageData(pageRolesTitle, webAdminRolesPath, r),
  3377. Roles: roles,
  3378. }
  3379. renderAdminTemplate(w, templateRoles, data)
  3380. }
  3381. func (s *httpdServer) handleWebAddRoleGet(w http.ResponseWriter, r *http.Request) {
  3382. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3383. s.renderRolePage(w, r, dataprovider.Role{}, genericPageModeAdd, "")
  3384. }
  3385. func (s *httpdServer) handleWebAddRolePost(w http.ResponseWriter, r *http.Request) {
  3386. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3387. role, err := getRoleFromPostFields(r)
  3388. if err != nil {
  3389. s.renderRolePage(w, r, role, genericPageModeAdd, err.Error())
  3390. return
  3391. }
  3392. claims, err := getTokenClaims(r)
  3393. if err != nil || claims.Username == "" {
  3394. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3395. return
  3396. }
  3397. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3398. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3399. s.renderForbiddenPage(w, r, err.Error())
  3400. return
  3401. }
  3402. err = dataprovider.AddRole(&role, claims.Username, ipAddr, claims.Role)
  3403. if err != nil {
  3404. s.renderRolePage(w, r, role, genericPageModeAdd, err.Error())
  3405. return
  3406. }
  3407. http.Redirect(w, r, webAdminRolesPath, http.StatusSeeOther)
  3408. }
  3409. func (s *httpdServer) handleWebUpdateRoleGet(w http.ResponseWriter, r *http.Request) {
  3410. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3411. role, err := dataprovider.RoleExists(getURLParam(r, "name"))
  3412. if err == nil {
  3413. s.renderRolePage(w, r, role, genericPageModeUpdate, "")
  3414. } else if _, ok := err.(*util.RecordNotFoundError); ok {
  3415. s.renderNotFoundPage(w, r, err)
  3416. } else {
  3417. s.renderInternalServerErrorPage(w, r, err)
  3418. }
  3419. }
  3420. func (s *httpdServer) handleWebUpdateRolePost(w http.ResponseWriter, r *http.Request) {
  3421. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3422. claims, err := getTokenClaims(r)
  3423. if err != nil || claims.Username == "" {
  3424. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3425. return
  3426. }
  3427. role, err := dataprovider.RoleExists(getURLParam(r, "name"))
  3428. if _, ok := err.(*util.RecordNotFoundError); ok {
  3429. s.renderNotFoundPage(w, r, err)
  3430. return
  3431. } else if err != nil {
  3432. s.renderInternalServerErrorPage(w, r, err)
  3433. return
  3434. }
  3435. updatedRole, err := getRoleFromPostFields(r)
  3436. if err != nil {
  3437. s.renderRolePage(w, r, role, genericPageModeAdd, err.Error())
  3438. return
  3439. }
  3440. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3441. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3442. s.renderForbiddenPage(w, r, err.Error())
  3443. return
  3444. }
  3445. updatedRole.ID = role.ID
  3446. updatedRole.Name = role.Name
  3447. err = dataprovider.UpdateRole(&updatedRole, claims.Username, ipAddr, claims.Role)
  3448. if err != nil {
  3449. s.renderRolePage(w, r, updatedRole, genericPageModeUpdate, err.Error())
  3450. return
  3451. }
  3452. http.Redirect(w, r, webAdminRolesPath, http.StatusSeeOther)
  3453. }
  3454. func (s *httpdServer) handleWebGetEvents(w http.ResponseWriter, r *http.Request) {
  3455. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3456. data := eventsPage{
  3457. basePage: s.getBasePageData(pageEventsTitle, webEventsPath, r),
  3458. FsEventsSearchURL: webEventsFsSearchPath,
  3459. ProviderEventsSearchURL: webEventsProviderSearchPath,
  3460. }
  3461. renderAdminTemplate(w, templateEvents, data)
  3462. }