Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ローカルユーザーが誰もフォローしていないリモートユーザーによるノートのブロックの改善 #206

Merged
merged 9 commits into from
Jun 30, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## Unreleased

### General
- 未知のリモートユーザーによる通知が発生するノートをブロックする機能の改善 (#206)

### Client

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: anatawa12
* SPDX-License-Identifier: AGPL-3.0-only
*/

export class NirilaBlockMentionsFromUnfamiliarRemoteUsers1719663422807 {
name = 'NirilaBlockMentionsFromUnfamiliarRemoteUsers1719663422807'

async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" ADD "nirilaBlockMentionsFromUnfamiliarRemoteUsers" boolean NOT NULL DEFAULT false`);
}

async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "nirilaBlockMentionsFromUnfamiliarRemoteUsers"`);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: anatawa12
* SPDX-License-Identifier: AGPL-3.0-only
*/

export class NirilaAllowedUnfamiliarRemoteUserIds1719664479666 {
name = 'NirilaAllowedUnfamiliarRemoteUserIds1719664479666'

async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" ADD "nirilaAllowedUnfamiliarRemoteUserIds" character varying(32) array NOT NULL DEFAULT '{}'`);
}

async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "nirilaAllowedUnfamiliarRemoteUserIds"`);
}
}
3 changes: 0 additions & 3 deletions packages/backend/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ type Source = {
maxWebImageSize?: number;
withRepliesInHomeTL?: boolean;
withRepliesInUserList?: boolean;
blockMentionsFromUnfamiliarRemoteUsers?: boolean;
}
};

Expand Down Expand Up @@ -191,7 +190,6 @@ export type Config = {
maxWebImageSize?: number;
withRepliesInHomeTL?: boolean,
withRepliesInUserList: boolean,
blockMentionsFromUnfamiliarRemoteUsers: boolean;
}
};

Expand Down Expand Up @@ -237,7 +235,6 @@ export function loadConfig(): Config {
// to avoid merge conflict in the future, this is at top
nirila: Object.assign({
withRepliesInUserList: true,
blockMentionsFromUnfamiliarRemoteUsers: false,
}, config.nirila ?? {}),
version,
publishTarballInsteadOfProvideRepositoryUrl: !!config.publishTarballInsteadOfProvideRepositoryUrl,
Expand Down
18 changes: 17 additions & 1 deletion packages/backend/src/core/NoteCreateService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,23 @@ export class NoteCreateService implements OnApplicationShutdown {
|| (data.visibility === 'specified' && data.visibleUsers?.some(u => u.host === null))
|| data.reply?.userHost === null || (this.isRenote(data) && this.isQuote(data) && data.renote?.userHost === null) || false;

if (this.config.nirila.blockMentionsFromUnfamiliarRemoteUsers && user.host !== null && willCauseNotification) {
const isAllowedToCreateNotification = () => {
const targetUserIds: string[] = [
...mentionedUsers.filter(x => x.host == null).map(x => x.id),
Sayamame-beans marked this conversation as resolved.
Show resolved Hide resolved
...(data.visibility === 'specified' && data.visibleUsers != null ? data.visibleUsers.filter(x => x.host == null).map(x => x.id) : []),
...(data.reply != null && data.reply.userHost == null ? [data.reply.userId] : []),
...(this.isRenote(data) && this.isQuote(data) && data.renote.userHost === null ? [data.renote.userId] : []),
];
const allowedIds = new Set(meta.nirilaAllowedUnfamiliarRemoteUserIds);
for (const targetUserId of targetUserIds) {
if (!allowedIds.has(targetUserId)) {
return false;
}
}
return true;
};

if (meta.nirilaBlockMentionsFromUnfamiliarRemoteUsers && user.host !== null && willCauseNotification && !isAllowedToCreateNotification()) {
const userEntity = await this.usersRepository.findOneBy({ id: user.id });
if ((userEntity?.followersCount ?? 0) === 0) {
this.logger.error('Request rejected because user has no local followers', { user: user.id, note: data });
Expand Down
12 changes: 12 additions & 0 deletions packages/backend/src/models/Meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -625,4 +625,16 @@ export class MiMeta {
nullable: true,
})
public urlPreviewUserAgent: string | null;

@Column('boolean', {
default: false,
})
public nirilaBlockMentionsFromUnfamiliarRemoteUsers: boolean;

@Column('varchar', {
length: 32,
array: true,
default: '{}',
})
public nirilaAllowedUnfamiliarRemoteUserIds: string[];
}
16 changes: 16 additions & 0 deletions packages/backend/src/server/api/endpoints/admin/meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,20 @@ export const meta = {
type: 'string',
optional: false, nullable: true,
},
nirilaBlockMentionsFromUnfamiliarRemoteUsers: {
type: 'boolean',
optional: false, nullable: false,
},
nirilaAllowedUnfamiliarRemoteUserIds: {
type: 'array',
optional: false,
nullable: false,
items: {
type: 'string',
optional: false,
nullable: false,
},
},
},
},
} as const;
Expand Down Expand Up @@ -615,6 +629,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
urlPreviewRequireContentLength: instance.urlPreviewRequireContentLength,
urlPreviewUserAgent: instance.urlPreviewUserAgent,
urlPreviewSummaryProxyUrl: instance.urlPreviewSummaryProxyUrl,
nirilaBlockMentionsFromUnfamiliarRemoteUsers: instance.nirilaBlockMentionsFromUnfamiliarRemoteUsers,
nirilaAllowedUnfamiliarRemoteUserIds: instance.nirilaAllowedUnfamiliarRemoteUserIds,
};
});
}
Expand Down
17 changes: 17 additions & 0 deletions packages/backend/src/server/api/endpoints/admin/update-meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,15 @@ export const paramDef = {
urlPreviewRequireContentLength: { type: 'boolean' },
urlPreviewUserAgent: { type: 'string', nullable: true },
urlPreviewSummaryProxyUrl: { type: 'string', nullable: true },
nirilaBlockMentionsFromUnfamiliarRemoteUsers: { type: 'boolean', nullable: false },
nirilaAllowedUnfamiliarRemoteUserIds: {
type: 'array',
nullable: false,
items: {
type: 'string',
nullable: false,
},
}
},
required: [],
} as const;
Expand Down Expand Up @@ -622,6 +631,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
set.urlPreviewSummaryProxyUrl = value === '' ? null : value;
}

if (ps.nirilaBlockMentionsFromUnfamiliarRemoteUsers !== undefined) {
set.nirilaBlockMentionsFromUnfamiliarRemoteUsers = ps.nirilaBlockMentionsFromUnfamiliarRemoteUsers;
}

if (ps.nirilaAllowedUnfamiliarRemoteUserIds !== undefined) {
set.nirilaAllowedUnfamiliarRemoteUserIds = ps.nirilaAllowedUnfamiliarRemoteUserIds;
}

const before = await this.metaService.fetch(true);

await this.metaService.update(set);
Expand Down
16 changes: 16 additions & 0 deletions packages/frontend/src/pages/admin/moderation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #label>{{ i18n.ts.hiddenTags }}</template>
<template #caption>{{ i18n.ts.hiddenTagsDescription }}</template>
</MkTextarea>

<MkSwitch v-model="nirilaBlockMentionsFromUnfamiliarRemoteUsers">
<template #label>未知のリモートユーザーによる通知が発生するノートをブロックする</template>
</MkSwitch>

<MkTextarea v-model="hiddenTags">
<template #label>未知のリモートユーザーによる通知を許可するローカルユーザーのID</template>
<template #caption>`@admin`のようなユーザ名ではなく、`9grmcrkrsl`のようなユーザーのIDであることに注意してください。</template>
</MkTextarea>
</div>
</FormSuspense>
</MkSpacer>
Expand Down Expand Up @@ -93,6 +102,8 @@ const preservedUsernames = ref<string>('');
const tosUrl = ref<string | null>(null);
const privacyPolicyUrl = ref<string | null>(null);
const inquiryUrl = ref<string | null>(null);
const nirilaBlockMentionsFromUnfamiliarRemoteUsers = ref<boolean>(false);
const nirilaAllowedUnfamiliarRemoteUserIds = ref<string>('');

async function init() {
const meta = await misskeyApi('admin/meta');
Expand All @@ -105,6 +116,8 @@ async function init() {
tosUrl.value = meta.tosUrl;
privacyPolicyUrl.value = meta.privacyPolicyUrl;
inquiryUrl.value = meta.inquiryUrl;
nirilaBlockMentionsFromUnfamiliarRemoteUsers.value = meta.nirilaBlockMentionsFromUnfamiliarRemoteUsers;
nirilaAllowedUnfamiliarRemoteUserIds.value = meta.nirilaAllowedUnfamiliarRemoteUserIds.join('\n');
}

function save() {
Expand All @@ -118,6 +131,9 @@ function save() {
prohibitedWords: prohibitedWords.value.split('\n'),
hiddenTags: hiddenTags.value.split('\n'),
preservedUsernames: preservedUsernames.value.split('\n'),
nirilaBlockMentionsFromUnfamiliarRemoteUsers: nirilaBlockMentionsFromUnfamiliarRemoteUsers.value,
nirilaAllowedUnfamiliarRemoteUserIds: nirilaAllowedUnfamiliarRemoteUserIds.value === ''
? [] : nirilaAllowedUnfamiliarRemoteUserIds.value.split('\n'),
}).then(() => {
fetchInstance(true);
});
Expand Down
4 changes: 4 additions & 0 deletions packages/misskey-js/src/autogen/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5100,6 +5100,8 @@ export type operations = {
urlPreviewRequireContentLength: boolean;
urlPreviewUserAgent: string | null;
urlPreviewSummaryProxyUrl: string | null;
nirilaBlockMentionsFromUnfamiliarRemoteUsers: boolean;
nirilaAllowedUnfamiliarRemoteUserIds: string[];
};
};
};
Expand Down Expand Up @@ -9110,6 +9112,8 @@ export type operations = {
urlPreviewRequireContentLength?: boolean;
urlPreviewUserAgent?: string | null;
urlPreviewSummaryProxyUrl?: string | null;
nirilaBlockMentionsFromUnfamiliarRemoteUsers?: boolean;
nirilaAllowedUnfamiliarRemoteUserIds?: string[];
};
};
};
Expand Down
Loading