webadmin.go 143 KB

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