diff --git a/.config/example.yml b/.config/example.yml index 7918d766e..2fd57094b 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 840dce573..2d0cf60bc 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 11f9d28fd..5acb49333 100644 --- a/src/client/app/admin/views/instance.vue +++ b/src/client/app/admin/views/instance.vue @@ -13,8 +13,8 @@
%i18n:@drive-config%
%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%
%i18n:@recaptcha-config%
@@ -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 07d2ec318..1e44c4061 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 3eb73681a..5d03d9418 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 43ca612b5..2ca1917dc 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 85266b47c..f54140927 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 3ed225cc5..03d2d9c6e 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 396f9813a..5612ff166 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); } }));