webadmin.go 138 KB

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