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