mirror of
https://github.com/docmost/docmost.git
synced 2025-11-22 04:01:12 +10:00
Refactoring
* replace TypeORM with Kysely query builder * refactor migrations * other changes and fixes
This commit is contained in:
@ -11,9 +11,7 @@ import { UpdateWorkspaceDto } from '../dto/update-workspace.dto';
|
||||
import { DeleteWorkspaceDto } from '../dto/delete-workspace.dto';
|
||||
import { UpdateWorkspaceUserRoleDto } from '../dto/update-workspace-user-role.dto';
|
||||
import { AuthUser } from '../../../decorators/auth-user.decorator';
|
||||
import { User } from '../../user/entities/user.entity';
|
||||
import { AuthWorkspace } from '../../../decorators/auth-workspace.decorator';
|
||||
import { Workspace } from '../entities/workspace.entity';
|
||||
import { PaginationOptions } from '../../../helpers/pagination/pagination-options';
|
||||
import { WorkspaceInvitationService } from '../services/workspace-invitation.service';
|
||||
import { Public } from '../../../decorators/public.decorator';
|
||||
@ -23,12 +21,12 @@ import {
|
||||
RevokeInviteDto,
|
||||
} from '../dto/invitation.dto';
|
||||
import { Action } from '../../casl/ability.action';
|
||||
import { WorkspaceInvitation } from '../entities/workspace-invitation.entity';
|
||||
import { CheckPolicies } from '../../casl/decorators/policies.decorator';
|
||||
import { AppAbility } from '../../casl/abilities/casl-ability.factory';
|
||||
import { PoliciesGuard } from '../../casl/guards/policies.guard';
|
||||
import { WorkspaceUserService } from '../services/workspace-user.service';
|
||||
import { JwtAuthGuard } from '../../../guards/jwt-auth.guard';
|
||||
import { User, Workspace } from '@docmost/db/types/entity.types';
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Controller('workspace')
|
||||
@ -49,7 +47,9 @@ export class WorkspaceController {
|
||||
}
|
||||
|
||||
@UseGuards(PoliciesGuard)
|
||||
@CheckPolicies((ability: AppAbility) => ability.can(Action.Manage, Workspace))
|
||||
@CheckPolicies((ability: AppAbility) =>
|
||||
ability.can(Action.Manage, 'Workspace'),
|
||||
)
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post('update')
|
||||
async updateWorkspace(
|
||||
@ -60,7 +60,9 @@ export class WorkspaceController {
|
||||
}
|
||||
|
||||
@UseGuards(PoliciesGuard)
|
||||
@CheckPolicies((ability: AppAbility) => ability.can(Action.Manage, Workspace))
|
||||
@CheckPolicies((ability: AppAbility) =>
|
||||
ability.can(Action.Manage, 'Workspace'),
|
||||
)
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post('delete')
|
||||
async deleteWorkspace(@Body() deleteWorkspaceDto: DeleteWorkspaceDto) {
|
||||
@ -69,7 +71,7 @@ export class WorkspaceController {
|
||||
|
||||
@UseGuards(PoliciesGuard)
|
||||
@CheckPolicies((ability: AppAbility) =>
|
||||
ability.can(Action.Read, 'workspaceUser'),
|
||||
ability.can(Action.Read, 'WorkspaceUser'),
|
||||
)
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post('members')
|
||||
@ -96,7 +98,7 @@ export class WorkspaceController {
|
||||
|
||||
@UseGuards(PoliciesGuard)
|
||||
@CheckPolicies((ability: AppAbility) =>
|
||||
ability.can(Action.Manage, 'workspaceUser'),
|
||||
ability.can(Action.Manage, 'WorkspaceUser'),
|
||||
)
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post('members/role')
|
||||
@ -114,7 +116,7 @@ export class WorkspaceController {
|
||||
|
||||
@UseGuards(PoliciesGuard)
|
||||
@CheckPolicies((ability: AppAbility) =>
|
||||
ability.can(Action.Manage, WorkspaceInvitation),
|
||||
ability.can(Action.Manage, 'WorkspaceInvitation'),
|
||||
)
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post('invite')
|
||||
@ -123,11 +125,11 @@ export class WorkspaceController {
|
||||
@AuthUser() authUser: User,
|
||||
@AuthWorkspace() workspace: Workspace,
|
||||
) {
|
||||
return this.workspaceInvitationService.createInvitation(
|
||||
/* return this.workspaceInvitationService.createInvitation(
|
||||
authUser,
|
||||
workspace.id,
|
||||
inviteUserDto,
|
||||
);
|
||||
);*/
|
||||
}
|
||||
|
||||
@Public()
|
||||
@ -143,8 +145,8 @@ export class WorkspaceController {
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post('invite/revoke')
|
||||
async revokeInvite(@Body() revokeInviteDto: RevokeInviteDto) {
|
||||
return this.workspaceInvitationService.revokeInvitation(
|
||||
revokeInviteDto.invitationId,
|
||||
);
|
||||
// return this.workspaceInvitationService.revokeInvitation(
|
||||
// revokeInviteDto.invitationId,
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,48 +0,0 @@
|
||||
import {
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
ManyToOne,
|
||||
JoinColumn,
|
||||
} from 'typeorm';
|
||||
import { Workspace } from './workspace.entity';
|
||||
import { User } from '../../user/entities/user.entity';
|
||||
|
||||
@Entity('workspace_invitations')
|
||||
export class WorkspaceInvitation {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column()
|
||||
workspaceId: string;
|
||||
|
||||
@ManyToOne(() => Workspace, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn({ name: 'workspaceId' })
|
||||
workspace: Workspace;
|
||||
|
||||
@Column()
|
||||
invitedById: string;
|
||||
|
||||
@ManyToOne(() => User)
|
||||
@JoinColumn({ name: 'invitedById' })
|
||||
invitedBy: User;
|
||||
|
||||
@Column({ length: 255 })
|
||||
email: string;
|
||||
|
||||
@Column({ length: 100, nullable: true })
|
||||
role: string;
|
||||
|
||||
@Column({ length: 100, nullable: true })
|
||||
status: string;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn()
|
||||
updatedAt: Date;
|
||||
}
|
||||
@ -1,95 +0,0 @@
|
||||
import {
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
OneToMany,
|
||||
JoinColumn,
|
||||
OneToOne,
|
||||
DeleteDateColumn,
|
||||
} from 'typeorm';
|
||||
import { User } from '../../user/entities/user.entity';
|
||||
import { Page } from '../../page/entities/page.entity';
|
||||
import { WorkspaceInvitation } from './workspace-invitation.entity';
|
||||
import { Comment } from '../../comment/entities/comment.entity';
|
||||
import { Space } from '../../space/entities/space.entity';
|
||||
import { Group } from '../../group/entities/group.entity';
|
||||
import { UserRole } from '../../../helpers/types/permission';
|
||||
|
||||
@Entity('workspaces')
|
||||
export class Workspace {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column({ length: 255, nullable: true })
|
||||
name: string;
|
||||
|
||||
@Column({ type: 'text', nullable: true })
|
||||
description: string;
|
||||
|
||||
@Column({ length: 255, nullable: true })
|
||||
logo: string;
|
||||
|
||||
@Column({ length: 255, nullable: true, unique: true })
|
||||
hostname: string;
|
||||
|
||||
@Column({ length: 255, nullable: true })
|
||||
customDomain: string;
|
||||
|
||||
@Column({ type: 'boolean', default: true })
|
||||
enableInvite: boolean;
|
||||
|
||||
@Column({ length: 255, unique: true, nullable: true })
|
||||
inviteCode: string;
|
||||
|
||||
@Column({ type: 'jsonb', nullable: true })
|
||||
settings: any;
|
||||
|
||||
@Column({ default: UserRole.MEMBER })
|
||||
defaultRole: string;
|
||||
|
||||
@Column({ nullable: true, type: 'uuid' })
|
||||
creatorId: string;
|
||||
|
||||
@OneToOne(() => User)
|
||||
@JoinColumn({ name: 'creatorId' })
|
||||
creator: User;
|
||||
|
||||
@Column({ nullable: true })
|
||||
defaultSpaceId: string;
|
||||
|
||||
@OneToOne(() => Space, { onDelete: 'SET NULL' })
|
||||
@JoinColumn({ name: 'defaultSpaceId' })
|
||||
defaultSpace: Space;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn()
|
||||
updatedAt: Date;
|
||||
|
||||
@DeleteDateColumn()
|
||||
deletedAt: Date;
|
||||
|
||||
@OneToMany(() => User, (user) => user.workspace)
|
||||
users: [];
|
||||
|
||||
@OneToMany(
|
||||
() => WorkspaceInvitation,
|
||||
(workspaceInvitation) => workspaceInvitation.workspace,
|
||||
)
|
||||
workspaceInvitations: WorkspaceInvitation[];
|
||||
|
||||
@OneToMany(() => Page, (page) => page.workspace)
|
||||
pages: Page[];
|
||||
|
||||
@OneToMany(() => Comment, (comment) => comment.workspace)
|
||||
comments: Comment[];
|
||||
|
||||
@OneToMany(() => Space, (space) => space.workspace)
|
||||
spaces: [];
|
||||
|
||||
@OneToMany(() => Group, (group) => group.workspace)
|
||||
groups: [];
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { DataSource, Repository } from 'typeorm';
|
||||
import { WorkspaceInvitation } from '../entities/workspace-invitation.entity';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceInvitationRepository extends Repository<WorkspaceInvitation> {
|
||||
constructor(private dataSource: DataSource) {
|
||||
super(WorkspaceInvitation, dataSource.createEntityManager());
|
||||
}
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { DataSource, Repository } from 'typeorm';
|
||||
import { Workspace } from '../entities/workspace.entity';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceRepository extends Repository<Workspace> {
|
||||
constructor(private dataSource: DataSource) {
|
||||
super(Workspace, dataSource.createEntityManager());
|
||||
}
|
||||
|
||||
async findById(workspaceId: string): Promise<Workspace> {
|
||||
// see: https://github.com/typeorm/typeorm/issues/9316
|
||||
const queryBuilder = this.dataSource.createQueryBuilder(
|
||||
Workspace,
|
||||
'workspace',
|
||||
);
|
||||
return await queryBuilder
|
||||
.where('workspace.id = :id', { id: workspaceId })
|
||||
.getOne();
|
||||
}
|
||||
|
||||
async findFirst(): Promise<Workspace> {
|
||||
const createdWorkspace = await this.find({
|
||||
order: {
|
||||
createdAt: 'ASC',
|
||||
},
|
||||
take: 1,
|
||||
});
|
||||
return createdWorkspace[0];
|
||||
}
|
||||
}
|
||||
@ -1,24 +1,17 @@
|
||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||
import { WorkspaceInvitationRepository } from '../repositories/workspace-invitation.repository';
|
||||
import { WorkspaceInvitation } from '../entities/workspace-invitation.entity';
|
||||
import { User } from '../../user/entities/user.entity';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { WorkspaceService } from './workspace.service';
|
||||
import { UserService } from '../../user/user.service';
|
||||
import { InviteUserDto } from '../dto/invitation.dto';
|
||||
import { WorkspaceUserService } from './workspace-user.service';
|
||||
import { UserRole } from '../../../helpers/types/permission';
|
||||
import { UserRepository } from '../../user/repositories/user.repository';
|
||||
|
||||
// need reworking
|
||||
@Injectable()
|
||||
export class WorkspaceInvitationService {
|
||||
constructor(
|
||||
private workspaceInvitationRepository: WorkspaceInvitationRepository,
|
||||
private workspaceService: WorkspaceService,
|
||||
private workspaceUserService: WorkspaceUserService,
|
||||
private userService: UserService,
|
||||
private userRepository: UserRepository,
|
||||
) {}
|
||||
|
||||
/*
|
||||
async findInvitedUserByEmail(
|
||||
email,
|
||||
workspaceId,
|
||||
@ -108,4 +101,6 @@ export class WorkspaceInvitationService {
|
||||
|
||||
await this.workspaceInvitationRepository.delete(invitationId);
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
@ -3,97 +3,67 @@ import { UpdateWorkspaceUserRoleDto } from '../dto/update-workspace-user-role.dt
|
||||
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 { WorkspaceRepository } from '../repositories/workspace.repository';
|
||||
import { UserRepository } from '../../user/repositories/user.repository';
|
||||
import { UserRole } from '../../../helpers/types/permission';
|
||||
import { UserRepo } from '@docmost/db/repos/user/user.repo';
|
||||
import { WorkspaceRepo } from '@docmost/db/repos/workspace/workspace.repo';
|
||||
import { User } from '@docmost/db/types/entity.types';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceUserService {
|
||||
constructor(
|
||||
private workspaceRepository: WorkspaceRepository,
|
||||
private userRepository: UserRepository,
|
||||
private workspaceRepo: WorkspaceRepo,
|
||||
private userRepo: UserRepo,
|
||||
) {}
|
||||
|
||||
async getWorkspaceUsers(
|
||||
workspaceId: string,
|
||||
paginationOptions: PaginationOptions,
|
||||
): Promise<PaginatedResult<User>> {
|
||||
const [workspaceUsers, count] = await this.userRepository.findAndCount({
|
||||
where: {
|
||||
workspaceId,
|
||||
},
|
||||
take: paginationOptions.limit,
|
||||
skip: paginationOptions.skip,
|
||||
});
|
||||
): Promise<PaginatedResult<any>> {
|
||||
const { users, count } = await this.userRepo.getUsersPaginated(
|
||||
workspaceId,
|
||||
paginationOptions,
|
||||
);
|
||||
|
||||
const paginationMeta = new PaginationMetaDto({ count, paginationOptions });
|
||||
return new PaginatedResult(workspaceUsers, paginationMeta);
|
||||
return new PaginatedResult(users, paginationMeta);
|
||||
}
|
||||
|
||||
async updateWorkspaceUserRole(
|
||||
authUser: User,
|
||||
workspaceUserRoleDto: UpdateWorkspaceUserRoleDto,
|
||||
userRoleDto: UpdateWorkspaceUserRoleDto,
|
||||
workspaceId: string,
|
||||
) {
|
||||
const workspaceUser = await this.findAndValidateWorkspaceUser(
|
||||
workspaceUserRoleDto.userId,
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
if (workspaceUser.role === workspaceUserRoleDto.role) {
|
||||
return workspaceUser;
|
||||
}
|
||||
|
||||
const workspaceOwnerCount = await this.userRepository.count({
|
||||
where: {
|
||||
role: UserRole.OWNER,
|
||||
workspaceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (workspaceUser.role === UserRole.OWNER && workspaceOwnerCount === 1) {
|
||||
throw new BadRequestException(
|
||||
'There must be at least one workspace owner',
|
||||
);
|
||||
}
|
||||
|
||||
workspaceUser.role = workspaceUserRoleDto.role;
|
||||
|
||||
return this.userRepository.save(workspaceUser);
|
||||
}
|
||||
|
||||
async deactivateUser(): Promise<any> {
|
||||
return 'todo';
|
||||
}
|
||||
|
||||
async findWorkspaceUser(userId: string, workspaceId: string): Promise<User> {
|
||||
return await this.userRepository.findOneBy({
|
||||
id: userId,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
async findWorkspaceUserByEmail(
|
||||
email: string,
|
||||
workspaceId: string,
|
||||
): Promise<User> {
|
||||
return await this.userRepository.findOneBy({
|
||||
email: email,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
async findAndValidateWorkspaceUser(
|
||||
userId: string,
|
||||
workspaceId: string,
|
||||
): Promise<User> {
|
||||
const user = await this.findWorkspaceUser(userId, workspaceId);
|
||||
const user = await this.userRepo.findById(userRoleDto.userId, workspaceId);
|
||||
|
||||
if (!user) {
|
||||
throw new BadRequestException('Workspace member not found');
|
||||
}
|
||||
|
||||
return user;
|
||||
if (user.role === userRoleDto.role) {
|
||||
return user;
|
||||
}
|
||||
|
||||
const workspaceOwnerCount = await this.userRepo.roleCountByWorkspaceId(
|
||||
UserRole.OWNER,
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
if (user.role === UserRole.OWNER && workspaceOwnerCount === 1) {
|
||||
throw new BadRequestException(
|
||||
'There must be at least one workspace owner',
|
||||
);
|
||||
}
|
||||
|
||||
await this.userRepo.updateUser(
|
||||
{
|
||||
role: userRoleDto.role,
|
||||
},
|
||||
user.id,
|
||||
workspaceId,
|
||||
);
|
||||
}
|
||||
|
||||
async deactivateUser(): Promise<any> {
|
||||
return 'todo';
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,93 +4,85 @@ import {
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { CreateWorkspaceDto } from '../dto/create-workspace.dto';
|
||||
import { WorkspaceRepository } from '../repositories/workspace.repository';
|
||||
import { Workspace } from '../entities/workspace.entity';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { UpdateWorkspaceDto } from '../dto/update-workspace.dto';
|
||||
import { DeleteWorkspaceDto } from '../dto/delete-workspace.dto';
|
||||
import { SpaceService } from '../../space/services/space.service';
|
||||
import { DataSource, EntityManager } from 'typeorm';
|
||||
import { transactionWrapper } from '../../../helpers/db.helper';
|
||||
import { CreateSpaceDto } from '../../space/dto/create-space.dto';
|
||||
import { UserRepository } from '../../user/repositories/user.repository';
|
||||
import { SpaceRole, UserRole } from '../../../helpers/types/permission';
|
||||
import { User } from '../../user/entities/user.entity';
|
||||
import { EnvironmentService } from '../../../integrations/environment/environment.service';
|
||||
import { GroupService } from '../../group/services/group.service';
|
||||
import { GroupUserService } from '../../group/services/group-user.service';
|
||||
import { SpaceMemberService } from '../../space/services/space-member.service';
|
||||
import { WorkspaceRepo } from '@docmost/db/repos/workspace/workspace.repo';
|
||||
import { KyselyDB, KyselyTransaction } from '@docmost/db/types/kysely.types';
|
||||
import { executeTx } from '@docmost/db/utils';
|
||||
import { InjectKysely } from 'nestjs-kysely';
|
||||
import { User } from '@docmost/db/types/entity.types';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceService {
|
||||
constructor(
|
||||
private workspaceRepository: WorkspaceRepository,
|
||||
private userRepository: UserRepository,
|
||||
private workspaceRepo: WorkspaceRepo,
|
||||
private spaceService: SpaceService,
|
||||
private spaceMemberService: SpaceMemberService,
|
||||
private groupService: GroupService,
|
||||
private groupUserService: GroupUserService,
|
||||
private environmentService: EnvironmentService,
|
||||
|
||||
private dataSource: DataSource,
|
||||
@InjectKysely() private readonly db: KyselyDB,
|
||||
) {}
|
||||
|
||||
async findById(workspaceId: string): Promise<Workspace> {
|
||||
return this.workspaceRepository.findById(workspaceId);
|
||||
async findById(workspaceId: string) {
|
||||
return this.workspaceRepo.findById(workspaceId);
|
||||
}
|
||||
|
||||
async getWorkspaceInfo(workspaceId: string): Promise<Workspace> {
|
||||
const space = await this.workspaceRepository
|
||||
.createQueryBuilder('workspace')
|
||||
.where('workspace.id = :workspaceId', { workspaceId })
|
||||
.loadRelationCountAndMap(
|
||||
'workspace.memberCount',
|
||||
'workspace.users',
|
||||
'workspaceUsers',
|
||||
)
|
||||
.getOne();
|
||||
|
||||
if (!space) {
|
||||
async getWorkspaceInfo(workspaceId: string) {
|
||||
// todo: add member count
|
||||
const workspace = this.workspaceRepo.findById(workspaceId);
|
||||
if (!workspace) {
|
||||
throw new NotFoundException('Workspace not found');
|
||||
}
|
||||
|
||||
return space;
|
||||
return workspace;
|
||||
}
|
||||
|
||||
async create(
|
||||
user: User,
|
||||
createWorkspaceDto: CreateWorkspaceDto,
|
||||
manager?: EntityManager,
|
||||
): Promise<Workspace> {
|
||||
return await transactionWrapper(
|
||||
async (manager) => {
|
||||
let workspace = new Workspace();
|
||||
|
||||
workspace.name = createWorkspaceDto.name;
|
||||
workspace.hostname = createWorkspaceDto?.hostname;
|
||||
workspace.description = createWorkspaceDto.description;
|
||||
workspace.inviteCode = uuidv4();
|
||||
workspace.creatorId = user.id;
|
||||
workspace = await manager.save(workspace);
|
||||
trx?: KyselyTransaction,
|
||||
) {
|
||||
return await executeTx(
|
||||
this.db,
|
||||
async (trx) => {
|
||||
// create workspace
|
||||
const workspace = await this.workspaceRepo.insertWorkspace(
|
||||
{
|
||||
name: createWorkspaceDto.name,
|
||||
hostname: createWorkspaceDto.hostname,
|
||||
description: createWorkspaceDto.description,
|
||||
creatorId: user.id,
|
||||
},
|
||||
trx,
|
||||
);
|
||||
|
||||
// create default group
|
||||
const group = await this.groupService.createDefaultGroup(
|
||||
workspace.id,
|
||||
user.id,
|
||||
manager,
|
||||
trx,
|
||||
);
|
||||
|
||||
// attach user to workspace
|
||||
user.workspaceId = workspace.id;
|
||||
user.role = UserRole.OWNER;
|
||||
await manager.save(user);
|
||||
// add user to workspace
|
||||
await trx
|
||||
.updateTable('users')
|
||||
.set({
|
||||
workspaceId: workspace.id,
|
||||
role: UserRole.OWNER,
|
||||
})
|
||||
.execute();
|
||||
|
||||
// add user to default group
|
||||
await this.groupUserService.addUserToGroup(
|
||||
user.id,
|
||||
group.id,
|
||||
workspace.id,
|
||||
manager,
|
||||
trx,
|
||||
);
|
||||
|
||||
// create default space
|
||||
@ -98,12 +90,11 @@ export class WorkspaceService {
|
||||
name: 'General',
|
||||
};
|
||||
|
||||
// create default space
|
||||
const createdSpace = await this.spaceService.create(
|
||||
user.id,
|
||||
workspace.id,
|
||||
spaceInfo,
|
||||
manager,
|
||||
trx,
|
||||
);
|
||||
|
||||
// and add user to space as owner
|
||||
@ -112,7 +103,7 @@ export class WorkspaceService {
|
||||
createdSpace.id,
|
||||
SpaceRole.OWNER,
|
||||
workspace.id,
|
||||
manager,
|
||||
trx,
|
||||
);
|
||||
|
||||
// add default group to space as writer
|
||||
@ -121,50 +112,58 @@ export class WorkspaceService {
|
||||
createdSpace.id,
|
||||
SpaceRole.WRITER,
|
||||
workspace.id,
|
||||
manager,
|
||||
trx,
|
||||
);
|
||||
|
||||
// update default spaceId
|
||||
workspace.defaultSpaceId = createdSpace.id;
|
||||
await manager.save(workspace);
|
||||
await this.workspaceRepo.updateWorkspace(
|
||||
{
|
||||
defaultSpaceId: createdSpace.id,
|
||||
},
|
||||
workspace.id,
|
||||
trx,
|
||||
);
|
||||
return workspace;
|
||||
},
|
||||
this.dataSource,
|
||||
manager,
|
||||
trx,
|
||||
);
|
||||
}
|
||||
|
||||
async addUserToWorkspace(
|
||||
user: User,
|
||||
workspaceId,
|
||||
userId: string,
|
||||
workspaceId: string,
|
||||
assignedRole?: UserRole,
|
||||
manager?: EntityManager,
|
||||
trx?: KyselyTransaction,
|
||||
): Promise<void> {
|
||||
return await transactionWrapper(
|
||||
async (manager: EntityManager) => {
|
||||
const workspace = await manager.findOneBy(Workspace, {
|
||||
id: workspaceId,
|
||||
});
|
||||
return await executeTx(
|
||||
this.db,
|
||||
async (trx) => {
|
||||
const workspace = await trx
|
||||
.selectFrom('workspaces')
|
||||
.select(['id', 'defaultRole'])
|
||||
.where('workspaces.id', '=', workspaceId)
|
||||
.executeTakeFirst();
|
||||
|
||||
if (!workspace) {
|
||||
throw new BadRequestException('Workspace does not exist');
|
||||
throw new BadRequestException('Workspace not found');
|
||||
}
|
||||
|
||||
user.role = assignedRole ?? workspace.defaultRole;
|
||||
user.workspaceId = workspace.id;
|
||||
await manager.save(user);
|
||||
|
||||
// User is now added to the default space via the default group
|
||||
await trx
|
||||
.updateTable('users')
|
||||
.set({
|
||||
role: assignedRole ?? workspace.defaultRole,
|
||||
workspaceId: workspace.id,
|
||||
})
|
||||
.where('id', '=', userId)
|
||||
.execute();
|
||||
},
|
||||
this.dataSource,
|
||||
manager,
|
||||
trx,
|
||||
);
|
||||
}
|
||||
|
||||
async update(
|
||||
workspaceId: string,
|
||||
updateWorkspaceDto: UpdateWorkspaceDto,
|
||||
): Promise<Workspace> {
|
||||
const workspace = await this.workspaceRepository.findById(workspaceId);
|
||||
async update(workspaceId: string, updateWorkspaceDto: UpdateWorkspaceDto) {
|
||||
const workspace = await this.workspaceRepo.findById(workspaceId);
|
||||
if (!workspace) {
|
||||
throw new NotFoundException('Workspace not found');
|
||||
}
|
||||
@ -177,16 +176,15 @@ export class WorkspaceService {
|
||||
workspace.logo = updateWorkspaceDto.logo;
|
||||
}
|
||||
|
||||
return this.workspaceRepository.save(workspace);
|
||||
await this.workspaceRepo.updateWorkspace(updateWorkspaceDto, workspaceId);
|
||||
return workspace;
|
||||
}
|
||||
|
||||
async delete(deleteWorkspaceDto: DeleteWorkspaceDto): Promise<void> {
|
||||
const workspace = await this.workspaceRepository.findById(
|
||||
deleteWorkspaceDto.workspaceId,
|
||||
);
|
||||
async delete(workspaceId: string): Promise<void> {
|
||||
const workspace = await this.workspaceRepo.findById(workspaceId);
|
||||
if (!workspace) {
|
||||
throw new NotFoundException('Workspace not found');
|
||||
}
|
||||
// delete
|
||||
//delete
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,32 +1,20 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { WorkspaceService } from './services/workspace.service';
|
||||
import { WorkspaceController } from './controllers/workspace.controller';
|
||||
import { WorkspaceRepository } from './repositories/workspace.repository';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { Workspace } from './entities/workspace.entity';
|
||||
import { WorkspaceInvitation } from './entities/workspace-invitation.entity';
|
||||
import { SpaceModule } from '../space/space.module';
|
||||
import { WorkspaceInvitationService } from './services/workspace-invitation.service';
|
||||
import { WorkspaceInvitationRepository } from './repositories/workspace-invitation.repository';
|
||||
import { WorkspaceUserService } from './services/workspace-user.service';
|
||||
import { UserModule } from '../user/user.module';
|
||||
import { GroupModule } from '../group/group.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Workspace, WorkspaceInvitation]),
|
||||
SpaceModule,
|
||||
UserModule,
|
||||
GroupModule,
|
||||
],
|
||||
imports: [SpaceModule, UserModule, GroupModule],
|
||||
controllers: [WorkspaceController],
|
||||
providers: [
|
||||
WorkspaceService,
|
||||
WorkspaceUserService,
|
||||
WorkspaceInvitationService,
|
||||
WorkspaceRepository,
|
||||
WorkspaceInvitationRepository,
|
||||
],
|
||||
exports: [WorkspaceService, WorkspaceRepository],
|
||||
exports: [WorkspaceService],
|
||||
})
|
||||
export class WorkspaceModule {}
|
||||
|
||||
Reference in New Issue
Block a user