72eba67af1
* Minor adaptation of VerifyCidTransform implementation * refactor: factorize content-encoding negotiation into new lib * bsky: Use undici to stream blob * fixup! bsky: Use undici to stream blob * disable ssrf bsky protection in dev-env * remove http requests to self to host "/img/" * drop axios from tests * fixes * fix tests * reviex changes * properly handle HEAD requests * handle client disconnection * fix tests * drop unrelated change * tidy * tidy * tidy * remove axios from dev-env * remove axios from identity package * use undici 6 * remove axios dependency from ozone * tidy * remove axios from PDS package * avoid killing bsky-pds connections * improve debugging data * Better handle invalid CID * tidy * tidy * refactor "allFulfilled" util in @atproto/common * tidy --------- Co-authored-by: devin ivy <devinivy@gmail.com>
101 lines
2.8 KiB
TypeScript
101 lines
2.8 KiB
TypeScript
import {
|
|
ModeratorClient,
|
|
SeedClient,
|
|
TestNetwork,
|
|
basicSeed,
|
|
} from '@atproto/dev-env'
|
|
import { ResponseType, XRPCError } from '@atproto/xrpc'
|
|
import assert from 'node:assert'
|
|
import { forSnapshot } from './_util'
|
|
|
|
describe('blob divert', () => {
|
|
let network: TestNetwork
|
|
let sc: SeedClient
|
|
let modClient: ModeratorClient
|
|
|
|
beforeAll(async () => {
|
|
network = await TestNetwork.create({
|
|
dbPostgresSchema: 'ozone_blob_divert_test',
|
|
ozone: {
|
|
blobDivertUrl: `https://blob-report.com`,
|
|
blobDivertAdminPassword: 'test-auth-token',
|
|
},
|
|
})
|
|
sc = network.getSeedClient()
|
|
modClient = network.ozone.getModClient()
|
|
await basicSeed(sc)
|
|
await network.processAll()
|
|
})
|
|
|
|
afterAll(async () => {
|
|
await network.close()
|
|
})
|
|
|
|
const mockReportServiceResponse = (succeeds: boolean) => {
|
|
const blobDiverter = network.ozone.ctx.blobDiverter
|
|
assert(blobDiverter)
|
|
return jest
|
|
.spyOn(blobDiverter, 'uploadBlob')
|
|
.mockImplementation(async () => {
|
|
if (!succeeds) {
|
|
// Using an XRPCError to trigger retries
|
|
throw new XRPCError(ResponseType.Unknown, undefined)
|
|
}
|
|
})
|
|
}
|
|
|
|
const getSubject = () => ({
|
|
$type: 'com.atproto.repo.strongRef',
|
|
uri: sc.posts[sc.dids.carol][0].ref.uriStr,
|
|
cid: sc.posts[sc.dids.carol][0].ref.cidStr,
|
|
})
|
|
|
|
const getImages = () => sc.posts[sc.dids.carol][0].images
|
|
|
|
const emitDivertEvent = async () =>
|
|
modClient.emitEvent(
|
|
{
|
|
subject: getSubject(),
|
|
event: {
|
|
$type: 'tools.ozone.moderation.defs#modEventDivert',
|
|
comment: 'Diverting for test',
|
|
},
|
|
createdBy: sc.dids.alice,
|
|
subjectBlobCids: getImages().map((img) => img.image.ref.toString()),
|
|
},
|
|
'moderator',
|
|
)
|
|
|
|
it('fails and keeps attempt count when report service fails to accept upload.', async () => {
|
|
// Simulate failure to fail upload
|
|
const reportServiceRequest = mockReportServiceResponse(false)
|
|
try {
|
|
await expect(emitDivertEvent()).rejects.toThrow('Failed to process blobs')
|
|
|
|
// 1 initial attempt + 3 retries
|
|
expect(reportServiceRequest).toHaveBeenCalledTimes(getImages().length * 4)
|
|
} finally {
|
|
reportServiceRequest.mockRestore()
|
|
}
|
|
})
|
|
|
|
it('sends blobs to configured divert service and marks divert date', async () => {
|
|
// Simulate success to accept upload
|
|
const reportServiceRequest = mockReportServiceResponse(true)
|
|
try {
|
|
const divertEvent = await emitDivertEvent()
|
|
|
|
expect(reportServiceRequest).toHaveBeenCalledTimes(getImages().length)
|
|
expect(forSnapshot(divertEvent)).toMatchSnapshot()
|
|
|
|
const { subjectStatuses } = await modClient.queryStatuses({
|
|
subject: getSubject().uri,
|
|
})
|
|
|
|
expect(subjectStatuses[0].takendown).toBe(true)
|
|
} finally {
|
|
reportServiceRequest.mockRestore()
|
|
}
|
|
})
|
|
})
|