- Added detailed logging for ACL enforcement failures in the OAuth guard, providing clearer insights into permission issues. - Updated error messages in the ACL enforcement logic to include contextual information such as client and user IDs, enhancing debugging capabilities. - Introduced new constraints (CreatorOnly, EditorOnly) in the data access model, allowing for more granular control over data visibility based on user roles. - Enhanced scope definitions to support additional constraints, improving flexibility in access control configurations. - Updated documentation to reflect changes in data constraints and their usage in API handlers.
816 lines
21 KiB
Markdown
816 lines
21 KiB
Markdown
# ACL Scopes Configuration Guide
|
|
|
|
## Overview
|
|
|
|
This guide explains how to configure and manage ACL (Access Control List) scopes for your OAuth-protected APIs. Scopes define what resources and actions are accessible to different users, teams, and clients.
|
|
|
|
---
|
|
|
|
## Directory Structure
|
|
|
|
All scope configurations should be placed in the `openapi/scopes/` directory with the following structure:
|
|
|
|
```
|
|
openapi/scopes/
|
|
├── scopes.yml # Global configuration and default policies
|
|
├── alias.yml # Scope aliases for simplified permission management
|
|
└── <resource>/ # Resource-specific scope definitions
|
|
├── collections.yml # Collections resource scopes
|
|
├── documents.yml # Documents resource scopes
|
|
└── ...
|
|
```
|
|
|
|
**Organization Guidelines**:
|
|
|
|
- Group related scopes by resource (e.g., `kb/`, `user/`, `job/`, `file/`)
|
|
- Use descriptive filenames matching the resource name
|
|
- Keep each file focused on a single resource or logical grouping
|
|
|
|
---
|
|
|
|
## Configuration Files
|
|
|
|
### 1. Global Configuration (`scopes.yml`)
|
|
|
|
The `scopes.yml` file defines global ACL behavior, public endpoints, and default rules.
|
|
|
|
#### Structure
|
|
|
|
```yaml
|
|
# Default action for unmatched API endpoints
|
|
default: deny # Options: "deny" or "allow"
|
|
|
|
# Public endpoints (accessible without authentication)
|
|
public:
|
|
- GET /user/entry
|
|
- GET /user/entry/captcha
|
|
- POST /user/entry/verify
|
|
- GET /user/teams/invitations/:invitation_id
|
|
|
|
# Default endpoint rules (can be overridden by specific scopes)
|
|
endpoints:
|
|
# Read operations allowed for authenticated users
|
|
- GET /kb/* allow
|
|
- GET /kb/collections allow
|
|
|
|
# Write operations require specific scopes
|
|
- POST /kb/* deny
|
|
- PUT /kb/* deny
|
|
- DELETE /kb/* deny
|
|
```
|
|
|
|
#### Fields
|
|
|
|
| Field | Type | Required | Description |
|
|
| ----------- | ------ | -------- | ------------------------------------------------------------- |
|
|
| `default` | string | Yes | Default policy for unmatched endpoints: `"allow"` or `"deny"` |
|
|
| `public` | array | No | List of public endpoints (no authentication required) |
|
|
| `endpoints` | array | No | Default endpoint rules (see Endpoint Rules below) |
|
|
|
|
#### Endpoint Rules Format
|
|
|
|
Each endpoint rule can be specified as:
|
|
|
|
**Simple String Format** (recommended):
|
|
|
|
```yaml
|
|
- GET /api/users allow
|
|
- POST /api/users deny
|
|
- DELETE /api/users/* deny
|
|
```
|
|
|
|
**Struct Format**:
|
|
|
|
```yaml
|
|
- method: GET
|
|
path: /api/users
|
|
action: allow
|
|
```
|
|
|
|
**Path Patterns**:
|
|
|
|
- **Exact path**: `/kb/collections` - matches exactly
|
|
- **Parameter path**: `/kb/collections/:collectionID` - matches with parameters
|
|
- **Wildcard path**: `/kb/*` - matches all paths under `/kb/`
|
|
|
|
**Best Practices**:
|
|
|
|
- Set `default: deny` for security (deny by default, allow explicitly)
|
|
- List public endpoints explicitly (login, registration, health checks)
|
|
- Use wildcards for broad policies, then override with specific scopes
|
|
- Order matters: more specific rules should come after general ones
|
|
|
|
---
|
|
|
|
### 2. Scope Definitions (Resource Files)
|
|
|
|
Scope definition files define specific permissions for resources. Each file contains multiple scope definitions.
|
|
|
|
#### Structure
|
|
|
|
```yaml
|
|
# Scope naming convention: resource:action:level
|
|
collections:read:all:
|
|
description: "Read knowledge base for all users"
|
|
endpoints:
|
|
- GET /kb/collections
|
|
- GET /kb/collections/:collectionID
|
|
- GET /kb/collections/:collectionID/exists
|
|
|
|
collections:read:own:
|
|
owner: true # Only show collections owned by current user
|
|
creator: true # Only show collections created by current user
|
|
description: "Read knowledge base for own collections"
|
|
endpoints:
|
|
- GET /kb/collections/own
|
|
- GET /kb/collections/own/:collectionID
|
|
- GET /kb/collections/own/:collectionID/exists
|
|
|
|
collections:write:own:
|
|
owner: true
|
|
editor: true # Only allow editing by last editor
|
|
description: "Write knowledge base for own collections"
|
|
endpoints:
|
|
- POST /kb/collections/own
|
|
- PUT /kb/collections/own/:collectionID
|
|
- DELETE /kb/collections/own/:collectionID
|
|
|
|
collections:read:team:
|
|
team: true # Only show team collections
|
|
description: "Read knowledge base for team collections"
|
|
endpoints:
|
|
- GET /kb/collections/team
|
|
- GET /kb/collections/team/:collectionID
|
|
|
|
collections:read:department:
|
|
extra: # Custom constraints
|
|
department_only: true
|
|
region: "us-west"
|
|
description: "Read collections for department in specific region"
|
|
endpoints:
|
|
- GET /kb/collections/department
|
|
- GET /kb/collections/department/:collectionID
|
|
```
|
|
|
|
#### Scope Definition Fields
|
|
|
|
| Field | Type | Required | Default | Description |
|
|
| ------------- | ------ | -------- | ------- | ---------------------------------------------------------------------------------- |
|
|
| `description` | string | No | "" | Human-readable description of the scope |
|
|
| `owner` | bool | No | false | If `true`, data access is restricted to owner only (sets `OwnerOnly` constraint) |
|
|
| `creator` | bool | No | false | If `true`, data access is restricted to creator only (sets `CreatorOnly` constraint) |
|
|
| `editor` | bool | No | false | If `true`, data access is restricted to editor only (sets `EditorOnly` constraint) |
|
|
| `team` | bool | No | false | If `true`, data access is restricted to team only (sets `TeamOnly` constraint) |
|
|
| `extra` | map | No | {} | User-defined custom constraints (key-value pairs) |
|
|
| `endpoints` | array | Yes | - | List of API endpoints this scope grants access to |
|
|
|
|
#### Endpoint Format
|
|
|
|
Each endpoint in the `endpoints` array should be formatted as:
|
|
|
|
```
|
|
METHOD /path
|
|
```
|
|
|
|
**Examples**:
|
|
|
|
```yaml
|
|
endpoints:
|
|
- GET /kb/collections
|
|
- GET /kb/collections/:collectionID
|
|
- POST /kb/collections/own
|
|
- PUT /kb/collections/:collectionID
|
|
- DELETE /kb/collections/own/:collectionID
|
|
```
|
|
|
|
**Supported HTTP Methods**:
|
|
|
|
- `GET` - Read operations
|
|
- `POST` - Create operations
|
|
- `PUT` - Update operations
|
|
- `DELETE` - Delete operations
|
|
- `PATCH` - Partial update operations
|
|
|
|
**Path Parameters**:
|
|
|
|
- Use `:paramName` syntax for path parameters (e.g., `:collectionID`, `:userID`)
|
|
- Parameter names should be descriptive and consistent
|
|
|
|
---
|
|
|
|
### 3. Scope Aliases (`alias.yml`)
|
|
|
|
Aliases allow you to group multiple scopes under a single name for simplified permission management.
|
|
|
|
#### Structure
|
|
|
|
```yaml
|
|
# Alias naming: category:level
|
|
user:auth:
|
|
- entry:access:public
|
|
- entry:register:authenticated
|
|
- entry:logout:own
|
|
|
|
kb:read:
|
|
- collections:read:all
|
|
- documents:read:all
|
|
- search:read:all
|
|
- hits:read:all
|
|
|
|
kb:own:
|
|
- collections:read:own
|
|
- collections:write:own
|
|
- collections:delete:own
|
|
- documents:read:own
|
|
- documents:write:own
|
|
- documents:delete:own
|
|
|
|
kb:admin:
|
|
- collections:read:all
|
|
- collections:write:all
|
|
- collections:delete:all
|
|
- documents:read:all
|
|
- documents:write:all
|
|
- documents:delete:all
|
|
- search:read:all
|
|
- graphs:read:all
|
|
|
|
# System root permission - absolute highest privilege
|
|
system:root:
|
|
- "*:*:*"
|
|
```
|
|
|
|
#### Alias Usage
|
|
|
|
**In Role Configuration**:
|
|
|
|
```go
|
|
// Assign aliases to roles instead of individual scopes
|
|
role := &Role{
|
|
ID: "kb-viewer",
|
|
AllowedScopes: []string{
|
|
"kb:read", // Expands to all KB read scopes
|
|
"user:auth", // Expands to all auth scopes
|
|
},
|
|
}
|
|
```
|
|
|
|
**Benefits**:
|
|
|
|
- **Simplified Management**: Change multiple scopes by updating one alias
|
|
- **Consistency**: Ensure users get consistent permission sets
|
|
- **Readability**: Clear, semantic permission names
|
|
- **Maintenance**: Easier to add/remove scopes from permission groups
|
|
|
|
**Best Practices**:
|
|
|
|
- Use hierarchical naming: `resource:level` (e.g., `kb:read`, `kb:own`, `kb:admin`)
|
|
- Create aliases for common permission patterns
|
|
- Document what each alias includes
|
|
- Use wildcards (`*:*:*`) sparingly and only for system-level access
|
|
|
|
---
|
|
|
|
## Scope Naming Convention
|
|
|
|
Follow a consistent three-part naming convention for scopes:
|
|
|
|
```
|
|
resource:action:level
|
|
```
|
|
|
|
### Components
|
|
|
|
1. **Resource** (noun): The resource being accessed
|
|
|
|
- Examples: `collections`, `documents`, `profile`, `jobs`, `files`
|
|
- Should be plural for collections, singular for single resources
|
|
|
|
2. **Action** (verb): The operation being performed
|
|
|
|
- `read` - View/retrieve data (GET)
|
|
- `write` - Create/update data (POST, PUT, PATCH)
|
|
- `delete` - Remove data (DELETE)
|
|
- `control` - Special operations (start, stop, pause)
|
|
- `access` - Generic access without CRUD semantics
|
|
|
|
3. **Level** (scope): The access level or data visibility
|
|
- `all` - Full access to all resources
|
|
- `own` - Access only to user's own resources
|
|
- `team` - Access to team resources
|
|
- `public` - Public/unauthenticated access
|
|
- `authenticated` - Basic authenticated access
|
|
|
|
### Examples
|
|
|
|
| Scope | Description |
|
|
| ------------------------ | ----------------------------- |
|
|
| `collections:read:all` | Read all collections |
|
|
| `collections:read:own` | Read only own collections |
|
|
| `collections:read:team` | Read team collections |
|
|
| `collections:write:own` | Create/update own collections |
|
|
| `collections:delete:own` | Delete own collections |
|
|
| `documents:write:all` | Create/update any document |
|
|
| `documents:delete:team` | Delete team documents |
|
|
| `profile:read:own` | Read own profile |
|
|
| `jobs:control:own` | Control (start/stop) own jobs |
|
|
| `search:read:all` | Search across all resources |
|
|
|
|
---
|
|
|
|
## Data Access Constraints
|
|
|
|
Data access constraints control how API handlers should filter data based on ownership.
|
|
|
|
### Owner-Only Access (`owner: true`)
|
|
|
|
When `owner: true` is set, the scope grants access only to resources owned by the current user.
|
|
|
|
```yaml
|
|
collections:read:own:
|
|
owner: true
|
|
description: "Read knowledge base for own collections"
|
|
endpoints:
|
|
- GET /kb/collections/own
|
|
- GET /kb/collections/own/:collectionID
|
|
```
|
|
|
|
**API Implementation**:
|
|
|
|
```go
|
|
func GetCollections(c *gin.Context) {
|
|
authInfo := authorized.GetInfo(c)
|
|
|
|
query := db.Query("SELECT * FROM collections")
|
|
|
|
// Apply owner constraint
|
|
if authInfo.Constraints.OwnerOnly {
|
|
query = query.Where("user_id = ?", authInfo.UserID)
|
|
}
|
|
|
|
collections, _ := query.Get()
|
|
c.JSON(200, collections)
|
|
}
|
|
```
|
|
|
|
### Team-Only Access (`team: true`)
|
|
|
|
When `team: true` is set, the scope grants access only to resources owned by the current team.
|
|
|
|
```yaml
|
|
collections:read:team:
|
|
team: true
|
|
description: "Read knowledge base for team collections"
|
|
endpoints:
|
|
- GET /kb/collections/team
|
|
- GET /kb/collections/team/:collectionID
|
|
```
|
|
|
|
**API Implementation**:
|
|
|
|
```go
|
|
func GetCollections(c *gin.Context) {
|
|
authInfo := authorized.GetInfo(c)
|
|
|
|
query := db.Query("SELECT * FROM collections")
|
|
|
|
// Apply team constraint
|
|
if authInfo.Constraints.TeamOnly {
|
|
query = query.Where("team_id = ?", authInfo.TeamID)
|
|
}
|
|
|
|
collections, _ := query.Get()
|
|
c.JSON(200, collections)
|
|
}
|
|
```
|
|
|
|
### Combined Constraints
|
|
|
|
Both constraints can be applied:
|
|
|
|
```yaml
|
|
documents:read:own:
|
|
owner: true
|
|
team: true # Can be used together
|
|
description: "Read own documents within team context"
|
|
endpoints:
|
|
- GET /kb/documents/own
|
|
```
|
|
|
|
**API Implementation**:
|
|
|
|
```go
|
|
func GetDocuments(c *gin.Context) {
|
|
authInfo := authorized.GetInfo(c)
|
|
|
|
query := db.Query("SELECT * FROM documents")
|
|
|
|
// Apply constraints (OwnerOnly is more restrictive)
|
|
if authInfo.Constraints.OwnerOnly {
|
|
query = query.Where("user_id = ?", authInfo.UserID)
|
|
} else if authInfo.Constraints.TeamOnly {
|
|
query = query.Where("team_id = ?", authInfo.TeamID)
|
|
}
|
|
|
|
documents, _ := query.Get()
|
|
c.JSON(200, documents)
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Complete Example
|
|
|
|
Let's create a complete scope configuration for a blog system.
|
|
|
|
### Directory Structure
|
|
|
|
```
|
|
openapi/scopes/
|
|
├── scopes.yml
|
|
├── alias.yml
|
|
└── blog/
|
|
├── posts.yml
|
|
├── comments.yml
|
|
└── categories.yml
|
|
```
|
|
|
|
### `scopes.yml`
|
|
|
|
```yaml
|
|
default: deny
|
|
|
|
public:
|
|
- GET /blog/posts
|
|
- GET /blog/posts/:postID
|
|
- GET /blog/categories
|
|
|
|
endpoints:
|
|
# Read operations allowed for authenticated users
|
|
- GET /blog/* allow
|
|
|
|
# Write operations require specific scopes
|
|
- POST /blog/* deny
|
|
- PUT /blog/* deny
|
|
- DELETE /blog/* deny
|
|
```
|
|
|
|
### `blog/posts.yml`
|
|
|
|
```yaml
|
|
posts:read:all:
|
|
description: "Read all blog posts"
|
|
endpoints:
|
|
- GET /blog/posts
|
|
- GET /blog/posts/:postID
|
|
|
|
posts:read:own:
|
|
owner: true
|
|
description: "Read own blog posts"
|
|
endpoints:
|
|
- GET /blog/posts/own
|
|
- GET /blog/posts/own/:postID
|
|
|
|
posts:write:own:
|
|
owner: true
|
|
description: "Create and update own blog posts"
|
|
endpoints:
|
|
- POST /blog/posts
|
|
- PUT /blog/posts/:postID
|
|
- PATCH /blog/posts/:postID
|
|
|
|
posts:delete:own:
|
|
owner: true
|
|
description: "Delete own blog posts"
|
|
endpoints:
|
|
- DELETE /blog/posts/:postID
|
|
|
|
posts:write:all:
|
|
description: "Create and update any blog post (admin)"
|
|
endpoints:
|
|
- POST /blog/posts/admin
|
|
- PUT /blog/posts/admin/:postID
|
|
|
|
posts:delete:all:
|
|
description: "Delete any blog post (admin)"
|
|
endpoints:
|
|
- DELETE /blog/posts/admin/:postID
|
|
```
|
|
|
|
### `blog/comments.yml`
|
|
|
|
```yaml
|
|
comments:read:all:
|
|
description: "Read all comments"
|
|
endpoints:
|
|
- GET /blog/posts/:postID/comments
|
|
- GET /blog/comments/:commentID
|
|
|
|
comments:write:own:
|
|
owner: true
|
|
description: "Write own comments"
|
|
endpoints:
|
|
- POST /blog/posts/:postID/comments
|
|
- PUT /blog/comments/:commentID
|
|
|
|
comments:delete:own:
|
|
owner: true
|
|
description: "Delete own comments"
|
|
endpoints:
|
|
- DELETE /blog/comments/:commentID
|
|
|
|
comments:delete:all:
|
|
description: "Delete any comment (moderator)"
|
|
endpoints:
|
|
- DELETE /blog/comments/admin/:commentID
|
|
```
|
|
|
|
### `alias.yml`
|
|
|
|
```yaml
|
|
# Blog reader - can read all posts and comments
|
|
blog:reader:
|
|
- posts:read:all
|
|
- comments:read:all
|
|
|
|
# Blog author - can manage own posts and comments
|
|
blog:author:
|
|
- posts:read:all
|
|
- posts:write:own
|
|
- posts:delete:own
|
|
- comments:read:all
|
|
- comments:write:own
|
|
- comments:delete:own
|
|
|
|
# Blog moderator - can manage all comments
|
|
blog:moderator:
|
|
- posts:read:all
|
|
- comments:read:all
|
|
- comments:delete:all
|
|
|
|
# Blog admin - full access to all blog features
|
|
blog:admin:
|
|
- posts:read:all
|
|
- posts:write:all
|
|
- posts:delete:all
|
|
- comments:read:all
|
|
- comments:write:own
|
|
- comments:delete:all
|
|
```
|
|
|
|
---
|
|
|
|
## Wildcard Scopes
|
|
|
|
Wildcard scopes allow flexible permission matching using `*` as a placeholder.
|
|
|
|
### Syntax
|
|
|
|
```yaml
|
|
system:root:
|
|
- "*:*:*" # Matches everything
|
|
|
|
blog:admin:
|
|
- "posts:*:*" # Matches all post operations at all levels
|
|
- "comments:*:*" # Matches all comment operations at all levels
|
|
|
|
kb:read:
|
|
- "collections:read:*" # Matches collections:read:all, collections:read:own, etc.
|
|
- "documents:read:*" # Matches documents:read:all, documents:read:own, etc.
|
|
```
|
|
|
|
### Matching Rules
|
|
|
|
1. **Full wildcard** (`*:*:*`): Matches any scope
|
|
2. **Resource wildcard** (`posts:*:*`): Matches any action and level for the resource
|
|
3. **Action wildcard** (`posts:read:*`): Matches any level for the resource and action
|
|
4. **No partial wildcards**: `post*:read:all` is NOT supported
|
|
|
|
### Use Cases
|
|
|
|
- **System root access**: `*:*:*` for system administrators
|
|
- **Resource administrators**: `resource:*:*` for resource-level admins
|
|
- **Grouped permissions**: `resource:action:*` for action-level permissions
|
|
|
|
### Security Considerations
|
|
|
|
- Use wildcards sparingly
|
|
- Prefer explicit scope lists for most roles
|
|
- Reserve `*:*:*` for system-level accounts only
|
|
- Document wildcard usage clearly
|
|
- Consider restricted scopes to block specific actions even with wildcards
|
|
|
|
---
|
|
|
|
## Best Practices
|
|
|
|
### 1. Scope Design
|
|
|
|
✅ **DO**:
|
|
|
|
- Use consistent naming conventions
|
|
- Group related scopes in the same file
|
|
- Provide clear descriptions for each scope
|
|
- Design scopes around resources and actions, not UI features
|
|
- Keep scopes granular but not too fine-grained
|
|
|
|
❌ **DON'T**:
|
|
|
|
- Mix different resources in one scope file
|
|
- Create scopes for every single endpoint
|
|
- Use vague or inconsistent naming
|
|
- Duplicate endpoint definitions across scopes
|
|
|
|
### 2. Permission Levels
|
|
|
|
Create a clear hierarchy of permission levels:
|
|
|
|
1. **Public** (`public`): No authentication required
|
|
2. **Authenticated** (`authenticated`): Basic logged-in access
|
|
3. **Owner** (`own`): User's own resources
|
|
4. **Team** (`team`): Team's resources
|
|
5. **All** (`all`): All resources (admin level)
|
|
|
|
### 3. Aliases
|
|
|
|
✅ **DO**:
|
|
|
|
- Create aliases for common user roles (viewer, editor, admin)
|
|
- Use aliases to group related scopes
|
|
- Document what each alias grants
|
|
- Keep alias names intuitive
|
|
|
|
❌ **DON'T**:
|
|
|
|
- Create single-scope aliases (use the scope directly)
|
|
- Nest aliases (aliases should reference scopes, not other aliases)
|
|
- Use ambiguous alias names
|
|
|
|
### 4. Data Constraints
|
|
|
|
✅ **DO**:
|
|
|
|
- Set `owner: true` for personal resource scopes
|
|
- Set `team: true` for team resource scopes
|
|
- Implement constraint checks in ALL relevant API handlers
|
|
- Return appropriate errors when constraints are violated
|
|
|
|
❌ **DON'T**:
|
|
|
|
- Rely solely on URL paths (`/own`, `/team`) for access control
|
|
- Skip constraint validation in database queries
|
|
- Assume constraints are enforced automatically
|
|
|
|
### 5. Endpoint Definitions
|
|
|
|
✅ **DO**:
|
|
|
|
- List all related endpoints for a scope
|
|
- Use consistent parameter naming (`:id`, `:userID`, `:collectionID`)
|
|
- Include all HTTP methods the scope covers
|
|
- Group similar endpoints together
|
|
|
|
❌ **DON'T**:
|
|
|
|
- Define the same endpoint in multiple scopes (unless intentional)
|
|
- Use inconsistent path formats
|
|
- Forget to include related endpoints
|
|
|
|
### 6. Testing
|
|
|
|
- Test each scope definition with real requests
|
|
- Verify data constraints are enforced correctly
|
|
- Test wildcard matching behavior
|
|
- Ensure public endpoints are accessible without auth
|
|
- Validate that denied endpoints return proper errors
|
|
|
|
### 7. Documentation
|
|
|
|
- Comment complex scope definitions
|
|
- Document the purpose of each alias
|
|
- Maintain a scope reference for developers
|
|
- Update documentation when scopes change
|
|
- Provide examples of scope usage in roles
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
**Issue**: Endpoint not accessible even with correct scope
|
|
|
|
**Solution**:
|
|
|
|
- Check if endpoint is in `scopes.yml` default deny list
|
|
- Verify scope name matches exactly (case-sensitive)
|
|
- Ensure endpoint path matches (check for typos, extra slashes)
|
|
- Verify HTTP method matches
|
|
|
|
---
|
|
|
|
**Issue**: Data constraint not working
|
|
|
|
**Solution**:
|
|
|
|
- Confirm `owner: true` or `team: true` is set in scope definition
|
|
- Check if API handler reads `authInfo.Constraints`
|
|
- Verify database query applies constraint filters
|
|
- Ensure `authInfo.UserID` or `authInfo.TeamID` is populated
|
|
|
|
---
|
|
|
|
**Issue**: Wildcard scope not matching
|
|
|
|
**Solution**:
|
|
|
|
- Verify wildcard syntax (`*` in correct position)
|
|
- Check scope name format (must be `part1:part2:part3`)
|
|
- Ensure no typos in scope name parts
|
|
- Remember: wildcards only work with colon-separated scopes
|
|
|
|
---
|
|
|
|
**Issue**: Changes not taking effect
|
|
|
|
**Solution**:
|
|
|
|
- Restart the application to reload scope configurations
|
|
- Clear role cache: `role.RoleManager.ClearCache()`
|
|
- Verify YAML syntax is correct (use YAML validator)
|
|
- Check file is in correct directory
|
|
|
|
---
|
|
|
|
## Reference
|
|
|
|
### Related Files
|
|
|
|
- **[types.go](./types.go)**: Scope configuration structures
|
|
- **[scope.go](./scope.go)**: Scope matching and validation logic
|
|
- **[README.md](./README.md)**: ACL enforcement logic
|
|
- **[DESIGN.md](./DESIGN.md)**: Overall ACL system design
|
|
|
|
### Related Concepts
|
|
|
|
- **OAuth 2.1 Scopes**: Standard OAuth scope mechanism
|
|
- **RBAC**: Role-Based Access Control
|
|
- **Data Constraints**: Fine-grained data access control
|
|
- **Endpoint Matching**: Path pattern matching algorithm
|
|
|
|
---
|
|
|
|
## Migration Guide
|
|
|
|
### From Legacy Permissions
|
|
|
|
If migrating from a legacy permission system:
|
|
|
|
1. **Map old permissions to scopes**:
|
|
|
|
```
|
|
can_read_posts → posts:read:all
|
|
can_edit_own_posts → posts:write:own
|
|
can_delete_any_post → posts:delete:all
|
|
```
|
|
|
|
2. **Create scope definitions** for each permission
|
|
|
|
3. **Define aliases** for existing roles:
|
|
|
|
```yaml
|
|
role:editor:
|
|
- posts:read:all
|
|
- posts:write:own
|
|
- posts:delete:own
|
|
```
|
|
|
|
4. **Update API handlers** to check constraints
|
|
|
|
5. **Migrate role assignments** to use new scopes/aliases
|
|
|
|
6. **Test thoroughly** before deploying
|
|
|
|
### Version Compatibility
|
|
|
|
- **v1.0**: Basic scope checking
|
|
- **v1.1**: Data constraints (`owner`, `team`)
|
|
- **v1.2**: Wildcard scopes, restricted scopes
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
Key points to remember:
|
|
|
|
1. **Three main files**: `scopes.yml` (global), `alias.yml` (aliases), resource files (scopes)
|
|
2. **Naming convention**: `resource:action:level`
|
|
3. **Data constraints**: Use `owner: true` and `team: true` for data filtering
|
|
4. **Aliases**: Group scopes for easier role management
|
|
5. **Wildcards**: Use `*` for flexible matching, but sparingly
|
|
6. **Testing**: Always test scope configurations thoroughly
|
|
|
|
For more details, refer to:
|
|
|
|
- [README.md](./README.md) - Enforcement logic
|
|
- [DESIGN.md](./DESIGN.md) - System architecture
|