diff --git a/.config/example.yml b/.config/example.yml
index 7918d766ed..2fd57094b6 100644
--- a/.config/example.yml
+++ b/.config/example.yml
@@ -135,11 +135,6 @@ autoAdmin: true
# client_id: example-github-client-id
# client_secret: example-github-client-secret
-# Ghost
-# Ghost account is an account used for the purpose of delegating
-# followers when putting users in the list.
-#ghost: user-id-of-your-ghost-account
-
# Clustering
#clusterLimit: 1
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 840dce5735..2d0cf60bc6 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -1090,6 +1090,11 @@ admin/views/instance.vue:
enable-recaptcha: "reCAPTCHAを有効にする"
recaptcha-site-key: "reCAPTCHA site key"
recaptcha-secret-key: "reCAPTCHA secret key"
+ proxy-account-config: "プロキシアカウントの設定"
+ proxy-account-info: "プロキシアカウントは、特定の条件下でユーザーのリモートフォローを代行するアカウントです。例えば、ユーザーがリモートユーザーをリストに入れたとき、リストに入れられたユーザーを誰もフォローしていないとアクティビティがサーバーに配達されないため、代わりにプロキシアカウントがフォローするようにします。"
+ proxy-account-username: "プロキシアカウントのユーザー名"
+ proxy-account-username-desc: "プロキシとして使用するアカウントのユーザー名を指定してください。"
+ proxy-account-warn: "アカウントは自動で作られないため、そのユーザー名のアカウントを予め作成しておく必要があります。"
max-note-text-length: "投稿の最大文字数"
disable-registration: "ユーザー登録の受付を停止する"
disable-local-timeline: "ローカルタイムラインを無効にする"
diff --git a/src/client/app/admin/views/instance.vue b/src/client/app/admin/views/instance.vue
index 11f9d28fd2..5acb493332 100644
--- a/src/client/app/admin/views/instance.vue
+++ b/src/client/app/admin/views/instance.vue
@@ -13,8 +13,8 @@
%i18n:@cache-remote-files%%i18n:@cache-remote-files-desc%
- %i18n:@local-drive-capacity-mb%%i18n:@mb%MB
- %i18n:@remote-drive-capacity-mb%%i18n:@mb%MB
+ %i18n:@local-drive-capacity-mb%MB%i18n:@mb%
+ %i18n:@remote-drive-capacity-mb%MB%i18n:@mb%
@@ -23,6 +23,12 @@
%i18n:@recaptcha-site-key%
%i18n:@recaptcha-secret-key%
+
+ %i18n:@proxy-account-config%
+ %i18n:@proxy-account-info%
+ @%i18n:@proxy-account-username%%i18n:@proxy-account-username-desc%
+ %i18n:@proxy-account-warn%
+
%i18n:@disable-registration%
@@ -62,6 +68,7 @@ export default Vue.extend({
enableRecaptcha: false,
recaptchaSiteKey: null,
recaptchaSecretKey: null,
+ proxyAccount: null,
inviteCode: null,
};
},
@@ -78,6 +85,7 @@ export default Vue.extend({
this.enableRecaptcha = meta.enableRecaptcha;
this.recaptchaSiteKey = meta.recaptchaSiteKey;
this.recaptchaSecretKey = meta.recaptchaSecretKey;
+ this.proxyAccount = meta.proxyAccount;
});
},
@@ -106,7 +114,8 @@ export default Vue.extend({
maxNoteTextLength: parseInt(this.maxNoteTextLength, 10),
enableRecaptcha: this.enableRecaptcha,
recaptchaSiteKey: this.recaptchaSiteKey,
- recaptchaSecretKey: this.recaptchaSecretKey
+ recaptchaSecretKey: this.recaptchaSecretKey,
+ proxyAccount: this.proxyAccount,
}).then(() => {
this.$swal({
type: 'success',
diff --git a/src/config/types.ts b/src/config/types.ts
index 07d2ec318f..1e44c4061e 100644
--- a/src/config/types.ts
+++ b/src/config/types.ts
@@ -50,11 +50,6 @@ export type Source = {
autoAdmin?: boolean;
- /**
- * ゴーストアカウントのID
- */
- ghost?: string;
-
proxy?: string;
summalyProxy?: string;
diff --git a/src/models/meta.ts b/src/models/meta.ts
index 3eb73681ac..5d03d94181 100644
--- a/src/models/meta.ts
+++ b/src/models/meta.ts
@@ -1,5 +1,7 @@
import db from '../db/mongodb';
import config from '../config';
+import User from './user';
+import { transform } from '../misc/cafy-id';
const Meta = db.get('meta');
export default Meta;
@@ -74,6 +76,18 @@ if ((config as any).recaptcha) {
}
});
}
+if ((config as any).ghost) {
+ Meta.findOne({}).then(async m => {
+ if (m != null && m.proxyAccount == null) {
+ const account = await User.findOne({ _id: transform((config as any).ghost) });
+ Meta.update({}, {
+ $set: {
+ proxyAccount: account.username
+ }
+ });
+ }
+ });
+}
export type IMeta = {
name?: string;
@@ -92,6 +106,8 @@ export type IMeta = {
cacheRemoteFiles?: boolean;
+ proxyAccount?: string;
+
enableRecaptcha?: boolean;
recaptchaSiteKey?: string;
recaptchaSecretKey?: string;
diff --git a/src/models/user.ts b/src/models/user.ts
index 43ca612b51..2ca1917dc9 100644
--- a/src/models/user.ts
+++ b/src/models/user.ts
@@ -10,6 +10,7 @@ import Mute from './mute';
import { getFriendIds } from '../server/api/common/get-friends';
import config from '../config';
import FollowRequest from './follow-request';
+import fetchMeta from '../misc/fetch-meta';
const User = db.get('users');
@@ -376,6 +377,7 @@ function img(url) {
}
*/
-export function getGhost(): Promise {
- return User.findOne({ _id: new mongo.ObjectId(config.ghost) });
+export async function fetchProxyAccount(): Promise {
+ const meta = await fetchMeta();
+ return await User.findOne({ username: meta.proxyAccount, host: null }) as ILocalUser;
}
diff --git a/src/server/api/endpoints/admin/update-meta.ts b/src/server/api/endpoints/admin/update-meta.ts
index 85266b47cf..f541409274 100644
--- a/src/server/api/endpoints/admin/update-meta.ts
+++ b/src/server/api/endpoints/admin/update-meta.ts
@@ -98,17 +98,24 @@ export const meta = {
},
recaptchaSiteKey: {
- validator: $.str.optional,
+ validator: $.str.optional.nullable,
desc: {
'ja-JP': 'reCAPTCHA site key'
}
},
recaptchaSecretKey: {
- validator: $.str.optional,
+ validator: $.str.optional.nullable,
desc: {
'ja-JP': 'reCAPTCHA secret key'
}
+ },
+
+ proxyAccount: {
+ validator: $.str.optional.nullable,
+ desc: {
+ 'ja-JP': 'Proxy account username'
+ }
}
}
};
@@ -172,6 +179,10 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
set.recaptchaSecretKey = ps.recaptchaSecretKey;
}
+ if (ps.proxyAccount !== undefined) {
+ set.proxyAccount = ps.proxyAccount;
+ }
+
await Meta.update({}, {
$set: set
}, { upsert: true });
diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts
index 3ed225cc5f..03d2d9c6eb 100644
--- a/src/server/api/endpoints/meta.ts
+++ b/src/server/api/endpoints/meta.ts
@@ -85,6 +85,7 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
if (me && me.isAdmin) {
response.hidedTags = instance.hidedTags;
response.recaptchaSecretKey = instance.recaptchaSecretKey;
+ response.proxyAccount = instance.proxyAccount;
}
res(response);
diff --git a/src/server/api/endpoints/users/lists/push.ts b/src/server/api/endpoints/users/lists/push.ts
index 396f9813a4..5612ff1665 100644
--- a/src/server/api/endpoints/users/lists/push.ts
+++ b/src/server/api/endpoints/users/lists/push.ts
@@ -1,6 +1,6 @@
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
import UserList from '../../../../../models/user-list';
-import User, { pack as packUser, isRemoteUser, getGhost } from '../../../../../models/user';
+import User, { pack as packUser, isRemoteUser, fetchProxyAccount } from '../../../../../models/user';
import { publishUserListStream } from '../../../../../stream';
import ap from '../../../../../remote/activitypub/renderer';
import renderFollow from '../../../../../remote/activitypub/renderer/follow';
@@ -71,8 +71,8 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
// このインスタンス内にこのリモートユーザーをフォローしているユーザーがいなくても投稿を受け取るためにダミーのユーザーがフォローしたということにする
if (isRemoteUser(user)) {
- const ghost = await getGhost();
- const content = ap(renderFollow(ghost, user));
- deliver(ghost, content, user.inbox);
+ const proxy = await fetchProxyAccount();
+ const content = ap(renderFollow(proxy, user));
+ deliver(proxy, content, user.inbox);
}
}));