mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-03-31 08:19:54 +02:00
133 lines
3.0 KiB
Go
133 lines
3.0 KiB
Go
package security
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// Predefined errors for authentication operations.
|
|
var (
|
|
ErrInvalidPassword = errors.New("invalid password")
|
|
)
|
|
|
|
// Session represents an authenticated user session.
|
|
type Session struct {
|
|
Token string
|
|
ExpiresAt time.Time
|
|
}
|
|
|
|
// AuthManager manages password-based authentication and session lifecycle.
|
|
type AuthManager struct {
|
|
password string
|
|
sessionDuration time.Duration
|
|
|
|
mu sync.RWMutex
|
|
sessions map[string]Session
|
|
}
|
|
|
|
// NewAuthManager creates a new AuthManager instance.
|
|
func NewAuthManager(password string, sessionDurationHours int) (*AuthManager, error) {
|
|
if strings.TrimSpace(password) == "" {
|
|
return nil, errors.New("auth password must be configured")
|
|
}
|
|
|
|
if sessionDurationHours <= 0 {
|
|
sessionDurationHours = 12
|
|
}
|
|
|
|
return &AuthManager{
|
|
password: password,
|
|
sessionDuration: time.Duration(sessionDurationHours) * time.Hour,
|
|
sessions: make(map[string]Session),
|
|
}, nil
|
|
}
|
|
|
|
// Authenticate validates the password and creates a new session.
|
|
func (a *AuthManager) Authenticate(password string) (string, time.Time, error) {
|
|
if password != a.password {
|
|
return "", time.Time{}, ErrInvalidPassword
|
|
}
|
|
|
|
token := uuid.NewString()
|
|
expiresAt := time.Now().Add(a.sessionDuration)
|
|
|
|
a.mu.Lock()
|
|
a.sessions[token] = Session{
|
|
Token: token,
|
|
ExpiresAt: expiresAt,
|
|
}
|
|
a.mu.Unlock()
|
|
|
|
return token, expiresAt, nil
|
|
}
|
|
|
|
// ValidateToken checks whether the provided token is still valid.
|
|
func (a *AuthManager) ValidateToken(token string) (Session, bool) {
|
|
if strings.TrimSpace(token) == "" {
|
|
return Session{}, false
|
|
}
|
|
|
|
a.mu.RLock()
|
|
session, ok := a.sessions[token]
|
|
a.mu.RUnlock()
|
|
if !ok {
|
|
return Session{}, false
|
|
}
|
|
|
|
if time.Now().After(session.ExpiresAt) {
|
|
a.mu.Lock()
|
|
delete(a.sessions, token)
|
|
a.mu.Unlock()
|
|
return Session{}, false
|
|
}
|
|
|
|
return session, true
|
|
}
|
|
|
|
// CheckPassword verifies whether the provided password matches the current password.
|
|
func (a *AuthManager) CheckPassword(password string) bool {
|
|
a.mu.RLock()
|
|
defer a.mu.RUnlock()
|
|
return password == a.password
|
|
}
|
|
|
|
// RevokeToken invalidates the specified token.
|
|
func (a *AuthManager) RevokeToken(token string) {
|
|
if strings.TrimSpace(token) == "" {
|
|
return
|
|
}
|
|
|
|
a.mu.Lock()
|
|
delete(a.sessions, token)
|
|
a.mu.Unlock()
|
|
}
|
|
|
|
// SessionDurationHours returns the configured session duration in hours.
|
|
func (a *AuthManager) SessionDurationHours() int {
|
|
return int(a.sessionDuration / time.Hour)
|
|
}
|
|
|
|
// UpdateConfig updates the password and session duration, revoking existing sessions.
|
|
func (a *AuthManager) UpdateConfig(password string, sessionDurationHours int) error {
|
|
password = strings.TrimSpace(password)
|
|
if password == "" {
|
|
return errors.New("auth password must be configured")
|
|
}
|
|
|
|
if sessionDurationHours <= 0 {
|
|
sessionDurationHours = 12
|
|
}
|
|
|
|
a.mu.Lock()
|
|
defer a.mu.Unlock()
|
|
|
|
a.password = password
|
|
a.sessionDuration = time.Duration(sessionDurationHours) * time.Hour
|
|
a.sessions = make(map[string]Session)
|
|
return nil
|
|
}
|