webadmin.go 146 KB

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