webadmin.go 109 KB

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