93 lines
2.0 KiB
Go
93 lines
2.0 KiB
Go
// Package auth provides authentication and session management functionality.
|
|
// It includes secure session storage with in-memory caching and JSON persistence,
|
|
// user authentication against the database, and secure cookie handling.
|
|
package auth
|
|
|
|
import (
|
|
"dk/internal/models/users"
|
|
"dk/internal/password"
|
|
"dk/internal/session"
|
|
)
|
|
|
|
var Manager *AuthManager
|
|
|
|
type AuthManager struct {
|
|
store *session.Store
|
|
}
|
|
|
|
func Init(sessionsFilePath string) {
|
|
Manager = &AuthManager{
|
|
store: session.NewStore(sessionsFilePath),
|
|
}
|
|
}
|
|
|
|
func (am *AuthManager) Authenticate(usernameOrEmail, plainPassword string) (*users.User, error) {
|
|
var user *users.User
|
|
var err error
|
|
|
|
user, err = users.ByUsername(usernameOrEmail)
|
|
if err != nil {
|
|
user, err = users.ByEmail(usernameOrEmail)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
isValid, err := password.Verify(plainPassword, user.Password)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !isValid {
|
|
return nil, ErrInvalidCredentials
|
|
}
|
|
|
|
return user, nil
|
|
}
|
|
|
|
func (am *AuthManager) CreateSession(user *users.User) *session.Session {
|
|
sess := session.New(user.ID, user.Username, user.Email)
|
|
am.store.Save(sess)
|
|
return sess
|
|
}
|
|
|
|
func (am *AuthManager) GetSession(sessionID string) (*session.Session, bool) {
|
|
return am.store.Get(sessionID)
|
|
}
|
|
|
|
func (am *AuthManager) UpdateSession(sessionID string) bool {
|
|
sess, exists := am.store.Get(sessionID)
|
|
if !exists {
|
|
return false
|
|
}
|
|
|
|
sess.Touch()
|
|
am.store.Save(sess)
|
|
return true
|
|
}
|
|
|
|
func (am *AuthManager) DeleteSession(sessionID string) {
|
|
am.store.Delete(sessionID)
|
|
}
|
|
|
|
func (am *AuthManager) SessionStats() (total, active int) {
|
|
return am.store.Stats()
|
|
}
|
|
|
|
func (am *AuthManager) Close() error {
|
|
return am.store.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
|
|
}
|