webadmin.go 105 KB

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