webadmin.go 150 KB

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