webadmin.go 138 KB

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