@powerhousedao/academy 5.1.0-dev.14 → 5.1.0-dev.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/docs/academy/01-GetStarted/00-ExploreDemoPackage.mdx +11 -11
- package/docs/academy/01-GetStarted/01-CreateNewPowerhouseProject.md +22 -5
- package/docs/academy/01-GetStarted/02-DefineToDoListDocumentModel.md +2 -20
- package/docs/academy/01-GetStarted/03-ImplementOperationReducers.md +2 -3
- package/docs/academy/01-GetStarted/05-BuildToDoListEditor.md +4 -4
- package/docs/academy/01-GetStarted/home.mdx +43 -104
- package/docs/academy/01-GetStarted/images/DocumentModelOperations.png +0 -0
- package/docs/academy/01-GetStarted/styles.module.css +30 -6
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/02-VetraStudio.md +95 -0
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/{02-StandardDocumentModelWorkflow.md → 03-CreateAPackageWithVetra.md} +202 -33
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/{03-BuilderTools.md → BuilderTools} +1 -1
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/02-ConfiguringDrives.md +4 -4
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/03-BuildingADriveExplorer.md +34 -34
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/07-Authorization/03-DocumentPermissions.md +387 -0
- package/docs/academy/02-MasteryTrack/05-Launch/02-PublishYourProject.md +118 -184
- package/docs/academy/02-MasteryTrack/05-Launch/03-SetupEnvironment.md +1 -1
- package/docs/academy/02-MasteryTrack/05-Launch/05-DockerDeployment.md +1 -1
- package/docs/academy/02-MasteryTrack/_category_.json +1 -1
- package/docs/academy/03-ExampleUsecases/00-Overview.mdx +60 -0
- package/docs/academy/03-ExampleUsecases/Chatroom/02-CreateNewPowerhouseProject.md +38 -16
- package/docs/academy/03-ExampleUsecases/Chatroom/03-DefineChatroomDocumentModel.md +11 -14
- package/docs/academy/03-ExampleUsecases/Chatroom/04-ImplementOperationReducers.md +12 -95
- package/docs/academy/03-ExampleUsecases/Chatroom/05-ImplementChatroomEditor.md +30 -20
- package/docs/academy/03-ExampleUsecases/Chatroom/{06-LaunchALocalReactor.md → 06-LaunchALocalReactor} +13 -8
- package/docs/academy/03-ExampleUsecases/VetraPackageLibrary/VetraPackageLibrary.md +13 -0
- package/docs/academy/03-ExampleUsecases/_category_.json +9 -0
- package/docs/academy/04-APIReferences/00-PowerhouseCLI.md +168 -15
- package/docs/academy/04-APIReferences/01-ReactHooks.md +7 -0
- package/docs/academy/04-APIReferences/04-RelationalDatabase.md +6 -0
- package/docs/academy/04-APIReferences/renown-sdk/03-CLIIdentity.md +321 -0
- package/docs/academy/05-Architecture/00-PowerhouseArchitecture.md +46 -11
- package/docs/academy/07-Cookbook.md +598 -145
- package/docs/academy/08-Glossary.md +1 -1
- package/docusaurus.config.ts +13 -35
- package/package.json +1 -1
- package/sidebars.ts +11 -11
- package/src/css/custom.css +28 -30
- package/src/theme/DocSidebarItem/Category/index.tsx +47 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/05-VetraStudio.md +0 -253
- package/docs/academy/02-MasteryTrack/05-Launch/01-IntroductionToPackages.md +0 -78
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
# Document Permission System
|
|
2
|
+
|
|
3
|
+
The Reactor API includes a fine-grained document permission system that allows you to control access to individual documents, folders, and drives. This system works alongside the global role-based authorization to provide granular access control.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The document permission system provides:
|
|
8
|
+
|
|
9
|
+
- **Document-level permissions**: Grant READ, WRITE, or ADMIN access to specific documents
|
|
10
|
+
- **Permission inheritance**: Permissions flow down from parent documents (drives → folders → documents)
|
|
11
|
+
- **Group-based access**: Organize users into groups and assign permissions to groups
|
|
12
|
+
- **Operation-level permissions**: Restrict specific operations to certain users or groups
|
|
13
|
+
|
|
14
|
+
## Prerequisites
|
|
15
|
+
|
|
16
|
+
Before using document permissions, you need:
|
|
17
|
+
|
|
18
|
+
1. **Renown authentication**: Users must authenticate via `ph login`
|
|
19
|
+
2. **AUTH_ENABLED=true**: Global authentication must be enabled
|
|
20
|
+
3. **DOCUMENT_PERMISSIONS_ENABLED=true**: Document permissions feature flag must be set
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Environment variables
|
|
24
|
+
AUTH_ENABLED=true
|
|
25
|
+
DOCUMENT_PERMISSIONS_ENABLED=true
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Permission Levels
|
|
29
|
+
|
|
30
|
+
The system defines three permission levels for documents:
|
|
31
|
+
|
|
32
|
+
| Level | Description | Capabilities |
|
|
33
|
+
|-------|-------------|--------------|
|
|
34
|
+
| `READ` | View access | Can fetch and read the document |
|
|
35
|
+
| `WRITE` | Edit access | Can push updates and modify the document |
|
|
36
|
+
| `ADMIN` | Full access | Can manage document permissions and settings |
|
|
37
|
+
|
|
38
|
+
Higher permission levels include all capabilities of lower levels (ADMIN includes WRITE and READ, WRITE includes READ).
|
|
39
|
+
|
|
40
|
+
## How It Works
|
|
41
|
+
|
|
42
|
+
### Permission Resolution
|
|
43
|
+
|
|
44
|
+
When a user attempts to access a document, the system checks permissions in this order:
|
|
45
|
+
|
|
46
|
+
1. **Global role check**: If AUTH_ENABLED is false, access is granted
|
|
47
|
+
2. **Direct user permission**: Check if user has explicit permission on the document
|
|
48
|
+
3. **Group permission**: Check if user belongs to a group with permission on the document
|
|
49
|
+
4. **Parent inheritance**: Recursively check parent documents (folder → drive)
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
Drive (ADMIN permission for user)
|
|
53
|
+
└── Folder A (inherits ADMIN)
|
|
54
|
+
└── Document 1 (inherits ADMIN)
|
|
55
|
+
└── Document 2 (inherits ADMIN)
|
|
56
|
+
└── Folder B (READ permission for user)
|
|
57
|
+
└── Document 3 (inherits READ)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Database Schema
|
|
61
|
+
|
|
62
|
+
The permission system uses six database tables:
|
|
63
|
+
|
|
64
|
+
| Table | Purpose |
|
|
65
|
+
|-------|---------|
|
|
66
|
+
| `DocumentPermission` | Direct user-document permissions |
|
|
67
|
+
| `Group` | Group definitions |
|
|
68
|
+
| `UserGroup` | User-group memberships |
|
|
69
|
+
| `DocumentGroupPermission` | Group-document permissions |
|
|
70
|
+
| `OperationUserPermission` | User-operation permissions |
|
|
71
|
+
| `OperationGroupPermission` | Group-operation permissions |
|
|
72
|
+
|
|
73
|
+
## GraphQL API
|
|
74
|
+
|
|
75
|
+
When `DOCUMENT_PERMISSIONS_ENABLED=true`, an Auth subgraph is registered with the following operations.
|
|
76
|
+
|
|
77
|
+
### Queries
|
|
78
|
+
|
|
79
|
+
#### Get document access info
|
|
80
|
+
|
|
81
|
+
```graphql
|
|
82
|
+
query GetDocumentAccess($documentId: String!) {
|
|
83
|
+
documentAccess(documentId: $documentId) {
|
|
84
|
+
documentId
|
|
85
|
+
permissions {
|
|
86
|
+
userAddress
|
|
87
|
+
permission
|
|
88
|
+
grantedBy
|
|
89
|
+
createdAt
|
|
90
|
+
}
|
|
91
|
+
groupPermissions {
|
|
92
|
+
groupId
|
|
93
|
+
group {
|
|
94
|
+
name
|
|
95
|
+
}
|
|
96
|
+
permission
|
|
97
|
+
grantedBy
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
#### Get current user's document permissions
|
|
104
|
+
|
|
105
|
+
```graphql
|
|
106
|
+
query MyDocuments {
|
|
107
|
+
userDocumentPermissions {
|
|
108
|
+
documentId
|
|
109
|
+
permission
|
|
110
|
+
grantedBy
|
|
111
|
+
createdAt
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
#### List all groups
|
|
117
|
+
|
|
118
|
+
```graphql
|
|
119
|
+
query ListGroups {
|
|
120
|
+
groups {
|
|
121
|
+
id
|
|
122
|
+
name
|
|
123
|
+
description
|
|
124
|
+
members
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### Check operation permission
|
|
130
|
+
|
|
131
|
+
```graphql
|
|
132
|
+
query CanExecute($documentId: String!, $operation: String!) {
|
|
133
|
+
canExecuteOperation(documentId: $documentId, operationType: $operation)
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Mutations
|
|
138
|
+
|
|
139
|
+
#### Grant user permission
|
|
140
|
+
|
|
141
|
+
```graphql
|
|
142
|
+
mutation GrantPermission($documentId: String!, $user: String!, $level: DocumentPermissionLevel!) {
|
|
143
|
+
grantDocumentPermission(
|
|
144
|
+
documentId: $documentId
|
|
145
|
+
userAddress: $user
|
|
146
|
+
permission: $level
|
|
147
|
+
) {
|
|
148
|
+
documentId
|
|
149
|
+
userAddress
|
|
150
|
+
permission
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
#### Revoke user permission
|
|
156
|
+
|
|
157
|
+
```graphql
|
|
158
|
+
mutation RevokePermission($documentId: String!, $user: String!) {
|
|
159
|
+
revokeDocumentPermission(documentId: $documentId, userAddress: $user)
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
#### Create a group
|
|
164
|
+
|
|
165
|
+
```graphql
|
|
166
|
+
mutation CreateGroup($name: String!, $description: String) {
|
|
167
|
+
createGroup(name: $name, description: $description) {
|
|
168
|
+
id
|
|
169
|
+
name
|
|
170
|
+
description
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
#### Add user to group
|
|
176
|
+
|
|
177
|
+
```graphql
|
|
178
|
+
mutation AddToGroup($user: String!, $groupId: Int!) {
|
|
179
|
+
addUserToGroup(userAddress: $user, groupId: $groupId)
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
#### Grant group permission on document
|
|
184
|
+
|
|
185
|
+
```graphql
|
|
186
|
+
mutation GrantGroupAccess($documentId: String!, $groupId: Int!, $level: DocumentPermissionLevel!) {
|
|
187
|
+
grantGroupPermission(
|
|
188
|
+
documentId: $documentId
|
|
189
|
+
groupId: $groupId
|
|
190
|
+
permission: $level
|
|
191
|
+
) {
|
|
192
|
+
documentId
|
|
193
|
+
groupId
|
|
194
|
+
permission
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
#### Grant operation permission
|
|
200
|
+
|
|
201
|
+
```graphql
|
|
202
|
+
mutation GrantOperation($documentId: String!, $operation: String!, $user: String!) {
|
|
203
|
+
grantOperationPermission(
|
|
204
|
+
documentId: $documentId
|
|
205
|
+
operationType: $operation
|
|
206
|
+
userAddress: $user
|
|
207
|
+
) {
|
|
208
|
+
documentId
|
|
209
|
+
operationType
|
|
210
|
+
userAddress
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Configuration
|
|
216
|
+
|
|
217
|
+
### Environment Variables
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
# Enable authentication (required)
|
|
221
|
+
AUTH_ENABLED=true
|
|
222
|
+
|
|
223
|
+
# Enable document permissions feature
|
|
224
|
+
DOCUMENT_PERMISSIONS_ENABLED=true
|
|
225
|
+
|
|
226
|
+
# Global admin addresses (bypass all permission checks)
|
|
227
|
+
ADMINS="0x123...,0x456..."
|
|
228
|
+
|
|
229
|
+
# Global user addresses (basic access)
|
|
230
|
+
USERS="0x789...,0xabc..."
|
|
231
|
+
|
|
232
|
+
# Global guest addresses (read-only access)
|
|
233
|
+
GUESTS="0xdef...,0xghi..."
|
|
234
|
+
|
|
235
|
+
# Allow any authenticated user (free entry mode)
|
|
236
|
+
FREE_ENTRY=true
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### powerhouse.config.json
|
|
240
|
+
|
|
241
|
+
```json
|
|
242
|
+
{
|
|
243
|
+
"auth": {
|
|
244
|
+
"enabled": true,
|
|
245
|
+
"admins": ["0x123...", "0x456..."],
|
|
246
|
+
"users": ["0x789...", "0xabc..."],
|
|
247
|
+
"guests": ["0xdef...", "0xghi..."],
|
|
248
|
+
"freeEntry": false
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Usage Examples
|
|
254
|
+
|
|
255
|
+
### Setting Up Drive Permissions
|
|
256
|
+
|
|
257
|
+
When creating a new drive, grant yourself ADMIN access:
|
|
258
|
+
|
|
259
|
+
```graphql
|
|
260
|
+
mutation SetupDriveAdmin {
|
|
261
|
+
grantDocumentPermission(
|
|
262
|
+
documentId: "drive-id-here"
|
|
263
|
+
userAddress: "0xYourAddress"
|
|
264
|
+
permission: ADMIN
|
|
265
|
+
) {
|
|
266
|
+
documentId
|
|
267
|
+
permission
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Creating a Team with Shared Access
|
|
273
|
+
|
|
274
|
+
1. Create a group:
|
|
275
|
+
|
|
276
|
+
```graphql
|
|
277
|
+
mutation CreateTeam {
|
|
278
|
+
createGroup(name: "Engineering", description: "Engineering team") {
|
|
279
|
+
id
|
|
280
|
+
name
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
2. Add team members:
|
|
286
|
+
|
|
287
|
+
```graphql
|
|
288
|
+
mutation AddMembers {
|
|
289
|
+
alice: addUserToGroup(userAddress: "0xAlice", groupId: 1)
|
|
290
|
+
bob: addUserToGroup(userAddress: "0xBob", groupId: 1)
|
|
291
|
+
charlie: addUserToGroup(userAddress: "0xCharlie", groupId: 1)
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
3. Grant group access to a drive:
|
|
296
|
+
|
|
297
|
+
```graphql
|
|
298
|
+
mutation GrantTeamAccess {
|
|
299
|
+
grantGroupPermission(
|
|
300
|
+
documentId: "drive-id"
|
|
301
|
+
groupId: 1
|
|
302
|
+
permission: WRITE
|
|
303
|
+
) {
|
|
304
|
+
documentId
|
|
305
|
+
permission
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
Now all Engineering team members can read and write documents in the drive.
|
|
311
|
+
|
|
312
|
+
### Restricting Specific Operations
|
|
313
|
+
|
|
314
|
+
You can restrict specific operations to certain users. For example, only allow admins to delete items:
|
|
315
|
+
|
|
316
|
+
```graphql
|
|
317
|
+
mutation RestrictDelete {
|
|
318
|
+
grantOperationPermission(
|
|
319
|
+
documentId: "drive-id"
|
|
320
|
+
operationType: "DELETE_NODE"
|
|
321
|
+
userAddress: "0xAdminAddress"
|
|
322
|
+
) {
|
|
323
|
+
operationType
|
|
324
|
+
userAddress
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
When operation permissions are set, only users with explicit permission can execute that operation.
|
|
330
|
+
|
|
331
|
+
## Integration with Auth Flow
|
|
332
|
+
|
|
333
|
+
The document permission system integrates with the Renown authentication flow:
|
|
334
|
+
|
|
335
|
+
1. User authenticates via `ph login` → gets a Renown credential
|
|
336
|
+
2. User generates a bearer token via `ph access-token`
|
|
337
|
+
3. Bearer token is included in API requests
|
|
338
|
+
4. Reactor API verifies the token and extracts the user's address
|
|
339
|
+
5. Permission checks are performed using the user's address
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
# Generate access token
|
|
343
|
+
TOKEN=$(ph access-token --expiry 7d)
|
|
344
|
+
|
|
345
|
+
# Make authenticated request
|
|
346
|
+
curl -X POST http://localhost:4001/graphql \
|
|
347
|
+
-H "Content-Type: application/json" \
|
|
348
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
349
|
+
-d '{"query": "{ userDocumentPermissions { documentId permission } }"}'
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
## Best Practices
|
|
353
|
+
|
|
354
|
+
1. **Use groups for team access**: Instead of granting individual permissions, create groups and assign permissions to groups
|
|
355
|
+
|
|
356
|
+
2. **Grant ADMIN sparingly**: Only grant ADMIN permission to users who need to manage permissions
|
|
357
|
+
|
|
358
|
+
3. **Use permission inheritance**: Grant permissions at the drive or folder level, let them inherit down
|
|
359
|
+
|
|
360
|
+
4. **Document your permission structure**: Keep track of which groups have access to which drives
|
|
361
|
+
|
|
362
|
+
5. **Regular audits**: Periodically review permissions and remove stale access
|
|
363
|
+
|
|
364
|
+
## Troubleshooting
|
|
365
|
+
|
|
366
|
+
### Permission denied errors
|
|
367
|
+
|
|
368
|
+
1. Verify `AUTH_ENABLED=true` and `DOCUMENT_PERMISSIONS_ENABLED=true`
|
|
369
|
+
2. Check that the user has a valid Renown credential (`ph login --status`)
|
|
370
|
+
3. Verify the bearer token is valid and not expired
|
|
371
|
+
4. Check if the user has direct or group permission on the document
|
|
372
|
+
5. Check if permission is inherited from a parent document
|
|
373
|
+
|
|
374
|
+
### Migrations not running
|
|
375
|
+
|
|
376
|
+
Ensure database migrations have run:
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
# Migrations run automatically on startup when DOCUMENT_PERMISSIONS_ENABLED=true
|
|
380
|
+
# Check logs for "Document permission migrations completed"
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Group permissions not working
|
|
384
|
+
|
|
385
|
+
1. Verify the user is a member of the group: `userGroups(userAddress: "0x...")`
|
|
386
|
+
2. Verify the group has permission on the document: `documentAccess(documentId: "...")`
|
|
387
|
+
3. Check that group membership was created before permission check
|