Google Drive Example
This example demonstrates how to implement Relationship-Based Access Control (ReBAC) for a collaborative document platform similar to Google Drive.
The schema models hierarchical folder structures where files and folders can have different permission levels, and permissions inherit from parent folders.
Schema
model AuthZ 1.0
type user
type Group
relation member: user
type File
relation owner: user | Group#member
relation writer: user | Group#member
relation commenter: user | Group#member
relation reader: user | Group#member
relation parent: Folder
permission can_delete_file: owner
permission can_access_historical_revisions: writer | parent.writer | can_delete_file
permission can_modify_content: writer | parent.writer | can_delete_file
permission can_modify_metadata: writer | parent.writer | can_delete_file
permission can_add_comment: commenter | parent.commenter | can_modify_content
permission can_read: reader | parent.reader | can_modify_content
permission can_read_metadata: reader | parent.reader | can_modify_metadata
type Folder
relation owner: user | Group#member
relation writer: user | Group#member
relation commenter: user | Group#member
relation reader: user | Group#member
relation parent: Folder
permission can_delete_folder: owner
permission can_share_files_from_folder: writer | parent.writer | can_delete_folder
permission can_remove_files_from_folder: writer | parent.writer | can_delete_folder
permission can_add_files_to_folder: writer | parent.writer | can_delete_folder
permission can_modify_metadata: writer | parent.writer | can_delete_folder
permission can_read_items: reader | parent.reader | can_add_files_to_folder
permission can_read_metadata: reader | parent.reader | can_modify_metadataSchema Components
Types
user: Individual users in the systemGroup: Groups of users that can be assigned permissions collectively (e.g., "Engineering Team", "Marketing Department")File: Individual files (e.g., documents, spreadsheets, presentations)Folder: Collections of files and subfolders that form a hierarchical structure
File Relations
Files support four relationship types:
owner: Full control over the file, including deletionwriter: Can edit the file content and metadatacommenter: Can add comments but cannot edit contentreader: Can only view the fileparent: Links the file to its parent folder
Folder Relations
Folders support the same four relationship types as files:
owner: Full control over the folder, including deletionwriter: Can add, remove, and modify files in the foldercommenter: Can comment on files in the folderreader: Can view files in the folderparent: Links the folder to its parent folder (enables nested folder structures)
Permission Hierarchy
The schema implements a hierarchical permission model with inheritance:
-
File Permissions:
can_delete_file: Only owners can delete filescan_access_historical_revisions: Writers, parent folder writers, or owners can view version historycan_modify_content: Writers or parent folder writers can edit file contentcan_modify_metadata: Writers or parent folder writers can change file propertiescan_add_comment: Commenters, parent folder commenters, or those who can modify contentcan_read: Readers, parent folder readers, or those who can modify contentcan_read_metadata: Readers or parent folder readers can view file properties
-
Folder Permissions:
can_delete_folder: Only owners can delete folderscan_share_files_from_folder: Writers, parent folder writers, or owners can share filescan_remove_files_from_folder: Writers, parent folder writers, or owners can remove filescan_add_files_to_folder: Writers, parent folder writers, or owners can add filescan_modify_metadata: Writers or parent folder writers can change folder propertiescan_read_items: Readers, parent folder readers, or those who can add filescan_read_metadata: Readers or parent folder readers can view folder properties
Use Cases
Personal Document Management
Scenario: A user organizes personal documents in a folder hierarchy (Work, Personal, Projects).
- User (Owner): Has full control over all folders and files
- Shared with Family (Reader): Family members can view files in the "Personal" folder but cannot edit
- Collaborator (Writer): A colleague can edit files in the "Work" folder
Example Relations:
// User owns the "Work" folder
{ resource: "work-folder", resourceType: "Folder", relation: "owner", target: "alice", targetType: "user" }
// Document belongs to Work folder
{ resource: "project-plan.docx", resourceType: "File", relation: "parent", target: "work-folder", targetType: "Folder" }
// Colleague is writer of Work folder (inherits to all files)
{ resource: "work-folder", resourceType: "Folder", relation: "writer", target: "bob", targetType: "user" }
// Family member is reader of Personal folder
{ resource: "personal-folder", resourceType: "Folder", relation: "reader", target: "family-group", targetType: "Group" }Team Collaboration
Scenario: An engineering team collaborates on project documentation with nested folder structures.
- Team Lead (Owner): Owns the main project folder and all subfolders
- Engineering Team (Group - Writer): All team members can edit files in project folders
- Product Manager (Commenter): Can comment on files but cannot edit
- Stakeholders (Reader): Can view project files but cannot modify
Example Relations:
// Team lead owns "Project Alpha" folder
{ resource: "project-alpha", resourceType: "Folder", relation: "owner", target: "team-lead", targetType: "user" }
// Engineering team is writer of project folder
{ resource: "project-alpha", resourceType: "Folder", relation: "writer", target: "engineering-team", targetType: "Group" }
// Design document in project folder
{ resource: "design-doc.md", resourceType: "File", relation: "parent", target: "project-alpha", targetType: "Folder" }
// Product manager is commenter (can comment but not edit)
{ resource: "design-doc.md", resourceType: "File", relation: "commenter", target: "pm-123", targetType: "user" }Enterprise Document Sharing
Scenario: A company manages documents across departments with strict access controls.
- Department Head (Owner): Owns department folders
- Department Members (Group - Writer): Can manage files in their department
- Cross-Department Collaborators (Writer): Specific users can edit files across departments
- External Partners (Reader): Limited read-only access to specific folders
Example Relations:
// Marketing department folder
{ resource: "marketing-dept", resourceType: "Folder", relation: "owner", target: "marketing-head", targetType: "user" }
// Marketing team members can write
{ resource: "marketing-dept", resourceType: "Folder", relation: "writer", target: "marketing-team", targetType: "Group" }
// Sales folder nested under Marketing
{ resource: "sales-materials", resourceType: "Folder", relation: "parent", target: "marketing-dept", targetType: "Folder" }
// External partner has read-only access
{ resource: "sales-materials", resourceType: "Folder", relation: "reader", target: "partner-company", targetType: "Group" }How It Works
Permission Inheritance
The schema uses hierarchical permission inheritance:
-
Folder → File: Permissions from the parent folder flow down to files
- If a user is a
writerof a folder, they cancan_modify_contenton all files in that folder - If a user is a
readerof a folder, they cancan_readall files in that folder
- If a user is a
-
Parent Folder → Child Folder: Permissions cascade through nested folders
- If a user is a
writerof a parent folder, they cancan_add_files_to_folderin child folders - Readers of parent folders can
can_read_itemsin child folders
- If a user is a
-
Direct File Relations: Files can have direct relations that complement folder permissions
- A file can have its own
commenterwho can comment even if not a commenter of the parent folder - A file can have its own
ownerwho has full control regardless of folder permissions
- A file can have its own
Access Control Flow
When checking if a user can perform an action on a file or folder:
- Check Direct Relations: First, check if the user has a direct relation to the file/folder
- Check Parent Folder: If no direct relation, check if the user has a relation to the parent folder
- Check Permissions: Evaluate permission expressions that may combine multiple relations
- Inherit from Parent: Parent folder permissions apply to all files and subfolders
Example: Checking Access
To check if user alice can read file project-plan.docx, you use the Descope SDK to check the can_read permission. The permission is defined as can_read: reader | parent.reader | can_modify_content, which means alice can read if she's a direct reader, a reader of the parent folder, or has permission to modify content.
// Check if alice can read the project-plan.docx file
const relations = await descopeClient.management.fga.check([
{
resource: 'project-plan.docx',
resourceType: 'File',
relation: 'can_read',
target: 'alice',
targetType: 'user',
},
]);
// relations[0] will have an 'allowed' property indicating if access is granted
if (relations[0].allowed) {
console.log('Alice can read the file');
// Proceed with reading the file
} else {
console.log('Access denied');
}# Check if alice can read the project-plan.docx file
relations = descope_client.mgmt.fga.check(
[
{
"resource": "project-plan.docx",
"resourceType": "File",
"relation": "can_read",
"target": "alice",
"targetType": "user",
}
]
)
# Check if access is granted
if relations[0]["allowed"]:
print("Alice can read the file")
# Proceed with reading the file
else:
print("Access denied")// Check if alice can read the project-plan.docx file
ctx := context.Background()
relations, err := descopeClient.Management.FGA().Check(ctx, []*descope.FGARelation{
{
Resource: "project-plan.docx",
ResourceType: "File",
Relation: "can_read",
Target: "alice",
TargetType: "user",
},
})
if err != nil {
// Handle error
log.Fatal(err)
}
// Check if access is granted
if relations[0].Allowed {
fmt.Println("Alice can read the file")
// Proceed with reading the file
} else {
fmt.Println("Access denied")
}Complete Implementation Example
Here's a complete example showing how to set up relations and check access for files and folders:
// 1. Create folder and file relations
await descopeClient.management.fga.createRelations([
// Alice owns the Work folder
{
resource: 'work-folder',
resourceType: 'Folder',
relation: 'owner',
target: 'alice',
targetType: 'user',
},
// Project document belongs to Work folder
{
resource: 'project-plan.docx',
resourceType: 'File',
relation: 'parent',
target: 'work-folder',
targetType: 'Folder',
},
// Bob is a writer of the Work folder (inherits to all files)
{
resource: 'work-folder',
resourceType: 'Folder',
relation: 'writer',
target: 'bob',
targetType: 'user',
},
// Charlie is a direct reader of the file
{
resource: 'project-plan.docx',
resourceType: 'File',
relation: 'reader',
target: 'charlie',
targetType: 'user',
},
]);
// 2. Check if alice can modify content (she can because she's owner of parent folder)
const aliceAccess = await descopeClient.management.fga.check([
{
resource: 'project-plan.docx',
resourceType: 'File',
relation: 'can_modify_content',
target: 'alice',
targetType: 'user',
},
]);
console.log('Alice can modify:', aliceAccess[0].allowed); // true
// 3. Check if bob can modify content (he can because he's writer of parent folder)
const bobAccess = await descopeClient.management.fga.check([
{
resource: 'project-plan.docx',
resourceType: 'File',
relation: 'can_modify_content',
target: 'bob',
targetType: 'user',
},
]);
console.log('Bob can modify:', bobAccess[0].allowed); // true
// 4. Check if charlie can read (he can because he's a direct reader)
const charlieAccess = await descopeClient.management.fga.check([
{
resource: 'project-plan.docx',
resourceType: 'File',
relation: 'can_read',
target: 'charlie',
targetType: 'user',
},
]);
console.log('Charlie can read:', charlieAccess[0].allowed); // true
// 5. Check if charlie can modify (he cannot - only reader)
const charlieModifyAccess = await descopeClient.management.fga.check([
{
resource: 'project-plan.docx',
resourceType: 'File',
relation: 'can_modify_content',
target: 'charlie',
targetType: 'user',
},
]);
console.log('Charlie can modify:', charlieModifyAccess[0].allowed); // false# 1. Create folder and file relations
descope_client.mgmt.fga.create_relations(
[
# Alice owns the Work folder
{
"resource": "work-folder",
"resourceType": "Folder",
"relation": "owner",
"target": "alice",
"targetType": "user",
},
# Project document belongs to Work folder
{
"resource": "project-plan.docx",
"resourceType": "File",
"relation": "parent",
"target": "work-folder",
"targetType": "Folder",
},
# Bob is a writer of the Work folder (inherits to all files)
{
"resource": "work-folder",
"resourceType": "Folder",
"relation": "writer",
"target": "bob",
"targetType": "user",
},
# Charlie is a direct reader of the file
{
"resource": "project-plan.docx",
"resourceType": "File",
"relation": "reader",
"target": "charlie",
"targetType": "user",
},
]
)
# 2. Check if alice can modify content (she can because she's owner of parent folder)
alice_access = descope_client.mgmt.fga.check(
[
{
"resource": "project-plan.docx",
"resourceType": "File",
"relation": "can_modify_content",
"target": "alice",
"targetType": "user",
}
]
)
print("Alice can modify:", alice_access[0]["allowed"]) # True
# 3. Check if bob can modify content (he can because he's writer of parent folder)
bob_access = descope_client.mgmt.fga.check(
[
{
"resource": "project-plan.docx",
"resourceType": "File",
"relation": "can_modify_content",
"target": "bob",
"targetType": "user",
}
]
)
print("Bob can modify:", bob_access[0]["allowed"]) # True
# 4. Check if charlie can read (he can because he's a direct reader)
charlie_access = descope_client.mgmt.fga.check(
[
{
"resource": "project-plan.docx",
"resourceType": "File",
"relation": "can_read",
"target": "charlie",
"targetType": "user",
}
]
)
print("Charlie can read:", charlie_access[0]["allowed"]) # True
# 5. Check if charlie can modify (he cannot - only reader)
charlie_modify_access = descope_client.mgmt.fga.check(
[
{
"resource": "project-plan.docx",
"resourceType": "File",
"relation": "can_modify_content",
"target": "charlie",
"targetType": "user",
}
]
)
print("Charlie can modify:", charlie_modify_access[0]["allowed"]) # Falsectx := context.Background()
// 1. Create folder and file relations
err := descopeClient.Management.FGA().CreateRelations(ctx, []*descope.FGARelation{
// Alice owns the Work folder
{
Resource: "work-folder",
ResourceType: "Folder",
Relation: "owner",
Target: "alice",
TargetType: "user",
},
// Project document belongs to Work folder
{
Resource: "project-plan.docx",
ResourceType: "File",
Relation: "parent",
Target: "work-folder",
TargetType: "Folder",
},
// Bob is a writer of the Work folder (inherits to all files)
{
Resource: "work-folder",
ResourceType: "Folder",
Relation: "writer",
Target: "bob",
TargetType: "user",
},
// Charlie is a direct reader of the file
{
Resource: "project-plan.docx",
ResourceType: "File",
Relation: "reader",
Target: "charlie",
TargetType: "user",
},
})
// 2. Check if alice can modify content (she can because she's owner of parent folder)
aliceAccess, err := descopeClient.Management.FGA().Check(ctx, []*descope.FGARelation{
{
Resource: "project-plan.docx",
ResourceType: "File",
Relation: "can_modify_content",
Target: "alice",
TargetType: "user",
},
})
fmt.Println("Alice can modify:", aliceAccess[0].Allowed) // true
// 3. Check if bob can modify content (he can because he's writer of parent folder)
bobAccess, err := descopeClient.Management.FGA().Check(ctx, []*descope.FGARelation{
{
Resource: "project-plan.docx",
ResourceType: "File",
Relation: "can_modify_content",
Target: "bob",
TargetType: "user",
},
})
fmt.Println("Bob can modify:", bobAccess[0].Allowed) // true
// 4. Check if charlie can read (he can because he's a direct reader)
charlieAccess, err := descopeClient.Management.FGA().Check(ctx, []*descope.FGARelation{
{
Resource: "project-plan.docx",
ResourceType: "File",
Relation: "can_read",
Target: "charlie",
TargetType: "user",
},
})
fmt.Println("Charlie can read:", charlieAccess[0].Allowed) // true
// 5. Check if charlie can modify (he cannot - only reader)
charlieModifyAccess, err := descopeClient.Management.FGA().Check(ctx, []*descope.FGARelation{
{
Resource: "project-plan.docx",
ResourceType: "File",
Relation: "can_modify_content",
Target: "charlie",
TargetType: "user",
},
})
fmt.Println("Charlie can modify:", charlieModifyAccess[0].Allowed) // falseImplementation Considerations
- File Organization: When a new file is created, it must be linked to a folder via the
parentrelation - Permission Propagation: Changes to folder permissions automatically affect all files and subfolders
- Nested Folders: Folders can have parent folders, creating deep hierarchies
- User Groups: Use groups for team-based permissions (e.g., all "Engineering Team" members)
- Sharing Workflow: Implement sharing by creating relations between users/groups and files/folders
This schema provides a robust foundation for managing document access in collaborative platforms, from personal file management to enterprise document sharing systems.