106 lines
2.2 KiB
Go

package auth
import (
"dk/internal/database"
"dk/internal/password"
"dk/internal/users"
)
// Manager is the global singleton instance
var Manager *AuthManager
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,
}
}
// InitializeManager initializes the global Manager singleton
func InitializeManager(db *database.DB, sessionsFilePath string) {
Manager = NewAuthManager(db, sessionsFilePath)
}
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(usernameOrEmail)
if err != nil {
// Try by email if username lookup failed
user, err = users.GetByEmail(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
}