summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2018-05-31 22:56:02 +0900
committersyuilo <syuilotan@yahoo.co.jp>2018-05-31 22:56:02 +0900
commit51255bb4467d7f797686639d785edf0eede846ec (patch)
tree7aaed0d73fd4d7f6183bbda5d98c05b7ed28d0ad /src
parentwip (diff)
downloadsharkey-51255bb4467d7f797686639d785edf0eede846ec.tar.gz
sharkey-51255bb4467d7f797686639d785edf0eede846ec.tar.bz2
sharkey-51255bb4467d7f797686639d785edf0eede846ec.zip
wip
Diffstat (limited to 'src')
-rw-r--r--src/remote/activitypub/kernel/accept/follow.ts27
-rw-r--r--src/remote/activitypub/kernel/accept/index.ts35
-rw-r--r--src/remote/activitypub/renderer/follow.ts8
-rw-r--r--src/server/api/endpoints/i/update.ts47
-rw-r--r--src/services/following/create.ts141
-rw-r--r--src/services/following/delete.ts2
-rw-r--r--src/services/user/accept-all-follow-requests.ts18
-rw-r--r--src/services/user/accept-follow-request.ts64
8 files changed, 259 insertions, 83 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..9d425419ab
--- /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/user/accept-follow-request';
+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..b647df022e
--- /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(resolver, actor, activity, object);
+ break;
+
+ default:
+ console.warn(`Unknown accept type: ${object.type}`);
+ break;
+ }
+};
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/server/api/endpoints/i/update.ts b/src/server/api/endpoints/i/update.ts
index 6e0c5b8515..5ca54d013c 100644
--- a/src/server/api/endpoints/i/update.ts
+++ b/src/server/api/endpoints/i/update.ts
@@ -12,50 +12,57 @@ import DriveFile from '../../../../models/drive-file';
module.exports = async (params, user, app) => new Promise(async (res, rej) => {
const isSecure = user != null && app == null;
+ const updates = {} as any;
+
// Get 'name' parameter
const [name, nameErr] = $.str.optional().nullable().pipe(isValidName).get(params.name);
if (nameErr) return rej('invalid name param');
- if (name) user.name = name;
+ if (name) updates.name = name;
// Get 'description' parameter
const [description, descriptionErr] = $.str.optional().nullable().pipe(isValidDescription).get(params.description);
if (descriptionErr) return rej('invalid description param');
- if (description !== undefined) user.description = description;
+ if (description !== undefined) updates.description = description;
// Get 'location' parameter
const [location, locationErr] = $.str.optional().nullable().pipe(isValidLocation).get(params.location);
if (locationErr) return rej('invalid location param');
- if (location !== undefined) user.profile.location = location;
+ if (location !== undefined) updates.profile.location = location;
// Get 'birthday' parameter
const [birthday, birthdayErr] = $.str.optional().nullable().pipe(isValidBirthday).get(params.birthday);
if (birthdayErr) return rej('invalid birthday param');
- if (birthday !== undefined) user.profile.birthday = birthday;
+ if (birthday !== undefined) updates.profile.birthday = birthday;
// Get 'avatarId' parameter
const [avatarId, avatarIdErr] = $.type(ID).optional().get(params.avatarId);
if (avatarIdErr) return rej('invalid avatarId param');
- if (avatarId) user.avatarId = avatarId;
+ if (avatarId) updates.avatarId = avatarId;
// Get 'bannerId' parameter
const [bannerId, bannerIdErr] = $.type(ID).optional().get(params.bannerId);
if (bannerIdErr) return rej('invalid bannerId param');
- if (bannerId) user.bannerId = bannerId;
+ if (bannerId) updates.bannerId = bannerId;
+
+ // Get 'isLocked' parameter
+ const [isLocked, isLockedErr] = $.bool.optional().get(params.isLocked);
+ if (isLockedErr) return rej('invalid isLocked param');
+ if (isLocked != null) updates.isLocked = isLocked;
// Get 'isBot' parameter
const [isBot, isBotErr] = $.bool.optional().get(params.isBot);
if (isBotErr) return rej('invalid isBot param');
- if (isBot != null) user.isBot = isBot;
+ if (isBot != null) updates.isBot = isBot;
// Get 'isCat' parameter
const [isCat, isCatErr] = $.bool.optional().get(params.isCat);
if (isCatErr) return rej('invalid isCat param');
- if (isCat != null) user.isCat = isCat;
+ if (isCat != null) updates.isCat = isCat;
// Get 'autoWatch' parameter
const [autoWatch, autoWatchErr] = $.bool.optional().get(params.autoWatch);
if (autoWatchErr) return rej('invalid autoWatch param');
- if (autoWatch != null) user.settings.autoWatch = autoWatch;
+ if (autoWatch != null) updates.settings.autoWatch = autoWatch;
if (avatarId) {
const avatar = await DriveFile.findOne({
@@ -63,7 +70,7 @@ module.exports = async (params, user, app) => new Promise(async (res, rej) => {
});
if (avatar != null && avatar.metadata.properties.avgColor) {
- user.avatarColor = avatar.metadata.properties.avgColor;
+ updates.avatarColor = avatar.metadata.properties.avgColor;
}
}
@@ -73,23 +80,12 @@ module.exports = async (params, user, app) => new Promise(async (res, rej) => {
});
if (banner != null && banner.metadata.properties.avgColor) {
- user.bannerColor = banner.metadata.properties.avgColor;
+ updates.bannerColor = banner.metadata.properties.avgColor;
}
}
await User.update(user._id, {
- $set: {
- name: user.name,
- description: user.description,
- avatarId: user.avatarId,
- avatarColor: user.avatarColor,
- bannerId: user.bannerId,
- bannerColor: user.bannerColor,
- profile: user.profile,
- isBot: user.isBot,
- isCat: user.isCat,
- settings: user.settings
- }
+ $set: updates
});
// Serialize
@@ -103,4 +99,9 @@ module.exports = async (params, user, app) => new Promise(async (res, rej) => {
// Publish i updated event
event(user._id, 'i_updated', iObj);
+
+ // 鍵垢を解除したとき、溜まっていたフォローリクエストがあるならすべて承認
+ if (user.isLocked && isLocked === false) {
+ acceptAllFollowRequests(user);
+ }
});
diff --git a/src/services/following/create.ts b/src/services/following/create.ts
index 3424c55dae..03a8f399e8 100644
--- a/src/services/following/create.ts
+++ b/src/services/following/create.ts
@@ -8,72 +8,103 @@ import pack from '../../remote/activitypub/renderer';
import renderFollow from '../../remote/activitypub/renderer/follow';
import renderAccept from '../../remote/activitypub/renderer/accept';
import { deliver } from '../../queue';
+import FollowRequest from '../../models/follow-request';
-export default async function(follower: IUser, followee: IUser, activity?) {
- const following = await Following.insert({
- createdAt: new Date(),
- followerId: follower._id,
- followeeId: followee._id,
- stalk: true,
+export default async function(follower: IUser, followee: IUser) {
+ if (followee.isLocked) {
+ await FollowRequest.insert({
+ createdAt: new Date(),
+ followerId: follower._id,
+ followeeId: followee._id,
- // 非正規化
- _follower: {
- host: follower.host,
- inbox: isRemoteUser(follower) ? follower.inbox : undefined
- },
- _followee: {
- host: followee.host,
- inbox: isRemoteUser(followee) ? followee.inbox : undefined
+ // 非正規化
+ _follower: {
+ host: follower.host,
+ inbox: isRemoteUser(follower) ? follower.inbox : undefined
+ },
+ _followee: {
+ host: followee.host,
+ inbox: isRemoteUser(followee) ? followee.inbox : undefined
+ }
+ });
+
+ // Publish reciveRequest event
+ if (isLocalUser(followee)) {
+ packUser(follower, followee).then(packed => event(followee._id, 'reciveRequest', packed)),
+
+ // 通知を作成
+ notify(followee._id, follower._id, 'reciveRequest');
}
- });
- //#region Increment following count
- User.update({ _id: follower._id }, {
- $inc: {
- followingCount: 1
+ if (isLocalUser(follower) && isRemoteUser(followee)) {
+ const content = pack(renderFollow(follower, followee));
+ deliver(follower, content, followee.inbox);
}
- });
+ } else {
+ const following = await Following.insert({
+ createdAt: new Date(),
+ followerId: follower._id,
+ followeeId: followee._id,
- FollowingLog.insert({
- createdAt: following.createdAt,
- userId: follower._id,
- count: follower.followingCount + 1
- });
- //#endregion
+ // 非正規化
+ _follower: {
+ host: follower.host,
+ inbox: isRemoteUser(follower) ? follower.inbox : undefined
+ },
+ _followee: {
+ host: followee.host,
+ inbox: isRemoteUser(followee) ? followee.inbox : undefined
+ }
+ });
- //#region Increment followers count
- User.update({ _id: followee._id }, {
- $inc: {
- followersCount: 1
- }
- });
- FollowedLog.insert({
- createdAt: following.createdAt,
- userId: followee._id,
- count: followee.followersCount + 1
- });
- //#endregion
+ //#region Increment following count
+ User.update({ _id: follower._id }, {
+ $inc: {
+ followingCount: 1
+ }
+ });
- // Publish follow event
- if (isLocalUser(follower)) {
- packUser(followee, follower).then(packed => event(follower._id, 'follow', packed));
- }
+ FollowingLog.insert({
+ createdAt: following.createdAt,
+ userId: follower._id,
+ count: follower.followingCount + 1
+ });
+ //#endregion
- // Publish followed event
- if (isLocalUser(followee)) {
- packUser(follower, followee).then(packed => event(followee._id, 'followed', packed)),
+ //#region Increment followers count
+ User.update({ _id: followee._id }, {
+ $inc: {
+ followersCount: 1
+ }
+ });
+ FollowedLog.insert({
+ createdAt: following.createdAt,
+ userId: followee._id,
+ count: followee.followersCount + 1
+ });
+ //#endregion
- // 通知を作成
- notify(followee._id, follower._id, 'follow');
- }
+ // Publish follow event
+ if (isLocalUser(follower)) {
+ packUser(followee, follower).then(packed => event(follower._id, 'follow', packed));
+ }
- if (isLocalUser(follower) && isRemoteUser(followee)) {
- const content = pack(renderFollow(follower, followee));
- deliver(follower, content, followee.inbox);
- }
+ // Publish followed event
+ if (isLocalUser(followee)) {
+ packUser(follower, followee).then(packed => event(followee._id, 'followed', packed)),
+
+ // 通知を作成
+ notify(followee._id, follower._id, 'follow');
+ }
- if (isRemoteUser(follower) && isLocalUser(followee)) {
- const content = pack(renderAccept(activity));
- deliver(followee, content, follower.inbox);
+ if (isLocalUser(follower) && isRemoteUser(followee)) {
+ const content = pack(renderFollow(follower, followee));
+ deliver(follower, content, followee.inbox);
+ }
+
+ if (isRemoteUser(follower) && isLocalUser(followee)) {
+ const content = pack(renderAccept(renderFollow(follower, followee)));
+ deliver(followee, content, follower.inbox);
+ }
}
}
diff --git a/src/services/following/delete.ts b/src/services/following/delete.ts
index c0c99fbed5..4fc5d42476 100644
--- a/src/services/following/delete.ts
+++ b/src/services/following/delete.ts
@@ -8,7 +8,7 @@ import renderFollow from '../../remote/activitypub/renderer/follow';
import renderUndo from '../../remote/activitypub/renderer/undo';
import { deliver } from '../../queue';
-export default async function(follower: IUser, followee: IUser, activity?) {
+export default async function(follower: IUser, followee: IUser) {
const following = await Following.findOne({
followerId: follower._id,
followeeId: followee._id
diff --git a/src/services/user/accept-all-follow-requests.ts b/src/services/user/accept-all-follow-requests.ts
new file mode 100644
index 0000000000..fbb221e772
--- /dev/null
+++ b/src/services/user/accept-all-follow-requests.ts
@@ -0,0 +1,18 @@
+import User, { IUser } from "../../models/user";
+import FollowRequest from "../../models/follow-request";
+import accept from './accept-follow-request';
+
+/**
+ * 指定したユーザー宛てのフォローリクエストをすべて承認
+ * @param user ユーザー
+ */
+export default async function(user: IUser) {
+ const requests = await FollowRequest.find({
+ followeeId: user._id
+ });
+
+ requests.forEach(async request => {
+ const follower = await User.findOne({ _id: request.followerId });
+ accept(user, follower);
+ });
+}
diff --git a/src/services/user/accept-follow-request.ts b/src/services/user/accept-follow-request.ts
new file mode 100644
index 0000000000..8b5c82c84e
--- /dev/null
+++ b/src/services/user/accept-follow-request.ts
@@ -0,0 +1,64 @@
+import User, { IUser, isRemoteUser, ILocalUser } from "../../models/user";
+import FollowRequest from "../../models/follow-request";
+import pack from '../../remote/activitypub/renderer';
+import renderFollow from '../../remote/activitypub/renderer/follow';
+import renderAccept from '../../remote/activitypub/renderer/accept';
+import { deliver } from '../../queue';
+import Following from "../../models/following";
+import FollowingLog from "../../models/following-log";
+import FollowedLog from "../../models/followed-log";
+
+export default async function(followee: IUser, follower: IUser) {
+ const following = await Following.insert({
+ createdAt: new Date(),
+ followerId: follower._id,
+ followeeId: followee._id,
+
+ // 非正規化
+ _follower: {
+ host: follower.host,
+ inbox: isRemoteUser(follower) ? follower.inbox : undefined
+ },
+ _followee: {
+ host: followee.host,
+ inbox: isRemoteUser(followee) ? followee.inbox : undefined
+ }
+ });
+
+ if (isRemoteUser(follower)) {
+ const content = pack(renderAccept(renderFollow(follower, followee)));
+ deliver(followee as ILocalUser, content, follower.inbox);
+ }
+
+ FollowRequest.remove({
+ followeeId: followee._id,
+ followerId: follower._id
+ });
+
+ //#region Increment following count
+ User.update({ _id: follower._id }, {
+ $inc: {
+ followingCount: 1
+ }
+ });
+
+ FollowingLog.insert({
+ createdAt: following.createdAt,
+ userId: follower._id,
+ count: follower.followingCount + 1
+ });
+ //#endregion
+
+ //#region Increment followers count
+ User.update({ _id: followee._id }, {
+ $inc: {
+ followersCount: 1
+ }
+ });
+ FollowedLog.insert({
+ createdAt: following.createdAt,
+ userId: followee._id,
+ count: followee.followersCount + 1
+ });
+ //#endregion
+}