@atproto/ozone 0.1.37 → 0.1.38
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/chat/getActorMetadata.d.ts.map +1 -1
- package/dist/api/chat/getActorMetadata.js +2 -1
- package/dist/api/chat/getActorMetadata.js.map +1 -1
- package/dist/api/chat/getMessageContext.d.ts.map +1 -1
- package/dist/api/chat/getMessageContext.js +2 -1
- package/dist/api/chat/getMessageContext.js.map +1 -1
- package/dist/api/moderation/searchRepos.d.ts.map +1 -1
- package/dist/api/moderation/searchRepos.js +2 -1
- package/dist/api/moderation/searchRepos.js.map +1 -1
- package/dist/api/proxied.d.ts.map +1 -1
- package/dist/api/proxied.js +18 -17
- package/dist/api/proxied.js.map +1 -1
- package/dist/api/util.d.ts.map +1 -1
- package/dist/api/util.js +2 -1
- package/dist/api/util.js.map +1 -1
- package/dist/auth-verifier.d.ts.map +1 -1
- package/dist/auth-verifier.js +2 -1
- package/dist/auth-verifier.js.map +1 -1
- package/dist/context.d.ts +4 -4
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +10 -10
- package/dist/context.js.map +1 -1
- package/dist/daemon/context.js +2 -2
- package/dist/daemon/context.js.map +1 -1
- package/dist/daemon/event-pusher.d.ts +2 -2
- package/dist/daemon/event-pusher.d.ts.map +1 -1
- package/dist/daemon/event-pusher.js +2 -1
- package/dist/daemon/event-pusher.js.map +1 -1
- package/dist/db/migrations/20240814T003647759Z-event-created-at-index.d.ts +4 -0
- package/dist/db/migrations/20240814T003647759Z-event-created-at-index.d.ts.map +1 -0
- package/dist/db/migrations/20240814T003647759Z-event-created-at-index.js +16 -0
- package/dist/db/migrations/20240814T003647759Z-event-created-at-index.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/mod-service/index.d.ts +2 -2
- package/dist/mod-service/index.d.ts.map +1 -1
- package/dist/mod-service/index.js +4 -3
- package/dist/mod-service/index.js.map +1 -1
- package/dist/mod-service/views.d.ts +1 -1
- package/dist/mod-service/views.d.ts.map +1 -1
- package/dist/mod-service/views.js +4 -3
- package/dist/mod-service/views.js.map +1 -1
- package/dist/team/index.d.ts.map +1 -1
- package/dist/team/index.js +2 -1
- package/dist/team/index.js.map +1 -1
- package/package.json +3 -3
- package/src/api/chat/getActorMetadata.ts +2 -1
- package/src/api/chat/getMessageContext.ts +2 -1
- package/src/api/moderation/searchRepos.ts +2 -1
- package/src/api/proxied.ts +18 -17
- package/src/api/util.ts +2 -1
- package/src/auth-verifier.ts +7 -2
- package/src/context.ts +10 -10
- package/src/daemon/context.ts +2 -2
- package/src/daemon/event-pusher.ts +9 -2
- package/src/db/migrations/20240814T003647759Z-event-created-at-index.ts +13 -0
- package/src/db/migrations/index.ts +1 -0
- package/src/mod-service/index.ts +15 -5
- package/src/mod-service/views.ts +5 -4
- package/src/team/index.ts +2 -1
- package/tests/3p-labeler.test.ts +23 -6
- package/tests/communication-templates.test.ts +29 -7
- package/tests/get-config.test.ts +5 -1
- package/tests/get-lists.test.ts +2 -1
- package/tests/get-record.test.ts +5 -4
- package/tests/get-repo.test.ts +19 -8
- package/tests/get-starter-pack.test.ts +15 -4
- package/tests/moderation.test.ts +11 -2
- package/tests/repo-search.test.ts +4 -1
package/src/api/proxied.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Server } from '../lexicon'
|
|
2
2
|
import AppContext from '../context'
|
|
3
|
+
import { ids } from '../lexicon/lexicons'
|
|
3
4
|
|
|
4
5
|
export default function (server: Server, ctx: AppContext) {
|
|
5
6
|
server.app.bsky.actor.getProfile({
|
|
@@ -7,7 +8,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
7
8
|
handler: async (request) => {
|
|
8
9
|
const res = await ctx.appviewAgent.api.app.bsky.actor.getProfile(
|
|
9
10
|
request.params,
|
|
10
|
-
await ctx.appviewAuth(),
|
|
11
|
+
await ctx.appviewAuth(ids.AppBskyActorGetProfile),
|
|
11
12
|
)
|
|
12
13
|
return {
|
|
13
14
|
encoding: 'application/json',
|
|
@@ -21,7 +22,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
21
22
|
handler: async (request) => {
|
|
22
23
|
const res = await ctx.appviewAgent.api.app.bsky.actor.getProfiles(
|
|
23
24
|
request.params,
|
|
24
|
-
await ctx.appviewAuth(),
|
|
25
|
+
await ctx.appviewAuth(ids.AppBskyActorGetProfiles),
|
|
25
26
|
)
|
|
26
27
|
return {
|
|
27
28
|
encoding: 'application/json',
|
|
@@ -35,7 +36,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
35
36
|
handler: async (request) => {
|
|
36
37
|
const res = await ctx.appviewAgent.api.app.bsky.feed.getAuthorFeed(
|
|
37
38
|
request.params,
|
|
38
|
-
await ctx.appviewAuth(),
|
|
39
|
+
await ctx.appviewAuth(ids.AppBskyFeedGetAuthorFeed),
|
|
39
40
|
)
|
|
40
41
|
return {
|
|
41
42
|
encoding: 'application/json',
|
|
@@ -49,7 +50,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
49
50
|
handler: async (request) => {
|
|
50
51
|
const res = await ctx.appviewAgent.api.app.bsky.feed.searchPosts(
|
|
51
52
|
request.params,
|
|
52
|
-
await ctx.appviewAuth(),
|
|
53
|
+
await ctx.appviewAuth(ids.AppBskyFeedSearchPosts),
|
|
53
54
|
)
|
|
54
55
|
return {
|
|
55
56
|
encoding: 'application/json',
|
|
@@ -63,7 +64,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
63
64
|
handler: async (request) => {
|
|
64
65
|
const res = await ctx.appviewAgent.api.app.bsky.feed.getPostThread(
|
|
65
66
|
request.params,
|
|
66
|
-
await ctx.appviewAuth(),
|
|
67
|
+
await ctx.appviewAuth(ids.AppBskyFeedGetPostThread),
|
|
67
68
|
)
|
|
68
69
|
return {
|
|
69
70
|
encoding: 'application/json',
|
|
@@ -77,7 +78,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
77
78
|
handler: async (request) => {
|
|
78
79
|
const res = await ctx.appviewAgent.api.app.bsky.feed.getFeedGenerator(
|
|
79
80
|
request.params,
|
|
80
|
-
await ctx.appviewAuth(),
|
|
81
|
+
await ctx.appviewAuth(ids.AppBskyFeedGetFeedGenerator),
|
|
81
82
|
)
|
|
82
83
|
return {
|
|
83
84
|
encoding: 'application/json',
|
|
@@ -91,7 +92,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
91
92
|
handler: async (request) => {
|
|
92
93
|
const res = await ctx.appviewAgent.api.app.bsky.graph.getFollows(
|
|
93
94
|
request.params,
|
|
94
|
-
await ctx.appviewAuth(),
|
|
95
|
+
await ctx.appviewAuth(ids.AppBskyGraphGetFollows),
|
|
95
96
|
)
|
|
96
97
|
return {
|
|
97
98
|
encoding: 'application/json',
|
|
@@ -105,7 +106,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
105
106
|
handler: async (request) => {
|
|
106
107
|
const res = await ctx.appviewAgent.api.app.bsky.graph.getFollowers(
|
|
107
108
|
request.params,
|
|
108
|
-
await ctx.appviewAuth(),
|
|
109
|
+
await ctx.appviewAuth(ids.AppBskyGraphGetFollowers),
|
|
109
110
|
)
|
|
110
111
|
return {
|
|
111
112
|
encoding: 'application/json',
|
|
@@ -119,7 +120,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
119
120
|
handler: async (request) => {
|
|
120
121
|
const res = await ctx.appviewAgent.api.app.bsky.graph.getList(
|
|
121
122
|
request.params,
|
|
122
|
-
await ctx.appviewAuth(),
|
|
123
|
+
await ctx.appviewAuth(ids.AppBskyGraphGetList),
|
|
123
124
|
)
|
|
124
125
|
return {
|
|
125
126
|
encoding: 'application/json',
|
|
@@ -133,7 +134,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
133
134
|
handler: async (request) => {
|
|
134
135
|
const res = await ctx.appviewAgent.api.app.bsky.graph.getLists(
|
|
135
136
|
request.params,
|
|
136
|
-
await ctx.appviewAuth(),
|
|
137
|
+
await ctx.appviewAuth(ids.AppBskyGraphGetLists),
|
|
137
138
|
)
|
|
138
139
|
return {
|
|
139
140
|
encoding: 'application/json',
|
|
@@ -150,7 +151,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
150
151
|
}
|
|
151
152
|
const res = await ctx.pdsAgent.api.com.atproto.admin.searchAccounts(
|
|
152
153
|
request.params,
|
|
153
|
-
await ctx.pdsAuth(),
|
|
154
|
+
await ctx.pdsAuth(ids.ComAtprotoAdminSearchAccounts),
|
|
154
155
|
)
|
|
155
156
|
return {
|
|
156
157
|
encoding: 'application/json',
|
|
@@ -164,7 +165,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
164
165
|
handler: async (request) => {
|
|
165
166
|
const res = await ctx.appviewAgent.api.app.bsky.graph.getStarterPack(
|
|
166
167
|
request.params,
|
|
167
|
-
await ctx.appviewAuth(),
|
|
168
|
+
await ctx.appviewAuth(ids.AppBskyGraphGetStarterPack),
|
|
168
169
|
)
|
|
169
170
|
return {
|
|
170
171
|
encoding: 'application/json',
|
|
@@ -178,7 +179,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
178
179
|
handler: async (request) => {
|
|
179
180
|
const res = await ctx.appviewAgent.api.app.bsky.graph.getStarterPacks(
|
|
180
181
|
request.params,
|
|
181
|
-
await ctx.appviewAuth(),
|
|
182
|
+
await ctx.appviewAuth(ids.AppBskyGraphGetStarterPacks),
|
|
182
183
|
)
|
|
183
184
|
return {
|
|
184
185
|
encoding: 'application/json',
|
|
@@ -193,7 +194,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
193
194
|
const res =
|
|
194
195
|
await ctx.appviewAgent.api.app.bsky.graph.getActorStarterPacks(
|
|
195
196
|
request.params,
|
|
196
|
-
await ctx.appviewAuth(),
|
|
197
|
+
await ctx.appviewAuth(ids.AppBskyGraphGetActorStarterPacks),
|
|
197
198
|
)
|
|
198
199
|
return {
|
|
199
200
|
encoding: 'application/json',
|
|
@@ -207,7 +208,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
207
208
|
handler: async (request) => {
|
|
208
209
|
const res = await ctx.appviewAgent.api.app.bsky.feed.getLikes(
|
|
209
210
|
request.params,
|
|
210
|
-
await ctx.appviewAuth(),
|
|
211
|
+
await ctx.appviewAuth(ids.AppBskyFeedGetLikes),
|
|
211
212
|
)
|
|
212
213
|
return {
|
|
213
214
|
encoding: 'application/json',
|
|
@@ -221,7 +222,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
221
222
|
handler: async (request) => {
|
|
222
223
|
const res = await ctx.appviewAgent.api.app.bsky.feed.getRepostedBy(
|
|
223
224
|
request.params,
|
|
224
|
-
await ctx.appviewAuth(),
|
|
225
|
+
await ctx.appviewAuth(ids.AppBskyFeedGetRepostedBy),
|
|
225
226
|
)
|
|
226
227
|
return {
|
|
227
228
|
encoding: 'application/json',
|
|
@@ -236,7 +237,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
236
237
|
const res =
|
|
237
238
|
await ctx.appviewAgent.api.app.bsky.actor.searchActorsTypeahead(
|
|
238
239
|
request.params,
|
|
239
|
-
await ctx.appviewAuth(),
|
|
240
|
+
await ctx.appviewAuth(ids.AppBskyActorSearchActorsTypeahead),
|
|
240
241
|
)
|
|
241
242
|
return {
|
|
242
243
|
encoding: 'application/json',
|
package/src/api/util.ts
CHANGED
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
ROLEMODERATOR,
|
|
27
27
|
ROLETRIAGE,
|
|
28
28
|
} from '../lexicon/types/tools/ozone/team/defs'
|
|
29
|
+
import { ids } from '../lexicon/lexicons'
|
|
29
30
|
|
|
30
31
|
export const getPdsAccountInfo = async (
|
|
31
32
|
ctx: AppContext,
|
|
@@ -33,7 +34,7 @@ export const getPdsAccountInfo = async (
|
|
|
33
34
|
): Promise<AccountView | null> => {
|
|
34
35
|
const agent = ctx.pdsAgent
|
|
35
36
|
if (!agent) return null
|
|
36
|
-
const auth = await ctx.pdsAuth()
|
|
37
|
+
const auth = await ctx.pdsAuth(ids.ComAtprotoAdminGetAccountInfo)
|
|
37
38
|
if (!auth) return null
|
|
38
39
|
try {
|
|
39
40
|
const res = await agent.api.com.atproto.admin.getAccountInfo({ did }, auth)
|
package/src/auth-verifier.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import express from 'express'
|
|
2
2
|
import * as ui8 from 'uint8arrays'
|
|
3
3
|
import { IdResolver } from '@atproto/identity'
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
AuthRequiredError,
|
|
6
|
+
parseReqNsid,
|
|
7
|
+
verifyJwt,
|
|
8
|
+
} from '@atproto/xrpc-server'
|
|
5
9
|
import { TeamService } from './team'
|
|
6
10
|
|
|
7
11
|
type ReqCtx = {
|
|
@@ -106,10 +110,11 @@ export class AuthVerifier {
|
|
|
106
110
|
if (!jwtStr) {
|
|
107
111
|
throw new AuthRequiredError('missing jwt', 'MissingJwt')
|
|
108
112
|
}
|
|
113
|
+
const nsid = parseReqNsid(reqCtx.req)
|
|
109
114
|
const payload = await verifyJwt(
|
|
110
115
|
jwtStr,
|
|
111
116
|
this.serviceDid,
|
|
112
|
-
|
|
117
|
+
nsid,
|
|
113
118
|
getSigningKey,
|
|
114
119
|
)
|
|
115
120
|
const iss = payload.iss
|
package/src/context.ts
CHANGED
|
@@ -84,11 +84,11 @@ export class AppContext {
|
|
|
84
84
|
didCache,
|
|
85
85
|
})
|
|
86
86
|
|
|
87
|
-
const createAuthHeaders = (aud: string) =>
|
|
87
|
+
const createAuthHeaders = (aud: string, lxm: string) =>
|
|
88
88
|
createServiceAuthHeaders({
|
|
89
89
|
iss: `${cfg.service.did}#atproto_labeler`,
|
|
90
90
|
aud,
|
|
91
|
-
lxm
|
|
91
|
+
lxm,
|
|
92
92
|
keypair: signingKey,
|
|
93
93
|
})
|
|
94
94
|
|
|
@@ -226,32 +226,32 @@ export class AppContext {
|
|
|
226
226
|
return this.opts.authVerifier
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
-
async serviceAuthHeaders(aud: string) {
|
|
229
|
+
async serviceAuthHeaders(aud: string, lxm: string) {
|
|
230
230
|
const iss = `${this.cfg.service.did}#atproto_labeler`
|
|
231
231
|
return createServiceAuthHeaders({
|
|
232
232
|
iss,
|
|
233
233
|
aud,
|
|
234
|
-
lxm
|
|
234
|
+
lxm,
|
|
235
235
|
keypair: this.signingKey,
|
|
236
236
|
})
|
|
237
237
|
}
|
|
238
238
|
|
|
239
|
-
async pdsAuth() {
|
|
239
|
+
async pdsAuth(lxm: string) {
|
|
240
240
|
if (!this.cfg.pds) {
|
|
241
241
|
return undefined
|
|
242
242
|
}
|
|
243
|
-
return this.serviceAuthHeaders(this.cfg.pds.did)
|
|
243
|
+
return this.serviceAuthHeaders(this.cfg.pds.did, lxm)
|
|
244
244
|
}
|
|
245
245
|
|
|
246
|
-
async appviewAuth() {
|
|
247
|
-
return this.serviceAuthHeaders(this.cfg.appview.did)
|
|
246
|
+
async appviewAuth(lxm: string) {
|
|
247
|
+
return this.serviceAuthHeaders(this.cfg.appview.did, lxm)
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
-
async chatAuth() {
|
|
250
|
+
async chatAuth(lxm: string) {
|
|
251
251
|
if (!this.cfg.chat) {
|
|
252
252
|
throw new Error('No chat service configured')
|
|
253
253
|
}
|
|
254
|
-
return this.serviceAuthHeaders(this.cfg.chat.did)
|
|
254
|
+
return this.serviceAuthHeaders(this.cfg.chat.did, lxm)
|
|
255
255
|
}
|
|
256
256
|
|
|
257
257
|
devOverride(overrides: Partial<AppContextOptions>) {
|
package/src/daemon/context.ts
CHANGED
|
@@ -39,11 +39,11 @@ export class DaemonContext {
|
|
|
39
39
|
})
|
|
40
40
|
|
|
41
41
|
const appviewAgent = new AtpAgent({ service: cfg.appview.url })
|
|
42
|
-
const createAuthHeaders = (aud: string) =>
|
|
42
|
+
const createAuthHeaders = (aud: string, lxm: string) =>
|
|
43
43
|
createServiceAuthHeaders({
|
|
44
44
|
iss: `${cfg.service.did}#atproto_labeler`,
|
|
45
45
|
aud,
|
|
46
|
-
lxm
|
|
46
|
+
lxm,
|
|
47
47
|
keypair: signingKey,
|
|
48
48
|
})
|
|
49
49
|
|
|
@@ -8,6 +8,7 @@ import { dbLogger } from '../logger'
|
|
|
8
8
|
import { InputSchema } from '../lexicon/types/com/atproto/admin/updateSubjectStatus'
|
|
9
9
|
import { BlobPushEvent } from '../db/schema/blob_push_event'
|
|
10
10
|
import { Insertable, Selectable } from 'kysely'
|
|
11
|
+
import { ids } from '../lexicon/lexicons'
|
|
11
12
|
|
|
12
13
|
type EventSubject = InputSchema['subject']
|
|
13
14
|
|
|
@@ -45,7 +46,10 @@ export class EventPusher {
|
|
|
45
46
|
|
|
46
47
|
constructor(
|
|
47
48
|
public db: Database,
|
|
48
|
-
public createAuthHeaders: (
|
|
49
|
+
public createAuthHeaders: (
|
|
50
|
+
aud: string,
|
|
51
|
+
method: string,
|
|
52
|
+
) => Promise<AuthHeaders>,
|
|
49
53
|
services: {
|
|
50
54
|
appview?: {
|
|
51
55
|
url: string
|
|
@@ -162,7 +166,10 @@ export class EventPusher {
|
|
|
162
166
|
subject: EventSubject,
|
|
163
167
|
takedownRef: string | null,
|
|
164
168
|
): Promise<boolean> {
|
|
165
|
-
const auth = await this.createAuthHeaders(
|
|
169
|
+
const auth = await this.createAuthHeaders(
|
|
170
|
+
service.did,
|
|
171
|
+
ids.ComAtprotoAdminUpdateSubjectStatus,
|
|
172
|
+
)
|
|
166
173
|
try {
|
|
167
174
|
await retryHttp(() =>
|
|
168
175
|
service.agent.com.atproto.admin.updateSubjectStatus(
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Kysely } from 'kysely'
|
|
2
|
+
|
|
3
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
4
|
+
await db.schema
|
|
5
|
+
.createIndex('moderation_event_created_at_idx')
|
|
6
|
+
.on('moderation_event')
|
|
7
|
+
.column('createdAt')
|
|
8
|
+
.execute()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
12
|
+
await db.schema.dropIndex('moderation_event_created_at_idx').execute()
|
|
13
|
+
}
|
|
@@ -10,3 +10,4 @@ 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
12
|
export * as _20240430T211332580Z from './20240521T211332580Z-member'
|
|
13
|
+
export * as _20240814T003647759Z from './20240814T003647759Z-event-created-at-index'
|
package/src/mod-service/index.ts
CHANGED
|
@@ -49,6 +49,7 @@ import { ImageInvalidator } from '../image-invalidator'
|
|
|
49
49
|
import { httpLogger as log } from '../logger'
|
|
50
50
|
import { OzoneConfig } from '../config'
|
|
51
51
|
import { LABELER_HEADER_NAME, ParsedLabelers } from '../util'
|
|
52
|
+
import { ids } from '../lexicon/lexicons'
|
|
52
53
|
|
|
53
54
|
export type ModerationServiceCreator = (db: Database) => ModerationService
|
|
54
55
|
|
|
@@ -62,7 +63,10 @@ export class ModerationService {
|
|
|
62
63
|
public idResolver: IdResolver,
|
|
63
64
|
public eventPusher: EventPusher,
|
|
64
65
|
public appviewAgent: AtpAgent,
|
|
65
|
-
private createAuthHeaders: (
|
|
66
|
+
private createAuthHeaders: (
|
|
67
|
+
aud: string,
|
|
68
|
+
method: string,
|
|
69
|
+
) => Promise<AuthHeaders>,
|
|
66
70
|
public imgInvalidator?: ImageInvalidator,
|
|
67
71
|
) {}
|
|
68
72
|
|
|
@@ -74,7 +78,7 @@ export class ModerationService {
|
|
|
74
78
|
idResolver: IdResolver,
|
|
75
79
|
eventPusher: EventPusher,
|
|
76
80
|
appviewAgent: AtpAgent,
|
|
77
|
-
createAuthHeaders: (aud: string) => Promise<AuthHeaders>,
|
|
81
|
+
createAuthHeaders: (aud: string, method: string) => Promise<AuthHeaders>,
|
|
78
82
|
imgInvalidator?: ImageInvalidator,
|
|
79
83
|
) {
|
|
80
84
|
return (db: Database) =>
|
|
@@ -97,8 +101,11 @@ export class ModerationService {
|
|
|
97
101
|
this.signingKey,
|
|
98
102
|
this.signingKeyId,
|
|
99
103
|
this.appviewAgent,
|
|
100
|
-
async (labelers?: ParsedLabelers) => {
|
|
101
|
-
const authHeaders = await this.createAuthHeaders(
|
|
104
|
+
async (method: string, labelers?: ParsedLabelers) => {
|
|
105
|
+
const authHeaders = await this.createAuthHeaders(
|
|
106
|
+
this.cfg.appview.did,
|
|
107
|
+
method,
|
|
108
|
+
)
|
|
102
109
|
if (labelers?.dids?.length) {
|
|
103
110
|
authHeaders.headers[LABELER_HEADER_NAME] = labelers.dids.join(', ')
|
|
104
111
|
}
|
|
@@ -936,7 +943,10 @@ export class ModerationService {
|
|
|
936
943
|
},
|
|
937
944
|
{
|
|
938
945
|
encoding: 'application/json',
|
|
939
|
-
...(await this.createAuthHeaders(
|
|
946
|
+
...(await this.createAuthHeaders(
|
|
947
|
+
serverInfo.did,
|
|
948
|
+
ids.ComAtprotoAdminSendEmail,
|
|
949
|
+
)),
|
|
940
950
|
},
|
|
941
951
|
)
|
|
942
952
|
if (!delivery.sent) {
|
package/src/mod-service/views.ts
CHANGED
|
@@ -29,6 +29,7 @@ import { LabelRow } from '../db/schema/label'
|
|
|
29
29
|
import { dbLogger } from '../logger'
|
|
30
30
|
import { httpLogger } from '../logger'
|
|
31
31
|
import { ParsedLabelers } from '../util'
|
|
32
|
+
import { ids } from '../lexicon/lexicons'
|
|
32
33
|
|
|
33
34
|
export type AuthHeaders = {
|
|
34
35
|
headers: {
|
|
@@ -43,12 +44,12 @@ export class ModerationViews {
|
|
|
43
44
|
private signingKey: Keypair,
|
|
44
45
|
private signingKeyId: number,
|
|
45
46
|
private appviewAgent: AtpAgent,
|
|
46
|
-
private appviewAuth: () => Promise<AuthHeaders>,
|
|
47
|
+
private appviewAuth: (method: string) => Promise<AuthHeaders>,
|
|
47
48
|
) {}
|
|
48
49
|
|
|
49
50
|
async getAccoutInfosByDid(dids: string[]): Promise<Map<string, AccountView>> {
|
|
50
51
|
if (dids.length === 0) return new Map()
|
|
51
|
-
const auth = await this.appviewAuth()
|
|
52
|
+
const auth = await this.appviewAuth(ids.ComAtprotoAdminGetAccountInfos)
|
|
52
53
|
if (!auth) return new Map()
|
|
53
54
|
try {
|
|
54
55
|
const res = await this.appviewAgent.api.com.atproto.admin.getAccountInfos(
|
|
@@ -236,7 +237,7 @@ export class ModerationViews {
|
|
|
236
237
|
async fetchRecords(
|
|
237
238
|
subjects: RecordSubject[],
|
|
238
239
|
): Promise<Map<string, RecordInfo>> {
|
|
239
|
-
const auth = await this.appviewAuth()
|
|
240
|
+
const auth = await this.appviewAuth(ids.ComAtprotoRepoGetRecord)
|
|
240
241
|
if (!auth) return new Map()
|
|
241
242
|
const fetched = await Promise.all(
|
|
242
243
|
subjects.map(async (subject) => {
|
|
@@ -547,7 +548,7 @@ export class ModerationViews {
|
|
|
547
548
|
async fetchAuthorFeed(
|
|
548
549
|
actor: string,
|
|
549
550
|
): Promise<AppBskyFeedDefs.FeedViewPost[]> {
|
|
550
|
-
const auth = await this.appviewAuth()
|
|
551
|
+
const auth = await this.appviewAuth(ids.AppBskyFeedGetAuthorFeed)
|
|
551
552
|
if (!auth) return []
|
|
552
553
|
const {
|
|
553
554
|
data: { feed },
|
package/src/team/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { InvalidRequestError } from '@atproto/xrpc-server'
|
|
|
7
7
|
import { chunkArray } from '@atproto/common'
|
|
8
8
|
import AppContext from '../context'
|
|
9
9
|
import { httpLogger } from '../logger'
|
|
10
|
+
import { ids } from '../lexicon/lexicons'
|
|
10
11
|
|
|
11
12
|
export type TeamServiceCreator = (db: Database) => TeamService
|
|
12
13
|
|
|
@@ -168,7 +169,7 @@ export class TeamService {
|
|
|
168
169
|
const profiles = new Map<string, ProfileViewDetailed>()
|
|
169
170
|
|
|
170
171
|
try {
|
|
171
|
-
const headers = await ctx.appviewAuth()
|
|
172
|
+
const headers = await ctx.appviewAuth(ids.AppBskyActorGetProfiles)
|
|
172
173
|
|
|
173
174
|
for (const actors of chunkArray(dids, 25)) {
|
|
174
175
|
const { data } = await ctx.appviewAgent.api.app.bsky.actor.getProfiles(
|
package/tests/3p-labeler.test.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import { AtpAgent } from '@atproto/api'
|
|
10
10
|
import { Secp256k1Keypair } from '@atproto/crypto'
|
|
11
11
|
import { LABELER_HEADER_NAME } from '../src/util'
|
|
12
|
+
import { ids } from '../src/lexicon/lexicons'
|
|
12
13
|
|
|
13
14
|
describe('labels from 3p labelers', () => {
|
|
14
15
|
let network: TestNetwork
|
|
@@ -170,11 +171,17 @@ describe('labels from 3p labelers', () => {
|
|
|
170
171
|
] = await Promise.all([
|
|
171
172
|
agent.api.tools.ozone.moderation.getRecord(
|
|
172
173
|
{ uri: sc.posts[sc.dids.alice][0].ref.uriStr },
|
|
173
|
-
{
|
|
174
|
+
{
|
|
175
|
+
headers: await ozone.modHeaders(ids.ToolsOzoneModerationGetRecord),
|
|
176
|
+
},
|
|
174
177
|
),
|
|
175
178
|
thirdPartyAgent.api.tools.ozone.moderation.getRecord(
|
|
176
179
|
{ uri: sc.posts[sc.dids.alice][0].ref.uriStr },
|
|
177
|
-
{
|
|
180
|
+
{
|
|
181
|
+
headers: await thirdPartyLabeler.modHeaders(
|
|
182
|
+
ids.ToolsOzoneModerationGetRecord,
|
|
183
|
+
),
|
|
184
|
+
},
|
|
178
185
|
),
|
|
179
186
|
])
|
|
180
187
|
|
|
@@ -189,7 +196,9 @@ describe('labels from 3p labelers', () => {
|
|
|
189
196
|
})
|
|
190
197
|
|
|
191
198
|
it('includes labels from all authorities requested via header', async () => {
|
|
192
|
-
const authHeaders = await ozone.modHeaders(
|
|
199
|
+
const authHeaders = await ozone.modHeaders(
|
|
200
|
+
ids.ToolsOzoneModerationGetRecord,
|
|
201
|
+
)
|
|
193
202
|
const { data: recordIncludingExternalLabels } =
|
|
194
203
|
await agent.api.tools.ozone.moderation.getRecord(
|
|
195
204
|
{ uri: sc.posts[sc.dids.alice][0].ref.uriStr },
|
|
@@ -225,11 +234,17 @@ describe('labels from 3p labelers', () => {
|
|
|
225
234
|
await Promise.all([
|
|
226
235
|
agent.api.tools.ozone.moderation.getRepo(
|
|
227
236
|
{ did: sc.dids.alice },
|
|
228
|
-
{
|
|
237
|
+
{
|
|
238
|
+
headers: await ozone.modHeaders(ids.ToolsOzoneModerationGetRepo),
|
|
239
|
+
},
|
|
229
240
|
),
|
|
230
241
|
thirdPartyAgent.api.tools.ozone.moderation.getRepo(
|
|
231
242
|
{ did: sc.dids.alice },
|
|
232
|
-
{
|
|
243
|
+
{
|
|
244
|
+
headers: await thirdPartyLabeler.modHeaders(
|
|
245
|
+
ids.ToolsOzoneModerationGetRepo,
|
|
246
|
+
),
|
|
247
|
+
},
|
|
233
248
|
),
|
|
234
249
|
])
|
|
235
250
|
|
|
@@ -244,7 +259,9 @@ describe('labels from 3p labelers', () => {
|
|
|
244
259
|
})
|
|
245
260
|
|
|
246
261
|
it('includes labels from all authorities requested via header', async () => {
|
|
247
|
-
const authHeaders = await ozone.modHeaders(
|
|
262
|
+
const authHeaders = await ozone.modHeaders(
|
|
263
|
+
ids.ToolsOzoneModerationGetRepo,
|
|
264
|
+
)
|
|
248
265
|
const { data: recordIncludingExternalLabels } =
|
|
249
266
|
await agent.api.tools.ozone.moderation.getRepo(
|
|
250
267
|
{ did: sc.dids.alice },
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { TestNetwork, SeedClient, basicSeed } from '@atproto/dev-env'
|
|
2
2
|
import { AtpAgent } from '@atproto/api'
|
|
3
|
+
import { ids } from '../src/lexicon/lexicons'
|
|
3
4
|
|
|
4
5
|
describe('communication-templates', () => {
|
|
5
6
|
let network: TestNetwork
|
|
@@ -30,7 +31,10 @@ describe('communication-templates', () => {
|
|
|
30
31
|
const { data } = await agent.api.tools.ozone.communication.listTemplates(
|
|
31
32
|
{},
|
|
32
33
|
{
|
|
33
|
-
headers: await network.ozone.modHeaders(
|
|
34
|
+
headers: await network.ozone.modHeaders(
|
|
35
|
+
ids.ToolsOzoneCommunicationListTemplates,
|
|
36
|
+
'moderator',
|
|
37
|
+
),
|
|
34
38
|
},
|
|
35
39
|
)
|
|
36
40
|
return data.communicationTemplates
|
|
@@ -42,7 +46,10 @@ describe('communication-templates', () => {
|
|
|
42
46
|
{ ...templateOne, createdBy: sc.dids.bob },
|
|
43
47
|
{
|
|
44
48
|
encoding: 'application/json',
|
|
45
|
-
headers: await network.ozone.modHeaders(
|
|
49
|
+
headers: await network.ozone.modHeaders(
|
|
50
|
+
ids.ToolsOzoneCommunicationCreateTemplate,
|
|
51
|
+
'triage',
|
|
52
|
+
),
|
|
46
53
|
},
|
|
47
54
|
)
|
|
48
55
|
await expect(moderatorReq).rejects.toThrow(
|
|
@@ -52,7 +59,10 @@ describe('communication-templates', () => {
|
|
|
52
59
|
{ ...templateOne, createdBy: sc.dids.bob },
|
|
53
60
|
{
|
|
54
61
|
encoding: 'application/json',
|
|
55
|
-
headers: await network.ozone.modHeaders(
|
|
62
|
+
headers: await network.ozone.modHeaders(
|
|
63
|
+
ids.ToolsOzoneCommunicationCreateTemplate,
|
|
64
|
+
'admin',
|
|
65
|
+
),
|
|
56
66
|
},
|
|
57
67
|
)
|
|
58
68
|
|
|
@@ -76,7 +86,10 @@ describe('communication-templates', () => {
|
|
|
76
86
|
{ ...templateTwo, createdBy: sc.dids.bob },
|
|
77
87
|
{
|
|
78
88
|
encoding: 'application/json',
|
|
79
|
-
headers: await network.ozone.modHeaders(
|
|
89
|
+
headers: await network.ozone.modHeaders(
|
|
90
|
+
ids.ToolsOzoneCommunicationCreateTemplate,
|
|
91
|
+
'admin',
|
|
92
|
+
),
|
|
80
93
|
},
|
|
81
94
|
)
|
|
82
95
|
|
|
@@ -91,7 +104,10 @@ describe('communication-templates', () => {
|
|
|
91
104
|
{ id: '1', updatedBy: sc.dids.bob, name: '1 Test template' },
|
|
92
105
|
{
|
|
93
106
|
encoding: 'application/json',
|
|
94
|
-
headers: await network.ozone.modHeaders(
|
|
107
|
+
headers: await network.ozone.modHeaders(
|
|
108
|
+
ids.ToolsOzoneCommunicationUpdateTemplate,
|
|
109
|
+
'admin',
|
|
110
|
+
),
|
|
95
111
|
},
|
|
96
112
|
)
|
|
97
113
|
|
|
@@ -105,7 +121,10 @@ describe('communication-templates', () => {
|
|
|
105
121
|
{ id: '1' },
|
|
106
122
|
{
|
|
107
123
|
encoding: 'application/json',
|
|
108
|
-
headers: await network.ozone.modHeaders(
|
|
124
|
+
headers: await network.ozone.modHeaders(
|
|
125
|
+
ids.ToolsOzoneCommunicationDeleteTemplate,
|
|
126
|
+
'triage',
|
|
127
|
+
),
|
|
109
128
|
},
|
|
110
129
|
)
|
|
111
130
|
|
|
@@ -117,7 +136,10 @@ describe('communication-templates', () => {
|
|
|
117
136
|
{ id: '1' },
|
|
118
137
|
{
|
|
119
138
|
encoding: 'application/json',
|
|
120
|
-
headers: await network.ozone.modHeaders(
|
|
139
|
+
headers: await network.ozone.modHeaders(
|
|
140
|
+
ids.ToolsOzoneCommunicationDeleteTemplate,
|
|
141
|
+
'moderator',
|
|
142
|
+
),
|
|
121
143
|
},
|
|
122
144
|
)
|
|
123
145
|
const list = await listTemplates()
|
package/tests/get-config.test.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { TestNetwork, SeedClient, basicSeed } from '@atproto/dev-env'
|
|
2
2
|
import { AtpAgent } from '@atproto/api'
|
|
3
3
|
import { TOOLS_OZONE_TEAM } from '../src/lexicon'
|
|
4
|
+
import { ids } from '../src/lexicon/lexicons'
|
|
4
5
|
|
|
5
6
|
describe('get-config', () => {
|
|
6
7
|
let network: TestNetwork
|
|
@@ -25,7 +26,10 @@ describe('get-config', () => {
|
|
|
25
26
|
const { data } = await agent.api.tools.ozone.server.getConfig(
|
|
26
27
|
{},
|
|
27
28
|
{
|
|
28
|
-
headers: await network.ozone.modHeaders(
|
|
29
|
+
headers: await network.ozone.modHeaders(
|
|
30
|
+
ids.ToolsOzoneServerGetConfig,
|
|
31
|
+
role,
|
|
32
|
+
),
|
|
29
33
|
},
|
|
30
34
|
)
|
|
31
35
|
return data
|
package/tests/get-lists.test.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
} from '@atproto/dev-env'
|
|
9
9
|
import { AtpAgent, BSKY_LABELER_DID } from '@atproto/api'
|
|
10
10
|
import { TAKEDOWN_LABEL } from '../src/mod-service'
|
|
11
|
+
import { ids } from '../src/lexicon/lexicons'
|
|
11
12
|
|
|
12
13
|
describe('admin get lists', () => {
|
|
13
14
|
let network: TestNetwork
|
|
@@ -42,7 +43,7 @@ describe('admin get lists', () => {
|
|
|
42
43
|
const [{ data: fromOzone }, { data: fromAppview }] = await Promise.all([
|
|
43
44
|
agent.api.app.bsky.graph.getLists(
|
|
44
45
|
{ actor: sc.dids.alice },
|
|
45
|
-
{ headers: await ozone.modHeaders() },
|
|
46
|
+
{ headers: await ozone.modHeaders(ids.AppBskyGraphGetLists) },
|
|
46
47
|
),
|
|
47
48
|
appviewAgent.api.app.bsky.graph.getLists({ actor: sc.dids.alice }),
|
|
48
49
|
])
|
package/tests/get-record.test.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
REASONSPAM,
|
|
13
13
|
} from '../src/lexicon/types/com/atproto/moderation/defs'
|
|
14
14
|
import { forSnapshot } from './_util'
|
|
15
|
+
import { ids } from '../src/lexicon/lexicons'
|
|
15
16
|
|
|
16
17
|
describe('admin get record view', () => {
|
|
17
18
|
let network: TestNetwork
|
|
@@ -72,7 +73,7 @@ describe('admin get record view', () => {
|
|
|
72
73
|
it('gets a record by uri, even when taken down.', async () => {
|
|
73
74
|
const result = await agent.api.tools.ozone.moderation.getRecord(
|
|
74
75
|
{ uri: sc.posts[sc.dids.alice][0].ref.uriStr },
|
|
75
|
-
{ headers: await ozone.modHeaders() },
|
|
76
|
+
{ headers: await ozone.modHeaders(ids.ToolsOzoneModerationGetRecord) },
|
|
76
77
|
)
|
|
77
78
|
expect(forSnapshot(result.data)).toMatchSnapshot()
|
|
78
79
|
})
|
|
@@ -83,7 +84,7 @@ describe('admin get record view', () => {
|
|
|
83
84
|
uri: sc.posts[sc.dids.alice][0].ref.uriStr,
|
|
84
85
|
cid: sc.posts[sc.dids.alice][0].ref.cidStr,
|
|
85
86
|
},
|
|
86
|
-
{ headers: await ozone.modHeaders() },
|
|
87
|
+
{ headers: await ozone.modHeaders(ids.ToolsOzoneModerationGetRecord) },
|
|
87
88
|
)
|
|
88
89
|
expect(forSnapshot(result.data)).toMatchSnapshot()
|
|
89
90
|
})
|
|
@@ -97,7 +98,7 @@ describe('admin get record view', () => {
|
|
|
97
98
|
'badrkey',
|
|
98
99
|
).toString(),
|
|
99
100
|
},
|
|
100
|
-
{ headers: await ozone.modHeaders() },
|
|
101
|
+
{ headers: await ozone.modHeaders(ids.ToolsOzoneModerationGetRecord) },
|
|
101
102
|
)
|
|
102
103
|
await expect(promise).rejects.toThrow('Record not found')
|
|
103
104
|
})
|
|
@@ -108,7 +109,7 @@ describe('admin get record view', () => {
|
|
|
108
109
|
uri: sc.posts[sc.dids.alice][0].ref.uriStr,
|
|
109
110
|
cid: sc.posts[sc.dids.alice][1].ref.cidStr, // Mismatching cid
|
|
110
111
|
},
|
|
111
|
-
{ headers: await ozone.modHeaders() },
|
|
112
|
+
{ headers: await ozone.modHeaders(ids.ToolsOzoneModerationGetRecord) },
|
|
112
113
|
)
|
|
113
114
|
await expect(promise).rejects.toThrow('Record not found')
|
|
114
115
|
})
|