diff --git a/.mockery.yaml b/.mockery.yaml index 1fd18b8..cb5c70c 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -3,11 +3,11 @@ dir: mocks/ outpkg: mocks issue-845-fix: True packages: - spend-sparrow/internal/service: + spend-sparrow/internal/core: interfaces: Random: Clock: Mail: - spend-sparrow/internal/db: + spend-sparrow/internal/authentication: interfaces: - Auth: + Db: diff --git a/internal/account/service.go b/internal/account/service.go index 30feb26..f0cc2e6 100644 --- a/internal/account/service.go +++ b/internal/account/service.go @@ -4,29 +4,31 @@ import ( "context" "errors" "fmt" - "github.com/google/uuid" - "github.com/jmoiron/sqlx" "log/slog" + "spend-sparrow/internal/auth_types" + "spend-sparrow/internal/core" "spend-sparrow/internal/db" "spend-sparrow/internal/service" - "spend-sparrow/internal/types" + + "github.com/google/uuid" + "github.com/jmoiron/sqlx" ) type Service interface { - Add(ctx context.Context, user *types.User, name string) (*Account, error) - UpdateName(ctx context.Context, user *types.User, id string, name string) (*Account, error) - Get(ctx context.Context, user *types.User, id string) (*Account, error) - GetAll(ctx context.Context, user *types.User) ([]*Account, error) - Delete(ctx context.Context, user *types.User, id string) error + Add(ctx context.Context, user *auth_types.User, name string) (*Account, error) + UpdateName(ctx context.Context, user *auth_types.User, id string, name string) (*Account, error) + Get(ctx context.Context, user *auth_types.User, id string) (*Account, error) + GetAll(ctx context.Context, user *auth_types.User) ([]*Account, error) + Delete(ctx context.Context, user *auth_types.User, id string) error } type ServiceImpl struct { db *sqlx.DB - clock service.Clock - random service.Random + clock core.Clock + random core.Random } -func NewServiceImpl(db *sqlx.DB, random service.Random, clock service.Clock) Service { +func NewServiceImpl(db *sqlx.DB, random core.Random, clock core.Clock) Service { return ServiceImpl{ db: db, clock: clock, @@ -34,14 +36,14 @@ func NewServiceImpl(db *sqlx.DB, random service.Random, clock service.Clock) Ser } } -func (s ServiceImpl) Add(ctx context.Context, user *types.User, name string) (*Account, error) { +func (s ServiceImpl) Add(ctx context.Context, user *auth_types.User, name string) (*Account, error) { if user == nil { - return nil, types.ErrUnauthorized + return nil, core.ErrUnauthorized } newId, err := s.random.UUID(ctx) if err != nil { - return nil, types.ErrInternal + return nil, core.ErrInternal } err = service.ValidateString(name, "name") @@ -76,9 +78,9 @@ func (s ServiceImpl) Add(ctx context.Context, user *types.User, name string) (*A return account, nil } -func (s ServiceImpl) UpdateName(ctx context.Context, user *types.User, id string, name string) (*Account, error) { +func (s ServiceImpl) UpdateName(ctx context.Context, user *auth_types.User, id string, name string) (*Account, error) { if user == nil { - return nil, types.ErrUnauthorized + return nil, core.ErrUnauthorized } err := service.ValidateString(name, "name") if err != nil { @@ -87,7 +89,7 @@ func (s ServiceImpl) UpdateName(ctx context.Context, user *types.User, id string uuid, err := uuid.Parse(id) if err != nil { slog.ErrorContext(ctx, "account update", "err", err) - return nil, fmt.Errorf("could not parse Id: %w", service.ErrBadRequest) + return nil, fmt.Errorf("could not parse Id: %w", core.ErrBadRequest) } tx, err := s.db.BeginTxx(ctx, nil) @@ -103,10 +105,10 @@ func (s ServiceImpl) UpdateName(ctx context.Context, user *types.User, id string err = tx.GetContext(ctx, &account, `SELECT * FROM account WHERE user_id = ? AND id = ?`, user.Id, uuid) err = db.TransformAndLogDbError(ctx, "account Update", nil, err) if err != nil { - if errors.Is(err, db.ErrNotFound) { - return nil, fmt.Errorf("account %v not found: %w", id, service.ErrBadRequest) + if errors.Is(err, core.ErrNotFound) { + return nil, fmt.Errorf("account %v not found: %w", id, core.ErrBadRequest) } - return nil, types.ErrInternal + return nil, core.ErrInternal } timestamp := s.clock.Now() @@ -136,14 +138,14 @@ func (s ServiceImpl) UpdateName(ctx context.Context, user *types.User, id string return &account, nil } -func (s ServiceImpl) Get(ctx context.Context, user *types.User, id string) (*Account, error) { +func (s ServiceImpl) Get(ctx context.Context, user *auth_types.User, id string) (*Account, error) { if user == nil { - return nil, service.ErrUnauthorized + return nil, core.ErrUnauthorized } uuid, err := uuid.Parse(id) if err != nil { slog.ErrorContext(ctx, "account get", "err", err) - return nil, fmt.Errorf("could not parse Id: %w", service.ErrBadRequest) + return nil, fmt.Errorf("could not parse Id: %w", core.ErrBadRequest) } var account Account @@ -158,9 +160,9 @@ func (s ServiceImpl) Get(ctx context.Context, user *types.User, id string) (*Acc return &account, nil } -func (s ServiceImpl) GetAll(ctx context.Context, user *types.User) ([]*Account, error) { +func (s ServiceImpl) GetAll(ctx context.Context, user *auth_types.User) ([]*Account, error) { if user == nil { - return nil, service.ErrUnauthorized + return nil, core.ErrUnauthorized } accounts := make([]*Account, 0) @@ -174,14 +176,14 @@ func (s ServiceImpl) GetAll(ctx context.Context, user *types.User) ([]*Account, return accounts, nil } -func (s ServiceImpl) Delete(ctx context.Context, user *types.User, id string) error { +func (s ServiceImpl) Delete(ctx context.Context, user *auth_types.User, id string) error { if user == nil { - return service.ErrUnauthorized + return core.ErrUnauthorized } uuid, err := uuid.Parse(id) if err != nil { slog.ErrorContext(ctx, "account delete", "err", err) - return fmt.Errorf("could not parse Id: %w", service.ErrBadRequest) + return fmt.Errorf("could not parse Id: %w", core.ErrBadRequest) } tx, err := s.db.BeginTxx(ctx, nil) @@ -200,7 +202,7 @@ func (s ServiceImpl) Delete(ctx context.Context, user *types.User, id string) er return err } if transactionsCount > 0 { - return fmt.Errorf("account has transactions, cannot delete: %w", service.ErrBadRequest) + return fmt.Errorf("account has transactions, cannot delete: %w", core.ErrBadRequest) } res, err := tx.ExecContext(ctx, "DELETE FROM account WHERE id = ? and user_id = ?", uuid, user.Id) diff --git a/internal/types/auth.go b/internal/auth_types/types.go similarity index 98% rename from internal/types/auth.go rename to internal/auth_types/types.go index b91e27f..fef0477 100644 --- a/internal/types/auth.go +++ b/internal/auth_types/types.go @@ -1,4 +1,4 @@ -package types +package auth_types import ( "time" diff --git a/internal/db/auth.go b/internal/authentication/db.go similarity index 66% rename from internal/db/auth.go rename to internal/authentication/db.go index f4eb361..7dec9ee 100644 --- a/internal/db/auth.go +++ b/internal/authentication/db.go @@ -1,11 +1,12 @@ -package db +package authentication import ( "context" "database/sql" "errors" "log/slog" - "spend-sparrow/internal/types" + "spend-sparrow/internal/auth_types" + "spend-sparrow/internal/core" "strings" "time" @@ -13,36 +14,36 @@ import ( "github.com/jmoiron/sqlx" ) -type Auth interface { - InsertUser(ctx context.Context, user *types.User) error - UpdateUser(ctx context.Context, user *types.User) error - GetUserByEmail(ctx context.Context, email string) (*types.User, error) - GetUser(ctx context.Context, userId uuid.UUID) (*types.User, error) +type Db interface { + InsertUser(ctx context.Context, user *auth_types.User) error + UpdateUser(ctx context.Context, user *auth_types.User) error + GetUserByEmail(ctx context.Context, email string) (*auth_types.User, error) + GetUser(ctx context.Context, userId uuid.UUID) (*auth_types.User, error) DeleteUser(ctx context.Context, userId uuid.UUID) error - InsertToken(ctx context.Context, token *types.Token) error - GetToken(ctx context.Context, token string) (*types.Token, error) - GetTokensByUserIdAndType(ctx context.Context, userId uuid.UUID, tokenType types.TokenType) ([]*types.Token, error) - GetTokensBySessionIdAndType(ctx context.Context, sessionId string, tokenType types.TokenType) ([]*types.Token, error) + InsertToken(ctx context.Context, token *auth_types.Token) error + GetToken(ctx context.Context, token string) (*auth_types.Token, error) + GetTokensByUserIdAndType(ctx context.Context, userId uuid.UUID, tokenType auth_types.TokenType) ([]*auth_types.Token, error) + GetTokensBySessionIdAndType(ctx context.Context, sessionId string, tokenType auth_types.TokenType) ([]*auth_types.Token, error) DeleteToken(ctx context.Context, token string) error - InsertSession(ctx context.Context, session *types.Session) error - GetSession(ctx context.Context, sessionId string) (*types.Session, error) - GetSessions(ctx context.Context, userId uuid.UUID) ([]*types.Session, error) + InsertSession(ctx context.Context, session *auth_types.Session) error + GetSession(ctx context.Context, sessionId string) (*auth_types.Session, error) + GetSessions(ctx context.Context, userId uuid.UUID) ([]*auth_types.Session, error) DeleteSession(ctx context.Context, sessionId string) error DeleteOldSessions(ctx context.Context) error DeleteOldTokens(ctx context.Context) error } -type AuthSqlite struct { +type DbSqlite struct { db *sqlx.DB } -func NewAuthSqlite(db *sqlx.DB) *AuthSqlite { - return &AuthSqlite{db: db} +func NewDbSqlite(db *sqlx.DB) *DbSqlite { + return &DbSqlite{db: db} } -func (db AuthSqlite) InsertUser(ctx context.Context, user *types.User) error { +func (db DbSqlite) InsertUser(ctx context.Context, user *auth_types.User) error { _, err := db.db.ExecContext(ctx, ` INSERT INTO user (user_id, email, email_verified, email_verified_at, is_admin, password, salt, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, @@ -50,17 +51,17 @@ func (db AuthSqlite) InsertUser(ctx context.Context, user *types.User) error { if err != nil { if strings.Contains(err.Error(), "email") { - return ErrAlreadyExists + return core.ErrAlreadyExists } slog.ErrorContext(ctx, "SQL error InsertUser", "err", err) - return types.ErrInternal + return core.ErrInternal } return nil } -func (db AuthSqlite) UpdateUser(ctx context.Context, user *types.User) error { +func (db DbSqlite) UpdateUser(ctx context.Context, user *auth_types.User) error { _, err := db.db.ExecContext(ctx, ` UPDATE user SET email_verified = ?, email_verified_at = ?, password = ? @@ -69,13 +70,13 @@ func (db AuthSqlite) UpdateUser(ctx context.Context, user *types.User) error { if err != nil { slog.ErrorContext(ctx, "SQL error UpdateUser", "err", err) - return types.ErrInternal + return core.ErrInternal } return nil } -func (db AuthSqlite) GetUserByEmail(ctx context.Context, email string) (*types.User, error) { +func (db DbSqlite) GetUserByEmail(ctx context.Context, email string) (*auth_types.User, error) { var ( userId uuid.UUID emailVerified bool @@ -92,17 +93,17 @@ func (db AuthSqlite) GetUserByEmail(ctx context.Context, email string) (*types.U WHERE email = ?`, email).Scan(&userId, &emailVerified, &emailVerifiedAt, &password, &salt, &createdAt) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, ErrNotFound + return nil, core.ErrNotFound } else { slog.ErrorContext(ctx, "SQL error GetUser", "err", err) - return nil, types.ErrInternal + return nil, core.ErrInternal } } - return types.NewUser(userId, email, emailVerified, emailVerifiedAt, isAdmin, password, salt, createdAt), nil + return auth_types.NewUser(userId, email, emailVerified, emailVerifiedAt, isAdmin, password, salt, createdAt), nil } -func (db AuthSqlite) GetUser(ctx context.Context, userId uuid.UUID) (*types.User, error) { +func (db DbSqlite) GetUser(ctx context.Context, userId uuid.UUID) (*auth_types.User, error) { var ( email string emailVerified bool @@ -119,92 +120,92 @@ func (db AuthSqlite) GetUser(ctx context.Context, userId uuid.UUID) (*types.User WHERE user_id = ?`, userId).Scan(&email, &emailVerified, &emailVerifiedAt, &password, &salt, &createdAt) if err != nil { if errors.Is(err, sql.ErrNoRows) { - return nil, ErrNotFound + return nil, core.ErrNotFound } else { slog.ErrorContext(ctx, "SQL error GetUser", "err", err) - return nil, types.ErrInternal + return nil, core.ErrInternal } } - return types.NewUser(userId, email, emailVerified, emailVerifiedAt, isAdmin, password, salt, createdAt), nil + return auth_types.NewUser(userId, email, emailVerified, emailVerifiedAt, isAdmin, password, salt, createdAt), nil } -func (db AuthSqlite) DeleteUser(ctx context.Context, userId uuid.UUID) error { +func (db DbSqlite) DeleteUser(ctx context.Context, userId uuid.UUID) error { tx, err := db.db.BeginTx(ctx, nil) if err != nil { slog.ErrorContext(ctx, "Could not start transaction", "err", err) - return types.ErrInternal + return core.ErrInternal } _, err = tx.ExecContext(ctx, "DELETE FROM account WHERE user_id = ?", userId) if err != nil { _ = tx.Rollback() slog.ErrorContext(ctx, "Could not delete accounts", "err", err) - return types.ErrInternal + return core.ErrInternal } _, err = tx.ExecContext(ctx, "DELETE FROM token WHERE user_id = ?", userId) if err != nil { _ = tx.Rollback() slog.ErrorContext(ctx, "Could not delete user tokens", "err", err) - return types.ErrInternal + return core.ErrInternal } _, err = tx.ExecContext(ctx, "DELETE FROM session WHERE user_id = ?", userId) if err != nil { _ = tx.Rollback() slog.ErrorContext(ctx, "Could not delete sessions", "err", err) - return types.ErrInternal + return core.ErrInternal } _, err = tx.ExecContext(ctx, "DELETE FROM user WHERE user_id = ?", userId) if err != nil { _ = tx.Rollback() slog.ErrorContext(ctx, "Could not delete user", "err", err) - return types.ErrInternal + return core.ErrInternal } _, err = tx.ExecContext(ctx, "DELETE FROM treasure_chest WHERE user_id = ?", userId) if err != nil { _ = tx.Rollback() slog.ErrorContext(ctx, "Could not delete user", "err", err) - return types.ErrInternal + return core.ErrInternal } _, err = tx.ExecContext(ctx, "DELETE FROM \"transaction\" WHERE user_id = ?", userId) if err != nil { _ = tx.Rollback() slog.ErrorContext(ctx, "Could not delete user", "err", err) - return types.ErrInternal + return core.ErrInternal } err = tx.Commit() if err != nil { slog.ErrorContext(ctx, "Could not commit transaction", "err", err) - return types.ErrInternal + return core.ErrInternal } return nil } -func (db AuthSqlite) InsertToken(ctx context.Context, token *types.Token) error { +func (db DbSqlite) InsertToken(ctx context.Context, token *auth_types.Token) error { _, err := db.db.ExecContext(ctx, ` INSERT INTO token (user_id, session_id, type, token, created_at, expires_at) VALUES (?, ?, ?, ?, ?, ?)`, token.UserId, token.SessionId, token.Type, token.Token, token.CreatedAt, token.ExpiresAt) if err != nil { slog.ErrorContext(ctx, "Could not insert token", "err", err) - return types.ErrInternal + return core.ErrInternal } return nil } -func (db AuthSqlite) GetToken(ctx context.Context, token string) (*types.Token, error) { +func (db DbSqlite) GetToken(ctx context.Context, token string) (*auth_types.Token, error) { var ( userId uuid.UUID sessionId string - tokenType types.TokenType + tokenType auth_types.TokenType createdAtStr string expiresAtStr string createdAt time.Time @@ -219,29 +220,29 @@ func (db AuthSqlite) GetToken(ctx context.Context, token string) (*types.Token, if err != nil { if errors.Is(err, sql.ErrNoRows) { slog.InfoContext(ctx, "Token not found", "token", token) - return nil, ErrNotFound + return nil, core.ErrNotFound } else { slog.ErrorContext(ctx, "Could not get token", "err", err) - return nil, types.ErrInternal + return nil, core.ErrInternal } } createdAt, err = time.Parse(time.RFC3339, createdAtStr) if err != nil { slog.ErrorContext(ctx, "Could not parse token.created_at", "err", err) - return nil, types.ErrInternal + return nil, core.ErrInternal } expiresAt, err = time.Parse(time.RFC3339, expiresAtStr) if err != nil { slog.ErrorContext(ctx, "Could not parse token.expires_at", "err", err) - return nil, types.ErrInternal + return nil, core.ErrInternal } - return types.NewToken(userId, sessionId, token, tokenType, createdAt, expiresAt), nil + return auth_types.NewToken(userId, sessionId, token, tokenType, createdAt, expiresAt), nil } -func (db AuthSqlite) GetTokensByUserIdAndType(ctx context.Context, userId uuid.UUID, tokenType types.TokenType) ([]*types.Token, error) { +func (db DbSqlite) GetTokensByUserIdAndType(ctx context.Context, userId uuid.UUID, tokenType auth_types.TokenType) ([]*auth_types.Token, error) { query, err := db.db.QueryContext(ctx, ` SELECT token, created_at, expires_at FROM token @@ -250,13 +251,13 @@ func (db AuthSqlite) GetTokensByUserIdAndType(ctx context.Context, userId uuid.U if err != nil { slog.ErrorContext(ctx, "Could not get token", "err", err) - return nil, types.ErrInternal + return nil, core.ErrInternal } return getTokensFromQuery(ctx, query, userId, "", tokenType) } -func (db AuthSqlite) GetTokensBySessionIdAndType(ctx context.Context, sessionId string, tokenType types.TokenType) ([]*types.Token, error) { +func (db DbSqlite) GetTokensBySessionIdAndType(ctx context.Context, sessionId string, tokenType auth_types.TokenType) ([]*auth_types.Token, error) { query, err := db.db.QueryContext(ctx, ` SELECT token, created_at, expires_at FROM token @@ -265,14 +266,14 @@ func (db AuthSqlite) GetTokensBySessionIdAndType(ctx context.Context, sessionId if err != nil { slog.ErrorContext(ctx, "Could not get token", "err", err) - return nil, types.ErrInternal + return nil, core.ErrInternal } return getTokensFromQuery(ctx, query, uuid.Nil, sessionId, tokenType) } -func getTokensFromQuery(ctx context.Context, query *sql.Rows, userId uuid.UUID, sessionId string, tokenType types.TokenType) ([]*types.Token, error) { - var tokens []*types.Token +func getTokensFromQuery(ctx context.Context, query *sql.Rows, userId uuid.UUID, sessionId string, tokenType auth_types.TokenType) ([]*auth_types.Token, error) { + var tokens []*auth_types.Token hasRows := false for query.Next() { @@ -289,54 +290,54 @@ func getTokensFromQuery(ctx context.Context, query *sql.Rows, userId uuid.UUID, err := query.Scan(&token, &createdAtStr, &expiresAtStr) if err != nil { slog.ErrorContext(ctx, "Could not scan token", "err", err) - return nil, types.ErrInternal + return nil, core.ErrInternal } createdAt, err = time.Parse(time.RFC3339, createdAtStr) if err != nil { slog.ErrorContext(ctx, "Could not parse token.created_at", "err", err) - return nil, types.ErrInternal + return nil, core.ErrInternal } expiresAt, err = time.Parse(time.RFC3339, expiresAtStr) if err != nil { slog.ErrorContext(ctx, "Could not parse token.expires_at", "err", err) - return nil, types.ErrInternal + return nil, core.ErrInternal } - tokens = append(tokens, types.NewToken(userId, sessionId, token, tokenType, createdAt, expiresAt)) + tokens = append(tokens, auth_types.NewToken(userId, sessionId, token, tokenType, createdAt, expiresAt)) } if !hasRows { - return nil, ErrNotFound + return nil, core.ErrNotFound } return tokens, nil } -func (db AuthSqlite) DeleteToken(ctx context.Context, token string) error { +func (db DbSqlite) DeleteToken(ctx context.Context, token string) error { _, err := db.db.ExecContext(ctx, "DELETE FROM token WHERE token = ?", token) if err != nil { slog.ErrorContext(ctx, "Could not delete token", "err", err) - return types.ErrInternal + return core.ErrInternal } return nil } -func (db AuthSqlite) InsertSession(ctx context.Context, session *types.Session) error { +func (db DbSqlite) InsertSession(ctx context.Context, session *auth_types.Session) error { _, err := db.db.ExecContext(ctx, ` INSERT INTO session (session_id, user_id, created_at, expires_at) VALUES (?, ?, ?, ?)`, session.Id, session.UserId, session.CreatedAt, session.ExpiresAt) if err != nil { slog.ErrorContext(ctx, "Could not insert new session", "err", err) - return types.ErrInternal + return core.ErrInternal } return nil } -func (db AuthSqlite) GetSession(ctx context.Context, sessionId string) (*types.Session, error) { +func (db DbSqlite) GetSession(ctx context.Context, sessionId string) (*auth_types.Session, error) { var ( userId uuid.UUID createdAt time.Time @@ -350,56 +351,56 @@ func (db AuthSqlite) GetSession(ctx context.Context, sessionId string) (*types.S if err != nil { slog.WarnContext(ctx, "Session not found", "session-id", sessionId, "err", err) - return nil, ErrNotFound + return nil, core.ErrNotFound } - return types.NewSession(sessionId, userId, createdAt, expiresAt), nil + return auth_types.NewSession(sessionId, userId, createdAt, expiresAt), nil } -func (db AuthSqlite) GetSessions(ctx context.Context, userId uuid.UUID) ([]*types.Session, error) { - var sessions []*types.Session +func (db DbSqlite) GetSessions(ctx context.Context, userId uuid.UUID) ([]*auth_types.Session, error) { + var sessions []*auth_types.Session err := db.db.SelectContext(ctx, &sessions, ` SELECT * FROM session WHERE user_id = ?`, userId) if err != nil { slog.ErrorContext(ctx, "Could not get sessions", "err", err) - return nil, types.ErrInternal + return nil, core.ErrInternal } return sessions, nil } -func (db AuthSqlite) DeleteSession(ctx context.Context, sessionId string) error { +func (db DbSqlite) DeleteSession(ctx context.Context, sessionId string) error { if sessionId != "" { _, err := db.db.ExecContext(ctx, "DELETE FROM session WHERE session_id = ?", sessionId) if err != nil { slog.ErrorContext(ctx, "Could not delete session", "err", err) - return types.ErrInternal + return core.ErrInternal } } return nil } -func (db AuthSqlite) DeleteOldSessions(ctx context.Context) error { +func (db DbSqlite) DeleteOldSessions(ctx context.Context) error { _, err := db.db.ExecContext(ctx, ` DELETE FROM session WHERE expires_at < datetime('now')`) if err != nil { slog.ErrorContext(ctx, "Could not delete old sessions", "err", err) - return types.ErrInternal + return core.ErrInternal } return nil } -func (db AuthSqlite) DeleteOldTokens(ctx context.Context) error { +func (db DbSqlite) DeleteOldTokens(ctx context.Context) error { _, err := db.db.ExecContext(ctx, ` DELETE FROM token WHERE expires_at < datetime('now')`) if err != nil { slog.ErrorContext(ctx, "Could not delete old tokens", "err", err) - return types.ErrInternal + return core.ErrInternal } return nil } diff --git a/internal/handler/auth.go b/internal/authentication/handler.go similarity index 81% rename from internal/handler/auth.go rename to internal/authentication/handler.go index 7370b98..6cf32f6 100644 --- a/internal/handler/auth.go +++ b/internal/authentication/handler.go @@ -1,36 +1,34 @@ -package handler +package authentication import ( "errors" "log/slog" "net/http" "net/url" + "spend-sparrow/internal/auth_types" + "spend-sparrow/internal/authentication/template" "spend-sparrow/internal/core" - "spend-sparrow/internal/handler/middleware" - "spend-sparrow/internal/service" - "spend-sparrow/internal/template/auth" - "spend-sparrow/internal/types" "spend-sparrow/internal/utils" "time" ) -type Auth interface { +type Handler interface { Handle(router *http.ServeMux) } -type AuthImpl struct { - service service.Auth +type HandlerImpl struct { + service Service render *core.Render } -func NewAuth(service service.Auth, render *core.Render) Auth { - return AuthImpl{ +func NewHandler(service Service, render *core.Render) Handler { + return HandlerImpl{ service: service, render: render, } } -func (handler AuthImpl) Handle(router *http.ServeMux) { +func (handler HandlerImpl) Handle(router *http.ServeMux) { router.Handle("GET /auth/signin", handler.handleSignInPage()) router.Handle("POST /api/auth/signin", handler.handleSignIn()) @@ -57,7 +55,7 @@ var ( securityWaitDuration = 250 * time.Millisecond ) -func (handler AuthImpl) handleSignInPage() http.HandlerFunc { +func (handler HandlerImpl) handleSignInPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) @@ -71,17 +69,17 @@ func (handler AuthImpl) handleSignInPage() http.HandlerFunc { return } - comp := auth.SignInOrUpComp(true) + comp := template.SignInOrUpComp(true) handler.render.RenderLayout(r, w, comp, nil) } } -func (handler AuthImpl) handleSignIn() http.HandlerFunc { +func (handler HandlerImpl) handleSignIn() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) - user, err := utils.WaitMinimumTime(securityWaitDuration, func() (*types.User, error) { + user, err := utils.WaitMinimumTime(securityWaitDuration, func() (*auth_types.User, error) { session := core.GetSession(r) email := r.FormValue("email") password := r.FormValue("password") @@ -91,14 +89,14 @@ func (handler AuthImpl) handleSignIn() http.HandlerFunc { return nil, err } - cookie := middleware.CreateSessionCookie(session.Id) + cookie := core.CreateSessionCookie(session.Id) http.SetCookie(w, &cookie) return user, nil }) if err != nil { - if errors.Is(err, service.ErrInvalidCredentials) { + if errors.Is(err, ErrInvalidCredentials) { utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Invalid email or password", http.StatusUnauthorized) } else { utils.TriggerToastWithStatus(r.Context(), w, r, "error", "An error occurred", http.StatusInternalServerError) @@ -114,7 +112,7 @@ func (handler AuthImpl) handleSignIn() http.HandlerFunc { } } -func (handler AuthImpl) handleSignUpPage() http.HandlerFunc { +func (handler HandlerImpl) handleSignUpPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) @@ -129,12 +127,12 @@ func (handler AuthImpl) handleSignUpPage() http.HandlerFunc { return } - signUpComp := auth.SignInOrUpComp(false) + signUpComp := template.SignInOrUpComp(false) handler.render.RenderLayout(r, w, signUpComp, nil) } } -func (handler AuthImpl) handleSignUpVerifyPage() http.HandlerFunc { +func (handler HandlerImpl) handleSignUpVerifyPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) @@ -149,12 +147,12 @@ func (handler AuthImpl) handleSignUpVerifyPage() http.HandlerFunc { return } - signIn := auth.VerifyComp() + signIn := template.VerifyComp() handler.render.RenderLayout(r, w, signIn, user) } } -func (handler AuthImpl) handleVerifyResendComp() http.HandlerFunc { +func (handler HandlerImpl) handleVerifyResendComp() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) @@ -173,7 +171,7 @@ func (handler AuthImpl) handleVerifyResendComp() http.HandlerFunc { } } -func (handler AuthImpl) handleSignUpVerifyResponsePage() http.HandlerFunc { +func (handler HandlerImpl) handleSignUpVerifyResponsePage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) @@ -182,7 +180,7 @@ func (handler AuthImpl) handleSignUpVerifyResponsePage() http.HandlerFunc { err := handler.service.VerifyUserEmail(r.Context(), token) isVerified := err == nil - comp := auth.VerifyResponseComp(isVerified) + comp := template.VerifyResponseComp(isVerified) var status int if isVerified { @@ -195,7 +193,7 @@ func (handler AuthImpl) handleSignUpVerifyResponsePage() http.HandlerFunc { } } -func (handler AuthImpl) handleSignUp() http.HandlerFunc { +func (handler HandlerImpl) handleSignUp() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) @@ -216,14 +214,14 @@ func (handler AuthImpl) handleSignUp() http.HandlerFunc { if err != nil { switch { - case errors.Is(err, types.ErrInternal): + case errors.Is(err, core.ErrInternal): utils.TriggerToastWithStatus(r.Context(), w, r, "error", "An error occurred", http.StatusInternalServerError) return - case errors.Is(err, service.ErrInvalidEmail): + case errors.Is(err, ErrInvalidEmail): utils.TriggerToastWithStatus(r.Context(), w, r, "error", "The email provided is invalid", http.StatusBadRequest) return - case errors.Is(err, service.ErrInvalidPassword): - utils.TriggerToastWithStatus(r.Context(), w, r, "error", service.ErrInvalidPassword.Error(), http.StatusBadRequest) + case errors.Is(err, ErrInvalidPassword): + utils.TriggerToastWithStatus(r.Context(), w, r, "error", ErrInvalidPassword.Error(), http.StatusBadRequest) return } // If err is "service.ErrAccountExists", then just continue @@ -233,7 +231,7 @@ func (handler AuthImpl) handleSignUp() http.HandlerFunc { } } -func (handler AuthImpl) handleSignOut() http.HandlerFunc { +func (handler HandlerImpl) handleSignOut() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) @@ -262,7 +260,7 @@ func (handler AuthImpl) handleSignOut() http.HandlerFunc { } } -func (handler AuthImpl) handleDeleteAccountPage() http.HandlerFunc { +func (handler HandlerImpl) handleDeleteAccountPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) @@ -272,12 +270,12 @@ func (handler AuthImpl) handleDeleteAccountPage() http.HandlerFunc { return } - comp := auth.DeleteAccountComp() + comp := template.DeleteAccountComp() handler.render.RenderLayout(r, w, comp, user) } } -func (handler AuthImpl) handleDeleteAccountComp() http.HandlerFunc { +func (handler HandlerImpl) handleDeleteAccountComp() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) @@ -291,7 +289,7 @@ func (handler AuthImpl) handleDeleteAccountComp() http.HandlerFunc { err := handler.service.DeleteAccount(r.Context(), user, password) if err != nil { - if errors.Is(err, service.ErrInvalidCredentials) { + if errors.Is(err, ErrInvalidCredentials) { utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Password not correct", http.StatusBadRequest) } else { utils.TriggerToastWithStatus(r.Context(), w, r, "error", "Internal Server Error", http.StatusInternalServerError) @@ -303,7 +301,7 @@ func (handler AuthImpl) handleDeleteAccountComp() http.HandlerFunc { } } -func (handler AuthImpl) handleChangePasswordPage() http.HandlerFunc { +func (handler HandlerImpl) handleChangePasswordPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) @@ -316,12 +314,12 @@ func (handler AuthImpl) handleChangePasswordPage() http.HandlerFunc { return } - comp := auth.ChangePasswordComp(isPasswordReset) + comp := template.ChangePasswordComp(isPasswordReset) handler.render.RenderLayout(r, w, comp, user) } } -func (handler AuthImpl) handleChangePasswordComp() http.HandlerFunc { +func (handler HandlerImpl) handleChangePasswordComp() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) @@ -345,7 +343,7 @@ func (handler AuthImpl) handleChangePasswordComp() http.HandlerFunc { } } -func (handler AuthImpl) handleForgotPasswordPage() http.HandlerFunc { +func (handler HandlerImpl) handleForgotPasswordPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) @@ -355,12 +353,12 @@ func (handler AuthImpl) handleForgotPasswordPage() http.HandlerFunc { return } - comp := auth.ResetPasswordComp() + comp := template.ResetPasswordComp() handler.render.RenderLayout(r, w, comp, user) } } -func (handler AuthImpl) handleForgotPasswordComp() http.HandlerFunc { +func (handler HandlerImpl) handleForgotPasswordComp() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) @@ -383,7 +381,7 @@ func (handler AuthImpl) handleForgotPasswordComp() http.HandlerFunc { } } -func (handler AuthImpl) handleForgotPasswordResponseComp() http.HandlerFunc { +func (handler HandlerImpl) handleForgotPasswordResponseComp() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) diff --git a/internal/service/auth.go b/internal/authentication/service.go similarity index 65% rename from internal/service/auth.go rename to internal/authentication/service.go index 06e782a..64424fd 100644 --- a/internal/service/auth.go +++ b/internal/authentication/service.go @@ -1,4 +1,4 @@ -package service +package authentication import ( "context" @@ -6,7 +6,8 @@ import ( "errors" "log/slog" "net/mail" - "spend-sparrow/internal/db" + "spend-sparrow/internal/auth_types" + "spend-sparrow/internal/core" mailTemplate "spend-sparrow/internal/template/mail" "spend-sparrow/internal/types" "strings" @@ -25,39 +26,39 @@ var ( ErrTokenInvalid = errors.New("token is invalid") ) -type Auth interface { - SignUp(ctx context.Context, email string, password string) (*types.User, error) +type Service interface { + SignUp(ctx context.Context, email string, password string) (*auth_types.User, error) SendVerificationMail(ctx context.Context, userId uuid.UUID, email string) VerifyUserEmail(ctx context.Context, token string) error - SignIn(ctx context.Context, session *types.Session, email string, password string) (*types.Session, *types.User, error) - SignInSession(ctx context.Context, sessionId string) (*types.Session, *types.User, error) - SignInAnonymous(ctx context.Context) (*types.Session, error) + SignIn(ctx context.Context, session *auth_types.Session, email string, password string) (*auth_types.Session, *auth_types.User, error) + SignInSession(ctx context.Context, sessionId string) (*auth_types.Session, *auth_types.User, error) + SignInAnonymous(ctx context.Context) (*auth_types.Session, error) SignOut(ctx context.Context, sessionId string) error - DeleteAccount(ctx context.Context, user *types.User, currPass string) error + DeleteAccount(ctx context.Context, user *auth_types.User, currPass string) error - ChangePassword(ctx context.Context, user *types.User, sessionId string, currPass, newPass string) error + ChangePassword(ctx context.Context, user *auth_types.User, sessionId string, currPass, newPass string) error SendForgotPasswordMail(ctx context.Context, email string) error ForgotPassword(ctx context.Context, token string, newPass string) error IsCsrfTokenValid(ctx context.Context, tokenStr string, sessionId string) bool - GetCsrfToken(ctx context.Context, session *types.Session) (string, error) + GetCsrfToken(ctx context.Context, session *auth_types.Session) (string, error) CleanupSessionsAndTokens(ctx context.Context) error } -type AuthImpl struct { - db db.Auth - random Random - clock Clock - mail Mail +type ServiceImpl struct { + db Db + random core.Random + clock core.Clock + mail core.Mail serverSettings *types.Settings } -func NewAuth(db db.Auth, random Random, clock Clock, mail Mail, serverSettings *types.Settings) *AuthImpl { - return &AuthImpl{ +func NewService(db Db, random core.Random, clock core.Clock, mail core.Mail, serverSettings *types.Settings) *ServiceImpl { + return &ServiceImpl{ db: db, random: random, clock: clock, @@ -66,13 +67,13 @@ func NewAuth(db db.Auth, random Random, clock Clock, mail Mail, serverSettings * } } -func (service AuthImpl) SignIn(ctx context.Context, session *types.Session, email string, password string) (*types.Session, *types.User, error) { +func (service ServiceImpl) SignIn(ctx context.Context, session *auth_types.Session, email string, password string) (*auth_types.Session, *auth_types.User, error) { user, err := service.db.GetUserByEmail(ctx, email) if err != nil { - if errors.Is(err, db.ErrNotFound) { + if errors.Is(err, core.ErrNotFound) { return nil, nil, ErrInvalidCredentials } else { - return nil, nil, types.ErrInternal + return nil, nil, core.ErrInternal } } @@ -84,36 +85,36 @@ func (service AuthImpl) SignIn(ctx context.Context, session *types.Session, emai newSession, err := service.createSession(ctx, user.Id) if err != nil { - return nil, nil, types.ErrInternal + return nil, nil, core.ErrInternal } err = service.db.DeleteSession(ctx, session.Id) if err != nil { - return nil, nil, types.ErrInternal + return nil, nil, core.ErrInternal } - tokens, err := service.db.GetTokensBySessionIdAndType(ctx, session.Id, types.TokenTypeCsrf) + tokens, err := service.db.GetTokensBySessionIdAndType(ctx, session.Id, auth_types.TokenTypeCsrf) if err != nil { - return nil, nil, types.ErrInternal + return nil, nil, core.ErrInternal } for _, token := range tokens { err = service.db.DeleteToken(ctx, token.Token) if err != nil { - return nil, nil, types.ErrInternal + return nil, nil, core.ErrInternal } } return newSession, user, nil } -func (service AuthImpl) SignInSession(ctx context.Context, sessionId string) (*types.Session, *types.User, error) { +func (service ServiceImpl) SignInSession(ctx context.Context, sessionId string) (*auth_types.Session, *auth_types.User, error) { if sessionId == "" { return nil, nil, ErrSessionIdInvalid } session, err := service.db.GetSession(ctx, sessionId) if err != nil { - return nil, nil, types.ErrInternal + return nil, nil, core.ErrInternal } if session.ExpiresAt.Before(service.clock.Now()) { _ = service.db.DeleteSession(ctx, sessionId) @@ -126,16 +127,16 @@ func (service AuthImpl) SignInSession(ctx context.Context, sessionId string) (*t user, err := service.db.GetUser(ctx, session.UserId) if err != nil { - return nil, nil, types.ErrInternal + return nil, nil, core.ErrInternal } return session, user, nil } -func (service AuthImpl) SignInAnonymous(ctx context.Context) (*types.Session, error) { +func (service ServiceImpl) SignInAnonymous(ctx context.Context) (*auth_types.Session, error) { session, err := service.createSession(ctx, uuid.Nil) if err != nil { - return nil, types.ErrInternal + return nil, core.ErrInternal } slog.InfoContext(ctx, "anonymous session created", "session-id", session.Id) @@ -143,7 +144,7 @@ func (service AuthImpl) SignInAnonymous(ctx context.Context) (*types.Session, er return session, nil } -func (service AuthImpl) SignUp(ctx context.Context, email string, password string) (*types.User, error) { +func (service ServiceImpl) SignUp(ctx context.Context, email string, password string) (*auth_types.User, error) { _, err := mail.ParseAddress(email) if err != nil { return nil, ErrInvalidEmail @@ -155,37 +156,37 @@ func (service AuthImpl) SignUp(ctx context.Context, email string, password strin userId, err := service.random.UUID(ctx) if err != nil { - return nil, types.ErrInternal + return nil, core.ErrInternal } salt, err := service.random.Bytes(ctx, 16) if err != nil { - return nil, types.ErrInternal + return nil, core.ErrInternal } hash := GetHashPassword(password, salt) - user := types.NewUser(userId, email, false, nil, false, hash, salt, service.clock.Now()) + user := auth_types.NewUser(userId, email, false, nil, false, hash, salt, service.clock.Now()) err = service.db.InsertUser(ctx, user) if err != nil { - if errors.Is(err, db.ErrAlreadyExists) { + if errors.Is(err, core.ErrAlreadyExists) { return nil, ErrAccountExists } else { - return nil, types.ErrInternal + return nil, core.ErrInternal } } return user, nil } -func (service AuthImpl) SendVerificationMail(ctx context.Context, userId uuid.UUID, email string) { - tokens, err := service.db.GetTokensByUserIdAndType(ctx, userId, types.TokenTypeEmailVerify) - if err != nil && !errors.Is(err, db.ErrNotFound) { +func (service ServiceImpl) SendVerificationMail(ctx context.Context, userId uuid.UUID, email string) { + tokens, err := service.db.GetTokensByUserIdAndType(ctx, userId, auth_types.TokenTypeEmailVerify) + if err != nil && !errors.Is(err, core.ErrNotFound) { return } - var token *types.Token + var token *auth_types.Token if len(tokens) > 0 { token = tokens[0] @@ -197,11 +198,11 @@ func (service AuthImpl) SendVerificationMail(ctx context.Context, userId uuid.UU return } - token = types.NewToken( + token = auth_types.NewToken( userId, "", newTokenStr, - types.TokenTypeEmailVerify, + auth_types.TokenTypeEmailVerify, service.clock.Now(), service.clock.Now().Add(24*time.Hour)) @@ -221,29 +222,29 @@ func (service AuthImpl) SendVerificationMail(ctx context.Context, userId uuid.UU service.mail.SendMail(ctx, email, "Welcome to spend-sparrow", w.String()) } -func (service AuthImpl) VerifyUserEmail(ctx context.Context, tokenStr string) error { +func (service ServiceImpl) VerifyUserEmail(ctx context.Context, tokenStr string) error { if tokenStr == "" { - return types.ErrInternal + return core.ErrInternal } token, err := service.db.GetToken(ctx, tokenStr) if err != nil { - return types.ErrInternal + return core.ErrInternal } user, err := service.db.GetUser(ctx, token.UserId) if err != nil { - return types.ErrInternal + return core.ErrInternal } - if token.Type != types.TokenTypeEmailVerify { - return types.ErrInternal + if token.Type != auth_types.TokenTypeEmailVerify { + return core.ErrInternal } now := service.clock.Now() if token.ExpiresAt.Before(now) { - return types.ErrInternal + return core.ErrInternal } user.EmailVerified = true @@ -251,21 +252,21 @@ func (service AuthImpl) VerifyUserEmail(ctx context.Context, tokenStr string) er err = service.db.UpdateUser(ctx, user) if err != nil { - return types.ErrInternal + return core.ErrInternal } _ = service.db.DeleteToken(ctx, token.Token) return nil } -func (service AuthImpl) SignOut(ctx context.Context, sessionId string) error { +func (service ServiceImpl) SignOut(ctx context.Context, sessionId string) error { return service.db.DeleteSession(ctx, sessionId) } -func (service AuthImpl) DeleteAccount(ctx context.Context, user *types.User, currPass string) error { +func (service ServiceImpl) DeleteAccount(ctx context.Context, user *auth_types.User, currPass string) error { userDb, err := service.db.GetUser(ctx, user.Id) if err != nil { - return types.ErrInternal + return core.ErrInternal } currHash := GetHashPassword(currPass, userDb.Salt) @@ -283,7 +284,7 @@ func (service AuthImpl) DeleteAccount(ctx context.Context, user *types.User, cur return nil } -func (service AuthImpl) ChangePassword(ctx context.Context, user *types.User, sessionId string, currPass, newPass string) error { +func (service ServiceImpl) ChangePassword(ctx context.Context, user *auth_types.User, sessionId string, currPass, newPass string) error { if !isPasswordValid(newPass) { return ErrInvalidPassword } @@ -308,13 +309,13 @@ func (service AuthImpl) ChangePassword(ctx context.Context, user *types.User, se sessions, err := service.db.GetSessions(ctx, user.Id) if err != nil { - return types.ErrInternal + return core.ErrInternal } for _, s := range sessions { if s.Id != sessionId { err = service.db.DeleteSession(ctx, s.Id) if err != nil { - return types.ErrInternal + return core.ErrInternal } } } @@ -322,7 +323,7 @@ func (service AuthImpl) ChangePassword(ctx context.Context, user *types.User, se return nil } -func (service AuthImpl) SendForgotPasswordMail(ctx context.Context, email string) error { +func (service ServiceImpl) SendForgotPasswordMail(ctx context.Context, email string) error { tokenStr, err := service.random.String(ctx, 32) if err != nil { return err @@ -330,38 +331,38 @@ func (service AuthImpl) SendForgotPasswordMail(ctx context.Context, email string user, err := service.db.GetUserByEmail(ctx, email) if err != nil { - if errors.Is(err, db.ErrNotFound) { + if errors.Is(err, core.ErrNotFound) { return nil } else { - return types.ErrInternal + return core.ErrInternal } } - token := types.NewToken( + token := auth_types.NewToken( user.Id, "", tokenStr, - types.TokenTypePasswordReset, + auth_types.TokenTypePasswordReset, service.clock.Now(), service.clock.Now().Add(15*time.Minute)) err = service.db.InsertToken(ctx, token) if err != nil { - return types.ErrInternal + return core.ErrInternal } var mail strings.Builder err = mailTemplate.ResetPassword(service.serverSettings.BaseUrl, token.Token).Render(context.Background(), &mail) if err != nil { slog.ErrorContext(ctx, "Could not render reset password email", "err", err) - return types.ErrInternal + return core.ErrInternal } service.mail.SendMail(ctx, email, "Reset Password", mail.String()) return nil } -func (service AuthImpl) ForgotPassword(ctx context.Context, tokenStr string, newPass string) error { +func (service ServiceImpl) ForgotPassword(ctx context.Context, tokenStr string, newPass string) error { if !isPasswordValid(newPass) { return ErrInvalidPassword } @@ -376,7 +377,7 @@ func (service AuthImpl) ForgotPassword(ctx context.Context, tokenStr string, new return err } - if token.Type != types.TokenTypePasswordReset || + if token.Type != auth_types.TokenTypePasswordReset || token.ExpiresAt.Before(service.clock.Now()) { return ErrTokenInvalid } @@ -384,7 +385,7 @@ func (service AuthImpl) ForgotPassword(ctx context.Context, tokenStr string, new user, err := service.db.GetUser(ctx, token.UserId) if err != nil { slog.ErrorContext(ctx, "Could not get user from token", "err", err) - return types.ErrInternal + return core.ErrInternal } passHash := GetHashPassword(newPass, user.Salt) @@ -397,26 +398,26 @@ func (service AuthImpl) ForgotPassword(ctx context.Context, tokenStr string, new sessions, err := service.db.GetSessions(ctx, user.Id) if err != nil { - return types.ErrInternal + return core.ErrInternal } for _, session := range sessions { err = service.db.DeleteSession(ctx, session.Id) if err != nil { - return types.ErrInternal + return core.ErrInternal } } return nil } -func (service AuthImpl) IsCsrfTokenValid(ctx context.Context, tokenStr string, sessionId string) bool { +func (service ServiceImpl) IsCsrfTokenValid(ctx context.Context, tokenStr string, sessionId string) bool { token, err := service.db.GetToken(ctx, tokenStr) if err != nil { return false } - if token.Type != types.TokenTypeCsrf || + if token.Type != auth_types.TokenTypeCsrf || token.SessionId != sessionId || token.ExpiresAt.Before(service.clock.Now()) { return false @@ -425,12 +426,12 @@ func (service AuthImpl) IsCsrfTokenValid(ctx context.Context, tokenStr string, s return true } -func (service AuthImpl) GetCsrfToken(ctx context.Context, session *types.Session) (string, error) { +func (service ServiceImpl) GetCsrfToken(ctx context.Context, session *auth_types.Session) (string, error) { if session == nil { - return "", types.ErrInternal + return "", core.ErrInternal } - tokens, _ := service.db.GetTokensBySessionIdAndType(ctx, session.Id, types.TokenTypeCsrf) + tokens, _ := service.db.GetTokensBySessionIdAndType(ctx, session.Id, auth_types.TokenTypeCsrf) if len(tokens) > 0 { return tokens[0].Token, nil @@ -438,19 +439,19 @@ func (service AuthImpl) GetCsrfToken(ctx context.Context, session *types.Session tokenStr, err := service.random.String(ctx, 32) if err != nil { - return "", types.ErrInternal + return "", core.ErrInternal } - token := types.NewToken( + token := auth_types.NewToken( session.UserId, session.Id, tokenStr, - types.TokenTypeCsrf, + auth_types.TokenTypeCsrf, service.clock.Now(), service.clock.Now().Add(8*time.Hour)) err = service.db.InsertToken(ctx, token) if err != nil { - return "", types.ErrInternal + return "", core.ErrInternal } slog.InfoContext(ctx, "CSRF-Token created", "token", tokenStr) @@ -458,34 +459,34 @@ func (service AuthImpl) GetCsrfToken(ctx context.Context, session *types.Session return tokenStr, nil } -func (service AuthImpl) CleanupSessionsAndTokens(ctx context.Context) error { +func (service ServiceImpl) CleanupSessionsAndTokens(ctx context.Context) error { err := service.db.DeleteOldSessions(ctx) if err != nil { - return types.ErrInternal + return core.ErrInternal } err = service.db.DeleteOldTokens(ctx) if err != nil { - return types.ErrInternal + return core.ErrInternal } return nil } -func (service AuthImpl) createSession(ctx context.Context, userId uuid.UUID) (*types.Session, error) { +func (service ServiceImpl) createSession(ctx context.Context, userId uuid.UUID) (*auth_types.Session, error) { sessionId, err := service.random.String(ctx, 32) if err != nil { - return nil, types.ErrInternal + return nil, core.ErrInternal } createAt := service.clock.Now() expiresAt := createAt.Add(24 * time.Hour) - session := types.NewSession(sessionId, userId, createAt, expiresAt) + session := auth_types.NewSession(sessionId, userId, createAt, expiresAt) err = service.db.InsertSession(ctx, session) if err != nil { - return nil, types.ErrInternal + return nil, core.ErrInternal } return session, nil diff --git a/internal/template/auth/change_password.templ b/internal/authentication/template/change_password.templ similarity index 98% rename from internal/template/auth/change_password.templ rename to internal/authentication/template/change_password.templ index 9e761fb..db3351d 100644 --- a/internal/template/auth/change_password.templ +++ b/internal/authentication/template/change_password.templ @@ -1,4 +1,4 @@ -package auth +package template templ ChangePasswordComp(isPasswordReset bool) {