diff --git a/.air.toml b/.air.toml index f01223d..cdf810e 100644 --- a/.air.toml +++ b/.air.toml @@ -5,7 +5,7 @@ tmp_dir = ".air-tmp" bin = "./tijl.dev" cmd = "just build" delay = 1000 - exclude_dir = ["node_modules","modules/database","web/assets/static"] + exclude_dir = ["node_modules","modules/database","web/static"] exclude_unchanged = false follow_symlink = false include_ext = ["go", "html", "js", "ts"] diff --git a/.gitignore b/.gitignore index 4baefbb..85a2aca 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ node_modules/ tijl.dev -web/assets/static/js/interactive.js -web/assets/static/css/styles.css +web/static/js/interactive.js +web/static/css/styles.css config.yaml diff --git a/views/views.go b/assets/embed.go similarity index 76% rename from views/views.go rename to assets/embed.go index ac02766..72048fd 100644 --- a/views/views.go +++ b/assets/embed.go @@ -1,4 +1,4 @@ -package views +package assets import "embed" diff --git a/web/assets/icons/about.svg b/assets/icons/about.svg similarity index 100% rename from web/assets/icons/about.svg rename to assets/icons/about.svg diff --git a/web/assets/icons/blog.svg b/assets/icons/blog.svg similarity index 100% rename from web/assets/icons/blog.svg rename to assets/icons/blog.svg diff --git a/web/assets/icons/home.svg b/assets/icons/home.svg similarity index 100% rename from web/assets/icons/home.svg rename to assets/icons/home.svg diff --git a/web/assets/icons/language.svg b/assets/icons/language.svg similarity index 100% rename from web/assets/icons/language.svg rename to assets/icons/language.svg diff --git a/web/assets/icons/login.svg b/assets/icons/login.svg similarity index 100% rename from web/assets/icons/login.svg rename to assets/icons/login.svg diff --git a/web/assets/icons/projects.svg b/assets/icons/projects.svg similarity index 100% rename from web/assets/icons/projects.svg rename to assets/icons/projects.svg diff --git a/internal/assets/svg.go b/internal/assets/svg.go index 9dfcf53..7d4d939 100644 --- a/internal/assets/svg.go +++ b/internal/assets/svg.go @@ -2,10 +2,10 @@ package assets import ( "html/template" - "os" "path/filepath" "strings" + "git.tijl.dev/tijl/tijl.dev/assets" "git.tijl.dev/tijl/tijl.dev/modules/logger" ) @@ -14,24 +14,29 @@ var SVGData map[string]string func loadSVGs() { SVGData = make(map[string]string) - dir := "web/assets/icons" - - // assets.Embed - - files, err := filepath.Glob(filepath.Join(dir, "*.svg")) + files, err := assets.Embed.ReadDir("icons") if err != nil { log.Fatal().Err(err) } for _, file := range files { - data, err := os.ReadFile(file) + if file.IsDir() { + continue + } + + if filepath.Ext(file.Name()) != ".svg" { + continue + } + + data, err := assets.Embed.ReadFile(filepath.Join("icons", file.Name())) if err != nil { log.Fatal().Err(err) continue } - filename := filepath.Base(file) + filename := file.Name() key := strings.TrimSuffix(filename, filepath.Ext(filename)) SVGData[key] = string(data) + log.Debug().Str("filename", filename).Msg("assets.loadSVGs: loaded") } log.Debug().Msg("loaded svg files") diff --git a/internal/handlers/account.go b/internal/handlers/account.go new file mode 100644 index 0000000..e0985ba --- /dev/null +++ b/internal/handlers/account.go @@ -0,0 +1,25 @@ +package handlers + +import ( + "database/sql" + + "git.tijl.dev/tijl/tijl.dev/internal/i18n" + "git.tijl.dev/tijl/tijl.dev/internal/user" + "git.tijl.dev/tijl/tijl.dev/modules/web" + "github.com/gofiber/fiber/v2" +) + +func accountHandler(c *fiber.Ctx) error { + data := *web.Common(c) + data["Title"] = i18n.Translate(c, "account") + err, u := user.GetUser(data["Uid"].(string)) + data["User"] = u + if err != nil { + if err == sql.ErrNoRows { + c.Redirect("/login") + } else { + return err + } + } + return c.Render("account", data, "layouts/base") +} diff --git a/internal/handlers/auth.go b/internal/handlers/auth.go new file mode 100644 index 0000000..7b96c12 --- /dev/null +++ b/internal/handlers/auth.go @@ -0,0 +1,39 @@ +package handlers + +import ( + "git.tijl.dev/tijl/tijl.dev/internal/i18n" + "git.tijl.dev/tijl/tijl.dev/internal/oidc" + "git.tijl.dev/tijl/tijl.dev/internal/user" + "git.tijl.dev/tijl/tijl.dev/modules/web" + "github.com/gofiber/fiber/v2" +) + +func loginHandler(c *fiber.Ctx) error { + _, err := user.GetSession(c) + if err == nil { + return c.Redirect("/account") + } else { + data := *web.Common(c) + data["Title"] = i18n.Translate(c, "login") + return c.Render("login", data, "layouts/base") + } +} + +func authHandler(c *fiber.Ctx) error { + _, err := user.GetSession(c) + if err == nil { + return c.Redirect("/account") + } else { + return oidc.HandleRedirect(c) + } +} + +func logoutHandler(c *fiber.Ctx) error { + _, err := user.GetSession(c) + if err == nil { + c.ClearCookie("session") + return c.Redirect("/login") + } else { + return c.Redirect("/login") + } +} diff --git a/internal/handlers/login.go b/internal/handlers/login.go deleted file mode 100644 index f12086f..0000000 --- a/internal/handlers/login.go +++ /dev/null @@ -1,16 +0,0 @@ -package handlers - -import ( - "git.tijl.dev/tijl/tijl.dev/internal/oidc" - "git.tijl.dev/tijl/tijl.dev/internal/sessions" - "github.com/gofiber/fiber/v2" -) - -func loginHandler(c *fiber.Ctx) error { - _, err := sessions.GetSession(c) - if err == nil { - return c.Redirect("/account") - } else { - return oidc.HandleRedirect(c) - } -} diff --git a/internal/handlers/routes.go b/internal/handlers/routes.go index 601709e..781aefd 100644 --- a/internal/handlers/routes.go +++ b/internal/handlers/routes.go @@ -8,7 +8,7 @@ import ( "git.tijl.dev/tijl/tijl.dev/internal/i18n" "git.tijl.dev/tijl/tijl.dev/internal/oidc" "git.tijl.dev/tijl/tijl.dev/modules/web" - "git.tijl.dev/tijl/tijl.dev/web/assets" + webf "git.tijl.dev/tijl/tijl.dev/web" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/filesystem" ) @@ -39,15 +39,18 @@ func routes(app *fiber.App) { data["Title"] = i18n.Translate(c, "about") return c.Render("about", data, "layouts/base") }) + app.Get("/login", loginHandler) + app.Get("/account", accountHandler) + app.Get("/logout", logoutHandler) app.Get("/settings", settingsHandler) - app.Get("/login", loginHandler) + app.Get("/auth", authHandler) app.Get(config.Config.Oidc.CallbackUrl, oidc.HandleCallback) /* Static */ - static, _ := fs.Sub(assets.StaticEmbed, "static") + static, _ := fs.Sub(webf.StaticEmbed, "static") app.Use("/static/", filesystem.New(filesystem.Config{ Root: http.FS(static), })) diff --git a/internal/handlers/settings.go b/internal/handlers/settings.go index cacba07..2e23f63 100644 --- a/internal/handlers/settings.go +++ b/internal/handlers/settings.go @@ -1,19 +1,33 @@ package handlers -import "github.com/gofiber/fiber/v2" +import ( + "git.tijl.dev/tijl/tijl.dev/internal/i18n" + "git.tijl.dev/tijl/tijl.dev/modules/web" + "github.com/gofiber/fiber/v2" +) func settingsHandler(c *fiber.Ctx) error { - lang := c.Query("lang") redirectURL := c.Query("redirect") - if lang != "" { - c.Cookie(&fiber.Cookie{ - Name: "language", - Value: lang, - Secure: false, - }) - } if redirectURL != "" { + lang := c.Query("lang") + logout := c.Query("logout") + + if lang != "" { + c.Cookie(&fiber.Cookie{ + Name: "language", + Value: lang, + Secure: false, + }) + } + + if logout == "true" { + c.ClearCookie("session", "state") + } + return c.Redirect(redirectURL) } - return nil + + data := *web.Common(c) + data["Title"] = i18n.Translate(c, "settings") + return c.Render("settings", data, "layouts/base") } diff --git a/internal/i18n/i18n.go b/internal/i18n/i18n.go index 1f6b088..4bc5a44 100644 --- a/internal/i18n/i18n.go +++ b/internal/i18n/i18n.go @@ -2,9 +2,10 @@ package i18n import ( "encoding/json" - "os" "path/filepath" + "strings" + "git.tijl.dev/tijl/tijl.dev/locales" log "git.tijl.dev/tijl/tijl.dev/modules/logger" "github.com/gofiber/fiber/v2" ) @@ -16,28 +17,35 @@ const DefaultLang = "en" func Load() { translations = make(map[string]map[string]string) - dir := "locales" - files, err := filepath.Glob(filepath.Join(dir, "*.json")) + files, err := locales.Embed.ReadDir(".") if err != nil { log.Fatal().Err(err) } for _, file := range files { - lang := filepath.Base(file) - lang = lang[:len(lang)-len(filepath.Ext(lang))] - - file, err := os.Open(file) - if err != nil { - log.Error().Err(err) + if file.IsDir() { + continue + } + + if filepath.Ext(file.Name()) != ".json" { + continue + } + + lang := strings.TrimSuffix(file.Name(), filepath.Ext(file.Name())) + + data, err := locales.Embed.ReadFile(filepath.Join(".", file.Name())) + if err != nil { + log.Error().Err(err).Msg("Failed to read file") continue } - defer file.Close() var messages map[string]string - if err := json.NewDecoder(file).Decode(&messages); err != nil { - log.Error().Err(err) + if err := json.Unmarshal(data, &messages); err != nil { + log.Error().Err(err).Msg("Failed to decode JSON") continue } + + log.Debug().Str("lang", lang).Msg("i18n.Load: loaded") translations[lang] = messages } diff --git a/internal/oidc/handler.go b/internal/oidc/handler.go index 1438630..0bb735e 100644 --- a/internal/oidc/handler.go +++ b/internal/oidc/handler.go @@ -7,7 +7,7 @@ import ( "net/http" "git.tijl.dev/tijl/tijl.dev/internal/db" - "git.tijl.dev/tijl/tijl.dev/internal/sessions" + "git.tijl.dev/tijl/tijl.dev/internal/user" "git.tijl.dev/tijl/tijl.dev/internal/utils" "git.tijl.dev/tijl/tijl.dev/modules/database" log "git.tijl.dev/tijl/tijl.dev/modules/logger" @@ -73,7 +73,7 @@ func HandleCallback(c *fiber.Ctx) error { return err } - _, err = sessions.NewSession(idToken.Subject, c) + _, err = user.NewSession(idToken.Subject, c) if err != nil { return err } diff --git a/internal/service/main.go b/internal/service/main.go index 9682725..f632b7a 100644 --- a/internal/service/main.go +++ b/internal/service/main.go @@ -13,7 +13,7 @@ import ( webinternal "git.tijl.dev/tijl/tijl.dev/internal/web" "git.tijl.dev/tijl/tijl.dev/modules/logger" "git.tijl.dev/tijl/tijl.dev/modules/web" - "git.tijl.dev/tijl/tijl.dev/views" + webf "git.tijl.dev/tijl/tijl.dev/web" "github.com/gofiber/contrib/fiberzerolog" "github.com/gofiber/fiber/v2" "github.com/gofiber/template/html/v2" @@ -41,7 +41,8 @@ func Listen() { webinternal.Load() // Init templating engine - engine := html.NewFileSystem(http.FS(views.Embed), ".html") + engine := html.NewFileSystem(http.FS(webf.ViewsEmbed), ".html") + engine.Directory = "views" engine.AddFunc("icon", assets.Svg) // Init fiber diff --git a/internal/sessions/sessions.go b/internal/user/sessions.go similarity index 98% rename from internal/sessions/sessions.go rename to internal/user/sessions.go index 12360f8..92f1208 100644 --- a/internal/sessions/sessions.go +++ b/internal/user/sessions.go @@ -1,4 +1,4 @@ -package sessions +package user import ( "context" diff --git a/internal/user/users.go b/internal/user/users.go new file mode 100644 index 0000000..0dd2e74 --- /dev/null +++ b/internal/user/users.go @@ -0,0 +1,17 @@ +package user + +import ( + "context" + + "git.tijl.dev/tijl/tijl.dev/internal/db" + "git.tijl.dev/tijl/tijl.dev/modules/database" +) + +func GetUser(uid string) (error, database.User) { + user, err := db.Queries.GetUser(context.TODO(), uid) + if err != nil { + return err, database.User{} + } + + return nil, user +} diff --git a/internal/web/common.go b/internal/web/common.go index afe9adf..282e805 100644 --- a/internal/web/common.go +++ b/internal/web/common.go @@ -2,19 +2,20 @@ package web import ( "git.tijl.dev/tijl/tijl.dev/internal/i18n" - "git.tijl.dev/tijl/tijl.dev/internal/sessions" + "git.tijl.dev/tijl/tijl.dev/internal/user" "git.tijl.dev/tijl/tijl.dev/modules/web" "github.com/gofiber/fiber/v2" ) func Load() { web.RegisterCommon(func(c *fiber.Ctx, m *fiber.Map) { - _, err := sessions.GetSession(c) + uid, err := user.GetSession(c) signedIn := false if err == nil { signedIn = true } + (*m)["Uid"] = uid (*m)["SignedIn"] = signedIn (*m)["Path"] = c.Path() (*m)["Language"] = i18n.GetLanguage(c) diff --git a/locales/en.json b/locales/en.json index 703bda2..21d53be 100644 --- a/locales/en.json +++ b/locales/en.json @@ -7,5 +7,7 @@ "dutch": "Dutch", "about": "About", "projects": "Projects", - "account": "Account" + "account": "Account", + "login": "Login", + "settings": "Settings" } diff --git a/locales/nl.json b/locales/nl.json index d8fe031..d0d3d02 100644 --- a/locales/nl.json +++ b/locales/nl.json @@ -7,5 +7,7 @@ "dutch": "Nederlands", "about": "Over", "projects": "Projecten", - "account": "Account" + "account": "Account", + "login": "Login", + "settings": "Instellingen" } diff --git a/package.json b/package.json index 7c908e7..ea97e00 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "scripts": { "dev": "vite", "build": "vite build", - "build:css": "tailwindcss -i ./web/styles.css -o ./web/assets/static/css/styles.css --minify" + "build:css": "tailwindcss -i ./web/lib/main.css -o ./web/static/css/styles.css --minify" }, "devDependencies": { "@tailwindcss/typography": "^0.5.14", diff --git a/vite.config.ts b/vite.config.ts index f9754d5..50201c2 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -3,7 +3,7 @@ import { defineConfig } from "vite"; export default defineConfig({ plugins: [], build: { - outDir: "web/assets/static/js", // Output directory for compiled JS + outDir: "web/static/js", // Output directory for compiled JS rollupOptions: { output: { entryFileNames: "[name].js", diff --git a/web/assets/embed.go b/web/assets/embed.go deleted file mode 100644 index f75d792..0000000 --- a/web/assets/embed.go +++ /dev/null @@ -1,9 +0,0 @@ -package assets - -import "embed" - -//go:embed * -var Embed embed.FS - -//go:embed static/* -var StaticEmbed embed.FS diff --git a/web/embed.go b/web/embed.go new file mode 100644 index 0000000..85eb4d9 --- /dev/null +++ b/web/embed.go @@ -0,0 +1,11 @@ +package web + +import ( + "embed" +) + +//go:embed static/* +var StaticEmbed embed.FS + +//go:embed views/* +var ViewsEmbed embed.FS diff --git a/web/styles.css b/web/lib/main.css similarity index 100% rename from web/styles.css rename to web/lib/main.css diff --git a/web/assets/static/css/.gitkeep b/web/static/css/.gitkeep similarity index 100% rename from web/assets/static/css/.gitkeep rename to web/static/css/.gitkeep diff --git a/web/assets/static/favicon.ico b/web/static/favicon.ico similarity index 100% rename from web/assets/static/favicon.ico rename to web/static/favicon.ico diff --git a/web/assets/static/fonts/Cantarell-VF.woff2 b/web/static/fonts/Cantarell-VF.woff2 similarity index 100% rename from web/assets/static/fonts/Cantarell-VF.woff2 rename to web/static/fonts/Cantarell-VF.woff2 diff --git a/views/404.html b/web/views/404.html similarity index 100% rename from views/404.html rename to web/views/404.html diff --git a/views/about.html b/web/views/about.html similarity index 100% rename from views/about.html rename to web/views/about.html diff --git a/web/views/account.html b/web/views/account.html new file mode 100644 index 0000000..d118a3b --- /dev/null +++ b/web/views/account.html @@ -0,0 +1,7 @@ +
+
id: {{.User.Uid}}
+
username: {{.User.Username}}
+
email: {{.User.Email}}
+
full name: {{.User.FullName}}
+ Logout +
diff --git a/views/blog.html b/web/views/blog.html similarity index 100% rename from views/blog.html rename to web/views/blog.html diff --git a/views/index.html b/web/views/index.html similarity index 100% rename from views/index.html rename to web/views/index.html diff --git a/views/layouts/base.html b/web/views/layouts/base.html similarity index 100% rename from views/layouts/base.html rename to web/views/layouts/base.html diff --git a/web/views/login.html b/web/views/login.html new file mode 100644 index 0000000..7a64efe --- /dev/null +++ b/web/views/login.html @@ -0,0 +1 @@ +Login with TT Authentication Services diff --git a/views/partials/menu.html b/web/views/partials/menu.html similarity index 97% rename from views/partials/menu.html rename to web/views/partials/menu.html index 98f2de6..3ea9481 100644 --- a/views/partials/menu.html +++ b/web/views/partials/menu.html @@ -45,6 +45,7 @@ {{.T.about}} +
  • {{if .SignedIn}} - + {{icon "login"}} diff --git a/views/projects.html b/web/views/projects.html similarity index 100% rename from views/projects.html rename to web/views/projects.html diff --git a/web/views/settings.html b/web/views/settings.html new file mode 100644 index 0000000..1005b0a --- /dev/null +++ b/web/views/settings.html @@ -0,0 +1 @@ +
    hello