diff options
Diffstat (limited to 'src/remote/activitypub')
| -rw-r--r-- | src/remote/activitypub/kernel/accept/follow.ts | 27 | ||||
| -rw-r--r-- | src/remote/activitypub/kernel/accept/index.ts | 35 | ||||
| -rw-r--r-- | src/remote/activitypub/kernel/follow.ts | 2 | ||||
| -rw-r--r-- | src/remote/activitypub/kernel/index.ts | 8 | ||||
| -rw-r--r-- | src/remote/activitypub/kernel/reject/follow.ts | 27 | ||||
| -rw-r--r-- | src/remote/activitypub/kernel/reject/index.ts | 35 | ||||
| -rw-r--r-- | src/remote/activitypub/kernel/undo/follow.ts | 13 | ||||
| -rw-r--r-- | src/remote/activitypub/models/person.ts | 1 | ||||
| -rw-r--r-- | src/remote/activitypub/renderer/follow.ts | 8 | ||||
| -rw-r--r-- | src/remote/activitypub/renderer/person.ts | 4 | ||||
| -rw-r--r-- | src/remote/activitypub/renderer/reject.ts | 4 | ||||
| -rw-r--r-- | src/remote/activitypub/type.ts | 6 |
12 files changed, 162 insertions, 8 deletions
diff --git a/src/remote/activitypub/kernel/accept/follow.ts b/src/remote/activitypub/kernel/accept/follow.ts new file mode 100644 index 0000000000..0f414ba321 --- /dev/null +++ b/src/remote/activitypub/kernel/accept/follow.ts @@ -0,0 +1,27 @@ +import * as mongo from 'mongodb'; +import User, { IRemoteUser } from '../../../../models/user'; +import config from '../../../../config'; +import accept from '../../../../services/following/requests/accept'; +import { IFollow } from '../../type'; + +export default async (actor: IRemoteUser, activity: IFollow): Promise<void> => { + const id = typeof activity.object == 'string' ? activity.object : activity.object.id; + + if (!id.startsWith(config.url + '/')) { + return null; + } + + const follower = await User.findOne({ + _id: new mongo.ObjectID(id.split('/').pop()) + }); + + if (follower === null) { + throw new Error('follower not found'); + } + + if (follower.host != null) { + throw new Error('フォローリクエストしたユーザーはローカルユーザーではありません'); + } + + await accept(actor, follower); +}; diff --git a/src/remote/activitypub/kernel/accept/index.ts b/src/remote/activitypub/kernel/accept/index.ts new file mode 100644 index 0000000000..2f9d646d14 --- /dev/null +++ b/src/remote/activitypub/kernel/accept/index.ts @@ -0,0 +1,35 @@ +import * as debug from 'debug'; + +import Resolver from '../../resolver'; +import { IRemoteUser } from '../../../../models/user'; +import acceptFollow from './follow'; +import { IAccept } from '../../type'; + +const log = debug('misskey:activitypub'); + +export default async (actor: IRemoteUser, activity: IAccept): Promise<void> => { + const uri = activity.id || activity; + + log(`Accept: ${uri}`); + + const resolver = new Resolver(); + + let object; + + try { + object = await resolver.resolve(activity.object); + } catch (e) { + log(`Resolution failed: ${e}`); + throw e; + } + + switch (object.type) { + case 'Follow': + acceptFollow(actor, object); + break; + + default: + console.warn(`Unknown accept type: ${object.type}`); + break; + } +}; diff --git a/src/remote/activitypub/kernel/follow.ts b/src/remote/activitypub/kernel/follow.ts index 7e31eb32ea..464f8582b7 100644 --- a/src/remote/activitypub/kernel/follow.ts +++ b/src/remote/activitypub/kernel/follow.ts @@ -23,5 +23,5 @@ export default async (actor: IRemoteUser, activity: IFollow): Promise<void> => { throw new Error('フォローしようとしているユーザーはローカルユーザーではありません'); } - await follow(actor, followee, activity); + await follow(actor, followee); }; diff --git a/src/remote/activitypub/kernel/index.ts b/src/remote/activitypub/kernel/index.ts index 15ea9494ae..752a9bd2e2 100644 --- a/src/remote/activitypub/kernel/index.ts +++ b/src/remote/activitypub/kernel/index.ts @@ -6,6 +6,8 @@ import follow from './follow'; import undo from './undo'; import like from './like'; import announce from './announce'; +import accept from './accept'; +import reject from './reject'; const self = async (actor: IRemoteUser, activity: Object): Promise<void> => { switch (activity.type) { @@ -22,7 +24,11 @@ const self = async (actor: IRemoteUser, activity: Object): Promise<void> => { break; case 'Accept': - // noop + await accept(actor, activity); + break; + + case 'Reject': + await reject(actor, activity); break; case 'Announce': diff --git a/src/remote/activitypub/kernel/reject/follow.ts b/src/remote/activitypub/kernel/reject/follow.ts new file mode 100644 index 0000000000..c139865d0e --- /dev/null +++ b/src/remote/activitypub/kernel/reject/follow.ts @@ -0,0 +1,27 @@ +import * as mongo from 'mongodb'; +import User, { IRemoteUser } from '../../../../models/user'; +import config from '../../../../config'; +import reject from '../../../../services/following/requests/reject'; +import { IFollow } from '../../type'; + +export default async (actor: IRemoteUser, activity: IFollow): Promise<void> => { + const id = typeof activity.object == 'string' ? activity.object : activity.object.id; + + if (!id.startsWith(config.url + '/')) { + return null; + } + + const follower = await User.findOne({ + _id: new mongo.ObjectID(id.split('/').pop()) + }); + + if (follower === null) { + throw new Error('follower not found'); + } + + if (follower.host != null) { + throw new Error('フォローリクエストしたユーザーはローカルユーザーではありません'); + } + + await reject(actor, follower); +}; diff --git a/src/remote/activitypub/kernel/reject/index.ts b/src/remote/activitypub/kernel/reject/index.ts new file mode 100644 index 0000000000..a82c3fd61e --- /dev/null +++ b/src/remote/activitypub/kernel/reject/index.ts @@ -0,0 +1,35 @@ +import * as debug from 'debug'; + +import Resolver from '../../resolver'; +import { IRemoteUser } from '../../../../models/user'; +import rejectFollow from './follow'; +import { IReject } from '../../type'; + +const log = debug('misskey:activitypub'); + +export default async (actor: IRemoteUser, activity: IReject): Promise<void> => { + const uri = activity.id || activity; + + log(`Reject: ${uri}`); + + const resolver = new Resolver(); + + let object; + + try { + object = await resolver.resolve(activity.object); + } catch (e) { + log(`Resolution failed: ${e}`); + throw e; + } + + switch (object.type) { + case 'Follow': + rejectFollow(actor, object); + break; + + default: + console.warn(`Unknown reject type: ${object.type}`); + break; + } +}; diff --git a/src/remote/activitypub/kernel/undo/follow.ts b/src/remote/activitypub/kernel/undo/follow.ts index c0b10c1898..7377984616 100644 --- a/src/remote/activitypub/kernel/undo/follow.ts +++ b/src/remote/activitypub/kernel/undo/follow.ts @@ -2,7 +2,9 @@ import * as mongo from 'mongodb'; import User, { IRemoteUser } from '../../../../models/user'; import config from '../../../../config'; import unfollow from '../../../../services/following/delete'; +import cancelRequest from '../../../../services/following/requests/cancel'; import { IFollow } from '../../type'; +import FollowRequest from '../../../../models/follow-request'; export default async (actor: IRemoteUser, activity: IFollow): Promise<void> => { const id = typeof activity.object == 'string' ? activity.object : activity.object.id; @@ -23,5 +25,14 @@ export default async (actor: IRemoteUser, activity: IFollow): Promise<void> => { throw new Error('フォロー解除しようとしているユーザーはローカルユーザーではありません'); } - await unfollow(actor, followee, activity); + const req = await FollowRequest.findOne({ + followerId: actor._id, + followeeId: followee._id + }); + + if (req) { + await cancelRequest(actor, followee); + } else { + await unfollow(actor, followee); + } }; diff --git a/src/remote/activitypub/models/person.ts b/src/remote/activitypub/models/person.ts index 33280f3d89..b720c445c6 100644 --- a/src/remote/activitypub/models/person.ts +++ b/src/remote/activitypub/models/person.ts @@ -93,6 +93,7 @@ export async function createPerson(value: any, resolver?: Resolver): Promise<IUs notesCount, name: person.name, driveCapacity: 1024 * 1024 * 8, // 8MiB + isLocked: person.manuallyApprovesFollowers, username: person.preferredUsername, usernameLower: person.preferredUsername.toLowerCase(), host, diff --git a/src/remote/activitypub/renderer/follow.ts b/src/remote/activitypub/renderer/follow.ts index bf8eeff06b..522422bcff 100644 --- a/src/remote/activitypub/renderer/follow.ts +++ b/src/remote/activitypub/renderer/follow.ts @@ -1,8 +1,8 @@ import config from '../../../config'; -import { IRemoteUser, ILocalUser } from '../../../models/user'; +import { IUser, isLocalUser } from '../../../models/user'; -export default (follower: ILocalUser, followee: IRemoteUser) => ({ +export default (follower: IUser, followee: IUser) => ({ type: 'Follow', - actor: `${config.url}/users/${follower._id}`, - object: followee.uri + actor: isLocalUser(follower) ? `${config.url}/users/${follower._id}` : follower.uri, + object: isLocalUser(followee) ? `${config.url}/users/${followee._id}` : followee.uri }); diff --git a/src/remote/activitypub/renderer/person.ts b/src/remote/activitypub/renderer/person.ts index 424305f8d3..b2ac885f46 100644 --- a/src/remote/activitypub/renderer/person.ts +++ b/src/remote/activitypub/renderer/person.ts @@ -1,8 +1,9 @@ import renderImage from './image'; import renderKey from './key'; import config from '../../../config'; +import { ILocalUser } from '../../../models/user'; -export default user => { +export default (user: ILocalUser) => { const id = `${config.url}/users/${user._id}`; return { @@ -17,6 +18,7 @@ export default user => { summary: user.description, icon: user.avatarId && renderImage({ _id: user.avatarId }), image: user.bannerId && renderImage({ _id: user.bannerId }), + manuallyApprovesFollowers: user.isLocked, publicKey: renderKey(user) }; }; diff --git a/src/remote/activitypub/renderer/reject.ts b/src/remote/activitypub/renderer/reject.ts new file mode 100644 index 0000000000..29c998a6b4 --- /dev/null +++ b/src/remote/activitypub/renderer/reject.ts @@ -0,0 +1,4 @@ +export default object => ({ + type: 'Reject', + object +}); diff --git a/src/remote/activitypub/type.ts b/src/remote/activitypub/type.ts index ca38ec2227..13e1969b4e 100644 --- a/src/remote/activitypub/type.ts +++ b/src/remote/activitypub/type.ts @@ -45,6 +45,7 @@ export interface IPerson extends IObject { type: 'Person'; name: string; preferredUsername: string; + manuallyApprovesFollowers: boolean; inbox: string; publicKey: any; followers: any; @@ -82,6 +83,10 @@ export interface IAccept extends IActivity { type: 'Accept'; } +export interface IReject extends IActivity { + type: 'Reject'; +} + export interface ILike extends IActivity { type: 'Like'; _misskey_reaction: string; @@ -99,5 +104,6 @@ export type Object = IUndo | IFollow | IAccept | + IReject | ILike | IAnnounce; |