mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-16 10:46:17 +00:00
Add Invite User Module and Update User and Space Entities
This commit introduces a new module for handling user invitations, including DTOs, entities, and repositories. It also updates the User and Space entities to include relationships with the new Invite User entities.
This commit is contained in:
@ -721,4 +721,24 @@ export class ControllerRoute {
|
||||
'This endpoint deletes a user’s subscription for device messages.';
|
||||
};
|
||||
};
|
||||
static INVITE_USER = class {
|
||||
public static readonly ROUTE = 'invite-user';
|
||||
static ACTIONS = class {
|
||||
public static readonly CREATE_USER_INVITATION_SUMMARY =
|
||||
'Create user invitation';
|
||||
|
||||
public static readonly CREATE_USER_INVITATION_DESCRIPTION =
|
||||
'This endpoint creates an invitation for a user to assign to role and spaces.';
|
||||
};
|
||||
};
|
||||
static PERMISSION = class {
|
||||
public static readonly ROUTE = 'permission';
|
||||
static ACTIONS = class {
|
||||
public static readonly GET_PERMISSION_BY_ROLE_SUMMARY =
|
||||
'Get permissions by role';
|
||||
|
||||
public static readonly GET_PERMISSION_BY_ROLE_DESCRIPTION =
|
||||
'This endpoint retrieves the permissions associated with a specific role.';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
5
libs/common/src/constants/user-status.enum.ts
Normal file
5
libs/common/src/constants/user-status.enum.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export enum UserStatusEnum {
|
||||
ACTIVE = 'active',
|
||||
INVITED = 'invited',
|
||||
DISABLED = 'disabled',
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { InviteUserEntity, InviteUserSpaceEntity } from './entities';
|
||||
|
||||
@Module({
|
||||
providers: [],
|
||||
exports: [],
|
||||
controllers: [],
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([InviteUserEntity, InviteUserSpaceEntity]),
|
||||
],
|
||||
})
|
||||
export class InviteUserRepositoryModule {}
|
42
libs/common/src/modules/Invite-user/dtos/Invite-user.dto.ts
Normal file
42
libs/common/src/modules/Invite-user/dtos/Invite-user.dto.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { UserStatusEnum } from '@app/common/constants/user-status.enum';
|
||||
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||
|
||||
export class InviteUserDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public uuid: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public email: string;
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public jobTitle: string;
|
||||
@IsEnum(UserStatusEnum)
|
||||
@IsNotEmpty()
|
||||
public status: UserStatusEnum;
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public firstName: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public lastName: string;
|
||||
}
|
||||
export class InviteUserSpaceDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public uuid: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public inviteUserUuid: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public spaceUuid: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public invitationCode: string;
|
||||
}
|
1
libs/common/src/modules/Invite-user/dtos/index.ts
Normal file
1
libs/common/src/modules/Invite-user/dtos/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './Invite-user.dto';
|
@ -0,0 +1,112 @@
|
||||
import {
|
||||
Column,
|
||||
Entity,
|
||||
JoinColumn,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
OneToOne,
|
||||
Unique,
|
||||
} from 'typeorm';
|
||||
import { InviteUserDto, InviteUserSpaceDto } from '../dtos';
|
||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||
import { RoleTypeEntity } from '../../role-type/entities';
|
||||
import { UserStatusEnum } from '@app/common/constants/user-status.enum';
|
||||
import { UserEntity } from '../../user/entities';
|
||||
import { SpaceEntity } from '../../space/entities';
|
||||
|
||||
@Entity({ name: 'invite-user' })
|
||||
@Unique(['email', 'invitationCode'])
|
||||
export class InviteUserEntity extends AbstractEntity<InviteUserDto> {
|
||||
@Column({
|
||||
type: 'uuid',
|
||||
default: () => 'gen_random_uuid()',
|
||||
nullable: false,
|
||||
})
|
||||
public uuid: string;
|
||||
|
||||
@Column({
|
||||
nullable: false,
|
||||
unique: true,
|
||||
})
|
||||
email: string;
|
||||
|
||||
@Column({
|
||||
nullable: false,
|
||||
})
|
||||
jobTitle: string;
|
||||
|
||||
@Column({
|
||||
nullable: false,
|
||||
enum: Object.values(UserStatusEnum),
|
||||
})
|
||||
status: string;
|
||||
|
||||
@Column()
|
||||
public firstName: string;
|
||||
|
||||
@Column({
|
||||
nullable: false,
|
||||
})
|
||||
public lastName: string;
|
||||
@Column({
|
||||
nullable: false,
|
||||
})
|
||||
public phoneNumber: string;
|
||||
|
||||
@Column({
|
||||
nullable: false,
|
||||
default: true,
|
||||
})
|
||||
public isEnabled: boolean;
|
||||
|
||||
@Column({
|
||||
nullable: false,
|
||||
default: true,
|
||||
})
|
||||
public isActive: boolean;
|
||||
@Column({
|
||||
nullable: false,
|
||||
unique: true,
|
||||
})
|
||||
public invitationCode: string;
|
||||
// Relation with RoleTypeEntity
|
||||
@ManyToOne(() => RoleTypeEntity, (roleType) => roleType.invitedUsers, {
|
||||
nullable: false,
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
public roleType: RoleTypeEntity;
|
||||
@OneToOne(() => UserEntity, (user) => user.inviteUser, { nullable: true })
|
||||
@JoinColumn({ name: 'user_uuid' }) // Foreign key in InviteUserEntity
|
||||
user: UserEntity;
|
||||
@OneToMany(
|
||||
() => InviteUserSpaceEntity,
|
||||
(inviteUserSpace) => inviteUserSpace.inviteUser,
|
||||
)
|
||||
spaces: InviteUserSpaceEntity[];
|
||||
constructor(partial: Partial<InviteUserEntity>) {
|
||||
super();
|
||||
Object.assign(this, partial);
|
||||
}
|
||||
}
|
||||
@Entity({ name: 'invite-user-space' })
|
||||
@Unique(['inviteUser', 'space'])
|
||||
export class InviteUserSpaceEntity extends AbstractEntity<InviteUserSpaceDto> {
|
||||
@Column({
|
||||
type: 'uuid',
|
||||
default: () => 'gen_random_uuid()',
|
||||
nullable: false,
|
||||
})
|
||||
public uuid: string;
|
||||
|
||||
@ManyToOne(() => InviteUserEntity, (inviteUser) => inviteUser.spaces)
|
||||
@JoinColumn({ name: 'invite_user_uuid' })
|
||||
public inviteUser: InviteUserEntity;
|
||||
|
||||
@ManyToOne(() => SpaceEntity, (space) => space.invitedUsers)
|
||||
@JoinColumn({ name: 'space_uuid' })
|
||||
public space: SpaceEntity;
|
||||
constructor(partial: Partial<InviteUserSpaceEntity>) {
|
||||
super();
|
||||
Object.assign(this, partial);
|
||||
}
|
||||
}
|
1
libs/common/src/modules/Invite-user/entities/index.ts
Normal file
1
libs/common/src/modules/Invite-user/entities/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './Invite-user.entity';
|
@ -0,0 +1,16 @@
|
||||
import { DataSource, Repository } from 'typeorm';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InviteUserEntity, InviteUserSpaceEntity } from '../entities/';
|
||||
|
||||
@Injectable()
|
||||
export class InviteUserRepository extends Repository<InviteUserEntity> {
|
||||
constructor(private dataSource: DataSource) {
|
||||
super(InviteUserEntity, dataSource.createEntityManager());
|
||||
}
|
||||
}
|
||||
@Injectable()
|
||||
export class InviteUserSpaceRepository extends Repository<InviteUserSpaceEntity> {
|
||||
constructor(private dataSource: DataSource) {
|
||||
super(InviteUserSpaceEntity, dataSource.createEntityManager());
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
export * from './Invite-user.repository';
|
@ -15,6 +15,7 @@ import { SubspaceEntity } from './subspace.entity';
|
||||
import { SpaceLinkEntity } from './space-link.entity';
|
||||
import { SpaceProductEntity } from './space-product.entity';
|
||||
import { SceneEntity } from '../../scene/entities';
|
||||
import { InviteUserSpaceEntity } from '../../Invite-user/entities';
|
||||
|
||||
@Entity({ name: 'space' })
|
||||
@Unique(['invitationCode'])
|
||||
@ -97,7 +98,11 @@ export class SpaceEntity extends AbstractEntity<SpaceDto> {
|
||||
|
||||
@OneToMany(() => SceneEntity, (scene) => scene.space)
|
||||
scenes: SceneEntity[];
|
||||
|
||||
@OneToMany(
|
||||
() => InviteUserSpaceEntity,
|
||||
(inviteUserSpace) => inviteUserSpace.space,
|
||||
)
|
||||
invitedUsers: InviteUserSpaceEntity[];
|
||||
constructor(partial: Partial<SpaceEntity>) {
|
||||
super();
|
||||
Object.assign(this, partial);
|
||||
|
@ -58,20 +58,6 @@ export class UserOtpDto {
|
||||
public expiryTime: string;
|
||||
}
|
||||
|
||||
export class UserRoleDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public uuid: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public userUuid: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public roleTypeUuid: string;
|
||||
}
|
||||
|
||||
export class UserSpaceDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
|
@ -2,15 +2,16 @@ import {
|
||||
Column,
|
||||
DeleteDateColumn,
|
||||
Entity,
|
||||
JoinColumn,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
OneToOne,
|
||||
Unique,
|
||||
} from 'typeorm';
|
||||
import {
|
||||
UserDto,
|
||||
UserNotificationDto,
|
||||
UserOtpDto,
|
||||
UserRoleDto,
|
||||
UserSpaceDto,
|
||||
} from '../dtos';
|
||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||
@ -26,6 +27,8 @@ import { OtpType } from '../../../../src/constants/otp-type.enum';
|
||||
import { RoleTypeEntity } from '../../role-type/entities';
|
||||
import { SpaceEntity } from '../../space/entities';
|
||||
import { VisitorPasswordEntity } from '../../visitor-password/entities';
|
||||
import { InviteUserEntity } from '../../Invite-user/entities';
|
||||
import { ProjectEntity } from '../../project/entities';
|
||||
|
||||
@Entity({ name: 'user' })
|
||||
export class UserEntity extends AbstractEntity<UserDto> {
|
||||
@ -100,10 +103,7 @@ export class UserEntity extends AbstractEntity<UserDto> {
|
||||
(deviceUserNotification) => deviceUserNotification.user,
|
||||
)
|
||||
deviceUserNotification: DeviceNotificationEntity[];
|
||||
@OneToMany(() => UserRoleEntity, (role) => role.user, {
|
||||
nullable: true,
|
||||
})
|
||||
roles: UserRoleEntity[];
|
||||
|
||||
@ManyToOne(() => RegionEntity, (region) => region.users, { nullable: true })
|
||||
region: RegionEntity;
|
||||
@ManyToOne(() => TimeZoneEntity, (timezone) => timezone.users, {
|
||||
@ -116,6 +116,21 @@ export class UserEntity extends AbstractEntity<UserDto> {
|
||||
)
|
||||
public visitorPasswords: VisitorPasswordEntity[];
|
||||
|
||||
@ManyToOne(() => RoleTypeEntity, (roleType) => roleType.users, {
|
||||
nullable: true,
|
||||
})
|
||||
public roleType: RoleTypeEntity;
|
||||
@OneToOne(() => InviteUserEntity, (inviteUser) => inviteUser.user, {
|
||||
nullable: true,
|
||||
})
|
||||
@JoinColumn({ name: 'invite_user_uuid' })
|
||||
inviteUser: InviteUserEntity;
|
||||
|
||||
@ManyToOne(() => ProjectEntity, (project) => project.users, {
|
||||
nullable: true,
|
||||
})
|
||||
@JoinColumn({ name: 'project_uuid' })
|
||||
public project: ProjectEntity;
|
||||
constructor(partial: Partial<UserEntity>) {
|
||||
super();
|
||||
Object.assign(this, partial);
|
||||
@ -125,7 +140,7 @@ export class UserEntity extends AbstractEntity<UserDto> {
|
||||
@Entity({ name: 'user-notification' })
|
||||
@Unique(['user', 'subscriptionUuid'])
|
||||
export class UserNotificationEntity extends AbstractEntity<UserNotificationDto> {
|
||||
@ManyToOne(() => UserEntity, (user) => user.roles, {
|
||||
@ManyToOne(() => UserEntity, (user) => user.roleType, {
|
||||
nullable: false,
|
||||
})
|
||||
user: UserEntity;
|
||||
@ -178,25 +193,6 @@ export class UserOtpEntity extends AbstractEntity<UserOtpDto> {
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
@Entity({ name: 'user-space' })
|
||||
@Unique(['user', 'space'])
|
||||
export class UserSpaceEntity extends AbstractEntity<UserSpaceDto> {
|
||||
|
@ -4,7 +4,6 @@ import {
|
||||
UserEntity,
|
||||
UserNotificationEntity,
|
||||
UserOtpEntity,
|
||||
UserRoleEntity,
|
||||
UserSpaceEntity,
|
||||
} from '../entities/';
|
||||
|
||||
@ -29,13 +28,6 @@ export class UserOtpRepository extends Repository<UserOtpEntity> {
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class UserRoleRepository extends Repository<UserRoleEntity> {
|
||||
constructor(private dataSource: DataSource) {
|
||||
super(UserRoleEntity, dataSource.createEntityManager());
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class UserSpaceRepository extends Repository<UserSpaceEntity> {
|
||||
constructor(private dataSource: DataSource) {
|
||||
|
@ -10,7 +10,6 @@ import { RoleTypeSeeder } from './services/role.type.seeder';
|
||||
import { SpaceRepositoryModule } from '../modules/space/space.repository.module';
|
||||
import { SuperAdminSeeder } from './services/supper.admin.seeder';
|
||||
import { UserRepository } from '../modules/user/repositories';
|
||||
import { UserRoleRepository } from '../modules/user/repositories';
|
||||
import { UserRepositoryModule } from '../modules/user/user.repository.module';
|
||||
import { RegionSeeder } from './services/regions.seeder';
|
||||
import { RegionRepository } from '../modules/region/repositories';
|
||||
@ -28,7 +27,6 @@ import { SceneIconRepository } from '../modules/scene/repositories';
|
||||
RoleTypeRepository,
|
||||
SuperAdminSeeder,
|
||||
UserRepository,
|
||||
UserRoleRepository,
|
||||
RegionSeeder,
|
||||
RegionRepository,
|
||||
TimeZoneSeeder,
|
||||
|
Reference in New Issue
Block a user