webadmin.go 140 KB

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