From 43d87270d99a321d5dc9c01c0d56e769f0ce8ed6 Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Thu, 21 Nov 2024 10:55:27 -0500 Subject: [PATCH] improve AP error formtting --- .../src/core/activitypub/ApInboxService.ts | 4 +- .../core/activitypub/models/ApNoteService.ts | 28 ++++++------- .../activitypub/models/ApPersonService.ts | 41 ++++++++++--------- .../activitypub/models/ApQuestionService.ts | 2 +- 4 files changed, 38 insertions(+), 37 deletions(-) diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts index ced8b8dc82..5d0404d24e 100644 --- a/packages/backend/src/core/activitypub/ApInboxService.ts +++ b/packages/backend/src/core/activitypub/ApInboxService.ts @@ -429,7 +429,7 @@ export class ApInboxService { if (isPost(object)) { await this.createNote(resolver, actor, object, false); } else { - return `skip: Unsupported type for Create: ${getApType(object)} (object ${getNullableApId(object)})`; + return `skip: Unsupported type for Create: ${getApType(object)} ${getNullableApId(object)}`; } } @@ -832,7 +832,7 @@ export class ApInboxService { await this.apNoteService.updateNote(object, actor, resolver); return 'ok: Note updated'; } else { - return `skip: Unsupported type for Update: ${getApType(object)} (object ${getNullableApId(object)})`; + return `skip: Unsupported type for Update: ${getApType(object)} ${getNullableApId(object)}`; } } diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts index 83ceef12bf..cd27e562a8 100644 --- a/packages/backend/src/core/activitypub/models/ApNoteService.ts +++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts @@ -182,18 +182,18 @@ export class ApNoteService { } if (!checkHttps(note.id)) { - throw new UnrecoverableError(`unexpected schema of note note.id ${note.id}: ${entryUri}`); + throw new UnrecoverableError(`unexpected schema of note.id ${note.id} in ${entryUri}`); } const url = getOneApHrefNullable(note.url); if (url != null) { if (!checkHttps(url)) { - throw new UnrecoverableError('unexpected schema of note url: ' + url); + throw new UnrecoverableError(`unexpected schema of note.url ${url} in ${entryUri}`); } if (this.utilityService.punyHost(url) !== this.utilityService.punyHost(note.id)) { - throw new Error(`note url <> uri host mismatch: ${url} <> ${note.id}`); + throw new Error(`note url <> uri host mismatch: ${url} <> ${note.id} in ${entryUri}`); } } @@ -201,7 +201,7 @@ export class ApNoteService { // 投稿者をフェッチ if (note.attributedTo == null) { - throw new UnrecoverableError(`invalid note.attributedTo ${note.attributedTo}: ${entryUri}`); + throw new UnrecoverableError(`invalid note.attributedTo ${note.attributedTo} in ${entryUri}`); } const uri = getOneApId(note.attributedTo); @@ -276,13 +276,13 @@ export class ApNoteService { .then(x => { if (x == null) { this.logger.warn('Specified inReplyTo, but not found'); - throw new Error(`could not fetch inReplyTo ${note.inReplyTo}: ${entryUri}`); + throw new Error(`could not fetch inReplyTo ${note.inReplyTo} for note ${entryUri}`); } return x; }) .catch(async err => { - this.logger.warn(`error ${err.statusCode ?? err} fetching inReplyTo ${note.inReplyTo}: ${entryUri}`); + this.logger.warn(`error ${err.statusCode ?? err} fetching inReplyTo ${note.inReplyTo} for note ${entryUri}`); throw err; }) : null; @@ -319,7 +319,7 @@ export class ApNoteService { const uris = unique([note._misskey_quote, note.quoteUrl, note.quoteUri].filter(x => x != null)); const results = await Promise.all(uris.map(tryResolveNote)); - quote = results.filter((x): x is { status: 'ok', res: MiNote, uri: string } => x.status === 'ok').map(x => x.res).at(0); + quote = results.filter((x): x is { status: 'ok', res: MiNote } => x.status === 'ok').map(x => x.res).at(0); if (!quote) { if (results.some(x => x.status === 'temperror')) { throw new Error(`temporary error resolving quote for ${entryUri}`); @@ -382,7 +382,7 @@ export class ApNoteService { this.logger.info('The note is already inserted while creating itself, reading again'); const duplicate = await this.fetchNote(value); if (!duplicate) { - throw new Error(`The note creation failed with duplication error even when there is no duplication, ${entryUri}`); + throw new Error(`The note creation failed with duplication error even when there is no duplication: ${entryUri}`); } return duplicate; } @@ -400,10 +400,10 @@ export class ApNoteService { //#region このサーバーに既に登録されているか const updatedNote = await this.notesRepository.findOneBy({ uri: noteUri }); - if (updatedNote == null) throw new Error(`Note is not registered: ${noteUri}`); + if (updatedNote == null) throw new Error(`Note is not registered (no note): ${noteUri}`); const user = await this.usersRepository.findOneBy({ id: updatedNote.userId }) as MiRemoteUser | null; - if (user == null) throw new Error('Note is not registered'); + if (user == null) throw new Error(`Note is not registered (no user): ${noteUri}`); // eslint-disable-next-line no-param-reassign if (resolver == null) resolver = this.apResolverService.createResolver(); @@ -434,7 +434,7 @@ export class ApNoteService { } if (!checkHttps(note.id)) { - throw new UnrecoverableError(`unexpected schema of note.id ${note.id}: ${noteUri}`); + throw new UnrecoverableError(`unexpected schema of note.id ${note.id} in ${noteUri}`); } const url = getOneApHrefNullable(note.url); @@ -445,11 +445,11 @@ export class ApNoteService { if (url != null) { if (!checkHttps(url)) { - throw new Error('unexpected schema of note url: ' + url); + throw new UnrecoverableError(`unexpected schema of note.url ${url} in ${noteUri}`); } if (this.utilityService.punyHost(url) !== this.utilityService.punyHost(note.id)) { - throw new Error(`note url <> id host mismatch: ${url} <> ${note.id}`); + throw new UnrecoverableError(`note url <> id host mismatch: ${url} <> ${note.id} in ${noteUri}`); } } @@ -557,7 +557,7 @@ export class ApNoteService { const uris = unique([note._misskey_quote, note.quoteUrl, note.quoteUri].filter(x => x != null)); const results = await Promise.all(uris.map(tryResolveNote)); - quote = results.filter((x): x is { status: 'ok', res: MiNote, uri: string } => x.status === 'ok').map(x => x.res).at(0); + quote = results.filter((x): x is { status: 'ok', res: MiNote } => x.status === 'ok').map(x => x.res).at(0); if (!quote) { if (results.some(x => x.status === 'temperror')) { throw new Error(`temporary error resolving quote for ${entryUri}`); diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index 23e99b9170..cd6078b2ed 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -141,26 +141,27 @@ export class ApPersonService implements OnModuleInit { const expectHost = this.utilityService.punyHost(uri); if (!isActor(x)) { - throw new UnrecoverableError(`invalid Actor type '${x.type}': ${uri}`); + throw new UnrecoverableError(`invalid Actor type '${x.type}' in ${uri}`); } if (!(typeof x.id === 'string' && x.id.length > 0)) { - throw new UnrecoverableError(`invalid Actor - wrong id: ${uri}`); + throw new UnrecoverableError(`invalid Actor ${uri} - wrong id type`); } if (!(typeof x.inbox === 'string' && x.inbox.length > 0)) { - throw new UnrecoverableError(`invalid Actor - wrong inbox: ${uri}`); + throw new UnrecoverableError(`invalid Actor ${uri} - wrong inbox type`); } - if (this.utilityService.punyHost(x.inbox) !== expectHost) { - throw new UnrecoverableError(`invalid Actor - inbox has different host: ${uri}`); + const inboxHost = this.utilityService.punyHost(x.inbox); + if (inboxHost !== expectHost) { + throw new UnrecoverableError(`invalid Actor ${uri} - wrong inbox ${inboxHost}`); } const sharedInboxObject = x.sharedInbox ?? (x.endpoints ? x.endpoints.sharedInbox : undefined); if (sharedInboxObject != null) { const sharedInbox = getApId(sharedInboxObject); if (!(typeof sharedInbox === 'string' && sharedInbox.length > 0 && this.utilityService.punyHost(sharedInbox) === expectHost)) { - throw new Error('invalid Actor: wrong shared inbox'); + throw new UnrecoverableError(`invalid Actor ${uri} - wrong shared inbox ${sharedInbox}`); } } @@ -170,16 +171,16 @@ export class ApPersonService implements OnModuleInit { const collectionUri = getApId(xCollection); if (typeof collectionUri === 'string' && collectionUri.length > 0) { if (this.utilityService.punyHost(collectionUri) !== expectHost) { - throw new UnrecoverableError(`invalid Actor - ${collection} has different host: ${uri}`); + throw new UnrecoverableError(`invalid Actor ${uri} - wrong ${collection} ${collectionUri}`); } } else if (collectionUri != null) { - throw new UnrecoverableError(`invalid Actor: wrong ${collection} in ${uri}`); + throw new UnrecoverableError(`invalid Actor ${uri}: wrong ${collection} type`); } } } if (!(typeof x.preferredUsername === 'string' && x.preferredUsername.length > 0 && x.preferredUsername.length <= 128 && /^\w([\w-.]*\w)?$/.test(x.preferredUsername))) { - throw new UnrecoverableError(`invalid Actor - wrong username: ${uri}`); + throw new UnrecoverableError(`invalid Actor ${uri} - wrong username`); } // These fields are only informational, and some AP software allows these @@ -187,7 +188,7 @@ export class ApPersonService implements OnModuleInit { // we can at least see these users and their activities. if (x.name) { if (!(typeof x.name === 'string' && x.name.length > 0)) { - throw new UnrecoverableError(`invalid Actor - wrong name: ${uri}`); + throw new UnrecoverableError(`invalid Actor ${uri} - wrong name`); } x.name = truncate(x.name, nameLength); } else if (x.name === '') { @@ -196,24 +197,24 @@ export class ApPersonService implements OnModuleInit { } if (x.summary) { if (!(typeof x.summary === 'string' && x.summary.length > 0)) { - throw new UnrecoverableError(`invalid Actor - wrong summary: ${uri}`); + throw new UnrecoverableError(`invalid Actor ${uri} - wrong summary`); } x.summary = truncate(x.summary, summaryLength); } const idHost = this.utilityService.punyHost(x.id); if (idHost !== expectHost) { - throw new UnrecoverableError(`invalid Actor - id has different host: ${uri}`); + throw new UnrecoverableError(`invalid Actor ${uri} - wrong id ${x.id}`); } if (x.publicKey) { if (typeof x.publicKey.id !== 'string') { - throw new UnrecoverableError(`invalid Actor - publicKey.id is not a string: ${uri}`); + throw new UnrecoverableError(`invalid Actor ${uri} - wrong publicKey.id type`); } const publicKeyIdHost = this.utilityService.punyHost(x.publicKey.id); if (publicKeyIdHost !== expectHost) { - throw new UnrecoverableError(`invalid Actor - publicKey.id has different host: ${uri}`); + throw new UnrecoverableError(`invalid Actor ${uri} - wrong publicKey.id ${x.publicKey.id}`); } } @@ -310,7 +311,7 @@ export class ApPersonService implements OnModuleInit { if (resolver == null) resolver = this.apResolverService.createResolver(); const object = await resolver.resolve(uri); - if (object.id == null) throw new UnrecoverableError(`null object.id: ${uri}`); + if (object.id == null) throw new UnrecoverableError(`null object.id in ${uri}`); const person = this.validateActor(object, uri); @@ -347,11 +348,11 @@ export class ApPersonService implements OnModuleInit { if (url != null) { if (!checkHttps(url)) { - throw new UnrecoverableError(`unexpected schema of person url ${url}: ${uri}`); + throw new UnrecoverableError(`unexpected schema of person url ${url} in ${uri}`); } if (this.utilityService.punyHost(url) !== this.utilityService.punyHost(person.id)) { - throw new UnrecoverableError(`person url <> uri host mismatch: ${url} <> ${person.id}`); + throw new UnrecoverableError(`person url <> uri host mismatch: ${url} <> ${person.id} in ${uri}`); } } @@ -559,11 +560,11 @@ export class ApPersonService implements OnModuleInit { if (url != null) { if (!checkHttps(url)) { - throw new UnrecoverableError(`unexpected schema of person url ${url}: ${uri}`); + throw new UnrecoverableError(`unexpected schema of person url ${url} in ${uri}`); } if (this.utilityService.punyHost(url) !== this.utilityService.punyHost(person.id)) { - throw new UnrecoverableError(`person url <> uri host mismatch: ${url} <> ${person.id}`); + throw new UnrecoverableError(`person url <> uri host mismatch: ${url} <> ${person.id} in ${uri}`); } } @@ -733,7 +734,7 @@ export class ApPersonService implements OnModuleInit { }); if (!collection) return; - if (!isCollectionOrOrderedCollection(collection)) throw new UnrecoverableError(`featured ${user.featured} is not Collection or OrderedCollection: ${user.uri}`); + if (!isCollectionOrOrderedCollection(collection)) throw new UnrecoverableError(`featured ${user.featured} is not Collection or OrderedCollection in ${user.uri}`); // Resolve to Object(may be Note) arrays const unresolvedItems = isCollection(collection) ? collection.items : collection.orderedItems; diff --git a/packages/backend/src/core/activitypub/models/ApQuestionService.ts b/packages/backend/src/core/activitypub/models/ApQuestionService.ts index 6a0b3520fc..79a4f49d92 100644 --- a/packages/backend/src/core/activitypub/models/ApQuestionService.ts +++ b/packages/backend/src/core/activitypub/models/ApQuestionService.ts @@ -52,7 +52,7 @@ export class ApQuestionService { if (!isQuestion(question)) throw new UnrecoverableError(`invalid type ${getApType(question)}: ${getNullableApId(question)}`); const multiple = question.oneOf === undefined; - if (multiple && question.anyOf === undefined) throw new Error(`invalid question - neither oneOf nor anyOf is defined: ${getNullableApId(question)}`); + if (multiple && question.anyOf === undefined) throw new UnrecoverableError(`invalid question - neither oneOf nor anyOf is defined: ${getNullableApId(question)}`); const expiresAt = question.endTime ? new Date(question.endTime) : question.closed ? new Date(question.closed) : null;