webadmin.go 110 KB

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