@atproto/ozone 0.1.25 → 0.1.26
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 +9 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +8 -0
- package/dist/api/index.js.map +1 -1
- package/dist/api/server/getConfig.d.ts.map +1 -1
- package/dist/api/server/getConfig.js +4 -3
- package/dist/api/server/getConfig.js.map +1 -1
- package/dist/api/team/addMember.d.ts +4 -0
- package/dist/api/team/addMember.d.ts.map +1 -0
- package/dist/api/team/addMember.js +38 -0
- package/dist/api/team/addMember.js.map +1 -0
- package/dist/api/team/deleteMember.d.ts +4 -0
- package/dist/api/team/deleteMember.d.ts.map +1 -0
- package/dist/api/team/deleteMember.js +26 -0
- package/dist/api/team/deleteMember.js.map +1 -0
- package/dist/api/team/listMembers.d.ts +4 -0
- package/dist/api/team/listMembers.d.ts.map +1 -0
- package/dist/api/team/listMembers.js +20 -0
- package/dist/api/team/listMembers.js.map +1 -0
- package/dist/api/team/updateMember.d.ts +4 -0
- package/dist/api/team/updateMember.d.ts.map +1 -0
- package/dist/api/team/updateMember.js +40 -0
- package/dist/api/team/updateMember.js.map +1 -0
- package/dist/api/util.d.ts +1 -0
- package/dist/api/util.d.ts.map +1 -1
- package/dist/api/util.js +10 -1
- package/dist/api/util.js.map +1 -1
- package/dist/auth-verifier.d.ts +3 -6
- package/dist/auth-verifier.d.ts.map +1 -1
- package/dist/auth-verifier.js +7 -19
- package/dist/auth-verifier.js.map +1 -1
- package/dist/context.d.ts +3 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +7 -3
- package/dist/context.js.map +1 -1
- package/dist/db/migrations/20240521T211332580Z-member.d.ts +4 -0
- package/dist/db/migrations/20240521T211332580Z-member.d.ts.map +1 -0
- package/dist/db/migrations/20240521T211332580Z-member.js +20 -0
- package/dist/db/migrations/20240521T211332580Z-member.js.map +1 -0
- package/dist/db/migrations/index.d.ts +1 -0
- package/dist/db/migrations/index.d.ts.map +1 -1
- package/dist/db/migrations/index.js +2 -1
- package/dist/db/migrations/index.js.map +1 -1
- package/dist/db/schema/index.d.ts +2 -1
- package/dist/db/schema/index.d.ts.map +1 -1
- package/dist/db/schema/member.d.ts +14 -0
- package/dist/db/schema/member.d.ts.map +1 -0
- package/dist/db/schema/member.js +5 -0
- package/dist/db/schema/member.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -1
- package/dist/lexicon/index.d.ts +18 -0
- package/dist/lexicon/index.d.ts.map +1 -1
- package/dist/lexicon/index.js +41 -1
- package/dist/lexicon/index.js.map +1 -1
- package/dist/lexicon/lexicons.d.ts +204 -0
- package/dist/lexicon/lexicons.d.ts.map +1 -1
- package/dist/lexicon/lexicons.js +222 -0
- package/dist/lexicon/lexicons.js.map +1 -1
- package/dist/lexicon/types/tools/ozone/team/addMember.d.ts +40 -0
- package/dist/lexicon/types/tools/ozone/team/addMember.d.ts.map +1 -0
- package/dist/lexicon/types/tools/ozone/team/addMember.js +3 -0
- package/dist/lexicon/types/tools/ozone/team/addMember.js.map +1 -0
- package/dist/lexicon/types/tools/ozone/team/defs.d.ts +24 -0
- package/dist/lexicon/types/tools/ozone/team/defs.d.ts.map +1 -0
- package/dist/lexicon/types/tools/ozone/team/defs.js +22 -0
- package/dist/lexicon/types/tools/ozone/team/defs.js.map +1 -0
- package/dist/lexicon/types/tools/ozone/team/deleteMember.d.ts +30 -0
- package/dist/lexicon/types/tools/ozone/team/deleteMember.d.ts.map +1 -0
- package/dist/lexicon/types/tools/ozone/team/deleteMember.js +3 -0
- package/dist/lexicon/types/tools/ozone/team/deleteMember.js.map +1 -0
- package/dist/lexicon/types/tools/ozone/team/listMembers.d.ts +38 -0
- package/dist/lexicon/types/tools/ozone/team/listMembers.d.ts.map +1 -0
- package/dist/lexicon/types/tools/ozone/team/listMembers.js +3 -0
- package/dist/lexicon/types/tools/ozone/team/listMembers.js.map +1 -0
- package/dist/lexicon/types/tools/ozone/team/updateMember.d.ts +41 -0
- package/dist/lexicon/types/tools/ozone/team/updateMember.d.ts.map +1 -0
- package/dist/lexicon/types/tools/ozone/team/updateMember.js +3 -0
- package/dist/lexicon/types/tools/ozone/team/updateMember.js.map +1 -0
- package/dist/team/index.d.ts +37 -0
- package/dist/team/index.d.ts.map +1 -0
- package/dist/team/index.js +144 -0
- package/dist/team/index.js.map +1 -0
- package/package.json +3 -3
- package/src/api/index.ts +8 -0
- package/src/api/server/getConfig.ts +4 -4
- package/src/api/team/addMember.ts +46 -0
- package/src/api/team/deleteMember.ts +29 -0
- package/src/api/team/listMembers.ts +20 -0
- package/src/api/team/updateMember.ts +47 -0
- package/src/api/util.ts +15 -0
- package/src/auth-verifier.ts +14 -12
- package/src/context.ts +9 -3
- package/src/db/migrations/20240521T211332580Z-member.ts +17 -0
- package/src/db/migrations/index.ts +1 -0
- package/src/db/schema/index.ts +3 -1
- package/src/db/schema/member.ts +19 -0
- package/src/index.ts +36 -0
- package/src/lexicon/index.ts +63 -0
- package/src/lexicon/lexicons.ts +225 -0
- package/src/lexicon/types/tools/ozone/team/addMember.ts +53 -0
- package/src/lexicon/types/tools/ozone/team/defs.ts +42 -0
- package/src/lexicon/types/tools/ozone/team/deleteMember.ts +39 -0
- package/src/lexicon/types/tools/ozone/team/listMembers.ts +48 -0
- package/src/lexicon/types/tools/ozone/team/updateMember.ts +54 -0
- package/src/team/index.ts +213 -0
- package/tests/__snapshots__/team.test.ts.snap +664 -0
- package/tests/get-config.test.ts +3 -4
- package/tests/team.test.ts +163 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { AuthRequiredError, InvalidRequestError } from '@atproto/xrpc-server'
|
|
2
|
+
import { Server } from '../../lexicon'
|
|
3
|
+
import AppContext from '../../context'
|
|
4
|
+
import { getMemberRole } from '../util'
|
|
5
|
+
|
|
6
|
+
export default function (server: Server, ctx: AppContext) {
|
|
7
|
+
server.tools.ozone.team.updateMember({
|
|
8
|
+
auth: ctx.authVerifier.modOrAdminToken,
|
|
9
|
+
handler: async ({ input, auth }) => {
|
|
10
|
+
const access = auth.credentials
|
|
11
|
+
const db = ctx.db
|
|
12
|
+
const { did, role, ...rest } = input.body
|
|
13
|
+
|
|
14
|
+
if (!access.isAdmin) {
|
|
15
|
+
throw new AuthRequiredError('Must be an admin to update a member')
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (did === ctx.cfg.service.did) {
|
|
19
|
+
throw new InvalidRequestError('Can not update service owner')
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const updatedMember = await db.transaction(async (dbTxn) => {
|
|
23
|
+
const teamService = ctx.teamService(dbTxn)
|
|
24
|
+
|
|
25
|
+
const memberExists = await teamService.doesMemberExist(did)
|
|
26
|
+
|
|
27
|
+
if (!memberExists) {
|
|
28
|
+
throw new InvalidRequestError('member not found', 'MemberNotFound')
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const updated = await teamService.update(did, {
|
|
32
|
+
...rest,
|
|
33
|
+
...(role ? { role: getMemberRole(role) } : {}),
|
|
34
|
+
lastUpdatedBy:
|
|
35
|
+
access.type === 'admin_token' ? 'admin_token' : access.iss,
|
|
36
|
+
})
|
|
37
|
+
const memberView = await teamService.view([updated], ctx)
|
|
38
|
+
return memberView[0]
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
encoding: 'application/json',
|
|
43
|
+
body: updatedMember,
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
})
|
|
47
|
+
}
|
package/src/api/util.ts
CHANGED
|
@@ -20,6 +20,12 @@ import {
|
|
|
20
20
|
import { ModerationEvent } from '../db/schema/moderation_event'
|
|
21
21
|
import { ModerationSubjectStatusRow } from '../mod-service/types'
|
|
22
22
|
import AppContext from '../context'
|
|
23
|
+
import { Member } from '../db/schema/member'
|
|
24
|
+
import {
|
|
25
|
+
ROLEADMIN,
|
|
26
|
+
ROLEMODERATOR,
|
|
27
|
+
ROLETRIAGE,
|
|
28
|
+
} from '../lexicon/types/tools/ozone/team/defs'
|
|
23
29
|
|
|
24
30
|
export const getPdsAccountInfo = async (
|
|
25
31
|
ctx: AppContext,
|
|
@@ -122,3 +128,12 @@ const eventTypes = new Set([
|
|
|
122
128
|
'tools.ozone.moderation.defs#modEventTag',
|
|
123
129
|
'tools.ozone.moderation.defs#modEventDivert',
|
|
124
130
|
])
|
|
131
|
+
|
|
132
|
+
export const getMemberRole = (role: string) => {
|
|
133
|
+
if (memberRoles.has(role)) {
|
|
134
|
+
return role as Member['role']
|
|
135
|
+
}
|
|
136
|
+
throw new InvalidRequestError('Invalid member role')
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const memberRoles = new Set([ROLEADMIN, ROLEMODERATOR, ROLETRIAGE])
|
package/src/auth-verifier.ts
CHANGED
|
@@ -2,6 +2,7 @@ import express from 'express'
|
|
|
2
2
|
import * as ui8 from 'uint8arrays'
|
|
3
3
|
import { IdResolver } from '@atproto/identity'
|
|
4
4
|
import { AuthRequiredError, verifyJwt } from '@atproto/xrpc-server'
|
|
5
|
+
import { TeamService } from './team'
|
|
5
6
|
|
|
6
7
|
type ReqCtx = {
|
|
7
8
|
req: express.Request
|
|
@@ -47,17 +48,13 @@ type NullOutput = {
|
|
|
47
48
|
|
|
48
49
|
export type AuthVerifierOpts = {
|
|
49
50
|
serviceDid: string
|
|
50
|
-
admins: string[]
|
|
51
|
-
moderators: string[]
|
|
52
|
-
triage: string[]
|
|
53
51
|
adminPassword: string
|
|
52
|
+
teamService: TeamService
|
|
54
53
|
}
|
|
55
54
|
|
|
56
55
|
export class AuthVerifier {
|
|
57
56
|
serviceDid: string
|
|
58
|
-
|
|
59
|
-
moderators: string[]
|
|
60
|
-
triage: string[]
|
|
57
|
+
teamService: TeamService
|
|
61
58
|
private adminPassword: string
|
|
62
59
|
|
|
63
60
|
constructor(
|
|
@@ -65,10 +62,8 @@ export class AuthVerifier {
|
|
|
65
62
|
opts: AuthVerifierOpts,
|
|
66
63
|
) {
|
|
67
64
|
this.serviceDid = opts.serviceDid
|
|
68
|
-
this.admins = opts.admins
|
|
69
|
-
this.moderators = opts.moderators
|
|
70
|
-
this.triage = opts.triage
|
|
71
65
|
this.adminPassword = opts.adminPassword
|
|
66
|
+
this.teamService = opts.teamService
|
|
72
67
|
}
|
|
73
68
|
|
|
74
69
|
modOrAdminToken = async (
|
|
@@ -113,9 +108,16 @@ export class AuthVerifier {
|
|
|
113
108
|
}
|
|
114
109
|
const payload = await verifyJwt(jwtStr, this.serviceDid, getSigningKey)
|
|
115
110
|
const iss = payload.iss
|
|
116
|
-
|
|
117
|
-
const
|
|
118
|
-
|
|
111
|
+
|
|
112
|
+
const member = await this.teamService.getMember(iss)
|
|
113
|
+
|
|
114
|
+
if (member?.disabled) {
|
|
115
|
+
throw new AuthRequiredError('member is disabled', 'MemberDisabled')
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const { isAdmin, isModerator, isTriage } =
|
|
119
|
+
this.teamService.getMemberRole(member)
|
|
120
|
+
|
|
119
121
|
return {
|
|
120
122
|
credentials: {
|
|
121
123
|
type: 'standard',
|
package/src/context.ts
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
import { BlobDiverter } from './daemon/blob-diverter'
|
|
19
19
|
import { AuthVerifier } from './auth-verifier'
|
|
20
20
|
import { ImageInvalidator } from './image-invalidator'
|
|
21
|
+
import { TeamService, TeamServiceCreator } from './team'
|
|
21
22
|
import {
|
|
22
23
|
defaultLabelerHeader,
|
|
23
24
|
getSigningKeyId,
|
|
@@ -31,6 +32,7 @@ export type AppContextOptions = {
|
|
|
31
32
|
cfg: OzoneConfig
|
|
32
33
|
modService: ModerationServiceCreator
|
|
33
34
|
communicationTemplateService: CommunicationTemplateServiceCreator
|
|
35
|
+
teamService: TeamServiceCreator
|
|
34
36
|
appviewAgent: AtpAgent
|
|
35
37
|
pdsAgent: AtpAgent | undefined
|
|
36
38
|
chatAgent: AtpAgent | undefined
|
|
@@ -107,15 +109,14 @@ export class AppContext {
|
|
|
107
109
|
)
|
|
108
110
|
|
|
109
111
|
const communicationTemplateService = CommunicationTemplateService.creator()
|
|
112
|
+
const teamService = TeamService.creator()
|
|
110
113
|
|
|
111
114
|
const sequencer = new Sequencer(modService(db))
|
|
112
115
|
|
|
113
116
|
const authVerifier = new AuthVerifier(idResolver, {
|
|
114
117
|
serviceDid: cfg.service.did,
|
|
115
|
-
admins: cfg.access.admins,
|
|
116
|
-
moderators: cfg.access.moderators,
|
|
117
|
-
triage: cfg.access.triage,
|
|
118
118
|
adminPassword: secrets.adminPassword,
|
|
119
|
+
teamService: teamService(db),
|
|
119
120
|
})
|
|
120
121
|
|
|
121
122
|
return new AppContext(
|
|
@@ -124,6 +125,7 @@ export class AppContext {
|
|
|
124
125
|
cfg,
|
|
125
126
|
modService,
|
|
126
127
|
communicationTemplateService,
|
|
128
|
+
teamService,
|
|
127
129
|
appviewAgent,
|
|
128
130
|
pdsAgent,
|
|
129
131
|
chatAgent,
|
|
@@ -168,6 +170,10 @@ export class AppContext {
|
|
|
168
170
|
return this.opts.communicationTemplateService
|
|
169
171
|
}
|
|
170
172
|
|
|
173
|
+
get teamService(): TeamServiceCreator {
|
|
174
|
+
return this.opts.teamService
|
|
175
|
+
}
|
|
176
|
+
|
|
171
177
|
get appviewAgent(): AtpAgent {
|
|
172
178
|
return this.opts.appviewAgent
|
|
173
179
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Kysely } from 'kysely'
|
|
2
|
+
|
|
3
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
4
|
+
await db.schema
|
|
5
|
+
.createTable('member')
|
|
6
|
+
.addColumn('did', 'varchar', (col) => col.primaryKey())
|
|
7
|
+
.addColumn('role', 'varchar', (col) => col.notNull())
|
|
8
|
+
.addColumn('disabled', 'boolean', (col) => col.defaultTo(false).notNull())
|
|
9
|
+
.addColumn('createdAt', 'timestamptz', (col) => col.notNull())
|
|
10
|
+
.addColumn('updatedAt', 'timestamptz', (col) => col.notNull())
|
|
11
|
+
.addColumn('lastUpdatedBy', 'varchar', (col) => col.notNull())
|
|
12
|
+
.execute()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
16
|
+
await db.schema.dropTable('member')
|
|
17
|
+
}
|
|
@@ -9,3 +9,4 @@ export * as _20240208T213404429Z from './20240208T213404429Z-add-tags-column-to-
|
|
|
9
9
|
export * as _20240228T003647759Z from './20240228T003647759Z-add-label-sigs'
|
|
10
10
|
export * as _20240408T192432676Z from './20240408T192432676Z-mute-reporting'
|
|
11
11
|
export * as _20240506T225055595Z from './20240506T225055595Z-message-subject'
|
|
12
|
+
export * as _20240430T211332580Z from './20240521T211332580Z-member'
|
package/src/db/schema/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ import * as blobPushEvent from './blob_push_event'
|
|
|
7
7
|
import * as label from './label'
|
|
8
8
|
import * as signingKey from './signing_key'
|
|
9
9
|
import * as communicationTemplate from './communication_template'
|
|
10
|
+
import * as member from './member'
|
|
10
11
|
|
|
11
12
|
export type DatabaseSchemaType = modEvent.PartialDB &
|
|
12
13
|
modSubjectStatus.PartialDB &
|
|
@@ -15,7 +16,8 @@ export type DatabaseSchemaType = modEvent.PartialDB &
|
|
|
15
16
|
repoPushEvent.PartialDB &
|
|
16
17
|
recordPushEvent.PartialDB &
|
|
17
18
|
blobPushEvent.PartialDB &
|
|
18
|
-
communicationTemplate.PartialDB
|
|
19
|
+
communicationTemplate.PartialDB &
|
|
20
|
+
member.PartialDB
|
|
19
21
|
|
|
20
22
|
export type DatabaseSchema = Kysely<DatabaseSchemaType>
|
|
21
23
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Generated } from 'kysely'
|
|
2
|
+
|
|
3
|
+
export const memberTableName = 'member'
|
|
4
|
+
|
|
5
|
+
export interface Member {
|
|
6
|
+
did: string
|
|
7
|
+
role:
|
|
8
|
+
| 'tools.ozone.team.defs#roleAdmin'
|
|
9
|
+
| 'tools.ozone.team.defs#roleTriage'
|
|
10
|
+
| 'tools.ozone.team.defs#roleModerator'
|
|
11
|
+
disabled: Generated<boolean>
|
|
12
|
+
createdAt: Date
|
|
13
|
+
updatedAt: Date
|
|
14
|
+
lastUpdatedBy: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type PartialDB = {
|
|
18
|
+
[memberTableName]: Member
|
|
19
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { dbLogger, loggerMiddleware } from './logger'
|
|
|
12
12
|
import { OzoneConfig, OzoneSecrets } from './config'
|
|
13
13
|
import { createServer } from './lexicon'
|
|
14
14
|
import AppContext, { AppContextOptions } from './context'
|
|
15
|
+
import { Member } from './db/schema/member'
|
|
15
16
|
|
|
16
17
|
export * from './config'
|
|
17
18
|
export { type ImageInvalidator } from './image-invalidator'
|
|
@@ -64,10 +65,45 @@ export class OzoneService {
|
|
|
64
65
|
return new OzoneService({ ctx, app })
|
|
65
66
|
}
|
|
66
67
|
|
|
68
|
+
async seedInitialMembers() {
|
|
69
|
+
const members: Array<{ role: Member['role']; did: string }> = []
|
|
70
|
+
this.ctx.cfg.access.admins.forEach((did) =>
|
|
71
|
+
members.push({
|
|
72
|
+
role: 'tools.ozone.team.defs#roleAdmin',
|
|
73
|
+
did,
|
|
74
|
+
}),
|
|
75
|
+
)
|
|
76
|
+
this.ctx.cfg.access.triage.forEach((did) =>
|
|
77
|
+
members.push({
|
|
78
|
+
role: 'tools.ozone.team.defs#roleTriage',
|
|
79
|
+
did,
|
|
80
|
+
}),
|
|
81
|
+
)
|
|
82
|
+
this.ctx.cfg.access.moderators.forEach((did) =>
|
|
83
|
+
members.push({
|
|
84
|
+
role: 'tools.ozone.team.defs#roleModerator',
|
|
85
|
+
did,
|
|
86
|
+
}),
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
for (const member of members) {
|
|
90
|
+
const service = this.ctx.teamService(this.ctx.db)
|
|
91
|
+
await service.upsert({
|
|
92
|
+
...member,
|
|
93
|
+
lastUpdatedBy: this.ctx.cfg.service.did,
|
|
94
|
+
})
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
67
98
|
async start(): Promise<http.Server> {
|
|
68
99
|
if (this.dbStatsInterval) {
|
|
69
100
|
throw new Error(`${this.constructor.name} already started`)
|
|
70
101
|
}
|
|
102
|
+
|
|
103
|
+
// Any moderator that are configured via env var may not exist in the database
|
|
104
|
+
// so we need to sync them from env var to the database
|
|
105
|
+
await this.seedInitialMembers()
|
|
106
|
+
|
|
71
107
|
const { db, backgroundQueue } = this.ctx
|
|
72
108
|
this.dbStatsInterval = setInterval(() => {
|
|
73
109
|
dbLogger.info(
|
package/src/lexicon/index.ts
CHANGED
|
@@ -163,6 +163,10 @@ import * as ToolsOzoneModerationQueryEvents from './types/tools/ozone/moderation
|
|
|
163
163
|
import * as ToolsOzoneModerationQueryStatuses from './types/tools/ozone/moderation/queryStatuses'
|
|
164
164
|
import * as ToolsOzoneModerationSearchRepos from './types/tools/ozone/moderation/searchRepos'
|
|
165
165
|
import * as ToolsOzoneServerGetConfig from './types/tools/ozone/server/getConfig'
|
|
166
|
+
import * as ToolsOzoneTeamAddMember from './types/tools/ozone/team/addMember'
|
|
167
|
+
import * as ToolsOzoneTeamDeleteMember from './types/tools/ozone/team/deleteMember'
|
|
168
|
+
import * as ToolsOzoneTeamListMembers from './types/tools/ozone/team/listMembers'
|
|
169
|
+
import * as ToolsOzoneTeamUpdateMember from './types/tools/ozone/team/updateMember'
|
|
166
170
|
|
|
167
171
|
export const COM_ATPROTO_MODERATION = {
|
|
168
172
|
DefsReasonSpam: 'com.atproto.moderation.defs#reasonSpam',
|
|
@@ -197,6 +201,11 @@ export const TOOLS_OZONE_MODERATION = {
|
|
|
197
201
|
DefsReviewClosed: 'tools.ozone.moderation.defs#reviewClosed',
|
|
198
202
|
DefsReviewNone: 'tools.ozone.moderation.defs#reviewNone',
|
|
199
203
|
}
|
|
204
|
+
export const TOOLS_OZONE_TEAM = {
|
|
205
|
+
DefsRoleAdmin: 'tools.ozone.team.defs#roleAdmin',
|
|
206
|
+
DefsRoleModerator: 'tools.ozone.team.defs#roleModerator',
|
|
207
|
+
DefsRoleTriage: 'tools.ozone.team.defs#roleTriage',
|
|
208
|
+
}
|
|
200
209
|
|
|
201
210
|
export function createServer(options?: XrpcOptions): Server {
|
|
202
211
|
return new Server(options)
|
|
@@ -2043,12 +2052,14 @@ export class ToolsOzoneNS {
|
|
|
2043
2052
|
communication: ToolsOzoneCommunicationNS
|
|
2044
2053
|
moderation: ToolsOzoneModerationNS
|
|
2045
2054
|
server: ToolsOzoneServerNS
|
|
2055
|
+
team: ToolsOzoneTeamNS
|
|
2046
2056
|
|
|
2047
2057
|
constructor(server: Server) {
|
|
2048
2058
|
this._server = server
|
|
2049
2059
|
this.communication = new ToolsOzoneCommunicationNS(server)
|
|
2050
2060
|
this.moderation = new ToolsOzoneModerationNS(server)
|
|
2051
2061
|
this.server = new ToolsOzoneServerNS(server)
|
|
2062
|
+
this.team = new ToolsOzoneTeamNS(server)
|
|
2052
2063
|
}
|
|
2053
2064
|
}
|
|
2054
2065
|
|
|
@@ -2208,6 +2219,58 @@ export class ToolsOzoneServerNS {
|
|
|
2208
2219
|
}
|
|
2209
2220
|
}
|
|
2210
2221
|
|
|
2222
|
+
export class ToolsOzoneTeamNS {
|
|
2223
|
+
_server: Server
|
|
2224
|
+
|
|
2225
|
+
constructor(server: Server) {
|
|
2226
|
+
this._server = server
|
|
2227
|
+
}
|
|
2228
|
+
|
|
2229
|
+
addMember<AV extends AuthVerifier>(
|
|
2230
|
+
cfg: ConfigOf<
|
|
2231
|
+
AV,
|
|
2232
|
+
ToolsOzoneTeamAddMember.Handler<ExtractAuth<AV>>,
|
|
2233
|
+
ToolsOzoneTeamAddMember.HandlerReqCtx<ExtractAuth<AV>>
|
|
2234
|
+
>,
|
|
2235
|
+
) {
|
|
2236
|
+
const nsid = 'tools.ozone.team.addMember' // @ts-ignore
|
|
2237
|
+
return this._server.xrpc.method(nsid, cfg)
|
|
2238
|
+
}
|
|
2239
|
+
|
|
2240
|
+
deleteMember<AV extends AuthVerifier>(
|
|
2241
|
+
cfg: ConfigOf<
|
|
2242
|
+
AV,
|
|
2243
|
+
ToolsOzoneTeamDeleteMember.Handler<ExtractAuth<AV>>,
|
|
2244
|
+
ToolsOzoneTeamDeleteMember.HandlerReqCtx<ExtractAuth<AV>>
|
|
2245
|
+
>,
|
|
2246
|
+
) {
|
|
2247
|
+
const nsid = 'tools.ozone.team.deleteMember' // @ts-ignore
|
|
2248
|
+
return this._server.xrpc.method(nsid, cfg)
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
listMembers<AV extends AuthVerifier>(
|
|
2252
|
+
cfg: ConfigOf<
|
|
2253
|
+
AV,
|
|
2254
|
+
ToolsOzoneTeamListMembers.Handler<ExtractAuth<AV>>,
|
|
2255
|
+
ToolsOzoneTeamListMembers.HandlerReqCtx<ExtractAuth<AV>>
|
|
2256
|
+
>,
|
|
2257
|
+
) {
|
|
2258
|
+
const nsid = 'tools.ozone.team.listMembers' // @ts-ignore
|
|
2259
|
+
return this._server.xrpc.method(nsid, cfg)
|
|
2260
|
+
}
|
|
2261
|
+
|
|
2262
|
+
updateMember<AV extends AuthVerifier>(
|
|
2263
|
+
cfg: ConfigOf<
|
|
2264
|
+
AV,
|
|
2265
|
+
ToolsOzoneTeamUpdateMember.Handler<ExtractAuth<AV>>,
|
|
2266
|
+
ToolsOzoneTeamUpdateMember.HandlerReqCtx<ExtractAuth<AV>>
|
|
2267
|
+
>,
|
|
2268
|
+
) {
|
|
2269
|
+
const nsid = 'tools.ozone.team.updateMember' // @ts-ignore
|
|
2270
|
+
return this._server.xrpc.method(nsid, cfg)
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
|
|
2211
2274
|
type SharedRateLimitOpts<T> = {
|
|
2212
2275
|
name: string
|
|
2213
2276
|
calcKey?: (ctx: T) => string
|
package/src/lexicon/lexicons.ts
CHANGED
|
@@ -11006,6 +11006,226 @@ export const schemaDict = {
|
|
|
11006
11006
|
},
|
|
11007
11007
|
},
|
|
11008
11008
|
},
|
|
11009
|
+
ToolsOzoneTeamAddMember: {
|
|
11010
|
+
lexicon: 1,
|
|
11011
|
+
id: 'tools.ozone.team.addMember',
|
|
11012
|
+
defs: {
|
|
11013
|
+
main: {
|
|
11014
|
+
type: 'procedure',
|
|
11015
|
+
description: 'Add a member to the ozone team. Requires admin role.',
|
|
11016
|
+
input: {
|
|
11017
|
+
encoding: 'application/json',
|
|
11018
|
+
schema: {
|
|
11019
|
+
type: 'object',
|
|
11020
|
+
required: ['did', 'role'],
|
|
11021
|
+
properties: {
|
|
11022
|
+
did: {
|
|
11023
|
+
type: 'string',
|
|
11024
|
+
format: 'did',
|
|
11025
|
+
},
|
|
11026
|
+
role: {
|
|
11027
|
+
type: 'string',
|
|
11028
|
+
knownValues: [
|
|
11029
|
+
'tools.ozone.team.defs#roleAdmin',
|
|
11030
|
+
'tools.ozone.team.defs#roleModerator',
|
|
11031
|
+
'tools.ozone.team.defs#roleTriage',
|
|
11032
|
+
],
|
|
11033
|
+
},
|
|
11034
|
+
},
|
|
11035
|
+
},
|
|
11036
|
+
},
|
|
11037
|
+
output: {
|
|
11038
|
+
encoding: 'application/json',
|
|
11039
|
+
schema: {
|
|
11040
|
+
type: 'ref',
|
|
11041
|
+
ref: 'lex:tools.ozone.team.defs#member',
|
|
11042
|
+
},
|
|
11043
|
+
},
|
|
11044
|
+
errors: [
|
|
11045
|
+
{
|
|
11046
|
+
name: 'MemberAlreadyExists',
|
|
11047
|
+
description: 'Member already exists in the team.',
|
|
11048
|
+
},
|
|
11049
|
+
],
|
|
11050
|
+
},
|
|
11051
|
+
},
|
|
11052
|
+
},
|
|
11053
|
+
ToolsOzoneTeamDefs: {
|
|
11054
|
+
lexicon: 1,
|
|
11055
|
+
id: 'tools.ozone.team.defs',
|
|
11056
|
+
defs: {
|
|
11057
|
+
member: {
|
|
11058
|
+
type: 'object',
|
|
11059
|
+
required: ['did', 'role'],
|
|
11060
|
+
properties: {
|
|
11061
|
+
did: {
|
|
11062
|
+
type: 'string',
|
|
11063
|
+
format: 'did',
|
|
11064
|
+
},
|
|
11065
|
+
disabled: {
|
|
11066
|
+
type: 'boolean',
|
|
11067
|
+
},
|
|
11068
|
+
profile: {
|
|
11069
|
+
type: 'ref',
|
|
11070
|
+
ref: 'lex:app.bsky.actor.defs#profileViewDetailed',
|
|
11071
|
+
},
|
|
11072
|
+
createdAt: {
|
|
11073
|
+
type: 'string',
|
|
11074
|
+
format: 'datetime',
|
|
11075
|
+
},
|
|
11076
|
+
updatedAt: {
|
|
11077
|
+
type: 'string',
|
|
11078
|
+
format: 'datetime',
|
|
11079
|
+
},
|
|
11080
|
+
lastUpdatedBy: {
|
|
11081
|
+
type: 'string',
|
|
11082
|
+
},
|
|
11083
|
+
role: {
|
|
11084
|
+
type: 'string',
|
|
11085
|
+
knownValues: [
|
|
11086
|
+
'lex:tools.ozone.team.defs#roleAdmin',
|
|
11087
|
+
'lex:tools.ozone.team.defs#roleModerator',
|
|
11088
|
+
'lex:tools.ozone.team.defs#roleTriage',
|
|
11089
|
+
],
|
|
11090
|
+
},
|
|
11091
|
+
},
|
|
11092
|
+
},
|
|
11093
|
+
roleAdmin: {
|
|
11094
|
+
type: 'token',
|
|
11095
|
+
description:
|
|
11096
|
+
'Admin role. Highest level of access, can perform all actions.',
|
|
11097
|
+
},
|
|
11098
|
+
roleModerator: {
|
|
11099
|
+
type: 'token',
|
|
11100
|
+
description: 'Moderator role. Can perform most actions.',
|
|
11101
|
+
},
|
|
11102
|
+
roleTriage: {
|
|
11103
|
+
type: 'token',
|
|
11104
|
+
description:
|
|
11105
|
+
'Triage role. Mostly intended for monitoring and escalating issues.',
|
|
11106
|
+
},
|
|
11107
|
+
},
|
|
11108
|
+
},
|
|
11109
|
+
ToolsOzoneTeamDeleteMember: {
|
|
11110
|
+
lexicon: 1,
|
|
11111
|
+
id: 'tools.ozone.team.deleteMember',
|
|
11112
|
+
defs: {
|
|
11113
|
+
main: {
|
|
11114
|
+
type: 'procedure',
|
|
11115
|
+
description: 'Delete a member from ozone team. Requires admin role.',
|
|
11116
|
+
input: {
|
|
11117
|
+
encoding: 'application/json',
|
|
11118
|
+
schema: {
|
|
11119
|
+
type: 'object',
|
|
11120
|
+
required: ['did'],
|
|
11121
|
+
properties: {
|
|
11122
|
+
did: {
|
|
11123
|
+
type: 'string',
|
|
11124
|
+
format: 'did',
|
|
11125
|
+
},
|
|
11126
|
+
},
|
|
11127
|
+
},
|
|
11128
|
+
},
|
|
11129
|
+
errors: [
|
|
11130
|
+
{
|
|
11131
|
+
name: 'MemberNotFound',
|
|
11132
|
+
description: 'The member being deleted does not exist',
|
|
11133
|
+
},
|
|
11134
|
+
],
|
|
11135
|
+
},
|
|
11136
|
+
},
|
|
11137
|
+
},
|
|
11138
|
+
ToolsOzoneTeamListMembers: {
|
|
11139
|
+
lexicon: 1,
|
|
11140
|
+
id: 'tools.ozone.team.listMembers',
|
|
11141
|
+
defs: {
|
|
11142
|
+
main: {
|
|
11143
|
+
type: 'query',
|
|
11144
|
+
description: 'List all members with access to the ozone service.',
|
|
11145
|
+
parameters: {
|
|
11146
|
+
type: 'params',
|
|
11147
|
+
properties: {
|
|
11148
|
+
limit: {
|
|
11149
|
+
type: 'integer',
|
|
11150
|
+
minimum: 1,
|
|
11151
|
+
maximum: 100,
|
|
11152
|
+
default: 50,
|
|
11153
|
+
},
|
|
11154
|
+
cursor: {
|
|
11155
|
+
type: 'string',
|
|
11156
|
+
},
|
|
11157
|
+
},
|
|
11158
|
+
},
|
|
11159
|
+
output: {
|
|
11160
|
+
encoding: 'application/json',
|
|
11161
|
+
schema: {
|
|
11162
|
+
type: 'object',
|
|
11163
|
+
required: ['members'],
|
|
11164
|
+
properties: {
|
|
11165
|
+
cursor: {
|
|
11166
|
+
type: 'string',
|
|
11167
|
+
},
|
|
11168
|
+
members: {
|
|
11169
|
+
type: 'array',
|
|
11170
|
+
items: {
|
|
11171
|
+
type: 'ref',
|
|
11172
|
+
ref: 'lex:tools.ozone.team.defs#member',
|
|
11173
|
+
},
|
|
11174
|
+
},
|
|
11175
|
+
},
|
|
11176
|
+
},
|
|
11177
|
+
},
|
|
11178
|
+
},
|
|
11179
|
+
},
|
|
11180
|
+
},
|
|
11181
|
+
ToolsOzoneTeamUpdateMember: {
|
|
11182
|
+
lexicon: 1,
|
|
11183
|
+
id: 'tools.ozone.team.updateMember',
|
|
11184
|
+
defs: {
|
|
11185
|
+
main: {
|
|
11186
|
+
type: 'procedure',
|
|
11187
|
+
description:
|
|
11188
|
+
'Update a member in the ozone service. Requires admin role.',
|
|
11189
|
+
input: {
|
|
11190
|
+
encoding: 'application/json',
|
|
11191
|
+
schema: {
|
|
11192
|
+
type: 'object',
|
|
11193
|
+
required: ['did'],
|
|
11194
|
+
properties: {
|
|
11195
|
+
did: {
|
|
11196
|
+
type: 'string',
|
|
11197
|
+
format: 'did',
|
|
11198
|
+
},
|
|
11199
|
+
disabled: {
|
|
11200
|
+
type: 'boolean',
|
|
11201
|
+
},
|
|
11202
|
+
role: {
|
|
11203
|
+
type: 'string',
|
|
11204
|
+
knownValues: [
|
|
11205
|
+
'tools.ozone.team.defs#roleAdmin',
|
|
11206
|
+
'tools.ozone.team.defs#roleModerator',
|
|
11207
|
+
'tools.ozone.team.defs#roleTriage',
|
|
11208
|
+
],
|
|
11209
|
+
},
|
|
11210
|
+
},
|
|
11211
|
+
},
|
|
11212
|
+
},
|
|
11213
|
+
output: {
|
|
11214
|
+
encoding: 'application/json',
|
|
11215
|
+
schema: {
|
|
11216
|
+
type: 'ref',
|
|
11217
|
+
ref: 'lex:tools.ozone.team.defs#member',
|
|
11218
|
+
},
|
|
11219
|
+
},
|
|
11220
|
+
errors: [
|
|
11221
|
+
{
|
|
11222
|
+
name: 'MemberNotFound',
|
|
11223
|
+
description: 'The member being updated does not exist in the team',
|
|
11224
|
+
},
|
|
11225
|
+
],
|
|
11226
|
+
},
|
|
11227
|
+
},
|
|
11228
|
+
},
|
|
11009
11229
|
}
|
|
11010
11230
|
export const schemas: LexiconDoc[] = Object.values(schemaDict) as LexiconDoc[]
|
|
11011
11231
|
export const lexicons: Lexicons = new Lexicons(schemas)
|
|
@@ -11216,4 +11436,9 @@ export const ids = {
|
|
|
11216
11436
|
ToolsOzoneModerationQueryStatuses: 'tools.ozone.moderation.queryStatuses',
|
|
11217
11437
|
ToolsOzoneModerationSearchRepos: 'tools.ozone.moderation.searchRepos',
|
|
11218
11438
|
ToolsOzoneServerGetConfig: 'tools.ozone.server.getConfig',
|
|
11439
|
+
ToolsOzoneTeamAddMember: 'tools.ozone.team.addMember',
|
|
11440
|
+
ToolsOzoneTeamDefs: 'tools.ozone.team.defs',
|
|
11441
|
+
ToolsOzoneTeamDeleteMember: 'tools.ozone.team.deleteMember',
|
|
11442
|
+
ToolsOzoneTeamListMembers: 'tools.ozone.team.listMembers',
|
|
11443
|
+
ToolsOzoneTeamUpdateMember: 'tools.ozone.team.updateMember',
|
|
11219
11444
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED CODE - DO NOT MODIFY
|
|
3
|
+
*/
|
|
4
|
+
import express from 'express'
|
|
5
|
+
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
|
6
|
+
import { lexicons } from '../../../../lexicons'
|
|
7
|
+
import { isObj, hasProp } from '../../../../util'
|
|
8
|
+
import { CID } from 'multiformats/cid'
|
|
9
|
+
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
|
10
|
+
import * as ToolsOzoneTeamDefs from './defs'
|
|
11
|
+
|
|
12
|
+
export interface QueryParams {}
|
|
13
|
+
|
|
14
|
+
export interface InputSchema {
|
|
15
|
+
did: string
|
|
16
|
+
role:
|
|
17
|
+
| 'tools.ozone.team.defs#roleAdmin'
|
|
18
|
+
| 'tools.ozone.team.defs#roleModerator'
|
|
19
|
+
| 'tools.ozone.team.defs#roleTriage'
|
|
20
|
+
| (string & {})
|
|
21
|
+
[k: string]: unknown
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type OutputSchema = ToolsOzoneTeamDefs.Member
|
|
25
|
+
|
|
26
|
+
export interface HandlerInput {
|
|
27
|
+
encoding: 'application/json'
|
|
28
|
+
body: InputSchema
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface HandlerSuccess {
|
|
32
|
+
encoding: 'application/json'
|
|
33
|
+
body: OutputSchema
|
|
34
|
+
headers?: { [key: string]: string }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface HandlerError {
|
|
38
|
+
status: number
|
|
39
|
+
message?: string
|
|
40
|
+
error?: 'MemberAlreadyExists'
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
|
|
44
|
+
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
|
45
|
+
auth: HA
|
|
46
|
+
params: QueryParams
|
|
47
|
+
input: HandlerInput
|
|
48
|
+
req: express.Request
|
|
49
|
+
res: express.Response
|
|
50
|
+
}
|
|
51
|
+
export type Handler<HA extends HandlerAuth = never> = (
|
|
52
|
+
ctx: HandlerReqCtx<HA>,
|
|
53
|
+
) => Promise<HandlerOutput> | HandlerOutput
|