From 070f1f3c6ee3188e1b16236366877c1c243601c1 Mon Sep 17 00:00:00 2001 From: MeiMei <30769358+mei23@users.noreply.github.com> Date: Sat, 9 May 2020 08:21:42 +0900 Subject: APリファクタとLD-Signatureの検証に対応 (#6300) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * DbResolver * inbox types * 認証順を変更 * User/Keyあたりをまとめる * LD-Signatue * Validate contexts url * LD-Signature DocumentLoaderにProxyとTimeout --- src/remote/activitypub/kernel/accept/follow.ts | 22 +++++++------------ src/remote/activitypub/kernel/block/index.ts | 30 +++++++++----------------- src/remote/activitypub/kernel/create/note.ts | 26 +++++++++++++++++++--- src/remote/activitypub/kernel/delete/note.ts | 29 ++++++++++++++++--------- src/remote/activitypub/kernel/follow.ts | 20 ++++++----------- src/remote/activitypub/kernel/reject/follow.ts | 20 +++++++---------- src/remote/activitypub/kernel/undo/block.ts | 29 +++++++------------------ src/remote/activitypub/kernel/undo/follow.ts | 24 ++++++++++----------- src/remote/activitypub/kernel/update/index.ts | 30 +++++++++++++++----------- 9 files changed, 112 insertions(+), 118 deletions(-) (limited to 'src/remote/activitypub/kernel') diff --git a/src/remote/activitypub/kernel/accept/follow.ts b/src/remote/activitypub/kernel/accept/follow.ts index cf6763186e..c067f7622a 100644 --- a/src/remote/activitypub/kernel/accept/follow.ts +++ b/src/remote/activitypub/kernel/accept/follow.ts @@ -1,28 +1,22 @@ import { IRemoteUser } from '../../../../models/entities/user'; -import config from '../../../../config'; import accept from '../../../../services/following/requests/accept'; import { IFollow } from '../../type'; -import { Users } from '../../../../models'; +import DbResolver from '../../db-resolver'; -export default async (actor: IRemoteUser, activity: IFollow): Promise => { - const id = typeof activity.actor === 'string' ? activity.actor : activity.actor.id; - if (id == null) throw new Error('missing id'); +export default async (actor: IRemoteUser, activity: IFollow): Promise => { + // ※ activityはこっちから投げたフォローリクエストなので、activity.actorは存在するローカルユーザーである必要がある - if (!id.startsWith(config.url + '/')) { - return; - } - - const follower = await Users.findOne({ - id: id.split('/').pop() - }); + const dbResolver = new DbResolver(); + const follower = await dbResolver.getUserFromApId(activity.actor); if (follower == null) { - throw new Error('follower not found'); + return `skip: follower not found`; } if (follower.host != null) { - throw new Error('フォローリクエストしたユーザーはローカルユーザーではありません'); + return `skip: follower is not a local user`; } await accept(actor, follower); + return `ok`; }; diff --git a/src/remote/activitypub/kernel/block/index.ts b/src/remote/activitypub/kernel/block/index.ts index 24bc9d524f..6c794e1250 100644 --- a/src/remote/activitypub/kernel/block/index.ts +++ b/src/remote/activitypub/kernel/block/index.ts @@ -1,32 +1,22 @@ -import config from '../../../../config'; -import { IBlock, getApId } from '../../type'; +import { IBlock } from '../../type'; import block from '../../../../services/blocking/create'; -import { apLogger } from '../../logger'; -import { Users } from '../../../../models'; import { IRemoteUser } from '../../../../models/entities/user'; +import DbResolver from '../../db-resolver'; -const logger = apLogger; +export default async (actor: IRemoteUser, activity: IBlock): Promise => { + // ※ activity.objectにブロック対象があり、それは存在するローカルユーザーのはず -export default async (actor: IRemoteUser, activity: IBlock): Promise => { - const id = getApId(activity.object); - - const uri = getApId(activity); - - logger.info(`Block: ${uri}`); - - if (!id.startsWith(config.url + '/')) { - return; - } - - const blockee = await Users.findOne(id.split('/').pop()); + const dbResolver = new DbResolver(); + const blockee = await dbResolver.getUserFromApId(activity.object); if (blockee == null) { - throw new Error('blockee not found'); + return `skip: blockee not found`; } if (blockee.host != null) { - throw new Error('ブロックしようとしているユーザーはローカルユーザーではありません'); + return `skip: ブロックしようとしているユーザーはローカルユーザーではありません`; } - block(actor, blockee); + await block(actor, blockee); + return `ok`; }; diff --git a/src/remote/activitypub/kernel/create/note.ts b/src/remote/activitypub/kernel/create/note.ts index d7027b8f3f..f4fb8e5647 100644 --- a/src/remote/activitypub/kernel/create/note.ts +++ b/src/remote/activitypub/kernel/create/note.ts @@ -3,19 +3,39 @@ import { IRemoteUser } from '../../../../models/entities/user'; import { createNote, fetchNote } from '../../models/note'; import { getApId, IObject, ICreate } from '../../type'; import { getApLock } from '../../../../misc/app-lock'; +import { extractDbHost } from '../../../../misc/convert-host'; /** * 投稿作成アクティビティを捌きます */ -export default async function(resolver: Resolver, actor: IRemoteUser, note: IObject, silent = false, activity?: ICreate): Promise { +export default async function(resolver: Resolver, actor: IRemoteUser, note: IObject, silent = false, activity?: ICreate): Promise { const uri = getApId(note); + if (typeof note === 'object') { + if (actor.uri !== note.attributedTo) { + return `skip: actor.uri !== note.attributedTo`; + } + + if (typeof note.id === 'string') { + if (extractDbHost(actor.uri) !== extractDbHost(note.id)) { + return `skip: host in actor.uri !== note.id`; + } + } + } + const unlock = await getApLock(uri); try { const exist = await fetchNote(note); - if (exist == null) { - await createNote(note, resolver, silent); + if (exist) return 'skip: note exists'; + + await createNote(note, resolver, silent); + return 'ok'; + } catch (e) { + if (e.statusCode >= 400 && e.statusCode < 500) { + return `skip ${e.statusCode}`; + } else { + throw e; } } finally { unlock(); diff --git a/src/remote/activitypub/kernel/delete/note.ts b/src/remote/activitypub/kernel/delete/note.ts index b146e68a07..9d7574c29b 100644 --- a/src/remote/activitypub/kernel/delete/note.ts +++ b/src/remote/activitypub/kernel/delete/note.ts @@ -1,22 +1,31 @@ import { IRemoteUser } from '../../../../models/entities/user'; import deleteNode from '../../../../services/note/delete'; import { apLogger } from '../../logger'; -import { Notes } from '../../../../models'; +import DbResolver from '../../db-resolver'; +import { getApLock } from '../../../../misc/app-lock'; const logger = apLogger; -export default async function(actor: IRemoteUser, uri: string): Promise { +export default async function(actor: IRemoteUser, uri: string): Promise { logger.info(`Deleting the Note: ${uri}`); - const note = await Notes.findOne({ uri }); + const unlock = await getApLock(uri); - if (note == null) { - throw new Error('note not found'); - } + try { + const dbResolver = new DbResolver(); + const note = await dbResolver.getNoteFromApId(uri); - if (note.userId !== actor.id) { - throw new Error('投稿を削除しようとしているユーザーは投稿の作成者ではありません'); - } + if (note == null) { + return 'note not found'; + } - await deleteNode(actor, note); + if (note.userId !== actor.id) { + return '投稿を削除しようとしているユーザーは投稿の作成者ではありません'; + } + + await deleteNode(actor, note); + return 'ok: deleted'; + } finally { + unlock(); + } } diff --git a/src/remote/activitypub/kernel/follow.ts b/src/remote/activitypub/kernel/follow.ts index fca6d26ccc..3e2063302a 100644 --- a/src/remote/activitypub/kernel/follow.ts +++ b/src/remote/activitypub/kernel/follow.ts @@ -1,26 +1,20 @@ import { IRemoteUser } from '../../../models/entities/user'; -import config from '../../../config'; import follow from '../../../services/following/create'; import { IFollow } from '../type'; -import { Users } from '../../../models'; +import DbResolver from '../db-resolver'; -export default async (actor: IRemoteUser, activity: IFollow): Promise => { - const id = typeof activity.object === 'string' ? activity.object : activity.object.id; - if (id == null) throw new Error('missing id'); - - if (!id.startsWith(config.url + '/')) { - return; - } - - const followee = await Users.findOne(id.split('/').pop()); +export default async (actor: IRemoteUser, activity: IFollow): Promise => { + const dbResolver = new DbResolver(); + const followee = await dbResolver.getUserFromApId(activity.object); if (followee == null) { - throw new Error('followee not found'); + return `skip: followee not found`; } if (followee.host != null) { - throw new Error('フォローしようとしているユーザーはローカルユーザーではありません'); + return `skip: フォローしようとしているユーザーはローカルユーザーではありません`; } await follow(actor, followee, activity.id); + return `ok`; }; diff --git a/src/remote/activitypub/kernel/reject/follow.ts b/src/remote/activitypub/kernel/reject/follow.ts index bc7d03f9a9..49e82c7afc 100644 --- a/src/remote/activitypub/kernel/reject/follow.ts +++ b/src/remote/activitypub/kernel/reject/follow.ts @@ -1,26 +1,22 @@ import { IRemoteUser } from '../../../../models/entities/user'; -import config from '../../../../config'; import reject from '../../../../services/following/requests/reject'; import { IFollow } from '../../type'; -import { Users } from '../../../../models'; +import DbResolver from '../../db-resolver'; -export default async (actor: IRemoteUser, activity: IFollow): Promise => { - const id = typeof activity.actor === 'string' ? activity.actor : activity.actor.id; - if (id == null) throw new Error('missing id'); +export default async (actor: IRemoteUser, activity: IFollow): Promise => { + // ※ activityはこっちから投げたフォローリクエストなので、activity.actorは存在するローカルユーザーである必要がある - if (!id.startsWith(config.url + '/')) { - return; - } - - const follower = await Users.findOne(id.split('/').pop()); + const dbResolver = new DbResolver(); + const follower = await dbResolver.getUserFromApId(activity.actor); if (follower == null) { - throw new Error('follower not found'); + return `skip: follower not found`; } if (follower.host != null) { - throw new Error('フォローリクエストしたユーザーはローカルユーザーではありません'); + return `skip: follower is not a local user`; } await reject(actor, follower); + return `ok`; }; diff --git a/src/remote/activitypub/kernel/undo/block.ts b/src/remote/activitypub/kernel/undo/block.ts index 17eab0d2d0..73000fc3f1 100644 --- a/src/remote/activitypub/kernel/undo/block.ts +++ b/src/remote/activitypub/kernel/undo/block.ts @@ -1,33 +1,20 @@ -import config from '../../../../config'; import { IBlock } from '../../type'; import unblock from '../../../../services/blocking/delete'; -import { apLogger } from '../../logger'; import { IRemoteUser } from '../../../../models/entities/user'; -import { Users } from '../../../../models'; +import DbResolver from '../../db-resolver'; -const logger = apLogger; - -export default async (actor: IRemoteUser, activity: IBlock): Promise => { - const id = typeof activity.object === 'string' ? activity.object : activity.object.id; - if (id == null) throw new Error('missing id'); - - const uri = activity.id || activity; - - logger.info(`UnBlock: ${uri}`); - - if (!id.startsWith(config.url + '/')) { - return; - } - - const blockee = await Users.findOne(id.split('/').pop()); +export default async (actor: IRemoteUser, activity: IBlock): Promise => { + const dbResolver = new DbResolver(); + const blockee = await dbResolver.getUserFromApId(activity.object); if (blockee == null) { - throw new Error('blockee not found'); + return `skip: blockee not found`; } if (blockee.host != null) { - throw new Error('ブロック解除しようとしているユーザーはローカルユーザーではありません'); + return `skip: ブロック解除しようとしているユーザーはローカルユーザーではありません`; } - unblock(actor, blockee); + await unblock(actor, blockee); + return `ok`; }; diff --git a/src/remote/activitypub/kernel/undo/follow.ts b/src/remote/activitypub/kernel/undo/follow.ts index 2a42f83907..73a164030b 100644 --- a/src/remote/activitypub/kernel/undo/follow.ts +++ b/src/remote/activitypub/kernel/undo/follow.ts @@ -1,26 +1,20 @@ -import config from '../../../../config'; import unfollow from '../../../../services/following/delete'; import cancelRequest from '../../../../services/following/requests/cancel'; import { IFollow } from '../../type'; import { IRemoteUser } from '../../../../models/entities/user'; -import { Users, FollowRequests, Followings } from '../../../../models'; +import { FollowRequests, Followings } from '../../../../models'; +import DbResolver from '../../db-resolver'; -export default async (actor: IRemoteUser, activity: IFollow): Promise => { - const id = typeof activity.object === 'string' ? activity.object : activity.object.id; - if (id == null) throw new Error('missing id'); - - if (!id.startsWith(config.url + '/')) { - return; - } - - const followee = await Users.findOne(id.split('/').pop()); +export default async (actor: IRemoteUser, activity: IFollow): Promise => { + const dbResolver = new DbResolver(); + const followee = await dbResolver.getUserFromApId(activity.object); if (followee == null) { - throw new Error('followee not found'); + return `skip: followee not found`; } if (followee.host != null) { - throw new Error('フォロー解除しようとしているユーザーはローカルユーザーではありません'); + return `skip: フォロー解除しようとしているユーザーはローカルユーザーではありません`; } const req = await FollowRequests.findOne({ @@ -35,9 +29,13 @@ export default async (actor: IRemoteUser, activity: IFollow): Promise => { if (req) { await cancelRequest(followee, actor); + return `ok: follow request canceled`; } if (following) { await unfollow(actor, followee); + return `ok: unfollowed`; } + + return `skip: リクエストもフォローもされていない`; }; diff --git a/src/remote/activitypub/kernel/update/index.ts b/src/remote/activitypub/kernel/update/index.ts index b8dff73395..ea7e6a063e 100644 --- a/src/remote/activitypub/kernel/update/index.ts +++ b/src/remote/activitypub/kernel/update/index.ts @@ -1,28 +1,34 @@ import { IRemoteUser } from '../../../../models/entities/user'; -import { IUpdate, IObject } from '../../type'; +import { IUpdate, validActor } from '../../type'; import { apLogger } from '../../logger'; import { updateQuestion } from '../../models/question'; +import Resolver from '../../resolver'; +import { updatePerson } from '../../models/person'; /** * Updateアクティビティを捌きます */ -export default async (actor: IRemoteUser, activity: IUpdate): Promise => { +export default async (actor: IRemoteUser, activity: IUpdate): Promise => { if ('actor' in activity && actor.uri !== activity.actor) { - throw new Error('invalid actor'); + return `skip: invalid actor`; } apLogger.debug('Update'); - const object = activity.object as IObject; + const resolver = new Resolver(); - switch (object.type) { - case 'Question': - apLogger.debug('Question'); - await updateQuestion(object).catch(e => console.log(e)); - break; + const object = await resolver.resolve(activity.object).catch(e => { + apLogger.error(`Resolution failed: ${e}`); + throw e; + }); - default: - apLogger.warn(`Unknown type: ${object.type}`); - break; + if (validActor.includes(object.type)) { + await updatePerson(actor.uri!, resolver, object); + return `ok: Person updated`; + } else if (object.type === 'Question') { + await updateQuestion(object).catch(e => console.log(e)); + return `ok: Question updated`; + } else { + return `skip: Unknown type: ${object.type}`; } }; -- cgit v1.2.3-freya