webadmin.go 105 KB

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