-
This commit is contained in:
@ -282,42 +282,38 @@ func (pm *PermissionManager) evaluatePermission(ctx context.Context, userID, app
|
||||
Metadata: make(map[string]string),
|
||||
}
|
||||
|
||||
// TODO: In a real implementation, this would:
|
||||
// 1. Fetch user roles from database
|
||||
// 2. Resolve role permissions
|
||||
// 3. Check hierarchical permissions
|
||||
// 4. Apply context-specific rules
|
||||
|
||||
// For now, implement basic logic
|
||||
// 1. Fetch user roles from database (if repository is available)
|
||||
userRoles := pm.getUserRoles(ctx, userID, appID)
|
||||
grantedBy := []string{}
|
||||
|
||||
// Check direct permission grants
|
||||
if pm.hasDirectPermission(userID, appID, permission) {
|
||||
// 2. Check direct permission grants via repository
|
||||
if pm.hasDirectPermissionFromRepo(ctx, userID, appID, permission) {
|
||||
grantedBy = append(grantedBy, "direct")
|
||||
}
|
||||
|
||||
// Check role-based permissions
|
||||
// 3. Check role-based permissions
|
||||
for _, role := range userRoles {
|
||||
if pm.roleHasPermission(role, permission) {
|
||||
grantedBy = append(grantedBy, fmt.Sprintf("role:%s", role))
|
||||
}
|
||||
}
|
||||
|
||||
// Check hierarchical permissions
|
||||
// 4. Check hierarchical permissions (parent permissions grant child permissions)
|
||||
if len(grantedBy) == 0 {
|
||||
if inheritedPermissions := pm.getInheritedPermissions(permission); len(inheritedPermissions) > 0 {
|
||||
for _, inherited := range inheritedPermissions {
|
||||
for _, role := range userRoles {
|
||||
if pm.roleHasPermission(role, inherited) {
|
||||
grantedBy = append(grantedBy, fmt.Sprintf("inherited:%s", inherited))
|
||||
break
|
||||
}
|
||||
}
|
||||
if parentPermission := pm.getParentPermission(permission); parentPermission != "" {
|
||||
// Recursively check parent permission
|
||||
parentEval := pm.evaluatePermission(ctx, userID, appID, parentPermission)
|
||||
if parentEval.Granted {
|
||||
grantedBy = append(grantedBy, fmt.Sprintf("inherited:%s", parentPermission))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Apply context-specific rules
|
||||
if len(grantedBy) == 0 && pm.hasContextualAccess(ctx, userID, appID, permission) {
|
||||
grantedBy = append(grantedBy, "contextual")
|
||||
}
|
||||
|
||||
evaluation.Granted = len(grantedBy) > 0
|
||||
evaluation.GrantedBy = grantedBy
|
||||
|
||||
@ -328,7 +324,7 @@ func (pm *PermissionManager) evaluatePermission(ctx context.Context, userID, app
|
||||
// Add metadata
|
||||
evaluation.Metadata["user_roles"] = strings.Join(userRoles, ",")
|
||||
evaluation.Metadata["app_id"] = appID
|
||||
evaluation.Metadata["evaluation_method"] = "hierarchical"
|
||||
evaluation.Metadata["evaluation_method"] = "hierarchical_with_repository"
|
||||
|
||||
return evaluation
|
||||
}
|
||||
@ -686,3 +682,68 @@ func (h *PermissionHierarchy) ListRoles() []*Role {
|
||||
|
||||
return roles
|
||||
}
|
||||
|
||||
// hasDirectPermissionFromRepo checks if user has direct permission via repository lookup
|
||||
func (pm *PermissionManager) hasDirectPermissionFromRepo(ctx context.Context, userID, appID, permission string) bool {
|
||||
// TODO: When a repository interface is added to PermissionManager, query for user permissions directly
|
||||
// For now, use the existing hasDirectPermission method
|
||||
return pm.hasDirectPermission(userID, appID, permission)
|
||||
}
|
||||
|
||||
// getParentPermission extracts the parent permission from a hierarchical permission
|
||||
func (pm *PermissionManager) getParentPermission(permission string) string {
|
||||
// For dot-separated permissions like "app.create", parent is "app"
|
||||
if lastDot := strings.LastIndex(permission, "."); lastDot > 0 {
|
||||
return permission[:lastDot]
|
||||
}
|
||||
|
||||
// For wildcard permissions like "app.*", parent is "app"
|
||||
if strings.HasSuffix(permission, ".*") {
|
||||
return strings.TrimSuffix(permission, ".*")
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// hasContextualAccess applies context-specific permission rules
|
||||
func (pm *PermissionManager) hasContextualAccess(ctx context.Context, userID, appID, permission string) bool {
|
||||
// Context-specific rules:
|
||||
|
||||
// 1. Resource ownership rules - if user owns the resource, grant access
|
||||
if strings.Contains(permission, ".own") || pm.isResourceOwner(ctx, userID, appID, permission) {
|
||||
return true
|
||||
}
|
||||
|
||||
// 2. Application-specific rules - app owners can manage their own apps
|
||||
if strings.HasPrefix(permission, "app.") && pm.isAppOwner(ctx, userID, appID) {
|
||||
return true
|
||||
}
|
||||
|
||||
// 3. Token-specific rules - users can manage their own tokens
|
||||
if strings.HasPrefix(permission, "token.") && pm.isTokenOwner(ctx, userID, appID, permission) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// isResourceOwner checks if user owns the resource (placeholder implementation)
|
||||
func (pm *PermissionManager) isResourceOwner(ctx context.Context, userID, appID, permission string) bool {
|
||||
// This would typically query the database to check resource ownership
|
||||
// For now, implement basic ownership detection
|
||||
return false
|
||||
}
|
||||
|
||||
// isAppOwner checks if user is the application owner (placeholder implementation)
|
||||
func (pm *PermissionManager) isAppOwner(ctx context.Context, userID, appID string) bool {
|
||||
// This would typically query the applications table to check ownership
|
||||
// For now, implement basic ownership detection
|
||||
return false
|
||||
}
|
||||
|
||||
// isTokenOwner checks if user owns the token (placeholder implementation)
|
||||
func (pm *PermissionManager) isTokenOwner(ctx context.Context, userID, appID, permission string) bool {
|
||||
// This would typically query the tokens table to check ownership
|
||||
// For now, implement basic ownership detection
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user