251211:1314 Frontend: reeactor Admin panel
This commit is contained in:
@@ -11,9 +11,9 @@ import {
|
||||
} from 'typeorm';
|
||||
import { User } from './user.entity';
|
||||
import { Role } from './role.entity';
|
||||
import { Organization } from '../../project/entities/organization.entity'; // ปรับ Path ให้ตรงกับ ProjectModule
|
||||
import { Organization } from '../../organization/entities/organization.entity'; // ปรับ Path ให้ตรงกับ ProjectModule
|
||||
import { Project } from '../../project/entities/project.entity'; // ปรับ Path ให้ตรงกับ ProjectModule
|
||||
import { Contract } from '../../project/entities/contract.entity'; // ปรับ Path ให้ตรงกับ ProjectModule
|
||||
import { Contract } from '../../contract/entities/contract.entity'; // ปรับ Path ให้ตรงกับ ProjectModule
|
||||
|
||||
@Entity('user_assignments')
|
||||
export class UserAssignment {
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
OneToOne,
|
||||
JoinColumn,
|
||||
} from 'typeorm';
|
||||
import { Organization } from '../../project/entities/organization.entity'; // Adjust path as needed
|
||||
import { Organization } from '../../organization/entities/organization.entity'; // Adjust path as needed
|
||||
import { UserAssignment } from './user-assignment.entity';
|
||||
import { UserPreference } from './user-preference.entity';
|
||||
|
||||
|
||||
@@ -93,6 +93,16 @@ export class UserController {
|
||||
return this.userService.findAllPermissions();
|
||||
}
|
||||
|
||||
@Patch('roles/:id/permissions')
|
||||
@RequirePermission('permission.assign')
|
||||
@ApiOperation({ summary: 'Update role permissions' })
|
||||
async updateRolePermissions(
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Body('permissionIds') permissionIds: number[]
|
||||
) {
|
||||
return this.userService.updateRolePermissions(id, permissionIds);
|
||||
}
|
||||
|
||||
// --- User CRUD (Admin) ---
|
||||
|
||||
@Post()
|
||||
|
||||
@@ -4,6 +4,8 @@ import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
import { CACHE_MANAGER } from '@nestjs/cache-manager';
|
||||
import { UserService } from './user.service';
|
||||
import { User } from './entities/user.entity';
|
||||
import { Role } from './entities/role.entity';
|
||||
import { Permission } from './entities/permission.entity';
|
||||
|
||||
// Mock Repository
|
||||
const mockUserRepository = {
|
||||
@@ -14,6 +16,14 @@ const mockUserRepository = {
|
||||
merge: jest.fn(),
|
||||
softDelete: jest.fn(),
|
||||
query: jest.fn(),
|
||||
createQueryBuilder: jest.fn(() => ({
|
||||
leftJoinAndSelect: jest.fn().mockReturnThis(),
|
||||
select: jest.fn().mockReturnThis(),
|
||||
andWhere: jest.fn().mockReturnThis(),
|
||||
skip: jest.fn().mockReturnThis(),
|
||||
take: jest.fn().mockReturnThis(),
|
||||
getManyAndCount: jest.fn().mockResolvedValue([[], 0]),
|
||||
})),
|
||||
};
|
||||
|
||||
// Mock Cache Manager
|
||||
@@ -38,6 +48,14 @@ describe('UserService', () => {
|
||||
provide: CACHE_MANAGER,
|
||||
useValue: mockCacheManager,
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(Role),
|
||||
useValue: mockUserRepository, // Reuse generic mock
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(Permission),
|
||||
useValue: mockUserRepository, // Reuse generic mock
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
@@ -53,14 +71,26 @@ describe('UserService', () => {
|
||||
});
|
||||
|
||||
describe('findAll', () => {
|
||||
it('should return array of users', async () => {
|
||||
it('should return paginated users', async () => {
|
||||
const mockUsers = [{ user_id: 1, username: 'test' }];
|
||||
mockUserRepository.find.mockResolvedValue(mockUsers);
|
||||
const mockTotal = 1;
|
||||
|
||||
const mockQB = {
|
||||
leftJoinAndSelect: jest.fn().mockReturnThis(),
|
||||
select: jest.fn().mockReturnThis(),
|
||||
andWhere: jest.fn().mockReturnThis(),
|
||||
skip: jest.fn().mockReturnThis(),
|
||||
take: jest.fn().mockReturnThis(),
|
||||
getManyAndCount: jest.fn().mockResolvedValue([mockUsers, mockTotal]),
|
||||
};
|
||||
|
||||
mockUserRepository.createQueryBuilder.mockReturnValue(mockQB);
|
||||
|
||||
const result = await service.findAll();
|
||||
|
||||
expect(result).toEqual(mockUsers);
|
||||
expect(mockUserRepository.find).toHaveBeenCalled();
|
||||
expect(result.data).toEqual(mockUsers);
|
||||
expect(result.total).toEqual(mockTotal);
|
||||
expect(mockUserRepository.createQueryBuilder).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -203,13 +203,39 @@ export class UserService {
|
||||
// --- Roles & Permissions (Helper for Admin/UI) ---
|
||||
|
||||
async findAllRoles(): Promise<Role[]> {
|
||||
return this.roleRepository.find();
|
||||
return this.roleRepository.find({ relations: ['permissions'] });
|
||||
}
|
||||
|
||||
async findAllPermissions(): Promise<Permission[]> {
|
||||
return this.permissionRepository.find();
|
||||
}
|
||||
|
||||
async updateRolePermissions(roleId: number, permissionIds: number[]) {
|
||||
const role = await this.roleRepository.findOne({
|
||||
where: { roleId },
|
||||
relations: ['permissions'],
|
||||
});
|
||||
|
||||
if (!role) {
|
||||
throw new NotFoundException(`Role ID ${roleId} not found`);
|
||||
}
|
||||
|
||||
// Load permissions entities
|
||||
const permissions = [];
|
||||
if (permissionIds.length > 0) {
|
||||
// Note: findByIds is deprecated in newer TypeORM, uses In() instead
|
||||
// but if current version supports it or using a simplified query:
|
||||
const perms = await this.permissionRepository
|
||||
.createQueryBuilder('p')
|
||||
.where('p.permissionId IN (:...ids)', { ids: permissionIds })
|
||||
.getMany();
|
||||
permissions.push(...perms);
|
||||
}
|
||||
|
||||
role.permissions = permissions;
|
||||
return this.roleRepository.save(role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper สำหรับล้าง Cache เมื่อมีการเปลี่ยนแปลงสิทธิ์หรือบทบาท
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user