New
This commit is contained in:
83
internal/service/security_service.go
Normal file
83
internal/service/security_service.go
Normal file
@@ -0,0 +1,83 @@
|
||||
// Filename: internal/service/security_service.go
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256" // [NEW] Import crypto library for hashing
|
||||
"encoding/hex" // [NEW] Import hex encoding
|
||||
"fmt"
|
||||
"gemini-balancer/internal/models"
|
||||
"gemini-balancer/internal/repository" // [NEW] Import repository
|
||||
"gemini-balancer/internal/settings"
|
||||
"gemini-balancer/internal/store"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const loginAttemptsKey = "security:login_attempts"
|
||||
|
||||
type SecurityService struct {
|
||||
repo repository.AuthTokenRepository
|
||||
store store.Store
|
||||
SettingsManager *settings.SettingsManager
|
||||
logger *logrus.Entry
|
||||
}
|
||||
|
||||
// NewSecurityService signature updated to accept the repository.
|
||||
func NewSecurityService(repo repository.AuthTokenRepository, store store.Store, settingsManager *settings.SettingsManager, logger *logrus.Logger) *SecurityService {
|
||||
return &SecurityService{
|
||||
repo: repo,
|
||||
store: store,
|
||||
SettingsManager: settingsManager,
|
||||
logger: logger.WithField("component", "SecurityService🛡️"),
|
||||
}
|
||||
}
|
||||
|
||||
// AuthenticateToken is now secure and efficient.
|
||||
func (s *SecurityService) AuthenticateToken(tokenValue string) (*models.AuthToken, error) {
|
||||
if tokenValue == "" {
|
||||
return nil, gorm.ErrRecordNotFound
|
||||
}
|
||||
// [REFACTORED]
|
||||
// 1. Hash the incoming plaintext token.
|
||||
hash := sha256.Sum256([]byte(tokenValue))
|
||||
tokenHash := hex.EncodeToString(hash[:])
|
||||
|
||||
// 2. Delegate the lookup to the repository using the hash.
|
||||
return s.repo.GetTokenByHashedValue(tokenHash)
|
||||
}
|
||||
|
||||
// IsIPBanned
|
||||
func (s *SecurityService) IsIPBanned(ctx context.Context, ip string) (bool, error) {
|
||||
banKey := fmt.Sprintf("banned_ip:%s", ip)
|
||||
return s.store.Exists(banKey)
|
||||
}
|
||||
|
||||
// RecordFailedLoginAttempt
|
||||
func (s *SecurityService) RecordFailedLoginAttempt(ctx context.Context, ip string) error {
|
||||
if !s.SettingsManager.IsIPBanEnabled() {
|
||||
return nil
|
||||
}
|
||||
|
||||
count, err := s.store.HIncrBy(loginAttemptsKey, ip, 1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
maxAttempts := s.SettingsManager.GetMaxLoginAttempts()
|
||||
if count >= int64(maxAttempts) {
|
||||
banDuration := s.SettingsManager.GetIPBanDuration()
|
||||
banKey := fmt.Sprintf("banned_ip:%s", ip)
|
||||
|
||||
if err := s.store.Set(banKey, []byte("1"), banDuration); err != nil {
|
||||
return err
|
||||
}
|
||||
s.logger.Warnf("IP BANNED: IP [%s] has been banned for %v due to excessive failed login attempts.", ip, banDuration)
|
||||
|
||||
s.store.HDel(loginAttemptsKey, ip)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user