feat: add licensing and access controls

This commit is contained in:
ShukeBta
2026-05-29 12:47:54 +08:00
parent 2f7ec3ab17
commit 27df93fa3d
61 changed files with 2032 additions and 237 deletions
+17 -7
View File
@@ -20,10 +20,10 @@ import (
// AuthService handles registration, login, and JWT issuance.
type AuthService struct {
cfg *config.Config
log *zap.Logger
repo *repository.Container
tokenSvc *TokenService
cfg *config.Config
log *zap.Logger
repo *repository.Container
tokenSvc *TokenService
permissionSvc *PermissionService
}
@@ -36,9 +36,14 @@ func NewAuthService(cfg *config.Config, log *zap.Logger, repo *repository.Contai
var (
ErrInvalidCredentials = errors.New("invalid username or password")
ErrUsernameTaken = errors.New("username already taken")
ErrUserInactive = errors.New("user account is inactive")
ErrUserInactive = errors.New("user account is inactive")
ErrUserLimitReached = errors.New("user limit reached")
)
// MaxUsers is kept for compatibility with tests and callers; dynamic runtime
// checks use LicensedMaxUsers so official licensed builds can raise the quota.
const MaxUsers = OpenSourceUserLimit
// SeedAdmin makes sure at least one admin user exists. It mirrors the
// MediaStation behaviour: if no admin row is found we create
// `admin / admin123` (overridable through ADMIN_INITIAL_PASSWORD) and warn.
@@ -89,6 +94,11 @@ func (s *AuthService) Register(ctx context.Context, username, password string) (
} else if existing != nil {
return nil, nil, ErrUsernameTaken
}
if n, err := s.repo.User.Count(ctx); err != nil {
return nil, nil, err
} else if n >= LicensedMaxUsers(ctx, s.repo) {
return nil, nil, ErrUserLimitReached
}
hash, err := hashPassword(password)
if err != nil {
return nil, nil, err
@@ -118,8 +128,8 @@ func (s *AuthService) Register(ctx context.Context, username, password string) (
// LoginResponse 登录响应结构。
type LoginResponse struct {
User *model.User `json:"user"`
Tokens *TokenPair `json:"tokens"`
User *model.User `json:"user"`
Tokens *TokenPair `json:"tokens"`
}
// Login validates credentials and returns the user + a fresh JWT token pair.