webadmin.go 150 KB

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