diff --git a/packages/backend/migration/1732538997055-AddEnableAllowedEmailDomainOnly.js b/packages/backend/migration/1732538997055-AddEnableAllowedEmailDomainOnly.js new file mode 100644 index 0000000000..4f30ac2dc8 --- /dev/null +++ b/packages/backend/migration/1732538997055-AddEnableAllowedEmailDomainOnly.js @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class AddEnableAllowedEmailDomainOnly1732538997055 { + name = 'AddEnableAllowedEmailDomainOnly1732538997055' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ADD "enableAllowedEmailDomainsOnly" boolean NOT NULL DEFAULT false`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableAllowedEmailDomainsOnly"`); + } +} diff --git a/packages/backend/src/core/EmailService.ts b/packages/backend/src/core/EmailService.ts index 71d2c2c668..95a1290125 100644 --- a/packages/backend/src/core/EmailService.ts +++ b/packages/backend/src/core/EmailService.ts @@ -164,7 +164,7 @@ export class EmailService { @bindThis public async validateEmailForAccount(emailAddress: string): Promise<{ available: boolean; - reason: null | 'used' | 'format' | 'disposable' | 'mx' | 'smtp' | 'banned' | 'network' | 'blacklist'; + reason: null | 'used' | 'format' | 'disposable' | 'mx' | 'smtp' | 'banned' | 'network' | 'blacklist' | 'allowedOnly'; }> { const exist = await this.userProfilesRepository.countBy({ emailVerified: true, @@ -188,6 +188,14 @@ export class EmailService { }; } + // ホワイトリストのみ許可の場合は即座にfalseを返す + if (this.meta.enableAllowedEmailDomainsOnly) { + return { + available: false, + reason: 'allowedOnly', + }; + } + const isBanned = this.utilityService.isBlockedHost(this.meta.bannedEmailDomains, emailDomain); if (isBanned) { diff --git a/packages/backend/src/models/Meta.ts b/packages/backend/src/models/Meta.ts index 7966df0bcf..e386353497 100644 --- a/packages/backend/src/models/Meta.ts +++ b/packages/backend/src/models/Meta.ts @@ -581,6 +581,11 @@ export class MiMeta { }) public enableAutoAddBannedEmailDomain: boolean; + @Column('boolean', { + default: false, + }) + public enableAllowedEmailDomainsOnly: boolean; + @Column('varchar', { length: 1024, array: true, default: '{ "admin", "administrator", "root", "system", "maintainer", "host", "mod", "moderator", "owner", "superuser", "staff", "auth", "i", "me", "everyone", "all", "mention", "mentions", "example", "user", "users", "account", "accounts", "official", "help", "helps", "support", "supports", "info", "information", "informations", "announce", "announces", "announcement", "announcements", "notice", "notification", "notifications", "dev", "developer", "developers", "tech", "misskey" }', }) diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index 4a6322f8f7..7429171a15 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -352,6 +352,10 @@ export const meta = { type: 'boolean', optional: false, nullable: false, }, + enableAllowedEmailDomainsOnly: { + type: 'boolean', + optional: false, nullable: false, + }, enableChartsForRemoteUser: { type: 'boolean', optional: false, nullable: false, @@ -650,6 +654,7 @@ export default class extends Endpoint { // eslint- truemailInstance: instance.truemailInstance, truemailAuthKey: instance.truemailAuthKey, enableAutoAddBannedEmailDomain: instance.enableAutoAddBannedEmailDomain, + enableAllowedEmailDomainsOnly: instance.enableAllowedEmailDomainsOnly, enableChartsForRemoteUser: instance.enableChartsForRemoteUser, enableChartsForFederatedInstances: instance.enableChartsForFederatedInstances, enableStatsForFederatedInstances: instance.enableStatsForFederatedInstances, diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts index cf6c46a33b..e54096b6d5 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -143,6 +143,7 @@ export const paramDef = { bannedEmailDomains: { type: 'array', items: { type: 'string' } }, allowedEmailDomains: { type: 'array', items: { type: 'string' } }, enableAutoAddBannedEmailDomain: { type: 'boolean' }, + enableAllowedEmailDomainsOnly: { type: 'boolean' }, preservedUsernames: { type: 'array', items: { type: 'string' } }, manifestJsonOverride: { type: 'string' }, enableFanoutTimeline: { type: 'boolean' }, @@ -649,6 +650,10 @@ export default class extends Endpoint { // eslint- set.enableAutoAddBannedEmailDomain = ps.enableAutoAddBannedEmailDomain; } + if (ps.enableAllowedEmailDomainsOnly !== undefined) { + set.enableAllowedEmailDomainsOnly = ps.enableAllowedEmailDomainsOnly; + } + if (ps.urlPreviewEnabled !== undefined) { set.urlPreviewEnabled = ps.urlPreviewEnabled; } diff --git a/packages/frontend/src/pages/admin/security.vue b/packages/frontend/src/pages/admin/security.vue index b9cf7a4578..182b77f260 100644 --- a/packages/frontend/src/pages/admin/security.vue +++ b/packages/frontend/src/pages/admin/security.vue @@ -101,6 +101,10 @@ SPDX-License-Identifier: AGPL-3.0-only + + + + @@ -213,9 +217,11 @@ const emailValidationForm = useForm({ const allowedEmailDomainsForm = useForm({ allowedEmailDomains: meta.allowedEmailDomains?.join('\n') || '', + enableAllowedEmailDomainsOnly: meta.enableAllowedEmailDomainsOnly, }, async (state) => { await os.apiWithDialog('admin/update-meta', { allowedEmailDomains: state.allowedEmailDomains.split('\n'), + enableAllowedEmailDomainsOnly: state.enableAllowedEmailDomainsOnly, }); fetchInstance(true); }); diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 06dea39fc3..12b9ffb573 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -5177,6 +5177,7 @@ export type operations = { truemailInstance: string | null; truemailAuthKey: string | null; enableAutoAddBannedEmailDomain: boolean; + enableAllowedEmailDomainsOnly: boolean; enableChartsForRemoteUser: boolean; enableChartsForFederatedInstances: boolean; enableStatsForFederatedInstances: boolean; @@ -9582,6 +9583,7 @@ export type operations = { bannedEmailDomains?: string[]; allowedEmailDomains?: string[]; enableAutoAddBannedEmailDomain?: boolean; + enableAllowedEmailDomainsOnly?: boolean; preservedUsernames?: string[]; manifestJsonOverride?: string; enableFanoutTimeline?: boolean;