webadmin.go 138 KB

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