webadmin.go 150 KB

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