Add multi language support for authentication middleware

This commit is contained in:
Achim Rohn
2025-09-17 18:05:23 +02:00
parent 667345bc9e
commit f70a4ad777
10 changed files with 182 additions and 10 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ import (
)
const AboutPath = "/about"
const AboutPathDe = "/de/ueber-uns"
const AboutPathDe = "/ueber-uns"
var aboutTexts *AboutTexts
+1 -1
View File
@@ -8,7 +8,7 @@ import (
)
const ContactPath = "/contact"
const ContactPathDe = "/de/kontakt"
const ContactPathDe = "/kontakt"
var contactTexts *ContactTexts
+1
View File
@@ -0,0 +1 @@
*.db
+8 -1
View File
@@ -5,7 +5,7 @@ go 1.25.0
require (
entgo.io/ent v0.14.5
ersteller-lib v0.0.0
github.com/jackc/pgx/v5 v5.7.6
github.com/gorilla/sessions v1.4.0
github.com/joho/godotenv v1.5.1
golang.org/x/oauth2 v0.30.0
maragu.dev/gomponents v1.2.0
@@ -13,18 +13,25 @@ require (
require (
ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9 // indirect
cloud.google.com/go/compute/metadata v0.3.0 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/bmatcuk/doublestar v1.3.4 // indirect
github.com/go-chi/chi/v5 v5.1.0 // indirect
github.com/go-openapi/inflect v0.19.0 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/context v1.1.1 // indirect
github.com/gorilla/mux v1.6.2 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
github.com/hashicorp/hcl/v2 v2.18.1 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/pgx/v5 v5.7.6 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/labstack/echo/v4 v4.13.4 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/markbates/goth v1.81.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v1.14.32 // indirect
+30
View File
@@ -1,7 +1,11 @@
ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9 h1:E0wvcUXTkgyN4wy4LGtNzMNGMytJN8afmIWXJVMi4cc=
ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9/go.mod h1:Oe1xWPuu5q9LzyrWfbZmEZxFYeu4BHTyzfjeW2aZp/w=
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
entgo.io/ent v0.14.5 h1:Rj2WOYJtCkWyFo6a+5wB3EfBRP0rnx1fMk6gGA0UUe4=
entgo.io/ent v0.14.5/go.mod h1:zTzLmWtPvGpmSwtkaayM2cm5m819NdM7z7tYPq3vN0U=
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
@@ -11,12 +15,26 @@ github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4=
github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4=
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
github.com/hashicorp/hcl/v2 v2.18.1 h1:6nxnOJFku1EuSawSD81fuviYUV8DxFr3fp2dUi3ZYSo=
github.com/hashicorp/hcl/v2 v2.18.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
@@ -29,10 +47,18 @@ github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/labstack/echo/v4 v4.13.4 h1:oTZZW+T3s9gAu5L8vmzihV7/lkXGZuITzTQkTEhcXEA=
github.com/labstack/echo/v4 v4.13.4/go.mod h1:g63b33BZ5vZzcIUF8AtRH40DrTlXnx4UMC8rBdndmjQ=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/markbates/goth v1.81.0 h1:XVcCkeGWokynPV7MXvgb8pd2s3r7DS40P7931w6kdnE=
github.com/markbates/goth v1.81.0/go.mod h1:+6z31QyUms84EHmuBY7iuqYSxyoN3njIgg9iCF/lR1k=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
@@ -43,6 +69,10 @@ github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQ
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+99
View File
@@ -0,0 +1,99 @@
package login
import (
. "ersteller-lib"
. "maragu.dev/gomponents"
. "maragu.dev/gomponents/html"
)
const LoginPath = "/login"
const LoginPathDe = "/anmelden"
var loginTexts *LoginTexts
type LoginTexts struct {
PageTitle I18nText
PageDescription I18nText
HeroTitle I18nText
HeroDescription I18nText
GoogleLoginBtn I18nText
}
type Page struct {
createPage CreateHtmxPageFunc
ViewRoute HtmxRoute
}
func NewPage(createPage CreateHtmxPageFunc, server HtmxServer, path *ActivePath) *Page {
if loginTexts == nil {
createLoginTexts()
}
page := &Page{
createPage: createPage,
}
page.ViewRoute = NewHtmxGetRoute(page.View, LanguagePaths{
En: LoginPath,
De: LoginPathDe,
}).SetActivePath(path)
page.ViewRoute.Add(server)
return page
}
func createLoginTexts() {
loginTexts = &LoginTexts{
PageTitle: NewI18nText(map[Language]string{
En: "Login",
De: "Anmelden",
}),
PageDescription: NewI18nText(map[Language]string{
En: "Sign in to your account",
De: "Melden Sie sich bei Ihrem Konto an",
}),
HeroTitle: NewI18nText(map[Language]string{
En: "Sign In",
De: "Anmelden",
}),
HeroDescription: NewI18nText(map[Language]string{
En: "Please sign in to access your account.",
De: "Bitte melden Sie sich an, um auf Ihr Konto zuzugreifen.",
}),
GoogleLoginBtn: NewI18nText(map[Language]string{
En: "Sign in with Google",
De: "Mit Google anmelden",
}),
}
}
func (p *Page) getMetaData() PageWebsiteMetaData {
return PageWebsiteMetaData{
Title: loginTexts.PageTitle,
Lang: En,
Description: loginTexts.PageDescription,
HideNavigation: true,
}
}
func (p *Page) View(c HtmxContext) {
content := LoginContent(c.GetLanguage())
p.createPage(c, p.getMetaData(), content)
}
func LoginContent(language Language) Group {
return []Node{
Div(Class("hero-section login-section"),
H1(Class("hero-title"), Text(loginTexts.HeroTitle.FromLang(language))),
P(Class("hero-description"), Text(loginTexts.HeroDescription.FromLang(language))),
Div(Class("login-buttons"),
A(
Href("/login/google"),
Button(
Class("btn btn-primary google-login-btn"),
Type("button"),
Text(loginTexts.GoogleLoginBtn.FromLang(language)),
),
),
),
),
}
}
+13 -1
View File
@@ -9,6 +9,7 @@ import (
"ersteller-lib/starter/env"
"ersteller-lib/starter/google"
"ersteller-lib/starter/index"
"ersteller-lib/starter/login"
"ersteller-lib/starter/page"
"net/http"
@@ -69,9 +70,20 @@ func CreateApi(environment env.Environment, db *ent.Client) http.Handler {
_ = about.NewPage(createPageFunc, server, &aboutActivePath)
_ = contact.NewPage(createPageFunc, server, &contactActivePath)
// Create Login page
loginPaths := LanguagePaths{
En: login.LoginPath,
De: login.LoginPathDe,
}
loginActivePath := NewActivePath(map[Language]string{
En: "Login",
De: "Anmelden",
}, loginPaths)
_ = login.NewPage(createPageFunc, server, &loginActivePath)
serverWithMiddleWare := UseMiddleware(server, LoggingMiddleware, MakeGzipHandler,
authentication.Middleware(sessionStore,
[]string{"/login", google.GoogleLogin, google.GoogleLoginCallback}, "/"))
[]string{"/de" + login.LoginPathDe, "/en" + authentication.LoginPath, google.GoogleLogin, google.GoogleLoginCallback, "/static"}, loginPaths))
return serverWithMiddleWare
}