tangled
alpha
login
or
join now
stream.place
/
streamplace
74
fork
atom
Live video on the AT Protocol
74
fork
atom
overview
issues
1
pulls
pipelines
oauth: dynamically generate permission sets
Eli Mallon
2 months ago
a990913b
17f35060
+101
-82
3 changed files
expand all
collapse all
unified
split
lexicons
place
stream
authFull.json
pkg
atproto
lexicon_permission_sets.go
lexicon_repo.go
-21
lexicons/place/stream/authFull.json
···
1
1
-
{
2
2
-
"lexicon": 1,
3
3
-
"id": "place.stream.authFull",
4
4
-
"defs": {
5
5
-
"main": {
6
6
-
"type": "permission-set",
7
7
-
"title": "Full Streamplace Access",
8
8
-
"detail": "Full access to all Streamplace features and data.",
9
9
-
"detail:lang": {
10
10
-
"en": "Full access to all Streamplace features and data."
11
11
-
},
12
12
-
"permissions": [
13
13
-
{
14
14
-
"type": "permission",
15
15
-
"resource": "repo",
16
16
-
"collection": ["place.stream.*"]
17
17
-
}
18
18
-
]
19
19
-
}
20
20
-
}
21
21
-
}
+95
pkg/atproto/lexicon_permission_sets.go
···
1
1
+
package atproto
2
2
+
3
3
+
import (
4
4
+
"context"
5
5
+
"fmt"
6
6
+
"strings"
7
7
+
8
8
+
"github.com/bluesky-social/indigo/atproto/lexicon"
9
9
+
)
10
10
+
11
11
+
// {
12
12
+
// "lexicon": 1,
13
13
+
// "id": "place.stream.authFull",
14
14
+
// "defs": {
15
15
+
// "main": {
16
16
+
// "type": "permission-set",
17
17
+
// "title": "Full Streamplace Access",
18
18
+
// "detail": "Full access to all Streamplace features and data.",
19
19
+
// "detail:lang": {
20
20
+
// "en": "Full access to all Streamplace features and data."
21
21
+
// },
22
22
+
// "permissions": [
23
23
+
// {
24
24
+
// "type": "permission",
25
25
+
// "resource": "repo",
26
26
+
// "collection": ["place.stream.*"]
27
27
+
// }
28
28
+
// ]
29
29
+
// }
30
30
+
// }
31
31
+
// }
32
32
+
33
33
+
func generatePermissionSets(ctx context.Context, lexs []*lexicon.SchemaFile) ([]*lexicon.SchemaFile, error) {
34
34
+
recordLexicons := []*lexicon.SchemaFile{}
35
35
+
for _, lex := range lexs {
36
36
+
main, ok := lex.Defs["main"]
37
37
+
if !ok {
38
38
+
continue
39
39
+
}
40
40
+
switch main.Inner.(type) {
41
41
+
case lexicon.SchemaRecord:
42
42
+
recordLexicons = append(recordLexicons, lex)
43
43
+
case lexicon.SchemaPermissionSet:
44
44
+
return nil, fmt.Errorf("unexpected permission set in `lexicons` directory: %s", lex.ID)
45
45
+
}
46
46
+
}
47
47
+
48
48
+
allRecords := []string{}
49
49
+
allCollectionStrings := []string{
50
50
+
"atproto",
51
51
+
"blob:*/*",
52
52
+
"repo?collection=app.bsky.feed.post&action=create",
53
53
+
"repo?collection=app.bsky.actor.status",
54
54
+
"repo?collection=app.bsky.graph.block",
55
55
+
"repo?collection=app.bsky.graph.follow",
56
56
+
"rpc:app.bsky.actor.getProfile?aud=did:web:api.bsky.app%23bsky_appview",
57
57
+
"rpc:app.bsky.actor.getProfiles?aud=did:web:api.bsky.app%23bsky_appview",
58
58
+
"include:place.stream.authFull",
59
59
+
}
60
60
+
for _, record := range recordLexicons {
61
61
+
allRecords = append(allRecords, record.ID)
62
62
+
allCollectionStrings = append(allCollectionStrings, fmt.Sprintf("repo?collection=%s", record.ID))
63
63
+
}
64
64
+
65
65
+
OAuthString = strings.Join(allCollectionStrings, " ")
66
66
+
permissionSets := []*lexicon.SchemaFile{}
67
67
+
68
68
+
// place.stream.authFull
69
69
+
authFullTitle := "Full Streamplace Access"
70
70
+
authFullDetail := "Full access to all Streamplace features and data."
71
71
+
authFullSet := &lexicon.SchemaPermissionSet{
72
72
+
Type: "permission-set",
73
73
+
Title: &authFullTitle,
74
74
+
Detail: &authFullDetail,
75
75
+
Permissions: []lexicon.SchemaPermission{
76
76
+
{
77
77
+
Type: "permission",
78
78
+
Resource: "repo",
79
79
+
Collection: allRecords,
80
80
+
},
81
81
+
},
82
82
+
}
83
83
+
authFull := &lexicon.SchemaFile{
84
84
+
Lexicon: 1,
85
85
+
ID: "place.stream.authFull",
86
86
+
Defs: map[string]lexicon.SchemaDef{
87
87
+
"main": {
88
88
+
Inner: authFullSet,
89
89
+
},
90
90
+
},
91
91
+
}
92
92
+
permissionSets = append(permissionSets, authFull)
93
93
+
94
94
+
return permissionSets, nil
95
95
+
}
+6
-61
pkg/atproto/lexicon_repo.go
···
8
8
"fmt"
9
9
"io"
10
10
"io/fs"
11
11
-
"slices"
12
11
"strings"
13
12
"time"
14
13
···
239
238
240
239
ops := []*comatproto.SyncSubscribeRepos_RepoOp{}
241
240
242
242
-
lexSchemas := []lexicon.SchemaFile{}
241
241
+
lexSchemas := []*lexicon.SchemaFile{}
243
242
244
243
for _, lex := range lexs {
245
244
lexFile := lexicon.SchemaFile{}
···
250
249
if !strings.HasPrefix(lexFile.ID, "place.stream") {
251
250
continue
252
251
}
253
253
-
lexSchemas = append(lexSchemas, lexFile)
252
252
+
lexSchemas = append(lexSchemas, &lexFile)
254
253
}
255
254
256
256
-
err = populatePermissionSets(ctx, lexSchemas)
255
255
+
permissionSchemas, err := generatePermissionSets(ctx, lexSchemas)
257
256
if err != nil {
258
257
return nil, fmt.Errorf("failed to generate permission sets: %w", err)
259
258
}
259
259
+
260
260
+
lexSchemas = append(lexSchemas, permissionSchemas...)
260
261
261
262
for _, lexFile := range lexSchemas {
262
262
-
sfw := &SchemaFileWrapper{SchemaFile: lexFile}
263
263
+
sfw := &SchemaFileWrapper{SchemaFile: *lexFile}
263
264
rpath := fmt.Sprintf("com.atproto.lexicon.schema/%s", lexFile.ID)
264
265
newCid, err := spid.GetCID(sfw)
265
266
if err != nil {
···
382
383
}
383
384
return val, nil
384
385
}
385
385
-
386
386
-
const AllStreamplaceRecords = "place.stream.*"
387
387
-
388
388
-
func populatePermissionSets(ctx context.Context, lexs []lexicon.SchemaFile) error {
389
389
-
recordLexicons := []*lexicon.SchemaFile{}
390
390
-
permissionSets := []*lexicon.SchemaFile{}
391
391
-
for _, lex := range lexs {
392
392
-
main, ok := lex.Defs["main"]
393
393
-
if !ok {
394
394
-
continue
395
395
-
}
396
396
-
switch main.Inner.(type) {
397
397
-
case lexicon.SchemaRecord:
398
398
-
recordLexicons = append(recordLexicons, &lex)
399
399
-
case lexicon.SchemaPermissionSet:
400
400
-
permissionSets = append(permissionSets, &lex)
401
401
-
}
402
402
-
}
403
403
-
404
404
-
allRecords := []string{}
405
405
-
allCollectionStrings := []string{
406
406
-
"atproto",
407
407
-
"blob:*/*",
408
408
-
"repo?collection=app.bsky.feed.post&action=create",
409
409
-
"repo?collection=app.bsky.actor.status",
410
410
-
"repo?collection=app.bsky.graph.block",
411
411
-
"repo?collection=app.bsky.graph.follow",
412
412
-
"rpc:app.bsky.actor.getProfile?aud=did:web:api.bsky.app%23bsky_appview",
413
413
-
"rpc:app.bsky.actor.getProfiles?aud=did:web:api.bsky.app%23bsky_appview",
414
414
-
"include:place.stream.authFull",
415
415
-
}
416
416
-
for _, record := range recordLexicons {
417
417
-
allRecords = append(allRecords, record.ID)
418
418
-
allCollectionStrings = append(allCollectionStrings, fmt.Sprintf("repo?collection=%s", record.ID))
419
419
-
}
420
420
-
421
421
-
OAuthString = strings.Join(allCollectionStrings, " ")
422
422
-
423
423
-
for _, permSetLex := range permissionSets {
424
424
-
permSet := permSetLex.Defs["main"].Inner.(lexicon.SchemaPermissionSet)
425
425
-
for i := range permSet.Permissions {
426
426
-
if permSet.Permissions[i].Resource != "repo" {
427
427
-
continue
428
428
-
}
429
429
-
if !slices.Contains(permSet.Permissions[i].Collection, AllStreamplaceRecords) {
430
430
-
continue
431
431
-
}
432
432
-
if len(permSet.Permissions[i].Collection) != 1 {
433
433
-
return fmt.Errorf("invalid permission set: found %s with other collections, but only one collection is allowed", AllStreamplaceRecords)
434
434
-
}
435
435
-
permSet.Permissions[i].Collection = allRecords
436
436
-
}
437
437
-
}
438
438
-
439
439
-
return nil
440
440
-
}