[READ ONLY MIRROR] Spark Social AppView Server
github.com/sprksocial/server
atproto
deno
hono
lexicon
1import {
2 AuthRequiredError,
3 InvalidRequestError,
4 Server,
5} from "@atp/xrpc-server";
6
7import { AppContext } from "../../../../context.ts";
8import * as com from "../../../../lex/com.ts";
9import {
10 repoBlobRef,
11 repoRef,
12} from "../../../../lex/com/atproto/admin/defs.ts";
13import { main as strongRef } from "../../../../lex/com/atproto/repo/strongRef.ts";
14import type { $InputBody } from "../../../../lex/com/atproto/admin/updateSubjectStatus.ts";
15
16type Subject = $InputBody["subject"];
17type RepoRefSubject = Extract<
18 Subject,
19 { $type: "com.atproto.admin.defs#repoRef" }
20>;
21type StrongRefSubject = Extract<
22 Subject,
23 { $type: "com.atproto.repo.strongRef" }
24>;
25type RepoBlobRefSubject = Extract<
26 Subject,
27 { $type: "com.atproto.admin.defs#repoBlobRef" }
28>;
29
30const isRepoRef = (subject: Subject): subject is RepoRefSubject =>
31 repoRef.isTypeOf(subject as Record<string, unknown>);
32
33const isStrongRef = (subject: Subject): subject is StrongRefSubject =>
34 strongRef.isTypeOf(subject as Record<string, unknown>);
35
36const isRepoBlobRef = (subject: Subject): subject is RepoBlobRefSubject =>
37 repoBlobRef.isTypeOf(subject as Record<string, unknown>);
38
39export default function (server: Server, ctx: AppContext) {
40 server.add(com.atproto.admin.updateSubjectStatus, {
41 auth: ctx.authVerifier.roleOrModService,
42 handler: async ({ input, auth }) => {
43 const { canPerformTakedown } = ctx.authVerifier.parseCreds(auth);
44 if (!canPerformTakedown) {
45 throw new AuthRequiredError(
46 "Must be a full moderator to update subject state",
47 );
48 }
49 const { subject, takedown } = input.body;
50 if (takedown) {
51 if (isRepoRef(subject)) {
52 if (takedown.applied) {
53 await ctx.dataplane.moderation.takedownActor(
54 subject.did,
55 takedown.ref,
56 );
57 } else {
58 await ctx.dataplane.moderation.untakedownActor(
59 subject.did,
60 );
61 }
62 } else if (isStrongRef(subject)) {
63 if (takedown.applied) {
64 await ctx.dataplane.moderation.takedownRecord(
65 subject.uri,
66 takedown.ref,
67 );
68 } else {
69 await ctx.dataplane.moderation.untakedownRecord(
70 subject.uri,
71 );
72 }
73 } else if (isRepoBlobRef(subject)) {
74 if (takedown.applied) {
75 await ctx.dataplane.moderation.takedownBlob(
76 subject.did,
77 subject.cid,
78 takedown.ref,
79 );
80 } else {
81 await ctx.dataplane.moderation.untakedownBlob(
82 subject.did,
83 subject.cid,
84 );
85 }
86 } else {
87 throw new InvalidRequestError("Invalid subject");
88 }
89 }
90
91 return {
92 encoding: "application/json",
93 body: {
94 subject,
95 takedown,
96 },
97 };
98 },
99 });
100}