webadmin.go 102 KB

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