webadmin.go 143 KB

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