add user frontend components
This commit is contained in:
@@ -5,7 +5,6 @@ import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
import { UserModule } from './user/user.module';
|
||||
import { AuthModule } from './auth/auth.module';
|
||||
import { User } from './entity/user';
|
||||
import { UserGroup } from './entity/user-group';
|
||||
import { UserRole } from './entity/user-role';
|
||||
import { LoggerModule } from './logger/logger.module';
|
||||
@@ -13,8 +12,9 @@ import { EventType } from './entity/event-type.entity';
|
||||
import { EventTypesModule } from './event-type/event-type.module';
|
||||
import { Product } from './entity/product.entity';
|
||||
import { ProductsModule } from './product/products.module';
|
||||
import { Event } from "./entity/event.entity";
|
||||
import { EventsModule } from "./event/events.module";
|
||||
import { Event } from './entity/event.entity';
|
||||
import { EventsModule } from './event/events.module';
|
||||
import { User } from './entity/user';
|
||||
|
||||
const moduleTypeOrm = TypeOrmModule.forRootAsync({
|
||||
imports: [ConfigModule],
|
||||
@@ -43,8 +43,8 @@ const moduleTypeOrm = TypeOrmModule.forRootAsync({
|
||||
LoggerModule,
|
||||
EventTypesModule,
|
||||
ProductsModule,
|
||||
EventsModule
|
||||
],
|
||||
EventsModule,
|
||||
],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
})
|
||||
|
||||
14
server/src/user/dto/query-user.dto.ts
Normal file
14
server/src/user/dto/query-user.dto.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import {
|
||||
IsOptional,
|
||||
IsString,
|
||||
IsNumber,
|
||||
IsIn,
|
||||
} from 'class-validator';
|
||||
import { Type } from 'class-transformer';
|
||||
|
||||
export class QueryUserDto {
|
||||
@IsOptional() @Type(() => Number) @IsNumber() page?: number;
|
||||
@IsOptional() @Type(() => Number) @IsNumber() limit?: number;
|
||||
@IsOptional() @IsString() sortBy?: string;
|
||||
@IsOptional() @IsIn(['ASC', 'DESC']) order?: 'ASC' | 'DESC';
|
||||
}
|
||||
@@ -8,6 +8,9 @@ import {
|
||||
Delete,
|
||||
UseGuards,
|
||||
ValidationPipe,
|
||||
Query,
|
||||
DefaultValuePipe,
|
||||
ParseIntPipe,
|
||||
} from '@nestjs/common';
|
||||
import { UserService } from './user.service';
|
||||
import { CreateUserDto } from './dto/create-user.dto';
|
||||
@@ -18,7 +21,7 @@ import { Roles } from '../auth/roles.decorator';
|
||||
import { Role } from '../auth/role.enum';
|
||||
import { RolesGuard } from '../auth/roles.guard';
|
||||
|
||||
@Controller('users')
|
||||
@Controller('user')
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles(Role.Admin)
|
||||
export class UserController {
|
||||
@@ -36,6 +39,15 @@ export class UserController {
|
||||
return this.userService.findAll();
|
||||
}
|
||||
|
||||
@Get('search')
|
||||
search(
|
||||
@Query('q') term: string,
|
||||
@Query('page', new DefaultValuePipe(1), ParseIntPipe) page: number,
|
||||
@Query('limit', new DefaultValuePipe(10), ParseIntPipe) limit: number,
|
||||
) {
|
||||
return this.userService.search(term, { page, limit });
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
findOne(@Param('id') id: string): Promise<User | null> {
|
||||
return this.userService.findOne(+id);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { ILike, Repository } from 'typeorm';
|
||||
import { User } from '../entity/user';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
import { FindOptionsRelations } from 'typeorm/find-options/FindOptionsRelations';
|
||||
@@ -8,6 +8,8 @@ import { DvbookingLoggerService } from '../logger/dvbooking-logger.service';
|
||||
|
||||
@Injectable()
|
||||
export class UserService {
|
||||
private readonly searchableFields: (keyof User)[] = ['username', 'email'];
|
||||
|
||||
constructor(
|
||||
@InjectRepository(User)
|
||||
private usersRepository: Repository<User>,
|
||||
@@ -55,6 +57,40 @@ export class UserService {
|
||||
await this.usersRepository.delete(id);
|
||||
}
|
||||
|
||||
async search(term: string, options: { page: number; limit: number }) {
|
||||
if (this.searchableFields.length === 0) {
|
||||
console.warn('Search is not configured for this entity.');
|
||||
return {
|
||||
data: [],
|
||||
meta: {
|
||||
totalItems: 0,
|
||||
itemCount: 0,
|
||||
itemsPerPage: options.limit,
|
||||
totalPages: 0,
|
||||
currentPage: options.page,
|
||||
},
|
||||
};
|
||||
}
|
||||
const whereConditions = this.searchableFields.map((field) => ({
|
||||
[field]: ILike(`%${term}%`),
|
||||
}));
|
||||
const [data, totalItems] = await this.usersRepository.findAndCount({
|
||||
where: whereConditions,
|
||||
skip: (options.page - 1) * options.limit,
|
||||
take: options.limit,
|
||||
});
|
||||
return {
|
||||
data,
|
||||
meta: {
|
||||
totalItems,
|
||||
itemCount: data.length,
|
||||
itemsPerPage: options.limit,
|
||||
totalPages: Math.ceil(totalItems / options.limit),
|
||||
currentPage: options.page,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async setRefreshToken(
|
||||
id: number,
|
||||
refreshToken: string | null,
|
||||
|
||||
Reference in New Issue
Block a user