mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-10 15:17:41 +00:00
Add permission and role management features
This commit is contained in:
43
libs/common/src/constants/permissions-mapping.ts
Normal file
43
libs/common/src/constants/permissions-mapping.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
export const PermissionMapping = {
|
||||||
|
DEVICE_MANAGEMENT: {
|
||||||
|
DEVICE: ['SINGLE_CONTROL', 'VIEW', 'DELETE', 'UPDATE', 'BATCH_CONTROL'],
|
||||||
|
FIRMWARE: ['CONTROL', 'VIEW'],
|
||||||
|
},
|
||||||
|
COMMUNITY_MANAGEMENT: {
|
||||||
|
COMMUNITY: ['VIEW', 'ADD', 'UPDATE', 'DELETE'],
|
||||||
|
},
|
||||||
|
SPACE_MANAGEMENT: {
|
||||||
|
SPACE: [
|
||||||
|
'VIEW',
|
||||||
|
'ADD',
|
||||||
|
'UPDATE',
|
||||||
|
'DELETE',
|
||||||
|
'MODULE_ADD',
|
||||||
|
'ASSIGN_USER_TO_SPACE',
|
||||||
|
'DELETE_USER_FROM_SPACE',
|
||||||
|
],
|
||||||
|
SUBSPACE: [
|
||||||
|
'VIEW',
|
||||||
|
'ADD',
|
||||||
|
'UPDATE',
|
||||||
|
'DELETE',
|
||||||
|
'ASSIGN_DEVICE_TO_SUBSPACE',
|
||||||
|
'DELETE_DEVICE_FROM_SUBSPACE',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
DEVICE_WIZARD: {
|
||||||
|
DEVICE_WIZARD: ['VIEW_DEVICE_WIZARD'],
|
||||||
|
SPACE_DEVICE: ['VIEW_DEVICE_IN_SPACE', 'ASSIGN_DEVICE_TO_SPACE'],
|
||||||
|
SUBSPACE_DEVICE: ['VIEW_DEVICE_IN_SUBSPACE', 'UPDATE_DEVICE_IN_SUBSPACE'],
|
||||||
|
},
|
||||||
|
AUTOMATION_MANAGEMENT: {
|
||||||
|
AUTOMATION: ['VIEW', 'ADD', 'UPDATE', 'DELETE', 'CONTROL'],
|
||||||
|
SCENES: ['VIEW', 'ADD', 'UPDATE', 'DELETE', 'CONTROL'],
|
||||||
|
},
|
||||||
|
VISITOR_PASSWORD_MANAGEMENT: {
|
||||||
|
VISITOR_PASSWORD: ['VIEW', 'ADD', 'UPDATE', 'DELETE'],
|
||||||
|
},
|
||||||
|
USER_MANAGEMENT: {
|
||||||
|
USER: ['ADD'],
|
||||||
|
},
|
||||||
|
};
|
130
libs/common/src/constants/role-permissions.ts
Normal file
130
libs/common/src/constants/role-permissions.ts
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
import { RoleType } from './role.type.enum';
|
||||||
|
|
||||||
|
export const RolePermissions = {
|
||||||
|
[RoleType.SUPER_ADMIN]: [
|
||||||
|
'DEVICE_SINGLE_CONTROL',
|
||||||
|
'DEVICE_VIEW',
|
||||||
|
'DEVICE_DELETE',
|
||||||
|
'DEVICE_UPDATE',
|
||||||
|
'DEVICE_BATCH_CONTROL',
|
||||||
|
'COMMUNITY_VIEW',
|
||||||
|
'COMMUNITY_ADD',
|
||||||
|
'COMMUNITY_UPDATE',
|
||||||
|
'COMMUNITY_DELETE',
|
||||||
|
'FIRMWARE_CONTROL',
|
||||||
|
'SPACE_VIEW',
|
||||||
|
'SPACE_ADD',
|
||||||
|
'SPACE_UPDATE',
|
||||||
|
'SPACE_DELETE',
|
||||||
|
'SPACE_MODULE_ADD',
|
||||||
|
'ASSIGN_USER_TO_SPACE',
|
||||||
|
'DELETE_USER_FROM_SPACE',
|
||||||
|
'SUBSPACE_VIEW',
|
||||||
|
'SUBSPACE_ADD',
|
||||||
|
'SUBSPACE_UPDATE',
|
||||||
|
'SUBSPACE_DELETE',
|
||||||
|
'ASSIGN_DEVICE_TO_SUBSPACE',
|
||||||
|
'DELETE_DEVICE_FROM_SUBSPACE',
|
||||||
|
'VIEW_DEVICE_WIZARD',
|
||||||
|
'VIEW_DEVICE_IN_SUBSPACE',
|
||||||
|
'VIEW_DEVICE_IN_SPACE',
|
||||||
|
'UPDATE_DEVICE_IN_SUBSPACE',
|
||||||
|
'ASSIGN_DEVICE_TO_SPACE',
|
||||||
|
'AUTOMATION_VIEW',
|
||||||
|
'AUTOMATION_ADD',
|
||||||
|
'AUTOMATION_UPDATE',
|
||||||
|
'AUTOMATION_DELETE',
|
||||||
|
'AUTOMATION_CONTROL',
|
||||||
|
'SCENES_VIEW',
|
||||||
|
'SCENES_ADD',
|
||||||
|
'SCENES_UPDATE',
|
||||||
|
'SCENES_DELETE',
|
||||||
|
'SCENES_CONTROL',
|
||||||
|
'VISITOR_PASSWORD_VIEW',
|
||||||
|
'VISITOR_PASSWORD_ADD',
|
||||||
|
'USER_ADD',
|
||||||
|
],
|
||||||
|
[RoleType.ADMIN]: [
|
||||||
|
'DEVICE_SINGLE_CONTROL',
|
||||||
|
'DEVICE_VIEW',
|
||||||
|
'DEVICE_DELETE',
|
||||||
|
'DEVICE_UPDATE',
|
||||||
|
'DEVICE_BATCH_CONTROL',
|
||||||
|
'COMMUNITY_VIEW',
|
||||||
|
'COMMUNITY_ADD',
|
||||||
|
'COMMUNITY_UPDATE',
|
||||||
|
'COMMUNITY_DELETE',
|
||||||
|
'FIRMWARE_CONTROL',
|
||||||
|
'SPACE_VIEW',
|
||||||
|
'SPACE_ADD',
|
||||||
|
'SPACE_UPDATE',
|
||||||
|
'SPACE_DELETE',
|
||||||
|
'SPACE_MODULE_ADD',
|
||||||
|
'ASSIGN_USER_TO_SPACE',
|
||||||
|
'DELETE_USER_FROM_SPACE',
|
||||||
|
'SUBSPACE_VIEW',
|
||||||
|
'SUBSPACE_ADD',
|
||||||
|
'SUBSPACE_UPDATE',
|
||||||
|
'SUBSPACE_DELETE',
|
||||||
|
'ASSIGN_DEVICE_TO_SUBSPACE',
|
||||||
|
'DELETE_DEVICE_FROM_SUBSPACE',
|
||||||
|
'VIEW_DEVICE_WIZARD',
|
||||||
|
'VIEW_DEVICE_IN_SUBSPACE',
|
||||||
|
'VIEW_DEVICE_IN_SPACE',
|
||||||
|
'UPDATE_DEVICE_IN_SUBSPACE',
|
||||||
|
'ASSIGN_DEVICE_TO_SPACE',
|
||||||
|
'AUTOMATION_VIEW',
|
||||||
|
'AUTOMATION_ADD',
|
||||||
|
'AUTOMATION_UPDATE',
|
||||||
|
'AUTOMATION_DELETE',
|
||||||
|
'AUTOMATION_CONTROL',
|
||||||
|
'SCENES_VIEW',
|
||||||
|
'SCENES_ADD',
|
||||||
|
'SCENES_UPDATE',
|
||||||
|
'SCENES_DELETE',
|
||||||
|
'SCENES_CONTROL',
|
||||||
|
'VISITOR_PASSWORD_VIEW',
|
||||||
|
'VISITOR_PASSWORD_ADD',
|
||||||
|
'USER_ADD',
|
||||||
|
],
|
||||||
|
[RoleType.SPACE_MEMBER]: [
|
||||||
|
'DEVICE_SINGLE_CONTROL',
|
||||||
|
'DEVICE_VIEW',
|
||||||
|
'SPACE_VIEW',
|
||||||
|
'SUBSPACE_VIEW',
|
||||||
|
'VIEW_DEVICE_WIZARD',
|
||||||
|
'VIEW_DEVICE_IN_SUBSPACE',
|
||||||
|
'VIEW_DEVICE_IN_SPACE',
|
||||||
|
'AUTOMATION_VIEW',
|
||||||
|
'AUTOMATION_CONTROL',
|
||||||
|
'SCENES_VIEW',
|
||||||
|
'SCENES_CONTROL',
|
||||||
|
'VISITOR_PASSWORD_VIEW',
|
||||||
|
],
|
||||||
|
[RoleType.SPACE_OWNER]: [
|
||||||
|
'DEVICE_SINGLE_CONTROL',
|
||||||
|
'DEVICE_VIEW',
|
||||||
|
'FIRMWARE_CONTROL',
|
||||||
|
'FIRMWARE_VIEW',
|
||||||
|
'SPACE_VIEW',
|
||||||
|
'SPACE_MEMBER_ADD',
|
||||||
|
'SUBSPACE_VIEW',
|
||||||
|
'SUBSPACE_ADD',
|
||||||
|
'SUBSPACE_UPDATE',
|
||||||
|
'SUBSPACE_DELETE',
|
||||||
|
'AUTOMATION_VIEW',
|
||||||
|
'AUTOMATION_ADD',
|
||||||
|
'AUTOMATION_UPDATE',
|
||||||
|
'AUTOMATION_DELETE',
|
||||||
|
'AUTOMATION_CONTROL',
|
||||||
|
'SCENES_VIEW',
|
||||||
|
'SCENES_ADD',
|
||||||
|
'SCENES_UPDATE',
|
||||||
|
'SCENES_DELETE',
|
||||||
|
'SCENES_CONTROL',
|
||||||
|
'VISITOR_PASSWORD_VIEW',
|
||||||
|
'VISITOR_PASSWORD_ADD',
|
||||||
|
'VISITOR_PASSWORD_UPDATE',
|
||||||
|
'VISITOR_PASSWORD_DELETE',
|
||||||
|
],
|
||||||
|
};
|
@ -15,7 +15,6 @@ import {
|
|||||||
} from '../modules/space/entities';
|
} from '../modules/space/entities';
|
||||||
import { UserSpaceEntity } from '../modules/user/entities';
|
import { UserSpaceEntity } from '../modules/user/entities';
|
||||||
import { DeviceUserPermissionEntity } from '../modules/device/entities';
|
import { DeviceUserPermissionEntity } from '../modules/device/entities';
|
||||||
import { UserRoleEntity } from '../modules/user/entities';
|
|
||||||
import { RoleTypeEntity } from '../modules/role-type/entities';
|
import { RoleTypeEntity } from '../modules/role-type/entities';
|
||||||
import { UserNotificationEntity } from '../modules/user/entities';
|
import { UserNotificationEntity } from '../modules/user/entities';
|
||||||
import { DeviceNotificationEntity } from '../modules/device/entities';
|
import { DeviceNotificationEntity } from '../modules/device/entities';
|
||||||
@ -34,6 +33,10 @@ import {
|
|||||||
SpaceProductModelEntity,
|
SpaceProductModelEntity,
|
||||||
SubspaceModelEntity,
|
SubspaceModelEntity,
|
||||||
} from '../modules/space-model/entities';
|
} from '../modules/space-model/entities';
|
||||||
|
import {
|
||||||
|
InviteUserEntity,
|
||||||
|
InviteUserSpaceEntity,
|
||||||
|
} from '../modules/Invite-user/entities';
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
TypeOrmModule.forRootAsync({
|
TypeOrmModule.forRootAsync({
|
||||||
@ -63,7 +66,6 @@ import {
|
|||||||
SpaceProductEntity,
|
SpaceProductEntity,
|
||||||
UserSpaceEntity,
|
UserSpaceEntity,
|
||||||
DeviceUserPermissionEntity,
|
DeviceUserPermissionEntity,
|
||||||
UserRoleEntity,
|
|
||||||
RoleTypeEntity,
|
RoleTypeEntity,
|
||||||
UserNotificationEntity,
|
UserNotificationEntity,
|
||||||
DeviceNotificationEntity,
|
DeviceNotificationEntity,
|
||||||
@ -78,6 +80,8 @@ import {
|
|||||||
SpaceProductModelEntity,
|
SpaceProductModelEntity,
|
||||||
SpaceProductItemModelEntity,
|
SpaceProductItemModelEntity,
|
||||||
SubspaceModelEntity,
|
SubspaceModelEntity,
|
||||||
|
InviteUserEntity,
|
||||||
|
InviteUserSpaceEntity,
|
||||||
],
|
],
|
||||||
namingStrategy: new SnakeNamingStrategy(),
|
namingStrategy: new SnakeNamingStrategy(),
|
||||||
synchronize: Boolean(JSON.parse(configService.get('DB_SYNC'))),
|
synchronize: Boolean(JSON.parse(configService.get('DB_SYNC'))),
|
||||||
|
@ -3,6 +3,7 @@ import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
|||||||
import { ProjectDto } from '../dtos';
|
import { ProjectDto } from '../dtos';
|
||||||
import { CommunityEntity } from '../../community/entities';
|
import { CommunityEntity } from '../../community/entities';
|
||||||
import { SpaceModelEntity } from '../../space-model';
|
import { SpaceModelEntity } from '../../space-model';
|
||||||
|
import { UserEntity } from '../../user/entities';
|
||||||
|
|
||||||
@Entity({ name: 'project' })
|
@Entity({ name: 'project' })
|
||||||
@Unique(['name'])
|
@Unique(['name'])
|
||||||
@ -28,6 +29,9 @@ export class ProjectEntity extends AbstractEntity<ProjectDto> {
|
|||||||
@OneToMany(() => CommunityEntity, (community) => community.project)
|
@OneToMany(() => CommunityEntity, (community) => community.project)
|
||||||
communities: CommunityEntity[];
|
communities: CommunityEntity[];
|
||||||
|
|
||||||
|
@OneToMany(() => UserEntity, (user) => user.project)
|
||||||
|
public users: UserEntity[];
|
||||||
|
|
||||||
constructor(partial: Partial<ProjectEntity>) {
|
constructor(partial: Partial<ProjectEntity>) {
|
||||||
super();
|
super();
|
||||||
Object.assign(this, partial);
|
Object.assign(this, partial);
|
||||||
|
@ -2,7 +2,8 @@ import { Column, Entity, OneToMany, Unique } from 'typeorm';
|
|||||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||||
import { RoleTypeDto } from '../dtos/role.type.dto';
|
import { RoleTypeDto } from '../dtos/role.type.dto';
|
||||||
import { RoleType } from '@app/common/constants/role.type.enum';
|
import { RoleType } from '@app/common/constants/role.type.enum';
|
||||||
import { UserRoleEntity } from '../../user/entities';
|
import { UserEntity } from '../../user/entities';
|
||||||
|
import { InviteUserEntity } from '../../Invite-user/entities';
|
||||||
|
|
||||||
@Entity({ name: 'role-type' })
|
@Entity({ name: 'role-type' })
|
||||||
@Unique(['type'])
|
@Unique(['type'])
|
||||||
@ -12,10 +13,14 @@ export class RoleTypeEntity extends AbstractEntity<RoleTypeDto> {
|
|||||||
enum: Object.values(RoleType),
|
enum: Object.values(RoleType),
|
||||||
})
|
})
|
||||||
type: string;
|
type: string;
|
||||||
@OneToMany(() => UserRoleEntity, (role) => role.roleType, {
|
@OneToMany(() => UserEntity, (inviteUser) => inviteUser.roleType, {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
roles: UserRoleEntity[];
|
users: UserEntity[];
|
||||||
|
@OneToMany(() => InviteUserEntity, (inviteUser) => inviteUser.roleType, {
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
invitedUsers: InviteUserEntity[];
|
||||||
constructor(partial: Partial<RoleTypeEntity>) {
|
constructor(partial: Partial<RoleTypeEntity>) {
|
||||||
super();
|
super();
|
||||||
Object.assign(this, partial);
|
Object.assign(this, partial);
|
||||||
|
@ -4,7 +4,6 @@ import {
|
|||||||
UserEntity,
|
UserEntity,
|
||||||
UserNotificationEntity,
|
UserNotificationEntity,
|
||||||
UserOtpEntity,
|
UserOtpEntity,
|
||||||
UserRoleEntity,
|
|
||||||
UserSpaceEntity,
|
UserSpaceEntity,
|
||||||
} from './entities';
|
} from './entities';
|
||||||
|
|
||||||
@ -17,7 +16,6 @@ import {
|
|||||||
UserEntity,
|
UserEntity,
|
||||||
UserNotificationEntity,
|
UserNotificationEntity,
|
||||||
UserOtpEntity,
|
UserOtpEntity,
|
||||||
UserRoleEntity,
|
|
||||||
UserSpaceEntity,
|
UserSpaceEntity,
|
||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
|
@ -7,7 +7,6 @@ import { GroupModule } from './group/group.module';
|
|||||||
import { DeviceModule } from './device/device.module';
|
import { DeviceModule } from './device/device.module';
|
||||||
import { UserDevicePermissionModule } from './user-device-permission/user-device-permission.module';
|
import { UserDevicePermissionModule } from './user-device-permission/user-device-permission.module';
|
||||||
import { CommunityModule } from './community/community.module';
|
import { CommunityModule } from './community/community.module';
|
||||||
import { RoleModule } from './role/role.module';
|
|
||||||
import { SeederModule } from '@app/common/seed/seeder.module';
|
import { SeederModule } from '@app/common/seed/seeder.module';
|
||||||
import { UserNotificationModule } from './user-notification/user-notification.module';
|
import { UserNotificationModule } from './user-notification/user-notification.module';
|
||||||
import { DeviceMessagesSubscriptionModule } from './device-messages/device-messages.module';
|
import { DeviceMessagesSubscriptionModule } from './device-messages/device-messages.module';
|
||||||
@ -24,6 +23,8 @@ import { SpaceModule } from './space/space.module';
|
|||||||
import { ProductModule } from './product';
|
import { ProductModule } from './product';
|
||||||
import { ProjectModule } from './project';
|
import { ProjectModule } from './project';
|
||||||
import { SpaceModelModule } from './space-model';
|
import { SpaceModelModule } from './space-model';
|
||||||
|
import { InviteUserModule } from './invite-user/invite-user.module';
|
||||||
|
import { PermissionModule } from './permission/permission.module';
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
ConfigModule.forRoot({
|
ConfigModule.forRoot({
|
||||||
@ -31,7 +32,7 @@ import { SpaceModelModule } from './space-model';
|
|||||||
}),
|
}),
|
||||||
AuthenticationModule,
|
AuthenticationModule,
|
||||||
UserModule,
|
UserModule,
|
||||||
RoleModule,
|
InviteUserModule,
|
||||||
CommunityModule,
|
CommunityModule,
|
||||||
|
|
||||||
SpaceModule,
|
SpaceModule,
|
||||||
@ -51,6 +52,7 @@ import { SpaceModelModule } from './space-model';
|
|||||||
ScheduleModule,
|
ScheduleModule,
|
||||||
ProductModule,
|
ProductModule,
|
||||||
ProjectModule,
|
ProjectModule,
|
||||||
|
PermissionModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
|
@ -6,10 +6,7 @@ import { UserAuthController } from './controllers';
|
|||||||
import { UserAuthService } from './services';
|
import { UserAuthService } from './services';
|
||||||
import { UserRepository } from '@app/common/modules/user/repositories';
|
import { UserRepository } from '@app/common/modules/user/repositories';
|
||||||
import { UserSessionRepository } from '@app/common/modules/session/repositories/session.repository';
|
import { UserSessionRepository } from '@app/common/modules/session/repositories/session.repository';
|
||||||
import {
|
import { UserOtpRepository } from '@app/common/modules/user/repositories';
|
||||||
UserRoleRepository,
|
|
||||||
UserOtpRepository,
|
|
||||||
} from '@app/common/modules/user/repositories';
|
|
||||||
import { RoleTypeRepository } from '@app/common/modules/role-type/repositories';
|
import { RoleTypeRepository } from '@app/common/modules/role-type/repositories';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
@ -20,7 +17,6 @@ import { RoleTypeRepository } from '@app/common/modules/role-type/repositories';
|
|||||||
UserRepository,
|
UserRepository,
|
||||||
UserSessionRepository,
|
UserSessionRepository,
|
||||||
UserOtpRepository,
|
UserOtpRepository,
|
||||||
UserRoleRepository,
|
|
||||||
RoleTypeRepository,
|
RoleTypeRepository,
|
||||||
],
|
],
|
||||||
exports: [UserAuthService],
|
exports: [UserAuthService],
|
||||||
|
@ -134,13 +134,12 @@ export class UserAuthService {
|
|||||||
isLoggedOut: false,
|
isLoggedOut: false,
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const res = await this.authService.login({
|
const res = await this.authService.login({
|
||||||
email: user.email,
|
email: user.email,
|
||||||
userId: user.uuid,
|
userId: user.uuid,
|
||||||
uuid: user.uuid,
|
uuid: user.uuid,
|
||||||
roles: user?.roles?.map((role) => {
|
role: user.roleType,
|
||||||
return { uuid: role.uuid, type: role.roleType.type };
|
|
||||||
}),
|
|
||||||
sessionId: session[1].uuid,
|
sessionId: session[1].uuid,
|
||||||
});
|
});
|
||||||
return res;
|
return res;
|
||||||
|
4
src/decorators/permissions.decorator.ts
Normal file
4
src/decorators/permissions.decorator.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { SetMetadata } from '@nestjs/common';
|
||||||
|
|
||||||
|
export const Permissions = (...permissions: string[]) =>
|
||||||
|
SetMetadata('permissions', permissions);
|
44
src/guards/permissions.guard.ts
Normal file
44
src/guards/permissions.guard.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { Injectable, ExecutionContext } from '@nestjs/common';
|
||||||
|
import { AuthGuard } from '@nestjs/passport';
|
||||||
|
import { Reflector } from '@nestjs/core';
|
||||||
|
import { RolePermissions } from '@app/common/constants/role-permissions';
|
||||||
|
import { RoleType } from '@app/common/constants/role.type.enum';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class PermissionsGuard extends AuthGuard('jwt') {
|
||||||
|
constructor(private reflector: Reflector) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||||
|
// First, run the AuthGuard logic to validate the JWT
|
||||||
|
const isAuthenticated = await super.canActivate(context);
|
||||||
|
if (!isAuthenticated) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authorization logic
|
||||||
|
const requiredPermissions = this.reflector.get<string[]>(
|
||||||
|
'permissions',
|
||||||
|
context.getHandler(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!requiredPermissions) {
|
||||||
|
return true; // Allow if no permissions are specified
|
||||||
|
}
|
||||||
|
|
||||||
|
const request = context.switchToHttp().getRequest();
|
||||||
|
const user = request.user; // User is now available after AuthGuard
|
||||||
|
console.log('user', user);
|
||||||
|
|
||||||
|
const userRole = user?.role.type as RoleType;
|
||||||
|
if (!userRole || !RolePermissions[userRole]) {
|
||||||
|
return false; // Deny if role or permissions are missing
|
||||||
|
}
|
||||||
|
|
||||||
|
const userPermissions = RolePermissions[userRole];
|
||||||
|
|
||||||
|
// Check if the user has the required permissions
|
||||||
|
return requiredPermissions.every((perm) => userPermissions.includes(perm));
|
||||||
|
}
|
||||||
|
}
|
1
src/invite-user/controllers/index.ts
Normal file
1
src/invite-user/controllers/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './invite-user.controller';
|
34
src/invite-user/controllers/invite-user.controller.ts
Normal file
34
src/invite-user/controllers/invite-user.controller.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { InviteUserService } from '../services/invite-user.service';
|
||||||
|
import { Body, Controller, Post, UseGuards } from '@nestjs/common';
|
||||||
|
import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger';
|
||||||
|
import { AddUserInvitationDto } from '../dtos/add.invite-user.dto';
|
||||||
|
import { ControllerRoute } from '@app/common/constants/controller-route';
|
||||||
|
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||||
|
import { PermissionsGuard } from 'src/guards/permissions.guard';
|
||||||
|
import { Permissions } from 'src/decorators/permissions.decorator';
|
||||||
|
|
||||||
|
@ApiTags('Invite User Module')
|
||||||
|
@Controller({
|
||||||
|
version: '1',
|
||||||
|
path: ControllerRoute.INVITE_USER.ROUTE,
|
||||||
|
})
|
||||||
|
export class InviteUserController {
|
||||||
|
constructor(private readonly inviteUserService: InviteUserService) {}
|
||||||
|
|
||||||
|
@ApiBearerAuth()
|
||||||
|
@UseGuards(PermissionsGuard)
|
||||||
|
@Permissions('USER_ADD')
|
||||||
|
@Post()
|
||||||
|
@ApiOperation({
|
||||||
|
summary: ControllerRoute.INVITE_USER.ACTIONS.CREATE_USER_INVITATION_SUMMARY,
|
||||||
|
description:
|
||||||
|
ControllerRoute.INVITE_USER.ACTIONS.CREATE_USER_INVITATION_DESCRIPTION,
|
||||||
|
})
|
||||||
|
async createUserInvitation(
|
||||||
|
@Body() addUserInvitationDto: AddUserInvitationDto,
|
||||||
|
): Promise<BaseResponseDto> {
|
||||||
|
return await this.inviteUserService.createUserInvitation(
|
||||||
|
addUserInvitationDto,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
75
src/invite-user/dtos/add.invite-user.dto.ts
Normal file
75
src/invite-user/dtos/add.invite-user.dto.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import {
|
||||||
|
ArrayMinSize,
|
||||||
|
IsArray,
|
||||||
|
IsNotEmpty,
|
||||||
|
IsOptional,
|
||||||
|
IsString,
|
||||||
|
} from 'class-validator';
|
||||||
|
|
||||||
|
export class AddUserInvitationDto {
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'The first name of the user',
|
||||||
|
example: 'John',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public firstName: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'The last name of the user',
|
||||||
|
example: 'Doe',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public lastName: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'The email of the user',
|
||||||
|
example: 'OqM9A@example.com',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public email: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'The job title of the user',
|
||||||
|
example: 'Software Engineer',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public jobTitle: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'The phone number of the user',
|
||||||
|
example: '+1234567890',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
public phoneNumber?: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'The role uuid of the user',
|
||||||
|
example: 'd290f1ee-6c54-4b01-90e6-d701748f0851',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public roleUuid: string;
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'The array of space UUIDs (at least one required)',
|
||||||
|
example: ['b5f3c9d2-58b7-4377-b3f7-60acb711d5d9'],
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
@IsArray()
|
||||||
|
@ArrayMinSize(1)
|
||||||
|
public spaceUuids: string[];
|
||||||
|
constructor(dto: Partial<AddUserInvitationDto>) {
|
||||||
|
Object.assign(this, dto);
|
||||||
|
}
|
||||||
|
}
|
1
src/invite-user/dtos/index.ts
Normal file
1
src/invite-user/dtos/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './add.invite-user.dto';
|
23
src/invite-user/invite-user.module.ts
Normal file
23
src/invite-user/invite-user.module.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { InviteUserService } from './services/invite-user.service';
|
||||||
|
import { InviteUserController } from './controllers/invite-user.controller';
|
||||||
|
import { ConfigModule } from '@nestjs/config';
|
||||||
|
import {
|
||||||
|
InviteUserRepository,
|
||||||
|
InviteUserSpaceRepository,
|
||||||
|
} from '@app/common/modules/Invite-user/repositories';
|
||||||
|
import { UserRepository } from '@app/common/modules/user/repositories';
|
||||||
|
import { InviteUserRepositoryModule } from '@app/common/modules/Invite-user/Invite-user.repository.module';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [ConfigModule, InviteUserRepositoryModule],
|
||||||
|
controllers: [InviteUserController],
|
||||||
|
providers: [
|
||||||
|
InviteUserService,
|
||||||
|
InviteUserRepository,
|
||||||
|
UserRepository,
|
||||||
|
InviteUserSpaceRepository,
|
||||||
|
],
|
||||||
|
exports: [InviteUserService],
|
||||||
|
})
|
||||||
|
export class InviteUserModule {}
|
1
src/invite-user/services/index.ts
Normal file
1
src/invite-user/services/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './invite-user.service';
|
1
src/permission/controllers/index.ts
Normal file
1
src/permission/controllers/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './permission.controller';
|
24
src/permission/controllers/permission.controller.ts
Normal file
24
src/permission/controllers/permission.controller.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { Controller, Get, Param } from '@nestjs/common';
|
||||||
|
import { ApiTags, ApiOperation } from '@nestjs/swagger';
|
||||||
|
import { ControllerRoute } from '@app/common/constants/controller-route';
|
||||||
|
import { EnableDisableStatusEnum } from '@app/common/constants/days.enum';
|
||||||
|
import { PermissionService } from '../services';
|
||||||
|
|
||||||
|
@ApiTags('Permission Module')
|
||||||
|
@Controller({
|
||||||
|
version: EnableDisableStatusEnum.ENABLED,
|
||||||
|
path: ControllerRoute.PERMISSION.ROUTE,
|
||||||
|
})
|
||||||
|
export class PermissionController {
|
||||||
|
constructor(private readonly permissionService: PermissionService) {}
|
||||||
|
|
||||||
|
@Get(':roleUuid')
|
||||||
|
@ApiOperation({
|
||||||
|
summary: ControllerRoute.PERMISSION.ACTIONS.GET_PERMISSION_BY_ROLE_SUMMARY,
|
||||||
|
description:
|
||||||
|
ControllerRoute.PERMISSION.ACTIONS.GET_PERMISSION_BY_ROLE_DESCRIPTION,
|
||||||
|
})
|
||||||
|
async getPermissionsByRole(@Param('roleUuid') roleUuid: string) {
|
||||||
|
return await this.permissionService.getPermissionsByRole(roleUuid);
|
||||||
|
}
|
||||||
|
}
|
14
src/permission/permission.module.ts
Normal file
14
src/permission/permission.module.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { ConfigModule } from '@nestjs/config';
|
||||||
|
import { CommonModule } from '@app/common';
|
||||||
|
import { PermissionController } from './controllers';
|
||||||
|
import { PermissionService } from './services';
|
||||||
|
import { RoleTypeRepository } from '@app/common/modules/role-type/repositories';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [ConfigModule, CommonModule],
|
||||||
|
controllers: [PermissionController],
|
||||||
|
providers: [PermissionService, RoleTypeRepository],
|
||||||
|
exports: [PermissionService],
|
||||||
|
})
|
||||||
|
export class PermissionModule {}
|
1
src/permission/services/index.ts
Normal file
1
src/permission/services/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './permission.service';
|
52
src/permission/services/permission.service.ts
Normal file
52
src/permission/services/permission.service.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { PermissionMapping } from '@app/common/constants/permissions-mapping';
|
||||||
|
import { RolePermissions } from '@app/common/constants/role-permissions';
|
||||||
|
import { RoleType } from '@app/common/constants/role.type.enum';
|
||||||
|
import { RoleTypeRepository } from '@app/common/modules/role-type/repositories';
|
||||||
|
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class PermissionService {
|
||||||
|
constructor(private readonly roleTypeRepository: RoleTypeRepository) {}
|
||||||
|
|
||||||
|
async getPermissionsByRole(roleUuid: string) {
|
||||||
|
try {
|
||||||
|
const role = await this.roleTypeRepository.findOne({
|
||||||
|
where: {
|
||||||
|
uuid: roleUuid,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!role) {
|
||||||
|
throw new HttpException('Role not found', HttpStatus.NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
const permissions = this.mapPermissions(role.type.toString() as RoleType);
|
||||||
|
return permissions;
|
||||||
|
} catch (err) {
|
||||||
|
throw new HttpException(
|
||||||
|
err.message || 'Internal Server Error',
|
||||||
|
err.status || HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mapPermissions(role: RoleType): any[] {
|
||||||
|
const rolePermissions = RolePermissions[role]; // Permissions for the role
|
||||||
|
|
||||||
|
const mappedPermissions = Object.entries(PermissionMapping).map(
|
||||||
|
([title, subOptions]) => ({
|
||||||
|
title,
|
||||||
|
subOptions: Object.entries(subOptions).map(
|
||||||
|
([subTitle, permissions]) => ({
|
||||||
|
title: subTitle,
|
||||||
|
subOptions: permissions.map((permission) => ({
|
||||||
|
title: permission,
|
||||||
|
isChecked: rolePermissions.includes(`${subTitle}_${permission}`), // Check if the role has the permission
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return mappedPermissions;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user