webadmin.go 134 KB

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