mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-16 02:36:19 +00:00
community controller
This commit is contained in:
@ -8,4 +8,34 @@ export class ControllerRoute {
|
||||
'Retrieve the list of all regions registered in Syncrow.';
|
||||
};
|
||||
};
|
||||
|
||||
static COMMUNITY = class {
|
||||
public static readonly ROUTE = 'communities';
|
||||
static ACTIONS = class {
|
||||
public static readonly GET_COMMUNITY_BY_ID_SUMMARY =
|
||||
'Get community by community id';
|
||||
|
||||
public static readonly GET_COMMUNITY_BY_ID_DESCRIPTION =
|
||||
'Get community by community id - ( [a-zA-Z0-9]{10} )';
|
||||
|
||||
public static readonly LIST_COMMUNITY_SUMMARY = 'Get list of community';
|
||||
|
||||
public static readonly LIST_COMMUNITY_DESCRIPTION =
|
||||
'Return a list of community';
|
||||
public static readonly UPDATE_COMMUNITY_SUMMARY = 'Update community';
|
||||
|
||||
public static readonly UPDATE_COMMUNITY_DESCRIPTION =
|
||||
'Update community in the database and return updated community';
|
||||
|
||||
public static readonly DELETE_COMMUNITY_SUMMARY = 'Delete community';
|
||||
|
||||
public static readonly DELETE_COMMUNITY_DESCRIPTION =
|
||||
'Delete community matching by community id';
|
||||
|
||||
public static readonly CREATE_COMMUNITY_SUMMARY = 'Create community';
|
||||
|
||||
public static readonly CREATE_COMMUNITY_DESCRIPTION =
|
||||
'Create community in the database and return in model';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import { DeviceNotificationEntity } from '../modules/device/entities';
|
||||
import { RegionEntity } from '../modules/region/entities';
|
||||
import { TimeZoneEntity } from '../modules/timezone/entities';
|
||||
import { VisitorPasswordEntity } from '../modules/visitor-password/entities';
|
||||
import { CommunityEntity } from '../modules/community/entities';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@ -41,6 +42,7 @@ import { VisitorPasswordEntity } from '../modules/visitor-password/entities';
|
||||
DeviceUserPermissionEntity,
|
||||
DeviceEntity,
|
||||
PermissionTypeEntity,
|
||||
CommunityEntity,
|
||||
SpaceEntity,
|
||||
SpaceTypeEntity,
|
||||
UserSpaceEntity,
|
||||
|
23
libs/common/src/dto/base.response.dto.ts
Normal file
23
libs/common/src/dto/base.response.dto.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { WithOptional } from '../type/optional.type';
|
||||
|
||||
export class BaseResponseDto {
|
||||
statusCode?: number;
|
||||
|
||||
message: string;
|
||||
|
||||
error?: string;
|
||||
|
||||
data?: any;
|
||||
|
||||
success?: boolean;
|
||||
|
||||
static wrap({
|
||||
data,
|
||||
statusCode = 200,
|
||||
message = 'Success',
|
||||
success = true,
|
||||
error = undefined,
|
||||
}: WithOptional<BaseResponseDto, 'message'>) {
|
||||
return { data, statusCode, success, message, error };
|
||||
}
|
||||
}
|
87
libs/common/src/dto/pagination.request.dto.ts
Normal file
87
libs/common/src/dto/pagination.request.dto.ts
Normal file
@ -0,0 +1,87 @@
|
||||
import { IsDate, IsOptional } from 'class-validator';
|
||||
import { IsPageRequestParam } from '../validators/is-page-request-param.validator';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsSizeRequestParam } from '../validators/is-size-request-param.validator';
|
||||
import { IsSortParam } from '../validators/is-sort-param.validator';
|
||||
import { Transform } from 'class-transformer';
|
||||
import { parseToDate } from '../util/parseToDate';
|
||||
|
||||
export class PaginationRequestGetListDto {
|
||||
@IsOptional()
|
||||
@IsPageRequestParam({
|
||||
message: 'Page must be bigger than 0',
|
||||
})
|
||||
@ApiProperty({
|
||||
name: 'page',
|
||||
required: false,
|
||||
description: 'Page request',
|
||||
})
|
||||
page?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsSizeRequestParam({
|
||||
message: 'Size must not be negative',
|
||||
})
|
||||
@ApiProperty({
|
||||
name: 'size',
|
||||
required: false,
|
||||
description: 'Size request',
|
||||
})
|
||||
size?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsSortParam({
|
||||
message:
|
||||
'Incorrect sorting condition format. Should be like this format propertyId:asc,createdDate:desc',
|
||||
})
|
||||
@ApiProperty({
|
||||
name: 'sort',
|
||||
required: false,
|
||||
description: 'Sort condition',
|
||||
})
|
||||
sort?: string;
|
||||
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
name: 'name',
|
||||
required: false,
|
||||
description: 'Name to be filtered',
|
||||
})
|
||||
name?: string;
|
||||
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
name: 'include',
|
||||
required: false,
|
||||
description: 'Fields to include',
|
||||
})
|
||||
include?: string;
|
||||
|
||||
@ApiProperty({
|
||||
name: 'from',
|
||||
required: false,
|
||||
type: Number,
|
||||
description: `Start time in UNIX timestamp format to filter`,
|
||||
example: 1674172800000,
|
||||
})
|
||||
@IsOptional()
|
||||
@Transform(({ value }) => parseToDate(value))
|
||||
@IsDate({
|
||||
message: `From must be in UNIX timestamp format in order to parse to Date instance`,
|
||||
})
|
||||
from?: Date;
|
||||
|
||||
@ApiProperty({
|
||||
name: 'to',
|
||||
required: false,
|
||||
type: Number,
|
||||
description: `End time in UNIX timestamp format to filter`,
|
||||
example: 1674259200000,
|
||||
})
|
||||
@IsOptional()
|
||||
@Transform(({ value }) => parseToDate(value))
|
||||
@IsDate({
|
||||
message: `To must be in UNIX timestamp format in order to parse to Date instance`,
|
||||
})
|
||||
to?: Date;
|
||||
}
|
62
libs/common/src/dto/pagination.response.dto.ts
Normal file
62
libs/common/src/dto/pagination.response.dto.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import { BaseResponseDto } from './base.response.dto';
|
||||
|
||||
export interface PageResponseDto {
|
||||
// Original paging information from the request ( or default )
|
||||
page: number;
|
||||
size: number;
|
||||
|
||||
// Useful for display (N Records found)
|
||||
totalItem: number;
|
||||
|
||||
// Use for display N Pages ( 0... N )
|
||||
totalPage: number;
|
||||
|
||||
// Has next is false when cursor is at last page
|
||||
hasNext: boolean;
|
||||
|
||||
// Has previous is false when cursor is at first page
|
||||
hasPrevious: boolean;
|
||||
}
|
||||
|
||||
export class PageResponse<T> implements BaseResponseDto, PageResponseDto {
|
||||
code?: number;
|
||||
|
||||
message: string;
|
||||
|
||||
data: Array<T>;
|
||||
|
||||
page: number;
|
||||
|
||||
size: number;
|
||||
|
||||
totalItem: number;
|
||||
|
||||
totalPage: number;
|
||||
|
||||
hasNext: boolean;
|
||||
|
||||
hasPrevious: boolean;
|
||||
|
||||
constructor(
|
||||
baseResponseDto: BaseResponseDto,
|
||||
pageResponseDto: PageResponseDto,
|
||||
) {
|
||||
if (baseResponseDto.statusCode) {
|
||||
this.code = baseResponseDto.statusCode;
|
||||
} else {
|
||||
this.code = 200;
|
||||
}
|
||||
|
||||
if (baseResponseDto.data) {
|
||||
this.data = baseResponseDto.data;
|
||||
}
|
||||
|
||||
this.message = baseResponseDto.message;
|
||||
this.page = pageResponseDto.page;
|
||||
this.size = pageResponseDto.size;
|
||||
this.totalItem = pageResponseDto.totalItem;
|
||||
this.totalPage = pageResponseDto.totalPage;
|
||||
this.hasNext = pageResponseDto.hasNext;
|
||||
this.hasPrevious = pageResponseDto.hasPrevious;
|
||||
}
|
||||
}
|
29
libs/common/src/dto/success.response.dto.ts
Normal file
29
libs/common/src/dto/success.response.dto.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { BaseResponseDto } from './base.response.dto';
|
||||
|
||||
export class SuccessResponseDto<Type> implements BaseResponseDto {
|
||||
@ApiProperty({
|
||||
example: 200,
|
||||
})
|
||||
statusCode: number;
|
||||
|
||||
data: Type;
|
||||
|
||||
@ApiProperty({
|
||||
example: 'Success message',
|
||||
})
|
||||
message: string;
|
||||
|
||||
@ApiProperty({
|
||||
example: true,
|
||||
description: 'Indicates that the operation was successful',
|
||||
})
|
||||
success: boolean;
|
||||
|
||||
constructor(input: BaseResponseDto) {
|
||||
if (input.statusCode) this.statusCode = input.statusCode;
|
||||
else this.statusCode = 200;
|
||||
if (input.data) this.data = input.data;
|
||||
this.success = true;
|
||||
}
|
||||
}
|
145
libs/common/src/models/typeOrmCustom.model.ts
Normal file
145
libs/common/src/models/typeOrmCustom.model.ts
Normal file
@ -0,0 +1,145 @@
|
||||
import { FindManyOptions, Repository } from 'typeorm';
|
||||
import { InternalServerErrorException } from '@nestjs/common';
|
||||
import { BaseResponseDto } from '../dto/base.response.dto';
|
||||
import { PageResponseDto } from '../dto/pagination.response.dto';
|
||||
import { buildTypeORMSortQuery } from '../util/buildTypeORMSortQuery';
|
||||
import { getPaginationResponseDto } from '../util/getPaginationResponseDto';
|
||||
import { buildTypeORMWhereClause } from '../util/buildTypeORMWhereClause';
|
||||
import { buildTypeORMIncludeQuery } from '../util/buildTypeORMIncludeQuery';
|
||||
|
||||
export interface TypeORMCustomModelFindAllQuery {
|
||||
page: number | undefined;
|
||||
size: number | undefined;
|
||||
sort?: string;
|
||||
modelName?: string;
|
||||
include?: string;
|
||||
where?: { [key: string]: unknown };
|
||||
select?: string[];
|
||||
includeDisable?: boolean | string;
|
||||
}
|
||||
interface CustomFindAllQuery {
|
||||
page?: number;
|
||||
size?: number;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
interface FindAllQueryWithDefaults extends CustomFindAllQuery {
|
||||
page: number;
|
||||
size: number;
|
||||
}
|
||||
|
||||
function getDefaultQueryOptions(
|
||||
query: Partial<TypeORMCustomModelFindAllQuery>,
|
||||
): FindManyOptions & FindAllQueryWithDefaults {
|
||||
const { page, size, includeDisable, modelName, ...rest } = query;
|
||||
|
||||
// Set default if undefined or null
|
||||
const returnPage = page ? Number(page) : 1;
|
||||
const returnSize = size ? Number(size) : 10;
|
||||
const returnIncludeDisable =
|
||||
includeDisable === true || includeDisable === 'true';
|
||||
|
||||
// Return query with defaults and ensure modelName is passed through
|
||||
return {
|
||||
skip: (returnPage - 1) * returnSize,
|
||||
take: returnSize,
|
||||
where: {
|
||||
...rest,
|
||||
},
|
||||
page: returnPage,
|
||||
size: returnSize,
|
||||
includeDisable: returnIncludeDisable,
|
||||
modelName: modelName || query.modelName, // Ensure modelName is passed through
|
||||
};
|
||||
}
|
||||
|
||||
export interface TypeORMCustomModelFindAllQueryWithDefault
|
||||
extends TypeORMCustomModelFindAllQuery {
|
||||
page: number;
|
||||
size: number;
|
||||
}
|
||||
|
||||
export type TypeORMCustomModelFindAllResponse = {
|
||||
baseResponseDto: BaseResponseDto;
|
||||
paginationResponseDto: PageResponseDto;
|
||||
};
|
||||
|
||||
export function TypeORMCustomModel(repository: Repository<any>) {
|
||||
return Object.assign(repository, {
|
||||
findAll: async function (
|
||||
query: Partial<TypeORMCustomModelFindAllQuery>,
|
||||
): Promise<TypeORMCustomModelFindAllResponse> {
|
||||
// Extract values from the query
|
||||
const {
|
||||
page = 1,
|
||||
size = 10,
|
||||
sort,
|
||||
modelName,
|
||||
include,
|
||||
where,
|
||||
select,
|
||||
} = getDefaultQueryOptions(query);
|
||||
|
||||
// Ensure modelName is set before proceeding
|
||||
if (!modelName) {
|
||||
console.error(
|
||||
'modelName is missing after getDefaultQueryOptions:',
|
||||
query,
|
||||
);
|
||||
throw new InternalServerErrorException(
|
||||
`[TypeORMCustomModel] Cannot findAll with unknown modelName`,
|
||||
);
|
||||
}
|
||||
|
||||
const skip = (page - 1) * size;
|
||||
const order = buildTypeORMSortQuery(sort);
|
||||
const relations = buildTypeORMIncludeQuery(modelName, include);
|
||||
|
||||
// Use the where clause directly, without wrapping it under 'where'
|
||||
const whereClause = buildTypeORMWhereClause({ where });
|
||||
console.log('Where clause after building:', whereClause);
|
||||
|
||||
// Ensure the whereClause is passed directly to findAndCount
|
||||
const [data, count] = await repository.findAndCount({
|
||||
where: whereClause.where || whereClause, // Don't wrap this under another 'where'
|
||||
take: size,
|
||||
skip: skip,
|
||||
order: order,
|
||||
select: select,
|
||||
relations: relations,
|
||||
});
|
||||
|
||||
const paginationResponseDto = getPaginationResponseDto(count, page, size);
|
||||
const baseResponseDto: BaseResponseDto = {
|
||||
data,
|
||||
message: getResponseMessage(modelName, { where: whereClause }),
|
||||
};
|
||||
|
||||
return { baseResponseDto, paginationResponseDto };
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function getResponseMessage(
|
||||
modelName: string,
|
||||
query?: {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
where?: any;
|
||||
},
|
||||
): string {
|
||||
if (!query) {
|
||||
return `Success get list ${modelName}`;
|
||||
}
|
||||
|
||||
const { where } = query;
|
||||
if (modelName === 'user' && where && where?.community) {
|
||||
const {
|
||||
some: { communityId },
|
||||
} = where.community;
|
||||
if (typeof communityId === 'string') {
|
||||
return `Success get list ${modelName} belong to community`;
|
||||
}
|
||||
}
|
||||
|
||||
return `Success get list ${modelName}`;
|
||||
}
|
19
libs/common/src/modules/community/dtos/community.dto.ts
Normal file
19
libs/common/src/modules/community/dtos/community.dto.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { IsNotEmpty, IsOptional, IsString, IsUUID } from 'class-validator';
|
||||
|
||||
export class CommunityDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public uuid: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public name: string;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
public description?: string;
|
||||
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
public regionId: string;
|
||||
}
|
1
libs/common/src/modules/community/dtos/index.ts
Normal file
1
libs/common/src/modules/community/dtos/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './community.dto';
|
@ -0,0 +1,38 @@
|
||||
import { Column, Entity, ManyToOne, OneToMany, Unique } from 'typeorm';
|
||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||
import { CommunityDto } from '../dtos';
|
||||
import { RegionEntity } from '../../region/entities';
|
||||
import { SpaceEntity } from '../../space/entities';
|
||||
import { RoleEntity } from '../../role/entities';
|
||||
|
||||
@Entity({ name: 'community' })
|
||||
@Unique(['name'])
|
||||
export class CommunityEntity extends AbstractEntity<CommunityDto> {
|
||||
@Column({
|
||||
type: 'uuid',
|
||||
default: () => 'gen_random_uuid()',
|
||||
nullable: false,
|
||||
})
|
||||
public uuid: string;
|
||||
|
||||
@Column({
|
||||
length: 255,
|
||||
nullable: false,
|
||||
})
|
||||
name: string;
|
||||
|
||||
@Column({ length: 255, nullable: true })
|
||||
description: string;
|
||||
|
||||
@ManyToOne(() => RegionEntity, (region) => region.communities, {
|
||||
nullable: false,
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
region: RegionEntity;
|
||||
|
||||
@OneToMany(() => SpaceEntity, (space) => space.community)
|
||||
spaces: SpaceEntity[];
|
||||
|
||||
@OneToMany(() => RoleEntity, (role) => role.community)
|
||||
roles: RoleEntity[];
|
||||
}
|
1
libs/common/src/modules/community/entities/index.ts
Normal file
1
libs/common/src/modules/community/entities/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './community.entity';
|
@ -0,0 +1,10 @@
|
||||
import { DataSource, Repository } from 'typeorm';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { CommunityEntity } from '../entities';
|
||||
|
||||
@Injectable()
|
||||
export class CommunityRepository extends Repository<CommunityEntity> {
|
||||
constructor(private dataSource: DataSource) {
|
||||
super(CommunityEntity, dataSource.createEntityManager());
|
||||
}
|
||||
}
|
1
libs/common/src/modules/community/repositories/index.ts
Normal file
1
libs/common/src/modules/community/repositories/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './community.repository';
|
2
libs/common/src/type/optional.type.ts
Normal file
2
libs/common/src/type/optional.type.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export type WithOptional<T, K extends keyof T> = Omit<T, K> & Partial<T>;
|
||||
export type WithRequired<T, K extends keyof T> = Omit<T, K> & Required<T>;
|
4
libs/common/src/util/parseToDate.ts
Normal file
4
libs/common/src/util/parseToDate.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export function parseToDate(value: unknown): Date {
|
||||
const valueInNumber = Number(value);
|
||||
return new Date(valueInNumber);
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
import { ValidateBy, ValidationOptions } from 'class-validator';
|
||||
|
||||
export function IsPageRequestParam(
|
||||
validationOptions?: ValidationOptions,
|
||||
): PropertyDecorator {
|
||||
return ValidateBy(
|
||||
{
|
||||
name: 'IsPageRequestParam',
|
||||
validator: {
|
||||
validate(value) {
|
||||
return IsPageParam(value); // you can return a Promise<boolean> here as well, if you want to make async validation
|
||||
},
|
||||
},
|
||||
},
|
||||
validationOptions,
|
||||
);
|
||||
}
|
||||
|
||||
function IsPageParam(value: any): boolean {
|
||||
return !isNaN(Number(value)) && value > 0;
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
import { ValidateBy, ValidationOptions } from 'class-validator';
|
||||
|
||||
export function IsSizeRequestParam(
|
||||
validationOptions?: ValidationOptions,
|
||||
): PropertyDecorator {
|
||||
return ValidateBy(
|
||||
{
|
||||
name: 'IsSizeRequestParam',
|
||||
validator: {
|
||||
validate(value) {
|
||||
return IsSizeParam(value); // you can return a Promise<boolean> here as well, if you want to make async validation
|
||||
},
|
||||
},
|
||||
},
|
||||
validationOptions,
|
||||
);
|
||||
}
|
||||
|
||||
function IsSizeParam(value: any): boolean {
|
||||
return !isNaN(Number(value)) && value > -1;
|
||||
}
|
54
libs/common/src/validators/is-sort-param.validator.ts
Normal file
54
libs/common/src/validators/is-sort-param.validator.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import { ValidateBy, ValidationOptions } from 'class-validator';
|
||||
|
||||
export function IsSortParam(
|
||||
validationOptions?: ValidationOptions,
|
||||
allowedFieldName?: string[],
|
||||
): PropertyDecorator {
|
||||
return ValidateBy(
|
||||
{
|
||||
name: 'IsSortParam',
|
||||
validator: {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
||||
validate(value) {
|
||||
return IsValidMultipleSortParam(value, allowedFieldName); // you can return a Promise<boolean> here as well, if you want to make async validation
|
||||
},
|
||||
},
|
||||
},
|
||||
validationOptions,
|
||||
);
|
||||
}
|
||||
|
||||
function IsValidMultipleSortParam(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
||||
value: any,
|
||||
allowedFieldName?: string[],
|
||||
): boolean {
|
||||
if (typeof value !== 'string') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const conditions: string[] = value.split(',');
|
||||
const isValid: boolean = conditions.every((condition) => {
|
||||
const combination: string[] = condition.split(':');
|
||||
if (combination.length !== 2) {
|
||||
return false;
|
||||
}
|
||||
const field = combination[0].trim();
|
||||
const direction = combination[1].trim();
|
||||
|
||||
if (!field) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (allowedFieldName?.length && !allowedFieldName.includes(field)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!['asc', 'desc'].includes(direction.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
return isValid;
|
||||
}
|
@ -2,7 +2,9 @@ import { CommunityService } from '../services/community.service';
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Param,
|
||||
Post,
|
||||
@ -10,23 +12,25 @@ import {
|
||||
Query,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger';
|
||||
import {
|
||||
AddCommunityDto,
|
||||
AddUserCommunityDto,
|
||||
} from '../dtos/add.community.dto';
|
||||
import { GetCommunityChildDto } from '../dtos/get.community.dto';
|
||||
import { GetCommunityParams } from '../dtos/get.community.dto';
|
||||
import { UpdateCommunityNameDto } from '../dtos/update.community.dto';
|
||||
// import { CheckUserCommunityGuard } from 'src/guards/user.community.guard';
|
||||
import { AdminRoleGuard } from 'src/guards/admin.role.guard';
|
||||
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
||||
import { EnableDisableStatusEnum } from '@app/common/constants/days.enum';
|
||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
||||
import { ControllerRoute } from '@app/common/constants/controller-route';
|
||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||
import { PaginationRequestGetListDto } from '@app/common/dto/pagination.request.dto';
|
||||
// import { CommunityPermissionGuard } from 'src/guards/community.permission.guard';
|
||||
|
||||
@ApiTags('Community Module')
|
||||
@Controller({
|
||||
version: EnableDisableStatusEnum.ENABLED,
|
||||
path: SpaceType.COMMUNITY,
|
||||
version: '1',
|
||||
path: ControllerRoute.COMMUNITY.ROUTE,
|
||||
})
|
||||
export class CommunityController {
|
||||
constructor(private readonly communityService: CommunityService) {}
|
||||
@ -34,73 +38,103 @@ export class CommunityController {
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post()
|
||||
async addCommunity(@Body() addCommunityDto: AddCommunityDto) {
|
||||
const community = await this.communityService.addCommunity(addCommunityDto);
|
||||
return {
|
||||
statusCode: HttpStatus.CREATED,
|
||||
success: true,
|
||||
message: 'Community added successfully',
|
||||
data: community,
|
||||
};
|
||||
@ApiOperation({
|
||||
summary: ControllerRoute.COMMUNITY.ACTIONS.CREATE_COMMUNITY_SUMMARY,
|
||||
description: ControllerRoute.COMMUNITY.ACTIONS.CREATE_COMMUNITY_DESCRIPTION,
|
||||
})
|
||||
async createCommunity(
|
||||
@Body() addCommunityDto: AddCommunityDto,
|
||||
): Promise<BaseResponseDto> {
|
||||
return await this.communityService.createCommunity(addCommunityDto);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Get(':communityUuid')
|
||||
async getCommunityByUuid(@Param('communityUuid') communityUuid: string) {
|
||||
const community =
|
||||
await this.communityService.getCommunityByUuid(communityUuid);
|
||||
return community;
|
||||
@ApiOperation({
|
||||
summary: ControllerRoute.COMMUNITY.ACTIONS.GET_COMMUNITY_BY_ID_SUMMARY,
|
||||
description:
|
||||
ControllerRoute.COMMUNITY.ACTIONS.GET_COMMUNITY_BY_ID_DESCRIPTION,
|
||||
})
|
||||
@Get('/:communityId')
|
||||
async getCommunityByUuid(
|
||||
@Param() params: GetCommunityParams,
|
||||
): Promise<BaseResponseDto> {
|
||||
return await this.communityService.getCommunityById(params.communityId);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiOperation({
|
||||
summary: ControllerRoute.COMMUNITY.ACTIONS.LIST_COMMUNITY_SUMMARY,
|
||||
description: ControllerRoute.COMMUNITY.ACTIONS.LIST_COMMUNITY_DESCRIPTION,
|
||||
})
|
||||
@Get()
|
||||
async getCommunities() {
|
||||
const communities = await this.communityService.getCommunities();
|
||||
return communities;
|
||||
async getCommunities(
|
||||
@Query() query: PaginationRequestGetListDto,
|
||||
): Promise<BaseResponseDto> {
|
||||
return this.communityService.getCommunities(query);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Get('child/:communityUuid')
|
||||
async getCommunityChildByUuid(
|
||||
@Param('communityUuid') communityUuid: string,
|
||||
@Query() query: GetCommunityChildDto,
|
||||
@ApiOperation({
|
||||
summary: ControllerRoute.COMMUNITY.ACTIONS.UPDATE_COMMUNITY_SUMMARY,
|
||||
description: ControllerRoute.COMMUNITY.ACTIONS.UPDATE_COMMUNITY_DESCRIPTION,
|
||||
})
|
||||
@Put('/:communityId')
|
||||
async updateCommunity(
|
||||
@Param() param: GetCommunityParams,
|
||||
@Body() updateCommunityDto: UpdateCommunityNameDto,
|
||||
) {
|
||||
const community = await this.communityService.getCommunityChildByUuid(
|
||||
communityUuid,
|
||||
query,
|
||||
return this.communityService.updateCommunity(
|
||||
param.communityId,
|
||||
updateCommunityDto,
|
||||
);
|
||||
return community;
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Delete('/:communityId')
|
||||
@ApiOperation({
|
||||
summary: ControllerRoute.COMMUNITY.ACTIONS.DELETE_COMMUNITY_SUMMARY,
|
||||
description: ControllerRoute.COMMUNITY.ACTIONS.DELETE_COMMUNITY_DESCRIPTION,
|
||||
})
|
||||
async deleteCommunity(
|
||||
@Param() param: GetCommunityParams,
|
||||
): Promise<BaseResponseDto> {
|
||||
return this.communityService.deleteCommunity(param.communityId);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Get('user/:userUuid')
|
||||
async getCommunitiesByUserId(@Param('userUuid') userUuid: string) {
|
||||
return await this.communityService.getCommunitiesByUserId(userUuid);
|
||||
try {
|
||||
return await this.communityService.getCommunitiesByUserId(userUuid);
|
||||
} catch (error) {
|
||||
throw new HttpException(
|
||||
error.message || 'Internal server error',
|
||||
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(AdminRoleGuard)
|
||||
@Post('user')
|
||||
async addUserCommunity(@Body() addUserCommunityDto: AddUserCommunityDto) {
|
||||
await this.communityService.addUserCommunity(addUserCommunityDto);
|
||||
return {
|
||||
statusCode: HttpStatus.CREATED,
|
||||
success: true,
|
||||
message: 'user community added successfully',
|
||||
};
|
||||
}
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Put(':communityUuid')
|
||||
async renameCommunityByUuid(
|
||||
@Param('communityUuid') communityUuid: string,
|
||||
@Body() updateCommunityDto: UpdateCommunityNameDto,
|
||||
) {
|
||||
const community = await this.communityService.renameCommunityByUuid(
|
||||
communityUuid,
|
||||
updateCommunityDto,
|
||||
);
|
||||
return community;
|
||||
try {
|
||||
await this.communityService.addUserCommunity(addUserCommunityDto);
|
||||
return {
|
||||
statusCode: HttpStatus.CREATED,
|
||||
success: true,
|
||||
message: 'user community added successfully',
|
||||
};
|
||||
} catch (error) {
|
||||
throw new HttpException(
|
||||
error.message || 'Internal server error',
|
||||
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,38 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNotEmpty, IsString } from 'class-validator';
|
||||
import { IsNotEmpty, IsOptional, IsString, IsUUID } from 'class-validator';
|
||||
|
||||
export class AddCommunityDto {
|
||||
@ApiProperty({
|
||||
description: 'communityName',
|
||||
description: 'The name of the community',
|
||||
example: 'Community A',
|
||||
required: true,
|
||||
})
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public communityName: string;
|
||||
public name: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'A description of the community',
|
||||
example: 'This is a community for developers.',
|
||||
required: false,
|
||||
})
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
public description?: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'The UUID of the region this community belongs to',
|
||||
example: 'b6fa62c5-4fcf-4872-89a0-571cf431a6c7',
|
||||
})
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
public regionId: string;
|
||||
|
||||
constructor(dto: Partial<AddCommunityDto>) {
|
||||
Object.assign(this, dto);
|
||||
}
|
||||
}
|
||||
|
||||
export class AddUserCommunityDto {
|
||||
@ApiProperty({
|
||||
description: 'communityUuid',
|
||||
|
@ -7,6 +7,7 @@ import {
|
||||
IsNotEmpty,
|
||||
IsOptional,
|
||||
IsString,
|
||||
IsUUID,
|
||||
Min,
|
||||
} from 'class-validator';
|
||||
|
||||
@ -20,6 +21,18 @@ export class GetCommunityDto {
|
||||
public communityUuid: string;
|
||||
}
|
||||
|
||||
export class GetCommunityParams {
|
||||
@ApiProperty({
|
||||
description: 'Community id of the specific community',
|
||||
required: true,
|
||||
name: 'communityId',
|
||||
})
|
||||
@IsUUID()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public communityId: string;
|
||||
}
|
||||
|
||||
export class GetCommunityChildDto {
|
||||
@ApiProperty({ example: 1, description: 'Page number', required: true })
|
||||
@IsInt({ message: 'Page must be a number' })
|
||||
|
@ -3,12 +3,12 @@ import { IsNotEmpty, IsString } from 'class-validator';
|
||||
|
||||
export class UpdateCommunityNameDto {
|
||||
@ApiProperty({
|
||||
description: 'communityName',
|
||||
description: 'community name',
|
||||
required: true,
|
||||
})
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public communityName: string;
|
||||
public name: string;
|
||||
|
||||
constructor(dto: Partial<UpdateCommunityNameDto>) {
|
||||
Object.assign(this, dto);
|
||||
|
@ -1,183 +1,173 @@
|
||||
import { GetCommunityChildDto } from './../dtos/get.community.dto';
|
||||
import { SpaceTypeRepository } from './../../../libs/common/src/modules/space/repositories/space.repository';
|
||||
import {
|
||||
Injectable,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
BadRequestException,
|
||||
} from '@nestjs/common';
|
||||
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
|
||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
||||
import { AddCommunityDto, AddUserCommunityDto } from '../dtos';
|
||||
import {
|
||||
CommunityChildInterface,
|
||||
GetCommunitiesInterface,
|
||||
GetCommunityByUserUuidInterface,
|
||||
GetCommunityByUuidInterface,
|
||||
RenameCommunityByUuidInterface,
|
||||
} from '../interface/community.interface';
|
||||
import { SpaceEntity } from '@app/common/modules/space/entities';
|
||||
import { GetCommunityByUserUuidInterface } from '../interface/community.interface';
|
||||
import { UpdateCommunityNameDto } from '../dtos/update.community.dto';
|
||||
import { UserSpaceRepository } from '@app/common/modules/user/repositories';
|
||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
||||
import { CommonErrorCodes } from '@app/common/constants/error-codes.enum';
|
||||
import { RegionRepository } from '@app/common/modules/region/repositories';
|
||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||
import {
|
||||
TypeORMCustomModel,
|
||||
TypeORMCustomModelFindAllQuery,
|
||||
} from '@app/common/models/typeOrmCustom.model';
|
||||
import { PageResponse } from '@app/common/dto/pagination.response.dto';
|
||||
import { CommunityRepository } from '@app/common/modules/community/repositories';
|
||||
import { CommunityDto } from '@app/common/modules/community/dtos';
|
||||
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
||||
|
||||
@Injectable()
|
||||
export class CommunityService {
|
||||
constructor(
|
||||
private readonly spaceRepository: SpaceRepository,
|
||||
private readonly spaceTypeRepository: SpaceTypeRepository,
|
||||
private readonly userSpaceRepository: UserSpaceRepository,
|
||||
private readonly communityRepository: CommunityRepository,
|
||||
private readonly regionRepository: RegionRepository,
|
||||
) {}
|
||||
|
||||
async addCommunity(addCommunityDto: AddCommunityDto) {
|
||||
try {
|
||||
const spaceType = await this.spaceTypeRepository.findOne({
|
||||
where: {
|
||||
type: SpaceType.COMMUNITY,
|
||||
},
|
||||
});
|
||||
async createCommunity(dto: AddCommunityDto): Promise<BaseResponseDto> {
|
||||
const { regionId, name, description } = dto;
|
||||
// Find the region by the provided regionId
|
||||
const region = await this.regionRepository.findOneBy({ uuid: regionId });
|
||||
|
||||
const community = await this.spaceRepository.save({
|
||||
spaceName: addCommunityDto.communityName,
|
||||
spaceType: { uuid: spaceType.uuid },
|
||||
});
|
||||
return community;
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
async getCommunityByUuid(
|
||||
communityUuid: string,
|
||||
): Promise<GetCommunityByUuidInterface> {
|
||||
try {
|
||||
const community = await this.spaceRepository.findOne({
|
||||
where: {
|
||||
uuid: communityUuid,
|
||||
spaceType: {
|
||||
type: SpaceType.COMMUNITY,
|
||||
},
|
||||
},
|
||||
relations: ['spaceType'],
|
||||
});
|
||||
if (
|
||||
!community ||
|
||||
!community.spaceType ||
|
||||
community.spaceType.type !== SpaceType.COMMUNITY
|
||||
) {
|
||||
throw new BadRequestException('Invalid community UUID');
|
||||
}
|
||||
return {
|
||||
uuid: community.uuid,
|
||||
createdAt: community.createdAt,
|
||||
updatedAt: community.updatedAt,
|
||||
name: community.spaceName,
|
||||
type: community.spaceType.type,
|
||||
};
|
||||
} catch (err) {
|
||||
if (err instanceof BadRequestException) {
|
||||
throw err; // Re-throw BadRequestException
|
||||
} else {
|
||||
throw new HttpException('Community not found', HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
async getCommunities(): Promise<GetCommunitiesInterface> {
|
||||
try {
|
||||
const community = await this.spaceRepository.find({
|
||||
where: { spaceType: { type: SpaceType.COMMUNITY } },
|
||||
relations: ['spaceType'],
|
||||
});
|
||||
return community.map((community) => ({
|
||||
uuid: community.uuid,
|
||||
createdAt: community.createdAt,
|
||||
updatedAt: community.updatedAt,
|
||||
name: community.spaceName,
|
||||
type: community.spaceType.type,
|
||||
}));
|
||||
} catch (err) {
|
||||
throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
async getCommunityChildByUuid(
|
||||
communityUuid: string,
|
||||
getCommunityChildDto: GetCommunityChildDto,
|
||||
): Promise<CommunityChildInterface> {
|
||||
try {
|
||||
const { includeSubSpaces, page, pageSize } = getCommunityChildDto;
|
||||
|
||||
const space = await this.spaceRepository.findOneOrFail({
|
||||
where: { uuid: communityUuid },
|
||||
relations: ['children', 'spaceType'],
|
||||
});
|
||||
|
||||
if (
|
||||
!space ||
|
||||
!space.spaceType ||
|
||||
space.spaceType.type !== SpaceType.COMMUNITY
|
||||
) {
|
||||
throw new BadRequestException('Invalid community UUID');
|
||||
}
|
||||
const totalCount = await this.spaceRepository.count({
|
||||
where: { parent: { uuid: space.uuid } },
|
||||
});
|
||||
const children = await this.buildHierarchy(
|
||||
space,
|
||||
includeSubSpaces,
|
||||
page,
|
||||
pageSize,
|
||||
if (!region) {
|
||||
throw new HttpException(
|
||||
`Region with ID ${dto.regionId} not found.`,
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
return {
|
||||
uuid: space.uuid,
|
||||
name: space.spaceName,
|
||||
type: space.spaceType.type,
|
||||
totalCount,
|
||||
children,
|
||||
};
|
||||
} catch (err) {
|
||||
if (err instanceof BadRequestException) {
|
||||
throw err; // Re-throw BadRequestException
|
||||
} else {
|
||||
throw new HttpException('Community not found', HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async buildHierarchy(
|
||||
space: SpaceEntity,
|
||||
includeSubSpaces: boolean,
|
||||
page: number,
|
||||
pageSize: number,
|
||||
): Promise<CommunityChildInterface[]> {
|
||||
const children = await this.spaceRepository.find({
|
||||
where: { parent: { uuid: space.uuid } },
|
||||
relations: ['spaceType'],
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
// Create the new community entity
|
||||
const community = this.communityRepository.create({
|
||||
name: name,
|
||||
description: description,
|
||||
region: region, // Associate with the found region
|
||||
});
|
||||
|
||||
if (!children || children.length === 0 || !includeSubSpaces) {
|
||||
return children
|
||||
.filter((child) => child.spaceType.type !== SpaceType.COMMUNITY) // Filter remaining community type
|
||||
.map((child) => ({
|
||||
uuid: child.uuid,
|
||||
name: child.spaceName,
|
||||
type: child.spaceType.type,
|
||||
}));
|
||||
// Save the community to the database
|
||||
try {
|
||||
await this.communityRepository.save(community);
|
||||
return new SuccessResponseDto({
|
||||
statusCode: HttpStatus.CREATED,
|
||||
success: true,
|
||||
data: community,
|
||||
message: 'Community created successfully',
|
||||
});
|
||||
} catch (error) {
|
||||
throw new HttpException(error.message, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
async getCommunityById(id: string): Promise<BaseResponseDto> {
|
||||
const community = await this.communityRepository.findOneBy({ uuid: id });
|
||||
|
||||
// If the community is not found, throw a 404 NotFoundException
|
||||
if (!community) {
|
||||
throw new HttpException(
|
||||
`Community with ID ${id} not found.`,
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const childHierarchies = await Promise.all(
|
||||
children
|
||||
.filter((child) => child.spaceType.type !== SpaceType.COMMUNITY) // Filter remaining community type
|
||||
.map(async (child) => ({
|
||||
uuid: child.uuid,
|
||||
name: child.spaceName,
|
||||
type: child.spaceType.type,
|
||||
children: await this.buildHierarchy(child, true, 1, pageSize),
|
||||
})),
|
||||
);
|
||||
// Return a success response
|
||||
return new SuccessResponseDto({
|
||||
data: community,
|
||||
message: 'Community fetched successfully',
|
||||
});
|
||||
}
|
||||
|
||||
return childHierarchies;
|
||||
async getCommunities(
|
||||
pageable: Partial<TypeORMCustomModelFindAllQuery>,
|
||||
): Promise<BaseResponseDto> {
|
||||
pageable.modelName = 'community';
|
||||
|
||||
const customModel = TypeORMCustomModel(this.communityRepository);
|
||||
|
||||
const { baseResponseDto, paginationResponseDto } =
|
||||
await customModel.findAll(pageable);
|
||||
|
||||
return new PageResponse<CommunityDto>(
|
||||
baseResponseDto,
|
||||
paginationResponseDto,
|
||||
);
|
||||
}
|
||||
|
||||
async updateCommunity(
|
||||
id: string,
|
||||
updateCommunityDto: UpdateCommunityNameDto,
|
||||
): Promise<BaseResponseDto> {
|
||||
const community = await this.communityRepository.findOne({
|
||||
where: { uuid: id },
|
||||
});
|
||||
|
||||
// If the community doesn't exist, throw a 404 error
|
||||
if (!community) {
|
||||
throw new HttpException(
|
||||
`Community with ID ${id} not found`,
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const { name } = updateCommunityDto;
|
||||
|
||||
// Find the community by its UUID
|
||||
|
||||
// Update the community name
|
||||
community.name = name;
|
||||
|
||||
// Save the updated community back to the database
|
||||
const updatedCommunity = await this.communityRepository.save(community);
|
||||
|
||||
// Return a SuccessResponseDto with the updated community data
|
||||
return new SuccessResponseDto<CommunityDto>({
|
||||
message: 'Success update Community',
|
||||
data: updatedCommunity,
|
||||
});
|
||||
} catch (err) {
|
||||
// Catch and handle any errors
|
||||
if (err instanceof HttpException) {
|
||||
throw err; // If it's an HttpException, rethrow it
|
||||
} else {
|
||||
// Throw a generic 404 error if anything else goes wrong
|
||||
throw new HttpException('Community not found', HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async deleteCommunity(id: string): Promise<BaseResponseDto> {
|
||||
const community = await this.communityRepository.findOne({
|
||||
where: { uuid: id },
|
||||
});
|
||||
|
||||
// If the community is not found, throw an error
|
||||
if (!community) {
|
||||
throw new HttpException(
|
||||
`Community with ID ${id} not found`,
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
try {
|
||||
// Find the community by its uuid
|
||||
|
||||
// Remove the community from the database
|
||||
await this.communityRepository.remove(community);
|
||||
|
||||
// Return success response
|
||||
return new SuccessResponseDto({
|
||||
message: `Community with ID ${id} successfully deleted`,
|
||||
data: null,
|
||||
});
|
||||
} catch (err) {
|
||||
// Catch and handle any errors
|
||||
if (err instanceof HttpException) {
|
||||
throw err; // If it's an HttpException, rethrow it
|
||||
} else {
|
||||
throw new HttpException(
|
||||
'An error occurred while deleting the community',
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async getCommunitiesByUserId(
|
||||
@ -188,7 +178,6 @@ export class CommunityService {
|
||||
relations: ['space', 'space.spaceType'],
|
||||
where: {
|
||||
user: { uuid: userUuid },
|
||||
space: { spaceType: { type: SpaceType.COMMUNITY } },
|
||||
},
|
||||
});
|
||||
|
||||
@ -200,7 +189,7 @@ export class CommunityService {
|
||||
}
|
||||
const spaces = communities.map((community) => ({
|
||||
uuid: community.space.uuid,
|
||||
name: community.space.spaceName,
|
||||
name: community.space.name,
|
||||
type: community.space.spaceType.type,
|
||||
}));
|
||||
|
||||
@ -221,7 +210,7 @@ export class CommunityService {
|
||||
space: { uuid: addUserCommunityDto.communityUuid },
|
||||
});
|
||||
} catch (err) {
|
||||
if (err.code === CommonErrorCodes.DUPLICATE_ENTITY) {
|
||||
if (err.code === '23505') {
|
||||
throw new HttpException(
|
||||
'User already belongs to this community',
|
||||
HttpStatus.BAD_REQUEST,
|
||||
@ -233,46 +222,4 @@ export class CommunityService {
|
||||
);
|
||||
}
|
||||
}
|
||||
async renameCommunityByUuid(
|
||||
communityUuid: string,
|
||||
updateCommunityDto: UpdateCommunityNameDto,
|
||||
): Promise<RenameCommunityByUuidInterface> {
|
||||
try {
|
||||
const community = await this.spaceRepository.findOneOrFail({
|
||||
where: { uuid: communityUuid },
|
||||
relations: ['spaceType'],
|
||||
});
|
||||
|
||||
if (
|
||||
!community ||
|
||||
!community.spaceType ||
|
||||
community.spaceType.type !== SpaceType.COMMUNITY
|
||||
) {
|
||||
throw new BadRequestException('Invalid community UUID');
|
||||
}
|
||||
|
||||
await this.spaceRepository.update(
|
||||
{ uuid: communityUuid },
|
||||
{ spaceName: updateCommunityDto.communityName },
|
||||
);
|
||||
|
||||
// Fetch the updated community
|
||||
const updatedCommunity = await this.spaceRepository.findOneOrFail({
|
||||
where: { uuid: communityUuid },
|
||||
relations: ['spaceType'],
|
||||
});
|
||||
|
||||
return {
|
||||
uuid: updatedCommunity.uuid,
|
||||
name: updatedCommunity.spaceName,
|
||||
type: updatedCommunity.spaceType.type,
|
||||
};
|
||||
} catch (err) {
|
||||
if (err instanceof BadRequestException) {
|
||||
throw err; // Re-throw BadRequestException
|
||||
} else {
|
||||
throw new HttpException('Community not found', HttpStatus.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user