move code to workspaceUser service

This commit is contained in:
Philipinho
2024-03-03 17:40:10 +00:00
parent 7afd893fa1
commit bfebfb27a9
6 changed files with 232 additions and 165 deletions

View File

@ -47,7 +47,7 @@ export class JwtGuard implements CanActivate {
//fetch user and current workspace data from db //fetch user and current workspace data from db
request['user'] = await this.userService.getUserInstance(payload.sub); request['user'] = await this.userService.getUserInstance(payload.sub);
} catch (error) { } catch (error) {
throw new UnauthorizedException(error.message); throw new UnauthorizedException('Failed to fetch auth user');
} }
return true; return true;

View File

@ -10,7 +10,6 @@ import { UserRepository } from './repositories/user.repository';
import { plainToInstance } from 'class-transformer'; import { plainToInstance } from 'class-transformer';
import * as bcrypt from 'bcrypt'; import * as bcrypt from 'bcrypt';
import { WorkspaceService } from '../workspace/services/workspace.service'; import { WorkspaceService } from '../workspace/services/workspace.service';
import { Workspace } from '../workspace/entities/workspace.entity';
import { DataSource, EntityManager } from 'typeorm'; import { DataSource, EntityManager } from 'typeorm';
import { transactionWrapper } from '../../helpers/db.helper'; import { transactionWrapper } from '../../helpers/db.helper';
import { CreateWorkspaceDto } from '../workspace/dto/create-workspace.dto'; import { CreateWorkspaceDto } from '../workspace/dto/create-workspace.dto';
@ -61,7 +60,10 @@ export class UserService {
} }
async getUserInstance(userId: string) { async getUserInstance(userId: string) {
console.log('what is')
const user: User = await this.findById(userId); const user: User = await this.findById(userId);
console.log('what one')
if (!user) { if (!user) {
throw new NotFoundException('User not found'); throw new NotFoundException('User not found');

View File

@ -18,11 +18,15 @@ import { User } from '../../user/entities/user.entity';
import { CurrentWorkspace } from '../../../decorators/current-workspace.decorator'; import { CurrentWorkspace } from '../../../decorators/current-workspace.decorator';
import { Workspace } from '../entities/workspace.entity'; import { Workspace } from '../entities/workspace.entity';
import { PaginationOptions } from '../../../helpers/pagination/pagination-options'; import { PaginationOptions } from '../../../helpers/pagination/pagination-options';
import { WorkspaceUserService } from '../services/workspace-user.service';
@UseGuards(JwtGuard) @UseGuards(JwtGuard)
@Controller('workspaces') @Controller('workspaces')
export class WorkspaceController { export class WorkspaceController {
constructor(private readonly workspaceService: WorkspaceService) {} constructor(
private readonly workspaceService: WorkspaceService,
private readonly workspaceUserService: WorkspaceUserService,
) {}
@HttpCode(HttpStatus.OK) @HttpCode(HttpStatus.OK)
@Post('/') @Post('/')
@ -67,7 +71,10 @@ export class WorkspaceController {
pagination: PaginationOptions, pagination: PaginationOptions,
@CurrentWorkspace() workspace: Workspace, @CurrentWorkspace() workspace: Workspace,
) { ) {
return this.workspaceService.getWorkspaceUsers(workspace.id, pagination); return this.workspaceUserService.getWorkspaceUsers(
workspace.id,
pagination,
);
} }
@HttpCode(HttpStatus.OK) @HttpCode(HttpStatus.OK)
@ -76,7 +83,7 @@ export class WorkspaceController {
@Body() addWorkspaceUserDto: AddWorkspaceUserDto, @Body() addWorkspaceUserDto: AddWorkspaceUserDto,
@CurrentWorkspace() workspace: Workspace, @CurrentWorkspace() workspace: Workspace,
) { ) {
return this.workspaceService.addUserToWorkspace( return this.workspaceUserService.addUserToWorkspace(
addWorkspaceUserDto.userId, addWorkspaceUserDto.userId,
workspace.id, workspace.id,
addWorkspaceUserDto.role, addWorkspaceUserDto.role,
@ -89,7 +96,7 @@ export class WorkspaceController {
@Body() removeWorkspaceUserDto: RemoveWorkspaceUserDto, @Body() removeWorkspaceUserDto: RemoveWorkspaceUserDto,
@CurrentWorkspace() workspace: Workspace, @CurrentWorkspace() workspace: Workspace,
) { ) {
return this.workspaceService.removeUserFromWorkspace( return this.workspaceUserService.removeUserFromWorkspace(
removeWorkspaceUserDto.userId, removeWorkspaceUserDto.userId,
workspace.id, workspace.id,
); );
@ -102,7 +109,7 @@ export class WorkspaceController {
@AuthUser() authUser: User, @AuthUser() authUser: User,
@CurrentWorkspace() workspace: Workspace, @CurrentWorkspace() workspace: Workspace,
) { ) {
return this.workspaceService.updateWorkspaceUserRole( return this.workspaceUserService.updateWorkspaceUserRole(
authUser, authUser,
workspaceUserRoleDto, workspaceUserRoleDto,
workspace.id, workspace.id,

View File

@ -0,0 +1,204 @@
import {
BadRequestException,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { WorkspaceUserRepository } from '../repositories/workspace-user.repository';
import {
WorkspaceUser,
WorkspaceUserRole,
} from '../entities/workspace-user.entity';
import { Workspace } from '../entities/workspace.entity';
import { UpdateWorkspaceUserRoleDto } from '../dto/update-workspace-user-role.dto';
import { SpaceService } from '../../space/space.service';
import { PaginationOptions } from '../../../helpers/pagination/pagination-options';
import { PaginationMetaDto } from '../../../helpers/pagination/pagination-meta-dto';
import { PaginatedResult } from '../../../helpers/pagination/paginated-result';
import { User } from '../../user/entities/user.entity';
import { DataSource, EntityManager } from 'typeorm';
import { transactionWrapper } from '../../../helpers/db.helper';
@Injectable()
export class WorkspaceUserService {
constructor(
private workspaceUserRepository: WorkspaceUserRepository,
private spaceService: SpaceService,
private dataSource: DataSource,
) {}
async addUserToWorkspace(
userId: string,
workspaceId: string,
role: string,
manager?: EntityManager,
): Promise<WorkspaceUser> {
let addedUser;
await transactionWrapper(
async (manager) => {
const existingWorkspaceUser = await manager.findOne(WorkspaceUser, {
where: { userId: userId, workspaceId: workspaceId },
});
const userExists = await manager.exists(User, {
where: { id: userId },
});
if (!userExists) {
throw new NotFoundException('User not found');
}
if (existingWorkspaceUser) {
throw new BadRequestException(
'User is already a member of this workspace',
);
}
const workspaceUser = new WorkspaceUser();
workspaceUser.userId = userId;
workspaceUser.workspaceId = workspaceId;
workspaceUser.role = role;
addedUser = await manager.save(workspaceUser);
},
this.dataSource,
manager,
);
return addedUser;
}
async updateWorkspaceUserRole(
authUser: User,
workspaceUserRoleDto: UpdateWorkspaceUserRoleDto,
workspaceId: string,
) {
const workspaceUser = await this.getWorkspaceUser(
workspaceUserRoleDto.userId,
workspaceId,
);
if (workspaceUser.role === workspaceUserRoleDto.role) {
return workspaceUser;
}
const workspaceOwnerCount = await this.workspaceUserRepository.count({
where: {
role: WorkspaceUserRole.OWNER,
},
});
if (
workspaceUser.role === WorkspaceUserRole.OWNER &&
workspaceOwnerCount === 1
) {
throw new BadRequestException(
'There must be at least one workspace owner',
);
}
workspaceUser.role = workspaceUserRoleDto.role;
return this.workspaceUserRepository.save(workspaceUser);
}
async removeUserFromWorkspace(
userId: string,
workspaceId: string,
): Promise<void> {
await this.getWorkspaceUser(userId, workspaceId);
const workspaceUser = await this.getWorkspaceUser(userId, workspaceId);
const workspaceOwnerCount = await this.workspaceUserRepository.count({
where: {
role: WorkspaceUserRole.OWNER,
},
});
if (
workspaceUser.role === WorkspaceUserRole.OWNER &&
workspaceOwnerCount === 1
) {
throw new BadRequestException(
'There must be at least one workspace owner',
);
}
await this.workspaceUserRepository.delete({
userId,
workspaceId,
});
}
async getUserWorkspaces(
userId: string,
paginationOptions: PaginationOptions,
): Promise<PaginatedResult<Workspace>> {
const [workspaces, count] = await this.workspaceUserRepository.findAndCount(
{
where: { userId: userId },
relations: ['workspace'],
take: paginationOptions.limit,
skip: paginationOptions.skip,
},
);
const userWorkspaces = workspaces.map(
(userWorkspace: WorkspaceUser) => userWorkspace.workspace,
);
const paginationMeta = new PaginationMetaDto({ count, paginationOptions });
return new PaginatedResult(userWorkspaces, paginationMeta);
}
async getWorkspaceUsers(
workspaceId: string,
paginationOptions: PaginationOptions,
): Promise<PaginatedResult<any>> {
const [workspaceUsers, count] =
await this.workspaceUserRepository.findAndCount({
relations: ['user'],
where: {
workspace: {
id: workspaceId,
},
},
take: paginationOptions.limit,
skip: paginationOptions.skip,
});
const users = workspaceUsers.map((workspaceUser) => {
workspaceUser.user.password = '';
return {
...workspaceUser.user,
role: workspaceUser.role,
};
});
const paginationMeta = new PaginationMetaDto({ count, paginationOptions });
return new PaginatedResult(users, paginationMeta);
}
async getUserRoleInWorkspace(
userId: string,
workspaceId: string,
): Promise<string> {
const workspaceUser = await this.getWorkspaceUser(userId, workspaceId);
return workspaceUser.role ? workspaceUser.role : null;
}
async getWorkspaceUser(
userId: string,
workspaceId: string,
): Promise<WorkspaceUser> {
const workspaceUser = await this.workspaceUserRepository.findOne({
where: { userId, workspaceId },
});
if (!workspaceUser) {
throw new BadRequestException('Workspace member not found');
}
return workspaceUser;
}
}

View File

@ -24,6 +24,7 @@ import { User } from '../../user/entities/user.entity';
import { DataSource, EntityManager } from 'typeorm'; import { DataSource, EntityManager } from 'typeorm';
import { transactionWrapper } from '../../../helpers/db.helper'; import { transactionWrapper } from '../../../helpers/db.helper';
import { CreateSpaceDto } from '../../space/dto/create-space.dto'; import { CreateSpaceDto } from '../../space/dto/create-space.dto';
import { WorkspaceUserService } from './workspace-user.service';
@Injectable() @Injectable()
export class WorkspaceService { export class WorkspaceService {
@ -31,6 +32,8 @@ export class WorkspaceService {
private workspaceRepository: WorkspaceRepository, private workspaceRepository: WorkspaceRepository,
private workspaceUserRepository: WorkspaceUserRepository, private workspaceUserRepository: WorkspaceUserRepository,
private spaceService: SpaceService, private spaceService: SpaceService,
private workspaceUserService: WorkspaceUserService,
private dataSource: DataSource, private dataSource: DataSource,
) {} ) {}
@ -60,7 +63,7 @@ export class WorkspaceService {
createWorkspaceDto ?? null, createWorkspaceDto ?? null,
manager, manager,
); );
await this.addUserToWorkspace( await this.workspaceUserService.addUserToWorkspace(
userId, userId,
createdWorkspace.id, createdWorkspace.id,
WorkspaceUserRole.OWNER, WorkspaceUserRole.OWNER,
@ -96,7 +99,7 @@ export class WorkspaceService {
// add user to workspace and default space // add user to workspace and default space
await this.addUserToWorkspace( await this.workspaceUserService.addUserToWorkspace(
userId, userId,
firstWorkspace[0].id, firstWorkspace[0].id,
WorkspaceUserRole.MEMBER, WorkspaceUserRole.MEMBER,
@ -180,110 +183,6 @@ export class WorkspaceService {
// delete workspace // delete workspace
} }
async addUserToWorkspace(
userId: string,
workspaceId: string,
role: string,
manager?: EntityManager,
): Promise<WorkspaceUser> {
let addedUser;
await transactionWrapper(
async (manager) => {
const existingWorkspaceUser = await manager.findOne(WorkspaceUser, {
where: { userId: userId, workspaceId: workspaceId },
});
const userExists = await manager.exists(User, {
where: { id: userId },
});
if (!userExists) {
throw new NotFoundException('User not found');
}
if (existingWorkspaceUser) {
throw new BadRequestException(
'User is already a member of this workspace',
);
}
const workspaceUser = new WorkspaceUser();
workspaceUser.userId = userId;
workspaceUser.workspaceId = workspaceId;
workspaceUser.role = role;
addedUser = await manager.save(workspaceUser);
},
this.dataSource,
manager,
);
return addedUser;
}
async updateWorkspaceUserRole(
authUser: User,
workspaceUserRoleDto: UpdateWorkspaceUserRoleDto,
workspaceId: string,
) {
const workspaceUser = await this.getWorkspaceUser(
workspaceUserRoleDto.userId,
workspaceId,
);
if (workspaceUser.role === workspaceUserRoleDto.role) {
return workspaceUser;
}
const workspaceOwnerCount = await this.workspaceUserRepository.count({
where: {
role: WorkspaceUserRole.OWNER,
},
});
if (
workspaceUser.role === WorkspaceUserRole.OWNER &&
workspaceOwnerCount === 1
) {
throw new BadRequestException(
'There must be at least one workspace owner',
);
}
workspaceUser.role = workspaceUserRoleDto.role;
return this.workspaceUserRepository.save(workspaceUser);
}
async removeUserFromWorkspace(
userId: string,
workspaceId: string,
): Promise<void> {
await this.getWorkspaceUser(userId, workspaceId);
const workspaceUser = await this.getWorkspaceUser(userId, workspaceId);
const workspaceOwnerCount = await this.workspaceUserRepository.count({
where: {
role: WorkspaceUserRole.OWNER,
},
});
if (
workspaceUser.role === WorkspaceUserRole.OWNER &&
workspaceOwnerCount === 1
) {
throw new BadRequestException(
'There must be at least one workspace owner',
);
}
await this.workspaceUserRepository.delete({
userId,
workspaceId,
});
}
async getUserCurrentWorkspace(userId: string): Promise<Workspace> { async getUserCurrentWorkspace(userId: string): Promise<Workspace> {
const userWorkspace = await this.workspaceUserRepository.findOne({ const userWorkspace = await this.workspaceUserRepository.findOne({
where: { userId: userId }, where: { userId: userId },
@ -320,55 +219,4 @@ export class WorkspaceService {
const paginationMeta = new PaginationMetaDto({ count, paginationOptions }); const paginationMeta = new PaginationMetaDto({ count, paginationOptions });
return new PaginatedResult(userWorkspaces, paginationMeta); return new PaginatedResult(userWorkspaces, paginationMeta);
} }
async getWorkspaceUsers(
workspaceId: string,
paginationOptions: PaginationOptions,
): Promise<PaginatedResult<any>> {
const [workspaceUsers, count] =
await this.workspaceUserRepository.findAndCount({
relations: ['user'],
where: {
workspace: {
id: workspaceId,
},
},
take: paginationOptions.limit,
skip: paginationOptions.skip,
});
const users = workspaceUsers.map((workspaceUser) => {
workspaceUser.user.password = '';
return {
...workspaceUser.user,
role: workspaceUser.role,
};
});
const paginationMeta = new PaginationMetaDto({ count, paginationOptions });
return new PaginatedResult(users, paginationMeta);
}
async getUserRoleInWorkspace(
userId: string,
workspaceId: string,
): Promise<string> {
const workspaceUser = await this.getWorkspaceUser(userId, workspaceId);
return workspaceUser.role ? workspaceUser.role : null;
}
async getWorkspaceUser(
userId: string,
workspaceId: string,
): Promise<WorkspaceUser> {
const workspaceUser = await this.workspaceUserRepository.findOne({
where: { userId, workspaceId },
});
if (!workspaceUser) {
throw new BadRequestException('Workspace member not found');
}
return workspaceUser;
}
} }

View File

@ -9,6 +9,7 @@ import { WorkspaceInvitation } from './entities/workspace-invitation.entity';
import { WorkspaceUserRepository } from './repositories/workspace-user.repository'; import { WorkspaceUserRepository } from './repositories/workspace-user.repository';
import { AuthModule } from '../auth/auth.module'; import { AuthModule } from '../auth/auth.module';
import { SpaceModule } from '../space/space.module'; import { SpaceModule } from '../space/space.module';
import { WorkspaceUserService } from './services/workspace-user.service';
@Module({ @Module({
imports: [ imports: [
@ -17,7 +18,12 @@ import { SpaceModule } from '../space/space.module';
SpaceModule, SpaceModule,
], ],
controllers: [WorkspaceController], controllers: [WorkspaceController],
providers: [WorkspaceService, WorkspaceRepository, WorkspaceUserRepository], providers: [
WorkspaceService,
WorkspaceUserService,
WorkspaceRepository,
WorkspaceUserRepository,
],
exports: [WorkspaceService, WorkspaceRepository, WorkspaceUserRepository], exports: [WorkspaceService, WorkspaceRepository, WorkspaceUserRepository],
}) })
export class WorkspaceModule {} export class WorkspaceModule {}