webadmin.go 103 KB

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