webadmin.go 143 KB

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