webadmin.go 151 KB

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