webadmin.go 119 KB

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