-
This commit is contained in:
@ -8,17 +8,19 @@ import (
|
||||
"github.com/google/uuid"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/kms/api-key-service/internal/crypto"
|
||||
"github.com/kms/api-key-service/internal/domain"
|
||||
"github.com/kms/api-key-service/internal/repository"
|
||||
)
|
||||
|
||||
// tokenService implements the TokenService interface
|
||||
type tokenService struct {
|
||||
tokenRepo repository.StaticTokenRepository
|
||||
appRepo repository.ApplicationRepository
|
||||
permRepo repository.PermissionRepository
|
||||
grantRepo repository.GrantedPermissionRepository
|
||||
logger *zap.Logger
|
||||
tokenRepo repository.StaticTokenRepository
|
||||
appRepo repository.ApplicationRepository
|
||||
permRepo repository.PermissionRepository
|
||||
grantRepo repository.GrantedPermissionRepository
|
||||
tokenGen *crypto.TokenGenerator
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// NewTokenService creates a new token service
|
||||
@ -27,6 +29,7 @@ func NewTokenService(
|
||||
appRepo repository.ApplicationRepository,
|
||||
permRepo repository.PermissionRepository,
|
||||
grantRepo repository.GrantedPermissionRepository,
|
||||
hmacKey string,
|
||||
logger *zap.Logger,
|
||||
) TokenService {
|
||||
return &tokenService{
|
||||
@ -34,6 +37,7 @@ func NewTokenService(
|
||||
appRepo: appRepo,
|
||||
permRepo: permRepo,
|
||||
grantRepo: grantRepo,
|
||||
tokenGen: crypto.NewTokenGenerator(hmacKey),
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
@ -42,10 +46,33 @@ func NewTokenService(
|
||||
func (s *tokenService) CreateStaticToken(ctx context.Context, req *domain.CreateStaticTokenRequest, userID string) (*domain.CreateStaticTokenResponse, error) {
|
||||
s.logger.Info("Creating static token", zap.String("app_id", req.AppID), zap.String("user_id", userID))
|
||||
|
||||
// TODO: Validate permissions
|
||||
// TODO: Validate application exists
|
||||
// TODO: Generate secure token
|
||||
// TODO: Grant permissions
|
||||
// Validate application exists
|
||||
app, err := s.appRepo.GetByID(ctx, req.AppID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get application", zap.Error(err), zap.String("app_id", req.AppID))
|
||||
return nil, fmt.Errorf("application not found: %w", err)
|
||||
}
|
||||
|
||||
// Validate permissions exist
|
||||
validPermissions, err := s.permRepo.ValidatePermissionScopes(ctx, req.Permissions)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to validate permissions", zap.Error(err))
|
||||
return nil, fmt.Errorf("failed to validate permissions: %w", err)
|
||||
}
|
||||
|
||||
if len(validPermissions) != len(req.Permissions) {
|
||||
s.logger.Warn("Some permissions are invalid",
|
||||
zap.Strings("requested", req.Permissions),
|
||||
zap.Strings("valid", validPermissions))
|
||||
return nil, fmt.Errorf("some requested permissions are invalid")
|
||||
}
|
||||
|
||||
// Generate secure token
|
||||
tokenInfo, err := s.tokenGen.GenerateTokenWithInfo()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to generate secure token", zap.Error(err))
|
||||
return nil, fmt.Errorf("failed to generate token: %w", err)
|
||||
}
|
||||
|
||||
tokenID := uuid.New()
|
||||
now := time.Now()
|
||||
@ -54,32 +81,62 @@ func (s *tokenService) CreateStaticToken(ctx context.Context, req *domain.Create
|
||||
token := &domain.StaticToken{
|
||||
ID: tokenID,
|
||||
AppID: req.AppID,
|
||||
Owner: domain.Owner{
|
||||
Type: domain.OwnerTypeIndividual,
|
||||
Name: userID,
|
||||
Owner: userID,
|
||||
},
|
||||
KeyHash: "placeholder-hash-" + tokenID.String(),
|
||||
Type: "hmac",
|
||||
Owner: req.Owner,
|
||||
KeyHash: tokenInfo.Hash,
|
||||
Type: "hmac",
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
// Save the token to the database
|
||||
err := s.tokenRepo.Create(ctx, token)
|
||||
err = s.tokenRepo.Create(ctx, token)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to create token in database", zap.Error(err), zap.String("token_id", tokenID.String()))
|
||||
return nil, fmt.Errorf("failed to create token: %w", err)
|
||||
}
|
||||
|
||||
// Grant permissions to the token
|
||||
var grants []*domain.GrantedPermission
|
||||
for _, permScope := range validPermissions {
|
||||
// Get permission by scope to get the ID
|
||||
perm, err := s.permRepo.GetAvailablePermissionByScope(ctx, permScope)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get permission by scope", zap.Error(err), zap.String("scope", permScope))
|
||||
continue
|
||||
}
|
||||
|
||||
grant := &domain.GrantedPermission{
|
||||
ID: uuid.New(),
|
||||
TokenType: domain.TokenTypeStatic,
|
||||
TokenID: tokenID,
|
||||
PermissionID: perm.ID,
|
||||
Scope: permScope,
|
||||
CreatedBy: userID,
|
||||
}
|
||||
grants = append(grants, grant)
|
||||
}
|
||||
|
||||
if len(grants) > 0 {
|
||||
err = s.grantRepo.GrantPermissions(ctx, grants)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to grant permissions", zap.Error(err))
|
||||
// Clean up the token if permission granting fails
|
||||
s.tokenRepo.Delete(ctx, tokenID)
|
||||
return nil, fmt.Errorf("failed to grant permissions: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
response := &domain.CreateStaticTokenResponse{
|
||||
ID: tokenID,
|
||||
Token: "static-token-placeholder-" + tokenID.String(),
|
||||
Permissions: req.Permissions,
|
||||
Token: tokenInfo.Token, // Return the actual token only once
|
||||
Permissions: validPermissions,
|
||||
CreatedAt: now,
|
||||
}
|
||||
|
||||
s.logger.Info("Static token created successfully", zap.String("token_id", tokenID.String()))
|
||||
s.logger.Info("Static token created successfully",
|
||||
zap.String("token_id", tokenID.String()),
|
||||
zap.String("app_id", app.AppID),
|
||||
zap.Strings("permissions", validPermissions))
|
||||
return response, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user