webadmin.go 107 KB

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