π‘οΈ Permissions System (ACL)ΒΆ
π― OverviewΒΆ
The Permissions System (Access Control List - ACL) provides fine-grained control over who can access what resources and perform which operations. It integrates seamlessly with the Authentication System to enforce role-based access control throughout Continuum.
π PurposeΒΆ
The ACL System enables: - Role-Based Access Control (RBAC): Assign permissions based on roles - Resource-Level Permissions: Control access to specific collections - Operation-Level Permissions: Define which actions are allowed - Conditional Permissions: Apply filters to limit data access - Field-Level Security: Control access to specific fields
ποΈ ArchitectureΒΆ
graph TB
Request[API Request]
Auth[Authentication]
subgraph "ACL System"
RoleCheck{User Role?}
PermLookup[Permission Lookup]
PolicyEval[Policy Evaluation]
FilterApply[Filter Application]
end
subgraph "Permission Storage"
Roles[(Roles)]
Permissions[(Permissions)]
Policies[(Policies)]
end
subgraph "Access Decision"
Allow[Allow Access]
Deny[Deny Access 403]
FilteredAccess[Filtered Access]
end
Request --> Auth
Auth --> RoleCheck
RoleCheck --> PermLookup
PermLookup --> Roles
PermLookup --> Permissions
Permissions --> PolicyEval
PolicyEval --> Policies
PolicyEval -->|No Restrictions| Allow
PolicyEval -->|Has Filters| FilterApply
PolicyEval -->|Denied| Deny
FilterApply --> FilteredAccess
classDef acl fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
classDef storage fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef decision fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px
classDef deny fill:#ffebee,stroke:#c62828,stroke-width:2px
class RoleCheck,PermLookup,PolicyEval,FilterApply acl
class Roles,Permissions,Policies storage
class Allow,FilteredAccess decision
class Deny deny π Core ConceptsΒΆ
π₯ RolesΒΆ
Roles are groups that define sets of permissions:
| Role | Typical Permissions | Use Case |
|---|---|---|
| Admin | Full system access | System administrators |
| Editor | Content CRUD, no schema changes | Content managers |
| Author | Create/update own content | Content creators |
| Viewer | Read-only access | Consumers, clients |
| API User | Programmatic access | Integration services |
π PermissionsΒΆ
Permissions define what actions a role can perform on which resources:
Structure: - Role: Which role this applies to - Resource: Which collection (e.g., "articles", "users") - Action: Which operation (e.g., "list", "create", "update") - Conditions: Optional filters or field restrictions
π ActionsΒΆ
Standard actions available for resources:
| Action | HTTP Method | Description |
|---|---|---|
list | GET | List/query records |
get | GET | Get single record |
create | POST | Create new record |
update | POST/PUT | Update existing record |
destroy | POST/DELETE | Delete record |
add | POST | Add relationship (M2M) |
set | POST | Set relationship (M2O) |
remove | POST | Remove relationship |
βοΈ Permission ConfigurationΒΆ
π Basic Permission StructureΒΆ
{
"role": "editor",
"resource": "articles",
"action": "create",
"scope": "all",
"filter": null,
"fields": null
}
π― Permission LevelsΒΆ
1οΈβ£ Public AccessΒΆ
No authentication required:
2οΈβ£ Authenticated AccessΒΆ
Any logged-in user or valid API key:
3οΈβ£ Role-Specific AccessΒΆ
Only specific roles:
π Conditional PermissionsΒΆ
π Filter-Based PermissionsΒΆ
Limit access to records matching specific conditions:
Own Records OnlyΒΆ
{
"role": "author",
"resource": "articles",
"action": "update",
"filter": {
"authorId": "{{ ctx.state.currentUser.id }}"
}
}
Effect: Authors can only update their own articles.
Status-Based AccessΒΆ
{
"role": "editor",
"resource": "articles",
"action": "list",
"filter": {
"status": {"$in": ["published", "review"]}
}
}
Effect: Editors see only published or in-review articles.
Date-Based AccessΒΆ
{
"role": "viewer",
"resource": "articles",
"action": "list",
"filter": {
"publishedAt": {"$lte": "{{ now }}"},
"status": "published"
}
}
Effect: Viewers see only published articles from the past.
π·οΈ Field-Level PermissionsΒΆ
Control which fields can be accessed:
Read RestrictionsΒΆ
Effect: Viewers can only see id, name, and email fields.
Write RestrictionsΒΆ
{
"role": "editor",
"resource": "articles",
"action": "update",
"fields": ["title", "content", "excerpt"]
}
Effect: Editors can only update specific fields.
Hidden FieldsΒΆ
{
"role": "author",
"resource": "articles",
"action": "get",
"except": ["internalNotes", "seoAnalysis"]
}
Effect: Authors don't see internal fields.
π― Permission ExamplesΒΆ
π Blog System PermissionsΒΆ
Admin RoleΒΆ
Full access to everything.
Editor RoleΒΆ
{
"role": "editor",
"permissions": [
{
"resource": "articles",
"action": ["list", "get", "create", "update", "destroy"],
"scope": "all"
},
{
"resource": "tags",
"action": ["list", "get", "create"],
"scope": "all"
},
{
"resource": "users",
"action": ["list", "get"],
"fields": ["id", "name", "email"]
}
]
}
Editors can manage content but not modify schema or other users.
Author RoleΒΆ
{
"role": "author",
"permissions": [
{
"resource": "articles",
"action": "list",
"filter": {
"authorId": "{{ ctx.state.currentUser.id }}"
}
},
{
"resource": "articles",
"action": ["create", "update"],
"filter": {
"authorId": "{{ ctx.state.currentUser.id }}"
},
"fields": ["title", "content", "excerpt", "status"]
},
{
"resource": "articles",
"action": "get",
"filter": {
"$or": [
{"authorId": "{{ ctx.state.currentUser.id }}"},
{"status": "published"}
]
}
},
{
"resource": "tags",
"action": ["list", "get"],
"scope": "all"
}
]
}
Authors can only manage their own articles and view published ones.
Viewer RoleΒΆ
{
"role": "viewer",
"permissions": [
{
"resource": "articles",
"action": ["list", "get"],
"filter": {
"status": "published",
"publishedAt": {"$lte": "{{ now }}"}
},
"fields": ["id", "title", "content", "publishedAt", "author", "tags"]
},
{
"resource": "tags",
"action": ["list", "get"],
"scope": "all"
}
]
}
Viewers can only read published articles.
π§ Managing PermissionsΒΆ
π Via API (Programmatic)ΒΆ
List Role PermissionsΒΆ
GET /api/roles:get?filterByTk=editor&appends=permissions
X-App: main
Authorization: Bearer {admin-api-key}
Add Permission to RoleΒΆ
POST /api/roles/{role-id}/permissions:add
X-App: main
Authorization: Bearer {admin-api-key}
Content-Type: application/json
{
"values": [
{
"resource": "articles",
"action": "create",
"scope": "all"
}
]
}
Remove PermissionΒΆ
POST /api/roles/{role-id}/permissions:remove
X-App: main
Authorization: Bearer {admin-api-key}
{
"values": [permission-id]
}
π₯οΈ Via UI (Administrative)ΒΆ
- Navigate to Settings β ACL
- Select a Role
- Configure permissions for each resource
- Set conditions and field restrictions
- Save changes
π Security Best PracticesΒΆ
π― Principle of Least PrivilegeΒΆ
DO: - β Grant minimum necessary permissions - β Use role hierarchies (viewer β author β editor β admin) - β Separate read and write permissions - β Use filters to limit data access - β Restrict field access when appropriate
DON'T: - β Give everyone admin access - β Grant blanket permissions without filters - β Allow unrestricted schema modifications - β Expose sensitive fields unnecessarily
π Filter SecurityΒΆ
DO: - β
Use ctx.state.currentUser.id for user-specific filters - β
Combine multiple conditions for security - β
Test filters thoroughly - β
Audit filter effectiveness
DON'T: - β Use client-provided values in filters - β Create overly complex filter logic - β Rely solely on filters for critical security - β Forget to handle edge cases
π·οΈ Field SecurityΒΆ
DO: - β
Hide sensitive data (passwords, API keys) - β
Separate public and internal fields - β
Use except to exclude specific fields - β
Document which fields are restricted
DON'T: - β Expose internal identifiers unnecessarily - β Return sensitive data in list operations - β Allow modification of system fields - β Forget to audit field access logs
π― Common Permission PatternsΒΆ
1οΈβ£ Multi-Tenant IsolationΒΆ
Ensure users can only access their organization's data:
{
"role": "member",
"resource": "projects",
"action": "*",
"filter": {
"organizationId": "{{ ctx.state.currentUser.organizationId }}"
}
}
2οΈβ£ Hierarchical AccessΒΆ
Team leaders see their team's data:
{
"role": "team-lead",
"resource": "tasks",
"action": ["list", "get", "update"],
"filter": {
"$or": [
{"assignedTo": "{{ ctx.state.currentUser.id }}"},
{"teamId": "{{ ctx.state.currentUser.teamId }}"}
]
}
}
3οΈβ£ Time-Based AccessΒΆ
Content visible only during specific periods:
{
"role": "subscriber",
"resource": "courses",
"action": "get",
"filter": {
"subscriptionStart": {"$lte": "{{ now }}"},
"subscriptionEnd": {"$gte": "{{ now }}"}
}
}
4οΈβ£ Approval WorkflowsΒΆ
Different permissions based on status:
{
"role": "approver",
"resource": "content",
"action": "update",
"filter": {
"status": "pending-approval"
},
"fields": ["status", "approvalNotes"]
}
π§ TroubleshootingΒΆ
β Error: "No permissions" (403)ΒΆ
Check: 1. User's role assignment 2. Role's permissions for that resource/action 3. Filter conditions (may exclude the record) 4. Field restrictions (may not include requested fields)
Debug:
# Check user's role
GET /api/users:get?filterByTk={user-id}&appends=roles
X-App: main
# Check role's permissions
GET /api/roles:get?filterByTk={role-name}&appends=permissions
X-App: main
# Test with admin key
# If works with admin, it's a permission issue
β Filter Not WorkingΒΆ
Common Issues: 1. Incorrect context variable syntax 2. Type mismatch in filter 3. Missing field in collection 4. Filter too restrictive
Debug:
# Check actual filter being applied
# Enable debug logging for ACL system
# Test without filter to verify data exists
β Field Access DeniedΒΆ
Check: 1. Field list in permission configuration 2. Using fields vs except 3. Field actually exists in collection 4. Not using reserved field names
π Permission AuditΒΆ
π Track Permission UsageΒΆ
GET /api/audit-logs:list?filter={"type":"permission-check"}
X-App: main
Authorization: Bearer {admin-api-key}
π Test PermissionsΒΆ
# Test as specific role
POST /api/permissions:test
X-App: main
Content-Type: application/json
{
"role": "editor",
"resource": "articles",
"action": "update",
"recordId": 123
}
Response:
π Related DocumentationΒΆ
- Authentication: API key and user authentication
- Multi-App Manager: Application-specific permissions
- Collection Manager: Resource definitions
- Best Practices: Security optimization
Note: Proper permission configuration is essential for data security and user experience. Always test thoroughly and follow the principle of least privilege.