Add login route

This commit is contained in:
Zoe Roux 2024-09-02 14:32:27 +02:00
parent 4685f76cad
commit b340958348
No known key found for this signature in database
5 changed files with 66 additions and 8 deletions

View File

@ -1 +1,2 @@
replace jwt.MapClaims map[string]string
replace uuid.UUID string

View File

@ -83,7 +83,6 @@ func OpenDatabase() (*pgxpool.Pool, error) {
fmt.Printf("Could not connect to database, check your env variables!")
return nil, err
}
defer db.Close()
if schema != "disabled" {
_, err = db.Exec(ctx, fmt.Sprintf("create schema if not exists %s", schema))
@ -92,6 +91,7 @@ func OpenDatabase() (*pgxpool.Pool, error) {
}
}
fmt.Println("Migrating database")
dbi := stdlib.OpenDBFromPool(db)
defer dbi.Close()
@ -104,8 +104,9 @@ func OpenDatabase() (*pgxpool.Pool, error) {
return nil, err
}
m.Up()
fmt.Println("Migrating finished")
return db, err
return db, nil
}
type Handler struct {
@ -149,6 +150,9 @@ func main() {
e.GET("/users", h.ListUsers)
e.POST("/users", h.Register)
e.POST("/session", h.Login)
e.GET("/swagger/*", echoSwagger.WrapHandler)
e.Logger.Fatal(e.Start(":4568"))

View File

@ -9,6 +9,7 @@ import (
"net/http"
"time"
"github.com/alexedwards/argon2id"
"github.com/golang-jwt/jwt/v5"
"github.com/labstack/echo/v4"
"github.com/zoriya/kyoo/keibi/dbc"
@ -19,6 +20,48 @@ type LoginDto struct {
Password string `json:"password" validate:"required"`
}
// @Summary Login
// @Description Login to your account and open a session
// @Tags sessions
// @Accept json
// @Produce json
// @Param device query uuid false "The device the created session will be used on"
// @Param user body LoginDto false "Account informations"
// @Success 201 {object} dbc.Session
// @Failure 400 {object} problem.Problem "Invalid login body"
// @Failure 400 {object} problem.Problem "Invalid password"
// @Failure 404 {object} problem.Problem "Account does not exists"
// @Router /sessions [post]
func (h *Handler) Login(c echo.Context) error {
var req LoginDto
err := c.Bind(&req)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
if err = c.Validate(&req); err != nil {
return err
}
dbuser, err := h.db.GetUserByLogin(context.Background(), req.Login)
if err != nil {
return echo.NewHTTPError(http.StatusNotFound, "No account exists with the specified email or username.")
}
if dbuser.Password == nil {
return echo.NewHTTPError(http.StatusBadRequest, "Can't login with password, this account was created with OIDC.")
}
match, err := argon2id.ComparePasswordAndHash(req.Password, *dbuser.Password)
if err != nil {
return err
}
if !match {
return echo.NewHTTPError(http.StatusBadRequest, "Invalid password")
}
user := MapDbUser(&dbuser)
return h.createSession(c, &user)
}
func (h *Handler) createSession(c echo.Context, user *User) error {
ctx := context.Background()

View File

@ -18,7 +18,7 @@ order by
id
limit $1;
-- name: GetUser :one
-- name: GetUser :many
select
sqlc.embed(u),
sqlc.embed(h)
@ -26,7 +26,16 @@ from
users as u
left join oidc_handle as h on u.id = h.user_id
where
u.id = $1
u.id = $1;
-- name: GetUserByLogin :one
select
*
from
users
where
email = sqlc.arg(login)
or username = sqlc.arg(login)
limit 1;
-- name: CreateUser :one

View File

@ -29,7 +29,7 @@ type OidcHandle struct {
}
type RegisterDto struct {
Username string `json:"username" validate:"required"`
Username string `json:"username" validate:"required,excludes=@"`
Email string `json:"email" validate:"required,email" format:"email"`
Password string `json:"password" validate:"required"`
}
@ -51,7 +51,7 @@ func MapDbUser(user *dbc.User) User {
// @Tags users
// @Accept json
// @Produce json
// @Param afterId query uuid false "used for pagination."
// @Param afterId query string false "used for pagination." Format(uuid)
// @Success 200 {object} User[]
// @Failure 400 {object} problem.Problem
// @Router /users [get]
@ -95,7 +95,8 @@ func (h *Handler) ListUsers(c echo.Context) error {
// @Param device query uuid false "The device the created session will be used on"
// @Param user body RegisterDto false "Registration informations"
// @Success 201 {object} dbc.Session
// @Failure 400 {object} problem.Problem
// @Failure 400 {object} problem.Problem "Invalid register body"
// @Success 409 {object} problem.Problem "Duplicated email or username"
// @Router /users [post]
func (h *Handler) Register(c echo.Context) error {
var req RegisterDto
@ -109,7 +110,7 @@ func (h *Handler) Register(c echo.Context) error {
pass, err := argon2id.CreateHash(req.Password, argon2id.DefaultParams)
if err != nil {
return echo.NewHTTPError(400, "Invalid password")
return err
}
duser, err := h.db.CreateUser(context.Background(), dbc.CreateUserParams{