fix(server): i18n etags missing (#3973)
This fixes missing etags from locales assets.pull/3972/head
parent
ec88b67cf1
commit
15110b732a
10
crowdin.yml
10
crowdin.yml
|
@ -6,14 +6,4 @@ files:
|
||||||
- source: /internal/server/locales/en/*
|
- source: /internal/server/locales/en/*
|
||||||
translation: /internal/server/locales/%locale%/%original_file_name%
|
translation: /internal/server/locales/%locale%/%original_file_name%
|
||||||
skip_untranslated_files: true
|
skip_untranslated_files: true
|
||||||
languages_mapping:
|
|
||||||
locale:
|
|
||||||
"de-DE": de
|
|
||||||
"en-EN": en
|
|
||||||
"es-ES": es
|
|
||||||
"fr-FR": fr
|
|
||||||
"nl-NL": nl
|
|
||||||
"pt-PT": pt
|
|
||||||
"ru-RU": ru
|
|
||||||
"zh-CH": zh
|
|
||||||
...
|
...
|
||||||
|
|
|
@ -9,20 +9,22 @@ import (
|
||||||
|
|
||||||
// AssetOverride allows overriding and serving of specific embedded assets from disk.
|
// AssetOverride allows overriding and serving of specific embedded assets from disk.
|
||||||
func AssetOverride(root string, strip int, next fasthttp.RequestHandler) fasthttp.RequestHandler {
|
func AssetOverride(root string, strip int, next fasthttp.RequestHandler) fasthttp.RequestHandler {
|
||||||
|
if root == "" {
|
||||||
|
return next
|
||||||
|
}
|
||||||
|
|
||||||
|
handler := fasthttp.FSHandler(root, strip)
|
||||||
|
stripper := fasthttp.NewPathSlashesStripper(strip)
|
||||||
|
|
||||||
return func(ctx *fasthttp.RequestCtx) {
|
return func(ctx *fasthttp.RequestCtx) {
|
||||||
if root == "" {
|
asset := filepath.Join(root, string(stripper(ctx)))
|
||||||
|
|
||||||
|
if _, err := os.Stat(asset); err != nil {
|
||||||
next(ctx)
|
next(ctx)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := os.Stat(filepath.Join(root, string(fasthttp.NewPathSlashesStripper(strip)(ctx))))
|
handler(ctx)
|
||||||
if err != nil {
|
|
||||||
next(ctx)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fasthttp.FSHandler(root, strip)(ctx)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,19 +20,21 @@ import (
|
||||||
"github.com/authelia/authelia/v4/internal/utils"
|
"github.com/authelia/authelia/v4/internal/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed locales
|
var (
|
||||||
var locales embed.FS
|
//go:embed public_html
|
||||||
|
assets embed.FS
|
||||||
|
|
||||||
//go:embed public_html
|
//go:embed locales
|
||||||
var assets embed.FS
|
locales embed.FS
|
||||||
|
)
|
||||||
|
|
||||||
func newPublicHTMLEmbeddedHandler() fasthttp.RequestHandler {
|
func newPublicHTMLEmbeddedHandler() fasthttp.RequestHandler {
|
||||||
etags := map[string][]byte{}
|
etags := map[string][]byte{}
|
||||||
|
|
||||||
getEmbedETags(assets, "public_html", etags)
|
getEmbedETags(assets, assetsRoot, etags)
|
||||||
|
|
||||||
return func(ctx *fasthttp.RequestCtx) {
|
return func(ctx *fasthttp.RequestCtx) {
|
||||||
p := path.Join("public_html", string(ctx.Path()))
|
p := path.Join(assetsRoot, string(ctx.Path()))
|
||||||
|
|
||||||
if etag, ok := etags[p]; ok {
|
if etag, ok := etags[p]; ok {
|
||||||
ctx.Response.Header.SetBytesKV(headerETag, etag)
|
ctx.Response.Header.SetBytesKV(headerETag, etag)
|
||||||
|
@ -66,8 +68,10 @@ func newPublicHTMLEmbeddedHandler() fasthttp.RequestHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newLocalesEmbeddedHandler() (handler fasthttp.RequestHandler) {
|
func newLocalesPathResolver() func(ctx *fasthttp.RequestCtx) (supported bool, asset string) {
|
||||||
var languages []string
|
var (
|
||||||
|
languages, dirs []string
|
||||||
|
)
|
||||||
|
|
||||||
entries, err := locales.ReadDir("locales")
|
entries, err := locales.ReadDir("locales")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -84,6 +88,10 @@ func newLocalesEmbeddedHandler() (handler fasthttp.RequestHandler) {
|
||||||
lng = strings.SplitN(entry.Name(), "-", 2)[0]
|
lng = strings.SplitN(entry.Name(), "-", 2)[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !utils.IsStringInSlice(entry.Name(), dirs) {
|
||||||
|
dirs = append(dirs, entry.Name())
|
||||||
|
}
|
||||||
|
|
||||||
if utils.IsStringInSlice(lng, languages) {
|
if utils.IsStringInSlice(lng, languages) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -93,34 +101,79 @@ func newLocalesEmbeddedHandler() (handler fasthttp.RequestHandler) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return func(ctx *fasthttp.RequestCtx) {
|
aliases := map[string]string{
|
||||||
var (
|
"sv": "sv-SE",
|
||||||
language, variant, locale, namespace string
|
"zh": "zh-CN",
|
||||||
)
|
}
|
||||||
|
|
||||||
language = ctx.UserValue("language").(string)
|
return func(ctx *fasthttp.RequestCtx) (supported bool, asset string) {
|
||||||
namespace = ctx.UserValue("namespace").(string)
|
var language, namespace, variant, locale string
|
||||||
locale = language
|
|
||||||
|
language, namespace = ctx.UserValue("language").(string), ctx.UserValue("namespace").(string)
|
||||||
|
|
||||||
|
if !utils.IsStringInSlice(language, languages) {
|
||||||
|
return false, ""
|
||||||
|
}
|
||||||
|
|
||||||
if v := ctx.UserValue("variant"); v != nil {
|
if v := ctx.UserValue("variant"); v != nil {
|
||||||
variant = v.(string)
|
variant = v.(string)
|
||||||
locale = fmt.Sprintf("%s-%s", language, variant)
|
locale = fmt.Sprintf("%s-%s", language, variant)
|
||||||
|
} else {
|
||||||
|
locale = language
|
||||||
}
|
}
|
||||||
|
|
||||||
var data []byte
|
ll := language + "-" + strings.ToUpper(language)
|
||||||
|
alias, ok := aliases[locale]
|
||||||
|
|
||||||
if data, err = locales.ReadFile(fmt.Sprintf("locales/%s/%s.json", locale, namespace)); err != nil {
|
switch {
|
||||||
if utils.IsStringInSliceFold(language, languages) {
|
case ok:
|
||||||
data = []byte("{}")
|
return true, fmt.Sprintf("locales/%s/%s.json", alias, namespace)
|
||||||
}
|
case utils.IsStringInSlice(locale, dirs):
|
||||||
|
return true, fmt.Sprintf("locales/%s/%s.json", locale, namespace)
|
||||||
|
case utils.IsStringInSlice(ll, dirs):
|
||||||
|
return true, fmt.Sprintf("locales/%s-%s/%s.json", language, strings.ToUpper(language), namespace)
|
||||||
|
default:
|
||||||
|
return true, fmt.Sprintf("locales/%s/%s.json", locale, namespace)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if len(data) == 0 {
|
func newLocalesEmbeddedHandler() (handler fasthttp.RequestHandler) {
|
||||||
hfsHandleErr(ctx, err)
|
etags := map[string][]byte{}
|
||||||
|
|
||||||
|
getEmbedETags(locales, "locales", etags)
|
||||||
|
|
||||||
|
getAssetName := newLocalesPathResolver()
|
||||||
|
|
||||||
|
return func(ctx *fasthttp.RequestCtx) {
|
||||||
|
supported, asset := getAssetName(ctx)
|
||||||
|
|
||||||
|
if !supported {
|
||||||
|
handlers.SetStatusCodeResponse(ctx, fasthttp.StatusNotFound)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if etag, ok := etags[asset]; ok {
|
||||||
|
ctx.Response.Header.SetBytesKV(headerETag, etag)
|
||||||
|
ctx.Response.Header.SetBytesKV(headerCacheControl, headerValueCacheControlETaggedAssets)
|
||||||
|
|
||||||
|
if bytes.Equal(etag, ctx.Request.Header.PeekBytes(headerIfNoneMatch)) {
|
||||||
|
ctx.SetStatusCode(fasthttp.StatusNotModified)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
data []byte
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if data, err = locales.ReadFile(asset); err != nil {
|
||||||
|
data = []byte("{}")
|
||||||
|
}
|
||||||
|
|
||||||
middlewares.SetContentTypeApplicationJSON(ctx)
|
middlewares.SetContentTypeApplicationJSON(ctx)
|
||||||
|
|
||||||
ctx.SetBody(data)
|
ctx.SetBody(data)
|
||||||
|
|
|
@ -5,16 +5,17 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
embeddedAssets = "public_html/"
|
assetsRoot = "public_html"
|
||||||
swaggerAssets = embeddedAssets + "api/"
|
assetsSwagger = assetsRoot + "/api"
|
||||||
apiFile = "openapi.yml"
|
|
||||||
indexFile = "index.html"
|
fileOpenAPI = "openapi.yml"
|
||||||
logoFile = "logo.png"
|
fileIndexHTML = "index.html"
|
||||||
|
fileLogo = "logo.png"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
rootFiles = []string{"manifest.json", "robots.txt"}
|
filesRoot = []string{"manifest.json", "robots.txt"}
|
||||||
swaggerFiles = []string{
|
filesSwagger = []string{
|
||||||
"favicon-16x16.png",
|
"favicon-16x16.png",
|
||||||
"favicon-32x32.png",
|
"favicon-32x32.png",
|
||||||
"index.css",
|
"index.css",
|
||||||
|
@ -35,7 +36,7 @@ var (
|
||||||
}
|
}
|
||||||
|
|
||||||
// Directories excluded from the not found handler proceeding to the next() handler.
|
// Directories excluded from the not found handler proceeding to the next() handler.
|
||||||
httpServerDirs = []struct {
|
dirsHTTPServer = []struct {
|
||||||
name, prefix string
|
name, prefix string
|
||||||
}{
|
}{
|
||||||
{name: "/api", prefix: "/api/"},
|
{name: "/api", prefix: "/api/"},
|
||||||
|
|
|
@ -79,8 +79,8 @@ func handleNotFound(next fasthttp.RequestHandler) fasthttp.RequestHandler {
|
||||||
return func(ctx *fasthttp.RequestCtx) {
|
return func(ctx *fasthttp.RequestCtx) {
|
||||||
path := strings.ToLower(string(ctx.Path()))
|
path := strings.ToLower(string(ctx.Path()))
|
||||||
|
|
||||||
for i := 0; i < len(httpServerDirs); i++ {
|
for i := 0; i < len(dirsHTTPServer); i++ {
|
||||||
if path == httpServerDirs[i].name || strings.HasPrefix(path, httpServerDirs[i].prefix) {
|
if path == dirsHTTPServer[i].name || strings.HasPrefix(path, dirsHTTPServer[i].prefix) {
|
||||||
handlers.SetStatusCodeResponse(ctx, fasthttp.StatusNotFound)
|
handlers.SetStatusCodeResponse(ctx, fasthttp.StatusNotFound)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -104,9 +104,9 @@ func handleRouter(config schema.Configuration, providers middlewares.Providers)
|
||||||
|
|
||||||
https := config.Server.TLS.Key != "" && config.Server.TLS.Certificate != ""
|
https := config.Server.TLS.Key != "" && config.Server.TLS.Certificate != ""
|
||||||
|
|
||||||
serveIndexHandler := ServeTemplatedFile(embeddedAssets, indexFile, config.Server.AssetPath, duoSelfEnrollment, rememberMe, resetPassword, resetPasswordCustomURL, config.Session.Name, config.Theme, https)
|
serveIndexHandler := ServeTemplatedFile(assetsRoot, fileIndexHTML, config.Server.AssetPath, duoSelfEnrollment, rememberMe, resetPassword, resetPasswordCustomURL, config.Session.Name, config.Theme, https)
|
||||||
serveSwaggerHandler := ServeTemplatedFile(swaggerAssets, indexFile, config.Server.AssetPath, duoSelfEnrollment, rememberMe, resetPassword, resetPasswordCustomURL, config.Session.Name, config.Theme, https)
|
serveSwaggerHandler := ServeTemplatedFile(assetsSwagger, fileIndexHTML, config.Server.AssetPath, duoSelfEnrollment, rememberMe, resetPassword, resetPasswordCustomURL, config.Session.Name, config.Theme, https)
|
||||||
serveSwaggerAPIHandler := ServeTemplatedFile(swaggerAssets, apiFile, config.Server.AssetPath, duoSelfEnrollment, rememberMe, resetPassword, resetPasswordCustomURL, config.Session.Name, config.Theme, https)
|
serveSwaggerAPIHandler := ServeTemplatedFile(assetsSwagger, fileOpenAPI, config.Server.AssetPath, duoSelfEnrollment, rememberMe, resetPassword, resetPasswordCustomURL, config.Session.Name, config.Theme, https)
|
||||||
|
|
||||||
handlerPublicHTML := newPublicHTMLEmbeddedHandler()
|
handlerPublicHTML := newPublicHTMLEmbeddedHandler()
|
||||||
handlerLocales := newLocalesEmbeddedHandler()
|
handlerLocales := newLocalesEmbeddedHandler()
|
||||||
|
@ -124,7 +124,7 @@ func handleRouter(config schema.Configuration, providers middlewares.Providers)
|
||||||
// Static Assets.
|
// Static Assets.
|
||||||
r.GET("/", middleware(serveIndexHandler))
|
r.GET("/", middleware(serveIndexHandler))
|
||||||
|
|
||||||
for _, f := range rootFiles {
|
for _, f := range filesRoot {
|
||||||
r.GET("/"+f, handlerPublicHTML)
|
r.GET("/"+f, handlerPublicHTML)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,10 +139,10 @@ func handleRouter(config schema.Configuration, providers middlewares.Providers)
|
||||||
// Swagger.
|
// Swagger.
|
||||||
r.GET("/api/", middleware(serveSwaggerHandler))
|
r.GET("/api/", middleware(serveSwaggerHandler))
|
||||||
r.OPTIONS("/api/", policyCORSPublicGET.HandleOPTIONS)
|
r.OPTIONS("/api/", policyCORSPublicGET.HandleOPTIONS)
|
||||||
r.GET("/api/"+apiFile, policyCORSPublicGET.Middleware(middleware(serveSwaggerAPIHandler)))
|
r.GET("/api/"+fileOpenAPI, policyCORSPublicGET.Middleware(middleware(serveSwaggerAPIHandler)))
|
||||||
r.OPTIONS("/api/"+apiFile, policyCORSPublicGET.HandleOPTIONS)
|
r.OPTIONS("/api/"+fileOpenAPI, policyCORSPublicGET.HandleOPTIONS)
|
||||||
|
|
||||||
for _, file := range swaggerFiles {
|
for _, file := range filesSwagger {
|
||||||
r.GET("/api/"+file, handlerPublicHTML)
|
r.GET("/api/"+file, handlerPublicHTML)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
{
|
|
||||||
"Accept": "Acceptera",
|
|
||||||
"Access your email addresses": "Hantera din e-postadress",
|
|
||||||
"Access your group membership": "Hantera dina gruppmedlemskap",
|
|
||||||
"Access your profile information": "Hantera din profilinformation",
|
|
||||||
"An email has been sent to your address to complete the process": "Ett mejl har skickats till din e-postadress för att slutföra processen.",
|
|
||||||
"Authenticated": "Autentiserad",
|
|
||||||
"Cancel": "Avbryt",
|
|
||||||
"Client ID": "Klient-ID: {{client_id}}",
|
|
||||||
"Consent Request": "Begäran om medgivande",
|
|
||||||
"Contact your administrator to register a device": "Kontakta din administratör för att registrera en enhet.",
|
|
||||||
"Could not obtain user settings": "Misslyckades med att hämta användarinställningarna.",
|
|
||||||
"Deny": "Avböj",
|
|
||||||
"Done": "Klar",
|
|
||||||
"Enter new password": "Skriv ditt nya lösenord",
|
|
||||||
"Enter one-time password": "Skriv ditt engångslösenord",
|
|
||||||
"Failed to register device, the provided link is expired or has already been used": "Enhetsregistreringen misslyckades, den angivna länken har utgått eller redan blivit använd.",
|
|
||||||
"Hi": "Hej",
|
|
||||||
"Incorrect username or password": "Fel användarnamn eller lösenord",
|
|
||||||
"Loading": "Läser in",
|
|
||||||
"Logout": "Logga ut",
|
|
||||||
"Lost your device?": "Har du tappat bort din enhet?",
|
|
||||||
"Methods": "Metoder",
|
|
||||||
"Must be at least {{len}} characters in length": "Måste vara minst {{len}} tecken långt",
|
|
||||||
"Must have at least one UPPERCASE letter": "Måste innehålla minst en stor bokstav",
|
|
||||||
"Must have at least one lowercase letter": "Måste innehålla minst en liten bokstav",
|
|
||||||
"Must have at least one number": "Måste innehålla minst ett nummer",
|
|
||||||
"Must have at least one special character": "Måste innehålla minst ett specialtecken",
|
|
||||||
"Must not be more than {{len}} characters in length": "Får inte vara längre än {{len}} tecken",
|
|
||||||
"Need Google Authenticator?": "Behöver du Google Authenticator?",
|
|
||||||
"New password": "Nytt lösenord",
|
|
||||||
"No verification token provided": "Ingen verifieringskod tillhandahålls",
|
|
||||||
"OTP Secret copied to clipboard": "OTP koden har kopierats till urklipp",
|
|
||||||
"OTP URL copied to clipboard": "OTP länken har kopierats till urklipp",
|
|
||||||
"One-Time Password": "Engångslösenord",
|
|
||||||
"Password has been reset": "Lösenordet har blivit återställt",
|
|
||||||
"Password": "Lösenord",
|
|
||||||
"Passwords do not match": "Lösenorden matchar inte",
|
|
||||||
"Push Notification": "Push-avisering",
|
|
||||||
"Register device": "Registrera enhet",
|
|
||||||
"Register your first device by clicking on the link below": "Registrera din första enhet genom att klicka på länken nedan",
|
|
||||||
"Remember Consent": "Kom ihåg samtycke",
|
|
||||||
"Remember me": "Kom ihåg mig",
|
|
||||||
"Repeat new password": "Upprepa nya lösenordet",
|
|
||||||
"Reset password": "Återställ lösenord",
|
|
||||||
"Reset password?": "Återställ lösenord?",
|
|
||||||
"Reset": "Återställ",
|
|
||||||
"Scan QR Code": "Skanna QR koden",
|
|
||||||
"Secret": "Kod",
|
|
||||||
"Security Key - WebAuthN": "Säkerhetsnyckel - WebAuthN",
|
|
||||||
"Select a Device": "Välj en enhet",
|
|
||||||
"Sign in": "Logga in",
|
|
||||||
"Sign out": "Logga ut",
|
|
||||||
"The above application is requesting the following permissions": "Ovanstående program begär följande behörigheter",
|
|
||||||
"The password does not meet the password policy": "Lösenordet uppfyller inte lösenordspolicyn",
|
|
||||||
"The resource you're attempting to access requires two-factor authentication": "Resursen du vill komma åt kräver tvåstegsverifiering",
|
|
||||||
"There was a problem initiating the registration process": "Ett problem uppstod när registreringsprocessen skulle starta",
|
|
||||||
"There was an issue completing the process. The verification token might have expired": "Det uppstod ett problem med att slutföra processen. Verifieringskoden kan ha gått ut",
|
|
||||||
"There was an issue initiating the password reset process": "Ett problem uppstod när processen för lösenordsåterställning startade",
|
|
||||||
"There was an issue resetting the password": "Ett problem uppstod med att återställa lösenordet",
|
|
||||||
"There was an issue signing out": "Ett problem uppstod med att logga ut",
|
|
||||||
"This saves this consent as a pre-configured consent for future use": "Spara detta samtycke som ett förkonfigurerat samtycke för framtida användning",
|
|
||||||
"Time-based One-Time Password": "Tidsbaserat engångslösenord",
|
|
||||||
"Use OpenID to verify your identity": "Använd OpenID till att verifiera din identitet",
|
|
||||||
"Username": "Användarnamn",
|
|
||||||
"You must open the link from the same device and browser that initiated the registration process": "Du måste öppna länken från samma enhet och webbläsare som startade registreringsprocessen",
|
|
||||||
"You're being signed out and redirected": "Du blir utloggad och omdirigerad",
|
|
||||||
"Your supplied password does not meet the password policy requirements": "Det angivna lösenordet möter inte lösenordskraven"
|
|
||||||
}
|
|
|
@ -4,10 +4,13 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/valyala/fasthttp"
|
||||||
|
|
||||||
"github.com/authelia/authelia/v4/internal/logging"
|
"github.com/authelia/authelia/v4/internal/logging"
|
||||||
"github.com/authelia/authelia/v4/internal/middlewares"
|
"github.com/authelia/authelia/v4/internal/middlewares"
|
||||||
"github.com/authelia/authelia/v4/internal/utils"
|
"github.com/authelia/authelia/v4/internal/utils"
|
||||||
|
@ -19,7 +22,7 @@ import (
|
||||||
func ServeTemplatedFile(publicDir, file, assetPath, duoSelfEnrollment, rememberMe, resetPassword, resetPasswordCustomURL, session, theme string, https bool) middlewares.RequestHandler {
|
func ServeTemplatedFile(publicDir, file, assetPath, duoSelfEnrollment, rememberMe, resetPassword, resetPasswordCustomURL, session, theme string, https bool) middlewares.RequestHandler {
|
||||||
logger := logging.Logger()
|
logger := logging.Logger()
|
||||||
|
|
||||||
a, err := assets.Open(publicDir + file)
|
a, err := assets.Open(path.Join(publicDir, file))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("Unable to open %s: %s", file, err)
|
logger.Fatalf("Unable to open %s: %s", file, err)
|
||||||
}
|
}
|
||||||
|
@ -43,7 +46,7 @@ func ServeTemplatedFile(publicDir, file, assetPath, duoSelfEnrollment, rememberM
|
||||||
logoOverride := f
|
logoOverride := f
|
||||||
|
|
||||||
if assetPath != "" {
|
if assetPath != "" {
|
||||||
if _, err := os.Stat(filepath.Join(assetPath, logoFile)); err == nil {
|
if _, err := os.Stat(filepath.Join(assetPath, fileLogo)); err == nil {
|
||||||
logoOverride = t
|
logoOverride = t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,14 +74,14 @@ func ServeTemplatedFile(publicDir, file, assetPath, duoSelfEnrollment, rememberM
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case publicDir == swaggerAssets:
|
case publicDir == assetsSwagger:
|
||||||
ctx.Response.Header.Add("Content-Security-Policy", fmt.Sprintf("base-uri 'self'; default-src 'self'; img-src 'self' https://validator.swagger.io data:; object-src 'none'; script-src 'self' 'unsafe-inline' 'nonce-%s'; style-src 'self' 'nonce-%s'", nonce, nonce))
|
ctx.Response.Header.Add(fasthttp.HeaderContentSecurityPolicy, fmt.Sprintf("base-uri 'self'; default-src 'self'; img-src 'self' https://validator.swagger.io data:; object-src 'none'; script-src 'self' 'unsafe-inline' 'nonce-%s'; style-src 'self' 'nonce-%s'", nonce, nonce))
|
||||||
case ctx.Configuration.Server.Headers.CSPTemplate != "":
|
case ctx.Configuration.Server.Headers.CSPTemplate != "":
|
||||||
ctx.Response.Header.Add("Content-Security-Policy", strings.ReplaceAll(ctx.Configuration.Server.Headers.CSPTemplate, cspNoncePlaceholder, nonce))
|
ctx.Response.Header.Add(fasthttp.HeaderContentSecurityPolicy, strings.ReplaceAll(ctx.Configuration.Server.Headers.CSPTemplate, cspNoncePlaceholder, nonce))
|
||||||
case os.Getenv("ENVIRONMENT") == dev:
|
case os.Getenv("ENVIRONMENT") == dev:
|
||||||
ctx.Response.Header.Add("Content-Security-Policy", fmt.Sprintf(cspDefaultTemplate, " 'unsafe-eval'", nonce))
|
ctx.Response.Header.Add(fasthttp.HeaderContentSecurityPolicy, fmt.Sprintf(cspDefaultTemplate, " 'unsafe-eval'", nonce))
|
||||||
default:
|
default:
|
||||||
ctx.Response.Header.Add("Content-Security-Policy", fmt.Sprintf(cspDefaultTemplate, "", nonce))
|
ctx.Response.Header.Add(fasthttp.HeaderContentSecurityPolicy, fmt.Sprintf(cspDefaultTemplate, "", nonce))
|
||||||
}
|
}
|
||||||
|
|
||||||
err := tmpl.Execute(ctx.Response.BodyWriter(), struct{ Base, BaseURL, CSPNonce, DuoSelfEnrollment, LogoOverride, RememberMe, ResetPassword, ResetPasswordCustomURL, Session, Theme string }{Base: base, BaseURL: baseURL, CSPNonce: nonce, DuoSelfEnrollment: duoSelfEnrollment, LogoOverride: logoOverride, RememberMe: rememberMe, ResetPassword: resetPassword, ResetPasswordCustomURL: resetPasswordCustomURL, Session: session, Theme: theme})
|
err := tmpl.Execute(ctx.Response.BodyWriter(), struct{ Base, BaseURL, CSPNonce, DuoSelfEnrollment, LogoOverride, RememberMe, ResetPassword, ResetPasswordCustomURL, Session, Theme string }{Base: base, BaseURL: baseURL, CSPNonce: nonce, DuoSelfEnrollment: duoSelfEnrollment, LogoOverride: logoOverride, RememberMe: rememberMe, ResetPassword: resetPassword, ResetPasswordCustomURL: resetPasswordCustomURL, Session: session, Theme: theme})
|
||||||
|
|
|
@ -18,9 +18,9 @@ i18n.use(Backend)
|
||||||
backend: {
|
backend: {
|
||||||
loadPath: basePath + "/locales/{{lng}}/{{ns}}.json",
|
loadPath: basePath + "/locales/{{lng}}/{{ns}}.json",
|
||||||
},
|
},
|
||||||
|
load: "all",
|
||||||
ns: ["portal"],
|
ns: ["portal"],
|
||||||
defaultNS: "portal",
|
defaultNS: "portal",
|
||||||
load: "all",
|
|
||||||
fallbackLng: {
|
fallbackLng: {
|
||||||
default: ["en"],
|
default: ["en"],
|
||||||
de: ["en"],
|
de: ["en"],
|
||||||
|
@ -33,7 +33,7 @@ i18n.use(Backend)
|
||||||
"sv-SE": ["sv", "en"],
|
"sv-SE": ["sv", "en"],
|
||||||
zh: ["en"],
|
zh: ["en"],
|
||||||
"zh-CN": ["zh", "en"],
|
"zh-CN": ["zh", "en"],
|
||||||
"zh-TW": ["zh", "en"],
|
"zh-TW": ["en"],
|
||||||
},
|
},
|
||||||
supportedLngs: ["en", "de", "es", "fr", "nl", "pt", "ru", "sv", "sv-SE", "zh", "zh-CN", "zh-TW"],
|
supportedLngs: ["en", "de", "es", "fr", "nl", "pt", "ru", "sv", "sv-SE", "zh", "zh-CN", "zh-TW"],
|
||||||
lowerCaseLng: false,
|
lowerCaseLng: false,
|
||||||
|
|
Loading…
Reference in New Issue