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 87% rename from internal/handler/auth.go rename to internal/authentication/handler.go index 7370b98..f4dde7e 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/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,13 +69,13 @@ 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) @@ -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) @@ -134,7 +132,7 @@ func (handler AuthImpl) handleSignUpPage() http.HandlerFunc { } } -func (handler AuthImpl) handleSignUpVerifyPage() http.HandlerFunc { +func (handler HandlerImpl) handleSignUpVerifyPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) @@ -154,7 +152,7 @@ func (handler AuthImpl) handleSignUpVerifyPage() http.HandlerFunc { } } -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) @@ -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) @@ -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) @@ -277,7 +275,7 @@ func (handler AuthImpl) handleDeleteAccountPage() http.HandlerFunc { } } -func (handler AuthImpl) handleDeleteAccountComp() http.HandlerFunc { +func (handler HandlerImpl) handleDeleteAccountComp() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { core.UpdateSpan(r) @@ -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) @@ -321,7 +319,7 @@ func (handler AuthImpl) handleChangePasswordPage() http.HandlerFunc { } } -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) @@ -360,7 +358,7 @@ func (handler AuthImpl) handleForgotPasswordPage() http.HandlerFunc { } } -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 79% rename from internal/service/auth.go rename to internal/authentication/service.go index 06e782a..30f6736 100644 --- a/internal/service/auth.go +++ b/internal/authentication/service.go @@ -1,4 +1,4 @@ -package service +package authentication import ( "context" @@ -6,6 +6,8 @@ import ( "errors" "log/slog" "net/mail" + "spend-sparrow/internal/auth_types" + "spend-sparrow/internal/core" "spend-sparrow/internal/db" mailTemplate "spend-sparrow/internal/template/mail" "spend-sparrow/internal/types" @@ -25,39 +27,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 +type ServiceImpl struct { + db Db + random core.Random clock Clock mail 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.Auth, random Random, clock Clock, mail Mail, serverSettings *types.Settings) *HandlerImpl { + return &HandlerImpl{ db: db, random: random, clock: clock, @@ -66,7 +68,7 @@ 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 HandlerImpl) SignIn(ctx context.Context, session *auth_types.Session, email string, password string) (*auth_type.Session, *auth_types.User, error) { user, err := service.db.GetUserByEmail(ctx, email) if err != nil { if errors.Is(err, db.ErrNotFound) { @@ -106,7 +108,7 @@ func (service AuthImpl) SignIn(ctx context.Context, session *types.Session, emai return newSession, user, nil } -func (service AuthImpl) SignInSession(ctx context.Context, sessionId string) (*types.Session, *types.User, error) { +func (service HandlerImpl) SignInSession(ctx context.Context, sessionId string) (*auth_types.Session, *auth_types.User, error) { if sessionId == "" { return nil, nil, ErrSessionIdInvalid } @@ -132,7 +134,7 @@ func (service AuthImpl) SignInSession(ctx context.Context, sessionId string) (*t return session, user, nil } -func (service AuthImpl) SignInAnonymous(ctx context.Context) (*types.Session, error) { +func (service HandlerImpl) SignInAnonymous(ctx context.Context) (*auth_types.Session, error) { session, err := service.createSession(ctx, uuid.Nil) if err != nil { return nil, types.ErrInternal @@ -143,7 +145,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 HandlerImpl) SignUp(ctx context.Context, email string, password string) (*auth_types.User, error) { _, err := mail.ParseAddress(email) if err != nil { return nil, ErrInvalidEmail @@ -179,7 +181,7 @@ func (service AuthImpl) SignUp(ctx context.Context, email string, password strin return user, nil } -func (service AuthImpl) SendVerificationMail(ctx context.Context, userId uuid.UUID, email string) { +func (service HandlerImpl) 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) { return @@ -221,7 +223,7 @@ 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 HandlerImpl) VerifyUserEmail(ctx context.Context, tokenStr string) error { if tokenStr == "" { return types.ErrInternal } @@ -258,11 +260,11 @@ func (service AuthImpl) VerifyUserEmail(ctx context.Context, tokenStr string) er return nil } -func (service AuthImpl) SignOut(ctx context.Context, sessionId string) error { +func (service HandlerImpl) 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 HandlerImpl) 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 @@ -283,7 +285,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 HandlerImpl) ChangePassword(ctx context.Context, user *auth_types.User, sessionId string, currPass, newPass string) error { if !isPasswordValid(newPass) { return ErrInvalidPassword } @@ -322,7 +324,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 HandlerImpl) SendForgotPasswordMail(ctx context.Context, email string) error { tokenStr, err := service.random.String(ctx, 32) if err != nil { return err @@ -361,7 +363,7 @@ func (service AuthImpl) SendForgotPasswordMail(ctx context.Context, email string return nil } -func (service AuthImpl) ForgotPassword(ctx context.Context, tokenStr string, newPass string) error { +func (service HandlerImpl) ForgotPassword(ctx context.Context, tokenStr string, newPass string) error { if !isPasswordValid(newPass) { return ErrInvalidPassword } @@ -410,7 +412,7 @@ func (service AuthImpl) ForgotPassword(ctx context.Context, tokenStr string, new return nil } -func (service AuthImpl) IsCsrfTokenValid(ctx context.Context, tokenStr string, sessionId string) bool { +func (service HandlerImpl) IsCsrfTokenValid(ctx context.Context, tokenStr string, sessionId string) bool { token, err := service.db.GetToken(ctx, tokenStr) if err != nil { return false @@ -425,7 +427,7 @@ 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 HandlerImpl) GetCsrfToken(ctx context.Context, session *auth_types.Session) (string, error) { if session == nil { return "", types.ErrInternal } @@ -458,7 +460,7 @@ func (service AuthImpl) GetCsrfToken(ctx context.Context, session *types.Session return tokenStr, nil } -func (service AuthImpl) CleanupSessionsAndTokens(ctx context.Context) error { +func (service HandlerImpl) CleanupSessionsAndTokens(ctx context.Context) error { err := service.db.DeleteOldSessions(ctx) if err != nil { return types.ErrInternal @@ -472,7 +474,7 @@ func (service AuthImpl) CleanupSessionsAndTokens(ctx context.Context) error { return nil } -func (service AuthImpl) createSession(ctx context.Context, userId uuid.UUID) (*types.Session, error) { +func (service HandlerImpl) 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 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) {