Sửa lỗi hiện danh sách trong bảng thêm thành viên
This commit is contained in:
Vendored
+16
-10
@@ -16,7 +16,6 @@ import { Module, Controller, Get, Post, Body, Param, Patch, Delete, ParseUUIDPip
|
|||||||
import { PrismaService } from './prisma.service.js';
|
import { PrismaService } from './prisma.service.js';
|
||||||
import 'dotenv/config';
|
import 'dotenv/config';
|
||||||
import * as bcrypt from 'bcrypt';
|
import * as bcrypt from 'bcrypt';
|
||||||
import { AdminGuard } from './admin.guard.js';
|
|
||||||
import { JwtModule, JwtService } from '@nestjs/jwt';
|
import { JwtModule, JwtService } from '@nestjs/jwt';
|
||||||
import { JwtAuthGuard } from './jwt-auth.guard.js';
|
import { JwtAuthGuard } from './jwt-auth.guard.js';
|
||||||
import { JwtStrategy } from './jwt.strategy.js';
|
import { JwtStrategy } from './jwt.strategy.js';
|
||||||
@@ -671,8 +670,9 @@ let UserController = class UserController {
|
|||||||
constructor(prisma) {
|
constructor(prisma) {
|
||||||
this.prisma = prisma;
|
this.prisma = prisma;
|
||||||
}
|
}
|
||||||
async getAllUsers(q) {
|
async getAllUsers(req, q) {
|
||||||
return this.prisma.user.findMany({
|
const currentUserId = req.user?.sub;
|
||||||
|
const users = await this.prisma.user.findMany({
|
||||||
where: q
|
where: q
|
||||||
? {
|
? {
|
||||||
OR: [
|
OR: [
|
||||||
@@ -683,6 +683,7 @@ let UserController = class UserController {
|
|||||||
: undefined,
|
: undefined,
|
||||||
select: { id: true, email: true, name: true, isAdmin: true, isBlocked: true, createdAt: true, phone: true, address: true }
|
select: { id: true, email: true, name: true, isAdmin: true, isBlocked: true, createdAt: true, phone: true, address: true }
|
||||||
});
|
});
|
||||||
|
return users.filter((u) => u.id !== currentUserId);
|
||||||
}
|
}
|
||||||
async updateUser(id, data) {
|
async updateUser(id, data) {
|
||||||
if (data.password) {
|
if (data.password) {
|
||||||
@@ -697,29 +698,35 @@ let UserController = class UserController {
|
|||||||
}
|
}
|
||||||
async deleteUser(id) {
|
async deleteUser(id) {
|
||||||
const user = await this.prisma.user.findUnique({ where: { id } });
|
const user = await this.prisma.user.findUnique({ where: { id } });
|
||||||
if (user?.isAdmin) {
|
if (!user)
|
||||||
|
throw new NotFoundException('Không tìm thấy người dùng');
|
||||||
|
if (user.isAdmin) {
|
||||||
const adminCount = await this.prisma.user.count({ where: { isAdmin: true } });
|
const adminCount = await this.prisma.user.count({ where: { isAdmin: true } });
|
||||||
if (adminCount <= 1)
|
if (adminCount <= 1)
|
||||||
throw new BadRequestException('Không thể xóa Quản trị viên cuối cùng');
|
throw new BadRequestException('Không thể xóa Quản trị viên cuối cùng');
|
||||||
}
|
}
|
||||||
|
await this.prisma.tourParticipant.deleteMany({ where: { userId: id } });
|
||||||
await this.prisma.user.delete({ where: { id } });
|
await this.prisma.user.delete({ where: { id } });
|
||||||
return { success: true };
|
return { message: 'Đã xóa người dùng' };
|
||||||
}
|
}
|
||||||
async toggleBlock(id) {
|
async toggleBlock(id) {
|
||||||
const user = await this.prisma.user.findUnique({ where: { id } });
|
const user = await this.prisma.user.findUnique({ where: { id } });
|
||||||
if (!user)
|
if (!user)
|
||||||
throw new NotFoundException('Người dùng không tồn tại');
|
throw new NotFoundException('Người dùng không tồn tại');
|
||||||
return this.prisma.user.update({
|
const updated = await this.prisma.user.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { isBlocked: !user.isBlocked }
|
data: { isBlocked: !user.isBlocked },
|
||||||
|
select: { id: true, email: true, name: true, isBlocked: true }
|
||||||
});
|
});
|
||||||
|
return updated;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
__decorate([
|
__decorate([
|
||||||
Get(),
|
Get(),
|
||||||
__param(0, Query('q')),
|
__param(0, Req()),
|
||||||
|
__param(1, Query('q')),
|
||||||
__metadata("design:type", Function),
|
__metadata("design:type", Function),
|
||||||
__metadata("design:paramtypes", [String]),
|
__metadata("design:paramtypes", [Object, String]),
|
||||||
__metadata("design:returntype", Promise)
|
__metadata("design:returntype", Promise)
|
||||||
], UserController.prototype, "getAllUsers", null);
|
], UserController.prototype, "getAllUsers", null);
|
||||||
__decorate([
|
__decorate([
|
||||||
@@ -746,7 +753,6 @@ __decorate([
|
|||||||
], UserController.prototype, "toggleBlock", null);
|
], UserController.prototype, "toggleBlock", null);
|
||||||
UserController = __decorate([
|
UserController = __decorate([
|
||||||
Controller('v1/users'),
|
Controller('v1/users'),
|
||||||
UseGuards(JwtAuthGuard, AdminGuard),
|
|
||||||
__metadata("design:paramtypes", [PrismaService])
|
__metadata("design:paramtypes", [PrismaService])
|
||||||
], UserController);
|
], UserController);
|
||||||
let AppModule = class AppModule {
|
let AppModule = class AppModule {
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+5
-1
@@ -9,9 +9,13 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|||||||
};
|
};
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { PrismaClient } from '@prisma/client';
|
import { PrismaClient } from '@prisma/client';
|
||||||
|
import { PrismaPg } from '@prisma/adapter-pg';
|
||||||
|
import { Pool } from 'pg';
|
||||||
let PrismaService = class PrismaService extends PrismaClient {
|
let PrismaService = class PrismaService extends PrismaClient {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
|
||||||
|
const adapter = new PrismaPg(pool);
|
||||||
|
super({ adapter });
|
||||||
}
|
}
|
||||||
async onModuleInit() { await this.$connect(); }
|
async onModuleInit() { await this.$connect(); }
|
||||||
async onModuleDestroy() { await this.$disconnect(); }
|
async onModuleDestroy() { await this.$disconnect(); }
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"prisma.service.js","sourceRoot":"","sources":["../prisma.service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,UAAU,EAAiC,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGvC,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,YAAY;IAC7C;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAED,KAAK,CAAC,YAAY,KAAK,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC/C,KAAK,CAAC,eAAe,KAAK,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;CACtD,CAAA;AAPY,aAAa;IADzB,UAAU,EAAE;;GACA,aAAa,CAOzB"}
|
{"version":3,"file":"prisma.service.js","sourceRoot":"","sources":["../prisma.service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,UAAU,EAAiC,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAGnB,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,YAAY;IAC7C;QACE,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,EAAE,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC;QACtE,MAAM,OAAO,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;QACnC,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,YAAY,KAAK,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC/C,KAAK,CAAC,eAAe,KAAK,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;CACtD,CAAA;AATY,aAAa;IADzB,UAAU,EAAE;;GACA,aAAa,CASzB"}
|
||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -598,13 +598,13 @@ class RoutingController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Controller('v1/users')
|
@Controller('v1/users')
|
||||||
@UseGuards(JwtAuthGuard, AdminGuard)
|
|
||||||
class UserController {
|
class UserController {
|
||||||
constructor(private prisma: PrismaService) {}
|
constructor(private prisma: PrismaService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
async getAllUsers(@Query('q') q?: string) {
|
async getAllUsers(@Req() req: any, @Query('q') q?: string) {
|
||||||
return this.prisma.user.findMany({
|
const currentUserId = req.user?.sub;
|
||||||
|
const users = await this.prisma.user.findMany({
|
||||||
where: q
|
where: q
|
||||||
? {
|
? {
|
||||||
OR: [
|
OR: [
|
||||||
@@ -615,11 +615,11 @@ class UserController {
|
|||||||
: undefined,
|
: undefined,
|
||||||
select: { id: true, email: true, name: true, isAdmin: true, isBlocked: true, createdAt: true, phone: true, address: true }
|
select: { id: true, email: true, name: true, isAdmin: true, isBlocked: true, createdAt: true, phone: true, address: true }
|
||||||
});
|
});
|
||||||
|
return users.filter((u: any) => u.id !== currentUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id')
|
@Patch(':id')
|
||||||
async updateUser(@Param('id', ParseUUIDPipe) id: string, @Body() data: any) {
|
async updateUser(@Param('id', ParseUUIDPipe) id: string, @Body() data: any) {
|
||||||
// Nếu đổi mật khẩu thì cần hash
|
|
||||||
if (data.password) {
|
if (data.password) {
|
||||||
data.passwordHash = await bcrypt.hash(data.password, 10);
|
data.passwordHash = await bcrypt.hash(data.password, 10);
|
||||||
delete data.password;
|
delete data.password;
|
||||||
@@ -633,24 +633,27 @@ class UserController {
|
|||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
async deleteUser(@Param('id', ParseUUIDPipe) id: string) {
|
async deleteUser(@Param('id', ParseUUIDPipe) id: string) {
|
||||||
// Không cho phép tự xóa chính mình hoặc xóa admin cuối cùng (logic đơn giản)
|
|
||||||
const user = await this.prisma.user.findUnique({ where: { id } });
|
const user = await this.prisma.user.findUnique({ where: { id } });
|
||||||
if (user?.isAdmin) {
|
if (!user) throw new NotFoundException('Không tìm thấy người dùng');
|
||||||
|
if (user.isAdmin) {
|
||||||
const adminCount = await this.prisma.user.count({ where: { isAdmin: true } });
|
const adminCount = await this.prisma.user.count({ where: { isAdmin: true } });
|
||||||
if (adminCount <= 1) throw new BadRequestException('Không thể xóa Quản trị viên cuối cùng');
|
if (adminCount <= 1) throw new BadRequestException('Không thể xóa Quản trị viên cuối cùng');
|
||||||
}
|
}
|
||||||
|
await this.prisma.tourParticipant.deleteMany({ where: { userId: id } });
|
||||||
await this.prisma.user.delete({ where: { id } });
|
await this.prisma.user.delete({ where: { id } });
|
||||||
return { success: true };
|
return { message: 'Đã xóa người dùng' };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('block/:id')
|
@Post('block/:id')
|
||||||
async toggleBlock(@Param('id', ParseUUIDPipe) id: string) {
|
async toggleBlock(@Param('id', ParseUUIDPipe) id: string) {
|
||||||
const user = await this.prisma.user.findUnique({ where: { id } });
|
const user = await this.prisma.user.findUnique({ where: { id } });
|
||||||
if (!user) throw new NotFoundException('Người dùng không tồn tại');
|
if (!user) throw new NotFoundException('Người dùng không tồn tại');
|
||||||
return this.prisma.user.update({
|
const updated = await this.prisma.user.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { isBlocked: !user.isBlocked }
|
data: { isBlocked: !user.isBlocked },
|
||||||
|
select: { id: true, email: true, name: true, isBlocked: true }
|
||||||
});
|
});
|
||||||
|
return updated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -1,10 +1,14 @@
|
|||||||
import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
|
import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
|
||||||
import { PrismaClient } from '@prisma/client';
|
import { PrismaClient } from '@prisma/client';
|
||||||
|
import { PrismaPg } from '@prisma/adapter-pg';
|
||||||
|
import { Pool } from 'pg';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
|
export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
|
||||||
|
const adapter = new PrismaPg(pool);
|
||||||
|
super({ adapter });
|
||||||
}
|
}
|
||||||
|
|
||||||
async onModuleInit() { await this.$connect(); }
|
async onModuleInit() { await this.$connect(); }
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
import { PrismaClient } from './prisma/client.js';
|
|
||||||
import bcrypt from 'bcrypt';
|
|
||||||
|
|
||||||
const prisma = new PrismaClient();
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
const email = 'owner@travel.com';
|
|
||||||
const newPassword = 'admin123';
|
|
||||||
const hash = await bcrypt.hash(newPassword, 10);
|
|
||||||
|
|
||||||
const user = await prisma.user.findUnique({ where: { email } });
|
|
||||||
if (!user) {
|
|
||||||
console.log('Tạo tài khoản admin mới...');
|
|
||||||
await prisma.user.create({
|
|
||||||
data: {
|
|
||||||
email,
|
|
||||||
passwordHash: hash,
|
|
||||||
name: 'Admin',
|
|
||||||
isAdmin: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
await prisma.user.update({
|
|
||||||
where: { email },
|
|
||||||
data: { passwordHash: hash, isAdmin: true },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Đã cập nhật xong mật khẩu cho ${email}`);
|
|
||||||
await prisma.$disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
main();
|
|
||||||
Reference in New Issue
Block a user