Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(backend): getApTypeでエラーを投げないように #14361

Merged
merged 8 commits into from
Aug 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
- Fix: Play各種エンドポイントの返り値に`visibility`が含まれていない問題を修正
- Fix: サーバー情報取得の際にモデレーター限定の情報が取得できないことがあるのを修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/582)
- Fix: ActivityPubのエンティティタイプ判定で不明なタイプを受け取った場合でも処理を継続するように
- キュー処理のつまりが改善される可能性があります

## 2024.7.0

Expand Down
5 changes: 3 additions & 2 deletions packages/backend/src/core/activitypub/models/ApNoteService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,10 @@ export class ApNoteService {
@bindThis
public validateNote(object: IObject, uri: string): Error | null {
const expectHost = this.utilityService.extractDbHost(uri);
const apType = getApType(object);

if (!validPost.includes(getApType(object))) {
return new IdentifiableError('d450b8a9-48e4-4dab-ae36-f4db763fda7c', `invalid Note: invalid object type ${getApType(object)}`);
if (apType == null || !validPost.includes(apType)) {
return new IdentifiableError('d450b8a9-48e4-4dab-ae36-f4db763fda7c', `invalid Note: invalid object type ${apType ?? 'undefined'}`);
}

if (object.id && this.utilityService.extractDbHost(object.id) !== expectHost) {
Expand Down
32 changes: 23 additions & 9 deletions packages/backend/src/core/activitypub/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,14 @@ export function getApId(value: string | IObject): string {

/**
* Get ActivityStreams Object type
*
* タイプ判定ができなかった場合に、あえてエラーではなくnullを返すようにしている。
* 詳細: https://github.com/misskey-dev/misskey/issues/14239
*/
export function getApType(value: IObject): string {
export function getApType(value: IObject): string | null {
if (typeof value.type === 'string') return value.type;
if (Array.isArray(value.type) && typeof value.type[0] === 'string') return value.type[0];
throw new Error('cannot detect type');
return null;
}

export function getOneApHrefNullable(value: ApObject | undefined): string | undefined {
Expand Down Expand Up @@ -110,8 +113,10 @@ export interface IOrderedCollection extends IObject {

export const validPost = ['Note', 'Question', 'Article', 'Audio', 'Document', 'Image', 'Page', 'Video', 'Event'];

export const isPost = (object: IObject): object is IPost =>
validPost.includes(getApType(object));
export const isPost = (object: IObject): object is IPost => {
const type = getApType(object);
return type != null && validPost.includes(type);
};

export interface IPost extends IObject {
type: 'Note' | 'Question' | 'Article' | 'Audio' | 'Document' | 'Image' | 'Page' | 'Video' | 'Event';
Expand Down Expand Up @@ -158,8 +163,10 @@ export const isTombstone = (object: IObject): object is ITombstone =>

export const validActor = ['Person', 'Service', 'Group', 'Organization', 'Application'];

export const isActor = (object: IObject): object is IActor =>
validActor.includes(getApType(object));
export const isActor = (object: IObject): object is IActor => {
const type = getApType(object);
return type != null && validActor.includes(type);
};

export interface IActor extends IObject {
type: 'Person' | 'Service' | 'Organization' | 'Group' | 'Application';
Expand Down Expand Up @@ -242,12 +249,16 @@ export interface IKey extends IObject {
publicKeyPem: string | Buffer;
}

export const validDocumentTypes = ['Audio', 'Document', 'Image', 'Page', 'Video'];

export interface IApDocument extends IObject {
type: 'Audio' | 'Document' | 'Image' | 'Page' | 'Video';
}

export const isDocument = (object: IObject): object is IApDocument =>
['Audio', 'Document', 'Image', 'Page', 'Video'].includes(getApType(object));
export const isDocument = (object: IObject): object is IApDocument => {
const type = getApType(object);
return type != null && validDocumentTypes.includes(type);
};

export interface IApImage extends IApDocument {
type: 'Image';
Expand Down Expand Up @@ -325,7 +336,10 @@ export const isAccept = (object: IObject): object is IAccept => getApType(object
export const isReject = (object: IObject): object is IReject => getApType(object) === 'Reject';
export const isAdd = (object: IObject): object is IAdd => getApType(object) === 'Add';
export const isRemove = (object: IObject): object is IRemove => getApType(object) === 'Remove';
export const isLike = (object: IObject): object is ILike => getApType(object) === 'Like' || getApType(object) === 'EmojiReaction' || getApType(object) === 'EmojiReact';
export const isLike = (object: IObject): object is ILike => {
const type = getApType(object);
return type != null && ['Like', 'EmojiReaction', 'EmojiReact'].includes(type);
};
export const isAnnounce = (object: IObject): object is IAnnounce => getApType(object) === 'Announce';
export const isBlock = (object: IObject): object is IBlock => getApType(object) === 'Block';
export const isFlag = (object: IObject): object is IFlag => getApType(object) === 'Flag';
Expand Down
Loading