mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-11-27 16:24:53 +00:00
Merge branch 'dev'
This commit is contained in:
14
.env.example
14
.env.example
@ -1,3 +1,5 @@
|
|||||||
|
NODE_ENV=
|
||||||
|
|
||||||
ACCESS_KEY=
|
ACCESS_KEY=
|
||||||
|
|
||||||
AZURE_POSTGRESQL_DATABASE=
|
AZURE_POSTGRESQL_DATABASE=
|
||||||
@ -52,6 +54,18 @@ SMTP_SECURE=
|
|||||||
|
|
||||||
SMTP_USER=
|
SMTP_USER=
|
||||||
|
|
||||||
|
MAILTRAP_API_TOKEN=
|
||||||
|
|
||||||
|
MAILTRAP_INVITATION_TEMPLATE_UUID=
|
||||||
|
|
||||||
|
MAILTRAP_EDIT_USER_TEMPLATE_UUID=
|
||||||
|
|
||||||
|
MAILTRAP_DISABLE_TEMPLATE_UUID=
|
||||||
|
|
||||||
|
MAILTRAP_ENABLE_TEMPLATE_UUID=
|
||||||
|
|
||||||
|
MAILTRAP_DELETE_USER_TEMPLATE_UUID=
|
||||||
|
|
||||||
WEBSITES_ENABLE_APP_SERVICE_STORAGE=
|
WEBSITES_ENABLE_APP_SERVICE_STORAGE=
|
||||||
|
|
||||||
PORT=
|
PORT=
|
||||||
|
|||||||
@ -22,4 +22,11 @@ module.exports = {
|
|||||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||||
'@typescript-eslint/no-explicit-any': 'off',
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
},
|
},
|
||||||
|
settings: {
|
||||||
|
'import/resolver': {
|
||||||
|
node: {
|
||||||
|
caseSensitive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,5 +4,5 @@ export class AuthInterface {
|
|||||||
uuid: string;
|
uuid: string;
|
||||||
sessionId: string;
|
sessionId: string;
|
||||||
id: number;
|
id: number;
|
||||||
roles?: string[];
|
role?: object;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,8 @@ import { UserSessionRepository } from '../../../../common/src/modules/session/re
|
|||||||
import { UserSessionEntity } from '../../../../common/src/modules/session/entities';
|
import { UserSessionEntity } from '../../../../common/src/modules/session/entities';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { OAuth2Client } from 'google-auth-library';
|
import { OAuth2Client } from 'google-auth-library';
|
||||||
|
import { PlatformType } from '@app/common/constants/platform-type.enum';
|
||||||
|
import { RoleType } from '@app/common/constants/role.type.enum';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthService {
|
export class AuthService {
|
||||||
@ -29,33 +31,46 @@ export class AuthService {
|
|||||||
email: string,
|
email: string,
|
||||||
pass: string,
|
pass: string,
|
||||||
regionUuid?: string,
|
regionUuid?: string,
|
||||||
|
platform?: PlatformType,
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
const user = await this.userRepository.findOne({
|
const user = await this.userRepository.findOne({
|
||||||
where: {
|
where: {
|
||||||
email,
|
email,
|
||||||
region: regionUuid
|
region: regionUuid ? { uuid: regionUuid } : undefined,
|
||||||
? {
|
|
||||||
uuid: regionUuid,
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
},
|
},
|
||||||
relations: ['roles.roleType'],
|
relations: ['roleType'],
|
||||||
});
|
});
|
||||||
|
if (
|
||||||
|
platform === PlatformType.WEB &&
|
||||||
|
(user.roleType.type === RoleType.SPACE_OWNER ||
|
||||||
|
user.roleType.type === RoleType.SPACE_MEMBER)
|
||||||
|
) {
|
||||||
|
throw new UnauthorizedException('Access denied for web platform');
|
||||||
|
}
|
||||||
|
if (!user) {
|
||||||
|
throw new BadRequestException('Invalid credentials');
|
||||||
|
}
|
||||||
|
|
||||||
if (!user.isUserVerified) {
|
if (!user.isUserVerified) {
|
||||||
throw new BadRequestException('User is not verified');
|
throw new BadRequestException('User is not verified');
|
||||||
}
|
}
|
||||||
if (user) {
|
if (!user.isActive) {
|
||||||
const passwordMatch = this.helperHashService.bcryptCompare(
|
throw new BadRequestException('User is not active');
|
||||||
pass,
|
|
||||||
user.password,
|
|
||||||
);
|
|
||||||
if (passwordMatch) {
|
|
||||||
const { ...result } = user;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
if (!user.hasAcceptedAppAgreement) {
|
||||||
|
throw new BadRequestException('User has not accepted app agreement');
|
||||||
|
}
|
||||||
|
const passwordMatch = await this.helperHashService.bcryptCompare(
|
||||||
|
pass,
|
||||||
|
user.password,
|
||||||
|
);
|
||||||
|
if (!passwordMatch) {
|
||||||
|
throw new BadRequestException('Invalid credentials');
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
const { password, ...result } = user;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
async createSession(data): Promise<UserSessionEntity> {
|
async createSession(data): Promise<UserSessionEntity> {
|
||||||
@ -85,10 +100,11 @@ export class AuthService {
|
|||||||
email: user.email,
|
email: user.email,
|
||||||
userId: user.userId,
|
userId: user.userId,
|
||||||
uuid: user.uuid,
|
uuid: user.uuid,
|
||||||
type: user.type,
|
|
||||||
sessionId: user.sessionId,
|
sessionId: user.sessionId,
|
||||||
roles: user?.roles,
|
role: user?.role,
|
||||||
googleCode: user.googleCode,
|
googleCode: user.googleCode,
|
||||||
|
hasAcceptedWebAgreement: user.hasAcceptedWebAgreement,
|
||||||
|
hasAcceptedAppAgreement: user.hasAcceptedAppAgreement,
|
||||||
};
|
};
|
||||||
if (payload.googleCode) {
|
if (payload.googleCode) {
|
||||||
const profile = await this.getProfile(payload.googleCode);
|
const profile = await this.getProfile(payload.googleCode);
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
|
|||||||
userUuid: payload.uuid,
|
userUuid: payload.uuid,
|
||||||
uuid: payload.uuid,
|
uuid: payload.uuid,
|
||||||
sessionId: payload.sessionId,
|
sessionId: payload.sessionId,
|
||||||
roles: payload?.roles,
|
role: payload?.role,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
throw new BadRequestException('Unauthorized');
|
throw new BadRequestException('Unauthorized');
|
||||||
|
|||||||
@ -34,7 +34,7 @@ export class RefreshTokenStrategy extends PassportStrategy(
|
|||||||
userUuid: payload.uuid,
|
userUuid: payload.uuid,
|
||||||
uuid: payload.uuid,
|
uuid: payload.uuid,
|
||||||
sessionId: payload.sessionId,
|
sessionId: payload.sessionId,
|
||||||
roles: payload?.roles,
|
role: payload?.role,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
throw new BadRequestException('Unauthorized');
|
throw new BadRequestException('Unauthorized');
|
||||||
|
|||||||
@ -9,6 +9,12 @@ import { EmailService } from './util/email.service';
|
|||||||
import { ErrorMessageService } from 'src/error-message/error-message.service';
|
import { ErrorMessageService } from 'src/error-message/error-message.service';
|
||||||
import { TuyaService } from './integrations/tuya/services/tuya.service';
|
import { TuyaService } from './integrations/tuya/services/tuya.service';
|
||||||
import { SceneDeviceRepository } from './modules/scene-device/repositories';
|
import { SceneDeviceRepository } from './modules/scene-device/repositories';
|
||||||
|
import { SpaceRepository } from './modules/space';
|
||||||
|
import {
|
||||||
|
SpaceModelRepository,
|
||||||
|
SubspaceModelRepository,
|
||||||
|
} from './modules/space-model';
|
||||||
|
import { SubspaceRepository } from './modules/space/repositories/subspace.repository';
|
||||||
@Module({
|
@Module({
|
||||||
providers: [
|
providers: [
|
||||||
CommonService,
|
CommonService,
|
||||||
@ -16,6 +22,10 @@ import { SceneDeviceRepository } from './modules/scene-device/repositories';
|
|||||||
ErrorMessageService,
|
ErrorMessageService,
|
||||||
TuyaService,
|
TuyaService,
|
||||||
SceneDeviceRepository,
|
SceneDeviceRepository,
|
||||||
|
SpaceRepository,
|
||||||
|
SubspaceRepository,
|
||||||
|
SubspaceModelRepository,
|
||||||
|
SpaceModelRepository,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
CommonService,
|
CommonService,
|
||||||
@ -25,6 +35,10 @@ import { SceneDeviceRepository } from './modules/scene-device/repositories';
|
|||||||
EmailService,
|
EmailService,
|
||||||
ErrorMessageService,
|
ErrorMessageService,
|
||||||
SceneDeviceRepository,
|
SceneDeviceRepository,
|
||||||
|
SpaceRepository,
|
||||||
|
SubspaceRepository,
|
||||||
|
SubspaceModelRepository,
|
||||||
|
SpaceModelRepository,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
ConfigModule.forRoot({
|
ConfigModule.forRoot({
|
||||||
|
|||||||
@ -10,5 +10,14 @@ export default registerAs(
|
|||||||
SMTP_USER: process.env.SMTP_USER,
|
SMTP_USER: process.env.SMTP_USER,
|
||||||
SMTP_SENDER: process.env.SMTP_SENDER,
|
SMTP_SENDER: process.env.SMTP_SENDER,
|
||||||
SMTP_PASSWORD: process.env.SMTP_PASSWORD,
|
SMTP_PASSWORD: process.env.SMTP_PASSWORD,
|
||||||
|
MAILTRAP_API_TOKEN: process.env.MAILTRAP_API_TOKEN,
|
||||||
|
MAILTRAP_INVITATION_TEMPLATE_UUID:
|
||||||
|
process.env.MAILTRAP_INVITATION_TEMPLATE_UUID,
|
||||||
|
MAILTRAP_DISABLE_TEMPLATE_UUID: process.env.MAILTRAP_DISABLE_TEMPLATE_UUID,
|
||||||
|
MAILTRAP_ENABLE_TEMPLATE_UUID: process.env.MAILTRAP_ENABLE_TEMPLATE_UUID,
|
||||||
|
MAILTRAP_DELETE_USER_TEMPLATE_UUID:
|
||||||
|
process.env.MAILTRAP_DELETE_USER_TEMPLATE_UUID,
|
||||||
|
MAILTRAP_EDIT_USER_TEMPLATE_UUID:
|
||||||
|
process.env.MAILTRAP_EDIT_USER_TEMPLATE_UUID,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -2,6 +2,8 @@ export enum ActionExecutorEnum {
|
|||||||
DEVICE_ISSUE = 'device_issue',
|
DEVICE_ISSUE = 'device_issue',
|
||||||
DELAY = 'delay',
|
DELAY = 'delay',
|
||||||
RULE_TRIGGER = 'rule_trigger',
|
RULE_TRIGGER = 'rule_trigger',
|
||||||
|
RULE_DISABLE = 'rule_disable',
|
||||||
|
RULE_ENABLE = 'rule_enable',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum EntityTypeEnum {
|
export enum EntityTypeEnum {
|
||||||
|
|||||||
@ -1,4 +1,47 @@
|
|||||||
export class ControllerRoute {
|
export class ControllerRoute {
|
||||||
|
static PROJECT = class {
|
||||||
|
public static readonly ROUTE = 'projects';
|
||||||
|
static ACTIONS = class {
|
||||||
|
public static readonly CREATE_PROJECT_SUMMARY = 'Create a new project';
|
||||||
|
public static readonly CREATE_PROJECT_DESCRIPTION =
|
||||||
|
'This endpoint allows you to create a new project by providing the required project details.';
|
||||||
|
|
||||||
|
public static readonly GET_PROJECT_SUMMARY = 'Retrieve project details';
|
||||||
|
public static readonly GET_PROJECT_DESCRIPTION =
|
||||||
|
'This endpoint retrieves the details of a project by its unique identifier (UUID).';
|
||||||
|
|
||||||
|
public static readonly UPDATE_PROJECT_SUMMARY = 'Update project details';
|
||||||
|
public static readonly UPDATE_PROJECT_DESCRIPTION =
|
||||||
|
'This endpoint updates the details of an existing project using its unique identifier (UUID).';
|
||||||
|
|
||||||
|
public static readonly LIST_PROJECTS_SUMMARY = 'List all projects';
|
||||||
|
public static readonly LIST_PROJECTS_DESCRIPTION =
|
||||||
|
'This endpoint retrieves a list of all existing projects, including their details.';
|
||||||
|
|
||||||
|
public static readonly DELETE_PROJECT_SUMMARY = 'Delete a project';
|
||||||
|
public static readonly DELETE_PROJECT_DESCRIPTION =
|
||||||
|
'This endpoint deletes an existing project by its unique identifier (UUID).';
|
||||||
|
|
||||||
|
public static readonly GET_USERS_BY_PROJECT_SUMMARY =
|
||||||
|
'Get users by project';
|
||||||
|
public static readonly GET_USERS_BY_PROJECT_DESCRIPTION =
|
||||||
|
'This endpoint retrieves all users associated with a specific project.';
|
||||||
|
public static readonly GET_USER_BY_UUID_IN_PROJECT_SUMMARY =
|
||||||
|
'Get user by uuid in project';
|
||||||
|
public static readonly GET_USER_BY_UUID_IN_PROJECT_DESCRIPTION =
|
||||||
|
'This endpoint retrieves a user by their unique identifier (UUID) associated with a specific project.';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
static PROJECT_USER = class {
|
||||||
|
public static readonly ROUTE = '/projects/:projectUuid/user';
|
||||||
|
static ACTIONS = class {
|
||||||
|
public static readonly GET_USERS_BY_PROJECT_SUMMARY =
|
||||||
|
'Get users by project';
|
||||||
|
public static readonly GET_USERS_BY_PROJECT_DESCRIPTION =
|
||||||
|
'This endpoint retrieves all users associated with a specific project.';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
static REGION = class {
|
static REGION = class {
|
||||||
public static readonly ROUTE = 'region';
|
public static readonly ROUTE = 'region';
|
||||||
static ACTIONS = class {
|
static ACTIONS = class {
|
||||||
@ -10,7 +53,7 @@ export class ControllerRoute {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static COMMUNITY = class {
|
static COMMUNITY = class {
|
||||||
public static readonly ROUTE = 'communities';
|
public static readonly ROUTE = '/projects/:projectUuid/communities';
|
||||||
static ACTIONS = class {
|
static ACTIONS = class {
|
||||||
public static readonly GET_COMMUNITY_BY_ID_SUMMARY =
|
public static readonly GET_COMMUNITY_BY_ID_SUMMARY =
|
||||||
'Get community by community community uuid';
|
'Get community by community community uuid';
|
||||||
@ -115,7 +158,8 @@ export class ControllerRoute {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static SPACE = class {
|
static SPACE = class {
|
||||||
public static readonly ROUTE = '/communities/:communityUuid/spaces';
|
public static readonly ROUTE =
|
||||||
|
'/projects/:projectUuid/communities/:communityUuid/spaces';
|
||||||
static ACTIONS = class {
|
static ACTIONS = class {
|
||||||
public static readonly CREATE_SPACE_SUMMARY = 'Create a new space';
|
public static readonly CREATE_SPACE_SUMMARY = 'Create a new space';
|
||||||
public static readonly CREATE_SPACE_DESCRIPTION =
|
public static readonly CREATE_SPACE_DESCRIPTION =
|
||||||
@ -156,7 +200,7 @@ export class ControllerRoute {
|
|||||||
|
|
||||||
static SPACE_SCENE = class {
|
static SPACE_SCENE = class {
|
||||||
public static readonly ROUTE =
|
public static readonly ROUTE =
|
||||||
'/communities/:communityUuid/spaces/:spaceUuid/scenes';
|
'/projects/:projectUuid/communities/:communityUuid/spaces/:spaceUuid/scenes';
|
||||||
static ACTIONS = class {
|
static ACTIONS = class {
|
||||||
public static readonly GET_TAP_TO_RUN_SCENE_BY_SPACE_SUMMARY =
|
public static readonly GET_TAP_TO_RUN_SCENE_BY_SPACE_SUMMARY =
|
||||||
'Retrieve Tap-to-Run Scenes by Space';
|
'Retrieve Tap-to-Run Scenes by Space';
|
||||||
@ -167,7 +211,7 @@ export class ControllerRoute {
|
|||||||
|
|
||||||
static SPACE_USER = class {
|
static SPACE_USER = class {
|
||||||
public static readonly ROUTE =
|
public static readonly ROUTE =
|
||||||
'/communities/:communityUuid/spaces/:spaceUuid/user';
|
'/projects/:projectUuid/communities/:communityUuid/spaces/:spaceUuid/user';
|
||||||
static ACTIONS = class {
|
static ACTIONS = class {
|
||||||
public static readonly ASSOCIATE_SPACE_USER_SUMMARY =
|
public static readonly ASSOCIATE_SPACE_USER_SUMMARY =
|
||||||
'Associate a user to a space';
|
'Associate a user to a space';
|
||||||
@ -183,7 +227,7 @@ export class ControllerRoute {
|
|||||||
|
|
||||||
static SPACE_DEVICES = class {
|
static SPACE_DEVICES = class {
|
||||||
public static readonly ROUTE =
|
public static readonly ROUTE =
|
||||||
'/communities/:communityUuid/spaces/:spaceUuid/devices';
|
'/projects/:projectUuid/communities/:communityUuid/spaces/:spaceUuid/devices';
|
||||||
static ACTIONS = class {
|
static ACTIONS = class {
|
||||||
public static readonly LIST_SPACE_DEVICE_SUMMARY =
|
public static readonly LIST_SPACE_DEVICE_SUMMARY =
|
||||||
'List devices in a space';
|
'List devices in a space';
|
||||||
@ -194,7 +238,7 @@ export class ControllerRoute {
|
|||||||
|
|
||||||
static SUBSPACE = class {
|
static SUBSPACE = class {
|
||||||
public static readonly ROUTE =
|
public static readonly ROUTE =
|
||||||
'/communities/:communityUuid/spaces/:spaceUuid/subspaces';
|
'/projects/:projectUuid/communities/:communityUuid/spaces/:spaceUuid/subspaces';
|
||||||
static ACTIONS = class {
|
static ACTIONS = class {
|
||||||
public static readonly CREATE_SUBSPACE_SUMMARY = 'Create Subspace';
|
public static readonly CREATE_SUBSPACE_SUMMARY = 'Create Subspace';
|
||||||
public static readonly CREATE_SUBSPACE_DESCRIPTION =
|
public static readonly CREATE_SUBSPACE_DESCRIPTION =
|
||||||
@ -220,7 +264,7 @@ export class ControllerRoute {
|
|||||||
|
|
||||||
static SUBSPACE_DEVICE = class {
|
static SUBSPACE_DEVICE = class {
|
||||||
public static readonly ROUTE =
|
public static readonly ROUTE =
|
||||||
'/communities/:communityUuid/spaces/:spaceUuid/subspaces/:subSpaceUuid/devices';
|
'/projects/:projectUuid/communities/:communityUuid/spaces/:spaceUuid/subspaces/:subSpaceUuid/devices';
|
||||||
|
|
||||||
static ACTIONS = class {
|
static ACTIONS = class {
|
||||||
public static readonly LIST_SUBSPACE_DEVICE_SUMMARY =
|
public static readonly LIST_SUBSPACE_DEVICE_SUMMARY =
|
||||||
@ -240,6 +284,32 @@ export class ControllerRoute {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static SPACE_MODEL = class {
|
||||||
|
public static readonly ROUTE = '/projects/:projectUuid/space-models';
|
||||||
|
static ACTIONS = class {
|
||||||
|
public static readonly CREATE_SPACE_MODEL_SUMMARY =
|
||||||
|
'Create a New Space Model';
|
||||||
|
public static readonly CREATE_SPACE_MODEL_DESCRIPTION =
|
||||||
|
'This endpoint allows you to create a new space model within a specified project. A space model defines the structure of spaces, including subspaces, products, and product items, and is uniquely identifiable within the project.';
|
||||||
|
|
||||||
|
public static readonly GET_SPACE_MODEL_SUMMARY = 'Get a New Space Model';
|
||||||
|
public static readonly GET_SPACE_MODEL_DESCRIPTION =
|
||||||
|
'Fetch a space model details';
|
||||||
|
|
||||||
|
public static readonly LIST_SPACE_MODEL_SUMMARY = 'List Space Models';
|
||||||
|
public static readonly LIST_SPACE_MODEL_DESCRIPTION =
|
||||||
|
'This endpoint allows you to retrieve a list of space models within a specified project. Each space model includes its structure, associated subspaces, products, and product items.';
|
||||||
|
|
||||||
|
public static readonly UPDATE_SPACE_MODEL_SUMMARY = 'Update Space Model';
|
||||||
|
public static readonly UPDATE_SPACE_MODEL_DESCRIPTION =
|
||||||
|
'This endpoint allows you to update a Space Model attributesas well as manage its associated Subspaces and Device';
|
||||||
|
|
||||||
|
public static readonly DELETE_SPACE_MODEL_SUMMARY = 'Delete Space Model';
|
||||||
|
public static readonly DELETE_SPACE_MODEL_DESCRIPTION =
|
||||||
|
'This endpoint allows you to delete a specified Space Model within a project. Deleting a Space Model disables the model and all its associated subspaces and tags, ensuring they are no longer active but remain in the system for auditing.';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
static PRODUCT = class {
|
static PRODUCT = class {
|
||||||
public static readonly ROUTE = 'products';
|
public static readonly ROUTE = 'products';
|
||||||
static ACTIONS = class {
|
static ACTIONS = class {
|
||||||
@ -279,6 +349,10 @@ export class ControllerRoute {
|
|||||||
public static readonly DELETE_USER_SUMMARY = 'Delete user by UUID';
|
public static readonly DELETE_USER_SUMMARY = 'Delete user by UUID';
|
||||||
public static readonly DELETE_USER_DESCRIPTION =
|
public static readonly DELETE_USER_DESCRIPTION =
|
||||||
'This endpoint deletes a user identified by their UUID. Accessible only by users with the Super Admin role.';
|
'This endpoint deletes a user identified by their UUID. Accessible only by users with the Super Admin role.';
|
||||||
|
public static readonly UPDATE_USER_WEB_AGREEMENT_SUMMARY =
|
||||||
|
'Update user web agreement by user UUID';
|
||||||
|
public static readonly UPDATE_USER_WEB_AGREEMENT_DESCRIPTION =
|
||||||
|
'This endpoint updates the web agreement for a user identified by their UUID.';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
static AUTHENTICATION = class {
|
static AUTHENTICATION = class {
|
||||||
@ -334,6 +408,25 @@ export class ControllerRoute {
|
|||||||
'This endpoint adds a new user role to the system based on the provided role data.';
|
'This endpoint adds a new user role to the system based on the provided role data.';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
static TERMS_AND_CONDITIONS = class {
|
||||||
|
public static readonly ROUTE = 'terms';
|
||||||
|
|
||||||
|
static ACTIONS = class {
|
||||||
|
public static readonly FETCH_TERMS_SUMMARY = 'Fetch Terms and Conditions';
|
||||||
|
public static readonly FETCH_TERMS_DESCRIPTION =
|
||||||
|
'This endpoint retrieves the terms and conditions for the application.';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
static PRIVACY_POLICY = class {
|
||||||
|
public static readonly ROUTE = 'policy';
|
||||||
|
|
||||||
|
static ACTIONS = class {
|
||||||
|
public static readonly FETCH_POLICY_SUMMARY = 'Fetch Privacy Policy';
|
||||||
|
public static readonly FETCH_POLICY_DESCRIPTION =
|
||||||
|
'This endpoint retrieves the privacy policy for the application.';
|
||||||
|
};
|
||||||
|
};
|
||||||
static GROUP = class {
|
static GROUP = class {
|
||||||
public static readonly ROUTE = 'group';
|
public static readonly ROUTE = 'group';
|
||||||
|
|
||||||
@ -685,4 +778,53 @@ export class ControllerRoute {
|
|||||||
'This endpoint deletes a user’s subscription for device messages.';
|
'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.';
|
||||||
|
|
||||||
|
public static readonly UPDATE_USER_INVITATION_SUMMARY =
|
||||||
|
'Update user invitation';
|
||||||
|
|
||||||
|
public static readonly UPDATE_USER_INVITATION_DESCRIPTION =
|
||||||
|
'This endpoint updates an invitation for a user to assign to role and spaces.';
|
||||||
|
|
||||||
|
public static readonly DISABLE_USER_INVITATION_SUMMARY =
|
||||||
|
'Disable user invitation';
|
||||||
|
|
||||||
|
public static readonly DISABLE_USER_INVITATION_DESCRIPTION =
|
||||||
|
'This endpoint disables an invitation for a user to assign to role and spaces.';
|
||||||
|
|
||||||
|
public static readonly DELETE_USER_INVITATION_SUMMARY =
|
||||||
|
'Delete user invitation';
|
||||||
|
|
||||||
|
public static readonly DELETE_USER_INVITATION_DESCRIPTION =
|
||||||
|
'This endpoint deletes an invitation for a user to assign to role and spaces.';
|
||||||
|
|
||||||
|
public static readonly ACTIVATION_CODE_SUMMARY =
|
||||||
|
'Activate Invitation Code';
|
||||||
|
|
||||||
|
public static readonly ACTIVATION_CODE_DESCRIPTION =
|
||||||
|
'This endpoint activate invitation code';
|
||||||
|
|
||||||
|
public static readonly CHECK_EMAIL_SUMMARY = 'Check email';
|
||||||
|
|
||||||
|
public static readonly CHECK_EMAIL_DESCRIPTION =
|
||||||
|
'This endpoint checks if an email already exists and have a project in the system.';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
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.';
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
3
libs/common/src/constants/mail-trap.ts
Normal file
3
libs/common/src/constants/mail-trap.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export const SEND_EMAIL_API_URL_PROD = 'https://send.api.mailtrap.io/api/send/';
|
||||||
|
export const SEND_EMAIL_API_URL_DEV =
|
||||||
|
'https://sandbox.api.mailtrap.io/api/send/2634012';
|
||||||
5
libs/common/src/constants/modify-action.enum.ts
Normal file
5
libs/common/src/constants/modify-action.enum.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export enum ModifyAction {
|
||||||
|
ADD = 'add',
|
||||||
|
UPDATE = 'update',
|
||||||
|
DELETE = 'delete',
|
||||||
|
}
|
||||||
4
libs/common/src/constants/orphan-constant.ts
Normal file
4
libs/common/src/constants/orphan-constant.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export const ORPHAN_COMMUNITY_NAME = 'orphan-community';
|
||||||
|
export const ORPHAN_COMMUNITY_DESCRIPTION =
|
||||||
|
'Default community for orphan spaces';
|
||||||
|
export const ORPHAN_SPACE_NAME = 'orphan-space';
|
||||||
53
libs/common/src/constants/permissions-mapping.ts
Normal file
53
libs/common/src/constants/permissions-mapping.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
export const PermissionMapping = {
|
||||||
|
DEVICE_MANAGEMENT: {
|
||||||
|
DEVICE: [
|
||||||
|
'SINGLE_CONTROL',
|
||||||
|
'VIEW',
|
||||||
|
'DELETE',
|
||||||
|
'UPDATE',
|
||||||
|
'BATCH_CONTROL',
|
||||||
|
'LOCATION_VIEW',
|
||||||
|
'LOCATION_UPDATE',
|
||||||
|
],
|
||||||
|
FIRMWARE: ['CONTROL', 'VIEW'],
|
||||||
|
},
|
||||||
|
COMMUNITY_MANAGEMENT: {
|
||||||
|
COMMUNITY: ['VIEW', 'ADD', 'UPDATE', 'DELETE'],
|
||||||
|
},
|
||||||
|
SPACE_MANAGEMENT: {
|
||||||
|
SPACE: [
|
||||||
|
'VIEW',
|
||||||
|
'ADD',
|
||||||
|
'UPDATE',
|
||||||
|
'DELETE',
|
||||||
|
'MODEL_ADD',
|
||||||
|
'MODEL_DELETE',
|
||||||
|
'MODEL_VIEW',
|
||||||
|
'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'],
|
||||||
|
},
|
||||||
|
};
|
||||||
4
libs/common/src/constants/platform-type.enum.ts
Normal file
4
libs/common/src/constants/platform-type.enum.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export enum PlatformType {
|
||||||
|
WEB = 'web',
|
||||||
|
MOBILE = 'mobile',
|
||||||
|
}
|
||||||
37
libs/common/src/constants/privacy-policy.html
Normal file
37
libs/common/src/constants/privacy-policy.html
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<div>
|
||||||
|
<p><strong>Syncrow Mobile Privacy Policy</strong></p>
|
||||||
|
<p>
|
||||||
|
Effective Date: 26/06/2022<br />
|
||||||
|
Updated: 26/06/2022
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Syncrow and subsidiaries (“we”, “us”, “our”, “Syncrow”) are committed to
|
||||||
|
protecting your privacy. This Privacy Policy (“Policy”) describes our
|
||||||
|
practices in connection with information privacy on Personal Data we process
|
||||||
|
through your individual use of the following services, products, and related
|
||||||
|
mobile applications (collectively, the “Products”):
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>Syncrow Mobile Application</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
Before you use our Products, please carefully read through this Policy and
|
||||||
|
understand our purposes and practices of collection, processing of your
|
||||||
|
Personal Data, including how we use, store, share and transfer Personal
|
||||||
|
Data. In the Policy you will also find ways to execute your rights of
|
||||||
|
access, update, delete or protect your Personal Data.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
When you accept this Policy when you register with your Personal Data, or if
|
||||||
|
you start to use our Products and does not expressly object to the contents
|
||||||
|
of this Policy, we will consider that you fully understand and agree with
|
||||||
|
this Policy. If you have any questions regarding this Policy, please do not
|
||||||
|
hesitate to contact us via:
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
For other branded mobile applications powered by Syncrow, our Clients
|
||||||
|
control all the Personal Data collected through our Products. We collect the
|
||||||
|
information under the direction of our Clients and the processing of such
|
||||||
|
information.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
@ -18,4 +18,5 @@ export enum ProductType {
|
|||||||
PC = 'PC',
|
PC = 'PC',
|
||||||
FOUR_S = '4S',
|
FOUR_S = '4S',
|
||||||
SIX_S = '6S',
|
SIX_S = '6S',
|
||||||
|
SOS = 'SOS',
|
||||||
}
|
}
|
||||||
|
|||||||
165
libs/common/src/constants/role-permissions.ts
Normal file
165
libs/common/src/constants/role-permissions.ts
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
import { RoleType } from './role.type.enum';
|
||||||
|
|
||||||
|
export const RolePermissions = {
|
||||||
|
[RoleType.SUPER_ADMIN]: [
|
||||||
|
'DEVICE_SINGLE_CONTROL',
|
||||||
|
'DEVICE_VIEW',
|
||||||
|
'DEVICE_DELETE',
|
||||||
|
'DEVICE_UPDATE',
|
||||||
|
'DEVICE_BATCH_CONTROL',
|
||||||
|
'DEVICE_LOCATION_VIEW',
|
||||||
|
'DEVICE_LOCATION_UPDATE',
|
||||||
|
'COMMUNITY_VIEW',
|
||||||
|
'COMMUNITY_ADD',
|
||||||
|
'COMMUNITY_UPDATE',
|
||||||
|
'COMMUNITY_DELETE',
|
||||||
|
'FIRMWARE_CONTROL',
|
||||||
|
'FIRMWARE_VIEW',
|
||||||
|
'SPACE_VIEW',
|
||||||
|
'SPACE_ADD',
|
||||||
|
'SPACE_UPDATE',
|
||||||
|
'SPACE_DELETE',
|
||||||
|
'SPACE_MODEL_ADD',
|
||||||
|
'SPACE_MODEL_VIEW',
|
||||||
|
'SPACE_MODEL_UPDATE',
|
||||||
|
'SPACE_MODEL_DELETE',
|
||||||
|
'SPACE_ASSIGN_USER_TO_SPACE',
|
||||||
|
'SPACE_DELETE_USER_FROM_SPACE',
|
||||||
|
'SUBSPACE_VIEW',
|
||||||
|
'SUBSPACE_ADD',
|
||||||
|
'SUBSPACE_UPDATE',
|
||||||
|
'SUBSPACE_DELETE',
|
||||||
|
'SUBSPACE_ASSIGN_DEVICE_TO_SUBSPACE',
|
||||||
|
'SUBSPACE_DELETE_DEVICE_FROM_SUBSPACE',
|
||||||
|
'DEVICE_WIZARD_VIEW_DEVICE_WIZARD',
|
||||||
|
'SUBSPACE_DEVICE_VIEW_DEVICE_IN_SUBSPACE',
|
||||||
|
'SPACE_DEVICE_VIEW_DEVICE_IN_SPACE',
|
||||||
|
'SUBSPACE_DEVICE_UPDATE_DEVICE_IN_SUBSPACE',
|
||||||
|
'SPACE_DEVICE_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',
|
||||||
|
'VISITOR_PASSWORD_UPDATE',
|
||||||
|
'VISITOR_PASSWORD_DELETE',
|
||||||
|
'USER_ADD',
|
||||||
|
'SPACE_MEMBER_ADD',
|
||||||
|
],
|
||||||
|
[RoleType.ADMIN]: [
|
||||||
|
'DEVICE_SINGLE_CONTROL',
|
||||||
|
'DEVICE_VIEW',
|
||||||
|
'DEVICE_DELETE',
|
||||||
|
'DEVICE_UPDATE',
|
||||||
|
'DEVICE_BATCH_CONTROL',
|
||||||
|
'DEVICE_LOCATION_VIEW',
|
||||||
|
'DEVICE_LOCATION_UPDATE',
|
||||||
|
'COMMUNITY_VIEW',
|
||||||
|
'COMMUNITY_ADD',
|
||||||
|
'COMMUNITY_UPDATE',
|
||||||
|
'COMMUNITY_DELETE',
|
||||||
|
'FIRMWARE_CONTROL',
|
||||||
|
'FIRMWARE_VIEW',
|
||||||
|
'SPACE_VIEW',
|
||||||
|
'SPACE_ADD',
|
||||||
|
'SPACE_UPDATE',
|
||||||
|
'SPACE_DELETE',
|
||||||
|
'SPACE_MODEL_ADD',
|
||||||
|
'SPACE_MODEL_VIEW',
|
||||||
|
'SPACE_MODEL_UPDATE',
|
||||||
|
'SPACE_MODEL_DELETE',
|
||||||
|
'SPACE_ASSIGN_USER_TO_SPACE',
|
||||||
|
'SPACE_DELETE_USER_FROM_SPACE',
|
||||||
|
'SUBSPACE_VIEW',
|
||||||
|
'SUBSPACE_ADD',
|
||||||
|
'SUBSPACE_UPDATE',
|
||||||
|
'SUBSPACE_DELETE',
|
||||||
|
'SUBSPACE_ASSIGN_DEVICE_TO_SUBSPACE',
|
||||||
|
'SUBSPACE_DELETE_DEVICE_FROM_SUBSPACE',
|
||||||
|
'DEVICE_WIZARD_VIEW_DEVICE_WIZARD',
|
||||||
|
'SUBSPACE_DEVICE_VIEW_DEVICE_IN_SUBSPACE',
|
||||||
|
'SPACE_DEVICE_VIEW_DEVICE_IN_SPACE',
|
||||||
|
'SUBSPACE_DEVICE_UPDATE_DEVICE_IN_SUBSPACE',
|
||||||
|
'SPACE_DEVICE_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',
|
||||||
|
'VISITOR_PASSWORD_UPDATE',
|
||||||
|
'VISITOR_PASSWORD_DELETE',
|
||||||
|
'USER_ADD',
|
||||||
|
'SPACE_MEMBER_ADD',
|
||||||
|
],
|
||||||
|
[RoleType.SPACE_MEMBER]: [
|
||||||
|
'DEVICE_SINGLE_CONTROL',
|
||||||
|
'DEVICE_VIEW',
|
||||||
|
'SPACE_VIEW',
|
||||||
|
'SUBSPACE_VIEW',
|
||||||
|
'DEVICE_WIZARD_VIEW_DEVICE_WIZARD',
|
||||||
|
'SUBSPACE_DEVICE_VIEW_DEVICE_IN_SUBSPACE',
|
||||||
|
'SPACE_DEVICE_VIEW_DEVICE_IN_SPACE',
|
||||||
|
'AUTOMATION_VIEW',
|
||||||
|
'AUTOMATION_CONTROL',
|
||||||
|
'SCENES_VIEW',
|
||||||
|
'SCENES_CONTROL',
|
||||||
|
],
|
||||||
|
[RoleType.SPACE_OWNER]: [
|
||||||
|
'DEVICE_SINGLE_CONTROL',
|
||||||
|
'DEVICE_VIEW',
|
||||||
|
'DEVICE_DELETE',
|
||||||
|
'DEVICE_UPDATE',
|
||||||
|
'DEVICE_BATCH_CONTROL',
|
||||||
|
'DEVICE_LOCATION_VIEW',
|
||||||
|
'DEVICE_LOCATION_UPDATE',
|
||||||
|
'FIRMWARE_CONTROL',
|
||||||
|
'FIRMWARE_VIEW',
|
||||||
|
'SPACE_VIEW',
|
||||||
|
'SPACE_ADD',
|
||||||
|
'SPACE_UPDATE',
|
||||||
|
'SPACE_DELETE',
|
||||||
|
'SPACE_ASSIGN_USER_TO_SPACE',
|
||||||
|
'SPACE_DELETE_USER_FROM_SPACE',
|
||||||
|
'SUBSPACE_VIEW',
|
||||||
|
'SUBSPACE_ADD',
|
||||||
|
'SUBSPACE_UPDATE',
|
||||||
|
'SUBSPACE_DELETE',
|
||||||
|
'SUBSPACE_ASSIGN_DEVICE_TO_SUBSPACE',
|
||||||
|
'SUBSPACE_DELETE_DEVICE_FROM_SUBSPACE',
|
||||||
|
'DEVICE_WIZARD_VIEW_DEVICE_WIZARD',
|
||||||
|
'SUBSPACE_DEVICE_VIEW_DEVICE_IN_SUBSPACE',
|
||||||
|
'SPACE_DEVICE_VIEW_DEVICE_IN_SPACE',
|
||||||
|
'SUBSPACE_DEVICE_UPDATE_DEVICE_IN_SUBSPACE',
|
||||||
|
'SPACE_DEVICE_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',
|
||||||
|
'VISITOR_PASSWORD_UPDATE',
|
||||||
|
'VISITOR_PASSWORD_DELETE',
|
||||||
|
'USER_ADD',
|
||||||
|
'SPACE_MEMBER_ADD',
|
||||||
|
],
|
||||||
|
};
|
||||||
@ -1,4 +1,6 @@
|
|||||||
export enum RoleType {
|
export enum RoleType {
|
||||||
SUPER_ADMIN = 'SUPER_ADMIN',
|
SUPER_ADMIN = 'SUPER_ADMIN',
|
||||||
ADMIN = 'ADMIN',
|
ADMIN = 'ADMIN',
|
||||||
|
SPACE_OWNER = 'SPACE_OWNER',
|
||||||
|
SPACE_MEMBER = 'SPACE_MEMBER',
|
||||||
}
|
}
|
||||||
|
|||||||
44
libs/common/src/constants/terms-and-conditions.html
Normal file
44
libs/common/src/constants/terms-and-conditions.html
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<div>
|
||||||
|
<p>User Agreement</p>
|
||||||
|
<p>Terms and Conditions</p>
|
||||||
|
<p><span>Last updated:</span> {{lastUpdated}}</p>
|
||||||
|
<p>
|
||||||
|
Please read these Terms and Conditions ("Terms", "Terms and Conditions")
|
||||||
|
carefully before using the
|
||||||
|
<a href="{{websiteUrl}}">{{websiteUrl}}</a> website and the {{mobileApp}}
|
||||||
|
mobile application (the "Service") operated by {{companyName}}.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Your access to and use of the Service is conditioned on your acceptance of
|
||||||
|
and compliance with these Terms. These Terms apply to all visitors, users,
|
||||||
|
and others who access or use the Service.
|
||||||
|
</p>
|
||||||
|
<p>Content</p>
|
||||||
|
<p>
|
||||||
|
Our Service allows you to post, link, store, share and otherwise make
|
||||||
|
available certain information, text, graphics, videos, or other material
|
||||||
|
("Content"). You are responsible for the Content you post.
|
||||||
|
</p>
|
||||||
|
<p>Links To Other Websites</p>
|
||||||
|
<p>
|
||||||
|
Our Service may contain links to third-party websites or services that are
|
||||||
|
not owned or controlled by {{companyName}}.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{{companyName}} has no control over, and assumes no responsibility for, the
|
||||||
|
content, privacy policies, or practices of any third-party websites or
|
||||||
|
services.
|
||||||
|
</p>
|
||||||
|
<p>Changes</p>
|
||||||
|
<p>
|
||||||
|
We reserve the right, at our sole discretion, to modify or replace these
|
||||||
|
Terms at any time. If a revision is material, we will try to provide at
|
||||||
|
least 30 days' notice prior to any new terms taking effect. What constitutes
|
||||||
|
a material change will be determined at our sole discretion.
|
||||||
|
</p>
|
||||||
|
<p>Contact Us</p>
|
||||||
|
<p>
|
||||||
|
If you have any questions about these Terms, please
|
||||||
|
<a href="mailto:{{contactEmail}}">contact us</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
7
libs/common/src/constants/terms-condtions.ts
Normal file
7
libs/common/src/constants/terms-condtions.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export const termsAndConditionsData = {
|
||||||
|
lastUpdated: '25/01/2025',
|
||||||
|
websiteUrl: 'https://www.Syncrow.ae',
|
||||||
|
mobileApp: 'Syncrow Mobile App',
|
||||||
|
companyName: 'Syncrow',
|
||||||
|
contactEmail: 'contact@Syncrow.ae',
|
||||||
|
};
|
||||||
4
libs/common/src/constants/user-status.enum.ts
Normal file
4
libs/common/src/constants/user-status.enum.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export enum UserStatusEnum {
|
||||||
|
ACTIVE = 'active',
|
||||||
|
INVITED = 'invited',
|
||||||
|
}
|
||||||
@ -12,10 +12,10 @@ import {
|
|||||||
SpaceEntity,
|
SpaceEntity,
|
||||||
SpaceLinkEntity,
|
SpaceLinkEntity,
|
||||||
SubspaceEntity,
|
SubspaceEntity,
|
||||||
|
TagEntity,
|
||||||
} 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';
|
||||||
@ -26,8 +26,18 @@ import { CommunityEntity } from '../modules/community/entities';
|
|||||||
import { DeviceStatusLogEntity } from '../modules/device-status-log/entities';
|
import { DeviceStatusLogEntity } from '../modules/device-status-log/entities';
|
||||||
import { SceneEntity, SceneIconEntity } from '../modules/scene/entities';
|
import { SceneEntity, SceneIconEntity } from '../modules/scene/entities';
|
||||||
import { SceneDeviceEntity } from '../modules/scene-device/entities';
|
import { SceneDeviceEntity } from '../modules/scene-device/entities';
|
||||||
import { SpaceProductEntity } from '../modules/space/entities/space-product.entity';
|
import { ProjectEntity } from '../modules/project/entities';
|
||||||
|
import {
|
||||||
|
SpaceModelEntity,
|
||||||
|
SubspaceModelEntity,
|
||||||
|
TagModel,
|
||||||
|
} from '../modules/space-model/entities';
|
||||||
|
import {
|
||||||
|
InviteUserEntity,
|
||||||
|
InviteUserSpaceEntity,
|
||||||
|
} from '../modules/Invite-user/entities';
|
||||||
|
import { InviteSpaceEntity } from '../modules/space/entities/invite-space.entity';
|
||||||
|
import { AutomationEntity } from '../modules/automation/entities';
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
TypeOrmModule.forRootAsync({
|
TypeOrmModule.forRootAsync({
|
||||||
@ -42,6 +52,7 @@ import { SpaceProductEntity } from '../modules/space/entities/space-product.enti
|
|||||||
password: configService.get('DB_PASSWORD'),
|
password: configService.get('DB_PASSWORD'),
|
||||||
database: configService.get('DB_NAME'),
|
database: configService.get('DB_NAME'),
|
||||||
entities: [
|
entities: [
|
||||||
|
ProjectEntity,
|
||||||
UserEntity,
|
UserEntity,
|
||||||
UserSessionEntity,
|
UserSessionEntity,
|
||||||
UserOtpEntity,
|
UserOtpEntity,
|
||||||
@ -53,10 +64,9 @@ import { SpaceProductEntity } from '../modules/space/entities/space-product.enti
|
|||||||
SpaceEntity,
|
SpaceEntity,
|
||||||
SpaceLinkEntity,
|
SpaceLinkEntity,
|
||||||
SubspaceEntity,
|
SubspaceEntity,
|
||||||
SpaceProductEntity,
|
TagEntity,
|
||||||
UserSpaceEntity,
|
UserSpaceEntity,
|
||||||
DeviceUserPermissionEntity,
|
DeviceUserPermissionEntity,
|
||||||
UserRoleEntity,
|
|
||||||
RoleTypeEntity,
|
RoleTypeEntity,
|
||||||
UserNotificationEntity,
|
UserNotificationEntity,
|
||||||
DeviceNotificationEntity,
|
DeviceNotificationEntity,
|
||||||
@ -67,6 +77,13 @@ import { SpaceProductEntity } from '../modules/space/entities/space-product.enti
|
|||||||
SceneEntity,
|
SceneEntity,
|
||||||
SceneIconEntity,
|
SceneIconEntity,
|
||||||
SceneDeviceEntity,
|
SceneDeviceEntity,
|
||||||
|
SpaceModelEntity,
|
||||||
|
SubspaceModelEntity,
|
||||||
|
TagModel,
|
||||||
|
InviteUserEntity,
|
||||||
|
InviteUserSpaceEntity,
|
||||||
|
InviteSpaceEntity,
|
||||||
|
AutomationEntity,
|
||||||
],
|
],
|
||||||
namingStrategy: new SnakeNamingStrategy(),
|
namingStrategy: new SnakeNamingStrategy(),
|
||||||
synchronize: Boolean(JSON.parse(configService.get('DB_SYNC'))),
|
synchronize: Boolean(JSON.parse(configService.get('DB_SYNC'))),
|
||||||
|
|||||||
@ -187,19 +187,19 @@ export class DeviceStatusFirebaseService {
|
|||||||
code,
|
code,
|
||||||
value,
|
value,
|
||||||
}));
|
}));
|
||||||
const newLog = this.deviceStatusLogRepository.create({
|
const newLogs = addDeviceStatusDto.log.properties.map((property) => {
|
||||||
deviceId: addDeviceStatusDto.deviceUuid,
|
return this.deviceStatusLogRepository.create({
|
||||||
deviceTuyaId: addDeviceStatusDto.deviceTuyaUuid,
|
deviceId: addDeviceStatusDto.deviceUuid,
|
||||||
productId: addDeviceStatusDto.log.productId,
|
deviceTuyaId: addDeviceStatusDto.deviceTuyaUuid,
|
||||||
log: addDeviceStatusDto.log,
|
productId: addDeviceStatusDto.log.productId,
|
||||||
code: existingData.status[0].code,
|
log: addDeviceStatusDto.log,
|
||||||
value: existingData.status[0].value,
|
code: property.code,
|
||||||
eventId: addDeviceStatusDto.log.dataId,
|
value: property.value,
|
||||||
eventTime: new Date(
|
eventId: addDeviceStatusDto.log.dataId,
|
||||||
addDeviceStatusDto.log.properties[0].time,
|
eventTime: new Date(property.time).toISOString(),
|
||||||
).toISOString(),
|
});
|
||||||
});
|
});
|
||||||
await this.deviceStatusLogRepository.save(newLog);
|
await this.deviceStatusLogRepository.save(newLogs);
|
||||||
// Save the updated data to Firebase
|
// Save the updated data to Firebase
|
||||||
await set(dataRef, existingData);
|
await set(dataRef, existingData);
|
||||||
|
|
||||||
|
|||||||
12
libs/common/src/helper/removeCircularReferences.ts
Normal file
12
libs/common/src/helper/removeCircularReferences.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
export function removeCircularReferences() {
|
||||||
|
const seen = new WeakSet();
|
||||||
|
return (key: string, value: any) => {
|
||||||
|
if (typeof value === 'object' && value !== null) {
|
||||||
|
if (seen.has(value)) {
|
||||||
|
return undefined; // Skip circular reference
|
||||||
|
}
|
||||||
|
seen.add(value);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -6,6 +6,7 @@ import {
|
|||||||
ConvertedAction,
|
ConvertedAction,
|
||||||
TuyaResponseInterface,
|
TuyaResponseInterface,
|
||||||
} from '../interfaces';
|
} from '../interfaces';
|
||||||
|
import { GetDeviceDetailsFunctionsStatusInterface } from 'src/device/interfaces/get.device.interface';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TuyaService {
|
export class TuyaService {
|
||||||
@ -284,4 +285,24 @@ export class TuyaService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async getDevicesInstructionStatusTuya(
|
||||||
|
deviceUuid: string,
|
||||||
|
): Promise<GetDeviceDetailsFunctionsStatusInterface> {
|
||||||
|
try {
|
||||||
|
const path = `/v1.0/iot-03/devices/status`;
|
||||||
|
const response = await this.tuya.request({
|
||||||
|
method: 'GET',
|
||||||
|
path,
|
||||||
|
query: {
|
||||||
|
device_ids: deviceUuid,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return response as GetDeviceDetailsFunctionsStatusInterface;
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException(
|
||||||
|
'Error fetching device functions status from Tuya',
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { FindManyOptions, Repository } from 'typeorm';
|
import { FindManyOptions, Repository, SelectQueryBuilder } from 'typeorm';
|
||||||
import { InternalServerErrorException } from '@nestjs/common';
|
import { InternalServerErrorException } from '@nestjs/common';
|
||||||
import { BaseResponseDto } from '../dto/base.response.dto';
|
import { BaseResponseDto } from '../dto/base.response.dto';
|
||||||
import { PageResponseDto } from '../dto/pagination.response.dto';
|
import { PageResponseDto } from '../dto/pagination.response.dto';
|
||||||
@ -31,7 +31,7 @@ interface FindAllQueryWithDefaults extends CustomFindAllQuery {
|
|||||||
function getDefaultQueryOptions(
|
function getDefaultQueryOptions(
|
||||||
query: Partial<TypeORMCustomModelFindAllQuery>,
|
query: Partial<TypeORMCustomModelFindAllQuery>,
|
||||||
): FindManyOptions & FindAllQueryWithDefaults {
|
): FindManyOptions & FindAllQueryWithDefaults {
|
||||||
const { page, size, includeDisable, modelName, ...rest } = query;
|
const { page, size, includeDisable, include, modelName, ...rest } = query;
|
||||||
|
|
||||||
// Set default if undefined or null
|
// Set default if undefined or null
|
||||||
const returnPage = page ? Number(page) : 1;
|
const returnPage = page ? Number(page) : 1;
|
||||||
@ -48,7 +48,9 @@ function getDefaultQueryOptions(
|
|||||||
},
|
},
|
||||||
page: returnPage,
|
page: returnPage,
|
||||||
size: returnSize,
|
size: returnSize,
|
||||||
|
include: include || undefined,
|
||||||
includeDisable: returnIncludeDisable,
|
includeDisable: returnIncludeDisable,
|
||||||
|
|
||||||
modelName: modelName || query.modelName, // Ensure modelName is passed through
|
modelName: modelName || query.modelName, // Ensure modelName is passed through
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -68,8 +70,8 @@ export function TypeORMCustomModel(repository: Repository<any>) {
|
|||||||
return Object.assign(repository, {
|
return Object.assign(repository, {
|
||||||
findAll: async function (
|
findAll: async function (
|
||||||
query: Partial<TypeORMCustomModelFindAllQuery>,
|
query: Partial<TypeORMCustomModelFindAllQuery>,
|
||||||
|
customQueryBuilder?: SelectQueryBuilder<any>,
|
||||||
): Promise<TypeORMCustomModelFindAllResponse> {
|
): Promise<TypeORMCustomModelFindAllResponse> {
|
||||||
// Extract values from the query
|
|
||||||
const {
|
const {
|
||||||
page = 1,
|
page = 1,
|
||||||
size = 10,
|
size = 10,
|
||||||
@ -80,12 +82,7 @@ export function TypeORMCustomModel(repository: Repository<any>) {
|
|||||||
select,
|
select,
|
||||||
} = getDefaultQueryOptions(query);
|
} = getDefaultQueryOptions(query);
|
||||||
|
|
||||||
// Ensure modelName is set before proceeding
|
|
||||||
if (!modelName) {
|
if (!modelName) {
|
||||||
console.error(
|
|
||||||
'modelName is missing after getDefaultQueryOptions:',
|
|
||||||
query,
|
|
||||||
);
|
|
||||||
throw new InternalServerErrorException(
|
throw new InternalServerErrorException(
|
||||||
`[TypeORMCustomModel] Cannot findAll with unknown modelName`,
|
`[TypeORMCustomModel] Cannot findAll with unknown modelName`,
|
||||||
);
|
);
|
||||||
@ -94,20 +91,44 @@ export function TypeORMCustomModel(repository: Repository<any>) {
|
|||||||
const skip = (page - 1) * size;
|
const skip = (page - 1) * size;
|
||||||
const order = buildTypeORMSortQuery(sort);
|
const order = buildTypeORMSortQuery(sort);
|
||||||
const relations = buildTypeORMIncludeQuery(modelName, include);
|
const relations = buildTypeORMIncludeQuery(modelName, include);
|
||||||
|
|
||||||
// Use the where clause directly, without wrapping it under 'where'
|
|
||||||
const whereClause = buildTypeORMWhereClause({ where });
|
const whereClause = buildTypeORMWhereClause({ where });
|
||||||
console.log('Final where clause:', whereClause);
|
|
||||||
|
|
||||||
// Ensure the whereClause is passed directly to findAndCount
|
let data: any[] = [];
|
||||||
const [data, count] = await repository.findAndCount({
|
let count = 0;
|
||||||
where: whereClause,
|
|
||||||
take: size,
|
if (customQueryBuilder) {
|
||||||
skip: skip,
|
const qb = customQueryBuilder.skip(skip).take(size);
|
||||||
order: order,
|
|
||||||
select: select,
|
if (order) {
|
||||||
relations: relations,
|
Object.keys(order).forEach((key) => {
|
||||||
});
|
qb.addOrderBy(key, order[key]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (whereClause) {
|
||||||
|
qb.andWhere(whereClause); // Use .andWhere instead of .where to avoid overwriting conditions
|
||||||
|
}
|
||||||
|
|
||||||
|
if (select) {
|
||||||
|
const selectColumns = Array.isArray(select)
|
||||||
|
? select
|
||||||
|
: Object.keys(select).map(
|
||||||
|
(key) => `${customQueryBuilder.alias}.${key}`,
|
||||||
|
);
|
||||||
|
qb.select(selectColumns as string[]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data, count] = await qb.getManyAndCount();
|
||||||
|
} else {
|
||||||
|
[data, count] = await repository.findAndCount({
|
||||||
|
where: whereClause,
|
||||||
|
take: size,
|
||||||
|
skip: skip,
|
||||||
|
order: order,
|
||||||
|
select: select,
|
||||||
|
relations: relations,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const paginationResponseDto = getPaginationResponseDto(count, page, size);
|
const paginationResponseDto = getPaginationResponseDto(count, page, size);
|
||||||
const baseResponseDto: BaseResponseDto = {
|
const baseResponseDto: BaseResponseDto = {
|
||||||
|
|||||||
@ -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 {}
|
||||||
50
libs/common/src/modules/Invite-user/dtos/Invite-user.dto.ts
Normal file
50
libs/common/src/modules/Invite-user/dtos/Invite-user.dto.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { RoleType } from '@app/common/constants/role.type.enum';
|
||||||
|
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;
|
||||||
|
|
||||||
|
@IsEnum(RoleType)
|
||||||
|
@IsNotEmpty()
|
||||||
|
public invitedBy: RoleType;
|
||||||
|
}
|
||||||
|
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,126 @@
|
|||||||
|
import {
|
||||||
|
Column,
|
||||||
|
Entity,
|
||||||
|
JoinColumn,
|
||||||
|
ManyToOne,
|
||||||
|
OneToMany,
|
||||||
|
OneToOne,
|
||||||
|
Unique,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
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';
|
||||||
|
import { RoleType } from '@app/common/constants/role.type.enum';
|
||||||
|
import { InviteUserDto, InviteUserSpaceDto } from '../dtos';
|
||||||
|
import { ProjectEntity } from '../../project/entities';
|
||||||
|
|
||||||
|
@Entity({ name: 'invite-user' })
|
||||||
|
@Unique(['email', 'project'])
|
||||||
|
export class InviteUserEntity extends AbstractEntity<InviteUserDto> {
|
||||||
|
@Column({
|
||||||
|
type: 'uuid',
|
||||||
|
default: () => 'gen_random_uuid()',
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
public uuid: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
email: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
jobTitle: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
enum: Object.values(UserStatusEnum),
|
||||||
|
})
|
||||||
|
status: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
public firstName: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
public lastName: string;
|
||||||
|
@Column({
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
public phoneNumber: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
default: true,
|
||||||
|
})
|
||||||
|
public isActive: boolean;
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
default: true,
|
||||||
|
})
|
||||||
|
public isEnabled: boolean;
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
unique: true,
|
||||||
|
})
|
||||||
|
public invitationCode: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
enum: Object.values(RoleType),
|
||||||
|
})
|
||||||
|
public invitedBy: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => RoleTypeEntity, (roleType) => roleType.invitedUsers, {
|
||||||
|
nullable: false,
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
})
|
||||||
|
public roleType: RoleTypeEntity;
|
||||||
|
@OneToOne(() => UserEntity, (user) => user.inviteUser, { nullable: true })
|
||||||
|
@JoinColumn({ name: 'user_uuid' })
|
||||||
|
user: UserEntity;
|
||||||
|
@OneToMany(
|
||||||
|
() => InviteUserSpaceEntity,
|
||||||
|
(inviteUserSpace) => inviteUserSpace.inviteUser,
|
||||||
|
)
|
||||||
|
spaces: InviteUserSpaceEntity[];
|
||||||
|
|
||||||
|
@ManyToOne(() => ProjectEntity, (project) => project.invitedUsers, {
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
@JoinColumn({ name: 'project_uuid' })
|
||||||
|
public project: ProjectEntity;
|
||||||
|
|
||||||
|
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';
|
||||||
1
libs/common/src/modules/Invite-user/index.ts
Normal file
1
libs/common/src/modules/Invite-user/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './Invite-user.repository.module';
|
||||||
@ -0,0 +1 @@
|
|||||||
|
export * from './invite-user.repository';
|
||||||
@ -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,11 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { AutomationEntity } from './entities';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
providers: [],
|
||||||
|
exports: [],
|
||||||
|
controllers: [],
|
||||||
|
imports: [TypeOrmModule.forFeature([AutomationEntity])],
|
||||||
|
})
|
||||||
|
export class AutomationRepositoryModule {}
|
||||||
14
libs/common/src/modules/automation/dtos/automation.dto.ts
Normal file
14
libs/common/src/modules/automation/dtos/automation.dto.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class AutomationDto {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public uuid: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public automationTuyaUuid: string;
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public spaceUuid: string;
|
||||||
|
}
|
||||||
1
libs/common/src/modules/automation/dtos/index.ts
Normal file
1
libs/common/src/modules/automation/dtos/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './automation.dto';
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm';
|
||||||
|
import { AutomationDto } from '../dtos';
|
||||||
|
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||||
|
import { SpaceEntity } from '../../space/entities';
|
||||||
|
|
||||||
|
@Entity({ name: 'automation' })
|
||||||
|
export class AutomationEntity extends AbstractEntity<AutomationDto> {
|
||||||
|
@Column({
|
||||||
|
type: 'uuid',
|
||||||
|
default: () => 'gen_random_uuid()',
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
public uuid: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
automationTuyaUuid: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => SpaceEntity, (space) => space.scenes, {
|
||||||
|
nullable: false,
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
})
|
||||||
|
@JoinColumn({ name: 'space_uuid' })
|
||||||
|
space: SpaceEntity;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
|
public disabled: boolean;
|
||||||
|
|
||||||
|
constructor(partial: Partial<AutomationEntity>) {
|
||||||
|
super();
|
||||||
|
Object.assign(this, partial);
|
||||||
|
}
|
||||||
|
}
|
||||||
1
libs/common/src/modules/automation/entities/index.ts
Normal file
1
libs/common/src/modules/automation/entities/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './automation.entity';
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { DataSource, Repository } from 'typeorm';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { AutomationEntity } from '../entities';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AutomationRepository extends Repository<AutomationEntity> {
|
||||||
|
constructor(private dataSource: DataSource) {
|
||||||
|
super(AutomationEntity, dataSource.createEntityManager());
|
||||||
|
}
|
||||||
|
}
|
||||||
1
libs/common/src/modules/automation/repositories/index.ts
Normal file
1
libs/common/src/modules/automation/repositories/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './automation.repository';
|
||||||
@ -1,7 +1,8 @@
|
|||||||
import { Column, Entity, 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 { CommunityDto } from '../dtos';
|
import { CommunityDto } from '../dtos';
|
||||||
import { SpaceEntity } from '../../space/entities';
|
import { SpaceEntity } from '../../space/entities';
|
||||||
|
import { ProjectEntity } from '../../project/entities';
|
||||||
|
|
||||||
@Entity({ name: 'community' })
|
@Entity({ name: 'community' })
|
||||||
@Unique(['name'])
|
@Unique(['name'])
|
||||||
@ -31,4 +32,9 @@ export class CommunityEntity extends AbstractEntity<CommunityDto> {
|
|||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
externalId: string;
|
externalId: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => ProjectEntity, (project) => project.communities, {
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
project: ProjectEntity;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,7 @@ export class DeviceStatusLogEntity {
|
|||||||
})
|
})
|
||||||
eventFrom: SourceType;
|
eventFrom: SourceType;
|
||||||
|
|
||||||
@Column({ type: 'text' })
|
@Column({ type: 'uuid' })
|
||||||
deviceId: string;
|
deviceId: string;
|
||||||
|
|
||||||
@Column({ type: 'text' })
|
@Column({ type: 'text' })
|
||||||
|
|||||||
@ -6,10 +6,11 @@ import {
|
|||||||
Unique,
|
Unique,
|
||||||
Index,
|
Index,
|
||||||
JoinColumn,
|
JoinColumn,
|
||||||
|
OneToOne,
|
||||||
} from 'typeorm';
|
} from 'typeorm';
|
||||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||||
import { DeviceDto, DeviceUserPermissionDto } from '../dtos/device.dto';
|
import { DeviceDto, DeviceUserPermissionDto } from '../dtos/device.dto';
|
||||||
import { SpaceEntity, SubspaceEntity } from '../../space/entities';
|
import { SpaceEntity, SubspaceEntity, TagEntity } from '../../space/entities';
|
||||||
import { ProductEntity } from '../../product/entities';
|
import { ProductEntity } from '../../product/entities';
|
||||||
import { UserEntity } from '../../user/entities';
|
import { UserEntity } from '../../user/entities';
|
||||||
import { DeviceNotificationDto } from '../dtos';
|
import { DeviceNotificationDto } from '../dtos';
|
||||||
@ -74,6 +75,11 @@ export class DeviceEntity extends AbstractEntity<DeviceDto> {
|
|||||||
@OneToMany(() => SceneDeviceEntity, (sceneDevice) => sceneDevice.device, {})
|
@OneToMany(() => SceneDeviceEntity, (sceneDevice) => sceneDevice.device, {})
|
||||||
sceneDevices: SceneDeviceEntity[];
|
sceneDevices: SceneDeviceEntity[];
|
||||||
|
|
||||||
|
@OneToOne(() => TagEntity, (tag) => tag.device, {
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
tag: TagEntity;
|
||||||
|
|
||||||
constructor(partial: Partial<DeviceEntity>) {
|
constructor(partial: Partial<DeviceEntity>) {
|
||||||
super();
|
super();
|
||||||
Object.assign(this, partial);
|
Object.assign(this, partial);
|
||||||
@ -102,6 +108,7 @@ export class DeviceNotificationEntity extends AbstractEntity<DeviceNotificationD
|
|||||||
nullable: false,
|
nullable: false,
|
||||||
})
|
})
|
||||||
user: UserEntity;
|
user: UserEntity;
|
||||||
|
|
||||||
constructor(partial: Partial<DeviceNotificationEntity>) {
|
constructor(partial: Partial<DeviceNotificationEntity>) {
|
||||||
super();
|
super();
|
||||||
Object.assign(this, partial);
|
Object.assign(this, partial);
|
||||||
|
|||||||
@ -2,8 +2,8 @@ import { Column, Entity, OneToMany } from 'typeorm';
|
|||||||
import { ProductDto } from '../dtos';
|
import { ProductDto } from '../dtos';
|
||||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||||
import { DeviceEntity } from '../../device/entities';
|
import { DeviceEntity } from '../../device/entities';
|
||||||
import { SpaceProductEntity } from '../../space/entities/space-product.entity';
|
import { TagModel } from '../../space-model';
|
||||||
|
import { TagEntity } from '../../space/entities/tag.entity';
|
||||||
@Entity({ name: 'product' })
|
@Entity({ name: 'product' })
|
||||||
export class ProductEntity extends AbstractEntity<ProductDto> {
|
export class ProductEntity extends AbstractEntity<ProductDto> {
|
||||||
@Column({
|
@Column({
|
||||||
@ -27,8 +27,11 @@ export class ProductEntity extends AbstractEntity<ProductDto> {
|
|||||||
})
|
})
|
||||||
public prodType: string;
|
public prodType: string;
|
||||||
|
|
||||||
@OneToMany(() => SpaceProductEntity, (spaceProduct) => spaceProduct.product)
|
@OneToMany(() => TagModel, (tag) => tag.product)
|
||||||
spaceProducts: SpaceProductEntity[];
|
tagModels: TagModel[];
|
||||||
|
|
||||||
|
@OneToMany(() => TagEntity, (tag) => tag.product)
|
||||||
|
tags: TagEntity[];
|
||||||
|
|
||||||
@OneToMany(
|
@OneToMany(
|
||||||
() => DeviceEntity,
|
() => DeviceEntity,
|
||||||
|
|||||||
1
libs/common/src/modules/project/dtos/index.ts
Normal file
1
libs/common/src/modules/project/dtos/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './project.dto';
|
||||||
15
libs/common/src/modules/project/dtos/project.dto.ts
Normal file
15
libs/common/src/modules/project/dtos/project.dto.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class ProjectDto {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
uuid: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
public description?: string;
|
||||||
|
}
|
||||||
1
libs/common/src/modules/project/entities/index.ts
Normal file
1
libs/common/src/modules/project/entities/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './project.entity';
|
||||||
43
libs/common/src/modules/project/entities/project.entity.ts
Normal file
43
libs/common/src/modules/project/entities/project.entity.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { Entity, Column, Unique, OneToMany } from 'typeorm';
|
||||||
|
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||||
|
import { ProjectDto } from '../dtos';
|
||||||
|
import { CommunityEntity } from '../../community/entities';
|
||||||
|
import { SpaceModelEntity } from '../../space-model';
|
||||||
|
import { UserEntity } from '../../user/entities';
|
||||||
|
import { InviteUserEntity } from '../../Invite-user/entities';
|
||||||
|
|
||||||
|
@Entity({ name: 'project' })
|
||||||
|
@Unique(['name'])
|
||||||
|
export class ProjectEntity extends AbstractEntity<ProjectDto> {
|
||||||
|
@Column({
|
||||||
|
type: 'uuid',
|
||||||
|
default: () => 'gen_random_uuid()',
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
public uuid: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
public name: string;
|
||||||
|
|
||||||
|
@Column({ length: 255, nullable: true })
|
||||||
|
description: string;
|
||||||
|
|
||||||
|
@OneToMany(() => SpaceModelEntity, (spaceModel) => spaceModel.project)
|
||||||
|
public spaceModels: SpaceModelEntity[];
|
||||||
|
|
||||||
|
@OneToMany(() => CommunityEntity, (community) => community.project)
|
||||||
|
communities: CommunityEntity[];
|
||||||
|
|
||||||
|
@OneToMany(() => UserEntity, (user) => user.project)
|
||||||
|
public users: UserEntity[];
|
||||||
|
|
||||||
|
@OneToMany(() => InviteUserEntity, (inviteUser) => inviteUser.project)
|
||||||
|
public invitedUsers: InviteUserEntity[];
|
||||||
|
|
||||||
|
constructor(partial: Partial<ProjectEntity>) {
|
||||||
|
super();
|
||||||
|
Object.assign(this, partial);
|
||||||
|
}
|
||||||
|
}
|
||||||
1
libs/common/src/modules/project/index.ts
Normal file
1
libs/common/src/modules/project/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './project.repository.module';
|
||||||
11
libs/common/src/modules/project/project.repository.module.ts
Normal file
11
libs/common/src/modules/project/project.repository.module.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { ProjectEntity } from './entities';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
providers: [],
|
||||||
|
exports: [],
|
||||||
|
controllers: [],
|
||||||
|
imports: [TypeOrmModule.forFeature([ProjectEntity])],
|
||||||
|
})
|
||||||
|
export class ProjectRepositoryModule {}
|
||||||
1
libs/common/src/modules/project/repositiories/index.ts
Normal file
1
libs/common/src/modules/project/repositiories/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './project.repository';
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { DataSource, Repository } from 'typeorm';
|
||||||
|
import { ProjectEntity } from '../entities';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ProjectRepository extends Repository<ProjectEntity> {
|
||||||
|
constructor(private dataSource: DataSource) {
|
||||||
|
super(ProjectEntity, dataSource.createEntityManager());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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);
|
||||||
|
|||||||
@ -44,6 +44,12 @@ export class SceneDeviceEntity extends AbstractEntity<SceneDeviceDto> {
|
|||||||
@JoinColumn({ name: 'scene_uuid' })
|
@JoinColumn({ name: 'scene_uuid' })
|
||||||
scene: SceneEntity;
|
scene: SceneEntity;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
|
public disabled: boolean;
|
||||||
|
|
||||||
constructor(partial: Partial<SceneDeviceEntity>) {
|
constructor(partial: Partial<SceneDeviceEntity>) {
|
||||||
super();
|
super();
|
||||||
Object.assign(this, partial);
|
Object.assign(this, partial);
|
||||||
|
|||||||
@ -59,6 +59,12 @@ export class SceneEntity extends AbstractEntity<SceneDto> {
|
|||||||
@JoinColumn({ name: 'space_uuid' })
|
@JoinColumn({ name: 'space_uuid' })
|
||||||
space: SpaceEntity;
|
space: SpaceEntity;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
|
public disabled: boolean;
|
||||||
|
|
||||||
@ManyToOne(() => SceneIconEntity, (icon) => icon.scenesIconEntity, {
|
@ManyToOne(() => SceneIconEntity, (icon) => icon.scenesIconEntity, {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
})
|
})
|
||||||
|
|||||||
2
libs/common/src/modules/space-model/dtos/index.ts
Normal file
2
libs/common/src/modules/space-model/dtos/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './subspace-model';
|
||||||
|
export * from './space-model.dto';
|
||||||
15
libs/common/src/modules/space-model/dtos/space-model.dto.ts
Normal file
15
libs/common/src/modules/space-model/dtos/space-model.dto.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { IsString, IsNotEmpty } from 'class-validator';
|
||||||
|
|
||||||
|
export class SpaceModelDto {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public uuid: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public spaceModelName: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
projectUuid: string;
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
export * from './subspace-model.dto';
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
import { IsString, IsNotEmpty } from 'class-validator';
|
||||||
|
|
||||||
|
export class SubSpaceModelDto {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public uuid: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public subSpaceModelName: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
spaceModelUuid: string;
|
||||||
|
}
|
||||||
21
libs/common/src/modules/space-model/dtos/tag-model.dto.ts
Normal file
21
libs/common/src/modules/space-model/dtos/tag-model.dto.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class TagModelDto {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public uuid: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public name: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public productUuid: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
spaceModelUuid: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
subspaceModelUuid: string;
|
||||||
|
}
|
||||||
3
libs/common/src/modules/space-model/entities/index.ts
Normal file
3
libs/common/src/modules/space-model/entities/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from './space-model.entity';
|
||||||
|
export * from './subspace-model';
|
||||||
|
export * from './tag-model.entity';
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
import { Entity, Column, OneToMany, ManyToOne, JoinColumn } from 'typeorm';
|
||||||
|
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||||
|
import { SpaceModelDto } from '../dtos';
|
||||||
|
import { SubspaceModelEntity } from './subspace-model';
|
||||||
|
import { ProjectEntity } from '../../project/entities';
|
||||||
|
import { SpaceEntity } from '../../space/entities';
|
||||||
|
import { TagModel } from './tag-model.entity';
|
||||||
|
|
||||||
|
@Entity({ name: 'space-model' })
|
||||||
|
export class SpaceModelEntity extends AbstractEntity<SpaceModelDto> {
|
||||||
|
@Column({
|
||||||
|
type: 'uuid',
|
||||||
|
default: () => 'gen_random_uuid()',
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
public uuid: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
public modelName: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
|
public disabled: boolean;
|
||||||
|
|
||||||
|
@ManyToOne(() => ProjectEntity, (project) => project.spaceModels, {
|
||||||
|
nullable: false,
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
})
|
||||||
|
@JoinColumn({ name: 'project_uuid' })
|
||||||
|
public project: ProjectEntity;
|
||||||
|
|
||||||
|
@OneToMany(
|
||||||
|
() => SubspaceModelEntity,
|
||||||
|
(subspaceModel) => subspaceModel.spaceModel,
|
||||||
|
{
|
||||||
|
cascade: true,
|
||||||
|
nullable: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
public subspaceModels: SubspaceModelEntity[];
|
||||||
|
|
||||||
|
@OneToMany(() => SpaceEntity, (space) => space.spaceModel, {
|
||||||
|
cascade: true,
|
||||||
|
})
|
||||||
|
public spaces: SpaceEntity[];
|
||||||
|
|
||||||
|
@OneToMany(() => TagModel, (tag) => tag.spaceModel)
|
||||||
|
tags: TagModel[];
|
||||||
|
|
||||||
|
constructor(partial: Partial<SpaceModelEntity>) {
|
||||||
|
super();
|
||||||
|
Object.assign(this, partial);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
export * from './subspace-model.entity';
|
||||||
|
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
import { AbstractEntity } from '@app/common/modules/abstract/entities/abstract.entity';
|
||||||
|
import { Column, Entity, ManyToOne, OneToMany, Unique } from 'typeorm';
|
||||||
|
import { SubSpaceModelDto } from '../../dtos';
|
||||||
|
import { SpaceModelEntity } from '../space-model.entity';
|
||||||
|
import { SubspaceEntity } from '@app/common/modules/space/entities';
|
||||||
|
import { TagModel } from '../tag-model.entity';
|
||||||
|
|
||||||
|
@Entity({ name: 'subspace-model' })
|
||||||
|
export class SubspaceModelEntity extends AbstractEntity<SubSpaceModelDto> {
|
||||||
|
@Column({
|
||||||
|
type: 'uuid',
|
||||||
|
default: () => 'gen_random_uuid()',
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
public uuid: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
public subspaceName: string;
|
||||||
|
|
||||||
|
@ManyToOne(
|
||||||
|
() => SpaceModelEntity,
|
||||||
|
(spaceModel) => spaceModel.subspaceModels,
|
||||||
|
{
|
||||||
|
nullable: false,
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
public spaceModel: SpaceModelEntity;
|
||||||
|
|
||||||
|
@OneToMany(() => SubspaceEntity, (subspace) => subspace.subSpaceModel, {
|
||||||
|
cascade: true,
|
||||||
|
})
|
||||||
|
public subspaceModel: SubspaceEntity[];
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
|
public disabled: boolean;
|
||||||
|
|
||||||
|
@OneToMany(() => TagModel, (tag) => tag.subspaceModel)
|
||||||
|
tags: TagModel[];
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
import { Column, Entity, JoinColumn, ManyToOne, OneToMany } from 'typeorm';
|
||||||
|
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||||
|
import { TagModelDto } from '../dtos/tag-model.dto';
|
||||||
|
import { SpaceModelEntity } from './space-model.entity';
|
||||||
|
import { SubspaceModelEntity } from './subspace-model';
|
||||||
|
import { ProductEntity } from '../../product/entities';
|
||||||
|
import { TagEntity } from '../../space/entities/tag.entity';
|
||||||
|
|
||||||
|
@Entity({ name: 'tag_model' })
|
||||||
|
export class TagModel extends AbstractEntity<TagModelDto> {
|
||||||
|
@Column({ type: 'varchar', length: 255 })
|
||||||
|
tag: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => ProductEntity, (product) => product.tagModels, {
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
@JoinColumn({ name: 'product_id' })
|
||||||
|
product: ProductEntity;
|
||||||
|
|
||||||
|
@ManyToOne(() => SpaceModelEntity, (space) => space.tags, { nullable: true })
|
||||||
|
@JoinColumn({ name: 'space_model_id' })
|
||||||
|
spaceModel: SpaceModelEntity;
|
||||||
|
|
||||||
|
@ManyToOne(() => SubspaceModelEntity, (subspace) => subspace.tags, {
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
@JoinColumn({ name: 'subspace_model_id' })
|
||||||
|
subspaceModel: SubspaceModelEntity;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
|
public disabled: boolean;
|
||||||
|
|
||||||
|
@OneToMany(() => TagEntity, (tag) => tag.model)
|
||||||
|
tags: TagEntity[];
|
||||||
|
}
|
||||||
3
libs/common/src/modules/space-model/index.ts
Normal file
3
libs/common/src/modules/space-model/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from './space-model.repository.module';
|
||||||
|
export * from './entities';
|
||||||
|
export * from './repositories';
|
||||||
@ -0,0 +1 @@
|
|||||||
|
export * from './space-model.repository';
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { DataSource, Repository } from 'typeorm';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { SpaceModelEntity, SubspaceModelEntity, TagModel } from '../entities';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SpaceModelRepository extends Repository<SpaceModelEntity> {
|
||||||
|
constructor(private dataSource: DataSource) {
|
||||||
|
super(SpaceModelEntity, dataSource.createEntityManager());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Injectable()
|
||||||
|
export class SubspaceModelRepository extends Repository<SubspaceModelEntity> {
|
||||||
|
constructor(private dataSource: DataSource) {
|
||||||
|
super(SubspaceModelEntity, dataSource.createEntityManager());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TagModelRepository extends Repository<TagModel> {
|
||||||
|
constructor(private dataSource: DataSource) {
|
||||||
|
super(TagModel, dataSource.createEntityManager());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { SpaceModelEntity, SubspaceModelEntity, TagModel } from './entities';
|
||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
providers: [],
|
||||||
|
exports: [],
|
||||||
|
controllers: [],
|
||||||
|
imports: [
|
||||||
|
TypeOrmModule.forFeature([SpaceModelEntity, SubspaceModelEntity, TagModel]),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class SpaceModelRepositoryModule {}
|
||||||
@ -1,2 +1,3 @@
|
|||||||
export * from './space.dto';
|
export * from './space.dto';
|
||||||
export * from './subspace.dto';
|
export * from './subspace.dto';
|
||||||
|
export * from './tag.dto';
|
||||||
|
|||||||
21
libs/common/src/modules/space/dtos/tag.dto.ts
Normal file
21
libs/common/src/modules/space/dtos/tag.dto.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class TagDto {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public uuid: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public name: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public productUuid: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
spaceUuid: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
subspaceUuid: string;
|
||||||
|
}
|
||||||
@ -1,3 +1,4 @@
|
|||||||
export * from './space.entity';
|
export * from './space.entity';
|
||||||
export * from './subspace.entity';
|
export * from './subspace';
|
||||||
export * from './space-link.entity';
|
export * from './space-link.entity';
|
||||||
|
export * from './tag.entity';
|
||||||
|
|||||||
@ -0,0 +1,35 @@
|
|||||||
|
import { Column, Entity, ManyToOne, Unique } from 'typeorm';
|
||||||
|
import { UserSpaceDto } from '../../user/dtos';
|
||||||
|
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||||
|
import { SpaceEntity } from './space.entity';
|
||||||
|
|
||||||
|
@Entity({ name: 'invite-space' })
|
||||||
|
@Unique(['invitationCode'])
|
||||||
|
export class InviteSpaceEntity extends AbstractEntity<UserSpaceDto> {
|
||||||
|
@Column({
|
||||||
|
type: 'uuid',
|
||||||
|
default: () => 'gen_random_uuid()', // Use gen_random_uuid() for default value
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
public uuid: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => SpaceEntity, (space) => space.userSpaces, {
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
space: SpaceEntity;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
public invitationCode: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
default: true,
|
||||||
|
})
|
||||||
|
public isActive: boolean;
|
||||||
|
constructor(partial: Partial<InviteSpaceEntity>) {
|
||||||
|
super();
|
||||||
|
Object.assign(this, partial);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,6 +13,12 @@ export class SpaceLinkEntity extends AbstractEntity {
|
|||||||
@JoinColumn({ name: 'end_space_id' })
|
@JoinColumn({ name: 'end_space_id' })
|
||||||
public endSpace: SpaceEntity;
|
public endSpace: SpaceEntity;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
|
public disabled: boolean;
|
||||||
|
|
||||||
@Column({
|
@Column({
|
||||||
nullable: false,
|
nullable: false,
|
||||||
enum: Object.values(Direction),
|
enum: Object.values(Direction),
|
||||||
|
|||||||
@ -1,32 +0,0 @@
|
|||||||
import { Column, Entity, ManyToOne, JoinColumn } from 'typeorm';
|
|
||||||
import { SpaceEntity } from './space.entity';
|
|
||||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
|
||||||
import { ProductEntity } from '../../product/entities';
|
|
||||||
|
|
||||||
@Entity({ name: 'space-product' })
|
|
||||||
export class SpaceProductEntity extends AbstractEntity<SpaceProductEntity> {
|
|
||||||
@ManyToOne(() => SpaceEntity, (space) => space.spaceProducts, {
|
|
||||||
nullable: false,
|
|
||||||
onDelete: 'CASCADE',
|
|
||||||
})
|
|
||||||
@JoinColumn({ name: 'space_uuid' })
|
|
||||||
space: SpaceEntity;
|
|
||||||
|
|
||||||
@ManyToOne(() => ProductEntity, (product) => product.spaceProducts, {
|
|
||||||
nullable: false,
|
|
||||||
onDelete: 'CASCADE',
|
|
||||||
})
|
|
||||||
@JoinColumn({ name: 'product_uuid' })
|
|
||||||
product: ProductEntity;
|
|
||||||
|
|
||||||
@Column({
|
|
||||||
nullable: false,
|
|
||||||
type: 'int',
|
|
||||||
})
|
|
||||||
productCount: number;
|
|
||||||
|
|
||||||
constructor(partial: Partial<SpaceProductEntity>) {
|
|
||||||
super();
|
|
||||||
Object.assign(this, partial);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,23 +1,17 @@
|
|||||||
import {
|
import { Column, Entity, JoinColumn, ManyToOne, OneToMany } from 'typeorm';
|
||||||
Column,
|
|
||||||
Entity,
|
|
||||||
JoinColumn,
|
|
||||||
ManyToOne,
|
|
||||||
OneToMany,
|
|
||||||
Unique,
|
|
||||||
} from 'typeorm';
|
|
||||||
import { SpaceDto } from '../dtos';
|
import { SpaceDto } from '../dtos';
|
||||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||||
import { UserSpaceEntity } from '../../user/entities';
|
import { UserSpaceEntity } from '../../user/entities';
|
||||||
import { DeviceEntity } from '../../device/entities';
|
import { DeviceEntity } from '../../device/entities';
|
||||||
import { CommunityEntity } from '../../community/entities';
|
import { CommunityEntity } from '../../community/entities';
|
||||||
import { SubspaceEntity } from './subspace.entity';
|
import { SubspaceEntity } from './subspace';
|
||||||
import { SpaceLinkEntity } from './space-link.entity';
|
import { SpaceLinkEntity } from './space-link.entity';
|
||||||
import { SpaceProductEntity } from './space-product.entity';
|
|
||||||
import { SceneEntity } from '../../scene/entities';
|
import { SceneEntity } from '../../scene/entities';
|
||||||
|
import { SpaceModelEntity } from '../../space-model';
|
||||||
|
import { InviteUserSpaceEntity } from '../../Invite-user/entities';
|
||||||
|
import { TagEntity } from './tag.entity';
|
||||||
|
|
||||||
@Entity({ name: 'space' })
|
@Entity({ name: 'space' })
|
||||||
@Unique(['invitationCode'])
|
|
||||||
export class SpaceEntity extends AbstractEntity<SpaceDto> {
|
export class SpaceEntity extends AbstractEntity<SpaceDto> {
|
||||||
@Column({
|
@Column({
|
||||||
type: 'uuid',
|
type: 'uuid',
|
||||||
@ -42,10 +36,6 @@ export class SpaceEntity extends AbstractEntity<SpaceDto> {
|
|||||||
@JoinColumn({ name: 'community_id' })
|
@JoinColumn({ name: 'community_id' })
|
||||||
community: CommunityEntity;
|
community: CommunityEntity;
|
||||||
|
|
||||||
@Column({
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
public invitationCode: string;
|
|
||||||
@ManyToOne(() => SpaceEntity, (space) => space.children, { nullable: true })
|
@ManyToOne(() => SpaceEntity, (space) => space.children, { nullable: true })
|
||||||
parent: SpaceEntity;
|
parent: SpaceEntity;
|
||||||
|
|
||||||
@ -58,6 +48,12 @@ export class SpaceEntity extends AbstractEntity<SpaceDto> {
|
|||||||
@OneToMany(() => UserSpaceEntity, (userSpace) => userSpace.space)
|
@OneToMany(() => UserSpaceEntity, (userSpace) => userSpace.space)
|
||||||
userSpaces: UserSpaceEntity[];
|
userSpaces: UserSpaceEntity[];
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
|
public disabled: boolean;
|
||||||
|
|
||||||
@OneToMany(() => SubspaceEntity, (subspace) => subspace.space, {
|
@OneToMany(() => SubspaceEntity, (subspace) => subspace.space, {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
@ -92,12 +88,23 @@ export class SpaceEntity extends AbstractEntity<SpaceDto> {
|
|||||||
})
|
})
|
||||||
public icon: string;
|
public icon: string;
|
||||||
|
|
||||||
@OneToMany(() => SpaceProductEntity, (spaceProduct) => spaceProduct.space)
|
|
||||||
spaceProducts: SpaceProductEntity[];
|
|
||||||
|
|
||||||
@OneToMany(() => SceneEntity, (scene) => scene.space)
|
@OneToMany(() => SceneEntity, (scene) => scene.space)
|
||||||
scenes: SceneEntity[];
|
scenes: SceneEntity[];
|
||||||
|
|
||||||
|
@ManyToOne(() => SpaceModelEntity, (spaceModel) => spaceModel.spaces, {
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
spaceModel?: SpaceModelEntity;
|
||||||
|
|
||||||
|
@OneToMany(
|
||||||
|
() => InviteUserSpaceEntity,
|
||||||
|
(inviteUserSpace) => inviteUserSpace.space,
|
||||||
|
)
|
||||||
|
invitedUsers: InviteUserSpaceEntity[];
|
||||||
|
|
||||||
|
@OneToMany(() => TagEntity, (tag) => tag.space)
|
||||||
|
tags: TagEntity[];
|
||||||
|
|
||||||
constructor(partial: Partial<SpaceEntity>) {
|
constructor(partial: Partial<SpaceEntity>) {
|
||||||
super();
|
super();
|
||||||
Object.assign(this, partial);
|
Object.assign(this, partial);
|
||||||
|
|||||||
@ -1,37 +0,0 @@
|
|||||||
import { Column, Entity, JoinColumn, ManyToOne, OneToMany } from 'typeorm';
|
|
||||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
|
||||||
import { DeviceEntity } from '../../device/entities';
|
|
||||||
import { SpaceEntity } from './space.entity';
|
|
||||||
import { SubspaceDto } from '../dtos';
|
|
||||||
|
|
||||||
@Entity({ name: 'subspace' })
|
|
||||||
export class SubspaceEntity extends AbstractEntity<SubspaceDto> {
|
|
||||||
@Column({
|
|
||||||
type: 'uuid',
|
|
||||||
default: () => 'gen_random_uuid()',
|
|
||||||
nullable: false,
|
|
||||||
})
|
|
||||||
public uuid: string;
|
|
||||||
|
|
||||||
@Column({
|
|
||||||
nullable: false,
|
|
||||||
})
|
|
||||||
public subspaceName: string;
|
|
||||||
|
|
||||||
@ManyToOne(() => SpaceEntity, (space) => space.subspaces, {
|
|
||||||
nullable: false,
|
|
||||||
onDelete: 'CASCADE',
|
|
||||||
})
|
|
||||||
@JoinColumn({ name: 'space_id' })
|
|
||||||
space: SpaceEntity;
|
|
||||||
|
|
||||||
@OneToMany(() => DeviceEntity, (device) => device.subspace, {
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
devices: DeviceEntity[];
|
|
||||||
|
|
||||||
constructor(partial: Partial<SubspaceEntity>) {
|
|
||||||
super();
|
|
||||||
Object.assign(this, partial);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1
libs/common/src/modules/space/entities/subspace/index.ts
Normal file
1
libs/common/src/modules/space/entities/subspace/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './subspace.entity';
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
import { AbstractEntity } from '@app/common/modules/abstract/entities/abstract.entity';
|
||||||
|
import { DeviceEntity } from '@app/common/modules/device/entities';
|
||||||
|
import { SubspaceModelEntity } from '@app/common/modules/space-model';
|
||||||
|
import { Column, Entity, JoinColumn, ManyToOne, OneToMany } from 'typeorm';
|
||||||
|
import { SubspaceDto } from '../../dtos';
|
||||||
|
import { SpaceEntity } from '../space.entity';
|
||||||
|
import { TagEntity } from '../tag.entity';
|
||||||
|
|
||||||
|
@Entity({ name: 'subspace' })
|
||||||
|
export class SubspaceEntity extends AbstractEntity<SubspaceDto> {
|
||||||
|
@Column({
|
||||||
|
type: 'uuid',
|
||||||
|
default: () => 'gen_random_uuid()',
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
public uuid: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
public subspaceName: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => SpaceEntity, (space) => space.subspaces, {
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
@JoinColumn({ name: 'space_uuid' })
|
||||||
|
space: SpaceEntity;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
|
public disabled: boolean;
|
||||||
|
|
||||||
|
@OneToMany(() => DeviceEntity, (device) => device.subspace, {
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
devices: DeviceEntity[];
|
||||||
|
|
||||||
|
@ManyToOne(() => SubspaceModelEntity, (subspace) => subspace.subspaceModel, {
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
subSpaceModel?: SubspaceModelEntity;
|
||||||
|
|
||||||
|
@OneToMany(() => TagEntity, (tag) => tag.subspace)
|
||||||
|
tags: TagEntity[];
|
||||||
|
|
||||||
|
constructor(partial: Partial<SubspaceEntity>) {
|
||||||
|
super();
|
||||||
|
Object.assign(this, partial);
|
||||||
|
}
|
||||||
|
}
|
||||||
45
libs/common/src/modules/space/entities/tag.entity.ts
Normal file
45
libs/common/src/modules/space/entities/tag.entity.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { Entity, Column, ManyToOne, JoinColumn, OneToOne } from 'typeorm';
|
||||||
|
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||||
|
import { ProductEntity } from '../../product/entities';
|
||||||
|
import { TagDto } from '../dtos';
|
||||||
|
import { TagModel } from '../../space-model/entities/tag-model.entity';
|
||||||
|
import { SpaceEntity } from './space.entity';
|
||||||
|
import { SubspaceEntity } from './subspace';
|
||||||
|
import { DeviceEntity } from '../../device/entities';
|
||||||
|
|
||||||
|
@Entity({ name: 'tag' })
|
||||||
|
export class TagEntity extends AbstractEntity<TagDto> {
|
||||||
|
@Column({ type: 'varchar', length: 255 })
|
||||||
|
tag: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => TagModel, (model) => model.tags, {
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
model: TagModel;
|
||||||
|
|
||||||
|
@ManyToOne(() => ProductEntity, (product) => product.tags, {
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
product: ProductEntity;
|
||||||
|
|
||||||
|
@ManyToOne(() => SpaceEntity, (space) => space.tags, { nullable: true })
|
||||||
|
space: SpaceEntity;
|
||||||
|
|
||||||
|
@ManyToOne(() => SubspaceEntity, (subspace) => subspace.tags, {
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
@JoinColumn({ name: 'subspace_id' })
|
||||||
|
subspace: SubspaceEntity;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
|
public disabled: boolean;
|
||||||
|
|
||||||
|
@OneToOne(() => DeviceEntity, (device) => device.tag, {
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
@JoinColumn({ name: 'device_id' })
|
||||||
|
device: DeviceEntity;
|
||||||
|
}
|
||||||
4
libs/common/src/modules/space/index.ts
Normal file
4
libs/common/src/modules/space/index.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export * from './dtos';
|
||||||
|
export * from './entities';
|
||||||
|
export * from './repositories';
|
||||||
|
export * from './space.repository.module';
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { DataSource, Repository } from 'typeorm';
|
import { DataSource, Repository } from 'typeorm';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { SpaceProductEntity } from '../entities/space-product.entity';
|
import { SpaceEntity, SpaceLinkEntity, TagEntity } from '../entities';
|
||||||
import { SpaceEntity, SpaceLinkEntity, SubspaceEntity } from '../entities';
|
import { InviteSpaceEntity } from '../entities/invite-space.entity';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SpaceRepository extends Repository<SpaceEntity> {
|
export class SpaceRepository extends Repository<SpaceEntity> {
|
||||||
@ -9,12 +9,6 @@ export class SpaceRepository extends Repository<SpaceEntity> {
|
|||||||
super(SpaceEntity, dataSource.createEntityManager());
|
super(SpaceEntity, dataSource.createEntityManager());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Injectable()
|
|
||||||
export class SubspaceRepository extends Repository<SubspaceEntity> {
|
|
||||||
constructor(private dataSource: DataSource) {
|
|
||||||
super(SubspaceEntity, dataSource.createEntityManager());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SpaceLinkRepository extends Repository<SpaceLinkEntity> {
|
export class SpaceLinkRepository extends Repository<SpaceLinkEntity> {
|
||||||
@ -22,9 +16,17 @@ export class SpaceLinkRepository extends Repository<SpaceLinkEntity> {
|
|||||||
super(SpaceLinkEntity, dataSource.createEntityManager());
|
super(SpaceLinkEntity, dataSource.createEntityManager());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SpaceProductRepository extends Repository<SpaceProductEntity> {
|
export class TagRepository extends Repository<TagEntity> {
|
||||||
constructor(private dataSource: DataSource) {
|
constructor(private dataSource: DataSource) {
|
||||||
super(SpaceProductEntity, dataSource.createEntityManager());
|
super(TagEntity, dataSource.createEntityManager());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class InviteSpaceRepository extends Repository<InviteSpaceEntity> {
|
||||||
|
constructor(private dataSource: DataSource) {
|
||||||
|
super(InviteSpaceEntity, dataSource.createEntityManager());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { DataSource, Repository } from 'typeorm';
|
||||||
|
import { SubspaceEntity } from '../entities';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SubspaceRepository extends Repository<SubspaceEntity> {
|
||||||
|
constructor(private dataSource: DataSource) {
|
||||||
|
super(SubspaceEntity, dataSource.createEntityManager());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,11 +1,19 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { SpaceEntity, SubspaceEntity } from './entities';
|
import { SpaceEntity, SubspaceEntity, TagEntity } from './entities';
|
||||||
|
import { InviteSpaceEntity } from './entities/invite-space.entity';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
providers: [],
|
providers: [],
|
||||||
exports: [],
|
exports: [],
|
||||||
controllers: [],
|
controllers: [],
|
||||||
imports: [TypeOrmModule.forFeature([SpaceEntity, SubspaceEntity])],
|
imports: [
|
||||||
|
TypeOrmModule.forFeature([
|
||||||
|
SpaceEntity,
|
||||||
|
SubspaceEntity,
|
||||||
|
TagEntity,
|
||||||
|
InviteSpaceEntity,
|
||||||
|
]),
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class SpaceRepositoryModule {}
|
export class SpaceRepositoryModule {}
|
||||||
|
|||||||
@ -58,20 +58,6 @@ export class UserOtpDto {
|
|||||||
public expiryTime: string;
|
public expiryTime: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UserRoleDto {
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public uuid: string;
|
|
||||||
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public userUuid: string;
|
|
||||||
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public roleTypeUuid: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class UserSpaceDto {
|
export class UserSpaceDto {
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
|
|||||||
@ -2,15 +2,16 @@ import {
|
|||||||
Column,
|
Column,
|
||||||
DeleteDateColumn,
|
DeleteDateColumn,
|
||||||
Entity,
|
Entity,
|
||||||
|
JoinColumn,
|
||||||
ManyToOne,
|
ManyToOne,
|
||||||
OneToMany,
|
OneToMany,
|
||||||
|
OneToOne,
|
||||||
Unique,
|
Unique,
|
||||||
} from 'typeorm';
|
} from 'typeorm';
|
||||||
import {
|
import {
|
||||||
UserDto,
|
UserDto,
|
||||||
UserNotificationDto,
|
UserNotificationDto,
|
||||||
UserOtpDto,
|
UserOtpDto,
|
||||||
UserRoleDto,
|
|
||||||
UserSpaceDto,
|
UserSpaceDto,
|
||||||
} from '../dtos';
|
} from '../dtos';
|
||||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
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 { RoleTypeEntity } from '../../role-type/entities';
|
||||||
import { SpaceEntity } from '../../space/entities';
|
import { SpaceEntity } from '../../space/entities';
|
||||||
import { VisitorPasswordEntity } from '../../visitor-password/entities';
|
import { VisitorPasswordEntity } from '../../visitor-password/entities';
|
||||||
|
import { InviteUserEntity } from '../../Invite-user/entities';
|
||||||
|
import { ProjectEntity } from '../../project/entities';
|
||||||
|
|
||||||
@Entity({ name: 'user' })
|
@Entity({ name: 'user' })
|
||||||
export class UserEntity extends AbstractEntity<UserDto> {
|
export class UserEntity extends AbstractEntity<UserDto> {
|
||||||
@ -79,6 +82,18 @@ export class UserEntity extends AbstractEntity<UserDto> {
|
|||||||
})
|
})
|
||||||
public isActive: boolean;
|
public isActive: boolean;
|
||||||
|
|
||||||
|
@Column({ default: false })
|
||||||
|
hasAcceptedWebAgreement: boolean;
|
||||||
|
|
||||||
|
@Column({ default: false })
|
||||||
|
hasAcceptedAppAgreement: boolean;
|
||||||
|
|
||||||
|
@Column({ type: 'timestamp', nullable: true })
|
||||||
|
webAgreementAcceptedAt: Date;
|
||||||
|
|
||||||
|
@Column({ type: 'timestamp', nullable: true })
|
||||||
|
appAgreementAcceptedAt: Date;
|
||||||
|
|
||||||
@OneToMany(() => UserSpaceEntity, (userSpace) => userSpace.user)
|
@OneToMany(() => UserSpaceEntity, (userSpace) => userSpace.user)
|
||||||
userSpaces: UserSpaceEntity[];
|
userSpaces: UserSpaceEntity[];
|
||||||
|
|
||||||
@ -100,10 +115,7 @@ export class UserEntity extends AbstractEntity<UserDto> {
|
|||||||
(deviceUserNotification) => deviceUserNotification.user,
|
(deviceUserNotification) => deviceUserNotification.user,
|
||||||
)
|
)
|
||||||
deviceUserNotification: DeviceNotificationEntity[];
|
deviceUserNotification: DeviceNotificationEntity[];
|
||||||
@OneToMany(() => UserRoleEntity, (role) => role.user, {
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
roles: UserRoleEntity[];
|
|
||||||
@ManyToOne(() => RegionEntity, (region) => region.users, { nullable: true })
|
@ManyToOne(() => RegionEntity, (region) => region.users, { nullable: true })
|
||||||
region: RegionEntity;
|
region: RegionEntity;
|
||||||
@ManyToOne(() => TimeZoneEntity, (timezone) => timezone.users, {
|
@ManyToOne(() => TimeZoneEntity, (timezone) => timezone.users, {
|
||||||
@ -116,6 +128,21 @@ export class UserEntity extends AbstractEntity<UserDto> {
|
|||||||
)
|
)
|
||||||
public visitorPasswords: VisitorPasswordEntity[];
|
public visitorPasswords: VisitorPasswordEntity[];
|
||||||
|
|
||||||
|
@ManyToOne(() => RoleTypeEntity, (roleType) => roleType.users, {
|
||||||
|
nullable: false,
|
||||||
|
})
|
||||||
|
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>) {
|
constructor(partial: Partial<UserEntity>) {
|
||||||
super();
|
super();
|
||||||
Object.assign(this, partial);
|
Object.assign(this, partial);
|
||||||
@ -125,7 +152,7 @@ export class UserEntity extends AbstractEntity<UserDto> {
|
|||||||
@Entity({ name: 'user-notification' })
|
@Entity({ name: 'user-notification' })
|
||||||
@Unique(['user', 'subscriptionUuid'])
|
@Unique(['user', 'subscriptionUuid'])
|
||||||
export class UserNotificationEntity extends AbstractEntity<UserNotificationDto> {
|
export class UserNotificationEntity extends AbstractEntity<UserNotificationDto> {
|
||||||
@ManyToOne(() => UserEntity, (user) => user.roles, {
|
@ManyToOne(() => UserEntity, (user) => user.roleType, {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
})
|
})
|
||||||
user: UserEntity;
|
user: UserEntity;
|
||||||
@ -178,25 +205,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' })
|
@Entity({ name: 'user-space' })
|
||||||
@Unique(['user', 'space'])
|
@Unique(['user', 'space'])
|
||||||
export class UserSpaceEntity extends AbstractEntity<UserSpaceDto> {
|
export class UserSpaceEntity extends AbstractEntity<UserSpaceDto> {
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import {
|
|||||||
UserEntity,
|
UserEntity,
|
||||||
UserNotificationEntity,
|
UserNotificationEntity,
|
||||||
UserOtpEntity,
|
UserOtpEntity,
|
||||||
UserRoleEntity,
|
|
||||||
UserSpaceEntity,
|
UserSpaceEntity,
|
||||||
} from '../entities/';
|
} 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()
|
@Injectable()
|
||||||
export class UserSpaceRepository extends Repository<UserSpaceEntity> {
|
export class UserSpaceRepository extends Repository<UserSpaceEntity> {
|
||||||
constructor(private dataSource: DataSource) {
|
constructor(private dataSource: DataSource) {
|
||||||
|
|||||||
@ -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,
|
||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -10,7 +10,6 @@ import { RoleTypeSeeder } from './services/role.type.seeder';
|
|||||||
import { SpaceRepositoryModule } from '../modules/space/space.repository.module';
|
import { SpaceRepositoryModule } from '../modules/space/space.repository.module';
|
||||||
import { SuperAdminSeeder } from './services/supper.admin.seeder';
|
import { SuperAdminSeeder } from './services/supper.admin.seeder';
|
||||||
import { UserRepository } from '../modules/user/repositories';
|
import { UserRepository } from '../modules/user/repositories';
|
||||||
import { UserRoleRepository } from '../modules/user/repositories';
|
|
||||||
import { UserRepositoryModule } from '../modules/user/user.repository.module';
|
import { UserRepositoryModule } from '../modules/user/user.repository.module';
|
||||||
import { RegionSeeder } from './services/regions.seeder';
|
import { RegionSeeder } from './services/regions.seeder';
|
||||||
import { RegionRepository } from '../modules/region/repositories';
|
import { RegionRepository } from '../modules/region/repositories';
|
||||||
@ -28,7 +27,6 @@ import { SceneIconRepository } from '../modules/scene/repositories';
|
|||||||
RoleTypeRepository,
|
RoleTypeRepository,
|
||||||
SuperAdminSeeder,
|
SuperAdminSeeder,
|
||||||
UserRepository,
|
UserRepository,
|
||||||
UserRoleRepository,
|
|
||||||
RegionSeeder,
|
RegionSeeder,
|
||||||
RegionRepository,
|
RegionRepository,
|
||||||
TimeZoneSeeder,
|
TimeZoneSeeder,
|
||||||
|
|||||||
@ -19,7 +19,12 @@ export class RoleTypeSeeder {
|
|||||||
if (!roleTypeNames.includes(RoleType.ADMIN)) {
|
if (!roleTypeNames.includes(RoleType.ADMIN)) {
|
||||||
missingRoleTypes.push(RoleType.ADMIN);
|
missingRoleTypes.push(RoleType.ADMIN);
|
||||||
}
|
}
|
||||||
|
if (!roleTypeNames.includes(RoleType.SPACE_OWNER)) {
|
||||||
|
missingRoleTypes.push(RoleType.SPACE_OWNER);
|
||||||
|
}
|
||||||
|
if (!roleTypeNames.includes(RoleType.SPACE_MEMBER)) {
|
||||||
|
missingRoleTypes.push(RoleType.SPACE_MEMBER);
|
||||||
|
}
|
||||||
if (missingRoleTypes.length > 0) {
|
if (missingRoleTypes.length > 0) {
|
||||||
await this.addRoleTypeData(missingRoleTypes);
|
await this.addRoleTypeData(missingRoleTypes);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { UserRepository } from '@app/common/modules/user/repositories';
|
import { UserRepository } from '@app/common/modules/user/repositories';
|
||||||
import { RoleType } from '@app/common/constants/role.type.enum';
|
import { RoleType } from '@app/common/constants/role.type.enum';
|
||||||
import { UserRoleRepository } from '@app/common/modules/user/repositories';
|
|
||||||
import { RoleTypeRepository } from '@app/common/modules/role-type/repositories';
|
import { RoleTypeRepository } from '@app/common/modules/role-type/repositories';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { HelperHashService } from '../../helper/services';
|
import { HelperHashService } from '../../helper/services';
|
||||||
@ -11,19 +10,23 @@ export class SuperAdminSeeder {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly configService: ConfigService,
|
private readonly configService: ConfigService,
|
||||||
private readonly userRepository: UserRepository,
|
private readonly userRepository: UserRepository,
|
||||||
private readonly userRoleRepository: UserRoleRepository,
|
|
||||||
private readonly roleTypeRepository: RoleTypeRepository,
|
private readonly roleTypeRepository: RoleTypeRepository,
|
||||||
private readonly helperHashService: HelperHashService,
|
private readonly helperHashService: HelperHashService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async createSuperAdminIfNotFound(): Promise<void> {
|
async createSuperAdminIfNotFound(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const superAdminData = await this.userRoleRepository.find({
|
const superAdmin = await this.userRepository.findOne({
|
||||||
where: { roleType: { type: RoleType.SUPER_ADMIN } },
|
where: {
|
||||||
|
roleType: { type: RoleType.SUPER_ADMIN },
|
||||||
|
email: this.configService.get<string>(
|
||||||
|
'super-admin.SUPER_ADMIN_EMAIL',
|
||||||
|
),
|
||||||
|
},
|
||||||
relations: ['roleType'],
|
relations: ['roleType'],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (superAdminData.length <= 0) {
|
if (!superAdmin) {
|
||||||
// Create the super admin user if not found
|
// Create the super admin user if not found
|
||||||
console.log('Creating super admin user...');
|
console.log('Creating super admin user...');
|
||||||
|
|
||||||
@ -48,20 +51,16 @@ export class SuperAdminSeeder {
|
|||||||
salt,
|
salt,
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
const user = await this.userRepository.save({
|
const defaultUserRoleUuid = await this.getRoleUuidByRoleType(
|
||||||
|
RoleType.SUPER_ADMIN,
|
||||||
|
);
|
||||||
|
await this.userRepository.save({
|
||||||
email: this.configService.get<string>('super-admin.SUPER_ADMIN_EMAIL'),
|
email: this.configService.get<string>('super-admin.SUPER_ADMIN_EMAIL'),
|
||||||
password: hashedPassword,
|
password: hashedPassword,
|
||||||
firstName: 'Super',
|
firstName: 'Super',
|
||||||
lastName: 'Admin',
|
lastName: 'Admin',
|
||||||
isUserVerified: true,
|
isUserVerified: true,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
});
|
|
||||||
const defaultUserRoleUuid = await this.getRoleUuidByRoleType(
|
|
||||||
RoleType.SUPER_ADMIN,
|
|
||||||
);
|
|
||||||
|
|
||||||
await this.userRoleRepository.save({
|
|
||||||
user: { uuid: user.uuid },
|
|
||||||
roleType: { uuid: defaultUserRoleUuid },
|
roleType: { uuid: defaultUserRoleUuid },
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@ -16,6 +16,20 @@ const mappingInclude: { [key: string]: any } = {
|
|||||||
subspace: {
|
subspace: {
|
||||||
subspace: true,
|
subspace: true,
|
||||||
},
|
},
|
||||||
|
project: {
|
||||||
|
project: true,
|
||||||
|
},
|
||||||
|
'space-model': {
|
||||||
|
subspaceModels: 'subspace-model',
|
||||||
|
tags: 'tag_model',
|
||||||
|
},
|
||||||
|
'subspace-model': {
|
||||||
|
tags: 'tag_model',
|
||||||
|
},
|
||||||
|
tag_model: {
|
||||||
|
tag_model: true,
|
||||||
|
product: true,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export function buildTypeORMIncludeQuery(
|
export function buildTypeORMIncludeQuery(
|
||||||
@ -27,17 +41,33 @@ export function buildTypeORMIncludeQuery(
|
|||||||
const fieldsToInclude: string[] = includeParam.split(',');
|
const fieldsToInclude: string[] = includeParam.split(',');
|
||||||
|
|
||||||
fieldsToInclude.forEach((field: string) => {
|
fieldsToInclude.forEach((field: string) => {
|
||||||
if (mappingInclude[field]) {
|
const nestedFields = field.split('.');
|
||||||
relations.push(field); // Push mapped field
|
let currentModelName = modelName;
|
||||||
} else {
|
let isValid = true;
|
||||||
console.warn(
|
|
||||||
`Field ${field} not found in mappingInclude for ${modelName}`,
|
nestedFields.forEach((nestedField, index) => {
|
||||||
);
|
const currentMapping = mappingInclude[currentModelName];
|
||||||
|
if (currentMapping?.[nestedField]) {
|
||||||
|
currentModelName =
|
||||||
|
typeof currentMapping[nestedField] === 'string'
|
||||||
|
? currentMapping[nestedField]
|
||||||
|
: currentModelName;
|
||||||
|
} else {
|
||||||
|
console.warn(
|
||||||
|
`Field "${nestedFields.slice(0, index + 1).join('.')}" not found in mappingInclude for model "${currentModelName}"`,
|
||||||
|
);
|
||||||
|
isValid = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isValid) {
|
||||||
|
relations.push(field);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return relations;
|
return relations.length ? relations : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined; // If no includes, return undefined
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import * as nodemailer from 'nodemailer';
|
import * as nodemailer from 'nodemailer';
|
||||||
|
import axios from 'axios';
|
||||||
|
import {
|
||||||
|
SEND_EMAIL_API_URL_DEV,
|
||||||
|
SEND_EMAIL_API_URL_PROD,
|
||||||
|
} from '../constants/mail-trap';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class EmailService {
|
export class EmailService {
|
||||||
@ -35,4 +40,180 @@ export class EmailService {
|
|||||||
|
|
||||||
await transporter.sendMail(mailOptions);
|
await transporter.sendMail(mailOptions);
|
||||||
}
|
}
|
||||||
|
async sendEmailWithInvitationTemplate(
|
||||||
|
email: string,
|
||||||
|
emailInvitationData: any,
|
||||||
|
): Promise<void> {
|
||||||
|
const isProduction = process.env.NODE_ENV === 'production';
|
||||||
|
const API_TOKEN = this.configService.get<string>(
|
||||||
|
'email-config.MAILTRAP_API_TOKEN',
|
||||||
|
);
|
||||||
|
const API_URL = isProduction
|
||||||
|
? SEND_EMAIL_API_URL_PROD
|
||||||
|
: SEND_EMAIL_API_URL_DEV;
|
||||||
|
const TEMPLATE_UUID = this.configService.get<string>(
|
||||||
|
'email-config.MAILTRAP_INVITATION_TEMPLATE_UUID',
|
||||||
|
);
|
||||||
|
|
||||||
|
const emailData = {
|
||||||
|
from: {
|
||||||
|
email: this.smtpConfig.sender,
|
||||||
|
},
|
||||||
|
to: [
|
||||||
|
{
|
||||||
|
email: email,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
template_uuid: TEMPLATE_UUID,
|
||||||
|
template_variables: emailInvitationData,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await axios.post(API_URL, emailData, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${API_TOKEN}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException(
|
||||||
|
error.response?.data?.message ||
|
||||||
|
'Error sending email using Mailtrap template',
|
||||||
|
error.response?.status || HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async sendEmailWithTemplate(
|
||||||
|
email: string,
|
||||||
|
name: string,
|
||||||
|
isEnable: boolean,
|
||||||
|
isDelete: boolean,
|
||||||
|
): Promise<void> {
|
||||||
|
const isProduction = process.env.NODE_ENV === 'production';
|
||||||
|
const API_TOKEN = this.configService.get<string>(
|
||||||
|
'email-config.MAILTRAP_API_TOKEN',
|
||||||
|
);
|
||||||
|
const API_URL = isProduction
|
||||||
|
? SEND_EMAIL_API_URL_PROD
|
||||||
|
: SEND_EMAIL_API_URL_DEV;
|
||||||
|
|
||||||
|
// Determine the template UUID based on the arguments
|
||||||
|
const templateUuid = isDelete
|
||||||
|
? this.configService.get<string>(
|
||||||
|
'email-config.MAILTRAP_DELETE_USER_TEMPLATE_UUID',
|
||||||
|
)
|
||||||
|
: this.configService.get<string>(
|
||||||
|
isEnable
|
||||||
|
? 'email-config.MAILTRAP_ENABLE_TEMPLATE_UUID'
|
||||||
|
: 'email-config.MAILTRAP_DISABLE_TEMPLATE_UUID',
|
||||||
|
);
|
||||||
|
|
||||||
|
const emailData = {
|
||||||
|
from: {
|
||||||
|
email: this.smtpConfig.sender,
|
||||||
|
},
|
||||||
|
to: [
|
||||||
|
{
|
||||||
|
email,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
template_uuid: templateUuid,
|
||||||
|
template_variables: {
|
||||||
|
name,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await axios.post(API_URL, emailData, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${API_TOKEN}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException(
|
||||||
|
error.response?.data?.message ||
|
||||||
|
'Error sending email using Mailtrap template',
|
||||||
|
error.response?.status || HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async sendEditUserEmailWithTemplate(
|
||||||
|
email: string,
|
||||||
|
emailEditData: any,
|
||||||
|
): Promise<void> {
|
||||||
|
const isProduction = process.env.NODE_ENV === 'production';
|
||||||
|
const API_TOKEN = this.configService.get<string>(
|
||||||
|
'email-config.MAILTRAP_API_TOKEN',
|
||||||
|
);
|
||||||
|
const API_URL = isProduction
|
||||||
|
? SEND_EMAIL_API_URL_PROD
|
||||||
|
: SEND_EMAIL_API_URL_DEV;
|
||||||
|
const TEMPLATE_UUID = this.configService.get<string>(
|
||||||
|
'email-config.MAILTRAP_EDIT_USER_TEMPLATE_UUID',
|
||||||
|
);
|
||||||
|
|
||||||
|
const emailData = {
|
||||||
|
from: {
|
||||||
|
email: this.smtpConfig.sender,
|
||||||
|
},
|
||||||
|
to: [
|
||||||
|
{
|
||||||
|
email: email,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
template_uuid: TEMPLATE_UUID,
|
||||||
|
template_variables: emailEditData,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await axios.post(API_URL, emailData, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${API_TOKEN}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException(
|
||||||
|
error.response?.data?.message ||
|
||||||
|
'Error sending email using Mailtrap template',
|
||||||
|
error.response?.status || HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
generateUserChangesEmailBody(
|
||||||
|
addedSpaceNames: string[],
|
||||||
|
removedSpaceNames: string[],
|
||||||
|
oldRole: string,
|
||||||
|
newRole: string,
|
||||||
|
oldName: string,
|
||||||
|
newName: string,
|
||||||
|
) {
|
||||||
|
const addedSpaceNamesChanged =
|
||||||
|
addedSpaceNames.length > 0
|
||||||
|
? `Access to the following spaces were added: ${addedSpaceNames.join(', ')}`
|
||||||
|
: '';
|
||||||
|
|
||||||
|
const removedSpaceNamesChanged =
|
||||||
|
removedSpaceNames.length > 0
|
||||||
|
? `Access to the following spaces were deleted: ${removedSpaceNames.join(', ')}`
|
||||||
|
: '';
|
||||||
|
|
||||||
|
const roleChanged =
|
||||||
|
oldRole !== newRole
|
||||||
|
? `Your user role has been changed from [${oldRole}] to [${newRole}]`
|
||||||
|
: '';
|
||||||
|
|
||||||
|
const nameChanged =
|
||||||
|
oldName !== newName
|
||||||
|
? `The name associated with your account has changed from [${oldName}] to [${newName}]`
|
||||||
|
: '';
|
||||||
|
|
||||||
|
return {
|
||||||
|
addedSpaceNamesChanged,
|
||||||
|
removedSpaceNamesChanged,
|
||||||
|
roleChanged,
|
||||||
|
nameChanged,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1675
package-lock.json
generated
1675
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -23,6 +23,7 @@
|
|||||||
"@nestjs/common": "^10.0.0",
|
"@nestjs/common": "^10.0.0",
|
||||||
"@nestjs/config": "^3.2.0",
|
"@nestjs/config": "^3.2.0",
|
||||||
"@nestjs/core": "^10.0.0",
|
"@nestjs/core": "^10.0.0",
|
||||||
|
"@nestjs/cqrs": "^10.2.8",
|
||||||
"@nestjs/jwt": "^10.2.0",
|
"@nestjs/jwt": "^10.2.0",
|
||||||
"@nestjs/passport": "^10.0.3",
|
"@nestjs/passport": "^10.0.3",
|
||||||
"@nestjs/platform-express": "^10.0.0",
|
"@nestjs/platform-express": "^10.0.0",
|
||||||
@ -66,6 +67,7 @@
|
|||||||
"concurrently": "^8.2.2",
|
"concurrently": "^8.2.2",
|
||||||
"eslint": "^8.42.0",
|
"eslint": "^8.42.0",
|
||||||
"eslint-config-prettier": "^9.0.0",
|
"eslint-config-prettier": "^9.0.0",
|
||||||
|
"eslint-plugin-import": "^2.31.0",
|
||||||
"eslint-plugin-prettier": "^5.0.0",
|
"eslint-plugin-prettier": "^5.0.0",
|
||||||
"jest": "^29.5.0",
|
"jest": "^29.5.0",
|
||||||
"prettier": "^3.0.0",
|
"prettier": "^3.0.0",
|
||||||
|
|||||||
@ -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';
|
||||||
@ -22,6 +21,13 @@ import { VisitorPasswordModule } from './vistor-password/visitor-password.module
|
|||||||
import { ScheduleModule } from './schedule/schedule.module';
|
import { ScheduleModule } from './schedule/schedule.module';
|
||||||
import { SpaceModule } from './space/space.module';
|
import { SpaceModule } from './space/space.module';
|
||||||
import { ProductModule } from './product';
|
import { ProductModule } from './product';
|
||||||
|
import { ProjectModule } from './project';
|
||||||
|
import { SpaceModelModule } from './space-model';
|
||||||
|
import { InviteUserModule } from './invite-user/invite-user.module';
|
||||||
|
import { PermissionModule } from './permission/permission.module';
|
||||||
|
import { RoleModule } from './role/role.module';
|
||||||
|
import { TermsConditionsModule } from './terms-conditions/terms-conditions.module';
|
||||||
|
import { PrivacyPolicyModule } from './privacy-policy/privacy-policy.module';
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
ConfigModule.forRoot({
|
ConfigModule.forRoot({
|
||||||
@ -29,11 +35,11 @@ import { ProductModule } from './product';
|
|||||||
}),
|
}),
|
||||||
AuthenticationModule,
|
AuthenticationModule,
|
||||||
UserModule,
|
UserModule,
|
||||||
RoleModule,
|
InviteUserModule,
|
||||||
CommunityModule,
|
CommunityModule,
|
||||||
|
|
||||||
SpaceModule,
|
SpaceModule,
|
||||||
|
SpaceModelModule,
|
||||||
GroupModule,
|
GroupModule,
|
||||||
DeviceModule,
|
DeviceModule,
|
||||||
DeviceMessagesSubscriptionModule,
|
DeviceMessagesSubscriptionModule,
|
||||||
@ -48,6 +54,11 @@ import { ProductModule } from './product';
|
|||||||
VisitorPasswordModule,
|
VisitorPasswordModule,
|
||||||
ScheduleModule,
|
ScheduleModule,
|
||||||
ProductModule,
|
ProductModule,
|
||||||
|
ProjectModule,
|
||||||
|
PermissionModule,
|
||||||
|
RoleModule,
|
||||||
|
TermsConditionsModule,
|
||||||
|
PrivacyPolicyModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -6,11 +6,9 @@ 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';
|
||||||
|
import { RoleService } from 'src/role/services';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [ConfigModule, UserRepositoryModule, CommonModule],
|
imports: [ConfigModule, UserRepositoryModule, CommonModule],
|
||||||
@ -20,8 +18,8 @@ import { RoleTypeRepository } from '@app/common/modules/role-type/repositories';
|
|||||||
UserRepository,
|
UserRepository,
|
||||||
UserSessionRepository,
|
UserSessionRepository,
|
||||||
UserOtpRepository,
|
UserOtpRepository,
|
||||||
UserRoleRepository,
|
|
||||||
RoleTypeRepository,
|
RoleTypeRepository,
|
||||||
|
RoleService,
|
||||||
],
|
],
|
||||||
exports: [UserAuthService],
|
exports: [UserAuthService],
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,5 +1,11 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { IsEmail, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
import {
|
||||||
|
IsBoolean,
|
||||||
|
IsEmail,
|
||||||
|
IsNotEmpty,
|
||||||
|
IsOptional,
|
||||||
|
IsString,
|
||||||
|
} from 'class-validator';
|
||||||
import { IsPasswordStrong } from 'src/validators/password.validator';
|
import { IsPasswordStrong } from 'src/validators/password.validator';
|
||||||
|
|
||||||
export class UserSignUpDto {
|
export class UserSignUpDto {
|
||||||
@ -39,7 +45,19 @@ export class UserSignUpDto {
|
|||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
public lastName: string;
|
public lastName: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'regionUuid',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
public regionUuid?: string;
|
public regionUuid?: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'hasAcceptedAppAgreement',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
@IsBoolean()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public hasAcceptedAppAgreement: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user