diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e6f338..7d99fa6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - added Changelog - Ability to change the url and description of shortlinks +- /api/v1/users/me endpoint to get user details +- Account page for user overview and later use ### Changed - License changed to MIT diff --git a/internal/api/users.go b/internal/api/users.go index 4e754f9..4e92ec2 100644 --- a/internal/api/users.go +++ b/internal/api/users.go @@ -1,10 +1,12 @@ package api import ( + "codeberg.org/lauralani/go-urlsh/internal/db" "codeberg.org/lauralani/go-urlsh/internal/misc" "codeberg.org/lauralani/go-urlsh/models" "context" "crypto/sha256" + "database/sql" "encoding/hex" "encoding/json" "github.com/gofiber/fiber/v2" @@ -58,3 +60,69 @@ func HandleUserPost(c *fiber.Ctx) error { return nil } } + +func HandleUserMe(c *fiber.Ctx) error { + if !db.IsCookieValid(c.Cookies(misc.CookieName, "")) && !db.IsApiKeyValid(c.GetRespHeader("x-api-key", "")) { + return fiber.NewError(fiber.StatusUnauthorized, "401 Unauthorized") + } + + cookie := c.Cookies(misc.CookieName, "") + apikey := c.GetRespHeader("x-api-key", "") + + var authmethod string + var user models.User + + if cookie != "" { + authmethod = "cookie" + } else { + authmethod = "apikey" + } + + switch authmethod { + case "cookie": + var session models.Session + err := models.DB.NewSelect().Model(&session).Where("cookie = ?", cookie).Scan(context.Background()) + if err != nil { + if err == sql.ErrNoRows { + log.Printf("[HandleUserMe] Session %v not found\n", cookie) + } else { + log.Printf("[HandleUserMe] Error querying session %v from database: %v\n", cookie, err) + } + return fiber.NewError(fiber.StatusInternalServerError, "500 Internal Server Error") + } + + err = models.DB.NewSelect().Model(&user).Where("username = ?", session.UserName).Scan(context.Background()) + if err != nil { + log.Printf("[HandleUserMe] Error querying user %v from database: %v\n", session.UserName, err) + return fiber.NewError(fiber.StatusInternalServerError, "500 Internal Server Error") + } + + case "apikey": + var key models.ApiKey + err := models.DB.NewSelect().Model(&key).Where("key = ?", apikey).Scan(context.Background()) + if err != nil { + if err == sql.ErrNoRows { + log.Printf("[HandleUserMe] ApiKey %v not found\n", apikey) + } else { + log.Printf("[HandleUserMe] Error querying apikey %v from database: %v\n", apikey, err) + } + return fiber.NewError(fiber.StatusInternalServerError, "500 Internal Server Error") + } + + err = models.DB.NewSelect().Model(&user).Where("username = ?", key.UserName).Scan(context.Background()) + if err != nil { + log.Printf("[HandleUserMe] Error querying user %v from database: %v\n", key.UserName, err) + return fiber.NewError(fiber.StatusInternalServerError, "500 Internal Server Error") + } + } + + var userresponse = new(models.UserResponse) + userresponse.UserName = user.UserName + userresponse.Created = user.Created + + err := c.JSON(userresponse) + if err != nil { + return err + } + return nil +} diff --git a/internal/app/fiber.go b/internal/app/fiber.go index 8067ea1..d06c24c 100644 --- a/internal/app/fiber.go +++ b/internal/app/fiber.go @@ -53,6 +53,8 @@ func SetupFiber() error { fiberapp.Get("/admin/", web.HandleAdminLinkIndexGet) + fiberapp.Get("/admin/account/", web.HandleAdminAccountGet) + fiberapp.Get("/admin/login", web.HandleAdminLoginGet) fiberapp.Post("/admin/login", web.HandleAdminLoginPost) diff --git a/internal/db/cookie.go b/internal/db/cookie.go index 0728e5f..1affab1 100644 --- a/internal/db/cookie.go +++ b/internal/db/cookie.go @@ -14,7 +14,7 @@ func IsCookieValid(val string) bool { return false } - count, err := models.DB.NewSelect().Model((*models.Login)(nil)).Where("cookie = ?", val).Count(context.Background()) + count, err := models.DB.NewSelect().Model((*models.Session)(nil)).Where("cookie = ?", val).Count(context.Background()) if err != nil { log.Printf("Error checking cookie validity for cookie %v\n", val) return false diff --git a/internal/db/initialize.go b/internal/db/initialize.go index 6a8c66f..b2e410e 100644 --- a/internal/db/initialize.go +++ b/internal/db/initialize.go @@ -25,7 +25,7 @@ func InitializeDB() error { return fmt.Errorf("couldn't create database: [%w]", err) } - _, err = models.DB.NewCreateTable().IfNotExists().Model((*models.Login)(nil)).Exec(context.Background()) + _, err = models.DB.NewCreateTable().IfNotExists().Model((*models.Session)(nil)).Exec(context.Background()) if err != nil { return fmt.Errorf("couldn't create database: [%w]", err) } diff --git a/internal/web/account.go b/internal/web/account.go new file mode 100644 index 0000000..7ec9cf6 --- /dev/null +++ b/internal/web/account.go @@ -0,0 +1,41 @@ +package web + +import ( + "codeberg.org/lauralani/go-urlsh/internal/db" + "codeberg.org/lauralani/go-urlsh/internal/misc" + "codeberg.org/lauralani/go-urlsh/models" + "context" + "database/sql" + "github.com/gofiber/fiber/v2" + "log" +) + +func HandleAdminAccountGet(c *fiber.Ctx) error { + if !db.IsCookieValid(c.Cookies(misc.CookieName, "")) { + c.Location("/admin/") + c.Status(fiber.StatusSeeOther) + return nil + } + + cookie := c.Cookies(misc.CookieName, "") + var session models.Session + var user models.User + + err := models.DB.NewSelect().Model(&session).Where("cookie = ?", cookie).Scan(context.Background()) + if err != nil { + if err == sql.ErrNoRows { + log.Printf("[HandleUserMe] Session %v not found\n", cookie) + } else { + log.Printf("[HandleUserMe] Error querying session %v from database: %v\n", cookie, err) + } + return fiber.NewError(fiber.StatusInternalServerError, "500 Internal Server Error") + } + + err = models.DB.NewSelect().Model(&user).Where("username = ?", session.UserName).Scan(context.Background()) + if err != nil { + log.Printf("[HandleUserMe] Error querying user %v from database: %v\n", session.UserName, err) + return fiber.NewError(fiber.StatusInternalServerError, "500 Internal Server Error") + } + + return c.Render("account", user) +} diff --git a/internal/web/login.go b/internal/web/login.go index 4b7d70e..e2e4b87 100644 --- a/internal/web/login.go +++ b/internal/web/login.go @@ -41,7 +41,7 @@ func HandleAdminLoginPost(c *fiber.Ctx) error { } key := uuid.New().String() - dblogin := new(models.Login) + dblogin := new(models.Session) cookie := new(fiber.Cookie) cookie.Name = misc.CookieName diff --git a/models/login.go b/models/login.go index 76c3cc3..2c23d32 100644 --- a/models/login.go +++ b/models/login.go @@ -5,7 +5,7 @@ import ( "time" ) -type Login struct { +type Session struct { bun.BaseModel `bun:"table:logins"` Cookie string `bun:"cookie,pk,type:uuid"` UserName string `bun:"username,notnull"` diff --git a/views/account.tmpl b/views/account.tmpl new file mode 100644 index 0000000..66ec3d7 --- /dev/null +++ b/views/account.tmpl @@ -0,0 +1,62 @@ + + + + + + + Account - go-urlsh + + + + + + + + + + +
+

Account

+

User Details

+ +

Username: {{ .UserName }}

+

Created at: {{ .Created }}

+ +

Security

+

nothing here yet

+ +

+

+
+ +
+
+
+ {{template "partials/footer" .}} + + + diff --git a/views/add_link.tmpl b/views/add_link.tmpl index 58cc2a8..6696115 100644 --- a/views/add_link.tmpl +++ b/views/add_link.tmpl @@ -23,6 +23,9 @@
  • Links
  • +
  • + Account +
  • API Keys
  • diff --git a/views/edit_link.tmpl b/views/edit_link.tmpl index 0bc3dd4..aa836cd 100644 --- a/views/edit_link.tmpl +++ b/views/edit_link.tmpl @@ -23,6 +23,9 @@
  • Links
  • +
  • + Account +
  • API Keys
  • diff --git a/views/links.tmpl b/views/links.tmpl index 6457ed3..9c0b4fe 100644 --- a/views/links.tmpl +++ b/views/links.tmpl @@ -29,6 +29,9 @@
  • Add new Shortlink
  • +
  • + Account +
  • API Keys