webadmin.go 103 KB

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