This commit is contained in:
@@ -7,6 +7,7 @@ import { SSOClientService } from "./sso-client.service";
|
||||
import { TokensService } from "./tokens.service";
|
||||
import { AuthMessage } from "../../../common/enums/message.enum";
|
||||
import { User } from "../../users/entities/user.entity";
|
||||
import { getPermissionsFromRoles } from "../../users/utils/role-permissions.util";
|
||||
import { ITokenPayload } from "../interfaces/IToken-payload";
|
||||
|
||||
@Injectable()
|
||||
@@ -46,7 +47,7 @@ export class SSOService {
|
||||
const payload: ITokenPayload = {
|
||||
id: user.id,
|
||||
isAdmin: user.roles.some((r) => r.isAdmin),
|
||||
permissions: user.roles.flatMap((r) => (r?.permissions?.length ? r.permissions.map((p) => p.name) : [])),
|
||||
permissions: getPermissionsFromRoles(user.roles),
|
||||
audience: clientId,
|
||||
};
|
||||
|
||||
@@ -105,7 +106,7 @@ export class SSOService {
|
||||
const payload: ITokenPayload = {
|
||||
id: user.id,
|
||||
isAdmin: user.roles.some((r) => r.isAdmin),
|
||||
permissions: user.roles.flatMap((r) => (r?.permissions?.length ? r.permissions.map((p) => p.name) : [])),
|
||||
permissions: getPermissionsFromRoles(user.roles),
|
||||
audience: clientId,
|
||||
};
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import { DataSource, QueryRunner } from "typeorm";
|
||||
import { AuthMessage } from "../../../common/enums/message.enum";
|
||||
import { User } from "../../users/entities/user.entity";
|
||||
import { RefreshTokensRepository } from "../../users/repositories/refresh-token.repository";
|
||||
import { getPermissionsFromRoles } from "../../users/utils/role-permissions.util";
|
||||
import { ITokenPayload } from "../interfaces/IToken-payload";
|
||||
import { ResellerType } from "../DTO/verify-reseller-otp.dto";
|
||||
|
||||
@@ -28,7 +29,7 @@ export class TokensService {
|
||||
{
|
||||
id: user.id,
|
||||
isAdmin: user.roles.some((r) => r.isAdmin),
|
||||
permissions: user.roles.flatMap((r) => (r?.permissions?.length ? r.permissions.map((p) => p.name) : [])),
|
||||
permissions: getPermissionsFromRoles(user.roles),
|
||||
},
|
||||
queryRunner,
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
|
||||
import { IsEmail, IsMobilePhone, IsNotEmpty, IsOptional, IsString, IsUUID, IsUrl, Length, MinLength } from "class-validator";
|
||||
import { ArrayNotEmpty, IsArray, IsEmail, IsMobilePhone, IsNotEmpty, IsOptional, IsString, IsUUID, IsUrl, Length, MinLength } from "class-validator";
|
||||
|
||||
import { AdminMessage, AuthMessage } from "../../../common/enums/message.enum";
|
||||
|
||||
@@ -22,9 +22,11 @@ export class CreateAdminDto {
|
||||
phone: string;
|
||||
|
||||
@IsNotEmpty({ message: AdminMessage.ROLE_REQUIRED })
|
||||
@IsUUID("4", { message: AdminMessage.ROLE_ID_SHOULD_BE_UUID })
|
||||
@ApiProperty({ description: "Role id", example: "123e4567-e89b-12d3-a456-426614174000" })
|
||||
roleId: string;
|
||||
@IsArray({ message: AdminMessage.ROLE_REQUIRED })
|
||||
@ArrayNotEmpty({ message: AdminMessage.ROLE_REQUIRED })
|
||||
@IsUUID("4", { each: true, message: AdminMessage.ROLE_ID_SHOULD_BE_UUID })
|
||||
@ApiProperty({ description: "Role ids", example: ["123e4567-e89b-12d3-a456-426614174000"], type: [String] })
|
||||
roleIds: string[];
|
||||
|
||||
@IsNotEmpty({ message: AuthMessage.FIRST_NAME_NOT_EMPTY })
|
||||
@IsString({ message: AuthMessage.FIRST_NAME_NOT_EMPTY })
|
||||
|
||||
@@ -18,6 +18,7 @@ import { RoleEnum } from "../enums/role.enum";
|
||||
import { PermissionsRepository } from "../repositories/permissions.repository";
|
||||
import { RoleRepository } from "../repositories/roles.repository";
|
||||
import { UserRepository } from "../repositories/users.repository";
|
||||
import { getPermissionEntitiesFromRoles } from "../utils/role-permissions.util";
|
||||
|
||||
@Injectable()
|
||||
export class AdminsService {
|
||||
@@ -43,22 +44,22 @@ export class AdminsService {
|
||||
const existPhone = await queryRunner.manager.findOneBy(this.userRepository.target, { phone: createDto.phone });
|
||||
if (existPhone) throw new BadRequestException(UserMessage.PHONE_EXIST);
|
||||
|
||||
const role = await queryRunner.manager.findOne(this.rolesRepository.target, {
|
||||
where: { id: createDto.roleId },
|
||||
const roles = await queryRunner.manager.find(this.rolesRepository.target, {
|
||||
where: { id: In(createDto.roleIds), isAdmin: true },
|
||||
relations: { permissions: true },
|
||||
});
|
||||
if (!role) throw new BadRequestException(AdsMessage.ROLE_NOT_FOUND);
|
||||
if (roles.length !== createDto.roleIds.length) throw new BadRequestException(AdsMessage.ROLE_NOT_FOUND);
|
||||
|
||||
if (createDto.password !== createDto.repeatPassword) throw new BadRequestException(AdminMessage.PASSWORD_NOT_MATCH);
|
||||
|
||||
const hashedPassword = await this.passwordService.hashPassword(createDto.password);
|
||||
const userName = slugify(`${createDto.firstName} ${Date.now().toString().slice(-5)}`, { lower: true, trim: true });
|
||||
|
||||
await queryRunner.manager.save(this.rolesRepository.target, role);
|
||||
const { roleIds: _roleIds, repeatPassword: _repeatPassword, ...adminData } = createDto;
|
||||
|
||||
const adminUser = queryRunner.manager.create(this.userRepository.target, {
|
||||
...createDto,
|
||||
roles: [role],
|
||||
...adminData,
|
||||
roles,
|
||||
password: hashedPassword,
|
||||
userName,
|
||||
});
|
||||
@@ -75,7 +76,7 @@ export class AdminsService {
|
||||
userAgent: userIpAndHeaders.headers["user-agent"],
|
||||
actionDescription: `Admin created new admin: ${createDto.email}`,
|
||||
metadata: {
|
||||
roleId: createDto.roleId,
|
||||
roleIds: createDto.roleIds,
|
||||
createdBy: "admin",
|
||||
email: createDto.email,
|
||||
phone: createDto.phone,
|
||||
@@ -118,16 +119,14 @@ export class AdminsService {
|
||||
if (existPhone) throw new BadRequestException(UserMessage.PHONE_EXIST);
|
||||
}
|
||||
|
||||
if (updateDto.roleId) {
|
||||
const role = await queryRunner.manager.findOne(this.rolesRepository.target, {
|
||||
where: { id: updateDto.roleId },
|
||||
if (updateDto.roleIds?.length) {
|
||||
const roles = await queryRunner.manager.find(this.rolesRepository.target, {
|
||||
where: { id: In(updateDto.roleIds), isAdmin: true },
|
||||
relations: { permissions: true },
|
||||
});
|
||||
if (!role) throw new BadRequestException(AdsMessage.ROLE_NOT_FOUND);
|
||||
if (roles.length !== updateDto.roleIds.length) throw new BadRequestException(AdsMessage.ROLE_NOT_FOUND);
|
||||
|
||||
await queryRunner.manager.save(this.rolesRepository.target, role);
|
||||
|
||||
admin.roles = [role];
|
||||
admin.roles = roles;
|
||||
|
||||
await queryRunner.manager.save(this.userRepository.target, admin);
|
||||
}
|
||||
@@ -138,7 +137,8 @@ export class AdminsService {
|
||||
admin.password = await this.passwordService.hashPassword(updateDto.password);
|
||||
}
|
||||
|
||||
await queryRunner.manager.save(this.userRepository.target, { ...admin, ...updateDto, password: admin.password });
|
||||
const { roleIds: _roleIds, repeatPassword: _repeatPassword, ...updateData } = updateDto;
|
||||
await queryRunner.manager.save(this.userRepository.target, { ...admin, ...updateData, password: admin.password });
|
||||
|
||||
await queryRunner.commitTransaction();
|
||||
await this.accessLogService.logUpdate("User", admin.id, UserType.ADMIN, {
|
||||
@@ -150,7 +150,7 @@ export class AdminsService {
|
||||
userType: UserType.ADMIN,
|
||||
actionDescription: `Admin updated admin: ${admin.email}`,
|
||||
metadata: {
|
||||
roleId: updateDto.roleId,
|
||||
roleIds: updateDto.roleIds,
|
||||
},
|
||||
oldValues: JSON.stringify({ ...admin }),
|
||||
newValues: JSON.stringify({ ...updateDto }),
|
||||
@@ -169,7 +169,7 @@ export class AdminsService {
|
||||
/************************************************************ */
|
||||
|
||||
async deleteAdmin(id: string, userIpAndHeaders: IUserIpAndHeaders) {
|
||||
const admin = await this.userRepository.findOne({ where: { id, roles: { isAdmin: true } } });
|
||||
const admin = await this.userRepository.findOne({ where: { id, roles: { isAdmin: true } }, relations: { roles: true } });
|
||||
if (!admin) throw new BadRequestException(AdminMessage.ADMIN_NOT_FOUND);
|
||||
|
||||
await this.userRepository.softDelete(id);
|
||||
@@ -182,7 +182,7 @@ export class AdminsService {
|
||||
userAgent: userIpAndHeaders.headers["user-agent"],
|
||||
actionDescription: `Admin deleted admin: ${admin.email}`,
|
||||
metadata: {
|
||||
roleId: admin.roles[0].id,
|
||||
roleIds: admin.roles.map((role) => role.id),
|
||||
email: admin.email,
|
||||
phone: admin.phone,
|
||||
},
|
||||
@@ -303,7 +303,7 @@ export class AdminsService {
|
||||
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
|
||||
|
||||
return {
|
||||
permissions: user.roles[0].permissions,
|
||||
permissions: getPermissionEntitiesFromRoles(user.roles),
|
||||
};
|
||||
}
|
||||
/************************************************************ */
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "../../../.."
|
||||
},
|
||||
{
|
||||
"path": "../../../../../danak-admin"
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { PermissionEnum } from "../enums/permission.enum";
|
||||
import { Role } from "../entities/role.entity";
|
||||
import { Permission } from "../entities/permission.entity";
|
||||
|
||||
export function getPermissionsFromRoles(roles: Role[]): PermissionEnum[] {
|
||||
return [...new Set(roles.flatMap((role) => (role?.permissions?.length ? role.permissions.map((permission) => permission.name) : [])))];
|
||||
}
|
||||
|
||||
export function getPermissionEntitiesFromRoles(roles: Role[]): Permission[] {
|
||||
const permissionsById = new Map<string, Permission>();
|
||||
|
||||
for (const role of roles) {
|
||||
for (const permission of role?.permissions ?? []) {
|
||||
permissionsById.set(permission.id, permission);
|
||||
}
|
||||
}
|
||||
|
||||
return [...permissionsById.values()];
|
||||
}
|
||||
Reference in New Issue
Block a user