webadmin.go 105 KB

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