webadmin.go 141 KB

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