feat: preserved usernames

Resolve #10704
This commit is contained in:
syuilo
2023-04-29 17:03:14 +09:00
parent e8177ee311
commit 0ad7869249
11 changed files with 68 additions and 6 deletions

View File

@@ -1,6 +1,7 @@
import { Inject, Injectable } from '@nestjs/common';
import rndstr from 'rndstr';
import bcrypt from 'bcryptjs';
import { IsNull } from 'typeorm';
import { DI } from '@/di-symbols.js';
import type { RegistrationTicketsRepository, UsedUsernamesRepository, UserPendingsRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js';
import type { Config } from '@/config.js';
@@ -15,7 +16,6 @@ import { FastifyReplyError } from '@/misc/fastify-reply-error.js';
import { bindThis } from '@/decorators.js';
import { SigninService } from './SigninService.js';
import type { FastifyRequest, FastifyReply } from 'fastify';
import { IsNull } from 'typeorm';
@Injectable()
export class SignupApiService {
@@ -137,6 +137,11 @@ export class SignupApiService {
throw new FastifyReplyError(400, 'USED_USERNAME');
}
const isPreserved = instance.preservedUsernames.map(x => x.toLowerCase()).includes(username.toLowerCase());
if (isPreserved) {
throw new FastifyReplyError(400, 'USED_USERNAME');
}
const code = rndstr('a-z0-9', 16);
// Generate hash of password

View File

@@ -52,6 +52,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
const { account, secret } = await this.signupService.signup({
username: ps.username,
password: ps.password,
ignorePreservedUsernames: true,
});
const res = await this.userEntityService.pack(account, account, {

View File

@@ -118,6 +118,14 @@ export const meta = {
optional: false, nullable: false,
},
},
preservedUsernames: {
type: 'array',
optional: false, nullable: false,
items: {
type: 'string',
optional: false, nullable: false,
},
},
hcaptchaSecretKey: {
type: 'string',
optional: true, nullable: true,
@@ -311,6 +319,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
hiddenTags: instance.hiddenTags,
blockedHosts: instance.blockedHosts,
sensitiveWords: instance.sensitiveWords,
preservedUsernames: instance.preservedUsernames,
hcaptchaSecretKey: instance.hcaptchaSecretKey,
recaptchaSecretKey: instance.recaptchaSecretKey,
turnstileSecretKey: instance.turnstileSecretKey,

View File

@@ -95,6 +95,7 @@ export const paramDef = {
enableChartsForRemoteUser: { type: 'boolean' },
enableChartsForFederatedInstances: { type: 'boolean' },
serverRules: { type: 'array', items: { type: 'string' } },
preservedUsernames: { type: 'array', items: { type: 'string' } },
},
required: [],
} as const;
@@ -392,6 +393,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
set.serverRules = ps.serverRules;
}
if (ps.preservedUsernames !== undefined) {
set.preservedUsernames = ps.preservedUsernames;
}
await this.metaService.update(set);
this.moderationLogService.insertModerationLog(me, 'updateMeta');
});

View File

@@ -4,6 +4,7 @@ import type { UsedUsernamesRepository, UsersRepository } from '@/models/index.js
import { Endpoint } from '@/server/api/endpoint-base.js';
import { localUsernameSchema } from '@/models/entities/User.js';
import { DI } from '@/di-symbols.js';
import { MetaService } from '@/core/MetaService.js';
export const meta = {
tags: ['users'],
@@ -39,9 +40,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
@Inject(DI.usedUsernamesRepository)
private usedUsernamesRepository: UsedUsernamesRepository,
private metaService: MetaService,
) {
super(meta, paramDef, async (ps, me) => {
// Get exist
const exist = await this.usersRepository.countBy({
host: IsNull(),
usernameLower: ps.username.toLowerCase(),
@@ -49,8 +51,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
const exist2 = await this.usedUsernamesRepository.countBy({ username: ps.username.toLowerCase() });
const meta = await this.metaService.fetch();
const isPreserved = meta.preservedUsernames.map(x => x.toLowerCase()).includes(ps.username.toLowerCase());
return {
available: exist === 0 && exist2 === 0,
available: exist === 0 && exist2 === 0 && !isPreserved,
};
});
}