webadmin.go 151 KB

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