webadmin.go 140 KB

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