@atproto/ozone 0.0.15 → 0.0.16
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/proxied.d.ts +3 -0
- package/dist/auth-verifier.d.ts +72 -0
- package/dist/config/config.d.ts +9 -2
- package/dist/config/env.d.ts +4 -0
- package/dist/context.d.ts +3 -90
- package/dist/db/index.js.map +2 -2
- package/dist/index.js +29669 -29467
- package/dist/index.js.map +3 -3
- package/dist/lexicon/lexicons.d.ts +5 -0
- package/dist/lexicon/types/app/bsky/actor/defs.d.ts +1 -1
- package/dist/lexicon/types/com/atproto/admin/defs.d.ts +1 -0
- package/dist/mod-service/index.d.ts +16 -7
- package/dist/mod-service/views.d.ts +3 -3
- package/package.json +5 -5
- package/src/api/admin/createCommunicationTemplate.ts +2 -2
- package/src/api/admin/deleteCommunicationTemplate.ts +2 -2
- package/src/api/admin/emitModerationEvent.ts +23 -4
- package/src/api/admin/getModerationEvent.ts +1 -1
- package/src/api/admin/getRecord.ts +2 -2
- package/src/api/admin/getRepo.ts +2 -2
- package/src/api/admin/listCommunicationTemplates.ts +2 -2
- package/src/api/admin/queryModerationEvents.ts +1 -1
- package/src/api/admin/queryModerationStatuses.ts +1 -1
- package/src/api/admin/searchRepos.ts +1 -1
- package/src/api/admin/updateCommunicationTemplate.ts +2 -2
- package/src/api/index.ts +2 -0
- package/src/api/moderation/createReport.ts +2 -2
- package/src/api/proxied.ts +116 -0
- package/src/api/temp/fetchLabels.ts +2 -2
- package/src/api/well-known.ts +3 -3
- package/src/auth-verifier.ts +218 -0
- package/src/config/config.ts +18 -2
- package/src/config/env.ts +9 -1
- package/src/context.ts +24 -38
- package/src/daemon/context.ts +10 -4
- package/src/daemon/event-pusher.ts +3 -3
- package/src/lexicon/lexicons.ts +5 -0
- package/src/lexicon/types/app/bsky/actor/defs.ts +1 -1
- package/src/lexicon/types/com/atproto/admin/defs.ts +2 -0
- package/src/mod-service/index.ts +64 -7
- package/src/mod-service/views.ts +22 -18
- package/tests/moderation-events.test.ts +49 -0
- package/dist/auth.d.ts +0 -81
- package/src/auth.ts +0 -147
|
@@ -779,6 +779,10 @@ export declare const schemaDict: {
|
|
|
779
779
|
type: string;
|
|
780
780
|
description: string;
|
|
781
781
|
};
|
|
782
|
+
content: {
|
|
783
|
+
type: string;
|
|
784
|
+
description: string;
|
|
785
|
+
};
|
|
782
786
|
comment: {
|
|
783
787
|
type: string;
|
|
784
788
|
description: string;
|
|
@@ -4731,6 +4735,7 @@ export declare const schemaDict: {
|
|
|
4731
4735
|
hideRepliesByUnfollowed: {
|
|
4732
4736
|
type: string;
|
|
4733
4737
|
description: string;
|
|
4738
|
+
default: boolean;
|
|
4734
4739
|
};
|
|
4735
4740
|
hideRepliesByLikeCount: {
|
|
4736
4741
|
type: string;
|
|
@@ -88,7 +88,7 @@ export declare function validatePersonalDetailsPref(v: unknown): ValidationResul
|
|
|
88
88
|
export interface FeedViewPref {
|
|
89
89
|
feed: string;
|
|
90
90
|
hideReplies?: boolean;
|
|
91
|
-
hideRepliesByUnfollowed
|
|
91
|
+
hideRepliesByUnfollowed: boolean;
|
|
92
92
|
hideRepliesByLikeCount?: number;
|
|
93
93
|
hideReposts?: boolean;
|
|
94
94
|
hideQuotePosts?: boolean;
|
|
@@ -313,6 +313,7 @@ export declare function isModEventUnmute(v: unknown): v is ModEventUnmute;
|
|
|
313
313
|
export declare function validateModEventUnmute(v: unknown): ValidationResult;
|
|
314
314
|
export interface ModEventEmail {
|
|
315
315
|
subjectLine: string;
|
|
316
|
+
content?: string;
|
|
316
317
|
comment?: string;
|
|
317
318
|
[k: string]: unknown;
|
|
318
319
|
}
|
|
@@ -1,29 +1,33 @@
|
|
|
1
1
|
import { CID } from 'multiformats/cid';
|
|
2
2
|
import { AtUri } from '@atproto/syntax';
|
|
3
|
+
import { IdResolver } from '@atproto/identity';
|
|
4
|
+
import AtpAgent from '@atproto/api';
|
|
3
5
|
import { Database } from '../db';
|
|
4
|
-
import {
|
|
6
|
+
import { AuthHeaders, ModerationViews } from './views';
|
|
5
7
|
import { Main as StrongRef } from '../lexicon/types/com/atproto/repo/strongRef';
|
|
6
8
|
import { RepoRef, RepoBlobRef } from '../lexicon/types/com/atproto/admin/defs';
|
|
7
9
|
import { ModEventType, ModerationEventRow, ModerationSubjectStatusRow, ReversibleModerationEvent } from './types';
|
|
8
10
|
import { ModerationEvent } from '../db/schema/moderation_event';
|
|
9
|
-
import AtpAgent from '@atproto/api';
|
|
10
11
|
import { Label } from '../lexicon/types/com/atproto/label/defs';
|
|
11
12
|
import { ModSubject, RecordSubject, RepoSubject } from './subject';
|
|
12
13
|
import { BackgroundQueue } from '../background';
|
|
13
14
|
import { EventPusher } from '../daemon';
|
|
14
15
|
import { ImageInvalidator } from '../image-invalidator';
|
|
16
|
+
import { OzoneConfig } from '../config';
|
|
15
17
|
export type ModerationServiceCreator = (db: Database) => ModerationService;
|
|
16
18
|
export declare class ModerationService {
|
|
17
19
|
db: Database;
|
|
20
|
+
cfg: OzoneConfig;
|
|
18
21
|
backgroundQueue: BackgroundQueue;
|
|
22
|
+
idResolver: IdResolver;
|
|
19
23
|
eventPusher: EventPusher;
|
|
20
24
|
appviewAgent: AtpAgent;
|
|
21
|
-
private
|
|
25
|
+
private createAuthHeaders;
|
|
22
26
|
serverDid: string;
|
|
23
27
|
imgInvalidator?: ImageInvalidator | undefined;
|
|
24
28
|
cdnPaths?: string[] | undefined;
|
|
25
|
-
constructor(db: Database, backgroundQueue: BackgroundQueue, eventPusher: EventPusher, appviewAgent: AtpAgent,
|
|
26
|
-
static creator(backgroundQueue: BackgroundQueue, eventPusher: EventPusher, appviewAgent: AtpAgent,
|
|
29
|
+
constructor(db: Database, cfg: OzoneConfig, backgroundQueue: BackgroundQueue, idResolver: IdResolver, eventPusher: EventPusher, appviewAgent: AtpAgent, createAuthHeaders: (aud: string) => Promise<AuthHeaders>, serverDid: string, imgInvalidator?: ImageInvalidator | undefined, cdnPaths?: string[] | undefined);
|
|
30
|
+
static creator(cfg: OzoneConfig, backgroundQueue: BackgroundQueue, idResolver: IdResolver, eventPusher: EventPusher, appviewAgent: AtpAgent, createAuthHeaders: (aud: string) => Promise<AuthHeaders>, serverDid: string, imgInvalidator?: ImageInvalidator, cdnPaths?: string[]): (db: Database) => ModerationService;
|
|
27
31
|
views: ModerationViews;
|
|
28
32
|
getEvent(id: number): Promise<ModerationEventRow | undefined>;
|
|
29
33
|
getEventOrThrow(id: number): Promise<ModerationEventRow>;
|
|
@@ -56,8 +60,8 @@ export declare class ModerationService {
|
|
|
56
60
|
} | {
|
|
57
61
|
cids: CID[];
|
|
58
62
|
}): Promise<{
|
|
59
|
-
did: string;
|
|
60
63
|
id: number;
|
|
64
|
+
did: string;
|
|
61
65
|
createdAt: string;
|
|
62
66
|
updatedAt: string;
|
|
63
67
|
reviewState: "com.atproto.admin.defs#reviewOpen" | "com.atproto.admin.defs#reviewEscalated" | "com.atproto.admin.defs#reviewClosed";
|
|
@@ -142,8 +146,8 @@ export declare class ModerationService {
|
|
|
142
146
|
}): Promise<{
|
|
143
147
|
statuses: {
|
|
144
148
|
handle: string;
|
|
145
|
-
did: string;
|
|
146
149
|
id: number;
|
|
150
|
+
did: string;
|
|
147
151
|
createdAt: string;
|
|
148
152
|
updatedAt: string;
|
|
149
153
|
reviewState: "com.atproto.admin.defs#reviewOpen" | "com.atproto.admin.defs#reviewEscalated" | "com.atproto.admin.defs#reviewClosed";
|
|
@@ -169,6 +173,11 @@ export declare class ModerationService {
|
|
|
169
173
|
negate?: string[];
|
|
170
174
|
}): Promise<Label[]>;
|
|
171
175
|
createLabels(labels: Label[]): Promise<void>;
|
|
176
|
+
sendEmail(opts: {
|
|
177
|
+
content: string;
|
|
178
|
+
recipientDid: string;
|
|
179
|
+
subject: string;
|
|
180
|
+
}): Promise<void>;
|
|
172
181
|
}
|
|
173
182
|
export type TakedownSubjects = {
|
|
174
183
|
did: string;
|
|
@@ -5,16 +5,16 @@ import { ModEventView, RepoView, RepoViewDetail, RecordView, RecordViewDetail, R
|
|
|
5
5
|
import { OutputSchema as ReportOutput } from '../lexicon/types/com/atproto/moderation/createReport';
|
|
6
6
|
import { Label } from '../lexicon/types/com/atproto/label/defs';
|
|
7
7
|
import { ModerationEventRowWithHandle, ModerationSubjectStatusRowWithHandle } from './types';
|
|
8
|
-
export type
|
|
8
|
+
export type AuthHeaders = {
|
|
9
9
|
headers: {
|
|
10
10
|
authorization: string;
|
|
11
11
|
};
|
|
12
|
-
}
|
|
12
|
+
};
|
|
13
13
|
export declare class ModerationViews {
|
|
14
14
|
private db;
|
|
15
15
|
private appviewAgent;
|
|
16
16
|
private appviewAuth;
|
|
17
|
-
constructor(db: Database, appviewAgent: AtpAgent, appviewAuth:
|
|
17
|
+
constructor(db: Database, appviewAgent: AtpAgent, appviewAuth: () => Promise<AuthHeaders>);
|
|
18
18
|
getAccoutInfosByDid(dids: string[]): Promise<Map<string, AccountView>>;
|
|
19
19
|
repos(dids: string[]): Promise<Map<string, RepoView>>;
|
|
20
20
|
formatEvent(event: ModerationEventRowWithHandle): ModEventView;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/ozone",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.16",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Backend service for moderating the Bluesky network.",
|
|
6
6
|
"keywords": [
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"pino-http": "^8.2.1",
|
|
31
31
|
"typed-emitter": "^2.1.0",
|
|
32
32
|
"uint8arrays": "3.0.0",
|
|
33
|
-
"@atproto/api": "^0.10.
|
|
33
|
+
"@atproto/api": "^0.10.5",
|
|
34
34
|
"@atproto/common": "^0.3.3",
|
|
35
35
|
"@atproto/crypto": "^0.3.0",
|
|
36
36
|
"@atproto/identity": "^0.3.2",
|
|
@@ -46,10 +46,10 @@
|
|
|
46
46
|
"@types/pg": "^8.6.6",
|
|
47
47
|
"@types/qs": "^6.9.7",
|
|
48
48
|
"axios": "^0.27.2",
|
|
49
|
-
"@atproto/api": "^0.10.
|
|
50
|
-
"@atproto/dev-env": "^0.2.
|
|
49
|
+
"@atproto/api": "^0.10.5",
|
|
50
|
+
"@atproto/dev-env": "^0.2.37",
|
|
51
51
|
"@atproto/lex-cli": "^0.3.1",
|
|
52
|
-
"@atproto/pds": "^0.4.
|
|
52
|
+
"@atproto/pds": "^0.4.5",
|
|
53
53
|
"@atproto/xrpc": "^0.4.2"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
@@ -4,13 +4,13 @@ import AppContext from '../../context'
|
|
|
4
4
|
|
|
5
5
|
export default function (server: Server, ctx: AppContext) {
|
|
6
6
|
server.com.atproto.admin.createCommunicationTemplate({
|
|
7
|
-
auth: ctx.
|
|
7
|
+
auth: ctx.authVerifier.modOrRole,
|
|
8
8
|
handler: async ({ input, auth }) => {
|
|
9
9
|
const access = auth.credentials
|
|
10
10
|
const db = ctx.db
|
|
11
11
|
const { createdBy, ...template } = input.body
|
|
12
12
|
|
|
13
|
-
if (!access.
|
|
13
|
+
if (!access.isAdmin) {
|
|
14
14
|
throw new AuthRequiredError(
|
|
15
15
|
'Must be an admin to create a communication template',
|
|
16
16
|
)
|
|
@@ -4,13 +4,13 @@ import AppContext from '../../context'
|
|
|
4
4
|
|
|
5
5
|
export default function (server: Server, ctx: AppContext) {
|
|
6
6
|
server.com.atproto.admin.deleteCommunicationTemplate({
|
|
7
|
-
auth: ctx.
|
|
7
|
+
auth: ctx.authVerifier.modOrRole,
|
|
8
8
|
handler: async ({ input, auth }) => {
|
|
9
9
|
const access = auth.credentials
|
|
10
10
|
const db = ctx.db
|
|
11
11
|
const { id } = input.body
|
|
12
12
|
|
|
13
|
-
if (!access.
|
|
13
|
+
if (!access.isAdmin) {
|
|
14
14
|
throw new AuthRequiredError(
|
|
15
15
|
'Must be an admin to delete a communication template',
|
|
16
16
|
)
|
|
@@ -2,16 +2,18 @@ import { AuthRequiredError, InvalidRequestError } from '@atproto/xrpc-server'
|
|
|
2
2
|
import { Server } from '../../lexicon'
|
|
3
3
|
import AppContext from '../../context'
|
|
4
4
|
import {
|
|
5
|
+
isModEventEmail,
|
|
5
6
|
isModEventLabel,
|
|
6
7
|
isModEventReverseTakedown,
|
|
7
8
|
isModEventTakedown,
|
|
8
9
|
} from '../../lexicon/types/com/atproto/admin/defs'
|
|
9
10
|
import { subjectFromInput } from '../../mod-service/subject'
|
|
10
11
|
import { ModerationLangService } from '../../mod-service/lang'
|
|
12
|
+
import { retryHttp } from '../../util'
|
|
11
13
|
|
|
12
14
|
export default function (server: Server, ctx: AppContext) {
|
|
13
15
|
server.com.atproto.admin.emitModerationEvent({
|
|
14
|
-
auth: ctx.
|
|
16
|
+
auth: ctx.authVerifier.modOrRole,
|
|
15
17
|
handler: async ({ input, auth }) => {
|
|
16
18
|
const access = auth.credentials
|
|
17
19
|
const db = ctx.db
|
|
@@ -29,7 +31,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
29
31
|
|
|
30
32
|
// if less than moderator access then can only take ack and escalation actions
|
|
31
33
|
if (isTakedownEvent || isReverseTakedownEvent) {
|
|
32
|
-
if (!access.
|
|
34
|
+
if (!access.isModerator) {
|
|
33
35
|
throw new AuthRequiredError(
|
|
34
36
|
'Must be a full moderator to take this type of action',
|
|
35
37
|
)
|
|
@@ -37,7 +39,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
37
39
|
|
|
38
40
|
// Non admins should not be able to take down feed generators
|
|
39
41
|
if (
|
|
40
|
-
!access.
|
|
42
|
+
!access.isAdmin &&
|
|
41
43
|
subject.recordPath?.includes('app.bsky.feed.generator/')
|
|
42
44
|
) {
|
|
43
45
|
throw new AuthRequiredError(
|
|
@@ -46,7 +48,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
46
48
|
}
|
|
47
49
|
}
|
|
48
50
|
// if less than moderator access then can not apply labels
|
|
49
|
-
if (!access.
|
|
51
|
+
if (!access.isModerator && isLabelEvent) {
|
|
50
52
|
throw new AuthRequiredError('Must be a full moderator to label content')
|
|
51
53
|
}
|
|
52
54
|
|
|
@@ -75,6 +77,23 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
75
77
|
}
|
|
76
78
|
}
|
|
77
79
|
|
|
80
|
+
if (isModEventEmail(event) && event.content) {
|
|
81
|
+
// sending email prior to logging the event to avoid a long transaction below
|
|
82
|
+
if (!subject.isRepo()) {
|
|
83
|
+
throw new InvalidRequestError(
|
|
84
|
+
'Email can only be sent to a repo subject',
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
const { content, subjectLine } = event
|
|
88
|
+
await retryHttp(() =>
|
|
89
|
+
ctx.modService(db).sendEmail({
|
|
90
|
+
subject: subjectLine,
|
|
91
|
+
content,
|
|
92
|
+
recipientDid: subject.did,
|
|
93
|
+
}),
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
78
97
|
const moderationEvent = await db.transaction(async (dbTxn) => {
|
|
79
98
|
const moderationTxn = ctx.modService(dbTxn)
|
|
80
99
|
|
|
@@ -3,7 +3,7 @@ import AppContext from '../../context'
|
|
|
3
3
|
|
|
4
4
|
export default function (server: Server, ctx: AppContext) {
|
|
5
5
|
server.com.atproto.admin.getModerationEvent({
|
|
6
|
-
auth: ctx.
|
|
6
|
+
auth: ctx.authVerifier.modOrRole,
|
|
7
7
|
handler: async ({ params }) => {
|
|
8
8
|
const { id } = params
|
|
9
9
|
const db = ctx.db
|
|
@@ -6,7 +6,7 @@ import { AtUri } from '@atproto/syntax'
|
|
|
6
6
|
|
|
7
7
|
export default function (server: Server, ctx: AppContext) {
|
|
8
8
|
server.com.atproto.admin.getRecord({
|
|
9
|
-
auth: ctx.
|
|
9
|
+
auth: ctx.authVerifier.modOrRole,
|
|
10
10
|
handler: async ({ params, auth }) => {
|
|
11
11
|
const db = ctx.db
|
|
12
12
|
|
|
@@ -22,7 +22,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
22
22
|
record.repo = addAccountInfoToRepoView(
|
|
23
23
|
record.repo,
|
|
24
24
|
accountInfo,
|
|
25
|
-
auth.credentials.
|
|
25
|
+
auth.credentials.isModerator,
|
|
26
26
|
)
|
|
27
27
|
|
|
28
28
|
return {
|
package/src/api/admin/getRepo.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { addAccountInfoToRepoViewDetail, getPdsAccountInfo } from './util'
|
|
|
5
5
|
|
|
6
6
|
export default function (server: Server, ctx: AppContext) {
|
|
7
7
|
server.com.atproto.admin.getRepo({
|
|
8
|
-
auth: ctx.
|
|
8
|
+
auth: ctx.authVerifier.modOrRole,
|
|
9
9
|
handler: async ({ params, auth }) => {
|
|
10
10
|
const { did } = params
|
|
11
11
|
const db = ctx.db
|
|
@@ -20,7 +20,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
20
20
|
const repo = addAccountInfoToRepoViewDetail(
|
|
21
21
|
partialRepo,
|
|
22
22
|
accountInfo,
|
|
23
|
-
auth.credentials.
|
|
23
|
+
auth.credentials.isModerator,
|
|
24
24
|
)
|
|
25
25
|
return {
|
|
26
26
|
encoding: 'application/json',
|
|
@@ -4,12 +4,12 @@ import AppContext from '../../context'
|
|
|
4
4
|
|
|
5
5
|
export default function (server: Server, ctx: AppContext) {
|
|
6
6
|
server.com.atproto.admin.listCommunicationTemplates({
|
|
7
|
-
auth: ctx.
|
|
7
|
+
auth: ctx.authVerifier.modOrRole,
|
|
8
8
|
handler: async ({ auth }) => {
|
|
9
9
|
const access = auth.credentials
|
|
10
10
|
const db = ctx.db
|
|
11
11
|
|
|
12
|
-
if (!access.
|
|
12
|
+
if (!access.isModerator) {
|
|
13
13
|
throw new AuthRequiredError(
|
|
14
14
|
'Must be a full moderator to view list of communication template',
|
|
15
15
|
)
|
|
@@ -4,7 +4,7 @@ import { getEventType } from '../moderation/util'
|
|
|
4
4
|
|
|
5
5
|
export default function (server: Server, ctx: AppContext) {
|
|
6
6
|
server.com.atproto.admin.queryModerationEvents({
|
|
7
|
-
auth: ctx.
|
|
7
|
+
auth: ctx.authVerifier.modOrRole,
|
|
8
8
|
handler: async ({ params }) => {
|
|
9
9
|
const {
|
|
10
10
|
subject,
|
|
@@ -4,7 +4,7 @@ import { getReviewState } from '../moderation/util'
|
|
|
4
4
|
|
|
5
5
|
export default function (server: Server, ctx: AppContext) {
|
|
6
6
|
server.com.atproto.admin.queryModerationStatuses({
|
|
7
|
-
auth: ctx.
|
|
7
|
+
auth: ctx.authVerifier.modOrRole,
|
|
8
8
|
handler: async ({ params }) => {
|
|
9
9
|
const {
|
|
10
10
|
subject,
|
|
@@ -4,7 +4,7 @@ import { mapDefined } from '@atproto/common'
|
|
|
4
4
|
|
|
5
5
|
export default function (server: Server, ctx: AppContext) {
|
|
6
6
|
server.com.atproto.admin.searchRepos({
|
|
7
|
-
auth: ctx.
|
|
7
|
+
auth: ctx.authVerifier.modOrRole,
|
|
8
8
|
handler: async ({ params }) => {
|
|
9
9
|
const modService = ctx.modService(ctx.db)
|
|
10
10
|
|
|
@@ -4,13 +4,13 @@ import AppContext from '../../context'
|
|
|
4
4
|
|
|
5
5
|
export default function (server: Server, ctx: AppContext) {
|
|
6
6
|
server.com.atproto.admin.updateCommunicationTemplate({
|
|
7
|
-
auth: ctx.
|
|
7
|
+
auth: ctx.authVerifier.modOrRole,
|
|
8
8
|
handler: async ({ input, auth }) => {
|
|
9
9
|
const access = auth.credentials
|
|
10
10
|
const db = ctx.db
|
|
11
11
|
const { id, updatedBy, ...template } = input.body
|
|
12
12
|
|
|
13
|
-
if (!access.
|
|
13
|
+
if (!access.isAdmin) {
|
|
14
14
|
throw new AuthRequiredError(
|
|
15
15
|
'Must be an admin to update a communication template',
|
|
16
16
|
)
|
package/src/api/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ import createCommunicationTemplate from './admin/createCommunicationTemplate'
|
|
|
15
15
|
import updateCommunicationTemplate from './admin/updateCommunicationTemplate'
|
|
16
16
|
import deleteCommunicationTemplate from './admin/deleteCommunicationTemplate'
|
|
17
17
|
import listCommunicationTemplates from './admin/listCommunicationTemplates'
|
|
18
|
+
import proxied from './proxied'
|
|
18
19
|
|
|
19
20
|
export * as health from './health'
|
|
20
21
|
|
|
@@ -36,5 +37,6 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
36
37
|
createCommunicationTemplate(server, ctx)
|
|
37
38
|
updateCommunicationTemplate(server, ctx)
|
|
38
39
|
deleteCommunicationTemplate(server, ctx)
|
|
40
|
+
proxied(server, ctx)
|
|
39
41
|
return server
|
|
40
42
|
}
|
|
@@ -9,10 +9,10 @@ import { ModerationLangService } from '../../mod-service/lang'
|
|
|
9
9
|
export default function (server: Server, ctx: AppContext) {
|
|
10
10
|
server.com.atproto.moderation.createReport({
|
|
11
11
|
// @TODO anonymous reports w/ optional auth are a temporary measure
|
|
12
|
-
auth: ctx.
|
|
12
|
+
auth: ctx.authVerifier.standardOptionalOrRole,
|
|
13
13
|
handler: async ({ input, auth }) => {
|
|
14
14
|
const requester =
|
|
15
|
-
'
|
|
15
|
+
'iss' in auth.credentials ? auth.credentials.iss : ctx.cfg.service.did
|
|
16
16
|
const { reasonType, reason } = input.body
|
|
17
17
|
const subject = subjectFromInput(input.body.subject)
|
|
18
18
|
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { Server } from '../lexicon'
|
|
2
|
+
import AppContext from '../context'
|
|
3
|
+
|
|
4
|
+
export default function (server: Server, ctx: AppContext) {
|
|
5
|
+
server.app.bsky.actor.getProfile({
|
|
6
|
+
auth: ctx.authVerifier.modOrRole,
|
|
7
|
+
handler: async (request) => {
|
|
8
|
+
const res = await ctx.appviewAgent.api.app.bsky.actor.getProfile(
|
|
9
|
+
request.params,
|
|
10
|
+
await ctx.appviewAuth(),
|
|
11
|
+
)
|
|
12
|
+
return {
|
|
13
|
+
encoding: 'application/json',
|
|
14
|
+
body: res.data,
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
server.app.bsky.actor.getProfiles({
|
|
20
|
+
auth: ctx.authVerifier.modOrRole,
|
|
21
|
+
handler: async (request) => {
|
|
22
|
+
const res = await ctx.appviewAgent.api.app.bsky.actor.getProfiles(
|
|
23
|
+
request.params,
|
|
24
|
+
await ctx.appviewAuth(),
|
|
25
|
+
)
|
|
26
|
+
return {
|
|
27
|
+
encoding: 'application/json',
|
|
28
|
+
body: res.data,
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
server.app.bsky.feed.getAuthorFeed({
|
|
34
|
+
auth: ctx.authVerifier.modOrRole,
|
|
35
|
+
handler: async (request) => {
|
|
36
|
+
const res = await ctx.appviewAgent.api.app.bsky.feed.getAuthorFeed(
|
|
37
|
+
request.params,
|
|
38
|
+
await ctx.appviewAuth(),
|
|
39
|
+
)
|
|
40
|
+
return {
|
|
41
|
+
encoding: 'application/json',
|
|
42
|
+
body: res.data,
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
server.app.bsky.feed.getPostThread({
|
|
48
|
+
auth: ctx.authVerifier.modOrRole,
|
|
49
|
+
handler: async (request) => {
|
|
50
|
+
const res = await ctx.appviewAgent.api.app.bsky.feed.getPostThread(
|
|
51
|
+
request.params,
|
|
52
|
+
await ctx.appviewAuth(),
|
|
53
|
+
)
|
|
54
|
+
return {
|
|
55
|
+
encoding: 'application/json',
|
|
56
|
+
body: res.data,
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
server.app.bsky.feed.getFeedGenerator({
|
|
62
|
+
auth: ctx.authVerifier.modOrRole,
|
|
63
|
+
handler: async (request) => {
|
|
64
|
+
const res = await ctx.appviewAgent.api.app.bsky.feed.getFeedGenerator(
|
|
65
|
+
request.params,
|
|
66
|
+
await ctx.appviewAuth(),
|
|
67
|
+
)
|
|
68
|
+
return {
|
|
69
|
+
encoding: 'application/json',
|
|
70
|
+
body: res.data,
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
server.app.bsky.graph.getFollows({
|
|
76
|
+
auth: ctx.authVerifier.modOrRole,
|
|
77
|
+
handler: async (request) => {
|
|
78
|
+
const res = await ctx.appviewAgent.api.app.bsky.graph.getFollows(
|
|
79
|
+
request.params,
|
|
80
|
+
await ctx.appviewAuth(),
|
|
81
|
+
)
|
|
82
|
+
return {
|
|
83
|
+
encoding: 'application/json',
|
|
84
|
+
body: res.data,
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
server.app.bsky.graph.getFollowers({
|
|
90
|
+
auth: ctx.authVerifier.modOrRole,
|
|
91
|
+
handler: async (request) => {
|
|
92
|
+
const res = await ctx.appviewAgent.api.app.bsky.graph.getFollowers(
|
|
93
|
+
request.params,
|
|
94
|
+
await ctx.appviewAuth(),
|
|
95
|
+
)
|
|
96
|
+
return {
|
|
97
|
+
encoding: 'application/json',
|
|
98
|
+
body: res.data,
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
server.app.bsky.graph.getList({
|
|
104
|
+
auth: ctx.authVerifier.modOrRole,
|
|
105
|
+
handler: async (request) => {
|
|
106
|
+
const res = await ctx.appviewAgent.api.app.bsky.graph.getList(
|
|
107
|
+
request.params,
|
|
108
|
+
await ctx.appviewAuth(),
|
|
109
|
+
)
|
|
110
|
+
return {
|
|
111
|
+
encoding: 'application/json',
|
|
112
|
+
body: res.data,
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
})
|
|
116
|
+
}
|
|
@@ -8,13 +8,13 @@ import {
|
|
|
8
8
|
|
|
9
9
|
export default function (server: Server, ctx: AppContext) {
|
|
10
10
|
server.com.atproto.temp.fetchLabels({
|
|
11
|
-
auth: ctx.
|
|
11
|
+
auth: ctx.authVerifier.standardOptionalOrRole,
|
|
12
12
|
handler: async ({ auth, params }) => {
|
|
13
13
|
const { limit } = params
|
|
14
14
|
const since =
|
|
15
15
|
params.since !== undefined ? new Date(params.since).toISOString() : ''
|
|
16
16
|
const includeUnspeccedTakedowns =
|
|
17
|
-
auth.credentials.type === '
|
|
17
|
+
auth.credentials.type === 'none' ? false : auth.credentials.isAdmin
|
|
18
18
|
const labelRes = await ctx.db.db
|
|
19
19
|
.selectFrom('label')
|
|
20
20
|
.selectAll()
|
package/src/api/well-known.ts
CHANGED
|
@@ -15,7 +15,7 @@ export const createRouter = (ctx: AppContext): express.Router => {
|
|
|
15
15
|
id: ctx.cfg.service.did,
|
|
16
16
|
verificationMethod: [
|
|
17
17
|
{
|
|
18
|
-
id: `${ctx.cfg.service.did}#
|
|
18
|
+
id: `${ctx.cfg.service.did}#atproto_label`,
|
|
19
19
|
type: 'Multikey',
|
|
20
20
|
controller: ctx.cfg.service.did,
|
|
21
21
|
publicKeyMultibase: ctx.signingKey.did().replace('did:key:', ''),
|
|
@@ -23,8 +23,8 @@ export const createRouter = (ctx: AppContext): express.Router => {
|
|
|
23
23
|
],
|
|
24
24
|
service: [
|
|
25
25
|
{
|
|
26
|
-
id: '#
|
|
27
|
-
type: '
|
|
26
|
+
id: '#atproto_labeler',
|
|
27
|
+
type: 'AtprotoLabeler',
|
|
28
28
|
serviceEndpoint: `https://${hostname}`,
|
|
29
29
|
},
|
|
30
30
|
],
|