package auth import ( "dk/internal/database" "dk/internal/password" "dk/internal/users" ) type User struct { ID int Username string Email string } type AuthManager struct { sessionStore *SessionStore db *database.DB } func NewAuthManager(db *database.DB, sessionsFilePath string) *AuthManager { return &AuthManager{ sessionStore: NewSessionStore(sessionsFilePath), db: db, } } func (am *AuthManager) Authenticate(usernameOrEmail, plainPassword string) (*User, error) { var user *users.User var err error // Try to find user by username first user, err = users.GetByUsername(am.db, usernameOrEmail) if err != nil { // Try by email if username lookup failed user, err = users.GetByEmail(am.db, usernameOrEmail) if err != nil { return nil, err } } // Verify password isValid, err := password.Verify(plainPassword, user.Password) if err != nil { return nil, err } if !isValid { return nil, ErrInvalidCredentials } return &User{ ID: user.ID, Username: user.Username, Email: user.Email, }, nil } func (am *AuthManager) CreateSession(user *User) *Session { return am.sessionStore.Create(user.ID, user.Username, user.Email) } func (am *AuthManager) GetSession(sessionID string) (*Session, bool) { return am.sessionStore.Get(sessionID) } func (am *AuthManager) UpdateSession(sessionID string) bool { return am.sessionStore.Update(sessionID) } func (am *AuthManager) DeleteSession(sessionID string) { am.sessionStore.Delete(sessionID) } func (am *AuthManager) SessionStats() (total, active int) { return am.sessionStore.Stats() } func (am *AuthManager) DB() *database.DB { return am.db } func (am *AuthManager) Close() error { return am.sessionStore.Close() } var ( ErrInvalidCredentials = &AuthError{"invalid username/email or password"} ErrSessionNotFound = &AuthError{"session not found"} ErrSessionExpired = &AuthError{"session expired"} ) type AuthError struct { Message string } func (e *AuthError) Error() string { return e.Message }