Skip to content

Commit a5e9061

Browse files
authored
Merge pull request #227 from import-ai/refactor/blocked_names
refactor/blocked names
2 parents 081bf00 + c26fe14 commit a5e9061

File tree

7 files changed

+360
-23
lines changed

7 files changed

+360
-23
lines changed

src/auth/social.service.ts

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { HttpStatus, Injectable } from '@nestjs/common';
66
import { AppException } from 'omniboxd/common/exceptions/app.exception';
77
import { I18nService } from 'nestjs-i18n';
88
import { CacheService } from 'omniboxd/common/cache.service';
9+
import { NamespacesService } from 'omniboxd/namespaces/namespaces.service';
10+
import { isNameBlocked } from 'omniboxd/utils/blocked-names';
911

1012
export interface UserSocialState {
1113
type: string;
@@ -24,6 +26,7 @@ export class SocialService {
2426
private readonly userService: UserService,
2527
private readonly i18n: I18nService,
2628
private readonly cacheService: CacheService,
29+
private readonly namespacesService: NamespacesService,
2730
) {}
2831

2932
/**
@@ -71,6 +74,33 @@ export class SocialService {
7174
);
7275
}
7376

77+
private async isUsernameValid(
78+
username: string,
79+
manager: EntityManager,
80+
): Promise<boolean> {
81+
if (isNameBlocked(username)) {
82+
return false;
83+
}
84+
85+
const user = await this.userService.findByUsername(username, manager);
86+
if (user) {
87+
return false;
88+
}
89+
90+
const namespaceName = this.i18n.t('namespace.userNamespaceName', {
91+
args: { userName: username },
92+
});
93+
const namespace = await this.namespacesService.getNamespaceByName(
94+
namespaceName,
95+
manager,
96+
);
97+
if (namespace) {
98+
return false;
99+
}
100+
101+
return true;
102+
}
103+
74104
async getValidUsername(
75105
nickname: string,
76106
manager: EntityManager,
@@ -81,21 +111,18 @@ export class SocialService {
81111
username = nickname.slice(0, this.maxUsernameLength);
82112
}
83113
if (username.length >= this.minUsernameLength) {
84-
const user = await this.userService.findByUsername(username, manager);
85-
if (!user) {
114+
const ok = await this.isUsernameValid(username, manager);
115+
if (ok) {
86116
return username;
87117
}
88118
}
89119

90120
username = nickname.slice(0, this.maxUsernameLength - 5);
91121
for (let i = 0; i < 5; i++) {
92-
const suffix = this.generateSuffix();
93-
const user = await this.userService.findByUsername(
94-
username + suffix,
95-
manager,
96-
);
97-
if (!user) {
98-
return username + suffix;
122+
const curUsername = username + this.generateSuffix();
123+
const ok = await this.isUsernameValid(curUsername, manager);
124+
if (ok) {
125+
return curUsername;
99126
}
100127
}
101128

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import { IsString, IsNotEmpty } from 'class-validator';
1+
import { IsString, IsNotEmpty, MinLength, MaxLength } from 'class-validator';
22

33
export class CreateNamespaceDto {
44
@IsString()
55
@IsNotEmpty()
6+
@MinLength(2)
7+
@MaxLength(64)
68
name: string;
79
}
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1-
import { IsString, IsOptional, IsNotEmpty } from 'class-validator';
1+
import {
2+
IsString,
3+
IsOptional,
4+
IsNotEmpty,
5+
MinLength,
6+
MaxLength,
7+
} from 'class-validator';
28

39
export class UpdateNamespaceDto {
410
@IsString()
511
@IsOptional()
612
@IsNotEmpty()
13+
@MinLength(2)
14+
@MaxLength(64)
715
name?: string;
816
}

src/namespaces/namespaces.e2e-spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ describe('NamespacesController (e2e)', () => {
420420
});
421421

422422
it('should handle very long namespace names', async () => {
423-
const longName = 'A'.repeat(255); // Test boundary conditions
423+
const longName = 'A'.repeat(64); // Test boundary conditions
424424
const longNameWorkspace = {
425425
name: longName,
426426
};

src/namespaces/namespaces.service.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { ResourcesService } from 'omniboxd/resources/resources.service';
1919
import { ResourceMetaDto } from 'omniboxd/resources/dto/resource-meta.dto';
2020
import { AppException } from 'omniboxd/common/exceptions/app.exception';
2121
import { I18nService } from 'nestjs-i18n';
22+
import { isNameBlocked } from 'omniboxd/utils/blocked-names';
2223

2324
@Injectable()
2425
export class NamespacesService {
@@ -173,7 +174,10 @@ export class NamespacesService {
173174
name: string,
174175
manager: EntityManager,
175176
): Promise<Namespace> {
176-
if ((await manager.countBy(Namespace, { name })) > 0) {
177+
if (
178+
isNameBlocked(name) ||
179+
(await manager.countBy(Namespace, { name })) > 0
180+
) {
177181
const message = this.i18n.t('namespace.errors.namespaceConflict');
178182
throw new AppException(
179183
message,
@@ -197,6 +201,16 @@ export class NamespacesService {
197201
return namespace;
198202
}
199203

204+
async getNamespaceByName(
205+
name: string,
206+
entityManager?: EntityManager,
207+
): Promise<Namespace | null> {
208+
const repo = entityManager
209+
? entityManager.getRepository(Namespace)
210+
: this.namespaceRepository;
211+
return repo.findOne({ where: { name } });
212+
}
213+
200214
async update(
201215
id: string,
202216
updateDto: UpdateNamespaceDto,
@@ -207,7 +221,10 @@ export class NamespacesService {
207221
: this.namespaceRepository;
208222
const namespace = await this.getNamespace(id, manager);
209223
if (updateDto.name && updateDto.name !== namespace.name) {
210-
if ((await repo.countBy({ name: updateDto.name })) > 0) {
224+
if (
225+
isNameBlocked(updateDto.name) ||
226+
(await repo.countBy({ name: updateDto.name })) > 0
227+
) {
211228
const message = this.i18n.t('namespace.errors.namespaceConflict');
212229
throw new AppException(
213230
message,

src/user/user.service.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { CreateUserOptionDto } from 'omniboxd/user/dto/create-user-option.dto';
1313
import { UpdateUserBindingDto } from 'omniboxd/user/dto/update-user-binding.dto';
1414
import { CreateUserBindingDto } from 'omniboxd/user/dto/create-user-binding.dto';
1515
import { Injectable, HttpStatus } from '@nestjs/common';
16-
import { isUsernameBlocked } from 'omniboxd/utils/blocked-usernames';
16+
import { isNameBlocked } from 'omniboxd/utils/blocked-names';
1717
import { AppException } from 'omniboxd/common/exceptions/app.exception';
1818
import { I18nService } from 'nestjs-i18n';
1919
import { CacheService } from 'omniboxd/common/cache.service';
@@ -84,7 +84,7 @@ export class UserService {
8484
}
8585

8686
async create(account: CreateUserDto, manager?: EntityManager) {
87-
if (account.username && isUsernameBlocked(account.username)) {
87+
if (account.username && isNameBlocked(account.username)) {
8888
const message = this.i18n.t('user.errors.accountAlreadyExists');
8989
throw new AppException(
9090
message,
@@ -341,7 +341,7 @@ export class UserService {
341341
HttpStatus.BAD_REQUEST,
342342
);
343343
}
344-
if (account.username && isUsernameBlocked(account.username)) {
344+
if (account.username && isNameBlocked(account.username)) {
345345
const message = this.i18n.t('user.errors.accountAlreadyExists');
346346
throw new AppException(
347347
message,

0 commit comments

Comments
 (0)