mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-16 18:56:22 +00:00
Merge branch 'dev' into SP-197-be-retrieve-devices-in-the-gateway
This commit is contained in:
@ -4,4 +4,5 @@ export class AuthInterface {
|
|||||||
uuid: string;
|
uuid: string;
|
||||||
sessionId: string;
|
sessionId: string;
|
||||||
id: number;
|
id: number;
|
||||||
|
roles?: string[];
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,9 @@ export class AuthService {
|
|||||||
where: {
|
where: {
|
||||||
email,
|
email,
|
||||||
},
|
},
|
||||||
|
relations: ['roles.roleType'],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!user.isUserVerified) {
|
if (!user.isUserVerified) {
|
||||||
throw new BadRequestException('User is not verified');
|
throw new BadRequestException('User is not verified');
|
||||||
}
|
}
|
||||||
@ -68,7 +70,9 @@ export class AuthService {
|
|||||||
uuid: user.uuid,
|
uuid: user.uuid,
|
||||||
type: user.type,
|
type: user.type,
|
||||||
sessionId: user.sessionId,
|
sessionId: user.sessionId,
|
||||||
|
roles: user?.roles,
|
||||||
};
|
};
|
||||||
|
|
||||||
const tokens = await this.getTokens(payload);
|
const tokens = await this.getTokens(payload);
|
||||||
await this.updateRefreshToken(user.uuid, tokens.refreshToken);
|
await this.updateRefreshToken(user.uuid, tokens.refreshToken);
|
||||||
return tokens;
|
return tokens;
|
||||||
|
@ -28,9 +28,10 @@ export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
|
|||||||
if (validateUser) {
|
if (validateUser) {
|
||||||
return {
|
return {
|
||||||
email: payload.email,
|
email: payload.email,
|
||||||
userId: payload.id,
|
userUuid: payload.uuid,
|
||||||
uuid: payload.uuid,
|
uuid: payload.uuid,
|
||||||
sessionId: payload.sessionId,
|
sessionId: payload.sessionId,
|
||||||
|
roles: payload?.roles,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
throw new BadRequestException('Unauthorized');
|
throw new BadRequestException('Unauthorized');
|
||||||
|
@ -31,9 +31,10 @@ export class RefreshTokenStrategy extends PassportStrategy(
|
|||||||
if (validateUser) {
|
if (validateUser) {
|
||||||
return {
|
return {
|
||||||
email: payload.email,
|
email: payload.email,
|
||||||
userId: payload.id,
|
userUuid: payload.uuid,
|
||||||
uuid: payload.uuid,
|
uuid: payload.uuid,
|
||||||
sessionId: payload.sessionId,
|
sessionId: payload.sessionId,
|
||||||
|
roles: payload?.roles,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
throw new BadRequestException('Unauthorized');
|
throw new BadRequestException('Unauthorized');
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
import emailConfig from './email.config';
|
import emailConfig from './email.config';
|
||||||
export default [emailConfig];
|
import superAdminConfig from './super.admin.config';
|
||||||
|
export default [emailConfig, superAdminConfig];
|
||||||
|
9
libs/common/src/config/super.admin.config.ts
Normal file
9
libs/common/src/config/super.admin.config.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
|
export default registerAs(
|
||||||
|
'super-admin',
|
||||||
|
(): Record<string, any> => ({
|
||||||
|
SUPER_ADMIN_EMAIL: process.env.SUPER_ADMIN_EMAIL,
|
||||||
|
SUPER_ADMIN_PASSWORD: process.env.SUPER_ADMIN_PASSWORD,
|
||||||
|
}),
|
||||||
|
);
|
4
libs/common/src/constants/role.type.enum.ts
Normal file
4
libs/common/src/constants/role.type.enum.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export enum RoleType {
|
||||||
|
SUPER_ADMIN = 'SUPER_ADMIN',
|
||||||
|
ADMIN = 'ADMIN',
|
||||||
|
}
|
7
libs/common/src/constants/space-type.enum.ts
Normal file
7
libs/common/src/constants/space-type.enum.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export enum SpaceType {
|
||||||
|
COMMUNITY = 'community',
|
||||||
|
BUILDING = 'building',
|
||||||
|
FLOOR = 'floor',
|
||||||
|
UNIT = 'unit',
|
||||||
|
ROOM = 'room',
|
||||||
|
}
|
@ -6,16 +6,16 @@ import { UserEntity } from '../modules/user/entities/user.entity';
|
|||||||
import { UserSessionEntity } from '../modules/session/entities/session.entity';
|
import { UserSessionEntity } from '../modules/session/entities/session.entity';
|
||||||
import { UserOtpEntity } from '../modules/user-otp/entities';
|
import { UserOtpEntity } from '../modules/user-otp/entities';
|
||||||
import { ProductEntity } from '../modules/product/entities';
|
import { ProductEntity } from '../modules/product/entities';
|
||||||
import {
|
import { DeviceEntity } from '../modules/device/entities';
|
||||||
DeviceEntity,
|
|
||||||
DeviceUserPermissionEntity,
|
|
||||||
} from '../modules/device/entities';
|
|
||||||
import { PermissionTypeEntity } from '../modules/permission/entities';
|
import { PermissionTypeEntity } from '../modules/permission/entities';
|
||||||
import { SpaceEntity } from '../modules/space/entities';
|
import { SpaceEntity } from '../modules/space/entities';
|
||||||
import { SpaceTypeEntity } from '../modules/space-type/entities';
|
import { SpaceTypeEntity } from '../modules/space-type/entities';
|
||||||
import { UserSpaceEntity } from '../modules/user-space/entities';
|
import { UserSpaceEntity } from '../modules/user-space/entities';
|
||||||
import { GroupEntity } from '../modules/group/entities';
|
import { GroupEntity } from '../modules/group/entities';
|
||||||
import { GroupDeviceEntity } from '../modules/group-device/entities';
|
import { GroupDeviceEntity } from '../modules/group-device/entities';
|
||||||
|
import { DeviceUserPermissionEntity } from '../modules/device-user-permission/entities';
|
||||||
|
import { UserRoleEntity } from '../modules/user-role/entities';
|
||||||
|
import { RoleTypeEntity } from '../modules/role-type/entities';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@ -43,6 +43,9 @@ import { GroupDeviceEntity } from '../modules/group-device/entities';
|
|||||||
UserSpaceEntity,
|
UserSpaceEntity,
|
||||||
GroupEntity,
|
GroupEntity,
|
||||||
GroupDeviceEntity,
|
GroupDeviceEntity,
|
||||||
|
DeviceUserPermissionEntity,
|
||||||
|
UserRoleEntity,
|
||||||
|
RoleTypeEntity,
|
||||||
],
|
],
|
||||||
namingStrategy: new SnakeNamingStrategy(),
|
namingStrategy: new SnakeNamingStrategy(),
|
||||||
synchronize: Boolean(JSON.parse(configService.get('DB_SYNC'))),
|
synchronize: Boolean(JSON.parse(configService.get('DB_SYNC'))),
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
import { Global, Module } from '@nestjs/common';
|
import { Global, Module } from '@nestjs/common';
|
||||||
import { HelperHashService } from './services';
|
import { HelperHashService } from './services';
|
||||||
|
import { SpacePermissionService } from './services/space.permission.service';
|
||||||
|
import { SpaceRepository } from '../modules/space/repositories';
|
||||||
|
import { SpaceRepositoryModule } from '../modules/space/space.repository.module';
|
||||||
|
|
||||||
@Global()
|
@Global()
|
||||||
@Module({
|
@Module({
|
||||||
providers: [HelperHashService],
|
providers: [HelperHashService, SpacePermissionService, SpaceRepository],
|
||||||
exports: [HelperHashService],
|
exports: [HelperHashService, SpacePermissionService],
|
||||||
controllers: [],
|
controllers: [],
|
||||||
imports: [],
|
imports: [SpaceRepositoryModule],
|
||||||
})
|
})
|
||||||
export class HelperModule {}
|
export class HelperModule {}
|
||||||
|
@ -1 +1,2 @@
|
|||||||
export * from './helper.hash.service';
|
export * from './helper.hash.service';
|
||||||
|
export * from './space.permission.service';
|
||||||
|
39
libs/common/src/helper/services/space.permission.service.ts
Normal file
39
libs/common/src/helper/services/space.permission.service.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
||||||
|
import { BadRequestException } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SpacePermissionService {
|
||||||
|
constructor(private readonly spaceRepository: SpaceRepository) {}
|
||||||
|
|
||||||
|
async checkUserPermission(
|
||||||
|
spaceUuid: string,
|
||||||
|
userUuid: string,
|
||||||
|
type: string,
|
||||||
|
): Promise<void> {
|
||||||
|
try {
|
||||||
|
const spaceData = await this.spaceRepository.findOne({
|
||||||
|
where: {
|
||||||
|
uuid: spaceUuid,
|
||||||
|
spaceType: {
|
||||||
|
type: type,
|
||||||
|
},
|
||||||
|
userSpaces: {
|
||||||
|
user: {
|
||||||
|
uuid: userUuid,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
relations: ['spaceType', 'userSpaces', 'userSpaces.user'],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!spaceData) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
`You do not have permission to access this ${type}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
throw new BadRequestException(err.message || 'Invalid UUID');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { DeviceUserPermissionEntity } from './entities';
|
||||||
|
@Module({
|
||||||
|
providers: [],
|
||||||
|
exports: [],
|
||||||
|
controllers: [],
|
||||||
|
imports: [TypeOrmModule.forFeature([DeviceUserPermissionEntity])],
|
||||||
|
})
|
||||||
|
export class DeviceUserPermissionRepositoryModule {}
|
@ -1,6 +1,6 @@
|
|||||||
import { IsNotEmpty, IsString } from 'class-validator';
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
export class DeviceUserTypeDto {
|
export class DeviceUserPermissionDto {
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
public uuid: string;
|
public uuid: string;
|
@ -0,0 +1 @@
|
|||||||
|
export * from './device.user.permission.dto';
|
@ -0,0 +1,43 @@
|
|||||||
|
import { Column, Entity, ManyToOne, Unique } from 'typeorm';
|
||||||
|
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||||
|
import { DeviceUserPermissionDto } from '../dtos';
|
||||||
|
import { PermissionTypeEntity } from '../../permission/entities';
|
||||||
|
import { DeviceEntity } from '../../device/entities';
|
||||||
|
import { UserEntity } from '../../user/entities';
|
||||||
|
|
||||||
|
@Entity({ name: 'device-user-permission' })
|
||||||
|
@Unique(['userUuid', 'deviceUuid'])
|
||||||
|
export class DeviceUserPermissionEntity extends AbstractEntity<DeviceUserPermissionDto> {
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
public userUuid: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
deviceUuid: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => DeviceEntity, (device) => device.permission, {
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
device: DeviceEntity;
|
||||||
|
|
||||||
|
@ManyToOne(
|
||||||
|
() => PermissionTypeEntity,
|
||||||
|
(permissionType) => permissionType.permission,
|
||||||
|
{
|
||||||
|
nullable: false,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
permissionType: PermissionTypeEntity;
|
||||||
|
|
||||||
|
@ManyToOne(() => UserEntity, (user) => user.userPermission, {
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
user: UserEntity;
|
||||||
|
constructor(partial: Partial<DeviceUserPermissionEntity>) {
|
||||||
|
super();
|
||||||
|
Object.assign(this, partial);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
export * from './device.user.permission.entity';
|
@ -3,7 +3,7 @@ import { Injectable } from '@nestjs/common';
|
|||||||
import { DeviceUserPermissionEntity } from '../entities';
|
import { DeviceUserPermissionEntity } from '../entities';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DeviceUserTypeRepository extends Repository<DeviceUserPermissionEntity> {
|
export class DeviceUserPermissionRepository extends Repository<DeviceUserPermissionEntity> {
|
||||||
constructor(private dataSource: DataSource) {
|
constructor(private dataSource: DataSource) {
|
||||||
super(DeviceUserPermissionEntity, dataSource.createEntityManager());
|
super(DeviceUserPermissionEntity, dataSource.createEntityManager());
|
||||||
}
|
}
|
@ -0,0 +1 @@
|
|||||||
|
export * from './device.user.permission.repository';
|
@ -1,13 +1,11 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { DeviceEntity, DeviceUserPermissionEntity } from './entities';
|
import { DeviceEntity } from './entities';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
providers: [],
|
providers: [],
|
||||||
exports: [],
|
exports: [],
|
||||||
controllers: [],
|
controllers: [],
|
||||||
imports: [
|
imports: [TypeOrmModule.forFeature([DeviceEntity])],
|
||||||
TypeOrmModule.forFeature([DeviceEntity, DeviceUserPermissionEntity]),
|
|
||||||
],
|
|
||||||
})
|
})
|
||||||
export class DeviceRepositoryModule {}
|
export class DeviceRepositoryModule {}
|
||||||
|
@ -1,2 +1 @@
|
|||||||
export * from './device.dto';
|
export * from './device.dto';
|
||||||
export * from './device-user-type.dto';
|
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm';
|
|
||||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
|
||||||
import { DeviceUserTypeDto } from '../dtos/device-user-type.dto';
|
|
||||||
import { DeviceEntity } from './device.entity';
|
|
||||||
import { PermissionTypeEntity } from '../../permission/entities';
|
|
||||||
|
|
||||||
@Entity({ name: 'device-user-permission' })
|
|
||||||
export class DeviceUserPermissionEntity extends AbstractEntity<DeviceUserTypeDto> {
|
|
||||||
@Column({
|
|
||||||
nullable: false,
|
|
||||||
})
|
|
||||||
public userUuid: string;
|
|
||||||
|
|
||||||
@Column({
|
|
||||||
nullable: false,
|
|
||||||
})
|
|
||||||
deviceUuid: string;
|
|
||||||
|
|
||||||
@Column({
|
|
||||||
nullable: false,
|
|
||||||
})
|
|
||||||
public permissionTypeUuid: string;
|
|
||||||
|
|
||||||
@ManyToOne(() => DeviceEntity, {
|
|
||||||
onDelete: 'CASCADE',
|
|
||||||
onUpdate: 'CASCADE',
|
|
||||||
})
|
|
||||||
@JoinColumn({ name: 'device_uuid', referencedColumnName: 'uuid' })
|
|
||||||
device: DeviceEntity;
|
|
||||||
|
|
||||||
@ManyToOne(() => PermissionTypeEntity, {
|
|
||||||
onDelete: 'CASCADE',
|
|
||||||
onUpdate: 'CASCADE',
|
|
||||||
})
|
|
||||||
@JoinColumn({ name: 'permission_type_uuid', referencedColumnName: 'uuid' })
|
|
||||||
type: PermissionTypeEntity;
|
|
||||||
|
|
||||||
constructor(partial: Partial<DeviceUserPermissionEntity>) {
|
|
||||||
super();
|
|
||||||
Object.assign(this, partial);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +1,10 @@
|
|||||||
import { Column, Entity, ManyToOne, OneToMany, Unique } from 'typeorm';
|
import { Column, Entity, ManyToOne, OneToMany, Unique } from 'typeorm';
|
||||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||||
import { DeviceDto } from '../dtos/device.dto';
|
import { DeviceDto } from '../dtos/device.dto';
|
||||||
import { DeviceUserPermissionEntity } from './device-user-type.entity';
|
|
||||||
import { GroupDeviceEntity } from '../../group-device/entities';
|
import { GroupDeviceEntity } from '../../group-device/entities';
|
||||||
import { SpaceEntity } from '../../space/entities';
|
import { SpaceEntity } from '../../space/entities';
|
||||||
import { ProductEntity } from '../../product/entities';
|
import { ProductEntity } from '../../product/entities';
|
||||||
|
import { DeviceUserPermissionEntity } from '../../device-user-permission/entities';
|
||||||
|
|
||||||
@Entity({ name: 'device' })
|
@Entity({ name: 'device' })
|
||||||
@Unique(['spaceDevice', 'deviceTuyaUuid'])
|
@Unique(['spaceDevice', 'deviceTuyaUuid'])
|
||||||
@ -25,8 +25,6 @@ export class DeviceEntity extends AbstractEntity<DeviceDto> {
|
|||||||
(permission) => permission.device,
|
(permission) => permission.device,
|
||||||
{
|
{
|
||||||
nullable: true,
|
nullable: true,
|
||||||
onDelete: 'CASCADE',
|
|
||||||
onUpdate: 'CASCADE',
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
permission: DeviceUserPermissionEntity[];
|
permission: DeviceUserPermissionEntity[];
|
||||||
|
@ -1,2 +1 @@
|
|||||||
export * from './device.entity';
|
export * from './device.entity';
|
||||||
export * from './device-user-type.entity';
|
|
||||||
|
@ -1,2 +1 @@
|
|||||||
export * from './device.repository';
|
export * from './device.repository';
|
||||||
export * from './device-user-type.repository';
|
|
||||||
|
@ -19,7 +19,6 @@ export class GroupEntity extends AbstractEntity<GroupDto> {
|
|||||||
|
|
||||||
@OneToMany(() => GroupDeviceEntity, (groupDevice) => groupDevice.group, {
|
@OneToMany(() => GroupDeviceEntity, (groupDevice) => groupDevice.group, {
|
||||||
cascade: true,
|
cascade: true,
|
||||||
onDelete: 'CASCADE',
|
|
||||||
})
|
})
|
||||||
groupDevices: GroupDeviceEntity[];
|
groupDevices: GroupDeviceEntity[];
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import { Column, Entity, OneToMany } from 'typeorm';
|
|||||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||||
import { PermissionType } from '@app/common/constants/permission-type.enum';
|
import { PermissionType } from '@app/common/constants/permission-type.enum';
|
||||||
import { PermissionTypeDto } from '../dtos/permission.dto';
|
import { PermissionTypeDto } from '../dtos/permission.dto';
|
||||||
import { DeviceUserPermissionEntity } from '../../device/entities';
|
import { DeviceUserPermissionEntity } from '../../device-user-permission/entities';
|
||||||
|
|
||||||
@Entity({ name: 'permission-type' })
|
@Entity({ name: 'permission-type' })
|
||||||
export class PermissionTypeEntity extends AbstractEntity<PermissionTypeDto> {
|
export class PermissionTypeEntity extends AbstractEntity<PermissionTypeDto> {
|
||||||
@ -14,11 +14,9 @@ export class PermissionTypeEntity extends AbstractEntity<PermissionTypeDto> {
|
|||||||
|
|
||||||
@OneToMany(
|
@OneToMany(
|
||||||
() => DeviceUserPermissionEntity,
|
() => DeviceUserPermissionEntity,
|
||||||
(permission) => permission.type,
|
(permission) => permission.permissionType,
|
||||||
{
|
{
|
||||||
nullable: true,
|
nullable: true,
|
||||||
onDelete: 'CASCADE',
|
|
||||||
onUpdate: 'CASCADE',
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
permission: DeviceUserPermissionEntity[];
|
permission: DeviceUserPermissionEntity[];
|
||||||
|
1
libs/common/src/modules/role-type/dtos/index.ts
Normal file
1
libs/common/src/modules/role-type/dtos/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './role.type.dto';
|
11
libs/common/src/modules/role-type/dtos/role.type.dto.ts
Normal file
11
libs/common/src/modules/role-type/dtos/role.type.dto.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { RoleType } from '@app/common/constants/role.type.enum';
|
||||||
|
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class RoleTypeDto {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public uuid: string;
|
||||||
|
|
||||||
|
@IsEnum(RoleType)
|
||||||
|
public type: RoleType;
|
||||||
|
}
|
1
libs/common/src/modules/role-type/entities/index.ts
Normal file
1
libs/common/src/modules/role-type/entities/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './role.type.entity';
|
@ -0,0 +1,23 @@
|
|||||||
|
import { Column, Entity, OneToMany, Unique } from 'typeorm';
|
||||||
|
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||||
|
import { RoleTypeDto } from '../dtos/role.type.dto';
|
||||||
|
import { RoleType } from '@app/common/constants/role.type.enum';
|
||||||
|
import { UserRoleEntity } from '../../user-role/entities';
|
||||||
|
|
||||||
|
@Entity({ name: 'role-type' })
|
||||||
|
@Unique(['type'])
|
||||||
|
export class RoleTypeEntity extends AbstractEntity<RoleTypeDto> {
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
enum: Object.values(RoleType),
|
||||||
|
})
|
||||||
|
type: string;
|
||||||
|
@OneToMany(() => UserRoleEntity, (role) => role.roleType, {
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
roles: UserRoleEntity[];
|
||||||
|
constructor(partial: Partial<RoleTypeEntity>) {
|
||||||
|
super();
|
||||||
|
Object.assign(this, partial);
|
||||||
|
}
|
||||||
|
}
|
1
libs/common/src/modules/role-type/repositories/index.ts
Normal file
1
libs/common/src/modules/role-type/repositories/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './role.type.repository';
|
@ -0,0 +1,10 @@
|
|||||||
|
import { DataSource, Repository } from 'typeorm';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { RoleTypeEntity } from '../entities/role.type.entity';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class RoleTypeRepository extends Repository<RoleTypeEntity> {
|
||||||
|
constructor(private dataSource: DataSource) {
|
||||||
|
super(RoleTypeEntity, dataSource.createEntityManager());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { RoleTypeEntity } from './entities/role.type.entity';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
providers: [],
|
||||||
|
exports: [],
|
||||||
|
controllers: [],
|
||||||
|
imports: [TypeOrmModule.forFeature([RoleTypeEntity])],
|
||||||
|
})
|
||||||
|
export class RoleTypeRepositoryModule {}
|
1
libs/common/src/modules/user-role/dtos/index.ts
Normal file
1
libs/common/src/modules/user-role/dtos/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './user.role.dto';
|
15
libs/common/src/modules/user-role/dtos/user.role.dto.ts
Normal file
15
libs/common/src/modules/user-role/dtos/user.role.dto.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class UserRoleDto {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public uuid: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public userUuid: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public roleTypeUuid: string;
|
||||||
|
}
|
1
libs/common/src/modules/user-role/entities/index.ts
Normal file
1
libs/common/src/modules/user-role/entities/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './user.role.entity';
|
@ -0,0 +1,24 @@
|
|||||||
|
import { Entity, ManyToOne, Unique } from 'typeorm';
|
||||||
|
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||||
|
import { UserRoleDto } from '../dtos';
|
||||||
|
import { UserEntity } from '../../user/entities';
|
||||||
|
import { RoleTypeEntity } from '../../role-type/entities';
|
||||||
|
|
||||||
|
@Entity({ name: 'user-role' })
|
||||||
|
@Unique(['user', 'roleType'])
|
||||||
|
export class UserRoleEntity extends AbstractEntity<UserRoleDto> {
|
||||||
|
@ManyToOne(() => UserEntity, (user) => user.roles, {
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
user: UserEntity;
|
||||||
|
|
||||||
|
@ManyToOne(() => RoleTypeEntity, (roleType) => roleType.roles, {
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
roleType: RoleTypeEntity;
|
||||||
|
|
||||||
|
constructor(partial: Partial<UserRoleEntity>) {
|
||||||
|
super();
|
||||||
|
Object.assign(this, partial);
|
||||||
|
}
|
||||||
|
}
|
1
libs/common/src/modules/user-role/repositories/index.ts
Normal file
1
libs/common/src/modules/user-role/repositories/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './user.role.repository';
|
@ -0,0 +1,10 @@
|
|||||||
|
import { DataSource, Repository } from 'typeorm';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { UserRoleEntity } from '../entities';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UserRoleRepository extends Repository<UserRoleEntity> {
|
||||||
|
constructor(private dataSource: DataSource) {
|
||||||
|
super(UserRoleEntity, dataSource.createEntityManager());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { UserRoleEntity } from './entities';
|
||||||
|
@Module({
|
||||||
|
providers: [],
|
||||||
|
exports: [],
|
||||||
|
controllers: [],
|
||||||
|
imports: [TypeOrmModule.forFeature([UserRoleEntity])],
|
||||||
|
})
|
||||||
|
export class UserRoleRepositoryModule {}
|
@ -1,7 +1,9 @@
|
|||||||
|
import { DeviceUserPermissionEntity } from '../../device-user-permission/entities/device.user.permission.entity';
|
||||||
import { Column, Entity, OneToMany } from 'typeorm';
|
import { Column, Entity, OneToMany } from 'typeorm';
|
||||||
import { UserDto } from '../dtos';
|
import { UserDto } from '../dtos';
|
||||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||||
import { UserSpaceEntity } from '../../user-space/entities';
|
import { UserSpaceEntity } from '../../user-space/entities';
|
||||||
|
import { UserRoleEntity } from '../../user-role/entities';
|
||||||
|
|
||||||
@Entity({ name: 'user' })
|
@Entity({ name: 'user' })
|
||||||
export class UserEntity extends AbstractEntity<UserDto> {
|
export class UserEntity extends AbstractEntity<UserDto> {
|
||||||
@ -51,6 +53,16 @@ export class UserEntity extends AbstractEntity<UserDto> {
|
|||||||
@OneToMany(() => UserSpaceEntity, (userSpace) => userSpace.user)
|
@OneToMany(() => UserSpaceEntity, (userSpace) => userSpace.user)
|
||||||
userSpaces: UserSpaceEntity[];
|
userSpaces: UserSpaceEntity[];
|
||||||
|
|
||||||
|
@OneToMany(
|
||||||
|
() => DeviceUserPermissionEntity,
|
||||||
|
(userPermission) => userPermission.user,
|
||||||
|
)
|
||||||
|
userPermission: DeviceUserPermissionEntity[];
|
||||||
|
|
||||||
|
@OneToMany(() => UserRoleEntity, (role) => role.user, {
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
roles: UserRoleEntity[];
|
||||||
constructor(partial: Partial<UserEntity>) {
|
constructor(partial: Partial<UserEntity>) {
|
||||||
super();
|
super();
|
||||||
Object.assign(this, partial);
|
Object.assign(this, partial);
|
||||||
|
43
libs/common/src/seed/seeder.module.ts
Normal file
43
libs/common/src/seed/seeder.module.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { Global, Module } from '@nestjs/common';
|
||||||
|
import { SeederService } from './services/seeder.service';
|
||||||
|
import { PermissionTypeRepository } from '../modules/permission/repositories';
|
||||||
|
import { PermissionTypeSeeder } from './services/permission.type.seeder';
|
||||||
|
import { PermissionTypeRepositoryModule } from '../modules/permission/permission.repository.module';
|
||||||
|
import { ConfigModule } from '@nestjs/config';
|
||||||
|
import { RoleTypeRepositoryModule } from '../modules/role-type/role.type.repository.module';
|
||||||
|
import { RoleTypeRepository } from '../modules/role-type/repositories';
|
||||||
|
import { RoleTypeSeeder } from './services/role.type.seeder';
|
||||||
|
import { SpaceTypeRepository } from '../modules/space-type/repositories';
|
||||||
|
import { SpaceTypeSeeder } from './services/space.type.seeder';
|
||||||
|
import { SpaceTypeRepositoryModule } from '../modules/space-type/space.type.repository.module';
|
||||||
|
import { SuperAdminSeeder } from './services/supper.admin.seeder';
|
||||||
|
import { UserRepository } from '../modules/user/repositories';
|
||||||
|
import { UserRoleRepository } from '../modules/user-role/repositories';
|
||||||
|
import { UserRoleRepositoryModule } from '../modules/user-role/user.role.repository.module';
|
||||||
|
import { UserRepositoryModule } from '../modules/user/user.repository.module';
|
||||||
|
@Global()
|
||||||
|
@Module({
|
||||||
|
providers: [
|
||||||
|
PermissionTypeSeeder,
|
||||||
|
RoleTypeSeeder,
|
||||||
|
SpaceTypeSeeder,
|
||||||
|
SeederService,
|
||||||
|
PermissionTypeRepository,
|
||||||
|
RoleTypeRepository,
|
||||||
|
SpaceTypeRepository,
|
||||||
|
SuperAdminSeeder,
|
||||||
|
UserRepository,
|
||||||
|
UserRoleRepository,
|
||||||
|
],
|
||||||
|
exports: [SeederService],
|
||||||
|
controllers: [],
|
||||||
|
imports: [
|
||||||
|
ConfigModule.forRoot(),
|
||||||
|
PermissionTypeRepositoryModule,
|
||||||
|
RoleTypeRepositoryModule,
|
||||||
|
UserRepositoryModule,
|
||||||
|
UserRoleRepositoryModule,
|
||||||
|
SpaceTypeRepositoryModule,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class SeederModule {}
|
49
libs/common/src/seed/services/permission.type.seeder.ts
Normal file
49
libs/common/src/seed/services/permission.type.seeder.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { PermissionTypeRepository } from '../../modules/permission/repositories';
|
||||||
|
import { PermissionType } from '../../constants/permission-type.enum';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class PermissionTypeSeeder {
|
||||||
|
constructor(
|
||||||
|
private readonly permissionTypeRepository: PermissionTypeRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async addPermissionTypeDataIfNotFound(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const existingPermissionTypes =
|
||||||
|
await this.permissionTypeRepository.find();
|
||||||
|
|
||||||
|
const permissionTypeNames = existingPermissionTypes.map((pt) => pt.type);
|
||||||
|
|
||||||
|
const missingPermissionTypes = [];
|
||||||
|
if (!permissionTypeNames.includes(PermissionType.CONTROLLABLE)) {
|
||||||
|
missingPermissionTypes.push(PermissionType.CONTROLLABLE);
|
||||||
|
}
|
||||||
|
if (!permissionTypeNames.includes(PermissionType.READ)) {
|
||||||
|
missingPermissionTypes.push(PermissionType.READ);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (missingPermissionTypes.length > 0) {
|
||||||
|
await this.addPermissionTypeData(missingPermissionTypes);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error while checking permission type data:', err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async addPermissionTypeData(
|
||||||
|
permissionTypes: string[],
|
||||||
|
): Promise<void> {
|
||||||
|
try {
|
||||||
|
const permissionTypeEntities = permissionTypes.map((type) => ({
|
||||||
|
type,
|
||||||
|
}));
|
||||||
|
|
||||||
|
await this.permissionTypeRepository.save(permissionTypeEntities);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error while adding permission type data:', err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
libs/common/src/seed/services/role.type.seeder.ts
Normal file
44
libs/common/src/seed/services/role.type.seeder.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { RoleType } from '../../constants/role.type.enum';
|
||||||
|
import { RoleTypeRepository } from '../../modules/role-type/repositories';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class RoleTypeSeeder {
|
||||||
|
constructor(private readonly roleTypeRepository: RoleTypeRepository) {}
|
||||||
|
|
||||||
|
async addRoleTypeDataIfNotFound(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const existingRoleTypes = await this.roleTypeRepository.find();
|
||||||
|
|
||||||
|
const roleTypeNames = existingRoleTypes.map((pt) => pt.type);
|
||||||
|
|
||||||
|
const missingRoleTypes = [];
|
||||||
|
if (!roleTypeNames.includes(RoleType.SUPER_ADMIN)) {
|
||||||
|
missingRoleTypes.push(RoleType.SUPER_ADMIN);
|
||||||
|
}
|
||||||
|
if (!roleTypeNames.includes(RoleType.ADMIN)) {
|
||||||
|
missingRoleTypes.push(RoleType.ADMIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (missingRoleTypes.length > 0) {
|
||||||
|
await this.addRoleTypeData(missingRoleTypes);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error while checking role type data:', err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async addRoleTypeData(roleTypes: string[]): Promise<void> {
|
||||||
|
try {
|
||||||
|
const roleTypeEntities = roleTypes.map((type) => ({
|
||||||
|
type,
|
||||||
|
}));
|
||||||
|
|
||||||
|
await this.roleTypeRepository.save(roleTypeEntities);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error while adding role type data:', err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
libs/common/src/seed/services/seeder.service.ts
Normal file
21
libs/common/src/seed/services/seeder.service.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { PermissionTypeSeeder } from './permission.type.seeder';
|
||||||
|
import { RoleTypeSeeder } from './role.type.seeder';
|
||||||
|
import { SpaceTypeSeeder } from './space.type.seeder';
|
||||||
|
import { SuperAdminSeeder } from './supper.admin.seeder';
|
||||||
|
@Injectable()
|
||||||
|
export class SeederService {
|
||||||
|
constructor(
|
||||||
|
private readonly permissionTypeSeeder: PermissionTypeSeeder,
|
||||||
|
private readonly roleTypeSeeder: RoleTypeSeeder,
|
||||||
|
private readonly spaceTypeSeeder: SpaceTypeSeeder,
|
||||||
|
private readonly superAdminSeeder: SuperAdminSeeder,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async seed() {
|
||||||
|
await this.permissionTypeSeeder.addPermissionTypeDataIfNotFound();
|
||||||
|
await this.roleTypeSeeder.addRoleTypeDataIfNotFound();
|
||||||
|
await this.spaceTypeSeeder.addSpaceTypeDataIfNotFound();
|
||||||
|
await this.superAdminSeeder.createSuperAdminIfNotFound();
|
||||||
|
}
|
||||||
|
}
|
52
libs/common/src/seed/services/space.type.seeder.ts
Normal file
52
libs/common/src/seed/services/space.type.seeder.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { SpaceType } from '../../constants/space-type.enum';
|
||||||
|
import { SpaceTypeRepository } from '../../modules/space-type/repositories';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SpaceTypeSeeder {
|
||||||
|
constructor(private readonly spaceTypeRepository: SpaceTypeRepository) {}
|
||||||
|
|
||||||
|
async addSpaceTypeDataIfNotFound(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const existingSpaceTypes = await this.spaceTypeRepository.find();
|
||||||
|
|
||||||
|
const spaceTypeNames = existingSpaceTypes.map((pt) => pt.type);
|
||||||
|
|
||||||
|
const missingSpaceTypes = [];
|
||||||
|
if (!spaceTypeNames.includes(SpaceType.COMMUNITY)) {
|
||||||
|
missingSpaceTypes.push(SpaceType.COMMUNITY);
|
||||||
|
}
|
||||||
|
if (!spaceTypeNames.includes(SpaceType.BUILDING)) {
|
||||||
|
missingSpaceTypes.push(SpaceType.BUILDING);
|
||||||
|
}
|
||||||
|
if (!spaceTypeNames.includes(SpaceType.FLOOR)) {
|
||||||
|
missingSpaceTypes.push(SpaceType.FLOOR);
|
||||||
|
}
|
||||||
|
if (!spaceTypeNames.includes(SpaceType.UNIT)) {
|
||||||
|
missingSpaceTypes.push(SpaceType.UNIT);
|
||||||
|
}
|
||||||
|
if (!spaceTypeNames.includes(SpaceType.ROOM)) {
|
||||||
|
missingSpaceTypes.push(SpaceType.ROOM);
|
||||||
|
}
|
||||||
|
if (missingSpaceTypes.length > 0) {
|
||||||
|
await this.addSpaceTypeData(missingSpaceTypes);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error while checking space type data:', err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async addSpaceTypeData(spaceTypes: string[]): Promise<void> {
|
||||||
|
try {
|
||||||
|
const spaceTypeEntities = spaceTypes.map((type) => ({
|
||||||
|
type,
|
||||||
|
}));
|
||||||
|
|
||||||
|
await this.spaceTypeRepository.save(spaceTypeEntities);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error while adding space type data:', err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
72
libs/common/src/seed/services/supper.admin.seeder.ts
Normal file
72
libs/common/src/seed/services/supper.admin.seeder.ts
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { UserRepository } from '@app/common/modules/user/repositories';
|
||||||
|
import { RoleType } from '@app/common/constants/role.type.enum';
|
||||||
|
import { UserRoleRepository } from '@app/common/modules/user-role/repositories';
|
||||||
|
import { RoleTypeRepository } from '@app/common/modules/role-type/repositories';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
import { HelperHashService } from '../../helper/services';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SuperAdminSeeder {
|
||||||
|
constructor(
|
||||||
|
private readonly configService: ConfigService,
|
||||||
|
private readonly userRepository: UserRepository,
|
||||||
|
private readonly userRoleRepository: UserRoleRepository,
|
||||||
|
private readonly roleTypeRepository: RoleTypeRepository,
|
||||||
|
private readonly helperHashService: HelperHashService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async createSuperAdminIfNotFound(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const superAdminData = await this.userRoleRepository.find({
|
||||||
|
where: { roleType: { type: RoleType.SUPER_ADMIN } },
|
||||||
|
relations: ['roleType'],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (superAdminData.length <= 0) {
|
||||||
|
// Create the super admin user if not found
|
||||||
|
console.log('Creating super admin user...');
|
||||||
|
|
||||||
|
await this.createSuperAdmin();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error while checking super admin:', err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private async getRoleUuidByRoleType(roleType: string) {
|
||||||
|
const role = await this.roleTypeRepository.findOne({
|
||||||
|
where: { type: roleType },
|
||||||
|
});
|
||||||
|
|
||||||
|
return role.uuid;
|
||||||
|
}
|
||||||
|
private async createSuperAdmin(): Promise<void> {
|
||||||
|
const salt = this.helperHashService.randomSalt(10); // Hash the password using bcrypt
|
||||||
|
const hashedPassword = await this.helperHashService.bcrypt(
|
||||||
|
this.configService.get<string>('super-admin.SUPER_ADMIN_PASSWORD'),
|
||||||
|
salt,
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
const user = await this.userRepository.save({
|
||||||
|
email: this.configService.get<string>('super-admin.SUPER_ADMIN_EMAIL'),
|
||||||
|
password: hashedPassword,
|
||||||
|
firstName: 'Super',
|
||||||
|
lastName: 'Admin',
|
||||||
|
isUserVerified: true,
|
||||||
|
isActive: true,
|
||||||
|
});
|
||||||
|
const defaultUserRoleUuid = await this.getRoleUuidByRoleType(
|
||||||
|
RoleType.SUPER_ADMIN,
|
||||||
|
);
|
||||||
|
|
||||||
|
await this.userRoleRepository.save({
|
||||||
|
user: { uuid: user.uuid },
|
||||||
|
roleType: { uuid: defaultUserRoleUuid },
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error while creating super admin:', err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,6 +12,8 @@ import { CommunityModule } from './community/community.module';
|
|||||||
import { BuildingModule } from './building/building.module';
|
import { BuildingModule } from './building/building.module';
|
||||||
import { FloorModule } from './floor/floor.module';
|
import { FloorModule } from './floor/floor.module';
|
||||||
import { UnitModule } from './unit/unit.module';
|
import { UnitModule } from './unit/unit.module';
|
||||||
|
import { RoleModule } from './role/role.module';
|
||||||
|
import { SeederModule } from '@app/common/seed/seeder.module';
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
ConfigModule.forRoot({
|
ConfigModule.forRoot({
|
||||||
@ -19,6 +21,7 @@ import { UnitModule } from './unit/unit.module';
|
|||||||
}),
|
}),
|
||||||
AuthenticationModule,
|
AuthenticationModule,
|
||||||
UserModule,
|
UserModule,
|
||||||
|
RoleModule,
|
||||||
CommunityModule,
|
CommunityModule,
|
||||||
BuildingModule,
|
BuildingModule,
|
||||||
FloorModule,
|
FloorModule,
|
||||||
@ -28,6 +31,7 @@ import { UnitModule } from './unit/unit.module';
|
|||||||
GroupModule,
|
GroupModule,
|
||||||
DeviceModule,
|
DeviceModule,
|
||||||
UserDevicePermissionModule,
|
UserDevicePermissionModule,
|
||||||
|
SeederModule,
|
||||||
],
|
],
|
||||||
controllers: [AuthenticationController],
|
controllers: [AuthenticationController],
|
||||||
})
|
})
|
||||||
|
@ -9,6 +9,8 @@ import { UserAuthService } from './services';
|
|||||||
import { UserRepository } from '../../libs/common/src/modules/user/repositories';
|
import { UserRepository } from '../../libs/common/src/modules/user/repositories';
|
||||||
import { UserSessionRepository } from '../../libs/common/src/modules/session/repositories/session.repository';
|
import { UserSessionRepository } from '../../libs/common/src/modules/session/repositories/session.repository';
|
||||||
import { UserOtpRepository } from '../../libs/common/src/modules/user-otp/repositories/user-otp.repository';
|
import { UserOtpRepository } from '../../libs/common/src/modules/user-otp/repositories/user-otp.repository';
|
||||||
|
import { UserRoleRepository } from '@app/common/modules/user-role/repositories';
|
||||||
|
import { RoleTypeRepository } from '@app/common/modules/role-type/repositories';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [ConfigModule, UserRepositoryModule, CommonModule],
|
imports: [ConfigModule, UserRepositoryModule, CommonModule],
|
||||||
@ -19,6 +21,8 @@ import { UserOtpRepository } from '../../libs/common/src/modules/user-otp/reposi
|
|||||||
UserRepository,
|
UserRepository,
|
||||||
UserSessionRepository,
|
UserSessionRepository,
|
||||||
UserOtpRepository,
|
UserOtpRepository,
|
||||||
|
UserRoleRepository,
|
||||||
|
RoleTypeRepository,
|
||||||
],
|
],
|
||||||
exports: [AuthenticationService, UserAuthService],
|
exports: [AuthenticationService, UserAuthService],
|
||||||
})
|
})
|
||||||
|
@ -14,9 +14,9 @@ import { UserSignUpDto } from '../dtos/user-auth.dto';
|
|||||||
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
|
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
|
||||||
import { ResponseMessage } from '../../../libs/common/src/response/response.decorator';
|
import { ResponseMessage } from '../../../libs/common/src/response/response.decorator';
|
||||||
import { UserLoginDto } from '../dtos/user-login.dto';
|
import { UserLoginDto } from '../dtos/user-login.dto';
|
||||||
import { JwtAuthGuard } from '../../../libs/common/src/guards/jwt.auth.guard';
|
|
||||||
import { ForgetPasswordDto, UserOtpDto, VerifyOtpDto } from '../dtos';
|
import { ForgetPasswordDto, UserOtpDto, VerifyOtpDto } from '../dtos';
|
||||||
import { RefreshTokenGuard } from '@app/common/guards/jwt-refresh.auth.guard';
|
import { RefreshTokenGuard } from '@app/common/guards/jwt-refresh.auth.guard';
|
||||||
|
import { SuperAdminRoleGuard } from 'src/guards/super.admin.role.guard';
|
||||||
|
|
||||||
@Controller({
|
@Controller({
|
||||||
version: '1',
|
version: '1',
|
||||||
@ -47,12 +47,12 @@ export class UserAuthController {
|
|||||||
return {
|
return {
|
||||||
statusCode: HttpStatus.CREATED,
|
statusCode: HttpStatus.CREATED,
|
||||||
data: accessToken,
|
data: accessToken,
|
||||||
message: 'User Loggedin Successfully',
|
message: 'User Logged in Successfully',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(SuperAdminRoleGuard)
|
||||||
@Delete('user/delete/:id')
|
@Delete('user/delete/:id')
|
||||||
async userDelete(@Param('id') id: string) {
|
async userDelete(@Param('id') id: string) {
|
||||||
await this.userAuthService.deleteUser(id);
|
await this.userAuthService.deleteUser(id);
|
||||||
@ -98,7 +98,7 @@ export class UserAuthController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(SuperAdminRoleGuard)
|
||||||
@Get('user/list')
|
@Get('user/list')
|
||||||
async userList() {
|
async userList() {
|
||||||
const userList = await this.userAuthService.userList();
|
const userList = await this.userAuthService.userList();
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { RoleTypeRepository } from './../../../libs/common/src/modules/role-type/repositories/role.type.repository';
|
||||||
|
import { UserRoleRepository } from './../../../libs/common/src/modules/user-role/repositories/user.role.repository';
|
||||||
import { UserRepository } from '../../../libs/common/src/modules/user/repositories';
|
import { UserRepository } from '../../../libs/common/src/modules/user/repositories';
|
||||||
import {
|
import {
|
||||||
BadRequestException,
|
BadRequestException,
|
||||||
@ -26,6 +28,8 @@ export class UserAuthService {
|
|||||||
private readonly helperHashService: HelperHashService,
|
private readonly helperHashService: HelperHashService,
|
||||||
private readonly authService: AuthService,
|
private readonly authService: AuthService,
|
||||||
private readonly emailService: EmailService,
|
private readonly emailService: EmailService,
|
||||||
|
private readonly userRoleRepository: UserRoleRepository,
|
||||||
|
private readonly roleTypeRepository: RoleTypeRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async signUp(userSignUpDto: UserSignUpDto): Promise<UserEntity> {
|
async signUp(userSignUpDto: UserSignUpDto): Promise<UserEntity> {
|
||||||
@ -33,12 +37,22 @@ export class UserAuthService {
|
|||||||
if (findUser) {
|
if (findUser) {
|
||||||
throw new BadRequestException('User already registered with given email');
|
throw new BadRequestException('User already registered with given email');
|
||||||
}
|
}
|
||||||
const salt = this.helperHashService.randomSalt(10);
|
const salt = this.helperHashService.randomSalt(10); // Hash the password using bcrypt
|
||||||
const password = this.helperHashService.bcrypt(
|
const hashedPassword = await this.helperHashService.bcrypt(
|
||||||
userSignUpDto.password,
|
userSignUpDto.password,
|
||||||
salt,
|
salt,
|
||||||
);
|
);
|
||||||
return await this.userRepository.save({ ...userSignUpDto, password });
|
|
||||||
|
try {
|
||||||
|
const user = await this.userRepository.save({
|
||||||
|
...userSignUpDto,
|
||||||
|
password: hashedPassword,
|
||||||
|
});
|
||||||
|
|
||||||
|
return user;
|
||||||
|
} catch (error) {
|
||||||
|
throw new BadRequestException('Failed to register user');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async findUser(email: string) {
|
async findUser(email: string) {
|
||||||
@ -67,6 +81,7 @@ export class UserAuthService {
|
|||||||
|
|
||||||
async userLogin(data: UserLoginDto) {
|
async userLogin(data: UserLoginDto) {
|
||||||
const user = await this.authService.validateUser(data.email, data.password);
|
const user = await this.authService.validateUser(data.email, data.password);
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new UnauthorizedException('Invalid login credentials.');
|
throw new UnauthorizedException('Invalid login credentials.');
|
||||||
}
|
}
|
||||||
@ -89,6 +104,9 @@ export class UserAuthService {
|
|||||||
email: user.email,
|
email: user.email,
|
||||||
userId: user.uuid,
|
userId: user.uuid,
|
||||||
uuid: user.uuid,
|
uuid: user.uuid,
|
||||||
|
roles: user?.roles?.map((role) => {
|
||||||
|
return { uuid: role.uuid, type: role.roleType.type };
|
||||||
|
}),
|
||||||
sessionId: session[1].uuid,
|
sessionId: session[1].uuid,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -12,12 +12,14 @@ import {
|
|||||||
UseGuards,
|
UseGuards,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
||||||
import { JwtAuthGuard } from '../../../libs/common/src/guards/jwt.auth.guard';
|
|
||||||
import { AddBuildingDto, AddUserBuildingDto } from '../dtos/add.building.dto';
|
import { AddBuildingDto, AddUserBuildingDto } from '../dtos/add.building.dto';
|
||||||
import { GetBuildingChildDto } from '../dtos/get.building.dto';
|
import { GetBuildingChildDto } from '../dtos/get.building.dto';
|
||||||
import { UpdateBuildingNameDto } from '../dtos/update.building.dto';
|
import { UpdateBuildingNameDto } from '../dtos/update.building.dto';
|
||||||
import { CheckCommunityTypeGuard } from 'src/guards/community.type.guard';
|
import { CheckCommunityTypeGuard } from 'src/guards/community.type.guard';
|
||||||
import { CheckUserBuildingGuard } from 'src/guards/user.building.guard';
|
import { CheckUserBuildingGuard } from 'src/guards/user.building.guard';
|
||||||
|
import { AdminRoleGuard } from 'src/guards/admin.role.guard';
|
||||||
|
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
||||||
|
import { BuildingPermissionGuard } from 'src/guards/building.permission.guard';
|
||||||
|
|
||||||
@ApiTags('Building Module')
|
@ApiTags('Building Module')
|
||||||
@Controller({
|
@Controller({
|
||||||
@ -28,12 +30,17 @@ export class BuildingController {
|
|||||||
constructor(private readonly buildingService: BuildingService) {}
|
constructor(private readonly buildingService: BuildingService) {}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard, CheckCommunityTypeGuard)
|
@UseGuards(AdminRoleGuard, CheckCommunityTypeGuard)
|
||||||
@Post()
|
@Post()
|
||||||
async addBuilding(@Body() addBuildingDto: AddBuildingDto) {
|
async addBuilding(@Body() addBuildingDto: AddBuildingDto) {
|
||||||
try {
|
try {
|
||||||
const building = await this.buildingService.addBuilding(addBuildingDto);
|
const building = await this.buildingService.addBuilding(addBuildingDto);
|
||||||
return { message: 'Building added successfully', uuid: building.uuid };
|
return {
|
||||||
|
statusCode: HttpStatus.CREATED,
|
||||||
|
success: true,
|
||||||
|
message: 'Building added successfully',
|
||||||
|
data: building,
|
||||||
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
error.message || 'Internal server error',
|
error.message || 'Internal server error',
|
||||||
@ -43,7 +50,7 @@ export class BuildingController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, BuildingPermissionGuard)
|
||||||
@Get(':buildingUuid')
|
@Get(':buildingUuid')
|
||||||
async getBuildingByUuid(@Param('buildingUuid') buildingUuid: string) {
|
async getBuildingByUuid(@Param('buildingUuid') buildingUuid: string) {
|
||||||
try {
|
try {
|
||||||
@ -59,7 +66,7 @@ export class BuildingController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, BuildingPermissionGuard)
|
||||||
@Get('child/:buildingUuid')
|
@Get('child/:buildingUuid')
|
||||||
async getBuildingChildByUuid(
|
async getBuildingChildByUuid(
|
||||||
@Param('buildingUuid') buildingUuid: string,
|
@Param('buildingUuid') buildingUuid: string,
|
||||||
@ -79,7 +86,7 @@ export class BuildingController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, BuildingPermissionGuard)
|
||||||
@Get('parent/:buildingUuid')
|
@Get('parent/:buildingUuid')
|
||||||
async getBuildingParentByUuid(@Param('buildingUuid') buildingUuid: string) {
|
async getBuildingParentByUuid(@Param('buildingUuid') buildingUuid: string) {
|
||||||
try {
|
try {
|
||||||
@ -94,12 +101,16 @@ export class BuildingController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard, CheckUserBuildingGuard)
|
@UseGuards(AdminRoleGuard, CheckUserBuildingGuard)
|
||||||
@Post('user')
|
@Post('user')
|
||||||
async addUserBuilding(@Body() addUserBuildingDto: AddUserBuildingDto) {
|
async addUserBuilding(@Body() addUserBuildingDto: AddUserBuildingDto) {
|
||||||
try {
|
try {
|
||||||
await this.buildingService.addUserBuilding(addUserBuildingDto);
|
await this.buildingService.addUserBuilding(addUserBuildingDto);
|
||||||
return { message: 'user building added successfully' };
|
return {
|
||||||
|
statusCode: HttpStatus.CREATED,
|
||||||
|
success: true,
|
||||||
|
message: 'user building added successfully',
|
||||||
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
error.message || 'Internal server error',
|
error.message || 'Internal server error',
|
||||||
@ -122,7 +133,7 @@ export class BuildingController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, BuildingPermissionGuard)
|
||||||
@Put('rename/:buildingUuid')
|
@Put('rename/:buildingUuid')
|
||||||
async renameBuildingByUuid(
|
async renameBuildingByUuid(
|
||||||
@Param('buildingUuid') buildingUuid: string,
|
@Param('buildingUuid') buildingUuid: string,
|
||||||
|
@ -10,6 +10,7 @@ import { UserSpaceRepositoryModule } from '@app/common/modules/user-space/user.s
|
|||||||
import { UserSpaceRepository } from '@app/common/modules/user-space/repositories';
|
import { UserSpaceRepository } from '@app/common/modules/user-space/repositories';
|
||||||
import { UserRepositoryModule } from '@app/common/modules/user/user.repository.module';
|
import { UserRepositoryModule } from '@app/common/modules/user/user.repository.module';
|
||||||
import { UserRepository } from '@app/common/modules/user/repositories';
|
import { UserRepository } from '@app/common/modules/user/repositories';
|
||||||
|
import { SpacePermissionService } from '@app/common/helper/services';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@ -26,7 +27,8 @@ import { UserRepository } from '@app/common/modules/user/repositories';
|
|||||||
SpaceTypeRepository,
|
SpaceTypeRepository,
|
||||||
UserSpaceRepository,
|
UserSpaceRepository,
|
||||||
UserRepository,
|
UserRepository,
|
||||||
|
SpacePermissionService,
|
||||||
],
|
],
|
||||||
exports: [CommunityService],
|
exports: [CommunityService, SpacePermissionService],
|
||||||
})
|
})
|
||||||
export class CommunityModule {}
|
export class CommunityModule {}
|
||||||
|
@ -12,7 +12,6 @@ import {
|
|||||||
UseGuards,
|
UseGuards,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
||||||
import { JwtAuthGuard } from '../../../libs/common/src/guards/jwt.auth.guard';
|
|
||||||
import {
|
import {
|
||||||
AddCommunityDto,
|
AddCommunityDto,
|
||||||
AddUserCommunityDto,
|
AddUserCommunityDto,
|
||||||
@ -20,6 +19,9 @@ import {
|
|||||||
import { GetCommunityChildDto } from '../dtos/get.community.dto';
|
import { GetCommunityChildDto } from '../dtos/get.community.dto';
|
||||||
import { UpdateCommunityNameDto } from '../dtos/update.community.dto';
|
import { UpdateCommunityNameDto } from '../dtos/update.community.dto';
|
||||||
import { CheckUserCommunityGuard } from 'src/guards/user.community.guard';
|
import { CheckUserCommunityGuard } from 'src/guards/user.community.guard';
|
||||||
|
import { AdminRoleGuard } from 'src/guards/admin.role.guard';
|
||||||
|
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
||||||
|
import { CommunityPermissionGuard } from 'src/guards/community.permission.guard';
|
||||||
|
|
||||||
@ApiTags('Community Module')
|
@ApiTags('Community Module')
|
||||||
@Controller({
|
@Controller({
|
||||||
@ -30,13 +32,18 @@ export class CommunityController {
|
|||||||
constructor(private readonly communityService: CommunityService) {}
|
constructor(private readonly communityService: CommunityService) {}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(AdminRoleGuard)
|
||||||
@Post()
|
@Post()
|
||||||
async addCommunity(@Body() addCommunityDto: AddCommunityDto) {
|
async addCommunity(@Body() addCommunityDto: AddCommunityDto) {
|
||||||
try {
|
try {
|
||||||
const community =
|
const community =
|
||||||
await this.communityService.addCommunity(addCommunityDto);
|
await this.communityService.addCommunity(addCommunityDto);
|
||||||
return { message: 'Community added successfully', uuid: community.uuid };
|
return {
|
||||||
|
statusCode: HttpStatus.CREATED,
|
||||||
|
success: true,
|
||||||
|
message: 'Community added successfully',
|
||||||
|
data: community,
|
||||||
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
error.message || 'Internal server error',
|
error.message || 'Internal server error',
|
||||||
@ -46,7 +53,7 @@ export class CommunityController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, CommunityPermissionGuard)
|
||||||
@Get(':communityUuid')
|
@Get(':communityUuid')
|
||||||
async getCommunityByUuid(@Param('communityUuid') communityUuid: string) {
|
async getCommunityByUuid(@Param('communityUuid') communityUuid: string) {
|
||||||
try {
|
try {
|
||||||
@ -62,7 +69,7 @@ export class CommunityController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, CommunityPermissionGuard)
|
||||||
@Get('child/:communityUuid')
|
@Get('child/:communityUuid')
|
||||||
async getCommunityChildByUuid(
|
async getCommunityChildByUuid(
|
||||||
@Param('communityUuid') communityUuid: string,
|
@Param('communityUuid') communityUuid: string,
|
||||||
@ -96,12 +103,16 @@ export class CommunityController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard, CheckUserCommunityGuard)
|
@UseGuards(AdminRoleGuard, CheckUserCommunityGuard)
|
||||||
@Post('user')
|
@Post('user')
|
||||||
async addUserCommunity(@Body() addUserCommunityDto: AddUserCommunityDto) {
|
async addUserCommunity(@Body() addUserCommunityDto: AddUserCommunityDto) {
|
||||||
try {
|
try {
|
||||||
await this.communityService.addUserCommunity(addUserCommunityDto);
|
await this.communityService.addUserCommunity(addUserCommunityDto);
|
||||||
return { message: 'user community added successfully' };
|
return {
|
||||||
|
statusCode: HttpStatus.CREATED,
|
||||||
|
success: true,
|
||||||
|
message: 'user community added successfully',
|
||||||
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
error.message || 'Internal server error',
|
error.message || 'Internal server error',
|
||||||
@ -110,7 +121,7 @@ export class CommunityController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, CommunityPermissionGuard)
|
||||||
@Put('rename/:communityUuid')
|
@Put('rename/:communityUuid')
|
||||||
async renameCommunityByUuid(
|
async renameCommunityByUuid(
|
||||||
@Param('communityUuid') communityUuid: string,
|
@Param('communityUuid') communityUuid: string,
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
HttpException,
|
HttpException,
|
||||||
HttpStatus,
|
HttpStatus,
|
||||||
UseGuards,
|
UseGuards,
|
||||||
|
Req,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
||||||
import {
|
import {
|
||||||
@ -22,6 +23,8 @@ import {
|
|||||||
import { ControlDeviceDto } from '../dtos/control.device.dto';
|
import { ControlDeviceDto } from '../dtos/control.device.dto';
|
||||||
import { CheckRoomGuard } from 'src/guards/room.guard';
|
import { CheckRoomGuard } from 'src/guards/room.guard';
|
||||||
import { CheckGroupGuard } from 'src/guards/group.guard';
|
import { CheckGroupGuard } from 'src/guards/group.guard';
|
||||||
|
import { CheckUserHavePermission } from 'src/guards/user.device.permission.guard';
|
||||||
|
import { CheckUserHaveControllablePermission } from 'src/guards/user.device.controllable.permission.guard';
|
||||||
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
||||||
|
|
||||||
@ApiTags('Device Module')
|
@ApiTags('Device Module')
|
||||||
@ -37,10 +40,13 @@ export class DeviceController {
|
|||||||
@Get('room')
|
@Get('room')
|
||||||
async getDevicesByRoomId(
|
async getDevicesByRoomId(
|
||||||
@Query() getDeviceByRoomUuidDto: GetDeviceByRoomUuidDto,
|
@Query() getDeviceByRoomUuidDto: GetDeviceByRoomUuidDto,
|
||||||
|
@Req() req: any,
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
const userUuid = req.user.uuid;
|
||||||
return await this.deviceService.getDevicesByRoomId(
|
return await this.deviceService.getDevicesByRoomId(
|
||||||
getDeviceByRoomUuidDto,
|
getDeviceByRoomUuidDto,
|
||||||
|
userUuid,
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
@ -55,7 +61,15 @@ export class DeviceController {
|
|||||||
@Post('room')
|
@Post('room')
|
||||||
async addDeviceInRoom(@Body() addDeviceInRoomDto: AddDeviceInRoomDto) {
|
async addDeviceInRoom(@Body() addDeviceInRoomDto: AddDeviceInRoomDto) {
|
||||||
try {
|
try {
|
||||||
return await this.deviceService.addDeviceInRoom(addDeviceInRoomDto);
|
const device =
|
||||||
|
await this.deviceService.addDeviceInRoom(addDeviceInRoomDto);
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusCode: HttpStatus.CREATED,
|
||||||
|
success: true,
|
||||||
|
message: 'device added in room successfully',
|
||||||
|
data: device,
|
||||||
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
error.message || 'Internal server error',
|
error.message || 'Internal server error',
|
||||||
@ -68,10 +82,13 @@ export class DeviceController {
|
|||||||
@Get('group')
|
@Get('group')
|
||||||
async getDevicesByGroupId(
|
async getDevicesByGroupId(
|
||||||
@Query() getDeviceByGroupIdDto: GetDeviceByGroupIdDto,
|
@Query() getDeviceByGroupIdDto: GetDeviceByGroupIdDto,
|
||||||
|
@Req() req: any,
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
const userUuid = req.user.uuid;
|
||||||
return await this.deviceService.getDevicesByGroupId(
|
return await this.deviceService.getDevicesByGroupId(
|
||||||
getDeviceByGroupIdDto,
|
getDeviceByGroupIdDto,
|
||||||
|
userUuid,
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
@ -94,11 +111,18 @@ export class DeviceController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, CheckUserHavePermission)
|
||||||
@Get(':deviceUuid')
|
@Get(':deviceUuid')
|
||||||
async getDeviceDetailsByDeviceId(@Param('deviceUuid') deviceUuid: string) {
|
async getDeviceDetailsByDeviceId(
|
||||||
|
@Param('deviceUuid') deviceUuid: string,
|
||||||
|
@Req() req: any,
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
return await this.deviceService.getDeviceDetailsByDeviceId(deviceUuid);
|
const userUuid = req.user.uuid;
|
||||||
|
return await this.deviceService.getDeviceDetailsByDeviceId(
|
||||||
|
deviceUuid,
|
||||||
|
userUuid,
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
error.message || 'Internal server error',
|
error.message || 'Internal server error',
|
||||||
@ -107,7 +131,7 @@ export class DeviceController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, CheckUserHavePermission)
|
||||||
@Get(':deviceUuid/functions')
|
@Get(':deviceUuid/functions')
|
||||||
async getDeviceInstructionByDeviceId(
|
async getDeviceInstructionByDeviceId(
|
||||||
@Param('deviceUuid') deviceUuid: string,
|
@Param('deviceUuid') deviceUuid: string,
|
||||||
@ -124,7 +148,7 @@ export class DeviceController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, CheckUserHavePermission)
|
||||||
@Get(':deviceUuid/functions/status')
|
@Get(':deviceUuid/functions/status')
|
||||||
async getDevicesInstructionStatus(@Param('deviceUuid') deviceUuid: string) {
|
async getDevicesInstructionStatus(@Param('deviceUuid') deviceUuid: string) {
|
||||||
try {
|
try {
|
||||||
@ -138,11 +162,17 @@ export class DeviceController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, CheckUserHaveControllablePermission)
|
||||||
@Post('control')
|
@Post(':deviceUuid/control')
|
||||||
async controlDevice(@Body() controlDeviceDto: ControlDeviceDto) {
|
async controlDevice(
|
||||||
|
@Body() controlDeviceDto: ControlDeviceDto,
|
||||||
|
@Param('deviceUuid') deviceUuid: string,
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
return await this.deviceService.controlDevice(controlDeviceDto);
|
return await this.deviceService.controlDevice(
|
||||||
|
controlDeviceDto,
|
||||||
|
deviceUuid,
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
error.message || 'Internal server error',
|
error.message || 'Internal server error',
|
||||||
|
@ -5,15 +5,14 @@ import { ConfigModule } from '@nestjs/config';
|
|||||||
import { ProductRepositoryModule } from '@app/common/modules/product/product.repository.module';
|
import { ProductRepositoryModule } from '@app/common/modules/product/product.repository.module';
|
||||||
import { ProductRepository } from '@app/common/modules/product/repositories';
|
import { ProductRepository } from '@app/common/modules/product/repositories';
|
||||||
import { DeviceRepositoryModule } from '@app/common/modules/device';
|
import { DeviceRepositoryModule } from '@app/common/modules/device';
|
||||||
import {
|
import { DeviceRepository } from '@app/common/modules/device/repositories';
|
||||||
DeviceRepository,
|
|
||||||
DeviceUserTypeRepository,
|
|
||||||
} from '@app/common/modules/device/repositories';
|
|
||||||
import { PermissionTypeRepository } from '@app/common/modules/permission/repositories';
|
import { PermissionTypeRepository } from '@app/common/modules/permission/repositories';
|
||||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
||||||
import { GroupDeviceRepository } from '@app/common/modules/group-device/repositories';
|
import { GroupDeviceRepository } from '@app/common/modules/group-device/repositories';
|
||||||
import { GroupRepository } from '@app/common/modules/group/repositories';
|
import { GroupRepository } from '@app/common/modules/group/repositories';
|
||||||
import { GroupRepositoryModule } from '@app/common/modules/group/group.repository.module';
|
import { GroupRepositoryModule } from '@app/common/modules/group/group.repository.module';
|
||||||
|
import { DeviceUserPermissionRepository } from '@app/common/modules/device-user-permission/repositories';
|
||||||
|
import { UserRepository } from '@app/common/modules/user/repositories';
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
ConfigModule,
|
ConfigModule,
|
||||||
@ -25,12 +24,13 @@ import { GroupRepositoryModule } from '@app/common/modules/group/group.repositor
|
|||||||
providers: [
|
providers: [
|
||||||
DeviceService,
|
DeviceService,
|
||||||
ProductRepository,
|
ProductRepository,
|
||||||
DeviceUserTypeRepository,
|
DeviceUserPermissionRepository,
|
||||||
PermissionTypeRepository,
|
PermissionTypeRepository,
|
||||||
SpaceRepository,
|
SpaceRepository,
|
||||||
DeviceRepository,
|
DeviceRepository,
|
||||||
GroupDeviceRepository,
|
GroupDeviceRepository,
|
||||||
GroupRepository,
|
GroupRepository,
|
||||||
|
UserRepository,
|
||||||
],
|
],
|
||||||
exports: [DeviceService],
|
exports: [DeviceService],
|
||||||
})
|
})
|
||||||
|
@ -2,14 +2,6 @@ import { ApiProperty } from '@nestjs/swagger';
|
|||||||
import { IsNotEmpty, IsString } from 'class-validator';
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
export class ControlDeviceDto {
|
export class ControlDeviceDto {
|
||||||
@ApiProperty({
|
|
||||||
description: 'deviceUuid',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public deviceUuid: string;
|
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'code',
|
description: 'code',
|
||||||
required: true,
|
required: true,
|
||||||
|
@ -4,7 +4,6 @@ import {
|
|||||||
HttpException,
|
HttpException,
|
||||||
HttpStatus,
|
HttpStatus,
|
||||||
NotFoundException,
|
NotFoundException,
|
||||||
BadRequestException,
|
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { TuyaContext } from '@tuya/tuya-connector-nodejs';
|
import { TuyaContext } from '@tuya/tuya-connector-nodejs';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
@ -18,7 +17,6 @@ import {
|
|||||||
GetDeviceDetailsFunctionsStatusInterface,
|
GetDeviceDetailsFunctionsStatusInterface,
|
||||||
GetDeviceDetailsInterface,
|
GetDeviceDetailsInterface,
|
||||||
controlDeviceInterface,
|
controlDeviceInterface,
|
||||||
updateDeviceFirmwareInterface,
|
|
||||||
} from '../interfaces/get.device.interface';
|
} from '../interfaces/get.device.interface';
|
||||||
import {
|
import {
|
||||||
GetDeviceByGroupIdDto,
|
GetDeviceByGroupIdDto,
|
||||||
@ -29,6 +27,8 @@ import { convertKeysToCamelCase } from '@app/common/helper/camelCaseConverter';
|
|||||||
import { DeviceRepository } from '@app/common/modules/device/repositories';
|
import { DeviceRepository } from '@app/common/modules/device/repositories';
|
||||||
import { GroupDeviceRepository } from '@app/common/modules/group-device/repositories';
|
import { GroupDeviceRepository } from '@app/common/modules/group-device/repositories';
|
||||||
import { ProductType } from '@app/common/constants/product-type.enum';
|
import { ProductType } from '@app/common/constants/product-type.enum';
|
||||||
|
import { PermissionType } from '@app/common/constants/permission-type.enum';
|
||||||
|
import { In } from 'typeorm';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DeviceService {
|
export class DeviceService {
|
||||||
@ -50,13 +50,25 @@ export class DeviceService {
|
|||||||
|
|
||||||
async getDevicesByRoomId(
|
async getDevicesByRoomId(
|
||||||
getDeviceByRoomUuidDto: GetDeviceByRoomUuidDto,
|
getDeviceByRoomUuidDto: GetDeviceByRoomUuidDto,
|
||||||
|
userUuid: string,
|
||||||
): Promise<GetDeviceDetailsInterface[]> {
|
): Promise<GetDeviceDetailsInterface[]> {
|
||||||
try {
|
try {
|
||||||
const devices = await this.deviceRepository.find({
|
const devices = await this.deviceRepository.find({
|
||||||
where: {
|
where: {
|
||||||
spaceDevice: { uuid: getDeviceByRoomUuidDto.roomUuid },
|
spaceDevice: { uuid: getDeviceByRoomUuidDto.roomUuid },
|
||||||
|
permission: {
|
||||||
|
userUuid,
|
||||||
|
permissionType: {
|
||||||
|
type: In([PermissionType.READ, PermissionType.CONTROLLABLE]),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
relations: ['spaceDevice', 'productDevice'],
|
relations: [
|
||||||
|
'spaceDevice',
|
||||||
|
'productDevice',
|
||||||
|
'permission',
|
||||||
|
'permission.permissionType',
|
||||||
|
],
|
||||||
});
|
});
|
||||||
const devicesData = await Promise.all(
|
const devicesData = await Promise.all(
|
||||||
devices.map(async (device) => {
|
devices.map(async (device) => {
|
||||||
@ -67,9 +79,11 @@ export class DeviceService {
|
|||||||
uuid: device.uuid,
|
uuid: device.uuid,
|
||||||
productUuid: device.productDevice.uuid,
|
productUuid: device.productDevice.uuid,
|
||||||
productType: device.productDevice.prodType,
|
productType: device.productDevice.prodType,
|
||||||
|
permissionType: device.permission[0].permissionType.type,
|
||||||
} as GetDeviceDetailsInterface;
|
} as GetDeviceDetailsInterface;
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
return devicesData;
|
return devicesData;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Handle the error here
|
// Handle the error here
|
||||||
@ -80,11 +94,29 @@ export class DeviceService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDevicesByGroupId(getDeviceByGroupIdDto: GetDeviceByGroupIdDto) {
|
async getDevicesByGroupId(
|
||||||
|
getDeviceByGroupIdDto: GetDeviceByGroupIdDto,
|
||||||
|
userUuid: string,
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
const groupDevices = await this.groupDeviceRepository.find({
|
const groupDevices = await this.groupDeviceRepository.find({
|
||||||
where: { group: { uuid: getDeviceByGroupIdDto.groupUuid } },
|
where: {
|
||||||
relations: ['device'],
|
group: { uuid: getDeviceByGroupIdDto.groupUuid },
|
||||||
|
device: {
|
||||||
|
permission: {
|
||||||
|
userUuid,
|
||||||
|
permissionType: {
|
||||||
|
type: PermissionType.READ || PermissionType.CONTROLLABLE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
relations: [
|
||||||
|
'device',
|
||||||
|
'device.productDevice',
|
||||||
|
'device.permission',
|
||||||
|
'device.permission.permissionType',
|
||||||
|
],
|
||||||
});
|
});
|
||||||
const devicesData = await Promise.all(
|
const devicesData = await Promise.all(
|
||||||
groupDevices.map(async (device) => {
|
groupDevices.map(async (device) => {
|
||||||
@ -92,9 +124,10 @@ export class DeviceService {
|
|||||||
...(await this.getDeviceDetailsByDeviceIdTuya(
|
...(await this.getDeviceDetailsByDeviceIdTuya(
|
||||||
device.device.deviceTuyaUuid,
|
device.device.deviceTuyaUuid,
|
||||||
)),
|
)),
|
||||||
uuid: device.uuid,
|
uuid: device.device.uuid,
|
||||||
productUuid: device.device.productDevice.uuid,
|
productUuid: device.device.productDevice.uuid,
|
||||||
productType: device.device.productDevice.prodType,
|
productType: device.device.productDevice.prodType,
|
||||||
|
permissionType: device.device.permission[0].permissionType.type,
|
||||||
} as GetDeviceDetailsInterface;
|
} as GetDeviceDetailsInterface;
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@ -107,7 +140,6 @@ export class DeviceService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async addDeviceInRoom(addDeviceInRoomDto: AddDeviceInRoomDto) {
|
async addDeviceInRoom(addDeviceInRoomDto: AddDeviceInRoomDto) {
|
||||||
try {
|
try {
|
||||||
const device = await this.getDeviceDetailsByDeviceIdTuya(
|
const device = await this.getDeviceDetailsByDeviceIdTuya(
|
||||||
@ -118,12 +150,11 @@ export class DeviceService {
|
|||||||
throw new Error('Product UUID is missing for the device.');
|
throw new Error('Product UUID is missing for the device.');
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.deviceRepository.save({
|
return await this.deviceRepository.save({
|
||||||
deviceTuyaUuid: addDeviceInRoomDto.deviceTuyaUuid,
|
deviceTuyaUuid: addDeviceInRoomDto.deviceTuyaUuid,
|
||||||
spaceDevice: { uuid: addDeviceInRoomDto.roomUuid },
|
spaceDevice: { uuid: addDeviceInRoomDto.roomUuid },
|
||||||
productDevice: { uuid: device.productUuid },
|
productDevice: { uuid: device.productUuid },
|
||||||
});
|
});
|
||||||
return { message: 'device added in room successfully' };
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.code === '23505') {
|
if (error.code === '23505') {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
@ -161,12 +192,9 @@ export class DeviceService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async controlDevice(controlDeviceDto: ControlDeviceDto) {
|
async controlDevice(controlDeviceDto: ControlDeviceDto, deviceUuid: string) {
|
||||||
try {
|
try {
|
||||||
const deviceDetails = await this.getDeviceByDeviceUuid(
|
const deviceDetails = await this.getDeviceByDeviceUuid(deviceUuid, false);
|
||||||
controlDeviceDto.deviceUuid,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!deviceDetails || !deviceDetails.deviceTuyaUuid) {
|
if (!deviceDetails || !deviceDetails.deviceTuyaUuid) {
|
||||||
throw new NotFoundException('Device Not Found');
|
throw new NotFoundException('Device Not Found');
|
||||||
@ -185,7 +213,10 @@ export class DeviceService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new HttpException('Device Not Found', HttpStatus.NOT_FOUND);
|
throw new HttpException(
|
||||||
|
error.message || 'Device Not Found',
|
||||||
|
error.status || HttpStatus.NOT_FOUND,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async controlDeviceTuya(
|
async controlDeviceTuya(
|
||||||
@ -213,8 +244,19 @@ export class DeviceService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDeviceDetailsByDeviceId(deviceUuid: string) {
|
async getDeviceDetailsByDeviceId(deviceUuid: string, userUuid: string) {
|
||||||
try {
|
try {
|
||||||
|
const userDevicePermission = await this.getUserDevicePermission(
|
||||||
|
userUuid,
|
||||||
|
deviceUuid,
|
||||||
|
);
|
||||||
|
|
||||||
|
const deviceDetails = await this.deviceRepository.findOne({
|
||||||
|
where: {
|
||||||
|
uuid: deviceUuid,
|
||||||
|
},
|
||||||
|
relations: ['productDevice'],
|
||||||
|
});
|
||||||
const deviceDetails = await this.getDeviceByDeviceUuid(deviceUuid);
|
const deviceDetails = await this.getDeviceByDeviceUuid(deviceUuid);
|
||||||
|
|
||||||
if (!deviceDetails) {
|
if (!deviceDetails) {
|
||||||
@ -230,9 +272,13 @@ export class DeviceService {
|
|||||||
uuid: deviceDetails.uuid,
|
uuid: deviceDetails.uuid,
|
||||||
productUuid: deviceDetails.productDevice.uuid,
|
productUuid: deviceDetails.productDevice.uuid,
|
||||||
productType: deviceDetails.productDevice.prodType,
|
productType: deviceDetails.productDevice.prodType,
|
||||||
|
permissionType: userDevicePermission,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new HttpException('Device Not Found', HttpStatus.NOT_FOUND);
|
throw new HttpException(
|
||||||
|
error.message || 'Device Not Found',
|
||||||
|
HttpStatus.NOT_FOUND,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async getDeviceDetailsByDeviceIdTuya(
|
async getDeviceDetailsByDeviceIdTuya(
|
||||||
@ -255,6 +301,7 @@ export class DeviceService {
|
|||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const { productName, productId, id, ...rest } = camelCaseResponse.result;
|
const { productName, productId, id, ...rest } = camelCaseResponse.result;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...rest,
|
...rest,
|
||||||
productUuid: product.uuid,
|
productUuid: product.uuid,
|
||||||
@ -465,4 +512,13 @@ export class DeviceService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private async getUserDevicePermission(userUuid: string, deviceUuid: string) {
|
||||||
|
const device = await this.deviceRepository.findOne({
|
||||||
|
where: {
|
||||||
|
uuid: deviceUuid,
|
||||||
|
},
|
||||||
|
relations: ['permission', 'permission.permissionType'],
|
||||||
|
});
|
||||||
|
return device.permission[0].permissionType.type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,12 +12,14 @@ import {
|
|||||||
UseGuards,
|
UseGuards,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
||||||
import { JwtAuthGuard } from '../../../libs/common/src/guards/jwt.auth.guard';
|
|
||||||
import { AddFloorDto, AddUserFloorDto } from '../dtos/add.floor.dto';
|
import { AddFloorDto, AddUserFloorDto } from '../dtos/add.floor.dto';
|
||||||
import { GetFloorChildDto } from '../dtos/get.floor.dto';
|
import { GetFloorChildDto } from '../dtos/get.floor.dto';
|
||||||
import { UpdateFloorNameDto } from '../dtos/update.floor.dto';
|
import { UpdateFloorNameDto } from '../dtos/update.floor.dto';
|
||||||
import { CheckBuildingTypeGuard } from 'src/guards/building.type.guard';
|
import { CheckBuildingTypeGuard } from 'src/guards/building.type.guard';
|
||||||
import { CheckUserFloorGuard } from 'src/guards/user.floor.guard';
|
import { CheckUserFloorGuard } from 'src/guards/user.floor.guard';
|
||||||
|
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
||||||
|
import { AdminRoleGuard } from 'src/guards/admin.role.guard';
|
||||||
|
import { FloorPermissionGuard } from 'src/guards/floor.permission.guard';
|
||||||
|
|
||||||
@ApiTags('Floor Module')
|
@ApiTags('Floor Module')
|
||||||
@Controller({
|
@Controller({
|
||||||
@ -28,12 +30,17 @@ export class FloorController {
|
|||||||
constructor(private readonly floorService: FloorService) {}
|
constructor(private readonly floorService: FloorService) {}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard, CheckBuildingTypeGuard)
|
@UseGuards(AdminRoleGuard, CheckBuildingTypeGuard)
|
||||||
@Post()
|
@Post()
|
||||||
async addFloor(@Body() addFloorDto: AddFloorDto) {
|
async addFloor(@Body() addFloorDto: AddFloorDto) {
|
||||||
try {
|
try {
|
||||||
const floor = await this.floorService.addFloor(addFloorDto);
|
const floor = await this.floorService.addFloor(addFloorDto);
|
||||||
return { message: 'Floor added successfully', uuid: floor.uuid };
|
return {
|
||||||
|
statusCode: HttpStatus.CREATED,
|
||||||
|
success: true,
|
||||||
|
message: 'Floor added successfully',
|
||||||
|
data: floor,
|
||||||
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
error.message || 'Internal server error',
|
error.message || 'Internal server error',
|
||||||
@ -43,7 +50,7 @@ export class FloorController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, FloorPermissionGuard)
|
||||||
@Get(':floorUuid')
|
@Get(':floorUuid')
|
||||||
async getFloorByUuid(@Param('floorUuid') floorUuid: string) {
|
async getFloorByUuid(@Param('floorUuid') floorUuid: string) {
|
||||||
try {
|
try {
|
||||||
@ -58,7 +65,7 @@ export class FloorController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, FloorPermissionGuard)
|
||||||
@Get('child/:floorUuid')
|
@Get('child/:floorUuid')
|
||||||
async getFloorChildByUuid(
|
async getFloorChildByUuid(
|
||||||
@Param('floorUuid') floorUuid: string,
|
@Param('floorUuid') floorUuid: string,
|
||||||
@ -78,7 +85,7 @@ export class FloorController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, FloorPermissionGuard)
|
||||||
@Get('parent/:floorUuid')
|
@Get('parent/:floorUuid')
|
||||||
async getFloorParentByUuid(@Param('floorUuid') floorUuid: string) {
|
async getFloorParentByUuid(@Param('floorUuid') floorUuid: string) {
|
||||||
try {
|
try {
|
||||||
@ -93,12 +100,16 @@ export class FloorController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard, CheckUserFloorGuard)
|
@UseGuards(AdminRoleGuard, CheckUserFloorGuard)
|
||||||
@Post('user')
|
@Post('user')
|
||||||
async addUserFloor(@Body() addUserFloorDto: AddUserFloorDto) {
|
async addUserFloor(@Body() addUserFloorDto: AddUserFloorDto) {
|
||||||
try {
|
try {
|
||||||
await this.floorService.addUserFloor(addUserFloorDto);
|
await this.floorService.addUserFloor(addUserFloorDto);
|
||||||
return { message: 'user floor added successfully' };
|
return {
|
||||||
|
statusCode: HttpStatus.CREATED,
|
||||||
|
success: true,
|
||||||
|
message: 'user floor added successfully',
|
||||||
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
error.message || 'Internal server error',
|
error.message || 'Internal server error',
|
||||||
@ -122,7 +133,7 @@ export class FloorController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, FloorPermissionGuard)
|
||||||
@Put('rename/:floorUuid')
|
@Put('rename/:floorUuid')
|
||||||
async renameFloorByUuid(
|
async renameFloorByUuid(
|
||||||
@Param('floorUuid') floorUuid: string,
|
@Param('floorUuid') floorUuid: string,
|
||||||
|
@ -12,11 +12,11 @@ import {
|
|||||||
HttpStatus,
|
HttpStatus,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
||||||
import { JwtAuthGuard } from '../../../libs/common/src/guards/jwt.auth.guard';
|
|
||||||
import { AddGroupDto } from '../dtos/add.group.dto';
|
import { AddGroupDto } from '../dtos/add.group.dto';
|
||||||
import { ControlGroupDto } from '../dtos/control.group.dto';
|
import { ControlGroupDto } from '../dtos/control.group.dto';
|
||||||
import { RenameGroupDto } from '../dtos/rename.group.dto copy';
|
import { RenameGroupDto } from '../dtos/rename.group.dto copy';
|
||||||
import { CheckProductUuidForAllDevicesGuard } from 'src/guards/device.product.guard';
|
import { CheckProductUuidForAllDevicesGuard } from 'src/guards/device.product.guard';
|
||||||
|
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
||||||
|
|
||||||
@ApiTags('Group Module')
|
@ApiTags('Group Module')
|
||||||
@Controller({
|
@Controller({
|
||||||
|
20
src/guards/admin.role.guard.ts
Normal file
20
src/guards/admin.role.guard.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { RoleType } from '@app/common/constants/role.type.enum';
|
||||||
|
import { BadRequestException, UnauthorizedException } from '@nestjs/common';
|
||||||
|
import { AuthGuard } from '@nestjs/passport';
|
||||||
|
|
||||||
|
export class AdminRoleGuard extends AuthGuard('jwt') {
|
||||||
|
handleRequest(err, user) {
|
||||||
|
if (err || !user) {
|
||||||
|
throw err || new UnauthorizedException();
|
||||||
|
} else {
|
||||||
|
const isAdmin = user.roles.some(
|
||||||
|
(role) =>
|
||||||
|
role.type === RoleType.SUPER_ADMIN || role.type === RoleType.ADMIN,
|
||||||
|
);
|
||||||
|
if (!isAdmin) {
|
||||||
|
throw new BadRequestException('Only admin role can access this route');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
35
src/guards/building.permission.guard.ts
Normal file
35
src/guards/building.permission.guard.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { SpacePermissionService } from '@app/common/helper/services/space.permission.service';
|
||||||
|
import {
|
||||||
|
BadRequestException,
|
||||||
|
CanActivate,
|
||||||
|
ExecutionContext,
|
||||||
|
Injectable,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class BuildingPermissionGuard implements CanActivate {
|
||||||
|
constructor(private readonly permissionService: SpacePermissionService) {}
|
||||||
|
|
||||||
|
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||||
|
const req = context.switchToHttp().getRequest();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { buildingUuid } = req.params;
|
||||||
|
const { user } = req;
|
||||||
|
|
||||||
|
if (!buildingUuid) {
|
||||||
|
throw new BadRequestException('buildingUuid is required');
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.permissionService.checkUserPermission(
|
||||||
|
buildingUuid,
|
||||||
|
user.uuid,
|
||||||
|
'building',
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
src/guards/community.permission.guard.ts
Normal file
35
src/guards/community.permission.guard.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { SpacePermissionService } from '@app/common/helper/services/space.permission.service';
|
||||||
|
import {
|
||||||
|
BadRequestException,
|
||||||
|
CanActivate,
|
||||||
|
ExecutionContext,
|
||||||
|
Injectable,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CommunityPermissionGuard implements CanActivate {
|
||||||
|
constructor(private readonly permissionService: SpacePermissionService) {}
|
||||||
|
|
||||||
|
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||||
|
const req = context.switchToHttp().getRequest();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { communityUuid } = req.params;
|
||||||
|
const { user } = req;
|
||||||
|
|
||||||
|
if (!communityUuid) {
|
||||||
|
throw new BadRequestException('communityUuid is required');
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.permissionService.checkUserPermission(
|
||||||
|
communityUuid,
|
||||||
|
user.uuid,
|
||||||
|
'community',
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,97 +0,0 @@
|
|||||||
import { PermissionType } from '@app/common/constants/permission-type.enum';
|
|
||||||
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
|
||||||
import { DeviceUserTypeRepository } from '@app/common/modules/device/repositories';
|
|
||||||
import { PermissionTypeRepository } from '@app/common/modules/permission/repositories';
|
|
||||||
import {
|
|
||||||
Injectable,
|
|
||||||
CanActivate,
|
|
||||||
HttpStatus,
|
|
||||||
ExecutionContext,
|
|
||||||
BadRequestException,
|
|
||||||
applyDecorators,
|
|
||||||
SetMetadata,
|
|
||||||
UseGuards,
|
|
||||||
} from '@nestjs/common';
|
|
||||||
import { Reflector } from '@nestjs/core';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class DevicePermissionGuard implements CanActivate {
|
|
||||||
constructor(
|
|
||||||
private reflector: Reflector,
|
|
||||||
private readonly deviceUserTypeRepository: DeviceUserTypeRepository,
|
|
||||||
private readonly permissionTypeRepository: PermissionTypeRepository,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
|
||||||
const req = context.switchToHttp().getRequest();
|
|
||||||
try {
|
|
||||||
const { deviceId } = req.headers;
|
|
||||||
const userId = req.user.uuid;
|
|
||||||
|
|
||||||
const requirePermission =
|
|
||||||
this.reflector.getAllAndOverride<PermissionType>('permission', [
|
|
||||||
context.getHandler(),
|
|
||||||
context.getClass(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (!requirePermission) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
await this.checkDevicePermission(deviceId, userId, requirePermission);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (error) {
|
|
||||||
this.handleGuardError(error, context);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async checkDevicePermission(
|
|
||||||
deviceId: string,
|
|
||||||
userId: string,
|
|
||||||
requirePermission,
|
|
||||||
) {
|
|
||||||
const [userPermissionDetails, permissionDetails] = await Promise.all([
|
|
||||||
this.deviceUserTypeRepository.findOne({
|
|
||||||
where: { deviceUuid: deviceId, userUuid: userId },
|
|
||||||
}),
|
|
||||||
this.permissionTypeRepository.findOne({
|
|
||||||
where: {
|
|
||||||
type: requirePermission,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
if (!userPermissionDetails) {
|
|
||||||
throw new BadRequestException('User Permission Details Not Found');
|
|
||||||
}
|
|
||||||
if (userPermissionDetails.permissionTypeUuid !== permissionDetails.uuid) {
|
|
||||||
throw new BadRequestException(
|
|
||||||
`User Does not have a ${requirePermission}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private handleGuardError(error: Error, context: ExecutionContext) {
|
|
||||||
const response = context.switchToHttp().getResponse();
|
|
||||||
console.error(error);
|
|
||||||
|
|
||||||
if (error instanceof BadRequestException) {
|
|
||||||
response
|
|
||||||
.status(HttpStatus.BAD_REQUEST)
|
|
||||||
.json({ statusCode: HttpStatus.BAD_REQUEST, message: error.message });
|
|
||||||
} else {
|
|
||||||
response.status(HttpStatus.NOT_FOUND).json({
|
|
||||||
statusCode: HttpStatus.NOT_FOUND,
|
|
||||||
message: 'User Permission not found',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function AuthGuardWithRoles(permission?: string) {
|
|
||||||
return applyDecorators(
|
|
||||||
SetMetadata('permission', permission),
|
|
||||||
UseGuards(JwtAuthGuard),
|
|
||||||
UseGuards(DevicePermissionGuard),
|
|
||||||
);
|
|
||||||
}
|
|
35
src/guards/floor.permission.guard.ts
Normal file
35
src/guards/floor.permission.guard.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { SpacePermissionService } from '@app/common/helper/services/space.permission.service';
|
||||||
|
import {
|
||||||
|
BadRequestException,
|
||||||
|
CanActivate,
|
||||||
|
ExecutionContext,
|
||||||
|
Injectable,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class FloorPermissionGuard implements CanActivate {
|
||||||
|
constructor(private readonly permissionService: SpacePermissionService) {}
|
||||||
|
|
||||||
|
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||||
|
const req = context.switchToHttp().getRequest();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { floorUuid } = req.params;
|
||||||
|
const { user } = req;
|
||||||
|
|
||||||
|
if (!floorUuid) {
|
||||||
|
throw new BadRequestException('floorUuid is required');
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.permissionService.checkUserPermission(
|
||||||
|
floorUuid,
|
||||||
|
user.uuid,
|
||||||
|
'floor',
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
src/guards/room.permission.guard.ts
Normal file
35
src/guards/room.permission.guard.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { SpacePermissionService } from '@app/common/helper/services/space.permission.service';
|
||||||
|
import {
|
||||||
|
BadRequestException,
|
||||||
|
CanActivate,
|
||||||
|
ExecutionContext,
|
||||||
|
Injectable,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class RoomPermissionGuard implements CanActivate {
|
||||||
|
constructor(private readonly permissionService: SpacePermissionService) {}
|
||||||
|
|
||||||
|
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||||
|
const req = context.switchToHttp().getRequest();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { roomUuid } = req.params;
|
||||||
|
const { user } = req;
|
||||||
|
|
||||||
|
if (!roomUuid) {
|
||||||
|
throw new BadRequestException('roomUuid is required');
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.permissionService.checkUserPermission(
|
||||||
|
roomUuid,
|
||||||
|
user.uuid,
|
||||||
|
'room',
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
src/guards/super.admin.role.guard.ts
Normal file
21
src/guards/super.admin.role.guard.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { RoleType } from '@app/common/constants/role.type.enum';
|
||||||
|
import { BadRequestException, UnauthorizedException } from '@nestjs/common';
|
||||||
|
import { AuthGuard } from '@nestjs/passport';
|
||||||
|
|
||||||
|
export class SuperAdminRoleGuard extends AuthGuard('jwt') {
|
||||||
|
handleRequest(err, user) {
|
||||||
|
if (err || !user) {
|
||||||
|
throw err || new UnauthorizedException();
|
||||||
|
} else {
|
||||||
|
const isSuperAdmin = user.roles.some(
|
||||||
|
(role) => role.type === RoleType.SUPER_ADMIN,
|
||||||
|
);
|
||||||
|
if (!isSuperAdmin) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
'Only super admin role can access this route',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
35
src/guards/unit.permission.guard.ts
Normal file
35
src/guards/unit.permission.guard.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { SpacePermissionService } from '@app/common/helper/services/space.permission.service';
|
||||||
|
import {
|
||||||
|
BadRequestException,
|
||||||
|
CanActivate,
|
||||||
|
ExecutionContext,
|
||||||
|
Injectable,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UnitPermissionGuard implements CanActivate {
|
||||||
|
constructor(private readonly permissionService: SpacePermissionService) {}
|
||||||
|
|
||||||
|
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||||
|
const req = context.switchToHttp().getRequest();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { unitUuid } = req.params;
|
||||||
|
const { user } = req;
|
||||||
|
|
||||||
|
if (!unitUuid) {
|
||||||
|
throw new BadRequestException('unitUuid is required');
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.permissionService.checkUserPermission(
|
||||||
|
unitUuid,
|
||||||
|
user.uuid,
|
||||||
|
'unit',
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
92
src/guards/user.device.controllable.permission.guard.ts
Normal file
92
src/guards/user.device.controllable.permission.guard.ts
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
import {
|
||||||
|
CanActivate,
|
||||||
|
ExecutionContext,
|
||||||
|
Injectable,
|
||||||
|
HttpStatus,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { BadRequestException, NotFoundException } from '@nestjs/common';
|
||||||
|
import { UserRepository } from '@app/common/modules/user/repositories';
|
||||||
|
import { DeviceRepository } from '@app/common/modules/device/repositories';
|
||||||
|
import { PermissionType } from '@app/common/constants/permission-type.enum';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CheckUserHaveControllablePermission implements CanActivate {
|
||||||
|
constructor(
|
||||||
|
private readonly deviceRepository: DeviceRepository,
|
||||||
|
private readonly userRepository: UserRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||||
|
const req = context.switchToHttp().getRequest();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const userUuid = req.user.uuid;
|
||||||
|
const { deviceUuid } = req.params;
|
||||||
|
|
||||||
|
const userIsFound = await this.checkUserIsFound(userUuid);
|
||||||
|
if (!userIsFound) {
|
||||||
|
throw new NotFoundException('User not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const userDevicePermission = await this.checkUserDevicePermission(
|
||||||
|
userUuid,
|
||||||
|
deviceUuid,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (userDevicePermission === PermissionType.CONTROLLABLE) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
throw new BadRequestException(
|
||||||
|
'You do not have controllable access to this device',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.handleGuardError(error, context);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async checkUserIsFound(userUuid: string) {
|
||||||
|
const userData = await this.userRepository.findOne({
|
||||||
|
where: { uuid: userUuid },
|
||||||
|
});
|
||||||
|
return !!userData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async checkUserDevicePermission(
|
||||||
|
userUuid: string,
|
||||||
|
deviceUuid: string,
|
||||||
|
): Promise<string> {
|
||||||
|
const device = await this.deviceRepository.findOne({
|
||||||
|
where: { uuid: deviceUuid, permission: { userUuid: userUuid } },
|
||||||
|
relations: ['permission', 'permission.permissionType'],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!device) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
'You do not have controllable access to this device',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return device.permission[0].permissionType.type; // Assuming permissionType is a string
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleGuardError(error: Error, context: ExecutionContext) {
|
||||||
|
const response = context.switchToHttp().getResponse();
|
||||||
|
if (error instanceof NotFoundException) {
|
||||||
|
response
|
||||||
|
.status(HttpStatus.NOT_FOUND)
|
||||||
|
.json({ statusCode: HttpStatus.NOT_FOUND, message: error.message });
|
||||||
|
} else if (error instanceof BadRequestException) {
|
||||||
|
response.status(HttpStatus.BAD_REQUEST).json({
|
||||||
|
statusCode: HttpStatus.BAD_REQUEST,
|
||||||
|
message: error.message,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
response.status(HttpStatus.INTERNAL_SERVER_ERROR).json({
|
||||||
|
statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
message: error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
91
src/guards/user.device.permission.guard.ts
Normal file
91
src/guards/user.device.permission.guard.ts
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
import {
|
||||||
|
CanActivate,
|
||||||
|
ExecutionContext,
|
||||||
|
Injectable,
|
||||||
|
HttpStatus,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { BadRequestException, NotFoundException } from '@nestjs/common';
|
||||||
|
import { UserRepository } from '@app/common/modules/user/repositories';
|
||||||
|
import { DeviceRepository } from '@app/common/modules/device/repositories';
|
||||||
|
import { PermissionType } from '@app/common/constants/permission-type.enum';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CheckUserHavePermission implements CanActivate {
|
||||||
|
constructor(
|
||||||
|
private readonly deviceRepository: DeviceRepository,
|
||||||
|
private readonly userRepository: UserRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||||
|
const req = context.switchToHttp().getRequest();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const userUuid = req.user.uuid;
|
||||||
|
const { deviceUuid } = req.params;
|
||||||
|
|
||||||
|
const userIsFound = await this.checkUserIsFound(userUuid);
|
||||||
|
if (!userIsFound) {
|
||||||
|
throw new NotFoundException('User not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const userDevicePermission = await this.checkUserDevicePermission(
|
||||||
|
userUuid,
|
||||||
|
deviceUuid,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
userDevicePermission === PermissionType.READ ||
|
||||||
|
userDevicePermission === PermissionType.CONTROLLABLE
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
throw new BadRequestException('You do not have access to this device');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.handleGuardError(error, context);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async checkUserIsFound(userUuid: string) {
|
||||||
|
const userData = await this.userRepository.findOne({
|
||||||
|
where: { uuid: userUuid },
|
||||||
|
});
|
||||||
|
return !!userData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async checkUserDevicePermission(
|
||||||
|
userUuid: string,
|
||||||
|
deviceUuid: string,
|
||||||
|
): Promise<string> {
|
||||||
|
const device = await this.deviceRepository.findOne({
|
||||||
|
where: { uuid: deviceUuid, permission: { userUuid: userUuid } },
|
||||||
|
relations: ['permission', 'permission.permissionType'],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!device) {
|
||||||
|
throw new BadRequestException('You do not have access to this device');
|
||||||
|
}
|
||||||
|
|
||||||
|
return device.permission[0].permissionType.type; // Assuming permissionType is a string
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleGuardError(error: Error, context: ExecutionContext) {
|
||||||
|
const response = context.switchToHttp().getResponse();
|
||||||
|
if (error instanceof NotFoundException) {
|
||||||
|
response
|
||||||
|
.status(HttpStatus.NOT_FOUND)
|
||||||
|
.json({ statusCode: HttpStatus.NOT_FOUND, message: error.message });
|
||||||
|
} else if (error instanceof BadRequestException) {
|
||||||
|
response.status(HttpStatus.BAD_REQUEST).json({
|
||||||
|
statusCode: HttpStatus.BAD_REQUEST,
|
||||||
|
message: error.message,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
response.status(HttpStatus.INTERNAL_SERVER_ERROR).json({
|
||||||
|
statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
message: error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ import rateLimit from 'express-rate-limit';
|
|||||||
import helmet from 'helmet';
|
import helmet from 'helmet';
|
||||||
import { setupSwaggerAuthentication } from '../libs/common/src/util/user-auth.swagger.utils';
|
import { setupSwaggerAuthentication } from '../libs/common/src/util/user-auth.swagger.utils';
|
||||||
import { ValidationPipe } from '@nestjs/common';
|
import { ValidationPipe } from '@nestjs/common';
|
||||||
|
import { SeederService } from '@app/common/seed/services/seeder.service';
|
||||||
|
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
const app = await NestFactory.create(AuthModule);
|
const app = await NestFactory.create(AuthModule);
|
||||||
@ -34,6 +35,13 @@ async function bootstrap() {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const seederService = app.get(SeederService);
|
||||||
|
try {
|
||||||
|
await seederService.seed();
|
||||||
|
console.log('Seeding complete!');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Seeding failed!', error);
|
||||||
|
}
|
||||||
await app.listen(process.env.PORT || 4000);
|
await app.listen(process.env.PORT || 4000);
|
||||||
}
|
}
|
||||||
console.log('Starting auth at port ...', process.env.PORT || 4000);
|
console.log('Starting auth at port ...', process.env.PORT || 4000);
|
||||||
|
1
src/role/controllers/index.ts
Normal file
1
src/role/controllers/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './role.controller';
|
54
src/role/controllers/role.controller.ts
Normal file
54
src/role/controllers/role.controller.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import {
|
||||||
|
Body,
|
||||||
|
Controller,
|
||||||
|
Get,
|
||||||
|
HttpException,
|
||||||
|
HttpStatus,
|
||||||
|
Post,
|
||||||
|
UseGuards,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
|
||||||
|
import { RoleService } from '../services/role.service';
|
||||||
|
import { AddUserRoleDto } from '../dtos';
|
||||||
|
import { SuperAdminRoleGuard } from 'src/guards/super.admin.role.guard';
|
||||||
|
|
||||||
|
@ApiTags('Role Module')
|
||||||
|
@Controller({
|
||||||
|
version: '1',
|
||||||
|
path: 'role',
|
||||||
|
})
|
||||||
|
export class RoleController {
|
||||||
|
constructor(private readonly roleService: RoleService) {}
|
||||||
|
@ApiBearerAuth()
|
||||||
|
@UseGuards(SuperAdminRoleGuard)
|
||||||
|
@Get('types')
|
||||||
|
async fetchRoleTypes() {
|
||||||
|
try {
|
||||||
|
const roleTypes = await this.roleService.fetchRoleTypes();
|
||||||
|
return {
|
||||||
|
statusCode: HttpStatus.OK,
|
||||||
|
message: 'Role Types fetched Successfully',
|
||||||
|
data: roleTypes,
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ApiBearerAuth()
|
||||||
|
@UseGuards(SuperAdminRoleGuard)
|
||||||
|
@Post()
|
||||||
|
async addUserRoleType(@Body() addUserRoleDto: AddUserRoleDto) {
|
||||||
|
try {
|
||||||
|
await this.roleService.addUserRoleType(addUserRoleDto);
|
||||||
|
return {
|
||||||
|
statusCode: HttpStatus.OK,
|
||||||
|
message: 'User Role Added Successfully',
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException(
|
||||||
|
error.message || 'Internal server error',
|
||||||
|
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
src/role/dtos/index.ts
Normal file
1
src/role/dtos/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './role.add.dto';
|
24
src/role/dtos/role.add.dto.ts
Normal file
24
src/role/dtos/role.add.dto.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { RoleType } from '@app/common/constants/role.type.enum';
|
||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import { IsEnum, IsIn, IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class AddUserRoleDto {
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'userUuid',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public userUuid: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'Role type (ADMIN)',
|
||||||
|
enum: [RoleType.ADMIN],
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
@IsEnum(RoleType)
|
||||||
|
@IsIn([RoleType.ADMIN], {
|
||||||
|
message: 'roleType must be one of the following values: ADMIN',
|
||||||
|
})
|
||||||
|
roleType: RoleType;
|
||||||
|
}
|
25
src/role/role.module.ts
Normal file
25
src/role/role.module.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { DeviceRepositoryModule } from '@app/common/modules/device';
|
||||||
|
import { DeviceRepository } from '@app/common/modules/device/repositories';
|
||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { ConfigModule } from '@nestjs/config';
|
||||||
|
import { RoleService } from './services/role.service';
|
||||||
|
import { RoleController } from './controllers/role.controller';
|
||||||
|
import { DeviceUserPermissionRepository } from '@app/common/modules/device-user-permission/repositories';
|
||||||
|
import { PermissionTypeRepository } from '@app/common/modules/permission/repositories';
|
||||||
|
import { RoleTypeRepository } from '@app/common/modules/role-type/repositories';
|
||||||
|
import { UserRoleRepository } from '@app/common/modules/user-role/repositories';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [ConfigModule, DeviceRepositoryModule],
|
||||||
|
controllers: [RoleController],
|
||||||
|
providers: [
|
||||||
|
DeviceUserPermissionRepository,
|
||||||
|
PermissionTypeRepository,
|
||||||
|
DeviceRepository,
|
||||||
|
RoleService,
|
||||||
|
RoleTypeRepository,
|
||||||
|
UserRoleRepository,
|
||||||
|
],
|
||||||
|
exports: [RoleService],
|
||||||
|
})
|
||||||
|
export class RoleModule {}
|
1
src/role/services/index.ts
Normal file
1
src/role/services/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './role.service';
|
54
src/role/services/role.service.ts
Normal file
54
src/role/services/role.service.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { RoleTypeRepository } from './../../../libs/common/src/modules/role-type/repositories/role.type.repository';
|
||||||
|
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||||
|
import { AddUserRoleDto } from '../dtos/role.add.dto';
|
||||||
|
import { UserRoleRepository } from '@app/common/modules/user-role/repositories';
|
||||||
|
import { QueryFailedError } from 'typeorm';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class RoleService {
|
||||||
|
constructor(
|
||||||
|
private readonly roleTypeRepository: RoleTypeRepository,
|
||||||
|
private readonly userRoleRepository: UserRoleRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async addUserRoleType(addUserRoleDto: AddUserRoleDto) {
|
||||||
|
try {
|
||||||
|
const roleType = await this.fetchRoleByType(addUserRoleDto.roleType);
|
||||||
|
|
||||||
|
if (roleType.uuid) {
|
||||||
|
return await this.userRoleRepository.save({
|
||||||
|
user: { uuid: addUserRoleDto.userUuid },
|
||||||
|
roleType: { uuid: roleType.uuid },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (
|
||||||
|
error instanceof QueryFailedError &&
|
||||||
|
error.driverError.code === '23505'
|
||||||
|
) {
|
||||||
|
// Postgres unique constraint violation error code
|
||||||
|
throw new HttpException(
|
||||||
|
'This role already exists for this user',
|
||||||
|
HttpStatus.CONFLICT,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
throw new HttpException(
|
||||||
|
error.message || 'Internal Server Error',
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchRoleTypes() {
|
||||||
|
const roleTypes = await this.roleTypeRepository.find();
|
||||||
|
|
||||||
|
return roleTypes;
|
||||||
|
}
|
||||||
|
private async fetchRoleByType(roleType: string) {
|
||||||
|
return await this.roleTypeRepository.findOne({
|
||||||
|
where: {
|
||||||
|
type: roleType,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -11,11 +11,13 @@ import {
|
|||||||
UseGuards,
|
UseGuards,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
||||||
import { JwtAuthGuard } from '../../../libs/common/src/guards/jwt.auth.guard';
|
|
||||||
import { AddRoomDto, AddUserRoomDto } from '../dtos/add.room.dto';
|
import { AddRoomDto, AddUserRoomDto } from '../dtos/add.room.dto';
|
||||||
import { UpdateRoomNameDto } from '../dtos/update.room.dto';
|
import { UpdateRoomNameDto } from '../dtos/update.room.dto';
|
||||||
import { CheckUnitTypeGuard } from 'src/guards/unit.type.guard';
|
import { CheckUnitTypeGuard } from 'src/guards/unit.type.guard';
|
||||||
import { CheckUserRoomGuard } from 'src/guards/user.room.guard';
|
import { CheckUserRoomGuard } from 'src/guards/user.room.guard';
|
||||||
|
import { AdminRoleGuard } from 'src/guards/admin.role.guard';
|
||||||
|
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
||||||
|
import { RoomPermissionGuard } from 'src/guards/room.permission.guard';
|
||||||
|
|
||||||
@ApiTags('Room Module')
|
@ApiTags('Room Module')
|
||||||
@Controller({
|
@Controller({
|
||||||
@ -26,12 +28,17 @@ export class RoomController {
|
|||||||
constructor(private readonly roomService: RoomService) {}
|
constructor(private readonly roomService: RoomService) {}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard, CheckUnitTypeGuard)
|
@UseGuards(AdminRoleGuard, CheckUnitTypeGuard)
|
||||||
@Post()
|
@Post()
|
||||||
async addRoom(@Body() addRoomDto: AddRoomDto) {
|
async addRoom(@Body() addRoomDto: AddRoomDto) {
|
||||||
try {
|
try {
|
||||||
const room = await this.roomService.addRoom(addRoomDto);
|
const room = await this.roomService.addRoom(addRoomDto);
|
||||||
return { message: 'Room added successfully', uuid: room.uuid };
|
return {
|
||||||
|
statusCode: HttpStatus.CREATED,
|
||||||
|
success: true,
|
||||||
|
message: 'Room added successfully',
|
||||||
|
data: room,
|
||||||
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
error.message || 'Internal server error',
|
error.message || 'Internal server error',
|
||||||
@ -41,7 +48,7 @@ export class RoomController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, RoomPermissionGuard)
|
||||||
@Get(':roomUuid')
|
@Get(':roomUuid')
|
||||||
async getRoomByUuid(@Param('roomUuid') roomUuid: string) {
|
async getRoomByUuid(@Param('roomUuid') roomUuid: string) {
|
||||||
try {
|
try {
|
||||||
@ -56,7 +63,7 @@ export class RoomController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, RoomPermissionGuard)
|
||||||
@Get('parent/:roomUuid')
|
@Get('parent/:roomUuid')
|
||||||
async getRoomParentByUuid(@Param('roomUuid') roomUuid: string) {
|
async getRoomParentByUuid(@Param('roomUuid') roomUuid: string) {
|
||||||
try {
|
try {
|
||||||
@ -70,12 +77,16 @@ export class RoomController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard, CheckUserRoomGuard)
|
@UseGuards(AdminRoleGuard, CheckUserRoomGuard)
|
||||||
@Post('user')
|
@Post('user')
|
||||||
async addUserRoom(@Body() addUserRoomDto: AddUserRoomDto) {
|
async addUserRoom(@Body() addUserRoomDto: AddUserRoomDto) {
|
||||||
try {
|
try {
|
||||||
await this.roomService.addUserRoom(addUserRoomDto);
|
await this.roomService.addUserRoom(addUserRoomDto);
|
||||||
return { message: 'user room added successfully' };
|
return {
|
||||||
|
statusCode: HttpStatus.CREATED,
|
||||||
|
success: true,
|
||||||
|
message: 'user room added successfully',
|
||||||
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
error.message || 'Internal server error',
|
error.message || 'Internal server error',
|
||||||
@ -98,7 +109,7 @@ export class RoomController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, RoomPermissionGuard)
|
||||||
@Put('rename/:roomUuid')
|
@Put('rename/:roomUuid')
|
||||||
async renameRoomByUuid(
|
async renameRoomByUuid(
|
||||||
@Param('roomUuid') roomUuid: string,
|
@Param('roomUuid') roomUuid: string,
|
||||||
|
@ -12,12 +12,14 @@ import {
|
|||||||
UseGuards,
|
UseGuards,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
||||||
import { JwtAuthGuard } from '../../../libs/common/src/guards/jwt.auth.guard';
|
|
||||||
import { AddUnitDto, AddUserUnitDto } from '../dtos/add.unit.dto';
|
import { AddUnitDto, AddUserUnitDto } from '../dtos/add.unit.dto';
|
||||||
import { GetUnitChildDto } from '../dtos/get.unit.dto';
|
import { GetUnitChildDto } from '../dtos/get.unit.dto';
|
||||||
import { UpdateUnitNameDto } from '../dtos/update.unit.dto';
|
import { UpdateUnitNameDto } from '../dtos/update.unit.dto';
|
||||||
import { CheckFloorTypeGuard } from 'src/guards/floor.type.guard';
|
import { CheckFloorTypeGuard } from 'src/guards/floor.type.guard';
|
||||||
import { CheckUserUnitGuard } from 'src/guards/user.unit.guard';
|
import { CheckUserUnitGuard } from 'src/guards/user.unit.guard';
|
||||||
|
import { AdminRoleGuard } from 'src/guards/admin.role.guard';
|
||||||
|
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
||||||
|
import { UnitPermissionGuard } from 'src/guards/unit.permission.guard';
|
||||||
|
|
||||||
@ApiTags('Unit Module')
|
@ApiTags('Unit Module')
|
||||||
@Controller({
|
@Controller({
|
||||||
@ -28,12 +30,17 @@ export class UnitController {
|
|||||||
constructor(private readonly unitService: UnitService) {}
|
constructor(private readonly unitService: UnitService) {}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard, CheckFloorTypeGuard)
|
@UseGuards(AdminRoleGuard, CheckFloorTypeGuard)
|
||||||
@Post()
|
@Post()
|
||||||
async addUnit(@Body() addUnitDto: AddUnitDto) {
|
async addUnit(@Body() addUnitDto: AddUnitDto) {
|
||||||
try {
|
try {
|
||||||
const unit = await this.unitService.addUnit(addUnitDto);
|
const unit = await this.unitService.addUnit(addUnitDto);
|
||||||
return { message: 'Unit added successfully', uuid: unit.uuid };
|
return {
|
||||||
|
statusCode: HttpStatus.CREATED,
|
||||||
|
success: true,
|
||||||
|
message: 'Unit added successfully',
|
||||||
|
data: unit,
|
||||||
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
error.message || 'Internal server error',
|
error.message || 'Internal server error',
|
||||||
@ -43,7 +50,7 @@ export class UnitController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, UnitPermissionGuard)
|
||||||
@Get(':unitUuid')
|
@Get(':unitUuid')
|
||||||
async getUnitByUuid(@Param('unitUuid') unitUuid: string) {
|
async getUnitByUuid(@Param('unitUuid') unitUuid: string) {
|
||||||
try {
|
try {
|
||||||
@ -58,7 +65,7 @@ export class UnitController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, UnitPermissionGuard)
|
||||||
@Get('child/:unitUuid')
|
@Get('child/:unitUuid')
|
||||||
async getUnitChildByUuid(
|
async getUnitChildByUuid(
|
||||||
@Param('unitUuid') unitUuid: string,
|
@Param('unitUuid') unitUuid: string,
|
||||||
@ -75,7 +82,7 @@ export class UnitController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, UnitPermissionGuard)
|
||||||
@Get('parent/:unitUuid')
|
@Get('parent/:unitUuid')
|
||||||
async getUnitParentByUuid(@Param('unitUuid') unitUuid: string) {
|
async getUnitParentByUuid(@Param('unitUuid') unitUuid: string) {
|
||||||
try {
|
try {
|
||||||
@ -89,12 +96,16 @@ export class UnitController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard, CheckUserUnitGuard)
|
@UseGuards(AdminRoleGuard, CheckUserUnitGuard)
|
||||||
@Post('user')
|
@Post('user')
|
||||||
async addUserUnit(@Body() addUserUnitDto: AddUserUnitDto) {
|
async addUserUnit(@Body() addUserUnitDto: AddUserUnitDto) {
|
||||||
try {
|
try {
|
||||||
await this.unitService.addUserUnit(addUserUnitDto);
|
await this.unitService.addUserUnit(addUserUnitDto);
|
||||||
return { message: 'user unit added successfully' };
|
return {
|
||||||
|
statusCode: HttpStatus.CREATED,
|
||||||
|
success: true,
|
||||||
|
message: 'user unit added successfully',
|
||||||
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
error.message || 'Internal server error',
|
error.message || 'Internal server error',
|
||||||
@ -117,7 +128,7 @@ export class UnitController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard, UnitPermissionGuard)
|
||||||
@Put('rename/:unitUuid')
|
@Put('rename/:unitUuid')
|
||||||
async renameUnitByUuid(
|
async renameUnitByUuid(
|
||||||
@Param('unitUuid') unitUuid: string,
|
@Param('unitUuid') unitUuid: string,
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
export * from './user-device-permission.controller';
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
Body,
|
Body,
|
||||||
Controller,
|
Controller,
|
||||||
|
Delete,
|
||||||
Get,
|
Get,
|
||||||
|
HttpException,
|
||||||
HttpStatus,
|
HttpStatus,
|
||||||
Param,
|
Param,
|
||||||
Post,
|
Post,
|
||||||
@ -11,8 +13,8 @@ import {
|
|||||||
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
|
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
|
||||||
import { UserDevicePermissionService } from '../services/user-device-permission.service';
|
import { UserDevicePermissionService } from '../services/user-device-permission.service';
|
||||||
import { UserDevicePermissionAddDto } from '../dtos/user-device-permission.add.dto';
|
import { UserDevicePermissionAddDto } from '../dtos/user-device-permission.add.dto';
|
||||||
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
|
||||||
import { UserDevicePermissionEditDto } from '../dtos/user-device-permission.edit.dto';
|
import { UserDevicePermissionEditDto } from '../dtos/user-device-permission.edit.dto';
|
||||||
|
import { AdminRoleGuard } from 'src/guards/admin.role.guard';
|
||||||
|
|
||||||
@ApiTags('Device Permission Module')
|
@ApiTags('Device Permission Module')
|
||||||
@Controller({
|
@Controller({
|
||||||
@ -25,7 +27,7 @@ export class UserDevicePermissionController {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(AdminRoleGuard)
|
||||||
@Post('add')
|
@Post('add')
|
||||||
async addDevicePermission(
|
async addDevicePermission(
|
||||||
@Body() userDevicePermissionDto: UserDevicePermissionAddDto,
|
@Body() userDevicePermissionDto: UserDevicePermissionAddDto,
|
||||||
@ -40,40 +42,45 @@ export class UserDevicePermissionController {
|
|||||||
message: 'User Permission for Devices Added Successfully',
|
message: 'User Permission for Devices Added Successfully',
|
||||||
data: addDetails,
|
data: addDetails,
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (error) {
|
||||||
throw new Error(err);
|
throw new HttpException(
|
||||||
|
error.message || 'Internal server error',
|
||||||
|
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(AdminRoleGuard)
|
||||||
@Put('edit/:userId')
|
@Put('edit/:devicePermissionUuid')
|
||||||
async editDevicePermission(
|
async editDevicePermission(
|
||||||
@Param('userId') userId: string,
|
@Param('devicePermissionUuid') devicePermissionUuid: string,
|
||||||
@Body() userDevicePermissionEditDto: UserDevicePermissionEditDto,
|
@Body() userDevicePermissionEditDto: UserDevicePermissionEditDto,
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
await this.userDevicePermissionService.editUserPermission(
|
await this.userDevicePermissionService.editUserPermission(
|
||||||
userId,
|
devicePermissionUuid,
|
||||||
userDevicePermissionEditDto,
|
userDevicePermissionEditDto,
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
statusCode: HttpStatus.OK,
|
statusCode: HttpStatus.OK,
|
||||||
message: 'User Permission for Devices Updated Successfully',
|
message: 'User Permission for Devices Updated Successfully',
|
||||||
data: {},
|
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (error) {
|
||||||
throw new Error(err);
|
throw new HttpException(
|
||||||
|
error.message || 'Internal server error',
|
||||||
|
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(AdminRoleGuard)
|
||||||
@Get('list')
|
@Get(':deviceUuid/list')
|
||||||
async fetchDevicePermission() {
|
async fetchDevicePermission(@Param('deviceUuid') deviceUuid: string) {
|
||||||
try {
|
try {
|
||||||
const deviceDetails =
|
const deviceDetails =
|
||||||
await this.userDevicePermissionService.fetchuserPermission();
|
await this.userDevicePermissionService.fetchUserPermission(deviceUuid);
|
||||||
return {
|
return {
|
||||||
statusCode: HttpStatus.OK,
|
statusCode: HttpStatus.OK,
|
||||||
message: 'Device Details fetched Successfully',
|
message: 'Device Details fetched Successfully',
|
||||||
@ -83,4 +90,25 @@ export class UserDevicePermissionController {
|
|||||||
throw new Error(err);
|
throw new Error(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ApiBearerAuth()
|
||||||
|
@UseGuards(AdminRoleGuard)
|
||||||
|
@Delete(':devicePermissionUuid')
|
||||||
|
async deleteDevicePermission(
|
||||||
|
@Param('devicePermissionUuid') devicePermissionUuid: string,
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
await this.userDevicePermissionService.deleteDevicePermission(
|
||||||
|
devicePermissionUuid,
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
statusCode: HttpStatus.OK,
|
||||||
|
message: 'User Permission for Devices Deleted Successfully',
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException(
|
||||||
|
error.message || 'Internal server error',
|
||||||
|
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
export * from './user-device-permission.add.dto';
|
||||||
|
export * from './user-device-permission.edit.dto';
|
||||||
|
@ -1,28 +1,29 @@
|
|||||||
|
import { PermissionType } from '@app/common/constants/permission-type.enum';
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { IsNotEmpty, IsString } from 'class-validator';
|
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
export class UserDevicePermissionAddDto {
|
export class UserDevicePermissionAddDto {
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'user id',
|
description: 'user uuid',
|
||||||
required: true,
|
required: true,
|
||||||
})
|
})
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
userId: string;
|
userUuid: string;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'permission type id',
|
description: 'permission type',
|
||||||
|
enum: PermissionType,
|
||||||
required: true,
|
required: true,
|
||||||
})
|
})
|
||||||
@IsString()
|
@IsEnum(PermissionType)
|
||||||
@IsNotEmpty()
|
permissionType: PermissionType;
|
||||||
permissionTypeId: string;
|
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'device id',
|
description: 'device uuid',
|
||||||
required: true,
|
required: true,
|
||||||
})
|
})
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
deviceId: string;
|
deviceUuid: string;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
import { OmitType } from '@nestjs/swagger';
|
import { PermissionType } from '@app/common/constants/permission-type.enum';
|
||||||
import { UserDevicePermissionAddDto } from './user-device-permission.add.dto';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import { IsEnum } from 'class-validator';
|
||||||
|
|
||||||
export class UserDevicePermissionEditDto extends OmitType(
|
export class UserDevicePermissionEditDto {
|
||||||
UserDevicePermissionAddDto,
|
@ApiProperty({
|
||||||
['userId'],
|
description: 'permission type',
|
||||||
) {}
|
enum: PermissionType,
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
@IsEnum(PermissionType)
|
||||||
|
permissionType: PermissionType;
|
||||||
|
}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
export * from './user-device-permission.service';
|
||||||
|
@ -1,36 +1,107 @@
|
|||||||
import { DeviceUserTypeRepository } from '@app/common/modules/device/repositories';
|
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||||
import { Injectable } from '@nestjs/common';
|
|
||||||
import { UserDevicePermissionAddDto } from '../dtos/user-device-permission.add.dto';
|
import { UserDevicePermissionAddDto } from '../dtos/user-device-permission.add.dto';
|
||||||
import { UserDevicePermissionEditDto } from '../dtos/user-device-permission.edit.dto';
|
import { UserDevicePermissionEditDto } from '../dtos/user-device-permission.edit.dto';
|
||||||
|
import { DeviceUserPermissionRepository } from '@app/common/modules/device-user-permission/repositories';
|
||||||
|
import { PermissionTypeRepository } from '@app/common/modules/permission/repositories';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UserDevicePermissionService {
|
export class UserDevicePermissionService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly deviceUserTypeRepository: DeviceUserTypeRepository,
|
private readonly deviceUserPermissionRepository: DeviceUserPermissionRepository,
|
||||||
|
private readonly permissionTypeRepository: PermissionTypeRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async addUserPermission(userDevicePermissionDto: UserDevicePermissionAddDto) {
|
async addUserPermission(userDevicePermissionDto: UserDevicePermissionAddDto) {
|
||||||
return await this.deviceUserTypeRepository.save({
|
try {
|
||||||
userUuid: userDevicePermissionDto.userId,
|
const permissionType = await this.getPermissionType(
|
||||||
deviceUuid: userDevicePermissionDto.deviceId,
|
userDevicePermissionDto.permissionType,
|
||||||
permissionTypeUuid: userDevicePermissionDto.permissionTypeId,
|
);
|
||||||
});
|
return await this.deviceUserPermissionRepository.save({
|
||||||
|
userUuid: userDevicePermissionDto.userUuid,
|
||||||
|
deviceUuid: userDevicePermissionDto.deviceUuid,
|
||||||
|
permissionType: {
|
||||||
|
uuid: permissionType.uuid,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if (error.code === '23505') {
|
||||||
|
throw new HttpException(
|
||||||
|
'This User already belongs to this device',
|
||||||
|
HttpStatus.BAD_REQUEST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
throw new HttpException(
|
||||||
|
error.message || 'Internal Server Error',
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async editUserPermission(
|
async editUserPermission(
|
||||||
userId: string,
|
devicePermissionUuid: string,
|
||||||
userDevicePermissionEditDto: UserDevicePermissionEditDto,
|
userDevicePermissionEditDto: UserDevicePermissionEditDto,
|
||||||
) {
|
) {
|
||||||
return await this.deviceUserTypeRepository.update(
|
try {
|
||||||
{ userUuid: userId },
|
const permissionType = await this.getPermissionType(
|
||||||
{
|
userDevicePermissionEditDto.permissionType,
|
||||||
deviceUuid: userDevicePermissionEditDto.deviceId,
|
);
|
||||||
permissionTypeUuid: userDevicePermissionEditDto.permissionTypeId,
|
return await this.deviceUserPermissionRepository.update(
|
||||||
},
|
{ uuid: devicePermissionUuid },
|
||||||
);
|
{
|
||||||
|
permissionType: {
|
||||||
|
uuid: permissionType.uuid,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
if (error.code === '23505') {
|
||||||
|
throw new HttpException(
|
||||||
|
'This User already belongs to this device',
|
||||||
|
HttpStatus.BAD_REQUEST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
throw new HttpException(
|
||||||
|
error.message || 'Internal Server Error',
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchuserPermission() {
|
async fetchUserPermission(deviceUuid: string) {
|
||||||
return await this.deviceUserTypeRepository.find();
|
const devicePermissions = await this.deviceUserPermissionRepository.find({
|
||||||
|
where: {
|
||||||
|
deviceUuid: deviceUuid,
|
||||||
|
},
|
||||||
|
relations: ['permissionType', 'user'],
|
||||||
|
});
|
||||||
|
return devicePermissions.map((permission) => {
|
||||||
|
return {
|
||||||
|
uuid: permission.uuid,
|
||||||
|
deviceUuid: permission.deviceUuid,
|
||||||
|
firstName: permission.user.firstName,
|
||||||
|
lastName: permission.user.lastName,
|
||||||
|
email: permission.user.email,
|
||||||
|
permissionType: permission.permissionType.type,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private async getPermissionType(permissionType: string) {
|
||||||
|
return await this.permissionTypeRepository.findOne({
|
||||||
|
where: {
|
||||||
|
type: permissionType,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async deleteDevicePermission(devicePermissionUuid: string) {
|
||||||
|
try {
|
||||||
|
return await this.deviceUserPermissionRepository.delete({
|
||||||
|
uuid: devicePermissionUuid,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException(
|
||||||
|
error.message || 'Internal Server Error',
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
import { DeviceRepositoryModule } from '@app/common/modules/device';
|
import { DeviceRepositoryModule } from '@app/common/modules/device';
|
||||||
import {
|
import { DeviceRepository } from '@app/common/modules/device/repositories';
|
||||||
DeviceRepository,
|
|
||||||
DeviceUserTypeRepository,
|
|
||||||
} from '@app/common/modules/device/repositories';
|
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { ConfigModule } from '@nestjs/config';
|
import { ConfigModule } from '@nestjs/config';
|
||||||
import { UserDevicePermissionService } from './services/user-device-permission.service';
|
import { UserDevicePermissionService } from './services/user-device-permission.service';
|
||||||
import { UserDevicePermissionController } from './controllers/user-device-permission.controller';
|
import { UserDevicePermissionController } from './controllers/user-device-permission.controller';
|
||||||
|
import { DeviceUserPermissionRepository } from '@app/common/modules/device-user-permission/repositories';
|
||||||
|
import { PermissionTypeRepository } from '@app/common/modules/permission/repositories';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [ConfigModule, DeviceRepositoryModule],
|
imports: [ConfigModule, DeviceRepositoryModule],
|
||||||
controllers: [UserDevicePermissionController],
|
controllers: [UserDevicePermissionController],
|
||||||
providers: [
|
providers: [
|
||||||
DeviceUserTypeRepository,
|
DeviceUserPermissionRepository,
|
||||||
|
PermissionTypeRepository,
|
||||||
DeviceRepository,
|
DeviceRepository,
|
||||||
UserDevicePermissionService,
|
UserDevicePermissionService,
|
||||||
],
|
],
|
||||||
|
@ -2,7 +2,7 @@ import { Controller, Get, Query, UseGuards } from '@nestjs/common';
|
|||||||
import { UserService } from '../services/user.service';
|
import { UserService } from '../services/user.service';
|
||||||
import { UserListDto } from '../dtos/user.list.dto';
|
import { UserListDto } from '../dtos/user.list.dto';
|
||||||
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
||||||
import { JwtAuthGuard } from '../../../libs/common/src/guards/jwt.auth.guard';
|
import { AdminRoleGuard } from 'src/guards/admin.role.guard';
|
||||||
|
|
||||||
@ApiTags('User Module')
|
@ApiTags('User Module')
|
||||||
@Controller({
|
@Controller({
|
||||||
@ -13,7 +13,7 @@ export class UserController {
|
|||||||
constructor(private readonly userService: UserService) {}
|
constructor(private readonly userService: UserService) {}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(AdminRoleGuard)
|
||||||
@Get('list')
|
@Get('list')
|
||||||
async userList(@Query() userListDto: UserListDto) {
|
async userList(@Query() userListDto: UserListDto) {
|
||||||
try {
|
try {
|
||||||
|
Reference in New Issue
Block a user