-
This commit is contained in:
@ -269,14 +269,81 @@ func (r *GrantedPermissionRepository) GrantPermissions(ctx context.Context, gran
|
||||
|
||||
// GetGrantedPermissions retrieves all granted permissions for a token
|
||||
func (r *GrantedPermissionRepository) GetGrantedPermissions(ctx context.Context, tokenType domain.TokenType, tokenID uuid.UUID) ([]*domain.GrantedPermission, error) {
|
||||
// TODO: Implement actual granted permissions retrieval
|
||||
return []*domain.GrantedPermission{}, nil
|
||||
query := `
|
||||
SELECT id, token_type, token_id, permission_id, scope, created_at, created_by, revoked
|
||||
FROM granted_permissions
|
||||
WHERE token_type = $1 AND token_id = $2 AND revoked = false
|
||||
ORDER BY created_at ASC
|
||||
`
|
||||
|
||||
db := r.db.GetDB().(*sql.DB)
|
||||
rows, err := db.QueryContext(ctx, query, string(tokenType), tokenID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to query granted permissions: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var permissions []*domain.GrantedPermission
|
||||
for rows.Next() {
|
||||
perm := &domain.GrantedPermission{}
|
||||
var tokenTypeStr string
|
||||
|
||||
err := rows.Scan(
|
||||
&perm.ID,
|
||||
&tokenTypeStr,
|
||||
&perm.TokenID,
|
||||
&perm.PermissionID,
|
||||
&perm.Scope,
|
||||
&perm.CreatedAt,
|
||||
&perm.CreatedBy,
|
||||
&perm.Revoked,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to scan granted permission: %w", err)
|
||||
}
|
||||
|
||||
perm.TokenType = domain.TokenType(tokenTypeStr)
|
||||
permissions = append(permissions, perm)
|
||||
}
|
||||
|
||||
if err = rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("error iterating granted permissions: %w", err)
|
||||
}
|
||||
|
||||
return permissions, nil
|
||||
}
|
||||
|
||||
// GetGrantedPermissionScopes retrieves only the scopes for a token (more efficient)
|
||||
func (r *GrantedPermissionRepository) GetGrantedPermissionScopes(ctx context.Context, tokenType domain.TokenType, tokenID uuid.UUID) ([]string, error) {
|
||||
// TODO: Implement actual scope retrieval
|
||||
return []string{}, nil
|
||||
query := `
|
||||
SELECT scope
|
||||
FROM granted_permissions
|
||||
WHERE token_type = $1 AND token_id = $2 AND revoked = false
|
||||
ORDER BY scope ASC
|
||||
`
|
||||
|
||||
db := r.db.GetDB().(*sql.DB)
|
||||
rows, err := db.QueryContext(ctx, query, string(tokenType), tokenID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to query granted permission scopes: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var scopes []string
|
||||
for rows.Next() {
|
||||
var scope string
|
||||
if err := rows.Scan(&scope); err != nil {
|
||||
return nil, fmt.Errorf("failed to scan permission scope: %w", err)
|
||||
}
|
||||
scopes = append(scopes, scope)
|
||||
}
|
||||
|
||||
if err = rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("error iterating permission scopes: %w", err)
|
||||
}
|
||||
|
||||
return scopes, nil
|
||||
}
|
||||
|
||||
// RevokePermission revokes a specific permission from a token
|
||||
|
||||
@ -208,15 +208,122 @@ func (s *tokenService) GenerateUserToken(ctx context.Context, appID, userID stri
|
||||
func (s *tokenService) VerifyToken(ctx context.Context, req *domain.VerifyRequest) (*domain.VerifyResponse, error) {
|
||||
s.logger.Debug("Verifying token", zap.String("app_id", req.AppID), zap.String("type", string(req.Type)))
|
||||
|
||||
// TODO: Implement actual token verification logic
|
||||
response := &domain.VerifyResponse{
|
||||
Valid: true,
|
||||
UserID: req.UserID,
|
||||
Permissions: []string{"basic"},
|
||||
TokenType: req.Type,
|
||||
// Validate request
|
||||
if req.Token == "" {
|
||||
return &domain.VerifyResponse{
|
||||
Valid: false,
|
||||
Error: "Token is required",
|
||||
}, nil
|
||||
}
|
||||
|
||||
return response, nil
|
||||
// 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 &domain.VerifyResponse{
|
||||
Valid: false,
|
||||
Error: "Invalid application",
|
||||
}, nil
|
||||
}
|
||||
|
||||
switch req.Type {
|
||||
case domain.TokenTypeStatic:
|
||||
return s.verifyStaticToken(ctx, req, app)
|
||||
case domain.TokenTypeUser:
|
||||
return s.verifyUserToken(ctx, req, app)
|
||||
default:
|
||||
return &domain.VerifyResponse{
|
||||
Valid: false,
|
||||
Error: "Invalid token type",
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// verifyStaticToken verifies a static token
|
||||
func (s *tokenService) verifyStaticToken(ctx context.Context, req *domain.VerifyRequest, app *domain.Application) (*domain.VerifyResponse, error) {
|
||||
s.logger.Debug("Verifying static token", zap.String("app_id", req.AppID))
|
||||
|
||||
// Check token format
|
||||
if !crypto.IsValidTokenFormat(req.Token) {
|
||||
s.logger.Warn("Invalid token format", zap.String("app_id", req.AppID))
|
||||
return &domain.VerifyResponse{
|
||||
Valid: false,
|
||||
Error: "Invalid token format",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Try to find token by testing against all stored hashes for this app
|
||||
tokens, err := s.tokenRepo.GetByAppID(ctx, req.AppID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get tokens for app", zap.Error(err), zap.String("app_id", req.AppID))
|
||||
return &domain.VerifyResponse{
|
||||
Valid: false,
|
||||
Error: "Token verification failed",
|
||||
}, nil
|
||||
}
|
||||
|
||||
var matchedToken *domain.StaticToken
|
||||
for _, token := range tokens {
|
||||
if s.tokenGen.VerifyToken(req.Token, token.KeyHash) {
|
||||
matchedToken = token
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if matchedToken == nil {
|
||||
s.logger.Warn("Token not found or invalid", zap.String("app_id", req.AppID))
|
||||
return &domain.VerifyResponse{
|
||||
Valid: false,
|
||||
Error: "Invalid token",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Get granted permissions for this token
|
||||
permissions, err := s.grantRepo.GetGrantedPermissionScopes(ctx, domain.TokenTypeStatic, matchedToken.ID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get token permissions", zap.Error(err), zap.String("token_id", matchedToken.ID.String()))
|
||||
return &domain.VerifyResponse{
|
||||
Valid: false,
|
||||
Error: "Failed to retrieve permissions",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Check specific permissions if requested
|
||||
var permissionResults map[string]bool
|
||||
if len(req.Permissions) > 0 {
|
||||
permissionResults, err = s.grantRepo.HasAnyPermission(ctx, domain.TokenTypeStatic, matchedToken.ID, req.Permissions)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to check specific permissions", zap.Error(err))
|
||||
return &domain.VerifyResponse{
|
||||
Valid: false,
|
||||
Error: "Failed to check permissions",
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
s.logger.Info("Static token verified successfully",
|
||||
zap.String("token_id", matchedToken.ID.String()),
|
||||
zap.String("app_id", req.AppID),
|
||||
zap.Strings("permissions", permissions))
|
||||
|
||||
return &domain.VerifyResponse{
|
||||
Valid: true,
|
||||
Permissions: permissions,
|
||||
PermissionResults: permissionResults,
|
||||
TokenType: domain.TokenTypeStatic,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// verifyUserToken verifies a user token (JWT-based)
|
||||
func (s *tokenService) verifyUserToken(ctx context.Context, req *domain.VerifyRequest, app *domain.Application) (*domain.VerifyResponse, error) {
|
||||
s.logger.Debug("Verifying user token", zap.String("app_id", req.AppID))
|
||||
|
||||
// TODO: Implement JWT token verification
|
||||
// For now, return an error since user tokens are not fully implemented
|
||||
return &domain.VerifyResponse{
|
||||
Valid: false,
|
||||
Error: "User token verification not yet implemented",
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RenewUserToken renews a user token
|
||||
|
||||
@ -420,12 +420,15 @@ func (suite *IntegrationTestSuite) TestStaticTokenWorkflow() {
|
||||
|
||||
assert.True(t, verifyResp.Valid)
|
||||
assert.Equal(t, domain.TokenTypeStatic, verifyResp.TokenType)
|
||||
// Note: The current service implementation returns ["basic"] as a placeholder
|
||||
assert.Contains(t, verifyResp.Permissions, "basic")
|
||||
// Verify that we get the actual permissions that were granted to the token
|
||||
assert.Contains(t, verifyResp.Permissions, "repo.read")
|
||||
assert.Contains(t, verifyResp.Permissions, "repo.write")
|
||||
|
||||
if verifyResp.PermissionResults != nil {
|
||||
// Check that we get some permission results
|
||||
// Check that we get permission results for the requested permissions
|
||||
assert.NotEmpty(t, verifyResp.PermissionResults)
|
||||
// The token should have the "repo.read" permission we requested
|
||||
assert.True(t, verifyResp.PermissionResults["repo.read"])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user