webadmin.go 121 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688
  1. // Copyright (C) 2019-2022 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. autoCredentials := r.Form.Get("gcs_auto_credentials")
  1410. if autoCredentials != "" {
  1411. config.AutomaticCredentials = 1
  1412. } else {
  1413. config.AutomaticCredentials = 0
  1414. }
  1415. credentials, _, err := r.FormFile("gcs_credential_file")
  1416. if err == http.ErrMissingFile {
  1417. return config, nil
  1418. }
  1419. if err != nil {
  1420. return config, err
  1421. }
  1422. defer credentials.Close()
  1423. fileBytes, err := io.ReadAll(credentials)
  1424. if err != nil || len(fileBytes) == 0 {
  1425. if len(fileBytes) == 0 {
  1426. err = errors.New("credentials file size must be greater than 0")
  1427. }
  1428. return config, err
  1429. }
  1430. config.Credentials = kms.NewPlainSecret(string(fileBytes))
  1431. config.AutomaticCredentials = 0
  1432. return config, err
  1433. }
  1434. func getSFTPConfig(r *http.Request) (vfs.SFTPFsConfig, error) {
  1435. var err error
  1436. config := vfs.SFTPFsConfig{}
  1437. config.Endpoint = strings.TrimSpace(r.Form.Get("sftp_endpoint"))
  1438. config.Username = r.Form.Get("sftp_username")
  1439. config.Password = getSecretFromFormField(r, "sftp_password")
  1440. config.PrivateKey = getSecretFromFormField(r, "sftp_private_key")
  1441. config.KeyPassphrase = getSecretFromFormField(r, "sftp_key_passphrase")
  1442. fingerprintsFormValue := r.Form.Get("sftp_fingerprints")
  1443. config.Fingerprints = getSliceFromDelimitedValues(fingerprintsFormValue, "\n")
  1444. config.Prefix = r.Form.Get("sftp_prefix")
  1445. config.DisableCouncurrentReads = r.Form.Get("sftp_disable_concurrent_reads") != ""
  1446. config.BufferSize, err = strconv.ParseInt(r.Form.Get("sftp_buffer_size"), 10, 64)
  1447. if r.Form.Get("sftp_equality_check_mode") != "" {
  1448. config.EqualityCheckMode = 1
  1449. } else {
  1450. config.EqualityCheckMode = 0
  1451. }
  1452. if err != nil {
  1453. return config, fmt.Errorf("invalid SFTP buffer size: %w", err)
  1454. }
  1455. return config, nil
  1456. }
  1457. func getHTTPFsConfig(r *http.Request) vfs.HTTPFsConfig {
  1458. config := vfs.HTTPFsConfig{}
  1459. config.Endpoint = strings.TrimSpace(r.Form.Get("http_endpoint"))
  1460. config.Username = r.Form.Get("http_username")
  1461. config.SkipTLSVerify = r.Form.Get("http_skip_tls_verify") != ""
  1462. config.Password = getSecretFromFormField(r, "http_password")
  1463. config.APIKey = getSecretFromFormField(r, "http_api_key")
  1464. if r.Form.Get("http_equality_check_mode") != "" {
  1465. config.EqualityCheckMode = 1
  1466. } else {
  1467. config.EqualityCheckMode = 0
  1468. }
  1469. return config
  1470. }
  1471. func getAzureConfig(r *http.Request) (vfs.AzBlobFsConfig, error) {
  1472. var err error
  1473. config := vfs.AzBlobFsConfig{}
  1474. config.Container = strings.TrimSpace(r.Form.Get("az_container"))
  1475. config.AccountName = strings.TrimSpace(r.Form.Get("az_account_name"))
  1476. config.AccountKey = getSecretFromFormField(r, "az_account_key")
  1477. config.SASURL = getSecretFromFormField(r, "az_sas_url")
  1478. config.Endpoint = strings.TrimSpace(r.Form.Get("az_endpoint"))
  1479. config.KeyPrefix = r.Form.Get("az_key_prefix")
  1480. config.AccessTier = strings.TrimSpace(r.Form.Get("az_access_tier"))
  1481. config.UseEmulator = r.Form.Get("az_use_emulator") != ""
  1482. config.UploadPartSize, err = strconv.ParseInt(r.Form.Get("az_upload_part_size"), 10, 64)
  1483. if err != nil {
  1484. return config, fmt.Errorf("invalid azure upload part size: %w", err)
  1485. }
  1486. config.UploadConcurrency, err = strconv.Atoi(r.Form.Get("az_upload_concurrency"))
  1487. if err != nil {
  1488. return config, fmt.Errorf("invalid azure upload concurrency: %w", err)
  1489. }
  1490. config.DownloadPartSize, err = strconv.ParseInt(r.Form.Get("az_download_part_size"), 10, 64)
  1491. if err != nil {
  1492. return config, fmt.Errorf("invalid azure download part size: %w", err)
  1493. }
  1494. config.DownloadConcurrency, err = strconv.Atoi(r.Form.Get("az_download_concurrency"))
  1495. if err != nil {
  1496. return config, fmt.Errorf("invalid azure download concurrency: %w", err)
  1497. }
  1498. return config, nil
  1499. }
  1500. func getFsConfigFromPostFields(r *http.Request) (vfs.Filesystem, error) {
  1501. var fs vfs.Filesystem
  1502. fs.Provider = sdk.GetProviderByName(r.Form.Get("fs_provider"))
  1503. switch fs.Provider {
  1504. case sdk.S3FilesystemProvider:
  1505. config, err := getS3Config(r)
  1506. if err != nil {
  1507. return fs, err
  1508. }
  1509. fs.S3Config = config
  1510. case sdk.AzureBlobFilesystemProvider:
  1511. config, err := getAzureConfig(r)
  1512. if err != nil {
  1513. return fs, err
  1514. }
  1515. fs.AzBlobConfig = config
  1516. case sdk.GCSFilesystemProvider:
  1517. config, err := getGCSConfig(r)
  1518. if err != nil {
  1519. return fs, err
  1520. }
  1521. fs.GCSConfig = config
  1522. case sdk.CryptedFilesystemProvider:
  1523. fs.CryptConfig.Passphrase = getSecretFromFormField(r, "crypt_passphrase")
  1524. case sdk.SFTPFilesystemProvider:
  1525. config, err := getSFTPConfig(r)
  1526. if err != nil {
  1527. return fs, err
  1528. }
  1529. fs.SFTPConfig = config
  1530. case sdk.HTTPFilesystemProvider:
  1531. fs.HTTPConfig = getHTTPFsConfig(r)
  1532. }
  1533. return fs, nil
  1534. }
  1535. func getAdminHiddenUserPageSections(r *http.Request) int {
  1536. var result int
  1537. for _, val := range r.Form["user_page_hidden_sections"] {
  1538. switch val {
  1539. case "1":
  1540. result++
  1541. case "2":
  1542. result += 2
  1543. case "3":
  1544. result += 4
  1545. case "4":
  1546. result += 8
  1547. case "5":
  1548. result += 16
  1549. case "6":
  1550. result += 32
  1551. case "7":
  1552. result += 64
  1553. }
  1554. }
  1555. return result
  1556. }
  1557. func getAdminFromPostFields(r *http.Request) (dataprovider.Admin, error) {
  1558. var admin dataprovider.Admin
  1559. err := r.ParseForm()
  1560. if err != nil {
  1561. return admin, err
  1562. }
  1563. status, err := strconv.Atoi(r.Form.Get("status"))
  1564. if err != nil {
  1565. return admin, fmt.Errorf("invalid status: %w", err)
  1566. }
  1567. admin.Username = r.Form.Get("username")
  1568. admin.Password = r.Form.Get("password")
  1569. admin.Permissions = r.Form["permissions"]
  1570. admin.Email = r.Form.Get("email")
  1571. admin.Status = status
  1572. admin.Role = r.Form.Get("role")
  1573. admin.Filters.AllowList = getSliceFromDelimitedValues(r.Form.Get("allowed_ip"), ",")
  1574. admin.Filters.AllowAPIKeyAuth = r.Form.Get("allow_api_key_auth") != ""
  1575. admin.AdditionalInfo = r.Form.Get("additional_info")
  1576. admin.Description = r.Form.Get("description")
  1577. admin.Filters.Preferences.HideUserPageSections = getAdminHiddenUserPageSections(r)
  1578. admin.Filters.Preferences.DefaultUsersExpiration = 0
  1579. if val := r.Form.Get("default_users_expiration"); val != "" {
  1580. defaultUsersExpiration, err := strconv.ParseInt(r.Form.Get("default_users_expiration"), 10, 64)
  1581. if err != nil {
  1582. return admin, fmt.Errorf("invalid default users expiration: %w", err)
  1583. }
  1584. admin.Filters.Preferences.DefaultUsersExpiration = int(defaultUsersExpiration)
  1585. }
  1586. for k := range r.Form {
  1587. if strings.HasPrefix(k, "group") {
  1588. groupName := strings.TrimSpace(r.Form.Get(k))
  1589. if groupName != "" {
  1590. idx := strings.TrimPrefix(k, "group")
  1591. addAsGroupType := r.Form.Get(fmt.Sprintf("add_as_group_type%s", idx))
  1592. group := dataprovider.AdminGroupMapping{
  1593. Name: groupName,
  1594. }
  1595. switch addAsGroupType {
  1596. case "1":
  1597. group.Options.AddToUsersAs = dataprovider.GroupAddToUsersAsPrimary
  1598. case "2":
  1599. group.Options.AddToUsersAs = dataprovider.GroupAddToUsersAsSecondary
  1600. default:
  1601. group.Options.AddToUsersAs = dataprovider.GroupAddToUsersAsMembership
  1602. }
  1603. admin.Groups = append(admin.Groups, group)
  1604. }
  1605. }
  1606. }
  1607. return admin, nil
  1608. }
  1609. func replacePlaceholders(field string, replacements map[string]string) string {
  1610. for k, v := range replacements {
  1611. field = strings.ReplaceAll(field, k, v)
  1612. }
  1613. return field
  1614. }
  1615. func getFolderFromTemplate(folder vfs.BaseVirtualFolder, name string) vfs.BaseVirtualFolder {
  1616. folder.Name = name
  1617. replacements := make(map[string]string)
  1618. replacements["%name%"] = folder.Name
  1619. folder.MappedPath = replacePlaceholders(folder.MappedPath, replacements)
  1620. folder.Description = replacePlaceholders(folder.Description, replacements)
  1621. switch folder.FsConfig.Provider {
  1622. case sdk.CryptedFilesystemProvider:
  1623. folder.FsConfig.CryptConfig = getCryptFsFromTemplate(folder.FsConfig.CryptConfig, replacements)
  1624. case sdk.S3FilesystemProvider:
  1625. folder.FsConfig.S3Config = getS3FsFromTemplate(folder.FsConfig.S3Config, replacements)
  1626. case sdk.GCSFilesystemProvider:
  1627. folder.FsConfig.GCSConfig = getGCSFsFromTemplate(folder.FsConfig.GCSConfig, replacements)
  1628. case sdk.AzureBlobFilesystemProvider:
  1629. folder.FsConfig.AzBlobConfig = getAzBlobFsFromTemplate(folder.FsConfig.AzBlobConfig, replacements)
  1630. case sdk.SFTPFilesystemProvider:
  1631. folder.FsConfig.SFTPConfig = getSFTPFsFromTemplate(folder.FsConfig.SFTPConfig, replacements)
  1632. case sdk.HTTPFilesystemProvider:
  1633. folder.FsConfig.HTTPConfig = getHTTPFsFromTemplate(folder.FsConfig.HTTPConfig, replacements)
  1634. }
  1635. return folder
  1636. }
  1637. func getCryptFsFromTemplate(fsConfig vfs.CryptFsConfig, replacements map[string]string) vfs.CryptFsConfig {
  1638. if fsConfig.Passphrase != nil {
  1639. if fsConfig.Passphrase.IsPlain() {
  1640. payload := replacePlaceholders(fsConfig.Passphrase.GetPayload(), replacements)
  1641. fsConfig.Passphrase = kms.NewPlainSecret(payload)
  1642. }
  1643. }
  1644. return fsConfig
  1645. }
  1646. func getS3FsFromTemplate(fsConfig vfs.S3FsConfig, replacements map[string]string) vfs.S3FsConfig {
  1647. fsConfig.KeyPrefix = replacePlaceholders(fsConfig.KeyPrefix, replacements)
  1648. fsConfig.AccessKey = replacePlaceholders(fsConfig.AccessKey, replacements)
  1649. if fsConfig.AccessSecret != nil && fsConfig.AccessSecret.IsPlain() {
  1650. payload := replacePlaceholders(fsConfig.AccessSecret.GetPayload(), replacements)
  1651. fsConfig.AccessSecret = kms.NewPlainSecret(payload)
  1652. }
  1653. return fsConfig
  1654. }
  1655. func getGCSFsFromTemplate(fsConfig vfs.GCSFsConfig, replacements map[string]string) vfs.GCSFsConfig {
  1656. fsConfig.KeyPrefix = replacePlaceholders(fsConfig.KeyPrefix, replacements)
  1657. return fsConfig
  1658. }
  1659. func getAzBlobFsFromTemplate(fsConfig vfs.AzBlobFsConfig, replacements map[string]string) vfs.AzBlobFsConfig {
  1660. fsConfig.KeyPrefix = replacePlaceholders(fsConfig.KeyPrefix, replacements)
  1661. fsConfig.AccountName = replacePlaceholders(fsConfig.AccountName, replacements)
  1662. if fsConfig.AccountKey != nil && fsConfig.AccountKey.IsPlain() {
  1663. payload := replacePlaceholders(fsConfig.AccountKey.GetPayload(), replacements)
  1664. fsConfig.AccountKey = kms.NewPlainSecret(payload)
  1665. }
  1666. return fsConfig
  1667. }
  1668. func getSFTPFsFromTemplate(fsConfig vfs.SFTPFsConfig, replacements map[string]string) vfs.SFTPFsConfig {
  1669. fsConfig.Prefix = replacePlaceholders(fsConfig.Prefix, replacements)
  1670. fsConfig.Username = replacePlaceholders(fsConfig.Username, replacements)
  1671. if fsConfig.Password != nil && fsConfig.Password.IsPlain() {
  1672. payload := replacePlaceholders(fsConfig.Password.GetPayload(), replacements)
  1673. fsConfig.Password = kms.NewPlainSecret(payload)
  1674. }
  1675. return fsConfig
  1676. }
  1677. func getHTTPFsFromTemplate(fsConfig vfs.HTTPFsConfig, replacements map[string]string) vfs.HTTPFsConfig {
  1678. fsConfig.Username = replacePlaceholders(fsConfig.Username, replacements)
  1679. return fsConfig
  1680. }
  1681. func getUserFromTemplate(user dataprovider.User, template userTemplateFields) dataprovider.User {
  1682. user.Username = template.Username
  1683. user.Password = template.Password
  1684. user.PublicKeys = template.PublicKeys
  1685. replacements := make(map[string]string)
  1686. replacements["%username%"] = user.Username
  1687. if user.Password != "" && !user.IsPasswordHashed() {
  1688. user.Password = replacePlaceholders(user.Password, replacements)
  1689. replacements["%password%"] = user.Password
  1690. }
  1691. user.HomeDir = replacePlaceholders(user.HomeDir, replacements)
  1692. var vfolders []vfs.VirtualFolder
  1693. for _, vfolder := range user.VirtualFolders {
  1694. vfolder.Name = replacePlaceholders(vfolder.Name, replacements)
  1695. vfolder.VirtualPath = replacePlaceholders(vfolder.VirtualPath, replacements)
  1696. vfolders = append(vfolders, vfolder)
  1697. }
  1698. user.VirtualFolders = vfolders
  1699. user.Description = replacePlaceholders(user.Description, replacements)
  1700. user.AdditionalInfo = replacePlaceholders(user.AdditionalInfo, replacements)
  1701. user.Filters.StartDirectory = replacePlaceholders(user.Filters.StartDirectory, replacements)
  1702. switch user.FsConfig.Provider {
  1703. case sdk.CryptedFilesystemProvider:
  1704. user.FsConfig.CryptConfig = getCryptFsFromTemplate(user.FsConfig.CryptConfig, replacements)
  1705. case sdk.S3FilesystemProvider:
  1706. user.FsConfig.S3Config = getS3FsFromTemplate(user.FsConfig.S3Config, replacements)
  1707. case sdk.GCSFilesystemProvider:
  1708. user.FsConfig.GCSConfig = getGCSFsFromTemplate(user.FsConfig.GCSConfig, replacements)
  1709. case sdk.AzureBlobFilesystemProvider:
  1710. user.FsConfig.AzBlobConfig = getAzBlobFsFromTemplate(user.FsConfig.AzBlobConfig, replacements)
  1711. case sdk.SFTPFilesystemProvider:
  1712. user.FsConfig.SFTPConfig = getSFTPFsFromTemplate(user.FsConfig.SFTPConfig, replacements)
  1713. case sdk.HTTPFilesystemProvider:
  1714. user.FsConfig.HTTPConfig = getHTTPFsFromTemplate(user.FsConfig.HTTPConfig, replacements)
  1715. }
  1716. return user
  1717. }
  1718. func getTransferLimits(r *http.Request) (int64, int64, int64, error) {
  1719. dataTransferUL, err := strconv.ParseInt(r.Form.Get("upload_data_transfer"), 10, 64)
  1720. if err != nil {
  1721. return 0, 0, 0, fmt.Errorf("invalid upload data transfer: %w", err)
  1722. }
  1723. dataTransferDL, err := strconv.ParseInt(r.Form.Get("download_data_transfer"), 10, 64)
  1724. if err != nil {
  1725. return 0, 0, 0, fmt.Errorf("invalid download data transfer: %w", err)
  1726. }
  1727. dataTransferTotal, err := strconv.ParseInt(r.Form.Get("total_data_transfer"), 10, 64)
  1728. if err != nil {
  1729. return 0, 0, 0, fmt.Errorf("invalid total data transfer: %w", err)
  1730. }
  1731. return dataTransferUL, dataTransferDL, dataTransferTotal, nil
  1732. }
  1733. func getQuotaLimits(r *http.Request) (int64, int, error) {
  1734. quotaSize, err := util.ParseBytes(r.Form.Get("quota_size"))
  1735. if err != nil {
  1736. return 0, 0, fmt.Errorf("invalid quota size: %w", err)
  1737. }
  1738. quotaFiles, err := strconv.Atoi(r.Form.Get("quota_files"))
  1739. if err != nil {
  1740. return 0, 0, fmt.Errorf("invalid quota files: %w", err)
  1741. }
  1742. return quotaSize, quotaFiles, nil
  1743. }
  1744. func getUserFromPostFields(r *http.Request) (dataprovider.User, error) {
  1745. user := dataprovider.User{}
  1746. err := r.ParseMultipartForm(maxRequestSize)
  1747. if err != nil {
  1748. return user, err
  1749. }
  1750. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  1751. uid, err := strconv.Atoi(r.Form.Get("uid"))
  1752. if err != nil {
  1753. return user, fmt.Errorf("invalid uid: %w", err)
  1754. }
  1755. gid, err := strconv.Atoi(r.Form.Get("gid"))
  1756. if err != nil {
  1757. return user, fmt.Errorf("invalid uid: %w", err)
  1758. }
  1759. maxSessions, err := strconv.Atoi(r.Form.Get("max_sessions"))
  1760. if err != nil {
  1761. return user, fmt.Errorf("invalid max sessions: %w", err)
  1762. }
  1763. quotaSize, quotaFiles, err := getQuotaLimits(r)
  1764. if err != nil {
  1765. return user, err
  1766. }
  1767. bandwidthUL, err := strconv.ParseInt(r.Form.Get("upload_bandwidth"), 10, 64)
  1768. if err != nil {
  1769. return user, fmt.Errorf("invalid upload bandwidth: %w", err)
  1770. }
  1771. bandwidthDL, err := strconv.ParseInt(r.Form.Get("download_bandwidth"), 10, 64)
  1772. if err != nil {
  1773. return user, fmt.Errorf("invalid download bandwidth: %w", err)
  1774. }
  1775. dataTransferUL, dataTransferDL, dataTransferTotal, err := getTransferLimits(r)
  1776. if err != nil {
  1777. return user, err
  1778. }
  1779. status, err := strconv.Atoi(r.Form.Get("status"))
  1780. if err != nil {
  1781. return user, fmt.Errorf("invalid status: %w", err)
  1782. }
  1783. expirationDateMillis := int64(0)
  1784. expirationDateString := r.Form.Get("expiration_date")
  1785. if strings.TrimSpace(expirationDateString) != "" {
  1786. expirationDate, err := time.Parse(webDateTimeFormat, expirationDateString)
  1787. if err != nil {
  1788. return user, err
  1789. }
  1790. expirationDateMillis = util.GetTimeAsMsSinceEpoch(expirationDate)
  1791. }
  1792. fsConfig, err := getFsConfigFromPostFields(r)
  1793. if err != nil {
  1794. return user, err
  1795. }
  1796. filters, err := getFiltersFromUserPostFields(r)
  1797. if err != nil {
  1798. return user, err
  1799. }
  1800. user = dataprovider.User{
  1801. BaseUser: sdk.BaseUser{
  1802. Username: r.Form.Get("username"),
  1803. Email: r.Form.Get("email"),
  1804. Password: r.Form.Get("password"),
  1805. PublicKeys: r.Form["public_keys"],
  1806. HomeDir: r.Form.Get("home_dir"),
  1807. UID: uid,
  1808. GID: gid,
  1809. Permissions: getUserPermissionsFromPostFields(r),
  1810. MaxSessions: maxSessions,
  1811. QuotaSize: quotaSize,
  1812. QuotaFiles: quotaFiles,
  1813. UploadBandwidth: bandwidthUL,
  1814. DownloadBandwidth: bandwidthDL,
  1815. UploadDataTransfer: dataTransferUL,
  1816. DownloadDataTransfer: dataTransferDL,
  1817. TotalDataTransfer: dataTransferTotal,
  1818. Status: status,
  1819. ExpirationDate: expirationDateMillis,
  1820. AdditionalInfo: r.Form.Get("additional_info"),
  1821. Description: r.Form.Get("description"),
  1822. Role: r.Form.Get("role"),
  1823. },
  1824. Filters: dataprovider.UserFilters{
  1825. BaseUserFilters: filters,
  1826. RequirePasswordChange: r.Form.Get("require_password_change") != "",
  1827. },
  1828. VirtualFolders: getVirtualFoldersFromPostFields(r),
  1829. FsConfig: fsConfig,
  1830. Groups: getGroupsFromUserPostFields(r),
  1831. }
  1832. return user, nil
  1833. }
  1834. func getGroupFromPostFields(r *http.Request) (dataprovider.Group, error) {
  1835. group := dataprovider.Group{}
  1836. err := r.ParseMultipartForm(maxRequestSize)
  1837. if err != nil {
  1838. return group, err
  1839. }
  1840. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  1841. maxSessions, err := strconv.Atoi(r.Form.Get("max_sessions"))
  1842. if err != nil {
  1843. return group, fmt.Errorf("invalid max sessions: %w", err)
  1844. }
  1845. quotaSize, quotaFiles, err := getQuotaLimits(r)
  1846. if err != nil {
  1847. return group, err
  1848. }
  1849. bandwidthUL, err := strconv.ParseInt(r.Form.Get("upload_bandwidth"), 10, 64)
  1850. if err != nil {
  1851. return group, fmt.Errorf("invalid upload bandwidth: %w", err)
  1852. }
  1853. bandwidthDL, err := strconv.ParseInt(r.Form.Get("download_bandwidth"), 10, 64)
  1854. if err != nil {
  1855. return group, fmt.Errorf("invalid download bandwidth: %w", err)
  1856. }
  1857. dataTransferUL, dataTransferDL, dataTransferTotal, err := getTransferLimits(r)
  1858. if err != nil {
  1859. return group, err
  1860. }
  1861. fsConfig, err := getFsConfigFromPostFields(r)
  1862. if err != nil {
  1863. return group, err
  1864. }
  1865. filters, err := getFiltersFromUserPostFields(r)
  1866. if err != nil {
  1867. return group, err
  1868. }
  1869. group = dataprovider.Group{
  1870. BaseGroup: sdk.BaseGroup{
  1871. Name: r.Form.Get("name"),
  1872. Description: r.Form.Get("description"),
  1873. },
  1874. UserSettings: dataprovider.GroupUserSettings{
  1875. BaseGroupUserSettings: sdk.BaseGroupUserSettings{
  1876. HomeDir: r.Form.Get("home_dir"),
  1877. MaxSessions: maxSessions,
  1878. QuotaSize: quotaSize,
  1879. QuotaFiles: quotaFiles,
  1880. Permissions: getSubDirPermissionsFromPostFields(r),
  1881. UploadBandwidth: bandwidthUL,
  1882. DownloadBandwidth: bandwidthDL,
  1883. UploadDataTransfer: dataTransferUL,
  1884. DownloadDataTransfer: dataTransferDL,
  1885. TotalDataTransfer: dataTransferTotal,
  1886. Filters: filters,
  1887. },
  1888. FsConfig: fsConfig,
  1889. },
  1890. VirtualFolders: getVirtualFoldersFromPostFields(r),
  1891. }
  1892. return group, nil
  1893. }
  1894. func getKeyValsFromPostFields(r *http.Request, key, val string) []dataprovider.KeyValue {
  1895. var res []dataprovider.KeyValue
  1896. for k := range r.Form {
  1897. if strings.HasPrefix(k, key) {
  1898. formKey := r.Form.Get(k)
  1899. idx := strings.TrimPrefix(k, key)
  1900. formVal := r.Form.Get(fmt.Sprintf("%s%s", val, idx))
  1901. if formKey != "" && formVal != "" {
  1902. res = append(res, dataprovider.KeyValue{
  1903. Key: formKey,
  1904. Value: formVal,
  1905. })
  1906. }
  1907. }
  1908. }
  1909. return res
  1910. }
  1911. func getFoldersRetentionFromPostFields(r *http.Request) ([]dataprovider.FolderRetention, error) {
  1912. var res []dataprovider.FolderRetention
  1913. for k := range r.Form {
  1914. if strings.HasPrefix(k, "folder_retention_path") {
  1915. folderPath := r.Form.Get(k)
  1916. if folderPath != "" {
  1917. idx := strings.TrimPrefix(k, "folder_retention_path")
  1918. retention, err := strconv.Atoi(r.Form.Get(fmt.Sprintf("folder_retention_val%s", idx)))
  1919. if err != nil {
  1920. return nil, fmt.Errorf("invalid retention for path %q: %w", folderPath, err)
  1921. }
  1922. options := r.Form[fmt.Sprintf("folder_retention_options%s", idx)]
  1923. res = append(res, dataprovider.FolderRetention{
  1924. Path: folderPath,
  1925. Retention: retention,
  1926. DeleteEmptyDirs: util.Contains(options, "1"),
  1927. IgnoreUserPermissions: util.Contains(options, "2"),
  1928. })
  1929. }
  1930. }
  1931. }
  1932. return res, nil
  1933. }
  1934. func getHTTPPartsFromPostFields(r *http.Request) []dataprovider.HTTPPart {
  1935. var result []dataprovider.HTTPPart
  1936. for k := range r.Form {
  1937. if strings.HasPrefix(k, "http_part_name") {
  1938. partName := r.Form.Get(k)
  1939. if partName != "" {
  1940. idx := strings.TrimPrefix(k, "http_part_name")
  1941. order, err := strconv.Atoi(idx)
  1942. if err != nil {
  1943. continue
  1944. }
  1945. filePath := r.Form.Get(fmt.Sprintf("http_part_file%s", idx))
  1946. body := r.Form.Get(fmt.Sprintf("http_part_body%s", idx))
  1947. concatHeaders := getSliceFromDelimitedValues(r.Form.Get(fmt.Sprintf("http_part_headers%s", idx)), "\n")
  1948. var headers []dataprovider.KeyValue
  1949. for _, h := range concatHeaders {
  1950. values := strings.SplitN(h, ":", 2)
  1951. if len(values) > 1 {
  1952. headers = append(headers, dataprovider.KeyValue{
  1953. Key: strings.TrimSpace(values[0]),
  1954. Value: strings.TrimSpace(values[1]),
  1955. })
  1956. }
  1957. }
  1958. result = append(result, dataprovider.HTTPPart{
  1959. Name: partName,
  1960. Filepath: filePath,
  1961. Headers: headers,
  1962. Body: body,
  1963. Order: order,
  1964. })
  1965. }
  1966. }
  1967. }
  1968. sort.Slice(result, func(i, j int) bool {
  1969. return result[i].Order < result[j].Order
  1970. })
  1971. return result
  1972. }
  1973. func getEventActionOptionsFromPostFields(r *http.Request) (dataprovider.BaseEventActionOptions, error) {
  1974. httpTimeout, err := strconv.Atoi(r.Form.Get("http_timeout"))
  1975. if err != nil {
  1976. return dataprovider.BaseEventActionOptions{}, fmt.Errorf("invalid http timeout: %w", err)
  1977. }
  1978. cmdTimeout, err := strconv.Atoi(r.Form.Get("cmd_timeout"))
  1979. if err != nil {
  1980. return dataprovider.BaseEventActionOptions{}, fmt.Errorf("invalid command timeout: %w", err)
  1981. }
  1982. foldersRetention, err := getFoldersRetentionFromPostFields(r)
  1983. if err != nil {
  1984. return dataprovider.BaseEventActionOptions{}, err
  1985. }
  1986. fsActionType, err := strconv.Atoi(r.Form.Get("fs_action_type"))
  1987. if err != nil {
  1988. return dataprovider.BaseEventActionOptions{}, fmt.Errorf("invalid fs action type: %w", err)
  1989. }
  1990. pwdExpirationThreshold, err := strconv.Atoi(r.Form.Get("pwd_expiration_threshold"))
  1991. if err != nil {
  1992. return dataprovider.BaseEventActionOptions{}, fmt.Errorf("invalid password expiration threshold: %w", err)
  1993. }
  1994. var emailAttachments []string
  1995. if r.Form.Get("email_attachments") != "" {
  1996. emailAttachments = strings.Split(strings.ReplaceAll(r.Form.Get("email_attachments"), " ", ""), ",")
  1997. }
  1998. var cmdArgs []string
  1999. if r.Form.Get("cmd_arguments") != "" {
  2000. cmdArgs = strings.Split(strings.ReplaceAll(r.Form.Get("cmd_arguments"), " ", ""), ",")
  2001. }
  2002. options := dataprovider.BaseEventActionOptions{
  2003. HTTPConfig: dataprovider.EventActionHTTPConfig{
  2004. Endpoint: r.Form.Get("http_endpoint"),
  2005. Username: r.Form.Get("http_username"),
  2006. Password: getSecretFromFormField(r, "http_password"),
  2007. Headers: getKeyValsFromPostFields(r, "http_header_key", "http_header_val"),
  2008. Timeout: httpTimeout,
  2009. SkipTLSVerify: r.Form.Get("http_skip_tls_verify") != "",
  2010. Method: r.Form.Get("http_method"),
  2011. QueryParameters: getKeyValsFromPostFields(r, "http_query_key", "http_query_val"),
  2012. Body: r.Form.Get("http_body"),
  2013. Parts: getHTTPPartsFromPostFields(r),
  2014. },
  2015. CmdConfig: dataprovider.EventActionCommandConfig{
  2016. Cmd: r.Form.Get("cmd_path"),
  2017. Args: cmdArgs,
  2018. Timeout: cmdTimeout,
  2019. EnvVars: getKeyValsFromPostFields(r, "cmd_env_key", "cmd_env_val"),
  2020. },
  2021. EmailConfig: dataprovider.EventActionEmailConfig{
  2022. Recipients: strings.Split(strings.ReplaceAll(r.Form.Get("email_recipients"), " ", ""), ","),
  2023. Subject: r.Form.Get("email_subject"),
  2024. Body: r.Form.Get("email_body"),
  2025. Attachments: emailAttachments,
  2026. },
  2027. RetentionConfig: dataprovider.EventActionDataRetentionConfig{
  2028. Folders: foldersRetention,
  2029. },
  2030. FsConfig: dataprovider.EventActionFilesystemConfig{
  2031. Type: fsActionType,
  2032. Renames: getKeyValsFromPostFields(r, "fs_rename_source", "fs_rename_target"),
  2033. Deletes: strings.Split(strings.ReplaceAll(r.Form.Get("fs_delete_paths"), " ", ""), ","),
  2034. MkDirs: strings.Split(strings.ReplaceAll(r.Form.Get("fs_mkdir_paths"), " ", ""), ","),
  2035. Exist: strings.Split(strings.ReplaceAll(r.Form.Get("fs_exist_paths"), " ", ""), ","),
  2036. Compress: dataprovider.EventActionFsCompress{
  2037. Name: r.Form.Get("fs_compress_name"),
  2038. Paths: strings.Split(strings.ReplaceAll(r.Form.Get("fs_compress_paths"), " ", ""), ","),
  2039. },
  2040. },
  2041. PwdExpirationConfig: dataprovider.EventActionPasswordExpiration{
  2042. Threshold: pwdExpirationThreshold,
  2043. },
  2044. }
  2045. return options, nil
  2046. }
  2047. func getEventActionFromPostFields(r *http.Request) (dataprovider.BaseEventAction, error) {
  2048. err := r.ParseForm()
  2049. if err != nil {
  2050. return dataprovider.BaseEventAction{}, err
  2051. }
  2052. actionType, err := strconv.Atoi(r.Form.Get("type"))
  2053. if err != nil {
  2054. return dataprovider.BaseEventAction{}, fmt.Errorf("invalid action type: %w", err)
  2055. }
  2056. options, err := getEventActionOptionsFromPostFields(r)
  2057. if err != nil {
  2058. return dataprovider.BaseEventAction{}, err
  2059. }
  2060. action := dataprovider.BaseEventAction{
  2061. Name: r.Form.Get("name"),
  2062. Description: r.Form.Get("description"),
  2063. Type: actionType,
  2064. Options: options,
  2065. }
  2066. return action, nil
  2067. }
  2068. func getEventRuleConditionsFromPostFields(r *http.Request) (dataprovider.EventConditions, error) {
  2069. var schedules []dataprovider.Schedule
  2070. var names, groupNames, roleNames, fsPaths []dataprovider.ConditionPattern
  2071. for k := range r.Form {
  2072. if strings.HasPrefix(k, "schedule_hour") {
  2073. hour := r.Form.Get(k)
  2074. if hour != "" {
  2075. idx := strings.TrimPrefix(k, "schedule_hour")
  2076. dayOfWeek := r.Form.Get(fmt.Sprintf("schedule_day_of_week%s", idx))
  2077. dayOfMonth := r.Form.Get(fmt.Sprintf("schedule_day_of_month%s", idx))
  2078. month := r.Form.Get(fmt.Sprintf("schedule_month%s", idx))
  2079. schedules = append(schedules, dataprovider.Schedule{
  2080. Hours: hour,
  2081. DayOfWeek: dayOfWeek,
  2082. DayOfMonth: dayOfMonth,
  2083. Month: month,
  2084. })
  2085. }
  2086. }
  2087. if strings.HasPrefix(k, "name_pattern") {
  2088. pattern := r.Form.Get(k)
  2089. if pattern != "" {
  2090. idx := strings.TrimPrefix(k, "name_pattern")
  2091. patternType := r.Form.Get(fmt.Sprintf("type_name_pattern%s", idx))
  2092. names = append(names, dataprovider.ConditionPattern{
  2093. Pattern: pattern,
  2094. InverseMatch: patternType == inversePatternType,
  2095. })
  2096. }
  2097. }
  2098. if strings.HasPrefix(k, "group_name_pattern") {
  2099. pattern := r.Form.Get(k)
  2100. if pattern != "" {
  2101. idx := strings.TrimPrefix(k, "group_name_pattern")
  2102. patternType := r.Form.Get(fmt.Sprintf("type_group_name_pattern%s", idx))
  2103. groupNames = append(groupNames, dataprovider.ConditionPattern{
  2104. Pattern: pattern,
  2105. InverseMatch: patternType == inversePatternType,
  2106. })
  2107. }
  2108. }
  2109. if strings.HasPrefix(k, "role_name_pattern") {
  2110. pattern := r.Form.Get(k)
  2111. if pattern != "" {
  2112. idx := strings.TrimPrefix(k, "role_name_pattern")
  2113. patternType := r.Form.Get(fmt.Sprintf("type_role_name_pattern%s", idx))
  2114. roleNames = append(roleNames, dataprovider.ConditionPattern{
  2115. Pattern: pattern,
  2116. InverseMatch: patternType == inversePatternType,
  2117. })
  2118. }
  2119. }
  2120. if strings.HasPrefix(k, "fs_path_pattern") {
  2121. pattern := r.Form.Get(k)
  2122. if pattern != "" {
  2123. idx := strings.TrimPrefix(k, "fs_path_pattern")
  2124. patternType := r.Form.Get(fmt.Sprintf("type_fs_path_pattern%s", idx))
  2125. fsPaths = append(fsPaths, dataprovider.ConditionPattern{
  2126. Pattern: pattern,
  2127. InverseMatch: patternType == inversePatternType,
  2128. })
  2129. }
  2130. }
  2131. }
  2132. minFileSize, err := util.ParseBytes(r.Form.Get("fs_min_size"))
  2133. if err != nil {
  2134. return dataprovider.EventConditions{}, fmt.Errorf("invalid min file size: %w", err)
  2135. }
  2136. maxFileSize, err := util.ParseBytes(r.Form.Get("fs_max_size"))
  2137. if err != nil {
  2138. return dataprovider.EventConditions{}, fmt.Errorf("invalid max file size: %w", err)
  2139. }
  2140. conditions := dataprovider.EventConditions{
  2141. FsEvents: r.Form["fs_events"],
  2142. ProviderEvents: r.Form["provider_events"],
  2143. Schedules: schedules,
  2144. Options: dataprovider.ConditionOptions{
  2145. Names: names,
  2146. GroupNames: groupNames,
  2147. RoleNames: roleNames,
  2148. FsPaths: fsPaths,
  2149. Protocols: r.Form["fs_protocols"],
  2150. ProviderObjects: r.Form["provider_objects"],
  2151. MinFileSize: minFileSize,
  2152. MaxFileSize: maxFileSize,
  2153. ConcurrentExecution: r.Form.Get("concurrent_execution") != "",
  2154. },
  2155. }
  2156. return conditions, nil
  2157. }
  2158. func getEventRuleActionsFromPostFields(r *http.Request) ([]dataprovider.EventAction, error) {
  2159. var actions []dataprovider.EventAction
  2160. for k := range r.Form {
  2161. if strings.HasPrefix(k, "action_name") {
  2162. name := r.Form.Get(k)
  2163. if name != "" {
  2164. idx := strings.TrimPrefix(k, "action_name")
  2165. order, err := strconv.Atoi(r.Form.Get(fmt.Sprintf("action_order%s", idx)))
  2166. if err != nil {
  2167. return actions, fmt.Errorf("invalid order: %w", err)
  2168. }
  2169. options := r.Form[fmt.Sprintf("action_options%s", idx)]
  2170. actions = append(actions, dataprovider.EventAction{
  2171. BaseEventAction: dataprovider.BaseEventAction{
  2172. Name: name,
  2173. },
  2174. Order: order + 1,
  2175. Options: dataprovider.EventActionOptions{
  2176. IsFailureAction: util.Contains(options, "1"),
  2177. StopOnFailure: util.Contains(options, "2"),
  2178. ExecuteSync: util.Contains(options, "3"),
  2179. },
  2180. })
  2181. }
  2182. }
  2183. }
  2184. return actions, nil
  2185. }
  2186. func getEventRuleFromPostFields(r *http.Request) (dataprovider.EventRule, error) {
  2187. err := r.ParseForm()
  2188. if err != nil {
  2189. return dataprovider.EventRule{}, err
  2190. }
  2191. trigger, err := strconv.Atoi(r.Form.Get("trigger"))
  2192. if err != nil {
  2193. return dataprovider.EventRule{}, fmt.Errorf("invalid trigger: %w", err)
  2194. }
  2195. conditions, err := getEventRuleConditionsFromPostFields(r)
  2196. if err != nil {
  2197. return dataprovider.EventRule{}, err
  2198. }
  2199. actions, err := getEventRuleActionsFromPostFields(r)
  2200. if err != nil {
  2201. return dataprovider.EventRule{}, err
  2202. }
  2203. rule := dataprovider.EventRule{
  2204. Name: r.Form.Get("name"),
  2205. Description: r.Form.Get("description"),
  2206. Trigger: trigger,
  2207. Conditions: conditions,
  2208. Actions: actions,
  2209. }
  2210. return rule, nil
  2211. }
  2212. func getRoleFromPostFields(r *http.Request) (dataprovider.Role, error) {
  2213. err := r.ParseForm()
  2214. if err != nil {
  2215. return dataprovider.Role{}, err
  2216. }
  2217. return dataprovider.Role{
  2218. Name: r.Form.Get("name"),
  2219. Description: r.Form.Get("description"),
  2220. }, nil
  2221. }
  2222. func (s *httpdServer) handleWebAdminForgotPwd(w http.ResponseWriter, r *http.Request) {
  2223. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2224. if !smtp.IsEnabled() {
  2225. s.renderNotFoundPage(w, r, errors.New("this page does not exist"))
  2226. return
  2227. }
  2228. s.renderForgotPwdPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr))
  2229. }
  2230. func (s *httpdServer) handleWebAdminForgotPwdPost(w http.ResponseWriter, r *http.Request) {
  2231. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2232. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2233. err := r.ParseForm()
  2234. if err != nil {
  2235. s.renderForgotPwdPage(w, err.Error(), ipAddr)
  2236. return
  2237. }
  2238. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2239. s.renderForbiddenPage(w, r, err.Error())
  2240. return
  2241. }
  2242. err = handleForgotPassword(r, r.Form.Get("username"), true)
  2243. if err != nil {
  2244. if e, ok := err.(*util.ValidationError); ok {
  2245. s.renderForgotPwdPage(w, e.GetErrorString(), ipAddr)
  2246. return
  2247. }
  2248. s.renderForgotPwdPage(w, err.Error(), ipAddr)
  2249. return
  2250. }
  2251. http.Redirect(w, r, webAdminResetPwdPath, http.StatusFound)
  2252. }
  2253. func (s *httpdServer) handleWebAdminPasswordReset(w http.ResponseWriter, r *http.Request) {
  2254. r.Body = http.MaxBytesReader(w, r.Body, maxLoginBodySize)
  2255. if !smtp.IsEnabled() {
  2256. s.renderNotFoundPage(w, r, errors.New("this page does not exist"))
  2257. return
  2258. }
  2259. s.renderResetPwdPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr))
  2260. }
  2261. func (s *httpdServer) handleWebAdminTwoFactor(w http.ResponseWriter, r *http.Request) {
  2262. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2263. s.renderTwoFactorPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr))
  2264. }
  2265. func (s *httpdServer) handleWebAdminTwoFactorRecovery(w http.ResponseWriter, r *http.Request) {
  2266. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2267. s.renderTwoFactorRecoveryPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr))
  2268. }
  2269. func (s *httpdServer) handleWebAdminMFA(w http.ResponseWriter, r *http.Request) {
  2270. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2271. s.renderMFAPage(w, r)
  2272. }
  2273. func (s *httpdServer) handleWebAdminProfile(w http.ResponseWriter, r *http.Request) {
  2274. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2275. s.renderProfilePage(w, r, "")
  2276. }
  2277. func (s *httpdServer) handleWebAdminChangePwd(w http.ResponseWriter, r *http.Request) {
  2278. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2279. s.renderChangePasswordPage(w, r, "")
  2280. }
  2281. func (s *httpdServer) handleWebAdminProfilePost(w http.ResponseWriter, r *http.Request) {
  2282. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2283. err := r.ParseForm()
  2284. if err != nil {
  2285. s.renderProfilePage(w, r, err.Error())
  2286. return
  2287. }
  2288. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2289. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2290. s.renderForbiddenPage(w, r, err.Error())
  2291. return
  2292. }
  2293. claims, err := getTokenClaims(r)
  2294. if err != nil || claims.Username == "" {
  2295. s.renderProfilePage(w, r, "Invalid token claims")
  2296. return
  2297. }
  2298. admin, err := dataprovider.AdminExists(claims.Username)
  2299. if err != nil {
  2300. s.renderProfilePage(w, r, err.Error())
  2301. return
  2302. }
  2303. admin.Filters.AllowAPIKeyAuth = r.Form.Get("allow_api_key_auth") != ""
  2304. admin.Email = r.Form.Get("email")
  2305. admin.Description = r.Form.Get("description")
  2306. err = dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, ipAddr, admin.Role)
  2307. if err != nil {
  2308. s.renderProfilePage(w, r, err.Error())
  2309. return
  2310. }
  2311. s.renderMessagePage(w, r, "Profile updated", "", http.StatusOK, nil,
  2312. "Your profile has been successfully updated")
  2313. }
  2314. func (s *httpdServer) handleWebMaintenance(w http.ResponseWriter, r *http.Request) {
  2315. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2316. s.renderMaintenancePage(w, r, "")
  2317. }
  2318. func (s *httpdServer) handleWebRestore(w http.ResponseWriter, r *http.Request) {
  2319. r.Body = http.MaxBytesReader(w, r.Body, MaxRestoreSize)
  2320. claims, err := getTokenClaims(r)
  2321. if err != nil || claims.Username == "" {
  2322. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2323. return
  2324. }
  2325. err = r.ParseMultipartForm(MaxRestoreSize)
  2326. if err != nil {
  2327. s.renderMaintenancePage(w, r, err.Error())
  2328. return
  2329. }
  2330. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  2331. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2332. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2333. s.renderForbiddenPage(w, r, err.Error())
  2334. return
  2335. }
  2336. restoreMode, err := strconv.Atoi(r.Form.Get("mode"))
  2337. if err != nil {
  2338. s.renderMaintenancePage(w, r, err.Error())
  2339. return
  2340. }
  2341. scanQuota, err := strconv.Atoi(r.Form.Get("quota"))
  2342. if err != nil {
  2343. s.renderMaintenancePage(w, r, err.Error())
  2344. return
  2345. }
  2346. backupFile, _, err := r.FormFile("backup_file")
  2347. if err != nil {
  2348. s.renderMaintenancePage(w, r, err.Error())
  2349. return
  2350. }
  2351. defer backupFile.Close()
  2352. backupContent, err := io.ReadAll(backupFile)
  2353. if err != nil || len(backupContent) == 0 {
  2354. if len(backupContent) == 0 {
  2355. err = errors.New("backup file size must be greater than 0")
  2356. }
  2357. s.renderMaintenancePage(w, r, err.Error())
  2358. return
  2359. }
  2360. if err := restoreBackup(backupContent, "", scanQuota, restoreMode, claims.Username, ipAddr, claims.Role); err != nil {
  2361. s.renderMaintenancePage(w, r, err.Error())
  2362. return
  2363. }
  2364. s.renderMessagePage(w, r, "Data restored", "", http.StatusOK, nil, "Your backup was successfully restored")
  2365. }
  2366. func (s *httpdServer) handleGetWebAdmins(w http.ResponseWriter, r *http.Request) {
  2367. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2368. limit := defaultQueryLimit
  2369. if _, ok := r.URL.Query()["qlimit"]; ok {
  2370. var err error
  2371. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  2372. if err != nil {
  2373. limit = defaultQueryLimit
  2374. }
  2375. }
  2376. admins := make([]dataprovider.Admin, 0, limit)
  2377. for {
  2378. a, err := dataprovider.GetAdmins(limit, len(admins), dataprovider.OrderASC)
  2379. if err != nil {
  2380. s.renderInternalServerErrorPage(w, r, err)
  2381. return
  2382. }
  2383. admins = append(admins, a...)
  2384. if len(a) < limit {
  2385. break
  2386. }
  2387. }
  2388. data := adminsPage{
  2389. basePage: s.getBasePageData(pageAdminsTitle, webAdminsPath, r),
  2390. Admins: admins,
  2391. }
  2392. renderAdminTemplate(w, templateAdmins, data)
  2393. }
  2394. func (s *httpdServer) handleWebAdminSetupGet(w http.ResponseWriter, r *http.Request) {
  2395. r.Body = http.MaxBytesReader(w, r.Body, maxLoginBodySize)
  2396. if dataprovider.HasAdmin() {
  2397. http.Redirect(w, r, webAdminLoginPath, http.StatusFound)
  2398. return
  2399. }
  2400. s.renderAdminSetupPage(w, r, "", "")
  2401. }
  2402. func (s *httpdServer) handleWebAddAdminGet(w http.ResponseWriter, r *http.Request) {
  2403. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2404. admin := &dataprovider.Admin{
  2405. Status: 1,
  2406. Permissions: []string{dataprovider.PermAdminAny},
  2407. }
  2408. s.renderAddUpdateAdminPage(w, r, admin, "", true)
  2409. }
  2410. func (s *httpdServer) handleWebUpdateAdminGet(w http.ResponseWriter, r *http.Request) {
  2411. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2412. username := getURLParam(r, "username")
  2413. admin, err := dataprovider.AdminExists(username)
  2414. if err == nil {
  2415. s.renderAddUpdateAdminPage(w, r, &admin, "", false)
  2416. } else if _, ok := err.(*util.RecordNotFoundError); ok {
  2417. s.renderNotFoundPage(w, r, err)
  2418. } else {
  2419. s.renderInternalServerErrorPage(w, r, err)
  2420. }
  2421. }
  2422. func (s *httpdServer) handleWebAddAdminPost(w http.ResponseWriter, r *http.Request) {
  2423. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2424. claims, err := getTokenClaims(r)
  2425. if err != nil || claims.Username == "" {
  2426. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2427. return
  2428. }
  2429. admin, err := getAdminFromPostFields(r)
  2430. if err != nil {
  2431. s.renderAddUpdateAdminPage(w, r, &admin, err.Error(), true)
  2432. return
  2433. }
  2434. if admin.Password == "" && s.binding.isWebAdminLoginFormDisabled() {
  2435. admin.Password = util.GenerateUniqueID()
  2436. }
  2437. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2438. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2439. s.renderForbiddenPage(w, r, err.Error())
  2440. return
  2441. }
  2442. err = dataprovider.AddAdmin(&admin, claims.Username, ipAddr, claims.Role)
  2443. if err != nil {
  2444. s.renderAddUpdateAdminPage(w, r, &admin, err.Error(), true)
  2445. return
  2446. }
  2447. http.Redirect(w, r, webAdminsPath, http.StatusSeeOther)
  2448. }
  2449. func (s *httpdServer) handleWebUpdateAdminPost(w http.ResponseWriter, r *http.Request) {
  2450. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2451. username := getURLParam(r, "username")
  2452. admin, err := dataprovider.AdminExists(username)
  2453. if _, ok := err.(*util.RecordNotFoundError); ok {
  2454. s.renderNotFoundPage(w, r, err)
  2455. return
  2456. } else if err != nil {
  2457. s.renderInternalServerErrorPage(w, r, err)
  2458. return
  2459. }
  2460. updatedAdmin, err := getAdminFromPostFields(r)
  2461. if err != nil {
  2462. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, err.Error(), false)
  2463. return
  2464. }
  2465. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2466. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2467. s.renderForbiddenPage(w, r, err.Error())
  2468. return
  2469. }
  2470. updatedAdmin.ID = admin.ID
  2471. updatedAdmin.Username = admin.Username
  2472. if updatedAdmin.Password == "" {
  2473. updatedAdmin.Password = admin.Password
  2474. }
  2475. updatedAdmin.Filters.TOTPConfig = admin.Filters.TOTPConfig
  2476. updatedAdmin.Filters.RecoveryCodes = admin.Filters.RecoveryCodes
  2477. claims, err := getTokenClaims(r)
  2478. if err != nil || claims.Username == "" {
  2479. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, "Invalid token claims", false)
  2480. return
  2481. }
  2482. if username == claims.Username {
  2483. if claims.isCriticalPermRemoved(updatedAdmin.Permissions) {
  2484. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, "You cannot remove these permissions to yourself", false)
  2485. return
  2486. }
  2487. if updatedAdmin.Status == 0 {
  2488. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, "You cannot disable yourself", false)
  2489. return
  2490. }
  2491. if updatedAdmin.Role != claims.Role {
  2492. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, "You cannot add/change your role", false)
  2493. return
  2494. }
  2495. }
  2496. err = dataprovider.UpdateAdmin(&updatedAdmin, claims.Username, ipAddr, claims.Role)
  2497. if err != nil {
  2498. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, err.Error(), false)
  2499. return
  2500. }
  2501. http.Redirect(w, r, webAdminsPath, http.StatusSeeOther)
  2502. }
  2503. func (s *httpdServer) handleWebDefenderPage(w http.ResponseWriter, r *http.Request) {
  2504. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2505. data := defenderHostsPage{
  2506. basePage: s.getBasePageData(pageDefenderTitle, webDefenderPath, r),
  2507. DefenderHostsURL: webDefenderHostsPath,
  2508. }
  2509. renderAdminTemplate(w, templateDefender, data)
  2510. }
  2511. func (s *httpdServer) handleGetWebUsers(w http.ResponseWriter, r *http.Request) {
  2512. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2513. claims, err := getTokenClaims(r)
  2514. if err != nil || claims.Username == "" {
  2515. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2516. return
  2517. }
  2518. var limit int
  2519. if _, ok := r.URL.Query()["qlimit"]; ok {
  2520. var err error
  2521. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  2522. if err != nil {
  2523. limit = defaultQueryLimit
  2524. }
  2525. } else {
  2526. limit = defaultQueryLimit
  2527. }
  2528. users := make([]dataprovider.User, 0, limit)
  2529. for {
  2530. u, err := dataprovider.GetUsers(limit, len(users), dataprovider.OrderASC, claims.Role)
  2531. if err != nil {
  2532. s.renderInternalServerErrorPage(w, r, err)
  2533. return
  2534. }
  2535. users = append(users, u...)
  2536. if len(u) < limit {
  2537. break
  2538. }
  2539. }
  2540. data := usersPage{
  2541. basePage: s.getBasePageData(pageUsersTitle, webUsersPath, r),
  2542. Users: users,
  2543. }
  2544. renderAdminTemplate(w, templateUsers, data)
  2545. }
  2546. func (s *httpdServer) handleWebTemplateFolderGet(w http.ResponseWriter, r *http.Request) {
  2547. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2548. if r.URL.Query().Get("from") != "" {
  2549. name := r.URL.Query().Get("from")
  2550. folder, err := dataprovider.GetFolderByName(name)
  2551. if err == nil {
  2552. folder.FsConfig.SetEmptySecrets()
  2553. s.renderFolderPage(w, r, folder, folderPageModeTemplate, "")
  2554. } else if _, ok := err.(*util.RecordNotFoundError); ok {
  2555. s.renderNotFoundPage(w, r, err)
  2556. } else {
  2557. s.renderInternalServerErrorPage(w, r, err)
  2558. }
  2559. } else {
  2560. folder := vfs.BaseVirtualFolder{}
  2561. s.renderFolderPage(w, r, folder, folderPageModeTemplate, "")
  2562. }
  2563. }
  2564. func (s *httpdServer) handleWebTemplateFolderPost(w http.ResponseWriter, r *http.Request) {
  2565. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2566. claims, err := getTokenClaims(r)
  2567. if err != nil || claims.Username == "" {
  2568. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2569. return
  2570. }
  2571. templateFolder := vfs.BaseVirtualFolder{}
  2572. err = r.ParseMultipartForm(maxRequestSize)
  2573. if err != nil {
  2574. s.renderMessagePage(w, r, "Error parsing folders fields", "", http.StatusBadRequest, err, "")
  2575. return
  2576. }
  2577. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  2578. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2579. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2580. s.renderForbiddenPage(w, r, err.Error())
  2581. return
  2582. }
  2583. templateFolder.MappedPath = r.Form.Get("mapped_path")
  2584. templateFolder.Description = r.Form.Get("description")
  2585. fsConfig, err := getFsConfigFromPostFields(r)
  2586. if err != nil {
  2587. s.renderMessagePage(w, r, "Error parsing folders fields", "", http.StatusBadRequest, err, "")
  2588. return
  2589. }
  2590. templateFolder.FsConfig = fsConfig
  2591. var dump dataprovider.BackupData
  2592. dump.Version = dataprovider.DumpVersion
  2593. foldersFields := getFoldersForTemplate(r)
  2594. for _, tmpl := range foldersFields {
  2595. f := getFolderFromTemplate(templateFolder, tmpl)
  2596. if err := dataprovider.ValidateFolder(&f); err != nil {
  2597. s.renderMessagePage(w, r, "Folder validation error", fmt.Sprintf("Error validating folder %#v", f.Name),
  2598. http.StatusBadRequest, err, "")
  2599. return
  2600. }
  2601. dump.Folders = append(dump.Folders, f)
  2602. }
  2603. if len(dump.Folders) == 0 {
  2604. s.renderMessagePage(w, r, "No folders defined", "No valid folders defined, unable to complete the requested action",
  2605. http.StatusBadRequest, nil, "")
  2606. return
  2607. }
  2608. if r.Form.Get("form_action") == "export_from_template" {
  2609. w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"sftpgo-%v-folders-from-template.json\"",
  2610. len(dump.Folders)))
  2611. render.JSON(w, r, dump)
  2612. return
  2613. }
  2614. if err = RestoreFolders(dump.Folders, "", 1, 0, claims.Username, ipAddr, claims.Role); err != nil {
  2615. s.renderMessagePage(w, r, "Unable to save folders", "Cannot save the defined folders:",
  2616. getRespStatus(err), err, "")
  2617. return
  2618. }
  2619. http.Redirect(w, r, webFoldersPath, http.StatusSeeOther)
  2620. }
  2621. func (s *httpdServer) handleWebTemplateUserGet(w http.ResponseWriter, r *http.Request) {
  2622. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2623. tokenAdmin := getAdminFromToken(r)
  2624. admin, err := dataprovider.AdminExists(tokenAdmin.Username)
  2625. if err != nil {
  2626. s.renderInternalServerErrorPage(w, r, fmt.Errorf("unable to get the admin %q: %w", tokenAdmin.Username, err))
  2627. return
  2628. }
  2629. if r.URL.Query().Get("from") != "" {
  2630. username := r.URL.Query().Get("from")
  2631. user, err := dataprovider.UserExists(username, admin.Role)
  2632. if err == nil {
  2633. user.SetEmptySecrets()
  2634. user.PublicKeys = nil
  2635. user.Email = ""
  2636. user.Description = ""
  2637. if user.ExpirationDate == 0 && admin.Filters.Preferences.DefaultUsersExpiration > 0 {
  2638. user.ExpirationDate = util.GetTimeAsMsSinceEpoch(time.Now().Add(24 * time.Hour * time.Duration(admin.Filters.Preferences.DefaultUsersExpiration)))
  2639. }
  2640. s.renderUserPage(w, r, &user, userPageModeTemplate, "", &admin)
  2641. } else if _, ok := err.(*util.RecordNotFoundError); ok {
  2642. s.renderNotFoundPage(w, r, err)
  2643. } else {
  2644. s.renderInternalServerErrorPage(w, r, err)
  2645. }
  2646. } else {
  2647. user := dataprovider.User{BaseUser: sdk.BaseUser{
  2648. Status: 1,
  2649. Permissions: map[string][]string{
  2650. "/": {dataprovider.PermAny},
  2651. },
  2652. }}
  2653. if admin.Filters.Preferences.DefaultUsersExpiration > 0 {
  2654. user.ExpirationDate = util.GetTimeAsMsSinceEpoch(time.Now().Add(24 * time.Hour * time.Duration(admin.Filters.Preferences.DefaultUsersExpiration)))
  2655. }
  2656. s.renderUserPage(w, r, &user, userPageModeTemplate, "", &admin)
  2657. }
  2658. }
  2659. func (s *httpdServer) handleWebTemplateUserPost(w http.ResponseWriter, r *http.Request) {
  2660. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2661. claims, err := getTokenClaims(r)
  2662. if err != nil || claims.Username == "" {
  2663. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2664. return
  2665. }
  2666. templateUser, err := getUserFromPostFields(r)
  2667. if err != nil {
  2668. s.renderMessagePage(w, r, "Error parsing user fields", "", http.StatusBadRequest, err, "")
  2669. return
  2670. }
  2671. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2672. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2673. s.renderForbiddenPage(w, r, err.Error())
  2674. return
  2675. }
  2676. var dump dataprovider.BackupData
  2677. dump.Version = dataprovider.DumpVersion
  2678. userTmplFields := getUsersForTemplate(r)
  2679. for _, tmpl := range userTmplFields {
  2680. u := getUserFromTemplate(templateUser, tmpl)
  2681. if err := dataprovider.ValidateUser(&u); err != nil {
  2682. s.renderMessagePage(w, r, "User validation error", fmt.Sprintf("Error validating user %#v", u.Username),
  2683. http.StatusBadRequest, err, "")
  2684. return
  2685. }
  2686. // to create a template the "manage_system" permission is required, so role admins cannot use
  2687. // this method, we don't need to force the role
  2688. dump.Users = append(dump.Users, u)
  2689. for _, folder := range u.VirtualFolders {
  2690. if !dump.HasFolder(folder.Name) {
  2691. dump.Folders = append(dump.Folders, folder.BaseVirtualFolder)
  2692. }
  2693. }
  2694. }
  2695. if len(dump.Users) == 0 {
  2696. s.renderMessagePage(w, r, "No users defined", "No valid users defined, unable to complete the requested action",
  2697. http.StatusBadRequest, nil, "")
  2698. return
  2699. }
  2700. if r.Form.Get("form_action") == "export_from_template" {
  2701. w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"sftpgo-%v-users-from-template.json\"",
  2702. len(dump.Users)))
  2703. render.JSON(w, r, dump)
  2704. return
  2705. }
  2706. if err = RestoreUsers(dump.Users, "", 1, 0, claims.Username, ipAddr, claims.Role); err != nil {
  2707. s.renderMessagePage(w, r, "Unable to save users", "Cannot save the defined users:",
  2708. getRespStatus(err), err, "")
  2709. return
  2710. }
  2711. http.Redirect(w, r, webUsersPath, http.StatusSeeOther)
  2712. }
  2713. func (s *httpdServer) handleWebAddUserGet(w http.ResponseWriter, r *http.Request) {
  2714. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2715. tokenAdmin := getAdminFromToken(r)
  2716. admin, err := dataprovider.AdminExists(tokenAdmin.Username)
  2717. if err != nil {
  2718. s.renderInternalServerErrorPage(w, r, fmt.Errorf("unable to get the admin %q: %w", tokenAdmin.Username, err))
  2719. return
  2720. }
  2721. user := dataprovider.User{BaseUser: sdk.BaseUser{
  2722. Status: 1,
  2723. Permissions: map[string][]string{
  2724. "/": {dataprovider.PermAny},
  2725. }},
  2726. }
  2727. if admin.Filters.Preferences.DefaultUsersExpiration > 0 {
  2728. user.ExpirationDate = util.GetTimeAsMsSinceEpoch(time.Now().Add(24 * time.Hour * time.Duration(admin.Filters.Preferences.DefaultUsersExpiration)))
  2729. }
  2730. s.renderUserPage(w, r, &user, userPageModeAdd, "", &admin)
  2731. }
  2732. func (s *httpdServer) handleWebUpdateUserGet(w http.ResponseWriter, r *http.Request) {
  2733. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2734. claims, err := getTokenClaims(r)
  2735. if err != nil || claims.Username == "" {
  2736. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2737. return
  2738. }
  2739. username := getURLParam(r, "username")
  2740. user, err := dataprovider.UserExists(username, claims.Role)
  2741. if err == nil {
  2742. s.renderUserPage(w, r, &user, userPageModeUpdate, "", nil)
  2743. } else if _, ok := err.(*util.RecordNotFoundError); ok {
  2744. s.renderNotFoundPage(w, r, err)
  2745. } else {
  2746. s.renderInternalServerErrorPage(w, r, err)
  2747. }
  2748. }
  2749. func (s *httpdServer) handleWebAddUserPost(w http.ResponseWriter, r *http.Request) {
  2750. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2751. claims, err := getTokenClaims(r)
  2752. if err != nil || claims.Username == "" {
  2753. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2754. return
  2755. }
  2756. user, err := getUserFromPostFields(r)
  2757. if err != nil {
  2758. s.renderUserPage(w, r, &user, userPageModeAdd, err.Error(), nil)
  2759. return
  2760. }
  2761. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2762. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2763. s.renderForbiddenPage(w, r, err.Error())
  2764. return
  2765. }
  2766. user = getUserFromTemplate(user, userTemplateFields{
  2767. Username: user.Username,
  2768. Password: user.Password,
  2769. PublicKeys: user.PublicKeys,
  2770. })
  2771. if claims.Role != "" {
  2772. user.Role = claims.Role
  2773. }
  2774. user.Filters.RecoveryCodes = nil
  2775. user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
  2776. Enabled: false,
  2777. }
  2778. err = dataprovider.AddUser(&user, claims.Username, ipAddr, claims.Role)
  2779. if err != nil {
  2780. s.renderUserPage(w, r, &user, userPageModeAdd, err.Error(), nil)
  2781. return
  2782. }
  2783. http.Redirect(w, r, webUsersPath, http.StatusSeeOther)
  2784. }
  2785. func (s *httpdServer) handleWebUpdateUserPost(w http.ResponseWriter, r *http.Request) {
  2786. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2787. claims, err := getTokenClaims(r)
  2788. if err != nil || claims.Username == "" {
  2789. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2790. return
  2791. }
  2792. username := getURLParam(r, "username")
  2793. user, err := dataprovider.UserExists(username, claims.Role)
  2794. if _, ok := err.(*util.RecordNotFoundError); ok {
  2795. s.renderNotFoundPage(w, r, err)
  2796. return
  2797. } else if err != nil {
  2798. s.renderInternalServerErrorPage(w, r, err)
  2799. return
  2800. }
  2801. updatedUser, err := getUserFromPostFields(r)
  2802. if err != nil {
  2803. s.renderUserPage(w, r, &user, userPageModeUpdate, err.Error(), nil)
  2804. return
  2805. }
  2806. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2807. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2808. s.renderForbiddenPage(w, r, err.Error())
  2809. return
  2810. }
  2811. updatedUser.ID = user.ID
  2812. updatedUser.Username = user.Username
  2813. updatedUser.Filters.RecoveryCodes = user.Filters.RecoveryCodes
  2814. updatedUser.Filters.TOTPConfig = user.Filters.TOTPConfig
  2815. updatedUser.LastPasswordChange = user.LastPasswordChange
  2816. updatedUser.SetEmptySecretsIfNil()
  2817. if updatedUser.Password == redactedSecret {
  2818. updatedUser.Password = user.Password
  2819. }
  2820. updateEncryptedSecrets(&updatedUser.FsConfig, user.FsConfig.S3Config.AccessSecret, user.FsConfig.AzBlobConfig.AccountKey,
  2821. user.FsConfig.AzBlobConfig.SASURL, user.FsConfig.GCSConfig.Credentials, user.FsConfig.CryptConfig.Passphrase,
  2822. user.FsConfig.SFTPConfig.Password, user.FsConfig.SFTPConfig.PrivateKey, user.FsConfig.SFTPConfig.KeyPassphrase,
  2823. user.FsConfig.HTTPConfig.Password, user.FsConfig.HTTPConfig.APIKey)
  2824. updatedUser = getUserFromTemplate(updatedUser, userTemplateFields{
  2825. Username: updatedUser.Username,
  2826. Password: updatedUser.Password,
  2827. PublicKeys: updatedUser.PublicKeys,
  2828. })
  2829. if claims.Role != "" {
  2830. updatedUser.Role = claims.Role
  2831. }
  2832. err = dataprovider.UpdateUser(&updatedUser, claims.Username, ipAddr, claims.Role)
  2833. if err != nil {
  2834. s.renderUserPage(w, r, &updatedUser, userPageModeUpdate, err.Error(), nil)
  2835. return
  2836. }
  2837. if r.Form.Get("disconnect") != "" {
  2838. disconnectUser(user.Username)
  2839. }
  2840. http.Redirect(w, r, webUsersPath, http.StatusSeeOther)
  2841. }
  2842. func (s *httpdServer) handleWebGetStatus(w http.ResponseWriter, r *http.Request) {
  2843. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2844. data := statusPage{
  2845. basePage: s.getBasePageData(pageStatusTitle, webStatusPath, r),
  2846. Status: getServicesStatus(),
  2847. }
  2848. renderAdminTemplate(w, templateStatus, data)
  2849. }
  2850. func (s *httpdServer) handleWebGetConnections(w http.ResponseWriter, r *http.Request) {
  2851. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2852. claims, err := getTokenClaims(r)
  2853. if err != nil || claims.Username == "" {
  2854. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2855. return
  2856. }
  2857. connectionStats := common.Connections.GetStats(claims.Role)
  2858. connectionStats = append(connectionStats, getNodesConnections(claims.Username, claims.Role)...)
  2859. data := connectionsPage{
  2860. basePage: s.getBasePageData(pageConnectionsTitle, webConnectionsPath, r),
  2861. Connections: connectionStats,
  2862. }
  2863. renderAdminTemplate(w, templateConnections, data)
  2864. }
  2865. func (s *httpdServer) handleWebAddFolderGet(w http.ResponseWriter, r *http.Request) {
  2866. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2867. s.renderFolderPage(w, r, vfs.BaseVirtualFolder{}, folderPageModeAdd, "")
  2868. }
  2869. func (s *httpdServer) handleWebAddFolderPost(w http.ResponseWriter, r *http.Request) {
  2870. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2871. claims, err := getTokenClaims(r)
  2872. if err != nil || claims.Username == "" {
  2873. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2874. return
  2875. }
  2876. folder := vfs.BaseVirtualFolder{}
  2877. err = r.ParseMultipartForm(maxRequestSize)
  2878. if err != nil {
  2879. s.renderFolderPage(w, r, folder, folderPageModeAdd, err.Error())
  2880. return
  2881. }
  2882. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  2883. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2884. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2885. s.renderForbiddenPage(w, r, err.Error())
  2886. return
  2887. }
  2888. folder.MappedPath = r.Form.Get("mapped_path")
  2889. folder.Name = r.Form.Get("name")
  2890. folder.Description = r.Form.Get("description")
  2891. fsConfig, err := getFsConfigFromPostFields(r)
  2892. if err != nil {
  2893. s.renderFolderPage(w, r, folder, folderPageModeAdd, err.Error())
  2894. return
  2895. }
  2896. folder.FsConfig = fsConfig
  2897. folder = getFolderFromTemplate(folder, folder.Name)
  2898. err = dataprovider.AddFolder(&folder, claims.Username, ipAddr, claims.Role)
  2899. if err == nil {
  2900. http.Redirect(w, r, webFoldersPath, http.StatusSeeOther)
  2901. } else {
  2902. s.renderFolderPage(w, r, folder, folderPageModeAdd, err.Error())
  2903. }
  2904. }
  2905. func (s *httpdServer) handleWebUpdateFolderGet(w http.ResponseWriter, r *http.Request) {
  2906. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2907. name := getURLParam(r, "name")
  2908. folder, err := dataprovider.GetFolderByName(name)
  2909. if err == nil {
  2910. s.renderFolderPage(w, r, folder, folderPageModeUpdate, "")
  2911. } else if _, ok := err.(*util.RecordNotFoundError); ok {
  2912. s.renderNotFoundPage(w, r, err)
  2913. } else {
  2914. s.renderInternalServerErrorPage(w, r, err)
  2915. }
  2916. }
  2917. func (s *httpdServer) handleWebUpdateFolderPost(w http.ResponseWriter, r *http.Request) {
  2918. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2919. claims, err := getTokenClaims(r)
  2920. if err != nil || claims.Username == "" {
  2921. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2922. return
  2923. }
  2924. name := getURLParam(r, "name")
  2925. folder, err := dataprovider.GetFolderByName(name)
  2926. if _, ok := err.(*util.RecordNotFoundError); ok {
  2927. s.renderNotFoundPage(w, r, err)
  2928. return
  2929. } else if err != nil {
  2930. s.renderInternalServerErrorPage(w, r, err)
  2931. return
  2932. }
  2933. err = r.ParseMultipartForm(maxRequestSize)
  2934. if err != nil {
  2935. s.renderFolderPage(w, r, folder, folderPageModeUpdate, err.Error())
  2936. return
  2937. }
  2938. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  2939. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2940. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2941. s.renderForbiddenPage(w, r, err.Error())
  2942. return
  2943. }
  2944. fsConfig, err := getFsConfigFromPostFields(r)
  2945. if err != nil {
  2946. s.renderFolderPage(w, r, folder, folderPageModeUpdate, err.Error())
  2947. return
  2948. }
  2949. updatedFolder := vfs.BaseVirtualFolder{
  2950. MappedPath: r.Form.Get("mapped_path"),
  2951. Description: r.Form.Get("description"),
  2952. }
  2953. updatedFolder.ID = folder.ID
  2954. updatedFolder.Name = folder.Name
  2955. updatedFolder.FsConfig = fsConfig
  2956. updatedFolder.FsConfig.SetEmptySecretsIfNil()
  2957. updateEncryptedSecrets(&updatedFolder.FsConfig, folder.FsConfig.S3Config.AccessSecret, folder.FsConfig.AzBlobConfig.AccountKey,
  2958. folder.FsConfig.AzBlobConfig.SASURL, folder.FsConfig.GCSConfig.Credentials, folder.FsConfig.CryptConfig.Passphrase,
  2959. folder.FsConfig.SFTPConfig.Password, folder.FsConfig.SFTPConfig.PrivateKey, folder.FsConfig.SFTPConfig.KeyPassphrase,
  2960. folder.FsConfig.HTTPConfig.Password, folder.FsConfig.HTTPConfig.APIKey)
  2961. updatedFolder = getFolderFromTemplate(updatedFolder, updatedFolder.Name)
  2962. err = dataprovider.UpdateFolder(&updatedFolder, folder.Users, folder.Groups, claims.Username, ipAddr, claims.Role)
  2963. if err != nil {
  2964. s.renderFolderPage(w, r, updatedFolder, folderPageModeUpdate, err.Error())
  2965. return
  2966. }
  2967. http.Redirect(w, r, webFoldersPath, http.StatusSeeOther)
  2968. }
  2969. func (s *httpdServer) getWebVirtualFolders(w http.ResponseWriter, r *http.Request, limit int, minimal bool) ([]vfs.BaseVirtualFolder, error) {
  2970. folders := make([]vfs.BaseVirtualFolder, 0, limit)
  2971. for {
  2972. f, err := dataprovider.GetFolders(limit, len(folders), dataprovider.OrderASC, minimal)
  2973. if err != nil {
  2974. s.renderInternalServerErrorPage(w, r, err)
  2975. return folders, err
  2976. }
  2977. folders = append(folders, f...)
  2978. if len(f) < limit {
  2979. break
  2980. }
  2981. }
  2982. return folders, nil
  2983. }
  2984. func (s *httpdServer) handleWebGetFolders(w http.ResponseWriter, r *http.Request) {
  2985. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2986. limit := defaultQueryLimit
  2987. if _, ok := r.URL.Query()["qlimit"]; ok {
  2988. var err error
  2989. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  2990. if err != nil {
  2991. limit = defaultQueryLimit
  2992. }
  2993. }
  2994. folders, err := s.getWebVirtualFolders(w, r, limit, false)
  2995. if err != nil {
  2996. return
  2997. }
  2998. data := foldersPage{
  2999. basePage: s.getBasePageData(pageFoldersTitle, webFoldersPath, r),
  3000. Folders: folders,
  3001. }
  3002. renderAdminTemplate(w, templateFolders, data)
  3003. }
  3004. func (s *httpdServer) getWebGroups(w http.ResponseWriter, r *http.Request, limit int, minimal bool) ([]dataprovider.Group, error) {
  3005. groups := make([]dataprovider.Group, 0, limit)
  3006. for {
  3007. f, err := dataprovider.GetGroups(limit, len(groups), dataprovider.OrderASC, minimal)
  3008. if err != nil {
  3009. s.renderInternalServerErrorPage(w, r, err)
  3010. return groups, err
  3011. }
  3012. groups = append(groups, f...)
  3013. if len(f) < limit {
  3014. break
  3015. }
  3016. }
  3017. return groups, nil
  3018. }
  3019. func (s *httpdServer) handleWebGetGroups(w http.ResponseWriter, r *http.Request) {
  3020. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3021. limit := defaultQueryLimit
  3022. if _, ok := r.URL.Query()["qlimit"]; ok {
  3023. var err error
  3024. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  3025. if err != nil {
  3026. limit = defaultQueryLimit
  3027. }
  3028. }
  3029. groups, err := s.getWebGroups(w, r, limit, false)
  3030. if err != nil {
  3031. return
  3032. }
  3033. data := groupsPage{
  3034. basePage: s.getBasePageData(pageGroupsTitle, webGroupsPath, r),
  3035. Groups: groups,
  3036. }
  3037. renderAdminTemplate(w, templateGroups, data)
  3038. }
  3039. func (s *httpdServer) handleWebAddGroupGet(w http.ResponseWriter, r *http.Request) {
  3040. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3041. s.renderGroupPage(w, r, dataprovider.Group{}, genericPageModeAdd, "")
  3042. }
  3043. func (s *httpdServer) handleWebAddGroupPost(w http.ResponseWriter, r *http.Request) {
  3044. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3045. claims, err := getTokenClaims(r)
  3046. if err != nil || claims.Username == "" {
  3047. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3048. return
  3049. }
  3050. group, err := getGroupFromPostFields(r)
  3051. if err != nil {
  3052. s.renderGroupPage(w, r, group, genericPageModeAdd, err.Error())
  3053. return
  3054. }
  3055. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3056. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3057. s.renderForbiddenPage(w, r, err.Error())
  3058. return
  3059. }
  3060. err = dataprovider.AddGroup(&group, claims.Username, ipAddr, claims.Role)
  3061. if err != nil {
  3062. s.renderGroupPage(w, r, group, genericPageModeAdd, err.Error())
  3063. return
  3064. }
  3065. http.Redirect(w, r, webGroupsPath, http.StatusSeeOther)
  3066. }
  3067. func (s *httpdServer) handleWebUpdateGroupGet(w http.ResponseWriter, r *http.Request) {
  3068. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3069. name := getURLParam(r, "name")
  3070. group, err := dataprovider.GroupExists(name)
  3071. if err == nil {
  3072. s.renderGroupPage(w, r, group, genericPageModeUpdate, "")
  3073. } else if _, ok := err.(*util.RecordNotFoundError); ok {
  3074. s.renderNotFoundPage(w, r, err)
  3075. } else {
  3076. s.renderInternalServerErrorPage(w, r, err)
  3077. }
  3078. }
  3079. func (s *httpdServer) handleWebUpdateGroupPost(w http.ResponseWriter, r *http.Request) {
  3080. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3081. claims, err := getTokenClaims(r)
  3082. if err != nil || claims.Username == "" {
  3083. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3084. return
  3085. }
  3086. name := getURLParam(r, "name")
  3087. group, err := dataprovider.GroupExists(name)
  3088. if _, ok := err.(*util.RecordNotFoundError); ok {
  3089. s.renderNotFoundPage(w, r, err)
  3090. return
  3091. } else if err != nil {
  3092. s.renderInternalServerErrorPage(w, r, err)
  3093. return
  3094. }
  3095. updatedGroup, err := getGroupFromPostFields(r)
  3096. if err != nil {
  3097. s.renderGroupPage(w, r, group, genericPageModeUpdate, err.Error())
  3098. return
  3099. }
  3100. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3101. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3102. s.renderForbiddenPage(w, r, err.Error())
  3103. return
  3104. }
  3105. updatedGroup.ID = group.ID
  3106. updatedGroup.Name = group.Name
  3107. updatedGroup.SetEmptySecretsIfNil()
  3108. updateEncryptedSecrets(&updatedGroup.UserSettings.FsConfig, group.UserSettings.FsConfig.S3Config.AccessSecret,
  3109. group.UserSettings.FsConfig.AzBlobConfig.AccountKey, group.UserSettings.FsConfig.AzBlobConfig.SASURL,
  3110. group.UserSettings.FsConfig.GCSConfig.Credentials, group.UserSettings.FsConfig.CryptConfig.Passphrase,
  3111. group.UserSettings.FsConfig.SFTPConfig.Password, group.UserSettings.FsConfig.SFTPConfig.PrivateKey,
  3112. group.UserSettings.FsConfig.SFTPConfig.KeyPassphrase, group.UserSettings.FsConfig.HTTPConfig.Password,
  3113. group.UserSettings.FsConfig.HTTPConfig.APIKey)
  3114. err = dataprovider.UpdateGroup(&updatedGroup, group.Users, claims.Username, ipAddr, claims.Role)
  3115. if err != nil {
  3116. s.renderGroupPage(w, r, updatedGroup, genericPageModeUpdate, err.Error())
  3117. return
  3118. }
  3119. http.Redirect(w, r, webGroupsPath, http.StatusSeeOther)
  3120. }
  3121. func (s *httpdServer) getWebEventActions(w http.ResponseWriter, r *http.Request, limit int, minimal bool,
  3122. ) ([]dataprovider.BaseEventAction, error) {
  3123. actions := make([]dataprovider.BaseEventAction, 0, limit)
  3124. for {
  3125. res, err := dataprovider.GetEventActions(limit, len(actions), dataprovider.OrderASC, minimal)
  3126. if err != nil {
  3127. s.renderInternalServerErrorPage(w, r, err)
  3128. return actions, err
  3129. }
  3130. actions = append(actions, res...)
  3131. if len(res) < limit {
  3132. break
  3133. }
  3134. }
  3135. return actions, nil
  3136. }
  3137. func (s *httpdServer) handleWebGetEventActions(w http.ResponseWriter, r *http.Request) {
  3138. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3139. limit := defaultQueryLimit
  3140. if _, ok := r.URL.Query()["qlimit"]; ok {
  3141. var err error
  3142. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  3143. if err != nil {
  3144. limit = defaultQueryLimit
  3145. }
  3146. }
  3147. actions, err := s.getWebEventActions(w, r, limit, false)
  3148. if err != nil {
  3149. return
  3150. }
  3151. data := eventActionsPage{
  3152. basePage: s.getBasePageData(pageEventActionsTitle, webAdminEventActionsPath, r),
  3153. Actions: actions,
  3154. }
  3155. renderAdminTemplate(w, templateEventActions, data)
  3156. }
  3157. func (s *httpdServer) handleWebAddEventActionGet(w http.ResponseWriter, r *http.Request) {
  3158. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3159. action := dataprovider.BaseEventAction{
  3160. Type: dataprovider.ActionTypeHTTP,
  3161. }
  3162. s.renderEventActionPage(w, r, action, genericPageModeAdd, "")
  3163. }
  3164. func (s *httpdServer) handleWebAddEventActionPost(w http.ResponseWriter, r *http.Request) {
  3165. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3166. claims, err := getTokenClaims(r)
  3167. if err != nil || claims.Username == "" {
  3168. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3169. return
  3170. }
  3171. action, err := getEventActionFromPostFields(r)
  3172. if err != nil {
  3173. s.renderEventActionPage(w, r, action, genericPageModeAdd, err.Error())
  3174. return
  3175. }
  3176. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3177. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3178. s.renderForbiddenPage(w, r, err.Error())
  3179. return
  3180. }
  3181. if err = dataprovider.AddEventAction(&action, claims.Username, ipAddr, claims.Role); err != nil {
  3182. s.renderEventActionPage(w, r, action, genericPageModeAdd, err.Error())
  3183. return
  3184. }
  3185. http.Redirect(w, r, webAdminEventActionsPath, http.StatusSeeOther)
  3186. }
  3187. func (s *httpdServer) handleWebUpdateEventActionGet(w http.ResponseWriter, r *http.Request) {
  3188. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3189. name := getURLParam(r, "name")
  3190. action, err := dataprovider.EventActionExists(name)
  3191. if err == nil {
  3192. s.renderEventActionPage(w, r, action, genericPageModeUpdate, "")
  3193. } else if _, ok := err.(*util.RecordNotFoundError); ok {
  3194. s.renderNotFoundPage(w, r, err)
  3195. } else {
  3196. s.renderInternalServerErrorPage(w, r, err)
  3197. }
  3198. }
  3199. func (s *httpdServer) handleWebUpdateEventActionPost(w http.ResponseWriter, r *http.Request) {
  3200. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3201. claims, err := getTokenClaims(r)
  3202. if err != nil || claims.Username == "" {
  3203. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3204. return
  3205. }
  3206. name := getURLParam(r, "name")
  3207. action, err := dataprovider.EventActionExists(name)
  3208. if _, ok := err.(*util.RecordNotFoundError); ok {
  3209. s.renderNotFoundPage(w, r, err)
  3210. return
  3211. } else if err != nil {
  3212. s.renderInternalServerErrorPage(w, r, err)
  3213. return
  3214. }
  3215. updatedAction, err := getEventActionFromPostFields(r)
  3216. if err != nil {
  3217. s.renderEventActionPage(w, r, updatedAction, genericPageModeUpdate, err.Error())
  3218. return
  3219. }
  3220. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3221. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3222. s.renderForbiddenPage(w, r, err.Error())
  3223. return
  3224. }
  3225. updatedAction.ID = action.ID
  3226. updatedAction.Name = action.Name
  3227. updatedAction.Options.SetEmptySecretsIfNil()
  3228. switch updatedAction.Type {
  3229. case dataprovider.ActionTypeHTTP:
  3230. if updatedAction.Options.HTTPConfig.Password.IsNotPlainAndNotEmpty() {
  3231. updatedAction.Options.HTTPConfig.Password = action.Options.HTTPConfig.Password
  3232. }
  3233. }
  3234. err = dataprovider.UpdateEventAction(&updatedAction, claims.Username, ipAddr, claims.Role)
  3235. if err != nil {
  3236. s.renderEventActionPage(w, r, updatedAction, genericPageModeUpdate, err.Error())
  3237. return
  3238. }
  3239. http.Redirect(w, r, webAdminEventActionsPath, http.StatusSeeOther)
  3240. }
  3241. func (s *httpdServer) handleWebGetEventRules(w http.ResponseWriter, r *http.Request) {
  3242. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3243. limit := defaultQueryLimit
  3244. if _, ok := r.URL.Query()["qlimit"]; ok {
  3245. if lim, err := strconv.Atoi(r.URL.Query().Get("qlimit")); err == nil {
  3246. limit = lim
  3247. }
  3248. }
  3249. rules := make([]dataprovider.EventRule, 0, limit)
  3250. for {
  3251. res, err := dataprovider.GetEventRules(limit, len(rules), dataprovider.OrderASC)
  3252. if err != nil {
  3253. s.renderInternalServerErrorPage(w, r, err)
  3254. return
  3255. }
  3256. rules = append(rules, res...)
  3257. if len(res) < limit {
  3258. break
  3259. }
  3260. }
  3261. data := eventRulesPage{
  3262. basePage: s.getBasePageData(pageEventRulesTitle, webAdminEventRulesPath, r),
  3263. Rules: rules,
  3264. }
  3265. renderAdminTemplate(w, templateEventRules, data)
  3266. }
  3267. func (s *httpdServer) handleWebAddEventRuleGet(w http.ResponseWriter, r *http.Request) {
  3268. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3269. rule := dataprovider.EventRule{
  3270. Trigger: dataprovider.EventTriggerFsEvent,
  3271. }
  3272. s.renderEventRulePage(w, r, rule, genericPageModeAdd, "")
  3273. }
  3274. func (s *httpdServer) handleWebAddEventRulePost(w http.ResponseWriter, r *http.Request) {
  3275. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3276. claims, err := getTokenClaims(r)
  3277. if err != nil || claims.Username == "" {
  3278. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3279. return
  3280. }
  3281. rule, err := getEventRuleFromPostFields(r)
  3282. if err != nil {
  3283. s.renderEventRulePage(w, r, rule, genericPageModeAdd, err.Error())
  3284. return
  3285. }
  3286. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3287. err = verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr)
  3288. if err != nil {
  3289. s.renderForbiddenPage(w, r, err.Error())
  3290. return
  3291. }
  3292. if err = dataprovider.AddEventRule(&rule, claims.Username, ipAddr, claims.Role); err != nil {
  3293. s.renderEventRulePage(w, r, rule, genericPageModeAdd, err.Error())
  3294. return
  3295. }
  3296. http.Redirect(w, r, webAdminEventRulesPath, http.StatusSeeOther)
  3297. }
  3298. func (s *httpdServer) handleWebUpdateEventRuleGet(w http.ResponseWriter, r *http.Request) {
  3299. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3300. name := getURLParam(r, "name")
  3301. rule, err := dataprovider.EventRuleExists(name)
  3302. if err == nil {
  3303. s.renderEventRulePage(w, r, rule, genericPageModeUpdate, "")
  3304. } else if _, ok := err.(*util.RecordNotFoundError); ok {
  3305. s.renderNotFoundPage(w, r, err)
  3306. } else {
  3307. s.renderInternalServerErrorPage(w, r, err)
  3308. }
  3309. }
  3310. func (s *httpdServer) handleWebUpdateEventRulePost(w http.ResponseWriter, r *http.Request) {
  3311. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3312. claims, err := getTokenClaims(r)
  3313. if err != nil || claims.Username == "" {
  3314. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3315. return
  3316. }
  3317. name := getURLParam(r, "name")
  3318. rule, err := dataprovider.EventRuleExists(name)
  3319. if _, ok := err.(*util.RecordNotFoundError); ok {
  3320. s.renderNotFoundPage(w, r, err)
  3321. return
  3322. } else if err != nil {
  3323. s.renderInternalServerErrorPage(w, r, err)
  3324. return
  3325. }
  3326. updatedRule, err := getEventRuleFromPostFields(r)
  3327. if err != nil {
  3328. s.renderEventRulePage(w, r, updatedRule, genericPageModeUpdate, err.Error())
  3329. return
  3330. }
  3331. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3332. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3333. s.renderForbiddenPage(w, r, err.Error())
  3334. return
  3335. }
  3336. updatedRule.ID = rule.ID
  3337. updatedRule.Name = rule.Name
  3338. err = dataprovider.UpdateEventRule(&updatedRule, claims.Username, ipAddr, claims.Role)
  3339. if err != nil {
  3340. s.renderEventRulePage(w, r, updatedRule, genericPageModeUpdate, err.Error())
  3341. return
  3342. }
  3343. http.Redirect(w, r, webAdminEventRulesPath, http.StatusSeeOther)
  3344. }
  3345. func (s *httpdServer) getWebRoles(w http.ResponseWriter, r *http.Request, limit int, minimal bool) ([]dataprovider.Role, error) {
  3346. roles := make([]dataprovider.Role, 0, limit)
  3347. for {
  3348. res, err := dataprovider.GetRoles(limit, len(roles), dataprovider.OrderASC, minimal)
  3349. if err != nil {
  3350. s.renderInternalServerErrorPage(w, r, err)
  3351. return roles, err
  3352. }
  3353. roles = append(roles, res...)
  3354. if len(res) < limit {
  3355. break
  3356. }
  3357. }
  3358. return roles, nil
  3359. }
  3360. func (s *httpdServer) handleWebGetRoles(w http.ResponseWriter, r *http.Request) {
  3361. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3362. roles, err := s.getWebRoles(w, r, 10, false)
  3363. if err != nil {
  3364. return
  3365. }
  3366. data := rolesPage{
  3367. basePage: s.getBasePageData(pageRolesTitle, webAdminRolesPath, r),
  3368. Roles: roles,
  3369. }
  3370. renderAdminTemplate(w, templateRoles, data)
  3371. }
  3372. func (s *httpdServer) handleWebAddRoleGet(w http.ResponseWriter, r *http.Request) {
  3373. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3374. s.renderRolePage(w, r, dataprovider.Role{}, genericPageModeAdd, "")
  3375. }
  3376. func (s *httpdServer) handleWebAddRolePost(w http.ResponseWriter, r *http.Request) {
  3377. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3378. role, err := getRoleFromPostFields(r)
  3379. if err != nil {
  3380. s.renderRolePage(w, r, role, genericPageModeAdd, err.Error())
  3381. return
  3382. }
  3383. claims, err := getTokenClaims(r)
  3384. if err != nil || claims.Username == "" {
  3385. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3386. return
  3387. }
  3388. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3389. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3390. s.renderForbiddenPage(w, r, err.Error())
  3391. return
  3392. }
  3393. err = dataprovider.AddRole(&role, claims.Username, ipAddr, claims.Role)
  3394. if err != nil {
  3395. s.renderRolePage(w, r, role, genericPageModeAdd, err.Error())
  3396. return
  3397. }
  3398. http.Redirect(w, r, webAdminRolesPath, http.StatusSeeOther)
  3399. }
  3400. func (s *httpdServer) handleWebUpdateRoleGet(w http.ResponseWriter, r *http.Request) {
  3401. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3402. role, err := dataprovider.RoleExists(getURLParam(r, "name"))
  3403. if err == nil {
  3404. s.renderRolePage(w, r, role, genericPageModeUpdate, "")
  3405. } else if _, ok := err.(*util.RecordNotFoundError); ok {
  3406. s.renderNotFoundPage(w, r, err)
  3407. } else {
  3408. s.renderInternalServerErrorPage(w, r, err)
  3409. }
  3410. }
  3411. func (s *httpdServer) handleWebUpdateRolePost(w http.ResponseWriter, r *http.Request) {
  3412. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3413. claims, err := getTokenClaims(r)
  3414. if err != nil || claims.Username == "" {
  3415. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3416. return
  3417. }
  3418. role, err := dataprovider.RoleExists(getURLParam(r, "name"))
  3419. if _, ok := err.(*util.RecordNotFoundError); ok {
  3420. s.renderNotFoundPage(w, r, err)
  3421. return
  3422. } else if err != nil {
  3423. s.renderInternalServerErrorPage(w, r, err)
  3424. return
  3425. }
  3426. updatedRole, err := getRoleFromPostFields(r)
  3427. if err != nil {
  3428. s.renderRolePage(w, r, role, genericPageModeAdd, err.Error())
  3429. return
  3430. }
  3431. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3432. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3433. s.renderForbiddenPage(w, r, err.Error())
  3434. return
  3435. }
  3436. updatedRole.ID = role.ID
  3437. updatedRole.Name = role.Name
  3438. err = dataprovider.UpdateRole(&updatedRole, claims.Username, ipAddr, claims.Role)
  3439. if err != nil {
  3440. s.renderRolePage(w, r, updatedRole, genericPageModeUpdate, err.Error())
  3441. return
  3442. }
  3443. http.Redirect(w, r, webAdminRolesPath, http.StatusSeeOther)
  3444. }
  3445. func (s *httpdServer) handleWebGetEvents(w http.ResponseWriter, r *http.Request) {
  3446. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3447. data := eventsPage{
  3448. basePage: s.getBasePageData(pageEventsTitle, webEventsPath, r),
  3449. FsEventsSearchURL: webEventsFsSearchPath,
  3450. ProviderEventsSearchURL: webEventsProviderSearchPath,
  3451. }
  3452. renderAdminTemplate(w, templateEvents, data)
  3453. }