Skip to content

Commit

Permalink
Ozone !takedown labels (#2069)
Browse files Browse the repository at this point in the history
* add purge labels on takedown

* wire up some cfg

* tests

* fix up tests

* purge -> takedown

* Temporary unspecced labels relating takedowns in ozone (#2101)

temporarily move to unspecced labels relating takedowns

---------

Co-authored-by: devin ivy <devinivy@gmail.com>
  • Loading branch information
dholms and devinivy authored Jan 27, 2024
1 parent 51aa369 commit c048962
Show file tree
Hide file tree
Showing 10 changed files with 286 additions and 114 deletions.
1 change: 0 additions & 1 deletion packages/ozone/src/api/admin/emitModerationEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ export default function (server: Server, ctx: AppContext) {

if (isLabelEvent) {
await moderationTxn.formatAndCreateLabels(
ctx.cfg.service.did,
result.subjectUri ?? result.subjectDid,
result.subjectCid,
{
Expand Down
57 changes: 36 additions & 21 deletions packages/ozone/src/api/temp/fetchLabels.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,44 @@
import { Server } from '../../lexicon'
import AppContext from '../../context'
import {
UNSPECCED_TAKEDOWN_BLOBS_LABEL,
UNSPECCED_TAKEDOWN_LABEL,
} from '../../mod-service/types'

export default function (server: Server, ctx: AppContext) {
server.com.atproto.temp.fetchLabels(async ({ params }) => {
const { limit } = params
const since =
params.since !== undefined ? new Date(params.since).toISOString() : ''
const labelRes = await ctx.db.db
.selectFrom('label')
.selectAll()
.orderBy('label.cts', 'asc')
.where('cts', '>', since)
.limit(limit)
.execute()
server.com.atproto.temp.fetchLabels({
auth: ctx.authOptionalAccessOrRoleVerifier,
handler: async ({ auth, params }) => {
const { limit } = params
const since =
params.since !== undefined ? new Date(params.since).toISOString() : ''
const includeUnspeccedTakedowns =
auth.credentials.type === 'role' && auth.credentials.admin
const labelRes = await ctx.db.db
.selectFrom('label')
.selectAll()
.orderBy('label.cts', 'asc')
.where('cts', '>', since)
.if(!includeUnspeccedTakedowns, (q) =>
q.where('label.val', 'not in', [
UNSPECCED_TAKEDOWN_LABEL,
UNSPECCED_TAKEDOWN_BLOBS_LABEL,
]),
)
.limit(limit)
.execute()

const labels = labelRes.map((l) => ({
...l,
cid: l.cid === '' ? undefined : l.cid,
}))
const labels = labelRes.map((l) => ({
...l,
cid: l.cid === '' ? undefined : l.cid,
}))

return {
encoding: 'application/json',
body: {
labels,
},
}
return {
encoding: 'application/json',
body: {
labels,
},
}
},
})
}
1 change: 1 addition & 0 deletions packages/ozone/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export class AppContext {
eventPusher,
appviewAgent,
appviewAuth,
cfg.service.did,
)

const communicationTemplateService = CommunicationTemplateService.creator()
Expand Down
1 change: 1 addition & 0 deletions packages/ozone/src/daemon/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export class DaemonContext {
eventPusher,
appviewAgent,
appviewAuth,
cfg.service.did,
)
const eventReverser = new EventReverser(db, modService)

Expand Down
141 changes: 85 additions & 56 deletions packages/ozone/src/mod-service/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import {
ModerationEventRow,
ModerationSubjectStatusRow,
ReversibleModerationEvent,
UNSPECCED_TAKEDOWN_BLOBS_LABEL,
UNSPECCED_TAKEDOWN_LABEL,
} from './types'
import { ModerationEvent } from '../db/schema/moderation_event'
import { StatusKeyset, TimeIdKeyset, paginate } from '../db/pagination'
Expand All @@ -49,13 +51,15 @@ export class ModerationService {
public eventPusher: EventPusher,
public appviewAgent: AtpAgent,
private appviewAuth: AppviewAuth,
public serverDid: string,
) {}

static creator(
backgroundQueue: BackgroundQueue,
eventPusher: EventPusher,
appviewAgent: AtpAgent,
appviewAuth: AppviewAuth,
serverDid: string,
) {
return (db: Database) =>
new ModerationService(
Expand All @@ -64,6 +68,7 @@ export class ModerationService {
eventPusher,
appviewAgent,
appviewAuth,
serverDid,
)
}

Expand Down Expand Up @@ -359,19 +364,25 @@ export class ModerationService {
subjectDid: subject.did,
takedownRef,
}))
const repoEvts = await this.db.db
.insertInto('repo_push_event')
.values(values)
.onConflict((oc) =>
oc.columns(['subjectDid', 'eventType']).doUpdateSet({
takedownRef,
confirmedAt: null,
attempts: 0,
lastAttempted: null,
}),
)
.returning('id')
.execute()

const [repoEvts] = await Promise.all([
this.db.db
.insertInto('repo_push_event')
.values(values)
.onConflict((oc) =>
oc.columns(['subjectDid', 'eventType']).doUpdateSet({
takedownRef,
confirmedAt: null,
attempts: 0,
lastAttempted: null,
}),
)
.returning('id')
.execute(),
this.formatAndCreateLabels(subject.did, null, {
create: [UNSPECCED_TAKEDOWN_LABEL],
}),
])

this.db.onCommit(() => {
this.backgroundQueue.add(async () => {
Expand All @@ -383,18 +394,23 @@ export class ModerationService {
}

async reverseTakedownRepo(subject: RepoSubject) {
const repoEvts = await this.db.db
.updateTable('repo_push_event')
.where('eventType', 'in', TAKEDOWNS)
.where('subjectDid', '=', subject.did)
.set({
takedownRef: null,
confirmedAt: null,
attempts: 0,
lastAttempted: null,
})
.returning('id')
.execute()
const [repoEvts] = await Promise.all([
this.db.db
.updateTable('repo_push_event')
.where('eventType', 'in', TAKEDOWNS)
.where('subjectDid', '=', subject.did)
.set({
takedownRef: null,
confirmedAt: null,
attempts: 0,
lastAttempted: null,
})
.returning('id')
.execute(),
this.formatAndCreateLabels(subject.did, null, {
negate: [UNSPECCED_TAKEDOWN_LABEL],
}),
])

this.db.onCommit(() => {
this.backgroundQueue.add(async () => {
Expand All @@ -415,19 +431,27 @@ export class ModerationService {
subjectCid: subject.cid,
takedownRef,
}))
const recordEvts = await this.db.db
.insertInto('record_push_event')
.values(values)
.onConflict((oc) =>
oc.columns(['subjectUri', 'eventType']).doUpdateSet({
takedownRef,
confirmedAt: null,
attempts: 0,
lastAttempted: null,
}),
)
.returning('id')
.execute()
const blobCids = subject.blobCids
const labels: string[] = [UNSPECCED_TAKEDOWN_LABEL]
if (blobCids && blobCids.length > 0) {
labels.push(UNSPECCED_TAKEDOWN_BLOBS_LABEL)
}
const [recordEvts] = await Promise.all([
this.db.db
.insertInto('record_push_event')
.values(values)
.onConflict((oc) =>
oc.columns(['subjectUri', 'eventType']).doUpdateSet({
takedownRef,
confirmedAt: null,
attempts: 0,
lastAttempted: null,
}),
)
.returning('id')
.execute(),
this.formatAndCreateLabels(subject.uri, subject.cid, { create: labels }),
])

this.db.onCommit(() => {
this.backgroundQueue.add(async () => {
Expand All @@ -437,7 +461,6 @@ export class ModerationService {
})
})

const blobCids = subject.blobCids
if (blobCids && blobCids.length > 0) {
const blobValues: Insertable<BlobPushEvent>[] = []
for (const eventType of TAKEDOWNS) {
Expand Down Expand Up @@ -478,19 +501,27 @@ export class ModerationService {

async reverseTakedownRecord(subject: RecordSubject) {
this.db.assertTransaction()
const recordEvts = await this.db.db
.updateTable('record_push_event')
.where('eventType', 'in', TAKEDOWNS)
.where('subjectDid', '=', subject.did)
.where('subjectUri', '=', subject.uri)
.set({
takedownRef: null,
confirmedAt: null,
attempts: 0,
lastAttempted: null,
})
.returning('id')
.execute()
const labels: string[] = [UNSPECCED_TAKEDOWN_LABEL]
const blobCids = subject.blobCids
if (blobCids && blobCids.length > 0) {
labels.push(UNSPECCED_TAKEDOWN_BLOBS_LABEL)
}
const [recordEvts] = await Promise.all([
this.db.db
.updateTable('record_push_event')
.where('eventType', 'in', TAKEDOWNS)
.where('subjectDid', '=', subject.did)
.where('subjectUri', '=', subject.uri)
.set({
takedownRef: null,
confirmedAt: null,
attempts: 0,
lastAttempted: null,
})
.returning('id')
.execute(),
this.formatAndCreateLabels(subject.uri, subject.cid, { negate: labels }),
])
this.db.onCommit(() => {
this.backgroundQueue.add(async () => {
await Promise.all(
Expand All @@ -499,7 +530,6 @@ export class ModerationService {
})
})

const blobCids = subject.blobCids
if (blobCids && blobCids.length > 0) {
const blobEvts = await this.db.db
.updateTable('blob_push_event')
Expand Down Expand Up @@ -695,22 +725,21 @@ export class ModerationService {
}

async formatAndCreateLabels(
src: string,
uri: string,
cid: string | null,
labels: { create?: string[]; negate?: string[] },
): Promise<Label[]> {
const { create = [], negate = [] } = labels
const toCreate = create.map((val) => ({
src,
src: this.serverDid,
uri,
cid: cid ?? undefined,
val,
neg: false,
cts: new Date().toISOString(),
}))
const toNegate = negate.map((val) => ({
src,
src: this.serverDid,
uri,
cid: cid ?? undefined,
val,
Expand Down
4 changes: 4 additions & 0 deletions packages/ozone/src/mod-service/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,7 @@ export type ModEventType =
| ComAtprotoAdminDefs.ModEventReport
| ComAtprotoAdminDefs.ModEventMute
| ComAtprotoAdminDefs.ModEventReverseTakedown

export const UNSPECCED_TAKEDOWN_LABEL = '!unspecced-takedown'

export const UNSPECCED_TAKEDOWN_BLOBS_LABEL = '!unspecced-takedown-blobs'
16 changes: 16 additions & 0 deletions packages/ozone/tests/__snapshots__/get-record.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ Object {
"cid": "cids(0)",
"indexedAt": "1970-01-01T00:00:00.000Z",
"labels": Array [
Object {
"cid": "cids(0)",
"cts": "1970-01-01T00:00:00.000Z",
"neg": false,
"src": "user(1)",
"uri": "record(0)",
"val": "!unspecced-takedown",
},
Object {
"cid": "cids(0)",
"cts": "1970-01-01T00:00:00.000Z",
Expand Down Expand Up @@ -93,6 +101,14 @@ Object {
"cid": "cids(0)",
"indexedAt": "1970-01-01T00:00:00.000Z",
"labels": Array [
Object {
"cid": "cids(0)",
"cts": "1970-01-01T00:00:00.000Z",
"neg": false,
"src": "user(1)",
"uri": "record(0)",
"val": "!unspecced-takedown",
},
Object {
"cid": "cids(0)",
"cts": "1970-01-01T00:00:00.000Z",
Expand Down
10 changes: 9 additions & 1 deletion packages/ozone/tests/__snapshots__/get-repo.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,15 @@ Object {
"indexedAt": "1970-01-01T00:00:00.000Z",
"invites": Array [],
"invitesDisabled": false,
"labels": Array [],
"labels": Array [
Object {
"cts": "1970-01-01T00:00:00.000Z",
"neg": false,
"src": "user(1)",
"uri": "user(0)",
"val": "!unspecced-takedown",
},
],
"moderation": Object {
"subjectStatus": Object {
"createdAt": "1970-01-01T00:00:00.000Z",
Expand Down
2 changes: 1 addition & 1 deletion packages/ozone/tests/moderation-appeals.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ describe('moderation-appeals', () => {

beforeAll(async () => {
network = await TestNetwork.create({
dbPostgresSchema: 'ozone_moderation_statuses',
dbPostgresSchema: 'ozone_moderation_appeals',
})
agent = network.ozone.getClient()
pdsAgent = network.pds.getClient()
Expand Down
Loading

0 comments on commit c048962

Please sign in to comment.