webadmin.go 138 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198
  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 = "Forgot password"
  112. pageResetPwdTitle = "Reset password"
  113. pageSetupTitle = "Create first admin user"
  114. defaultQueryLimit = 1000
  115. inversePatternType = "inverse"
  116. )
  117. var (
  118. adminTemplates = make(map[string]*template.Template)
  119. )
  120. type basePage struct {
  121. commonBasePage
  122. Title string
  123. CurrentURL string
  124. UsersURL string
  125. UserURL string
  126. UserTemplateURL string
  127. AdminsURL string
  128. AdminURL string
  129. QuotaScanURL string
  130. ConnectionsURL string
  131. GroupsURL string
  132. GroupURL string
  133. FoldersURL string
  134. FolderURL string
  135. FolderTemplateURL string
  136. DefenderURL string
  137. IPListsURL string
  138. IPListURL string
  139. EventsURL string
  140. ConfigsURL string
  141. LogoutURL string
  142. ProfileURL string
  143. ChangePwdURL string
  144. MFAURL string
  145. EventRulesURL string
  146. EventRuleURL string
  147. EventActionsURL string
  148. EventActionURL string
  149. RolesURL string
  150. RoleURL string
  151. FolderQuotaScanURL string
  152. StatusURL string
  153. MaintenanceURL 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. commonBasePage: getCommonBasePage(r),
  650. Title: title,
  651. CurrentURL: currentURL,
  652. UsersURL: webUsersPath,
  653. UserURL: webUserPath,
  654. UserTemplateURL: webTemplateUser,
  655. AdminsURL: webAdminsPath,
  656. AdminURL: webAdminPath,
  657. GroupsURL: webGroupsPath,
  658. GroupURL: webGroupPath,
  659. FoldersURL: webFoldersPath,
  660. FolderURL: webFolderPath,
  661. FolderTemplateURL: webTemplateFolder,
  662. DefenderURL: webDefenderPath,
  663. IPListsURL: webIPListsPath,
  664. IPListURL: webIPListPath,
  665. EventsURL: webEventsPath,
  666. ConfigsURL: webConfigsPath,
  667. LogoutURL: webLogoutPath,
  668. ProfileURL: webAdminProfilePath,
  669. ChangePwdURL: webChangeAdminPwdPath,
  670. MFAURL: webAdminMFAPath,
  671. EventRulesURL: webAdminEventRulesPath,
  672. EventRuleURL: webAdminEventRulePath,
  673. EventActionsURL: webAdminEventActionsPath,
  674. EventActionURL: webAdminEventActionPath,
  675. RolesURL: webAdminRolesPath,
  676. RoleURL: webAdminRolePath,
  677. QuotaScanURL: webQuotaScanPath,
  678. ConnectionsURL: webConnectionsPath,
  679. StatusURL: webStatusPath,
  680. FolderQuotaScanURL: webScanVFolderPath,
  681. MaintenanceURL: webMaintenancePath,
  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, r *http.Request, error, ip string) {
  745. data := forgotPwdPage{
  746. commonBasePage: getCommonBasePage(r),
  747. CurrentURL: webAdminForgotPwdPath,
  748. Error: error,
  749. CSRFToken: createCSRFToken(ip),
  750. Title: pageForgotPwdTitle,
  751. Branding: s.binding.Branding.WebAdmin,
  752. }
  753. renderAdminTemplate(w, templateForgotPassword, data)
  754. }
  755. func (s *httpdServer) renderResetPwdPage(w http.ResponseWriter, r *http.Request, error, ip string) {
  756. data := resetPwdPage{
  757. commonBasePage: getCommonBasePage(r),
  758. CurrentURL: webAdminResetPwdPath,
  759. Error: error,
  760. CSRFToken: createCSRFToken(ip),
  761. Title: pageResetPwdTitle,
  762. Branding: s.binding.Branding.WebAdmin,
  763. }
  764. renderAdminTemplate(w, templateResetPassword, data)
  765. }
  766. func (s *httpdServer) renderTwoFactorPage(w http.ResponseWriter, r *http.Request, error, ip string) {
  767. data := twoFactorPage{
  768. commonBasePage: getCommonBasePage(r),
  769. Title: pageTwoFactorTitle,
  770. CurrentURL: webAdminTwoFactorPath,
  771. Error: error,
  772. CSRFToken: createCSRFToken(ip),
  773. RecoveryURL: webAdminTwoFactorRecoveryPath,
  774. Branding: s.binding.Branding.WebAdmin,
  775. }
  776. renderAdminTemplate(w, templateTwoFactor, data)
  777. }
  778. func (s *httpdServer) renderTwoFactorRecoveryPage(w http.ResponseWriter, r *http.Request, error, ip string) {
  779. data := twoFactorPage{
  780. commonBasePage: getCommonBasePage(r),
  781. Title: pageTwoFactorRecoveryTitle,
  782. CurrentURL: webAdminTwoFactorRecoveryPath,
  783. Error: error,
  784. CSRFToken: createCSRFToken(ip),
  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 getBandwidthLimitsFromPostFields(r *http.Request) ([]sdk.BandwidthLimit, error) {
  1260. var result []sdk.BandwidthLimit
  1261. for k := range r.Form {
  1262. if strings.HasPrefix(k, "bandwidth_limit_sources") {
  1263. sources := getSliceFromDelimitedValues(r.Form.Get(k), ",")
  1264. if len(sources) > 0 {
  1265. bwLimit := sdk.BandwidthLimit{
  1266. Sources: sources,
  1267. }
  1268. idx := strings.TrimPrefix(k, "bandwidth_limit_sources")
  1269. ul := r.Form.Get(fmt.Sprintf("upload_bandwidth_source%v", idx))
  1270. dl := r.Form.Get(fmt.Sprintf("download_bandwidth_source%v", idx))
  1271. if ul != "" {
  1272. bandwidthUL, err := strconv.ParseInt(ul, 10, 64)
  1273. if err != nil {
  1274. return result, fmt.Errorf("invalid upload_bandwidth_source%v %q: %w", idx, ul, err)
  1275. }
  1276. bwLimit.UploadBandwidth = bandwidthUL
  1277. }
  1278. if dl != "" {
  1279. bandwidthDL, err := strconv.ParseInt(dl, 10, 64)
  1280. if err != nil {
  1281. return result, fmt.Errorf("invalid download_bandwidth_source%v %q: %w", idx, ul, err)
  1282. }
  1283. bwLimit.DownloadBandwidth = bandwidthDL
  1284. }
  1285. result = append(result, bwLimit)
  1286. }
  1287. }
  1288. }
  1289. return result, nil
  1290. }
  1291. func getPatterDenyPolicyFromString(policy string) int {
  1292. denyPolicy := sdk.DenyPolicyDefault
  1293. if policy == "1" {
  1294. denyPolicy = sdk.DenyPolicyHide
  1295. }
  1296. return denyPolicy
  1297. }
  1298. func getFilePatternsFromPostField(r *http.Request) []sdk.PatternsFilter {
  1299. var result []sdk.PatternsFilter
  1300. allowedPatterns := make(map[string][]string)
  1301. deniedPatterns := make(map[string][]string)
  1302. patternPolicies := make(map[string]string)
  1303. for k := range r.Form {
  1304. if strings.HasPrefix(k, "pattern_path") {
  1305. p := strings.TrimSpace(r.Form.Get(k))
  1306. idx := strings.TrimPrefix(k, "pattern_path")
  1307. filters := strings.TrimSpace(r.Form.Get(fmt.Sprintf("patterns%v", idx)))
  1308. filters = strings.ReplaceAll(filters, " ", "")
  1309. patternType := r.Form.Get(fmt.Sprintf("pattern_type%v", idx))
  1310. patternPolicy := r.Form.Get(fmt.Sprintf("pattern_policy%v", idx))
  1311. if p != "" && filters != "" {
  1312. if patternType == "allowed" {
  1313. allowedPatterns[p] = append(allowedPatterns[p], strings.Split(filters, ",")...)
  1314. } else {
  1315. deniedPatterns[p] = append(deniedPatterns[p], strings.Split(filters, ",")...)
  1316. }
  1317. if patternPolicy != "" && patternPolicy != "0" {
  1318. patternPolicies[p] = patternPolicy
  1319. }
  1320. }
  1321. }
  1322. }
  1323. for dirAllowed, allowPatterns := range allowedPatterns {
  1324. filter := sdk.PatternsFilter{
  1325. Path: dirAllowed,
  1326. AllowedPatterns: allowPatterns,
  1327. DenyPolicy: getPatterDenyPolicyFromString(patternPolicies[dirAllowed]),
  1328. }
  1329. for dirDenied, denPatterns := range deniedPatterns {
  1330. if dirAllowed == dirDenied {
  1331. filter.DeniedPatterns = denPatterns
  1332. break
  1333. }
  1334. }
  1335. result = append(result, filter)
  1336. }
  1337. for dirDenied, denPatterns := range deniedPatterns {
  1338. found := false
  1339. for _, res := range result {
  1340. if res.Path == dirDenied {
  1341. found = true
  1342. break
  1343. }
  1344. }
  1345. if !found {
  1346. result = append(result, sdk.PatternsFilter{
  1347. Path: dirDenied,
  1348. DeniedPatterns: denPatterns,
  1349. DenyPolicy: getPatterDenyPolicyFromString(patternPolicies[dirDenied]),
  1350. })
  1351. }
  1352. }
  1353. return result
  1354. }
  1355. func getGroupsFromUserPostFields(r *http.Request) []sdk.GroupMapping {
  1356. var groups []sdk.GroupMapping
  1357. primaryGroup := strings.TrimSpace(r.Form.Get("primary_group"))
  1358. if primaryGroup != "" {
  1359. groups = append(groups, sdk.GroupMapping{
  1360. Name: primaryGroup,
  1361. Type: sdk.GroupTypePrimary,
  1362. })
  1363. }
  1364. secondaryGroups := r.Form["secondary_groups"]
  1365. for _, name := range secondaryGroups {
  1366. groups = append(groups, sdk.GroupMapping{
  1367. Name: strings.TrimSpace(name),
  1368. Type: sdk.GroupTypeSecondary,
  1369. })
  1370. }
  1371. membershipGroups := r.Form["membership_groups"]
  1372. for _, name := range membershipGroups {
  1373. groups = append(groups, sdk.GroupMapping{
  1374. Name: strings.TrimSpace(name),
  1375. Type: sdk.GroupTypeMembership,
  1376. })
  1377. }
  1378. return groups
  1379. }
  1380. func getFiltersFromUserPostFields(r *http.Request) (sdk.BaseUserFilters, error) {
  1381. var filters sdk.BaseUserFilters
  1382. bwLimits, err := getBandwidthLimitsFromPostFields(r)
  1383. if err != nil {
  1384. return filters, err
  1385. }
  1386. maxFileSize, err := util.ParseBytes(r.Form.Get("max_upload_file_size"))
  1387. if err != nil {
  1388. return filters, fmt.Errorf("invalid max upload file size: %w", err)
  1389. }
  1390. defaultSharesExpiration, err := strconv.Atoi(r.Form.Get("default_shares_expiration"))
  1391. if err != nil {
  1392. return filters, fmt.Errorf("invalid default shares expiration: %w", err)
  1393. }
  1394. maxSharesExpiration, err := strconv.Atoi(r.Form.Get("max_shares_expiration"))
  1395. if err != nil {
  1396. return filters, fmt.Errorf("invalid max shares expiration: %w", err)
  1397. }
  1398. passwordExpiration, err := strconv.Atoi(r.Form.Get("password_expiration"))
  1399. if err != nil {
  1400. return filters, fmt.Errorf("invalid password expiration: %w", err)
  1401. }
  1402. passwordStrength, err := strconv.Atoi(r.Form.Get("password_strength"))
  1403. if err != nil {
  1404. return filters, fmt.Errorf("invalid password strength: %w", err)
  1405. }
  1406. if r.Form.Get("ftp_security") == "1" {
  1407. filters.FTPSecurity = 1
  1408. }
  1409. filters.BandwidthLimits = bwLimits
  1410. filters.AllowedIP = getSliceFromDelimitedValues(r.Form.Get("allowed_ip"), ",")
  1411. filters.DeniedIP = getSliceFromDelimitedValues(r.Form.Get("denied_ip"), ",")
  1412. filters.DeniedLoginMethods = r.Form["denied_login_methods"]
  1413. filters.DeniedProtocols = r.Form["denied_protocols"]
  1414. filters.TwoFactorAuthProtocols = r.Form["required_two_factor_protocols"]
  1415. filters.FilePatterns = getFilePatternsFromPostField(r)
  1416. filters.TLSUsername = sdk.TLSUsername(strings.TrimSpace(r.Form.Get("tls_username")))
  1417. filters.WebClient = r.Form["web_client_options"]
  1418. filters.DefaultSharesExpiration = defaultSharesExpiration
  1419. filters.MaxSharesExpiration = maxSharesExpiration
  1420. filters.PasswordExpiration = passwordExpiration
  1421. filters.PasswordStrength = passwordStrength
  1422. hooks := r.Form["hooks"]
  1423. if util.Contains(hooks, "external_auth_disabled") {
  1424. filters.Hooks.ExternalAuthDisabled = true
  1425. }
  1426. if util.Contains(hooks, "pre_login_disabled") {
  1427. filters.Hooks.PreLoginDisabled = true
  1428. }
  1429. if util.Contains(hooks, "check_password_disabled") {
  1430. filters.Hooks.CheckPasswordDisabled = true
  1431. }
  1432. filters.IsAnonymous = r.Form.Get("is_anonymous") != ""
  1433. filters.DisableFsChecks = r.Form.Get("disable_fs_checks") != ""
  1434. filters.AllowAPIKeyAuth = r.Form.Get("allow_api_key_auth") != ""
  1435. filters.StartDirectory = strings.TrimSpace(r.Form.Get("start_directory"))
  1436. filters.MaxUploadFileSize = maxFileSize
  1437. filters.ExternalAuthCacheTime, err = strconv.ParseInt(r.Form.Get("external_auth_cache_time"), 10, 64)
  1438. if err != nil {
  1439. return filters, fmt.Errorf("invalid external auth cache time: %w", err)
  1440. }
  1441. return filters, nil
  1442. }
  1443. func getSecretFromFormField(r *http.Request, field string) *kms.Secret {
  1444. secret := kms.NewPlainSecret(r.Form.Get(field))
  1445. if strings.TrimSpace(secret.GetPayload()) == redactedSecret {
  1446. secret.SetStatus(sdkkms.SecretStatusRedacted)
  1447. }
  1448. if strings.TrimSpace(secret.GetPayload()) == "" {
  1449. secret.SetStatus("")
  1450. }
  1451. return secret
  1452. }
  1453. func getS3Config(r *http.Request) (vfs.S3FsConfig, error) {
  1454. var err error
  1455. config := vfs.S3FsConfig{}
  1456. config.Bucket = strings.TrimSpace(r.Form.Get("s3_bucket"))
  1457. config.Region = strings.TrimSpace(r.Form.Get("s3_region"))
  1458. config.AccessKey = strings.TrimSpace(r.Form.Get("s3_access_key"))
  1459. config.RoleARN = strings.TrimSpace(r.Form.Get("s3_role_arn"))
  1460. config.AccessSecret = getSecretFromFormField(r, "s3_access_secret")
  1461. config.Endpoint = strings.TrimSpace(r.Form.Get("s3_endpoint"))
  1462. config.StorageClass = strings.TrimSpace(r.Form.Get("s3_storage_class"))
  1463. config.ACL = strings.TrimSpace(r.Form.Get("s3_acl"))
  1464. config.KeyPrefix = strings.TrimSpace(strings.TrimPrefix(r.Form.Get("s3_key_prefix"), "/"))
  1465. config.UploadPartSize, err = strconv.ParseInt(r.Form.Get("s3_upload_part_size"), 10, 64)
  1466. if err != nil {
  1467. return config, fmt.Errorf("invalid s3 upload part size: %w", err)
  1468. }
  1469. config.UploadConcurrency, err = strconv.Atoi(r.Form.Get("s3_upload_concurrency"))
  1470. if err != nil {
  1471. return config, fmt.Errorf("invalid s3 upload concurrency: %w", err)
  1472. }
  1473. config.DownloadPartSize, err = strconv.ParseInt(r.Form.Get("s3_download_part_size"), 10, 64)
  1474. if err != nil {
  1475. return config, fmt.Errorf("invalid s3 download part size: %w", err)
  1476. }
  1477. config.DownloadConcurrency, err = strconv.Atoi(r.Form.Get("s3_download_concurrency"))
  1478. if err != nil {
  1479. return config, fmt.Errorf("invalid s3 download concurrency: %w", err)
  1480. }
  1481. config.ForcePathStyle = r.Form.Get("s3_force_path_style") != ""
  1482. config.SkipTLSVerify = r.Form.Get("s3_skip_tls_verify") != ""
  1483. config.DownloadPartMaxTime, err = strconv.Atoi(r.Form.Get("s3_download_part_max_time"))
  1484. if err != nil {
  1485. return config, fmt.Errorf("invalid s3 download part max time: %w", err)
  1486. }
  1487. config.UploadPartMaxTime, err = strconv.Atoi(r.Form.Get("s3_upload_part_max_time"))
  1488. if err != nil {
  1489. return config, fmt.Errorf("invalid s3 upload part max time: %w", err)
  1490. }
  1491. return config, nil
  1492. }
  1493. func getGCSConfig(r *http.Request) (vfs.GCSFsConfig, error) {
  1494. var err error
  1495. config := vfs.GCSFsConfig{}
  1496. config.Bucket = strings.TrimSpace(r.Form.Get("gcs_bucket"))
  1497. config.StorageClass = strings.TrimSpace(r.Form.Get("gcs_storage_class"))
  1498. config.ACL = strings.TrimSpace(r.Form.Get("gcs_acl"))
  1499. config.KeyPrefix = strings.TrimSpace(strings.TrimPrefix(r.Form.Get("gcs_key_prefix"), "/"))
  1500. uploadPartSize, err := strconv.ParseInt(r.Form.Get("gcs_upload_part_size"), 10, 64)
  1501. if err == nil {
  1502. config.UploadPartSize = uploadPartSize
  1503. }
  1504. uploadPartMaxTime, err := strconv.Atoi(r.Form.Get("gcs_upload_part_max_time"))
  1505. if err == nil {
  1506. config.UploadPartMaxTime = uploadPartMaxTime
  1507. }
  1508. autoCredentials := r.Form.Get("gcs_auto_credentials")
  1509. if autoCredentials != "" {
  1510. config.AutomaticCredentials = 1
  1511. } else {
  1512. config.AutomaticCredentials = 0
  1513. }
  1514. credentials, _, err := r.FormFile("gcs_credential_file")
  1515. if err == http.ErrMissingFile {
  1516. return config, nil
  1517. }
  1518. if err != nil {
  1519. return config, err
  1520. }
  1521. defer credentials.Close()
  1522. fileBytes, err := io.ReadAll(credentials)
  1523. if err != nil || len(fileBytes) == 0 {
  1524. if len(fileBytes) == 0 {
  1525. err = errors.New("credentials file size must be greater than 0")
  1526. }
  1527. return config, err
  1528. }
  1529. config.Credentials = kms.NewPlainSecret(string(fileBytes))
  1530. config.AutomaticCredentials = 0
  1531. return config, err
  1532. }
  1533. func getSFTPConfig(r *http.Request) (vfs.SFTPFsConfig, error) {
  1534. var err error
  1535. config := vfs.SFTPFsConfig{}
  1536. config.Endpoint = strings.TrimSpace(r.Form.Get("sftp_endpoint"))
  1537. config.Username = strings.TrimSpace(r.Form.Get("sftp_username"))
  1538. config.Password = getSecretFromFormField(r, "sftp_password")
  1539. config.PrivateKey = getSecretFromFormField(r, "sftp_private_key")
  1540. config.KeyPassphrase = getSecretFromFormField(r, "sftp_key_passphrase")
  1541. fingerprintsFormValue := r.Form.Get("sftp_fingerprints")
  1542. config.Fingerprints = getSliceFromDelimitedValues(fingerprintsFormValue, "\n")
  1543. config.Prefix = strings.TrimSpace(r.Form.Get("sftp_prefix"))
  1544. config.DisableCouncurrentReads = r.Form.Get("sftp_disable_concurrent_reads") != ""
  1545. config.BufferSize, err = strconv.ParseInt(r.Form.Get("sftp_buffer_size"), 10, 64)
  1546. if r.Form.Get("sftp_equality_check_mode") != "" {
  1547. config.EqualityCheckMode = 1
  1548. } else {
  1549. config.EqualityCheckMode = 0
  1550. }
  1551. if err != nil {
  1552. return config, fmt.Errorf("invalid SFTP buffer size: %w", err)
  1553. }
  1554. return config, nil
  1555. }
  1556. func getHTTPFsConfig(r *http.Request) vfs.HTTPFsConfig {
  1557. config := vfs.HTTPFsConfig{}
  1558. config.Endpoint = strings.TrimSpace(r.Form.Get("http_endpoint"))
  1559. config.Username = strings.TrimSpace(r.Form.Get("http_username"))
  1560. config.SkipTLSVerify = r.Form.Get("http_skip_tls_verify") != ""
  1561. config.Password = getSecretFromFormField(r, "http_password")
  1562. config.APIKey = getSecretFromFormField(r, "http_api_key")
  1563. if r.Form.Get("http_equality_check_mode") != "" {
  1564. config.EqualityCheckMode = 1
  1565. } else {
  1566. config.EqualityCheckMode = 0
  1567. }
  1568. return config
  1569. }
  1570. func getAzureConfig(r *http.Request) (vfs.AzBlobFsConfig, error) {
  1571. var err error
  1572. config := vfs.AzBlobFsConfig{}
  1573. config.Container = strings.TrimSpace(r.Form.Get("az_container"))
  1574. config.AccountName = strings.TrimSpace(r.Form.Get("az_account_name"))
  1575. config.AccountKey = getSecretFromFormField(r, "az_account_key")
  1576. config.SASURL = getSecretFromFormField(r, "az_sas_url")
  1577. config.Endpoint = strings.TrimSpace(r.Form.Get("az_endpoint"))
  1578. config.KeyPrefix = strings.TrimSpace(strings.TrimPrefix(r.Form.Get("az_key_prefix"), "/"))
  1579. config.AccessTier = strings.TrimSpace(r.Form.Get("az_access_tier"))
  1580. config.UseEmulator = r.Form.Get("az_use_emulator") != ""
  1581. config.UploadPartSize, err = strconv.ParseInt(r.Form.Get("az_upload_part_size"), 10, 64)
  1582. if err != nil {
  1583. return config, fmt.Errorf("invalid azure upload part size: %w", err)
  1584. }
  1585. config.UploadConcurrency, err = strconv.Atoi(r.Form.Get("az_upload_concurrency"))
  1586. if err != nil {
  1587. return config, fmt.Errorf("invalid azure upload concurrency: %w", err)
  1588. }
  1589. config.DownloadPartSize, err = strconv.ParseInt(r.Form.Get("az_download_part_size"), 10, 64)
  1590. if err != nil {
  1591. return config, fmt.Errorf("invalid azure download part size: %w", err)
  1592. }
  1593. config.DownloadConcurrency, err = strconv.Atoi(r.Form.Get("az_download_concurrency"))
  1594. if err != nil {
  1595. return config, fmt.Errorf("invalid azure download concurrency: %w", err)
  1596. }
  1597. return config, nil
  1598. }
  1599. func getOsConfigFromPostFields(r *http.Request, readBufferField, writeBufferField string) sdk.OSFsConfig {
  1600. config := sdk.OSFsConfig{}
  1601. readBuffer, err := strconv.Atoi(r.Form.Get(readBufferField))
  1602. if err == nil {
  1603. config.ReadBufferSize = readBuffer
  1604. }
  1605. writeBuffer, err := strconv.Atoi(r.Form.Get(writeBufferField))
  1606. if err == nil {
  1607. config.WriteBufferSize = writeBuffer
  1608. }
  1609. return config
  1610. }
  1611. func getFsConfigFromPostFields(r *http.Request) (vfs.Filesystem, error) {
  1612. var fs vfs.Filesystem
  1613. fs.Provider = sdk.GetProviderByName(r.Form.Get("fs_provider"))
  1614. switch fs.Provider {
  1615. case sdk.LocalFilesystemProvider:
  1616. fs.OSConfig = getOsConfigFromPostFields(r, "osfs_read_buffer_size", "osfs_write_buffer_size")
  1617. case sdk.S3FilesystemProvider:
  1618. config, err := getS3Config(r)
  1619. if err != nil {
  1620. return fs, err
  1621. }
  1622. fs.S3Config = config
  1623. case sdk.AzureBlobFilesystemProvider:
  1624. config, err := getAzureConfig(r)
  1625. if err != nil {
  1626. return fs, err
  1627. }
  1628. fs.AzBlobConfig = config
  1629. case sdk.GCSFilesystemProvider:
  1630. config, err := getGCSConfig(r)
  1631. if err != nil {
  1632. return fs, err
  1633. }
  1634. fs.GCSConfig = config
  1635. case sdk.CryptedFilesystemProvider:
  1636. fs.CryptConfig.Passphrase = getSecretFromFormField(r, "crypt_passphrase")
  1637. fs.CryptConfig.OSFsConfig = getOsConfigFromPostFields(r, "cryptfs_read_buffer_size", "cryptfs_write_buffer_size")
  1638. case sdk.SFTPFilesystemProvider:
  1639. config, err := getSFTPConfig(r)
  1640. if err != nil {
  1641. return fs, err
  1642. }
  1643. fs.SFTPConfig = config
  1644. case sdk.HTTPFilesystemProvider:
  1645. fs.HTTPConfig = getHTTPFsConfig(r)
  1646. }
  1647. return fs, nil
  1648. }
  1649. func getAdminHiddenUserPageSections(r *http.Request) int {
  1650. var result int
  1651. for _, val := range r.Form["user_page_hidden_sections"] {
  1652. switch val {
  1653. case "1":
  1654. result++
  1655. case "2":
  1656. result += 2
  1657. case "3":
  1658. result += 4
  1659. case "4":
  1660. result += 8
  1661. case "5":
  1662. result += 16
  1663. case "6":
  1664. result += 32
  1665. case "7":
  1666. result += 64
  1667. }
  1668. }
  1669. return result
  1670. }
  1671. func getAdminFromPostFields(r *http.Request) (dataprovider.Admin, error) {
  1672. var admin dataprovider.Admin
  1673. err := r.ParseForm()
  1674. if err != nil {
  1675. return admin, err
  1676. }
  1677. status, err := strconv.Atoi(r.Form.Get("status"))
  1678. if err != nil {
  1679. return admin, fmt.Errorf("invalid status: %w", err)
  1680. }
  1681. admin.Username = strings.TrimSpace(r.Form.Get("username"))
  1682. admin.Password = strings.TrimSpace(r.Form.Get("password"))
  1683. admin.Permissions = r.Form["permissions"]
  1684. admin.Email = strings.TrimSpace(r.Form.Get("email"))
  1685. admin.Status = status
  1686. admin.Role = strings.TrimSpace(r.Form.Get("role"))
  1687. admin.Filters.AllowList = getSliceFromDelimitedValues(r.Form.Get("allowed_ip"), ",")
  1688. admin.Filters.AllowAPIKeyAuth = r.Form.Get("allow_api_key_auth") != ""
  1689. admin.AdditionalInfo = r.Form.Get("additional_info")
  1690. admin.Description = r.Form.Get("description")
  1691. admin.Filters.Preferences.HideUserPageSections = getAdminHiddenUserPageSections(r)
  1692. admin.Filters.Preferences.DefaultUsersExpiration = 0
  1693. if val := r.Form.Get("default_users_expiration"); val != "" {
  1694. defaultUsersExpiration, err := strconv.Atoi(r.Form.Get("default_users_expiration"))
  1695. if err != nil {
  1696. return admin, fmt.Errorf("invalid default users expiration: %w", err)
  1697. }
  1698. admin.Filters.Preferences.DefaultUsersExpiration = defaultUsersExpiration
  1699. }
  1700. for k := range r.Form {
  1701. if strings.HasPrefix(k, "group") {
  1702. groupName := strings.TrimSpace(r.Form.Get(k))
  1703. if groupName != "" {
  1704. idx := strings.TrimPrefix(k, "group")
  1705. addAsGroupType := r.Form.Get(fmt.Sprintf("add_as_group_type%s", idx))
  1706. group := dataprovider.AdminGroupMapping{
  1707. Name: groupName,
  1708. }
  1709. switch addAsGroupType {
  1710. case "1":
  1711. group.Options.AddToUsersAs = dataprovider.GroupAddToUsersAsPrimary
  1712. case "2":
  1713. group.Options.AddToUsersAs = dataprovider.GroupAddToUsersAsSecondary
  1714. default:
  1715. group.Options.AddToUsersAs = dataprovider.GroupAddToUsersAsMembership
  1716. }
  1717. admin.Groups = append(admin.Groups, group)
  1718. }
  1719. }
  1720. }
  1721. return admin, nil
  1722. }
  1723. func replacePlaceholders(field string, replacements map[string]string) string {
  1724. for k, v := range replacements {
  1725. field = strings.ReplaceAll(field, k, v)
  1726. }
  1727. return field
  1728. }
  1729. func getFolderFromTemplate(folder vfs.BaseVirtualFolder, name string) vfs.BaseVirtualFolder {
  1730. folder.Name = name
  1731. replacements := make(map[string]string)
  1732. replacements["%name%"] = folder.Name
  1733. folder.MappedPath = replacePlaceholders(folder.MappedPath, replacements)
  1734. folder.Description = replacePlaceholders(folder.Description, replacements)
  1735. switch folder.FsConfig.Provider {
  1736. case sdk.CryptedFilesystemProvider:
  1737. folder.FsConfig.CryptConfig = getCryptFsFromTemplate(folder.FsConfig.CryptConfig, replacements)
  1738. case sdk.S3FilesystemProvider:
  1739. folder.FsConfig.S3Config = getS3FsFromTemplate(folder.FsConfig.S3Config, replacements)
  1740. case sdk.GCSFilesystemProvider:
  1741. folder.FsConfig.GCSConfig = getGCSFsFromTemplate(folder.FsConfig.GCSConfig, replacements)
  1742. case sdk.AzureBlobFilesystemProvider:
  1743. folder.FsConfig.AzBlobConfig = getAzBlobFsFromTemplate(folder.FsConfig.AzBlobConfig, replacements)
  1744. case sdk.SFTPFilesystemProvider:
  1745. folder.FsConfig.SFTPConfig = getSFTPFsFromTemplate(folder.FsConfig.SFTPConfig, replacements)
  1746. case sdk.HTTPFilesystemProvider:
  1747. folder.FsConfig.HTTPConfig = getHTTPFsFromTemplate(folder.FsConfig.HTTPConfig, replacements)
  1748. }
  1749. return folder
  1750. }
  1751. func getCryptFsFromTemplate(fsConfig vfs.CryptFsConfig, replacements map[string]string) vfs.CryptFsConfig {
  1752. if fsConfig.Passphrase != nil {
  1753. if fsConfig.Passphrase.IsPlain() {
  1754. payload := replacePlaceholders(fsConfig.Passphrase.GetPayload(), replacements)
  1755. fsConfig.Passphrase = kms.NewPlainSecret(payload)
  1756. }
  1757. }
  1758. return fsConfig
  1759. }
  1760. func getS3FsFromTemplate(fsConfig vfs.S3FsConfig, replacements map[string]string) vfs.S3FsConfig {
  1761. fsConfig.KeyPrefix = replacePlaceholders(fsConfig.KeyPrefix, replacements)
  1762. fsConfig.AccessKey = replacePlaceholders(fsConfig.AccessKey, replacements)
  1763. if fsConfig.AccessSecret != nil && fsConfig.AccessSecret.IsPlain() {
  1764. payload := replacePlaceholders(fsConfig.AccessSecret.GetPayload(), replacements)
  1765. fsConfig.AccessSecret = kms.NewPlainSecret(payload)
  1766. }
  1767. return fsConfig
  1768. }
  1769. func getGCSFsFromTemplate(fsConfig vfs.GCSFsConfig, replacements map[string]string) vfs.GCSFsConfig {
  1770. fsConfig.KeyPrefix = replacePlaceholders(fsConfig.KeyPrefix, replacements)
  1771. return fsConfig
  1772. }
  1773. func getAzBlobFsFromTemplate(fsConfig vfs.AzBlobFsConfig, replacements map[string]string) vfs.AzBlobFsConfig {
  1774. fsConfig.KeyPrefix = replacePlaceholders(fsConfig.KeyPrefix, replacements)
  1775. fsConfig.AccountName = replacePlaceholders(fsConfig.AccountName, replacements)
  1776. if fsConfig.AccountKey != nil && fsConfig.AccountKey.IsPlain() {
  1777. payload := replacePlaceholders(fsConfig.AccountKey.GetPayload(), replacements)
  1778. fsConfig.AccountKey = kms.NewPlainSecret(payload)
  1779. }
  1780. return fsConfig
  1781. }
  1782. func getSFTPFsFromTemplate(fsConfig vfs.SFTPFsConfig, replacements map[string]string) vfs.SFTPFsConfig {
  1783. fsConfig.Prefix = replacePlaceholders(fsConfig.Prefix, replacements)
  1784. fsConfig.Username = replacePlaceholders(fsConfig.Username, replacements)
  1785. if fsConfig.Password != nil && fsConfig.Password.IsPlain() {
  1786. payload := replacePlaceholders(fsConfig.Password.GetPayload(), replacements)
  1787. fsConfig.Password = kms.NewPlainSecret(payload)
  1788. }
  1789. return fsConfig
  1790. }
  1791. func getHTTPFsFromTemplate(fsConfig vfs.HTTPFsConfig, replacements map[string]string) vfs.HTTPFsConfig {
  1792. fsConfig.Username = replacePlaceholders(fsConfig.Username, replacements)
  1793. return fsConfig
  1794. }
  1795. func getUserFromTemplate(user dataprovider.User, template userTemplateFields) dataprovider.User {
  1796. user.Username = template.Username
  1797. user.Password = template.Password
  1798. user.PublicKeys = template.PublicKeys
  1799. replacements := make(map[string]string)
  1800. replacements["%username%"] = user.Username
  1801. if user.Password != "" && !user.IsPasswordHashed() {
  1802. user.Password = replacePlaceholders(user.Password, replacements)
  1803. replacements["%password%"] = user.Password
  1804. }
  1805. user.HomeDir = replacePlaceholders(user.HomeDir, replacements)
  1806. var vfolders []vfs.VirtualFolder
  1807. for _, vfolder := range user.VirtualFolders {
  1808. vfolder.Name = replacePlaceholders(vfolder.Name, replacements)
  1809. vfolder.VirtualPath = replacePlaceholders(vfolder.VirtualPath, replacements)
  1810. vfolders = append(vfolders, vfolder)
  1811. }
  1812. user.VirtualFolders = vfolders
  1813. user.Description = replacePlaceholders(user.Description, replacements)
  1814. user.AdditionalInfo = replacePlaceholders(user.AdditionalInfo, replacements)
  1815. user.Filters.StartDirectory = replacePlaceholders(user.Filters.StartDirectory, replacements)
  1816. switch user.FsConfig.Provider {
  1817. case sdk.CryptedFilesystemProvider:
  1818. user.FsConfig.CryptConfig = getCryptFsFromTemplate(user.FsConfig.CryptConfig, replacements)
  1819. case sdk.S3FilesystemProvider:
  1820. user.FsConfig.S3Config = getS3FsFromTemplate(user.FsConfig.S3Config, replacements)
  1821. case sdk.GCSFilesystemProvider:
  1822. user.FsConfig.GCSConfig = getGCSFsFromTemplate(user.FsConfig.GCSConfig, replacements)
  1823. case sdk.AzureBlobFilesystemProvider:
  1824. user.FsConfig.AzBlobConfig = getAzBlobFsFromTemplate(user.FsConfig.AzBlobConfig, replacements)
  1825. case sdk.SFTPFilesystemProvider:
  1826. user.FsConfig.SFTPConfig = getSFTPFsFromTemplate(user.FsConfig.SFTPConfig, replacements)
  1827. case sdk.HTTPFilesystemProvider:
  1828. user.FsConfig.HTTPConfig = getHTTPFsFromTemplate(user.FsConfig.HTTPConfig, replacements)
  1829. }
  1830. return user
  1831. }
  1832. func getTransferLimits(r *http.Request) (int64, int64, int64, error) {
  1833. dataTransferUL, err := strconv.ParseInt(r.Form.Get("upload_data_transfer"), 10, 64)
  1834. if err != nil {
  1835. return 0, 0, 0, fmt.Errorf("invalid upload data transfer: %w", err)
  1836. }
  1837. dataTransferDL, err := strconv.ParseInt(r.Form.Get("download_data_transfer"), 10, 64)
  1838. if err != nil {
  1839. return 0, 0, 0, fmt.Errorf("invalid download data transfer: %w", err)
  1840. }
  1841. dataTransferTotal, err := strconv.ParseInt(r.Form.Get("total_data_transfer"), 10, 64)
  1842. if err != nil {
  1843. return 0, 0, 0, fmt.Errorf("invalid total data transfer: %w", err)
  1844. }
  1845. return dataTransferUL, dataTransferDL, dataTransferTotal, nil
  1846. }
  1847. func getQuotaLimits(r *http.Request) (int64, int, error) {
  1848. quotaSize, err := util.ParseBytes(r.Form.Get("quota_size"))
  1849. if err != nil {
  1850. return 0, 0, fmt.Errorf("invalid quota size: %w", err)
  1851. }
  1852. quotaFiles, err := strconv.Atoi(r.Form.Get("quota_files"))
  1853. if err != nil {
  1854. return 0, 0, fmt.Errorf("invalid quota files: %w", err)
  1855. }
  1856. return quotaSize, quotaFiles, nil
  1857. }
  1858. func getUserFromPostFields(r *http.Request) (dataprovider.User, error) {
  1859. user := dataprovider.User{}
  1860. err := r.ParseMultipartForm(maxRequestSize)
  1861. if err != nil {
  1862. return user, err
  1863. }
  1864. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  1865. uid, err := strconv.Atoi(r.Form.Get("uid"))
  1866. if err != nil {
  1867. return user, fmt.Errorf("invalid uid: %w", err)
  1868. }
  1869. gid, err := strconv.Atoi(r.Form.Get("gid"))
  1870. if err != nil {
  1871. return user, fmt.Errorf("invalid uid: %w", err)
  1872. }
  1873. maxSessions, err := strconv.Atoi(r.Form.Get("max_sessions"))
  1874. if err != nil {
  1875. return user, fmt.Errorf("invalid max sessions: %w", err)
  1876. }
  1877. quotaSize, quotaFiles, err := getQuotaLimits(r)
  1878. if err != nil {
  1879. return user, err
  1880. }
  1881. bandwidthUL, err := strconv.ParseInt(r.Form.Get("upload_bandwidth"), 10, 64)
  1882. if err != nil {
  1883. return user, fmt.Errorf("invalid upload bandwidth: %w", err)
  1884. }
  1885. bandwidthDL, err := strconv.ParseInt(r.Form.Get("download_bandwidth"), 10, 64)
  1886. if err != nil {
  1887. return user, fmt.Errorf("invalid download bandwidth: %w", err)
  1888. }
  1889. dataTransferUL, dataTransferDL, dataTransferTotal, err := getTransferLimits(r)
  1890. if err != nil {
  1891. return user, err
  1892. }
  1893. status, err := strconv.Atoi(r.Form.Get("status"))
  1894. if err != nil {
  1895. return user, fmt.Errorf("invalid status: %w", err)
  1896. }
  1897. expirationDateMillis := int64(0)
  1898. expirationDateString := r.Form.Get("expiration_date")
  1899. if strings.TrimSpace(expirationDateString) != "" {
  1900. expirationDate, err := time.Parse(webDateTimeFormat, expirationDateString)
  1901. if err != nil {
  1902. return user, err
  1903. }
  1904. expirationDateMillis = util.GetTimeAsMsSinceEpoch(expirationDate)
  1905. }
  1906. fsConfig, err := getFsConfigFromPostFields(r)
  1907. if err != nil {
  1908. return user, err
  1909. }
  1910. filters, err := getFiltersFromUserPostFields(r)
  1911. if err != nil {
  1912. return user, err
  1913. }
  1914. user = dataprovider.User{
  1915. BaseUser: sdk.BaseUser{
  1916. Username: strings.TrimSpace(r.Form.Get("username")),
  1917. Email: strings.TrimSpace(r.Form.Get("email")),
  1918. Password: strings.TrimSpace(r.Form.Get("password")),
  1919. PublicKeys: r.Form["public_keys"],
  1920. HomeDir: strings.TrimSpace(r.Form.Get("home_dir")),
  1921. UID: uid,
  1922. GID: gid,
  1923. Permissions: getUserPermissionsFromPostFields(r),
  1924. MaxSessions: maxSessions,
  1925. QuotaSize: quotaSize,
  1926. QuotaFiles: quotaFiles,
  1927. UploadBandwidth: bandwidthUL,
  1928. DownloadBandwidth: bandwidthDL,
  1929. UploadDataTransfer: dataTransferUL,
  1930. DownloadDataTransfer: dataTransferDL,
  1931. TotalDataTransfer: dataTransferTotal,
  1932. Status: status,
  1933. ExpirationDate: expirationDateMillis,
  1934. AdditionalInfo: r.Form.Get("additional_info"),
  1935. Description: r.Form.Get("description"),
  1936. Role: strings.TrimSpace(r.Form.Get("role")),
  1937. },
  1938. Filters: dataprovider.UserFilters{
  1939. BaseUserFilters: filters,
  1940. RequirePasswordChange: r.Form.Get("require_password_change") != "",
  1941. },
  1942. VirtualFolders: getVirtualFoldersFromPostFields(r),
  1943. FsConfig: fsConfig,
  1944. Groups: getGroupsFromUserPostFields(r),
  1945. }
  1946. return user, nil
  1947. }
  1948. func getGroupFromPostFields(r *http.Request) (dataprovider.Group, error) {
  1949. group := dataprovider.Group{}
  1950. err := r.ParseMultipartForm(maxRequestSize)
  1951. if err != nil {
  1952. return group, err
  1953. }
  1954. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  1955. maxSessions, err := strconv.Atoi(r.Form.Get("max_sessions"))
  1956. if err != nil {
  1957. return group, fmt.Errorf("invalid max sessions: %w", err)
  1958. }
  1959. quotaSize, quotaFiles, err := getQuotaLimits(r)
  1960. if err != nil {
  1961. return group, err
  1962. }
  1963. bandwidthUL, err := strconv.ParseInt(r.Form.Get("upload_bandwidth"), 10, 64)
  1964. if err != nil {
  1965. return group, fmt.Errorf("invalid upload bandwidth: %w", err)
  1966. }
  1967. bandwidthDL, err := strconv.ParseInt(r.Form.Get("download_bandwidth"), 10, 64)
  1968. if err != nil {
  1969. return group, fmt.Errorf("invalid download bandwidth: %w", err)
  1970. }
  1971. dataTransferUL, dataTransferDL, dataTransferTotal, err := getTransferLimits(r)
  1972. if err != nil {
  1973. return group, err
  1974. }
  1975. expiresIn, err := strconv.Atoi(r.Form.Get("expires_in"))
  1976. if err != nil {
  1977. return group, fmt.Errorf("invalid expires in: %w", err)
  1978. }
  1979. fsConfig, err := getFsConfigFromPostFields(r)
  1980. if err != nil {
  1981. return group, err
  1982. }
  1983. filters, err := getFiltersFromUserPostFields(r)
  1984. if err != nil {
  1985. return group, err
  1986. }
  1987. group = dataprovider.Group{
  1988. BaseGroup: sdk.BaseGroup{
  1989. Name: strings.TrimSpace(r.Form.Get("name")),
  1990. Description: r.Form.Get("description"),
  1991. },
  1992. UserSettings: dataprovider.GroupUserSettings{
  1993. BaseGroupUserSettings: sdk.BaseGroupUserSettings{
  1994. HomeDir: strings.TrimSpace(r.Form.Get("home_dir")),
  1995. MaxSessions: maxSessions,
  1996. QuotaSize: quotaSize,
  1997. QuotaFiles: quotaFiles,
  1998. Permissions: getSubDirPermissionsFromPostFields(r),
  1999. UploadBandwidth: bandwidthUL,
  2000. DownloadBandwidth: bandwidthDL,
  2001. UploadDataTransfer: dataTransferUL,
  2002. DownloadDataTransfer: dataTransferDL,
  2003. TotalDataTransfer: dataTransferTotal,
  2004. ExpiresIn: expiresIn,
  2005. Filters: filters,
  2006. },
  2007. FsConfig: fsConfig,
  2008. },
  2009. VirtualFolders: getVirtualFoldersFromPostFields(r),
  2010. }
  2011. return group, nil
  2012. }
  2013. func getKeyValsFromPostFields(r *http.Request, key, val string) []dataprovider.KeyValue {
  2014. var res []dataprovider.KeyValue
  2015. for k := range r.Form {
  2016. if strings.HasPrefix(k, key) {
  2017. formKey := r.Form.Get(k)
  2018. idx := strings.TrimPrefix(k, key)
  2019. formVal := strings.TrimSpace(r.Form.Get(fmt.Sprintf("%s%s", val, idx)))
  2020. if formKey != "" && formVal != "" {
  2021. res = append(res, dataprovider.KeyValue{
  2022. Key: formKey,
  2023. Value: formVal,
  2024. })
  2025. }
  2026. }
  2027. }
  2028. return res
  2029. }
  2030. func getFoldersRetentionFromPostFields(r *http.Request) ([]dataprovider.FolderRetention, error) {
  2031. var res []dataprovider.FolderRetention
  2032. for k := range r.Form {
  2033. if strings.HasPrefix(k, "folder_retention_path") {
  2034. folderPath := strings.TrimSpace(r.Form.Get(k))
  2035. if folderPath != "" {
  2036. idx := strings.TrimPrefix(k, "folder_retention_path")
  2037. retention, err := strconv.Atoi(r.Form.Get(fmt.Sprintf("folder_retention_val%s", idx)))
  2038. if err != nil {
  2039. return nil, fmt.Errorf("invalid retention for path %q: %w", folderPath, err)
  2040. }
  2041. options := r.Form[fmt.Sprintf("folder_retention_options%s", idx)]
  2042. res = append(res, dataprovider.FolderRetention{
  2043. Path: folderPath,
  2044. Retention: retention,
  2045. DeleteEmptyDirs: util.Contains(options, "1"),
  2046. IgnoreUserPermissions: util.Contains(options, "2"),
  2047. })
  2048. }
  2049. }
  2050. }
  2051. return res, nil
  2052. }
  2053. func getHTTPPartsFromPostFields(r *http.Request) []dataprovider.HTTPPart {
  2054. var result []dataprovider.HTTPPart
  2055. for k := range r.Form {
  2056. if strings.HasPrefix(k, "http_part_name") {
  2057. partName := strings.TrimSpace(r.Form.Get(k))
  2058. if partName != "" {
  2059. idx := strings.TrimPrefix(k, "http_part_name")
  2060. order, err := strconv.Atoi(idx)
  2061. if err != nil {
  2062. continue
  2063. }
  2064. filePath := strings.TrimSpace(r.Form.Get(fmt.Sprintf("http_part_file%s", idx)))
  2065. body := r.Form.Get(fmt.Sprintf("http_part_body%s", idx))
  2066. concatHeaders := getSliceFromDelimitedValues(r.Form.Get(fmt.Sprintf("http_part_headers%s", idx)), "\n")
  2067. var headers []dataprovider.KeyValue
  2068. for _, h := range concatHeaders {
  2069. values := strings.SplitN(h, ":", 2)
  2070. if len(values) > 1 {
  2071. headers = append(headers, dataprovider.KeyValue{
  2072. Key: strings.TrimSpace(values[0]),
  2073. Value: strings.TrimSpace(values[1]),
  2074. })
  2075. }
  2076. }
  2077. result = append(result, dataprovider.HTTPPart{
  2078. Name: partName,
  2079. Filepath: filePath,
  2080. Headers: headers,
  2081. Body: body,
  2082. Order: order,
  2083. })
  2084. }
  2085. }
  2086. }
  2087. sort.Slice(result, func(i, j int) bool {
  2088. return result[i].Order < result[j].Order
  2089. })
  2090. return result
  2091. }
  2092. func getEventActionOptionsFromPostFields(r *http.Request) (dataprovider.BaseEventActionOptions, error) {
  2093. httpTimeout, err := strconv.Atoi(r.Form.Get("http_timeout"))
  2094. if err != nil {
  2095. return dataprovider.BaseEventActionOptions{}, fmt.Errorf("invalid http timeout: %w", err)
  2096. }
  2097. cmdTimeout, err := strconv.Atoi(r.Form.Get("cmd_timeout"))
  2098. if err != nil {
  2099. return dataprovider.BaseEventActionOptions{}, fmt.Errorf("invalid command timeout: %w", err)
  2100. }
  2101. foldersRetention, err := getFoldersRetentionFromPostFields(r)
  2102. if err != nil {
  2103. return dataprovider.BaseEventActionOptions{}, err
  2104. }
  2105. fsActionType, err := strconv.Atoi(r.Form.Get("fs_action_type"))
  2106. if err != nil {
  2107. return dataprovider.BaseEventActionOptions{}, fmt.Errorf("invalid fs action type: %w", err)
  2108. }
  2109. pwdExpirationThreshold, err := strconv.Atoi(r.Form.Get("pwd_expiration_threshold"))
  2110. if err != nil {
  2111. return dataprovider.BaseEventActionOptions{}, fmt.Errorf("invalid password expiration threshold: %w", err)
  2112. }
  2113. var emailAttachments []string
  2114. if r.Form.Get("email_attachments") != "" {
  2115. emailAttachments = getSliceFromDelimitedValues(r.Form.Get("email_attachments"), ",")
  2116. }
  2117. var cmdArgs []string
  2118. if r.Form.Get("cmd_arguments") != "" {
  2119. cmdArgs = getSliceFromDelimitedValues(r.Form.Get("cmd_arguments"), ",")
  2120. }
  2121. idpMode := 0
  2122. if r.Form.Get("idp_mode") == "1" {
  2123. idpMode = 1
  2124. }
  2125. emailContentType := 0
  2126. if r.Form.Get("email_content_type") == "1" {
  2127. emailContentType = 1
  2128. }
  2129. options := dataprovider.BaseEventActionOptions{
  2130. HTTPConfig: dataprovider.EventActionHTTPConfig{
  2131. Endpoint: strings.TrimSpace(r.Form.Get("http_endpoint")),
  2132. Username: strings.TrimSpace(r.Form.Get("http_username")),
  2133. Password: getSecretFromFormField(r, "http_password"),
  2134. Headers: getKeyValsFromPostFields(r, "http_header_key", "http_header_val"),
  2135. Timeout: httpTimeout,
  2136. SkipTLSVerify: r.Form.Get("http_skip_tls_verify") != "",
  2137. Method: r.Form.Get("http_method"),
  2138. QueryParameters: getKeyValsFromPostFields(r, "http_query_key", "http_query_val"),
  2139. Body: r.Form.Get("http_body"),
  2140. Parts: getHTTPPartsFromPostFields(r),
  2141. },
  2142. CmdConfig: dataprovider.EventActionCommandConfig{
  2143. Cmd: strings.TrimSpace(r.Form.Get("cmd_path")),
  2144. Args: cmdArgs,
  2145. Timeout: cmdTimeout,
  2146. EnvVars: getKeyValsFromPostFields(r, "cmd_env_key", "cmd_env_val"),
  2147. },
  2148. EmailConfig: dataprovider.EventActionEmailConfig{
  2149. Recipients: getSliceFromDelimitedValues(r.Form.Get("email_recipients"), ","),
  2150. Bcc: getSliceFromDelimitedValues(r.Form.Get("email_bcc"), ","),
  2151. Subject: r.Form.Get("email_subject"),
  2152. ContentType: emailContentType,
  2153. Body: r.Form.Get("email_body"),
  2154. Attachments: emailAttachments,
  2155. },
  2156. RetentionConfig: dataprovider.EventActionDataRetentionConfig{
  2157. Folders: foldersRetention,
  2158. },
  2159. FsConfig: dataprovider.EventActionFilesystemConfig{
  2160. Type: fsActionType,
  2161. Renames: getKeyValsFromPostFields(r, "fs_rename_source", "fs_rename_target"),
  2162. Deletes: getSliceFromDelimitedValues(r.Form.Get("fs_delete_paths"), ","),
  2163. MkDirs: getSliceFromDelimitedValues(r.Form.Get("fs_mkdir_paths"), ","),
  2164. Exist: getSliceFromDelimitedValues(r.Form.Get("fs_exist_paths"), ","),
  2165. Copy: getKeyValsFromPostFields(r, "fs_copy_source", "fs_copy_target"),
  2166. Compress: dataprovider.EventActionFsCompress{
  2167. Name: strings.TrimSpace(r.Form.Get("fs_compress_name")),
  2168. Paths: getSliceFromDelimitedValues(r.Form.Get("fs_compress_paths"), ","),
  2169. },
  2170. },
  2171. PwdExpirationConfig: dataprovider.EventActionPasswordExpiration{
  2172. Threshold: pwdExpirationThreshold,
  2173. },
  2174. IDPConfig: dataprovider.EventActionIDPAccountCheck{
  2175. Mode: idpMode,
  2176. TemplateUser: strings.TrimSpace(r.Form.Get("idp_user")),
  2177. TemplateAdmin: strings.TrimSpace(r.Form.Get("idp_admin")),
  2178. },
  2179. }
  2180. return options, nil
  2181. }
  2182. func getEventActionFromPostFields(r *http.Request) (dataprovider.BaseEventAction, error) {
  2183. err := r.ParseForm()
  2184. if err != nil {
  2185. return dataprovider.BaseEventAction{}, err
  2186. }
  2187. actionType, err := strconv.Atoi(r.Form.Get("type"))
  2188. if err != nil {
  2189. return dataprovider.BaseEventAction{}, fmt.Errorf("invalid action type: %w", err)
  2190. }
  2191. options, err := getEventActionOptionsFromPostFields(r)
  2192. if err != nil {
  2193. return dataprovider.BaseEventAction{}, err
  2194. }
  2195. action := dataprovider.BaseEventAction{
  2196. Name: strings.TrimSpace(r.Form.Get("name")),
  2197. Description: r.Form.Get("description"),
  2198. Type: actionType,
  2199. Options: options,
  2200. }
  2201. return action, nil
  2202. }
  2203. func getIDPLoginEventFromPostField(r *http.Request) int {
  2204. switch r.Form.Get("idp_login_event") {
  2205. case "1":
  2206. return 1
  2207. case "2":
  2208. return 2
  2209. default:
  2210. return 0
  2211. }
  2212. }
  2213. func getEventRuleConditionsFromPostFields(r *http.Request) (dataprovider.EventConditions, error) {
  2214. var schedules []dataprovider.Schedule
  2215. var names, groupNames, roleNames, fsPaths []dataprovider.ConditionPattern
  2216. for k := range r.Form {
  2217. if strings.HasPrefix(k, "schedule_hour") {
  2218. hour := strings.TrimSpace(r.Form.Get(k))
  2219. if hour != "" {
  2220. idx := strings.TrimPrefix(k, "schedule_hour")
  2221. dayOfWeek := strings.TrimSpace(r.Form.Get(fmt.Sprintf("schedule_day_of_week%s", idx)))
  2222. dayOfMonth := strings.TrimSpace(r.Form.Get(fmt.Sprintf("schedule_day_of_month%s", idx)))
  2223. month := strings.TrimSpace(r.Form.Get(fmt.Sprintf("schedule_month%s", idx)))
  2224. schedules = append(schedules, dataprovider.Schedule{
  2225. Hours: hour,
  2226. DayOfWeek: dayOfWeek,
  2227. DayOfMonth: dayOfMonth,
  2228. Month: month,
  2229. })
  2230. }
  2231. }
  2232. if strings.HasPrefix(k, "name_pattern") {
  2233. pattern := strings.TrimSpace(r.Form.Get(k))
  2234. if pattern != "" {
  2235. idx := strings.TrimPrefix(k, "name_pattern")
  2236. patternType := r.Form.Get(fmt.Sprintf("type_name_pattern%s", idx))
  2237. names = append(names, dataprovider.ConditionPattern{
  2238. Pattern: pattern,
  2239. InverseMatch: patternType == inversePatternType,
  2240. })
  2241. }
  2242. }
  2243. if strings.HasPrefix(k, "group_name_pattern") {
  2244. pattern := strings.TrimSpace(r.Form.Get(k))
  2245. if pattern != "" {
  2246. idx := strings.TrimPrefix(k, "group_name_pattern")
  2247. patternType := r.Form.Get(fmt.Sprintf("type_group_name_pattern%s", idx))
  2248. groupNames = append(groupNames, dataprovider.ConditionPattern{
  2249. Pattern: pattern,
  2250. InverseMatch: patternType == inversePatternType,
  2251. })
  2252. }
  2253. }
  2254. if strings.HasPrefix(k, "role_name_pattern") {
  2255. pattern := strings.TrimSpace(r.Form.Get(k))
  2256. if pattern != "" {
  2257. idx := strings.TrimPrefix(k, "role_name_pattern")
  2258. patternType := r.Form.Get(fmt.Sprintf("type_role_name_pattern%s", idx))
  2259. roleNames = append(roleNames, dataprovider.ConditionPattern{
  2260. Pattern: pattern,
  2261. InverseMatch: patternType == inversePatternType,
  2262. })
  2263. }
  2264. }
  2265. if strings.HasPrefix(k, "fs_path_pattern") {
  2266. pattern := strings.TrimSpace(r.Form.Get(k))
  2267. if pattern != "" {
  2268. idx := strings.TrimPrefix(k, "fs_path_pattern")
  2269. patternType := r.Form.Get(fmt.Sprintf("type_fs_path_pattern%s", idx))
  2270. fsPaths = append(fsPaths, dataprovider.ConditionPattern{
  2271. Pattern: pattern,
  2272. InverseMatch: patternType == inversePatternType,
  2273. })
  2274. }
  2275. }
  2276. }
  2277. minFileSize, err := util.ParseBytes(r.Form.Get("fs_min_size"))
  2278. if err != nil {
  2279. return dataprovider.EventConditions{}, fmt.Errorf("invalid min file size: %w", err)
  2280. }
  2281. maxFileSize, err := util.ParseBytes(r.Form.Get("fs_max_size"))
  2282. if err != nil {
  2283. return dataprovider.EventConditions{}, fmt.Errorf("invalid max file size: %w", err)
  2284. }
  2285. conditions := dataprovider.EventConditions{
  2286. FsEvents: r.Form["fs_events"],
  2287. ProviderEvents: r.Form["provider_events"],
  2288. IDPLoginEvent: getIDPLoginEventFromPostField(r),
  2289. Schedules: schedules,
  2290. Options: dataprovider.ConditionOptions{
  2291. Names: names,
  2292. GroupNames: groupNames,
  2293. RoleNames: roleNames,
  2294. FsPaths: fsPaths,
  2295. Protocols: r.Form["fs_protocols"],
  2296. ProviderObjects: r.Form["provider_objects"],
  2297. MinFileSize: minFileSize,
  2298. MaxFileSize: maxFileSize,
  2299. ConcurrentExecution: r.Form.Get("concurrent_execution") != "",
  2300. },
  2301. }
  2302. return conditions, nil
  2303. }
  2304. func getEventRuleActionsFromPostFields(r *http.Request) ([]dataprovider.EventAction, error) {
  2305. var actions []dataprovider.EventAction
  2306. for k := range r.Form {
  2307. if strings.HasPrefix(k, "action_name") {
  2308. name := strings.TrimSpace(r.Form.Get(k))
  2309. if name != "" {
  2310. idx := strings.TrimPrefix(k, "action_name")
  2311. order, err := strconv.Atoi(r.Form.Get(fmt.Sprintf("action_order%s", idx)))
  2312. if err != nil {
  2313. return actions, fmt.Errorf("invalid order: %w", err)
  2314. }
  2315. options := r.Form[fmt.Sprintf("action_options%s", idx)]
  2316. actions = append(actions, dataprovider.EventAction{
  2317. BaseEventAction: dataprovider.BaseEventAction{
  2318. Name: name,
  2319. },
  2320. Order: order + 1,
  2321. Options: dataprovider.EventActionOptions{
  2322. IsFailureAction: util.Contains(options, "1"),
  2323. StopOnFailure: util.Contains(options, "2"),
  2324. ExecuteSync: util.Contains(options, "3"),
  2325. },
  2326. })
  2327. }
  2328. }
  2329. }
  2330. return actions, nil
  2331. }
  2332. func getEventRuleFromPostFields(r *http.Request) (dataprovider.EventRule, error) {
  2333. err := r.ParseForm()
  2334. if err != nil {
  2335. return dataprovider.EventRule{}, err
  2336. }
  2337. status, err := strconv.Atoi(r.Form.Get("status"))
  2338. if err != nil {
  2339. return dataprovider.EventRule{}, fmt.Errorf("invalid status: %w", err)
  2340. }
  2341. trigger, err := strconv.Atoi(r.Form.Get("trigger"))
  2342. if err != nil {
  2343. return dataprovider.EventRule{}, fmt.Errorf("invalid trigger: %w", err)
  2344. }
  2345. conditions, err := getEventRuleConditionsFromPostFields(r)
  2346. if err != nil {
  2347. return dataprovider.EventRule{}, err
  2348. }
  2349. actions, err := getEventRuleActionsFromPostFields(r)
  2350. if err != nil {
  2351. return dataprovider.EventRule{}, err
  2352. }
  2353. rule := dataprovider.EventRule{
  2354. Name: strings.TrimSpace(r.Form.Get("name")),
  2355. Status: status,
  2356. Description: r.Form.Get("description"),
  2357. Trigger: trigger,
  2358. Conditions: conditions,
  2359. Actions: actions,
  2360. }
  2361. return rule, nil
  2362. }
  2363. func getRoleFromPostFields(r *http.Request) (dataprovider.Role, error) {
  2364. err := r.ParseForm()
  2365. if err != nil {
  2366. return dataprovider.Role{}, err
  2367. }
  2368. return dataprovider.Role{
  2369. Name: strings.TrimSpace(r.Form.Get("name")),
  2370. Description: r.Form.Get("description"),
  2371. }, nil
  2372. }
  2373. func getIPListEntryFromPostFields(r *http.Request, listType dataprovider.IPListType) (dataprovider.IPListEntry, error) {
  2374. err := r.ParseForm()
  2375. if err != nil {
  2376. return dataprovider.IPListEntry{}, err
  2377. }
  2378. var mode int
  2379. if listType == dataprovider.IPListTypeDefender {
  2380. mode, err = strconv.Atoi(r.Form.Get("mode"))
  2381. if err != nil {
  2382. return dataprovider.IPListEntry{}, fmt.Errorf("invalid mode: %w", err)
  2383. }
  2384. } else {
  2385. mode = 1
  2386. }
  2387. protocols := 0
  2388. for _, proto := range r.Form["protocols"] {
  2389. p, err := strconv.Atoi(proto)
  2390. if err == nil {
  2391. protocols += p
  2392. }
  2393. }
  2394. return dataprovider.IPListEntry{
  2395. IPOrNet: strings.TrimSpace(r.Form.Get("ipornet")),
  2396. Mode: mode,
  2397. Protocols: protocols,
  2398. Description: r.Form.Get("description"),
  2399. }, nil
  2400. }
  2401. func getSFTPConfigsFromPostFields(r *http.Request) *dataprovider.SFTPDConfigs {
  2402. return &dataprovider.SFTPDConfigs{
  2403. HostKeyAlgos: r.Form["sftp_host_key_algos"],
  2404. PublicKeyAlgos: r.Form["sftp_pub_key_algos"],
  2405. Moduli: getSliceFromDelimitedValues(r.Form.Get("sftp_moduli"), ","),
  2406. KexAlgorithms: r.Form["sftp_kex_algos"],
  2407. Ciphers: r.Form["sftp_ciphers"],
  2408. MACs: r.Form["sftp_macs"],
  2409. }
  2410. }
  2411. func getACMEConfigsFromPostFields(r *http.Request) *dataprovider.ACMEConfigs {
  2412. port, err := strconv.Atoi(r.Form.Get("acme_port"))
  2413. if err != nil {
  2414. port = 80
  2415. }
  2416. var protocols int
  2417. for _, val := range r.Form["acme_protocols"] {
  2418. switch val {
  2419. case "1":
  2420. protocols++
  2421. case "2":
  2422. protocols += 2
  2423. case "3":
  2424. protocols += 4
  2425. }
  2426. }
  2427. return &dataprovider.ACMEConfigs{
  2428. Domain: strings.TrimSpace(r.Form.Get("acme_domain")),
  2429. Email: strings.TrimSpace(r.Form.Get("acme_email")),
  2430. HTTP01Challenge: dataprovider.ACMEHTTP01Challenge{Port: port},
  2431. Protocols: protocols,
  2432. }
  2433. }
  2434. func getSMTPConfigsFromPostFields(r *http.Request) *dataprovider.SMTPConfigs {
  2435. port, err := strconv.Atoi(r.Form.Get("smtp_port"))
  2436. if err != nil {
  2437. port = 587
  2438. }
  2439. authType, err := strconv.Atoi(r.Form.Get("smtp_auth"))
  2440. if err != nil {
  2441. authType = 0
  2442. }
  2443. encryption, err := strconv.Atoi(r.Form.Get("smtp_encryption"))
  2444. if err != nil {
  2445. encryption = 0
  2446. }
  2447. debug := 0
  2448. if r.Form.Get("smtp_debug") != "" {
  2449. debug = 1
  2450. }
  2451. oauth2Provider := 0
  2452. if r.Form.Get("smtp_oauth2_provider") == "1" {
  2453. oauth2Provider = 1
  2454. }
  2455. return &dataprovider.SMTPConfigs{
  2456. Host: strings.TrimSpace(r.Form.Get("smtp_host")),
  2457. Port: port,
  2458. From: strings.TrimSpace(r.Form.Get("smtp_from")),
  2459. User: strings.TrimSpace(r.Form.Get("smtp_username")),
  2460. Password: getSecretFromFormField(r, "smtp_password"),
  2461. AuthType: authType,
  2462. Encryption: encryption,
  2463. Domain: strings.TrimSpace(r.Form.Get("smtp_domain")),
  2464. Debug: debug,
  2465. OAuth2: dataprovider.SMTPOAuth2{
  2466. Provider: oauth2Provider,
  2467. Tenant: strings.TrimSpace(r.Form.Get("smtp_oauth2_tenant")),
  2468. ClientID: strings.TrimSpace(r.Form.Get("smtp_oauth2_client_id")),
  2469. ClientSecret: getSecretFromFormField(r, "smtp_oauth2_client_secret"),
  2470. RefreshToken: getSecretFromFormField(r, "smtp_oauth2_refresh_token"),
  2471. },
  2472. }
  2473. }
  2474. func (s *httpdServer) handleWebAdminForgotPwd(w http.ResponseWriter, r *http.Request) {
  2475. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2476. if !smtp.IsEnabled() {
  2477. s.renderNotFoundPage(w, r, errors.New("this page does not exist"))
  2478. return
  2479. }
  2480. s.renderForgotPwdPage(w, r, "", util.GetIPFromRemoteAddress(r.RemoteAddr))
  2481. }
  2482. func (s *httpdServer) handleWebAdminForgotPwdPost(w http.ResponseWriter, r *http.Request) {
  2483. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2484. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2485. err := r.ParseForm()
  2486. if err != nil {
  2487. s.renderForgotPwdPage(w, r, err.Error(), ipAddr)
  2488. return
  2489. }
  2490. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2491. s.renderForbiddenPage(w, r, err.Error())
  2492. return
  2493. }
  2494. err = handleForgotPassword(r, r.Form.Get("username"), true)
  2495. if err != nil {
  2496. var e *util.ValidationError
  2497. if errors.As(err, &e) {
  2498. s.renderForgotPwdPage(w, r, e.GetErrorString(), ipAddr)
  2499. return
  2500. }
  2501. s.renderForgotPwdPage(w, r, err.Error(), ipAddr)
  2502. return
  2503. }
  2504. http.Redirect(w, r, webAdminResetPwdPath, http.StatusFound)
  2505. }
  2506. func (s *httpdServer) handleWebAdminPasswordReset(w http.ResponseWriter, r *http.Request) {
  2507. r.Body = http.MaxBytesReader(w, r.Body, maxLoginBodySize)
  2508. if !smtp.IsEnabled() {
  2509. s.renderNotFoundPage(w, r, errors.New("this page does not exist"))
  2510. return
  2511. }
  2512. s.renderResetPwdPage(w, r, "", util.GetIPFromRemoteAddress(r.RemoteAddr))
  2513. }
  2514. func (s *httpdServer) handleWebAdminTwoFactor(w http.ResponseWriter, r *http.Request) {
  2515. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2516. s.renderTwoFactorPage(w, r, "", util.GetIPFromRemoteAddress(r.RemoteAddr))
  2517. }
  2518. func (s *httpdServer) handleWebAdminTwoFactorRecovery(w http.ResponseWriter, r *http.Request) {
  2519. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2520. s.renderTwoFactorRecoveryPage(w, r, "", util.GetIPFromRemoteAddress(r.RemoteAddr))
  2521. }
  2522. func (s *httpdServer) handleWebAdminMFA(w http.ResponseWriter, r *http.Request) {
  2523. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2524. s.renderMFAPage(w, r)
  2525. }
  2526. func (s *httpdServer) handleWebAdminProfile(w http.ResponseWriter, r *http.Request) {
  2527. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2528. s.renderProfilePage(w, r, "")
  2529. }
  2530. func (s *httpdServer) handleWebAdminChangePwd(w http.ResponseWriter, r *http.Request) {
  2531. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2532. s.renderChangePasswordPage(w, r, "")
  2533. }
  2534. func (s *httpdServer) handleWebAdminProfilePost(w http.ResponseWriter, r *http.Request) {
  2535. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2536. err := r.ParseForm()
  2537. if err != nil {
  2538. s.renderProfilePage(w, r, err.Error())
  2539. return
  2540. }
  2541. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2542. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2543. s.renderForbiddenPage(w, r, err.Error())
  2544. return
  2545. }
  2546. claims, err := getTokenClaims(r)
  2547. if err != nil || claims.Username == "" {
  2548. s.renderProfilePage(w, r, "Invalid token claims")
  2549. return
  2550. }
  2551. admin, err := dataprovider.AdminExists(claims.Username)
  2552. if err != nil {
  2553. s.renderProfilePage(w, r, err.Error())
  2554. return
  2555. }
  2556. admin.Filters.AllowAPIKeyAuth = r.Form.Get("allow_api_key_auth") != ""
  2557. admin.Email = r.Form.Get("email")
  2558. admin.Description = r.Form.Get("description")
  2559. err = dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, ipAddr, admin.Role)
  2560. if err != nil {
  2561. s.renderProfilePage(w, r, err.Error())
  2562. return
  2563. }
  2564. s.renderMessagePage(w, r, "Profile updated", "", http.StatusOK, nil,
  2565. "Your profile has been successfully updated")
  2566. }
  2567. func (s *httpdServer) handleWebMaintenance(w http.ResponseWriter, r *http.Request) {
  2568. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2569. s.renderMaintenancePage(w, r, "")
  2570. }
  2571. func (s *httpdServer) handleWebRestore(w http.ResponseWriter, r *http.Request) {
  2572. r.Body = http.MaxBytesReader(w, r.Body, MaxRestoreSize)
  2573. claims, err := getTokenClaims(r)
  2574. if err != nil || claims.Username == "" {
  2575. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2576. return
  2577. }
  2578. err = r.ParseMultipartForm(MaxRestoreSize)
  2579. if err != nil {
  2580. s.renderMaintenancePage(w, r, err.Error())
  2581. return
  2582. }
  2583. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  2584. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2585. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2586. s.renderForbiddenPage(w, r, err.Error())
  2587. return
  2588. }
  2589. restoreMode, err := strconv.Atoi(r.Form.Get("mode"))
  2590. if err != nil {
  2591. s.renderMaintenancePage(w, r, err.Error())
  2592. return
  2593. }
  2594. scanQuota, err := strconv.Atoi(r.Form.Get("quota"))
  2595. if err != nil {
  2596. s.renderMaintenancePage(w, r, err.Error())
  2597. return
  2598. }
  2599. backupFile, _, err := r.FormFile("backup_file")
  2600. if err != nil {
  2601. s.renderMaintenancePage(w, r, err.Error())
  2602. return
  2603. }
  2604. defer backupFile.Close()
  2605. backupContent, err := io.ReadAll(backupFile)
  2606. if err != nil || len(backupContent) == 0 {
  2607. if len(backupContent) == 0 {
  2608. err = errors.New("backup file size must be greater than 0")
  2609. }
  2610. s.renderMaintenancePage(w, r, err.Error())
  2611. return
  2612. }
  2613. if err := restoreBackup(backupContent, "", scanQuota, restoreMode, claims.Username, ipAddr, claims.Role); err != nil {
  2614. s.renderMaintenancePage(w, r, err.Error())
  2615. return
  2616. }
  2617. s.renderMessagePage(w, r, "Data restored", "", http.StatusOK, nil, "Your backup was successfully restored")
  2618. }
  2619. func (s *httpdServer) handleGetWebAdmins(w http.ResponseWriter, r *http.Request) {
  2620. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2621. limit := defaultQueryLimit
  2622. if _, ok := r.URL.Query()["qlimit"]; ok {
  2623. var err error
  2624. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  2625. if err != nil {
  2626. limit = defaultQueryLimit
  2627. }
  2628. }
  2629. admins := make([]dataprovider.Admin, 0, limit)
  2630. for {
  2631. a, err := dataprovider.GetAdmins(limit, len(admins), dataprovider.OrderASC)
  2632. if err != nil {
  2633. s.renderInternalServerErrorPage(w, r, err)
  2634. return
  2635. }
  2636. admins = append(admins, a...)
  2637. if len(a) < limit {
  2638. break
  2639. }
  2640. }
  2641. data := adminsPage{
  2642. basePage: s.getBasePageData(pageAdminsTitle, webAdminsPath, r),
  2643. Admins: admins,
  2644. }
  2645. renderAdminTemplate(w, templateAdmins, data)
  2646. }
  2647. func (s *httpdServer) handleWebAdminSetupGet(w http.ResponseWriter, r *http.Request) {
  2648. r.Body = http.MaxBytesReader(w, r.Body, maxLoginBodySize)
  2649. if dataprovider.HasAdmin() {
  2650. http.Redirect(w, r, webAdminLoginPath, http.StatusFound)
  2651. return
  2652. }
  2653. s.renderAdminSetupPage(w, r, "", "")
  2654. }
  2655. func (s *httpdServer) handleWebAddAdminGet(w http.ResponseWriter, r *http.Request) {
  2656. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2657. admin := &dataprovider.Admin{
  2658. Status: 1,
  2659. Permissions: []string{dataprovider.PermAdminAny},
  2660. }
  2661. s.renderAddUpdateAdminPage(w, r, admin, "", true)
  2662. }
  2663. func (s *httpdServer) handleWebUpdateAdminGet(w http.ResponseWriter, r *http.Request) {
  2664. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2665. username := getURLParam(r, "username")
  2666. admin, err := dataprovider.AdminExists(username)
  2667. if err == nil {
  2668. s.renderAddUpdateAdminPage(w, r, &admin, "", false)
  2669. } else if errors.Is(err, util.ErrNotFound) {
  2670. s.renderNotFoundPage(w, r, err)
  2671. } else {
  2672. s.renderInternalServerErrorPage(w, r, err)
  2673. }
  2674. }
  2675. func (s *httpdServer) handleWebAddAdminPost(w http.ResponseWriter, r *http.Request) {
  2676. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2677. claims, err := getTokenClaims(r)
  2678. if err != nil || claims.Username == "" {
  2679. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2680. return
  2681. }
  2682. admin, err := getAdminFromPostFields(r)
  2683. if err != nil {
  2684. s.renderAddUpdateAdminPage(w, r, &admin, err.Error(), true)
  2685. return
  2686. }
  2687. if admin.Password == "" && s.binding.isWebAdminLoginFormDisabled() {
  2688. admin.Password = util.GenerateUniqueID()
  2689. }
  2690. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2691. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2692. s.renderForbiddenPage(w, r, err.Error())
  2693. return
  2694. }
  2695. err = dataprovider.AddAdmin(&admin, claims.Username, ipAddr, claims.Role)
  2696. if err != nil {
  2697. s.renderAddUpdateAdminPage(w, r, &admin, err.Error(), true)
  2698. return
  2699. }
  2700. http.Redirect(w, r, webAdminsPath, http.StatusSeeOther)
  2701. }
  2702. func (s *httpdServer) handleWebUpdateAdminPost(w http.ResponseWriter, r *http.Request) {
  2703. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2704. username := getURLParam(r, "username")
  2705. admin, err := dataprovider.AdminExists(username)
  2706. if errors.Is(err, util.ErrNotFound) {
  2707. s.renderNotFoundPage(w, r, err)
  2708. return
  2709. } else if err != nil {
  2710. s.renderInternalServerErrorPage(w, r, err)
  2711. return
  2712. }
  2713. updatedAdmin, err := getAdminFromPostFields(r)
  2714. if err != nil {
  2715. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, err.Error(), false)
  2716. return
  2717. }
  2718. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2719. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2720. s.renderForbiddenPage(w, r, err.Error())
  2721. return
  2722. }
  2723. updatedAdmin.ID = admin.ID
  2724. updatedAdmin.Username = admin.Username
  2725. if updatedAdmin.Password == "" {
  2726. updatedAdmin.Password = admin.Password
  2727. }
  2728. updatedAdmin.Filters.TOTPConfig = admin.Filters.TOTPConfig
  2729. updatedAdmin.Filters.RecoveryCodes = admin.Filters.RecoveryCodes
  2730. claims, err := getTokenClaims(r)
  2731. if err != nil || claims.Username == "" {
  2732. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, "Invalid token claims", false)
  2733. return
  2734. }
  2735. if username == claims.Username {
  2736. if claims.isCriticalPermRemoved(updatedAdmin.Permissions) {
  2737. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, "You cannot remove these permissions to yourself", false)
  2738. return
  2739. }
  2740. if updatedAdmin.Status == 0 {
  2741. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, "You cannot disable yourself", false)
  2742. return
  2743. }
  2744. if updatedAdmin.Role != claims.Role {
  2745. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, "You cannot add/change your role", false)
  2746. return
  2747. }
  2748. }
  2749. err = dataprovider.UpdateAdmin(&updatedAdmin, claims.Username, ipAddr, claims.Role)
  2750. if err != nil {
  2751. s.renderAddUpdateAdminPage(w, r, &updatedAdmin, err.Error(), false)
  2752. return
  2753. }
  2754. http.Redirect(w, r, webAdminsPath, http.StatusSeeOther)
  2755. }
  2756. func (s *httpdServer) handleWebDefenderPage(w http.ResponseWriter, r *http.Request) {
  2757. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2758. data := defenderHostsPage{
  2759. basePage: s.getBasePageData(pageDefenderTitle, webDefenderPath, r),
  2760. DefenderHostsURL: webDefenderHostsPath,
  2761. }
  2762. renderAdminTemplate(w, templateDefender, data)
  2763. }
  2764. func (s *httpdServer) handleGetWebUsers(w http.ResponseWriter, r *http.Request) {
  2765. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2766. claims, err := getTokenClaims(r)
  2767. if err != nil || claims.Username == "" {
  2768. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2769. return
  2770. }
  2771. var limit int
  2772. if _, ok := r.URL.Query()["qlimit"]; ok {
  2773. var err error
  2774. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  2775. if err != nil {
  2776. limit = defaultQueryLimit
  2777. }
  2778. } else {
  2779. limit = defaultQueryLimit
  2780. }
  2781. users := make([]dataprovider.User, 0, limit)
  2782. for {
  2783. u, err := dataprovider.GetUsers(limit, len(users), dataprovider.OrderASC, claims.Role)
  2784. if err != nil {
  2785. s.renderInternalServerErrorPage(w, r, err)
  2786. return
  2787. }
  2788. users = append(users, u...)
  2789. if len(u) < limit {
  2790. break
  2791. }
  2792. }
  2793. data := usersPage{
  2794. basePage: s.getBasePageData(pageUsersTitle, webUsersPath, r),
  2795. Users: users,
  2796. }
  2797. renderAdminTemplate(w, templateUsers, data)
  2798. }
  2799. func (s *httpdServer) handleWebTemplateFolderGet(w http.ResponseWriter, r *http.Request) {
  2800. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2801. if r.URL.Query().Get("from") != "" {
  2802. name := r.URL.Query().Get("from")
  2803. folder, err := dataprovider.GetFolderByName(name)
  2804. if err == nil {
  2805. folder.FsConfig.SetEmptySecrets()
  2806. s.renderFolderPage(w, r, folder, folderPageModeTemplate, "")
  2807. } else if errors.Is(err, util.ErrNotFound) {
  2808. s.renderNotFoundPage(w, r, err)
  2809. } else {
  2810. s.renderInternalServerErrorPage(w, r, err)
  2811. }
  2812. } else {
  2813. folder := vfs.BaseVirtualFolder{}
  2814. s.renderFolderPage(w, r, folder, folderPageModeTemplate, "")
  2815. }
  2816. }
  2817. func (s *httpdServer) handleWebTemplateFolderPost(w http.ResponseWriter, r *http.Request) {
  2818. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2819. claims, err := getTokenClaims(r)
  2820. if err != nil || claims.Username == "" {
  2821. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2822. return
  2823. }
  2824. templateFolder := vfs.BaseVirtualFolder{}
  2825. err = r.ParseMultipartForm(maxRequestSize)
  2826. if err != nil {
  2827. s.renderMessagePage(w, r, "Error parsing folders fields", "", http.StatusBadRequest, err, "")
  2828. return
  2829. }
  2830. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  2831. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2832. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2833. s.renderForbiddenPage(w, r, err.Error())
  2834. return
  2835. }
  2836. templateFolder.MappedPath = r.Form.Get("mapped_path")
  2837. templateFolder.Description = r.Form.Get("description")
  2838. fsConfig, err := getFsConfigFromPostFields(r)
  2839. if err != nil {
  2840. s.renderMessagePage(w, r, "Error parsing folders fields", "", http.StatusBadRequest, err, "")
  2841. return
  2842. }
  2843. templateFolder.FsConfig = fsConfig
  2844. var dump dataprovider.BackupData
  2845. dump.Version = dataprovider.DumpVersion
  2846. foldersFields := getFoldersForTemplate(r)
  2847. for _, tmpl := range foldersFields {
  2848. f := getFolderFromTemplate(templateFolder, tmpl)
  2849. if err := dataprovider.ValidateFolder(&f); err != nil {
  2850. s.renderMessagePage(w, r, "Folder validation error", fmt.Sprintf("Error validating folder %q", f.Name),
  2851. http.StatusBadRequest, err, "")
  2852. return
  2853. }
  2854. dump.Folders = append(dump.Folders, f)
  2855. }
  2856. if len(dump.Folders) == 0 {
  2857. s.renderMessagePage(w, r, "No folders defined", "No valid folders defined, unable to complete the requested action",
  2858. http.StatusBadRequest, nil, "")
  2859. return
  2860. }
  2861. if r.Form.Get("form_action") == "export_from_template" {
  2862. w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"sftpgo-%v-folders-from-template.json\"",
  2863. len(dump.Folders)))
  2864. render.JSON(w, r, dump)
  2865. return
  2866. }
  2867. if err = RestoreFolders(dump.Folders, "", 1, 0, claims.Username, ipAddr, claims.Role); err != nil {
  2868. s.renderMessagePage(w, r, "Unable to save folders", "Cannot save the defined folders:",
  2869. getRespStatus(err), err, "")
  2870. return
  2871. }
  2872. http.Redirect(w, r, webFoldersPath, http.StatusSeeOther)
  2873. }
  2874. func (s *httpdServer) handleWebTemplateUserGet(w http.ResponseWriter, r *http.Request) {
  2875. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2876. tokenAdmin := getAdminFromToken(r)
  2877. admin, err := dataprovider.AdminExists(tokenAdmin.Username)
  2878. if err != nil {
  2879. s.renderInternalServerErrorPage(w, r, fmt.Errorf("unable to get the admin %q: %w", tokenAdmin.Username, err))
  2880. return
  2881. }
  2882. if r.URL.Query().Get("from") != "" {
  2883. username := r.URL.Query().Get("from")
  2884. user, err := dataprovider.UserExists(username, admin.Role)
  2885. if err == nil {
  2886. user.SetEmptySecrets()
  2887. user.PublicKeys = nil
  2888. user.Email = ""
  2889. user.Description = ""
  2890. if user.ExpirationDate == 0 && admin.Filters.Preferences.DefaultUsersExpiration > 0 {
  2891. user.ExpirationDate = util.GetTimeAsMsSinceEpoch(time.Now().Add(24 * time.Hour * time.Duration(admin.Filters.Preferences.DefaultUsersExpiration)))
  2892. }
  2893. s.renderUserPage(w, r, &user, userPageModeTemplate, "", &admin)
  2894. } else if errors.Is(err, util.ErrNotFound) {
  2895. s.renderNotFoundPage(w, r, err)
  2896. } else {
  2897. s.renderInternalServerErrorPage(w, r, err)
  2898. }
  2899. } else {
  2900. user := dataprovider.User{BaseUser: sdk.BaseUser{
  2901. Status: 1,
  2902. Permissions: map[string][]string{
  2903. "/": {dataprovider.PermAny},
  2904. },
  2905. }}
  2906. if admin.Filters.Preferences.DefaultUsersExpiration > 0 {
  2907. user.ExpirationDate = util.GetTimeAsMsSinceEpoch(time.Now().Add(24 * time.Hour * time.Duration(admin.Filters.Preferences.DefaultUsersExpiration)))
  2908. }
  2909. s.renderUserPage(w, r, &user, userPageModeTemplate, "", &admin)
  2910. }
  2911. }
  2912. func (s *httpdServer) handleWebTemplateUserPost(w http.ResponseWriter, r *http.Request) {
  2913. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2914. claims, err := getTokenClaims(r)
  2915. if err != nil || claims.Username == "" {
  2916. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2917. return
  2918. }
  2919. templateUser, err := getUserFromPostFields(r)
  2920. if err != nil {
  2921. s.renderMessagePage(w, r, "Error parsing user fields", "", http.StatusBadRequest, err, "")
  2922. return
  2923. }
  2924. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  2925. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  2926. s.renderForbiddenPage(w, r, err.Error())
  2927. return
  2928. }
  2929. var dump dataprovider.BackupData
  2930. dump.Version = dataprovider.DumpVersion
  2931. userTmplFields := getUsersForTemplate(r)
  2932. for _, tmpl := range userTmplFields {
  2933. u := getUserFromTemplate(templateUser, tmpl)
  2934. if err := dataprovider.ValidateUser(&u); err != nil {
  2935. s.renderMessagePage(w, r, "User validation error", fmt.Sprintf("Error validating user %q", u.Username),
  2936. http.StatusBadRequest, err, "")
  2937. return
  2938. }
  2939. // to create a template the "manage_system" permission is required, so role admins cannot use
  2940. // this method, we don't need to force the role
  2941. dump.Users = append(dump.Users, u)
  2942. for _, folder := range u.VirtualFolders {
  2943. if !dump.HasFolder(folder.Name) {
  2944. dump.Folders = append(dump.Folders, folder.BaseVirtualFolder)
  2945. }
  2946. }
  2947. }
  2948. if len(dump.Users) == 0 {
  2949. s.renderMessagePage(w, r, "No users defined", "No valid users defined, unable to complete the requested action",
  2950. http.StatusBadRequest, nil, "")
  2951. return
  2952. }
  2953. if r.Form.Get("form_action") == "export_from_template" {
  2954. w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"sftpgo-%v-users-from-template.json\"",
  2955. len(dump.Users)))
  2956. render.JSON(w, r, dump)
  2957. return
  2958. }
  2959. if err = RestoreUsers(dump.Users, "", 1, 0, claims.Username, ipAddr, claims.Role); err != nil {
  2960. s.renderMessagePage(w, r, "Unable to save users", "Cannot save the defined users:",
  2961. getRespStatus(err), err, "")
  2962. return
  2963. }
  2964. http.Redirect(w, r, webUsersPath, http.StatusSeeOther)
  2965. }
  2966. func (s *httpdServer) handleWebAddUserGet(w http.ResponseWriter, r *http.Request) {
  2967. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2968. tokenAdmin := getAdminFromToken(r)
  2969. admin, err := dataprovider.AdminExists(tokenAdmin.Username)
  2970. if err != nil {
  2971. s.renderInternalServerErrorPage(w, r, fmt.Errorf("unable to get the admin %q: %w", tokenAdmin.Username, err))
  2972. return
  2973. }
  2974. user := dataprovider.User{BaseUser: sdk.BaseUser{
  2975. Status: 1,
  2976. Permissions: map[string][]string{
  2977. "/": {dataprovider.PermAny},
  2978. }},
  2979. }
  2980. if admin.Filters.Preferences.DefaultUsersExpiration > 0 {
  2981. user.ExpirationDate = util.GetTimeAsMsSinceEpoch(time.Now().Add(24 * time.Hour * time.Duration(admin.Filters.Preferences.DefaultUsersExpiration)))
  2982. }
  2983. s.renderUserPage(w, r, &user, userPageModeAdd, "", &admin)
  2984. }
  2985. func (s *httpdServer) handleWebUpdateUserGet(w http.ResponseWriter, r *http.Request) {
  2986. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  2987. claims, err := getTokenClaims(r)
  2988. if err != nil || claims.Username == "" {
  2989. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  2990. return
  2991. }
  2992. username := getURLParam(r, "username")
  2993. user, err := dataprovider.UserExists(username, claims.Role)
  2994. if err == nil {
  2995. s.renderUserPage(w, r, &user, userPageModeUpdate, "", nil)
  2996. } else if errors.Is(err, util.ErrNotFound) {
  2997. s.renderNotFoundPage(w, r, err)
  2998. } else {
  2999. s.renderInternalServerErrorPage(w, r, err)
  3000. }
  3001. }
  3002. func (s *httpdServer) handleWebAddUserPost(w http.ResponseWriter, r *http.Request) {
  3003. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3004. claims, err := getTokenClaims(r)
  3005. if err != nil || claims.Username == "" {
  3006. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3007. return
  3008. }
  3009. user, err := getUserFromPostFields(r)
  3010. if err != nil {
  3011. s.renderUserPage(w, r, &user, userPageModeAdd, err.Error(), nil)
  3012. return
  3013. }
  3014. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3015. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3016. s.renderForbiddenPage(w, r, err.Error())
  3017. return
  3018. }
  3019. user = getUserFromTemplate(user, userTemplateFields{
  3020. Username: user.Username,
  3021. Password: user.Password,
  3022. PublicKeys: user.PublicKeys,
  3023. })
  3024. if claims.Role != "" {
  3025. user.Role = claims.Role
  3026. }
  3027. user.Filters.RecoveryCodes = nil
  3028. user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
  3029. Enabled: false,
  3030. }
  3031. err = dataprovider.AddUser(&user, claims.Username, ipAddr, claims.Role)
  3032. if err != nil {
  3033. s.renderUserPage(w, r, &user, userPageModeAdd, err.Error(), nil)
  3034. return
  3035. }
  3036. http.Redirect(w, r, webUsersPath, http.StatusSeeOther)
  3037. }
  3038. func (s *httpdServer) handleWebUpdateUserPost(w http.ResponseWriter, r *http.Request) {
  3039. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3040. claims, err := getTokenClaims(r)
  3041. if err != nil || claims.Username == "" {
  3042. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3043. return
  3044. }
  3045. username := getURLParam(r, "username")
  3046. user, err := dataprovider.UserExists(username, claims.Role)
  3047. if errors.Is(err, util.ErrNotFound) {
  3048. s.renderNotFoundPage(w, r, err)
  3049. return
  3050. } else if err != nil {
  3051. s.renderInternalServerErrorPage(w, r, err)
  3052. return
  3053. }
  3054. updatedUser, err := getUserFromPostFields(r)
  3055. if err != nil {
  3056. s.renderUserPage(w, r, &user, userPageModeUpdate, err.Error(), nil)
  3057. return
  3058. }
  3059. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3060. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3061. s.renderForbiddenPage(w, r, err.Error())
  3062. return
  3063. }
  3064. updatedUser.ID = user.ID
  3065. updatedUser.Username = user.Username
  3066. updatedUser.Filters.RecoveryCodes = user.Filters.RecoveryCodes
  3067. updatedUser.Filters.TOTPConfig = user.Filters.TOTPConfig
  3068. updatedUser.LastPasswordChange = user.LastPasswordChange
  3069. updatedUser.SetEmptySecretsIfNil()
  3070. if updatedUser.Password == redactedSecret {
  3071. updatedUser.Password = user.Password
  3072. }
  3073. updateEncryptedSecrets(&updatedUser.FsConfig, user.FsConfig.S3Config.AccessSecret, user.FsConfig.AzBlobConfig.AccountKey,
  3074. user.FsConfig.AzBlobConfig.SASURL, user.FsConfig.GCSConfig.Credentials, user.FsConfig.CryptConfig.Passphrase,
  3075. user.FsConfig.SFTPConfig.Password, user.FsConfig.SFTPConfig.PrivateKey, user.FsConfig.SFTPConfig.KeyPassphrase,
  3076. user.FsConfig.HTTPConfig.Password, user.FsConfig.HTTPConfig.APIKey)
  3077. updatedUser = getUserFromTemplate(updatedUser, userTemplateFields{
  3078. Username: updatedUser.Username,
  3079. Password: updatedUser.Password,
  3080. PublicKeys: updatedUser.PublicKeys,
  3081. })
  3082. if claims.Role != "" {
  3083. updatedUser.Role = claims.Role
  3084. }
  3085. err = dataprovider.UpdateUser(&updatedUser, claims.Username, ipAddr, claims.Role)
  3086. if err != nil {
  3087. s.renderUserPage(w, r, &updatedUser, userPageModeUpdate, err.Error(), nil)
  3088. return
  3089. }
  3090. if r.Form.Get("disconnect") != "" {
  3091. disconnectUser(user.Username, claims.Username, claims.Role)
  3092. }
  3093. http.Redirect(w, r, webUsersPath, http.StatusSeeOther)
  3094. }
  3095. func (s *httpdServer) handleWebGetStatus(w http.ResponseWriter, r *http.Request) {
  3096. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3097. data := statusPage{
  3098. basePage: s.getBasePageData(pageStatusTitle, webStatusPath, r),
  3099. Status: getServicesStatus(),
  3100. }
  3101. renderAdminTemplate(w, templateStatus, data)
  3102. }
  3103. func (s *httpdServer) handleWebGetConnections(w http.ResponseWriter, r *http.Request) {
  3104. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3105. claims, err := getTokenClaims(r)
  3106. if err != nil || claims.Username == "" {
  3107. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3108. return
  3109. }
  3110. connectionStats := common.Connections.GetStats(claims.Role)
  3111. connectionStats = append(connectionStats, getNodesConnections(claims.Username, claims.Role)...)
  3112. data := connectionsPage{
  3113. basePage: s.getBasePageData(pageConnectionsTitle, webConnectionsPath, r),
  3114. Connections: connectionStats,
  3115. }
  3116. renderAdminTemplate(w, templateConnections, data)
  3117. }
  3118. func (s *httpdServer) handleWebAddFolderGet(w http.ResponseWriter, r *http.Request) {
  3119. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3120. s.renderFolderPage(w, r, vfs.BaseVirtualFolder{}, folderPageModeAdd, "")
  3121. }
  3122. func (s *httpdServer) handleWebAddFolderPost(w http.ResponseWriter, r *http.Request) {
  3123. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3124. claims, err := getTokenClaims(r)
  3125. if err != nil || claims.Username == "" {
  3126. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3127. return
  3128. }
  3129. folder := vfs.BaseVirtualFolder{}
  3130. err = r.ParseMultipartForm(maxRequestSize)
  3131. if err != nil {
  3132. s.renderFolderPage(w, r, folder, folderPageModeAdd, err.Error())
  3133. return
  3134. }
  3135. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  3136. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3137. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3138. s.renderForbiddenPage(w, r, err.Error())
  3139. return
  3140. }
  3141. folder.MappedPath = strings.TrimSpace(r.Form.Get("mapped_path"))
  3142. folder.Name = strings.TrimSpace(r.Form.Get("name"))
  3143. folder.Description = r.Form.Get("description")
  3144. fsConfig, err := getFsConfigFromPostFields(r)
  3145. if err != nil {
  3146. s.renderFolderPage(w, r, folder, folderPageModeAdd, err.Error())
  3147. return
  3148. }
  3149. folder.FsConfig = fsConfig
  3150. folder = getFolderFromTemplate(folder, folder.Name)
  3151. err = dataprovider.AddFolder(&folder, claims.Username, ipAddr, claims.Role)
  3152. if err == nil {
  3153. http.Redirect(w, r, webFoldersPath, http.StatusSeeOther)
  3154. } else {
  3155. s.renderFolderPage(w, r, folder, folderPageModeAdd, err.Error())
  3156. }
  3157. }
  3158. func (s *httpdServer) handleWebUpdateFolderGet(w http.ResponseWriter, r *http.Request) {
  3159. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3160. name := getURLParam(r, "name")
  3161. folder, err := dataprovider.GetFolderByName(name)
  3162. if err == nil {
  3163. s.renderFolderPage(w, r, folder, folderPageModeUpdate, "")
  3164. } else if errors.Is(err, util.ErrNotFound) {
  3165. s.renderNotFoundPage(w, r, err)
  3166. } else {
  3167. s.renderInternalServerErrorPage(w, r, err)
  3168. }
  3169. }
  3170. func (s *httpdServer) handleWebUpdateFolderPost(w http.ResponseWriter, r *http.Request) {
  3171. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3172. claims, err := getTokenClaims(r)
  3173. if err != nil || claims.Username == "" {
  3174. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3175. return
  3176. }
  3177. name := getURLParam(r, "name")
  3178. folder, err := dataprovider.GetFolderByName(name)
  3179. if errors.Is(err, util.ErrNotFound) {
  3180. s.renderNotFoundPage(w, r, err)
  3181. return
  3182. } else if err != nil {
  3183. s.renderInternalServerErrorPage(w, r, err)
  3184. return
  3185. }
  3186. err = r.ParseMultipartForm(maxRequestSize)
  3187. if err != nil {
  3188. s.renderFolderPage(w, r, folder, folderPageModeUpdate, err.Error())
  3189. return
  3190. }
  3191. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  3192. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3193. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3194. s.renderForbiddenPage(w, r, err.Error())
  3195. return
  3196. }
  3197. fsConfig, err := getFsConfigFromPostFields(r)
  3198. if err != nil {
  3199. s.renderFolderPage(w, r, folder, folderPageModeUpdate, err.Error())
  3200. return
  3201. }
  3202. updatedFolder := vfs.BaseVirtualFolder{
  3203. MappedPath: strings.TrimSpace(r.Form.Get("mapped_path")),
  3204. Description: r.Form.Get("description"),
  3205. }
  3206. updatedFolder.ID = folder.ID
  3207. updatedFolder.Name = folder.Name
  3208. updatedFolder.FsConfig = fsConfig
  3209. updatedFolder.FsConfig.SetEmptySecretsIfNil()
  3210. updateEncryptedSecrets(&updatedFolder.FsConfig, folder.FsConfig.S3Config.AccessSecret, folder.FsConfig.AzBlobConfig.AccountKey,
  3211. folder.FsConfig.AzBlobConfig.SASURL, folder.FsConfig.GCSConfig.Credentials, folder.FsConfig.CryptConfig.Passphrase,
  3212. folder.FsConfig.SFTPConfig.Password, folder.FsConfig.SFTPConfig.PrivateKey, folder.FsConfig.SFTPConfig.KeyPassphrase,
  3213. folder.FsConfig.HTTPConfig.Password, folder.FsConfig.HTTPConfig.APIKey)
  3214. updatedFolder = getFolderFromTemplate(updatedFolder, updatedFolder.Name)
  3215. err = dataprovider.UpdateFolder(&updatedFolder, folder.Users, folder.Groups, claims.Username, ipAddr, claims.Role)
  3216. if err != nil {
  3217. s.renderFolderPage(w, r, updatedFolder, folderPageModeUpdate, err.Error())
  3218. return
  3219. }
  3220. http.Redirect(w, r, webFoldersPath, http.StatusSeeOther)
  3221. }
  3222. func (s *httpdServer) getWebVirtualFolders(w http.ResponseWriter, r *http.Request, limit int, minimal bool) ([]vfs.BaseVirtualFolder, error) {
  3223. folders := make([]vfs.BaseVirtualFolder, 0, limit)
  3224. for {
  3225. f, err := dataprovider.GetFolders(limit, len(folders), dataprovider.OrderASC, minimal)
  3226. if err != nil {
  3227. s.renderInternalServerErrorPage(w, r, err)
  3228. return folders, err
  3229. }
  3230. folders = append(folders, f...)
  3231. if len(f) < limit {
  3232. break
  3233. }
  3234. }
  3235. return folders, nil
  3236. }
  3237. func (s *httpdServer) handleWebGetFolders(w http.ResponseWriter, r *http.Request) {
  3238. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3239. limit := defaultQueryLimit
  3240. if _, ok := r.URL.Query()["qlimit"]; ok {
  3241. var err error
  3242. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  3243. if err != nil {
  3244. limit = defaultQueryLimit
  3245. }
  3246. }
  3247. folders, err := s.getWebVirtualFolders(w, r, limit, false)
  3248. if err != nil {
  3249. return
  3250. }
  3251. data := foldersPage{
  3252. basePage: s.getBasePageData(pageFoldersTitle, webFoldersPath, r),
  3253. Folders: folders,
  3254. }
  3255. renderAdminTemplate(w, templateFolders, data)
  3256. }
  3257. func (s *httpdServer) getWebGroups(w http.ResponseWriter, r *http.Request, limit int, minimal bool) ([]dataprovider.Group, error) {
  3258. groups := make([]dataprovider.Group, 0, limit)
  3259. for {
  3260. f, err := dataprovider.GetGroups(limit, len(groups), dataprovider.OrderASC, minimal)
  3261. if err != nil {
  3262. s.renderInternalServerErrorPage(w, r, err)
  3263. return groups, err
  3264. }
  3265. groups = append(groups, f...)
  3266. if len(f) < limit {
  3267. break
  3268. }
  3269. }
  3270. return groups, nil
  3271. }
  3272. func (s *httpdServer) handleWebGetGroups(w http.ResponseWriter, r *http.Request) {
  3273. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3274. limit := defaultQueryLimit
  3275. if _, ok := r.URL.Query()["qlimit"]; ok {
  3276. var err error
  3277. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  3278. if err != nil {
  3279. limit = defaultQueryLimit
  3280. }
  3281. }
  3282. groups, err := s.getWebGroups(w, r, limit, false)
  3283. if err != nil {
  3284. return
  3285. }
  3286. data := groupsPage{
  3287. basePage: s.getBasePageData(pageGroupsTitle, webGroupsPath, r),
  3288. Groups: groups,
  3289. }
  3290. renderAdminTemplate(w, templateGroups, data)
  3291. }
  3292. func (s *httpdServer) handleWebAddGroupGet(w http.ResponseWriter, r *http.Request) {
  3293. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3294. s.renderGroupPage(w, r, dataprovider.Group{}, genericPageModeAdd, "")
  3295. }
  3296. func (s *httpdServer) handleWebAddGroupPost(w http.ResponseWriter, r *http.Request) {
  3297. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3298. claims, err := getTokenClaims(r)
  3299. if err != nil || claims.Username == "" {
  3300. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3301. return
  3302. }
  3303. group, err := getGroupFromPostFields(r)
  3304. if err != nil {
  3305. s.renderGroupPage(w, r, group, genericPageModeAdd, err.Error())
  3306. return
  3307. }
  3308. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3309. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3310. s.renderForbiddenPage(w, r, err.Error())
  3311. return
  3312. }
  3313. err = dataprovider.AddGroup(&group, claims.Username, ipAddr, claims.Role)
  3314. if err != nil {
  3315. s.renderGroupPage(w, r, group, genericPageModeAdd, err.Error())
  3316. return
  3317. }
  3318. http.Redirect(w, r, webGroupsPath, http.StatusSeeOther)
  3319. }
  3320. func (s *httpdServer) handleWebUpdateGroupGet(w http.ResponseWriter, r *http.Request) {
  3321. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3322. name := getURLParam(r, "name")
  3323. group, err := dataprovider.GroupExists(name)
  3324. if err == nil {
  3325. s.renderGroupPage(w, r, group, genericPageModeUpdate, "")
  3326. } else if errors.Is(err, util.ErrNotFound) {
  3327. s.renderNotFoundPage(w, r, err)
  3328. } else {
  3329. s.renderInternalServerErrorPage(w, r, err)
  3330. }
  3331. }
  3332. func (s *httpdServer) handleWebUpdateGroupPost(w http.ResponseWriter, r *http.Request) {
  3333. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3334. claims, err := getTokenClaims(r)
  3335. if err != nil || claims.Username == "" {
  3336. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3337. return
  3338. }
  3339. name := getURLParam(r, "name")
  3340. group, err := dataprovider.GroupExists(name)
  3341. if errors.Is(err, util.ErrNotFound) {
  3342. s.renderNotFoundPage(w, r, err)
  3343. return
  3344. } else if err != nil {
  3345. s.renderInternalServerErrorPage(w, r, err)
  3346. return
  3347. }
  3348. updatedGroup, err := getGroupFromPostFields(r)
  3349. if err != nil {
  3350. s.renderGroupPage(w, r, group, genericPageModeUpdate, err.Error())
  3351. return
  3352. }
  3353. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3354. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3355. s.renderForbiddenPage(w, r, err.Error())
  3356. return
  3357. }
  3358. updatedGroup.ID = group.ID
  3359. updatedGroup.Name = group.Name
  3360. updatedGroup.SetEmptySecretsIfNil()
  3361. updateEncryptedSecrets(&updatedGroup.UserSettings.FsConfig, group.UserSettings.FsConfig.S3Config.AccessSecret,
  3362. group.UserSettings.FsConfig.AzBlobConfig.AccountKey, group.UserSettings.FsConfig.AzBlobConfig.SASURL,
  3363. group.UserSettings.FsConfig.GCSConfig.Credentials, group.UserSettings.FsConfig.CryptConfig.Passphrase,
  3364. group.UserSettings.FsConfig.SFTPConfig.Password, group.UserSettings.FsConfig.SFTPConfig.PrivateKey,
  3365. group.UserSettings.FsConfig.SFTPConfig.KeyPassphrase, group.UserSettings.FsConfig.HTTPConfig.Password,
  3366. group.UserSettings.FsConfig.HTTPConfig.APIKey)
  3367. err = dataprovider.UpdateGroup(&updatedGroup, group.Users, claims.Username, ipAddr, claims.Role)
  3368. if err != nil {
  3369. s.renderGroupPage(w, r, updatedGroup, genericPageModeUpdate, err.Error())
  3370. return
  3371. }
  3372. http.Redirect(w, r, webGroupsPath, http.StatusSeeOther)
  3373. }
  3374. func (s *httpdServer) getWebEventActions(w http.ResponseWriter, r *http.Request, limit int, minimal bool,
  3375. ) ([]dataprovider.BaseEventAction, error) {
  3376. actions := make([]dataprovider.BaseEventAction, 0, limit)
  3377. for {
  3378. res, err := dataprovider.GetEventActions(limit, len(actions), dataprovider.OrderASC, minimal)
  3379. if err != nil {
  3380. s.renderInternalServerErrorPage(w, r, err)
  3381. return actions, err
  3382. }
  3383. actions = append(actions, res...)
  3384. if len(res) < limit {
  3385. break
  3386. }
  3387. }
  3388. return actions, nil
  3389. }
  3390. func (s *httpdServer) handleWebGetEventActions(w http.ResponseWriter, r *http.Request) {
  3391. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3392. limit := defaultQueryLimit
  3393. if _, ok := r.URL.Query()["qlimit"]; ok {
  3394. var err error
  3395. limit, err = strconv.Atoi(r.URL.Query().Get("qlimit"))
  3396. if err != nil {
  3397. limit = defaultQueryLimit
  3398. }
  3399. }
  3400. actions, err := s.getWebEventActions(w, r, limit, false)
  3401. if err != nil {
  3402. return
  3403. }
  3404. data := eventActionsPage{
  3405. basePage: s.getBasePageData(pageEventActionsTitle, webAdminEventActionsPath, r),
  3406. Actions: actions,
  3407. }
  3408. renderAdminTemplate(w, templateEventActions, data)
  3409. }
  3410. func (s *httpdServer) handleWebAddEventActionGet(w http.ResponseWriter, r *http.Request) {
  3411. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3412. action := dataprovider.BaseEventAction{
  3413. Type: dataprovider.ActionTypeHTTP,
  3414. }
  3415. s.renderEventActionPage(w, r, action, genericPageModeAdd, "")
  3416. }
  3417. func (s *httpdServer) handleWebAddEventActionPost(w http.ResponseWriter, r *http.Request) {
  3418. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3419. claims, err := getTokenClaims(r)
  3420. if err != nil || claims.Username == "" {
  3421. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3422. return
  3423. }
  3424. action, err := getEventActionFromPostFields(r)
  3425. if err != nil {
  3426. s.renderEventActionPage(w, r, action, genericPageModeAdd, err.Error())
  3427. return
  3428. }
  3429. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3430. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3431. s.renderForbiddenPage(w, r, err.Error())
  3432. return
  3433. }
  3434. if err = dataprovider.AddEventAction(&action, claims.Username, ipAddr, claims.Role); err != nil {
  3435. s.renderEventActionPage(w, r, action, genericPageModeAdd, err.Error())
  3436. return
  3437. }
  3438. http.Redirect(w, r, webAdminEventActionsPath, http.StatusSeeOther)
  3439. }
  3440. func (s *httpdServer) handleWebUpdateEventActionGet(w http.ResponseWriter, r *http.Request) {
  3441. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3442. name := getURLParam(r, "name")
  3443. action, err := dataprovider.EventActionExists(name)
  3444. if err == nil {
  3445. s.renderEventActionPage(w, r, action, genericPageModeUpdate, "")
  3446. } else if errors.Is(err, util.ErrNotFound) {
  3447. s.renderNotFoundPage(w, r, err)
  3448. } else {
  3449. s.renderInternalServerErrorPage(w, r, err)
  3450. }
  3451. }
  3452. func (s *httpdServer) handleWebUpdateEventActionPost(w http.ResponseWriter, r *http.Request) {
  3453. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3454. claims, err := getTokenClaims(r)
  3455. if err != nil || claims.Username == "" {
  3456. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3457. return
  3458. }
  3459. name := getURLParam(r, "name")
  3460. action, err := dataprovider.EventActionExists(name)
  3461. if errors.Is(err, util.ErrNotFound) {
  3462. s.renderNotFoundPage(w, r, err)
  3463. return
  3464. } else if err != nil {
  3465. s.renderInternalServerErrorPage(w, r, err)
  3466. return
  3467. }
  3468. updatedAction, err := getEventActionFromPostFields(r)
  3469. if err != nil {
  3470. s.renderEventActionPage(w, r, updatedAction, genericPageModeUpdate, err.Error())
  3471. return
  3472. }
  3473. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3474. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3475. s.renderForbiddenPage(w, r, err.Error())
  3476. return
  3477. }
  3478. updatedAction.ID = action.ID
  3479. updatedAction.Name = action.Name
  3480. updatedAction.Options.SetEmptySecretsIfNil()
  3481. switch updatedAction.Type {
  3482. case dataprovider.ActionTypeHTTP:
  3483. if updatedAction.Options.HTTPConfig.Password.IsNotPlainAndNotEmpty() {
  3484. updatedAction.Options.HTTPConfig.Password = action.Options.HTTPConfig.Password
  3485. }
  3486. }
  3487. err = dataprovider.UpdateEventAction(&updatedAction, claims.Username, ipAddr, claims.Role)
  3488. if err != nil {
  3489. s.renderEventActionPage(w, r, updatedAction, genericPageModeUpdate, err.Error())
  3490. return
  3491. }
  3492. http.Redirect(w, r, webAdminEventActionsPath, http.StatusSeeOther)
  3493. }
  3494. func (s *httpdServer) handleWebGetEventRules(w http.ResponseWriter, r *http.Request) {
  3495. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3496. limit := defaultQueryLimit
  3497. if _, ok := r.URL.Query()["qlimit"]; ok {
  3498. if lim, err := strconv.Atoi(r.URL.Query().Get("qlimit")); err == nil {
  3499. limit = lim
  3500. }
  3501. }
  3502. rules := make([]dataprovider.EventRule, 0, limit)
  3503. for {
  3504. res, err := dataprovider.GetEventRules(limit, len(rules), dataprovider.OrderASC)
  3505. if err != nil {
  3506. s.renderInternalServerErrorPage(w, r, err)
  3507. return
  3508. }
  3509. rules = append(rules, res...)
  3510. if len(res) < limit {
  3511. break
  3512. }
  3513. }
  3514. data := eventRulesPage{
  3515. basePage: s.getBasePageData(pageEventRulesTitle, webAdminEventRulesPath, r),
  3516. Rules: rules,
  3517. }
  3518. renderAdminTemplate(w, templateEventRules, data)
  3519. }
  3520. func (s *httpdServer) handleWebAddEventRuleGet(w http.ResponseWriter, r *http.Request) {
  3521. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3522. rule := dataprovider.EventRule{
  3523. Status: 1,
  3524. Trigger: dataprovider.EventTriggerFsEvent,
  3525. }
  3526. s.renderEventRulePage(w, r, rule, genericPageModeAdd, "")
  3527. }
  3528. func (s *httpdServer) handleWebAddEventRulePost(w http.ResponseWriter, r *http.Request) {
  3529. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3530. claims, err := getTokenClaims(r)
  3531. if err != nil || claims.Username == "" {
  3532. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3533. return
  3534. }
  3535. rule, err := getEventRuleFromPostFields(r)
  3536. if err != nil {
  3537. s.renderEventRulePage(w, r, rule, genericPageModeAdd, err.Error())
  3538. return
  3539. }
  3540. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3541. err = verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr)
  3542. if err != nil {
  3543. s.renderForbiddenPage(w, r, err.Error())
  3544. return
  3545. }
  3546. if err = dataprovider.AddEventRule(&rule, claims.Username, ipAddr, claims.Role); err != nil {
  3547. s.renderEventRulePage(w, r, rule, genericPageModeAdd, err.Error())
  3548. return
  3549. }
  3550. http.Redirect(w, r, webAdminEventRulesPath, http.StatusSeeOther)
  3551. }
  3552. func (s *httpdServer) handleWebUpdateEventRuleGet(w http.ResponseWriter, r *http.Request) {
  3553. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3554. name := getURLParam(r, "name")
  3555. rule, err := dataprovider.EventRuleExists(name)
  3556. if err == nil {
  3557. s.renderEventRulePage(w, r, rule, genericPageModeUpdate, "")
  3558. } else if errors.Is(err, util.ErrNotFound) {
  3559. s.renderNotFoundPage(w, r, err)
  3560. } else {
  3561. s.renderInternalServerErrorPage(w, r, err)
  3562. }
  3563. }
  3564. func (s *httpdServer) handleWebUpdateEventRulePost(w http.ResponseWriter, r *http.Request) {
  3565. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3566. claims, err := getTokenClaims(r)
  3567. if err != nil || claims.Username == "" {
  3568. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3569. return
  3570. }
  3571. name := getURLParam(r, "name")
  3572. rule, err := dataprovider.EventRuleExists(name)
  3573. if errors.Is(err, util.ErrNotFound) {
  3574. s.renderNotFoundPage(w, r, err)
  3575. return
  3576. } else if err != nil {
  3577. s.renderInternalServerErrorPage(w, r, err)
  3578. return
  3579. }
  3580. updatedRule, err := getEventRuleFromPostFields(r)
  3581. if err != nil {
  3582. s.renderEventRulePage(w, r, updatedRule, genericPageModeUpdate, err.Error())
  3583. return
  3584. }
  3585. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3586. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3587. s.renderForbiddenPage(w, r, err.Error())
  3588. return
  3589. }
  3590. updatedRule.ID = rule.ID
  3591. updatedRule.Name = rule.Name
  3592. err = dataprovider.UpdateEventRule(&updatedRule, claims.Username, ipAddr, claims.Role)
  3593. if err != nil {
  3594. s.renderEventRulePage(w, r, updatedRule, genericPageModeUpdate, err.Error())
  3595. return
  3596. }
  3597. http.Redirect(w, r, webAdminEventRulesPath, http.StatusSeeOther)
  3598. }
  3599. func (s *httpdServer) getWebRoles(w http.ResponseWriter, r *http.Request, limit int, minimal bool) ([]dataprovider.Role, error) {
  3600. roles := make([]dataprovider.Role, 0, limit)
  3601. for {
  3602. res, err := dataprovider.GetRoles(limit, len(roles), dataprovider.OrderASC, minimal)
  3603. if err != nil {
  3604. s.renderInternalServerErrorPage(w, r, err)
  3605. return roles, err
  3606. }
  3607. roles = append(roles, res...)
  3608. if len(res) < limit {
  3609. break
  3610. }
  3611. }
  3612. return roles, nil
  3613. }
  3614. func (s *httpdServer) handleWebGetRoles(w http.ResponseWriter, r *http.Request) {
  3615. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3616. roles, err := s.getWebRoles(w, r, 10, false)
  3617. if err != nil {
  3618. return
  3619. }
  3620. data := rolesPage{
  3621. basePage: s.getBasePageData(pageRolesTitle, webAdminRolesPath, r),
  3622. Roles: roles,
  3623. }
  3624. renderAdminTemplate(w, templateRoles, data)
  3625. }
  3626. func (s *httpdServer) handleWebAddRoleGet(w http.ResponseWriter, r *http.Request) {
  3627. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3628. s.renderRolePage(w, r, dataprovider.Role{}, genericPageModeAdd, "")
  3629. }
  3630. func (s *httpdServer) handleWebAddRolePost(w http.ResponseWriter, r *http.Request) {
  3631. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3632. role, err := getRoleFromPostFields(r)
  3633. if err != nil {
  3634. s.renderRolePage(w, r, role, genericPageModeAdd, err.Error())
  3635. return
  3636. }
  3637. claims, err := getTokenClaims(r)
  3638. if err != nil || claims.Username == "" {
  3639. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3640. return
  3641. }
  3642. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3643. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3644. s.renderForbiddenPage(w, r, err.Error())
  3645. return
  3646. }
  3647. err = dataprovider.AddRole(&role, claims.Username, ipAddr, claims.Role)
  3648. if err != nil {
  3649. s.renderRolePage(w, r, role, genericPageModeAdd, err.Error())
  3650. return
  3651. }
  3652. http.Redirect(w, r, webAdminRolesPath, http.StatusSeeOther)
  3653. }
  3654. func (s *httpdServer) handleWebUpdateRoleGet(w http.ResponseWriter, r *http.Request) {
  3655. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3656. role, err := dataprovider.RoleExists(getURLParam(r, "name"))
  3657. if err == nil {
  3658. s.renderRolePage(w, r, role, genericPageModeUpdate, "")
  3659. } else if errors.Is(err, util.ErrNotFound) {
  3660. s.renderNotFoundPage(w, r, err)
  3661. } else {
  3662. s.renderInternalServerErrorPage(w, r, err)
  3663. }
  3664. }
  3665. func (s *httpdServer) handleWebUpdateRolePost(w http.ResponseWriter, r *http.Request) {
  3666. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3667. claims, err := getTokenClaims(r)
  3668. if err != nil || claims.Username == "" {
  3669. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3670. return
  3671. }
  3672. role, err := dataprovider.RoleExists(getURLParam(r, "name"))
  3673. if errors.Is(err, util.ErrNotFound) {
  3674. s.renderNotFoundPage(w, r, err)
  3675. return
  3676. } else if err != nil {
  3677. s.renderInternalServerErrorPage(w, r, err)
  3678. return
  3679. }
  3680. updatedRole, err := getRoleFromPostFields(r)
  3681. if err != nil {
  3682. s.renderRolePage(w, r, role, genericPageModeUpdate, err.Error())
  3683. return
  3684. }
  3685. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3686. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3687. s.renderForbiddenPage(w, r, err.Error())
  3688. return
  3689. }
  3690. updatedRole.ID = role.ID
  3691. updatedRole.Name = role.Name
  3692. err = dataprovider.UpdateRole(&updatedRole, claims.Username, ipAddr, claims.Role)
  3693. if err != nil {
  3694. s.renderRolePage(w, r, updatedRole, genericPageModeUpdate, err.Error())
  3695. return
  3696. }
  3697. http.Redirect(w, r, webAdminRolesPath, http.StatusSeeOther)
  3698. }
  3699. func (s *httpdServer) handleWebGetEvents(w http.ResponseWriter, r *http.Request) {
  3700. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3701. data := eventsPage{
  3702. basePage: s.getBasePageData(pageEventsTitle, webEventsPath, r),
  3703. FsEventsSearchURL: webEventsFsSearchPath,
  3704. ProviderEventsSearchURL: webEventsProviderSearchPath,
  3705. LogEventsSearchURL: webEventsLogSearchPath,
  3706. }
  3707. renderAdminTemplate(w, templateEvents, data)
  3708. }
  3709. func (s *httpdServer) handleWebIPListsPage(w http.ResponseWriter, r *http.Request) {
  3710. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3711. rtlStatus, rtlProtocols := common.Config.GetRateLimitersStatus()
  3712. data := ipListsPage{
  3713. basePage: s.getBasePageData(pageIPListsTitle, webIPListsPath, r),
  3714. RateLimitersStatus: rtlStatus,
  3715. RateLimitersProtocols: strings.Join(rtlProtocols, ", "),
  3716. IsAllowListEnabled: common.Config.IsAllowListEnabled(),
  3717. }
  3718. renderAdminTemplate(w, templateIPLists, data)
  3719. }
  3720. func (s *httpdServer) handleWebAddIPListEntryGet(w http.ResponseWriter, r *http.Request) {
  3721. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3722. listType, _, err := getIPListPathParams(r)
  3723. if err != nil {
  3724. s.renderBadRequestPage(w, r, err)
  3725. return
  3726. }
  3727. s.renderIPListPage(w, r, dataprovider.IPListEntry{Type: listType}, genericPageModeAdd, "")
  3728. }
  3729. func (s *httpdServer) handleWebAddIPListEntryPost(w http.ResponseWriter, r *http.Request) {
  3730. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3731. listType, _, err := getIPListPathParams(r)
  3732. if err != nil {
  3733. s.renderBadRequestPage(w, r, err)
  3734. return
  3735. }
  3736. entry, err := getIPListEntryFromPostFields(r, listType)
  3737. if err != nil {
  3738. s.renderIPListPage(w, r, entry, genericPageModeAdd, err.Error())
  3739. return
  3740. }
  3741. entry.Type = listType
  3742. claims, err := getTokenClaims(r)
  3743. if err != nil || claims.Username == "" {
  3744. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3745. return
  3746. }
  3747. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3748. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3749. s.renderForbiddenPage(w, r, err.Error())
  3750. return
  3751. }
  3752. err = dataprovider.AddIPListEntry(&entry, claims.Username, ipAddr, claims.Role)
  3753. if err != nil {
  3754. s.renderIPListPage(w, r, entry, genericPageModeAdd, err.Error())
  3755. return
  3756. }
  3757. http.Redirect(w, r, webIPListsPath, http.StatusSeeOther)
  3758. }
  3759. func (s *httpdServer) handleWebUpdateIPListEntryGet(w http.ResponseWriter, r *http.Request) {
  3760. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3761. listType, ipOrNet, err := getIPListPathParams(r)
  3762. if err != nil {
  3763. s.renderBadRequestPage(w, r, err)
  3764. return
  3765. }
  3766. entry, err := dataprovider.IPListEntryExists(ipOrNet, listType)
  3767. if err == nil {
  3768. s.renderIPListPage(w, r, entry, genericPageModeUpdate, "")
  3769. } else if errors.Is(err, util.ErrNotFound) {
  3770. s.renderNotFoundPage(w, r, err)
  3771. } else {
  3772. s.renderInternalServerErrorPage(w, r, err)
  3773. }
  3774. }
  3775. func (s *httpdServer) handleWebUpdateIPListEntryPost(w http.ResponseWriter, r *http.Request) {
  3776. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3777. claims, err := getTokenClaims(r)
  3778. if err != nil || claims.Username == "" {
  3779. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3780. return
  3781. }
  3782. listType, ipOrNet, err := getIPListPathParams(r)
  3783. if err != nil {
  3784. s.renderBadRequestPage(w, r, err)
  3785. return
  3786. }
  3787. entry, err := dataprovider.IPListEntryExists(ipOrNet, listType)
  3788. if errors.Is(err, util.ErrNotFound) {
  3789. s.renderNotFoundPage(w, r, err)
  3790. return
  3791. } else if err != nil {
  3792. s.renderInternalServerErrorPage(w, r, err)
  3793. return
  3794. }
  3795. updatedEntry, err := getIPListEntryFromPostFields(r, listType)
  3796. if err != nil {
  3797. s.renderIPListPage(w, r, entry, genericPageModeUpdate, err.Error())
  3798. return
  3799. }
  3800. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3801. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3802. s.renderForbiddenPage(w, r, err.Error())
  3803. return
  3804. }
  3805. updatedEntry.Type = listType
  3806. updatedEntry.IPOrNet = ipOrNet
  3807. err = dataprovider.UpdateIPListEntry(&updatedEntry, claims.Username, ipAddr, claims.Role)
  3808. if err != nil {
  3809. s.renderIPListPage(w, r, entry, genericPageModeUpdate, err.Error())
  3810. return
  3811. }
  3812. http.Redirect(w, r, webIPListsPath, http.StatusSeeOther)
  3813. }
  3814. func (s *httpdServer) handleWebConfigs(w http.ResponseWriter, r *http.Request) {
  3815. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3816. configs, err := dataprovider.GetConfigs()
  3817. if err != nil {
  3818. s.renderInternalServerErrorPage(w, r, err)
  3819. return
  3820. }
  3821. s.renderConfigsPage(w, r, configs, "", 0)
  3822. }
  3823. func (s *httpdServer) handleWebConfigsPost(w http.ResponseWriter, r *http.Request) {
  3824. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3825. claims, err := getTokenClaims(r)
  3826. if err != nil || claims.Username == "" {
  3827. s.renderBadRequestPage(w, r, errors.New("invalid token claims"))
  3828. return
  3829. }
  3830. configs, err := dataprovider.GetConfigs()
  3831. if err != nil {
  3832. s.renderInternalServerErrorPage(w, r, err)
  3833. return
  3834. }
  3835. err = r.ParseForm()
  3836. if err != nil {
  3837. s.renderBadRequestPage(w, r, err)
  3838. return
  3839. }
  3840. ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
  3841. if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil {
  3842. s.renderForbiddenPage(w, r, err.Error())
  3843. return
  3844. }
  3845. var configSection int
  3846. switch r.Form.Get("form_action") {
  3847. case "sftp_submit":
  3848. configSection = 1
  3849. sftpConfigs := getSFTPConfigsFromPostFields(r)
  3850. configs.SFTPD = sftpConfigs
  3851. case "acme_submit":
  3852. configSection = 2
  3853. acmeConfigs := getACMEConfigsFromPostFields(r)
  3854. configs.ACME = acmeConfigs
  3855. if err := acme.GetCertificatesForConfig(acmeConfigs, configurationDir); err != nil {
  3856. s.renderConfigsPage(w, r, configs, err.Error(), configSection)
  3857. return
  3858. }
  3859. case "smtp_submit":
  3860. configSection = 3
  3861. smtpConfigs := getSMTPConfigsFromPostFields(r)
  3862. updateSMTPSecrets(smtpConfigs, configs.SMTP)
  3863. configs.SMTP = smtpConfigs
  3864. default:
  3865. s.renderBadRequestPage(w, r, errors.New("unsupported form action"))
  3866. return
  3867. }
  3868. err = dataprovider.UpdateConfigs(&configs, claims.Username, ipAddr, claims.Role)
  3869. if err != nil {
  3870. s.renderConfigsPage(w, r, configs, err.Error(), configSection)
  3871. return
  3872. }
  3873. if configSection == 3 {
  3874. err := configs.SMTP.TryDecrypt()
  3875. if err == nil {
  3876. smtp.Activate(configs.SMTP)
  3877. } else {
  3878. logger.Error(logSender, "", "unable to decrypt SMTP configuration, cannot activate configuration: %v", err)
  3879. }
  3880. }
  3881. s.renderMessagePage(w, r, "Configurations updated", "", http.StatusOK, nil,
  3882. "Configurations has been successfully updated")
  3883. }
  3884. func (s *httpdServer) handleOAuth2TokenRedirect(w http.ResponseWriter, r *http.Request) {
  3885. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  3886. stateToken := r.URL.Query().Get("state")
  3887. errorTitle := "Unable to complete OAuth2 flow"
  3888. successTitle := "OAuth2 flow completed"
  3889. state, err := verifyOAuth2Token(stateToken, util.GetIPFromRemoteAddress(r.RemoteAddr))
  3890. if err != nil {
  3891. s.renderMessagePage(w, r, errorTitle, "Invalid auth request:", http.StatusBadRequest, err, "")
  3892. return
  3893. }
  3894. defer oauth2Mgr.removePendingAuth(state)
  3895. pendingAuth, err := oauth2Mgr.getPendingAuth(state)
  3896. if err != nil {
  3897. s.renderMessagePage(w, r, errorTitle, "Unable to validate auth request:", http.StatusInternalServerError, err, "")
  3898. return
  3899. }
  3900. oauth2Config := smtp.OAuth2Config{
  3901. Provider: pendingAuth.Provider,
  3902. ClientID: pendingAuth.ClientID,
  3903. ClientSecret: pendingAuth.ClientSecret.GetPayload(),
  3904. }
  3905. ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
  3906. defer cancel()
  3907. cfg := oauth2Config.GetOAuth2()
  3908. cfg.RedirectURL = pendingAuth.RedirectURL
  3909. token, err := cfg.Exchange(ctx, r.URL.Query().Get("code"))
  3910. if err != nil {
  3911. s.renderMessagePage(w, r, errorTitle, "Unable to get token:", http.StatusInternalServerError, err, "")
  3912. return
  3913. }
  3914. if token.RefreshToken == "" {
  3915. errTxt := "the OAuth2 provider returned an empty token. " +
  3916. "Some providers only return the token when the user first authorizes. " +
  3917. "If you have already registered SFTPGo with this user in the past, revoke access and try again. " +
  3918. "This way you will invalidate the previous token"
  3919. s.renderMessagePage(w, r, errorTitle, "Unable to get token:", http.StatusBadRequest, errors.New(errTxt), "")
  3920. return
  3921. }
  3922. s.renderMessagePage(w, r, successTitle, "", http.StatusOK, nil,
  3923. fmt.Sprintf("Copy the following string, without the quotes, into SMTP OAuth2 Token configuration field: %q", token.RefreshToken))
  3924. }
  3925. func updateSMTPSecrets(newConfigs, currentConfigs *dataprovider.SMTPConfigs) {
  3926. if newConfigs.Password.IsNotPlainAndNotEmpty() {
  3927. newConfigs.Password = currentConfigs.Password
  3928. }
  3929. if newConfigs.OAuth2.ClientSecret.IsNotPlainAndNotEmpty() {
  3930. newConfigs.OAuth2.ClientSecret = currentConfigs.OAuth2.ClientSecret
  3931. }
  3932. if newConfigs.OAuth2.RefreshToken.IsNotPlainAndNotEmpty() {
  3933. newConfigs.OAuth2.RefreshToken = currentConfigs.OAuth2.RefreshToken
  3934. }
  3935. }