mirror of
https://github.com/Shadowfita/docmost.git
synced 2025-11-12 15:52:32 +10:00
Implement Space membership by group
* Add all users to default group * Fixes and updates
This commit is contained in:
@ -9,6 +9,7 @@ import { WorkspaceModule } from '../workspace/workspace.module';
|
|||||||
import { SignupService } from './services/signup.service';
|
import { SignupService } from './services/signup.service';
|
||||||
import { UserModule } from '../user/user.module';
|
import { UserModule } from '../user/user.module';
|
||||||
import { SpaceModule } from '../space/space.module';
|
import { SpaceModule } from '../space/space.module';
|
||||||
|
import { GroupModule } from '../group/group.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@ -26,6 +27,7 @@ import { SpaceModule } from '../space/space.module';
|
|||||||
UserModule,
|
UserModule,
|
||||||
WorkspaceModule,
|
WorkspaceModule,
|
||||||
SpaceModule,
|
SpaceModule,
|
||||||
|
GroupModule,
|
||||||
],
|
],
|
||||||
controllers: [AuthController],
|
controllers: [AuthController],
|
||||||
providers: [AuthService, SignupService, TokenService, JwtStrategy],
|
providers: [AuthService, SignupService, TokenService, JwtStrategy],
|
||||||
|
|||||||
@ -51,7 +51,7 @@ export class AuthService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async setup(createAdminUserDto: CreateAdminUserDto) {
|
async setup(createAdminUserDto: CreateAdminUserDto) {
|
||||||
const user: User = await this.signupService.firstSetup(createAdminUserDto);
|
const user: User = await this.signupService.initialSetup(createAdminUserDto);
|
||||||
|
|
||||||
const tokens: TokensDto = await this.tokenService.generateTokens(user);
|
const tokens: TokensDto = await this.tokenService.generateTokens(user);
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { CreateWorkspaceDto } from '../../workspace/dto/create-workspace.dto';
|
|||||||
import { Workspace } from '../../workspace/entities/workspace.entity';
|
import { Workspace } from '../../workspace/entities/workspace.entity';
|
||||||
import { SpaceService } from '../../space/space.service';
|
import { SpaceService } from '../../space/space.service';
|
||||||
import { CreateAdminUserDto } from '../dto/create-admin-user.dto';
|
import { CreateAdminUserDto } from '../dto/create-admin-user.dto';
|
||||||
|
import { GroupUserService } from '../../group/services/group-user.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SignupService {
|
export class SignupService {
|
||||||
@ -18,6 +19,7 @@ export class SignupService {
|
|||||||
private workspaceRepository: WorkspaceRepository,
|
private workspaceRepository: WorkspaceRepository,
|
||||||
private workspaceService: WorkspaceService,
|
private workspaceService: WorkspaceService,
|
||||||
private spaceService: SpaceService,
|
private spaceService: SpaceService,
|
||||||
|
private groupUserService: GroupUserService,
|
||||||
private dataSource: DataSource,
|
private dataSource: DataSource,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@ -39,7 +41,6 @@ export class SignupService {
|
|||||||
async (transactionManager: EntityManager) => {
|
async (transactionManager: EntityManager) => {
|
||||||
let user = this.prepareUser(createUserDto);
|
let user = this.prepareUser(createUserDto);
|
||||||
user = await transactionManager.save(user);
|
user = await transactionManager.save(user);
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
},
|
},
|
||||||
this.dataSource,
|
this.dataSource,
|
||||||
@ -57,7 +58,9 @@ export class SignupService {
|
|||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
if (userCheck) {
|
if (userCheck) {
|
||||||
throw new BadRequestException('You have an account on this workspace');
|
throw new BadRequestException(
|
||||||
|
'You already have an account on this workspace',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return await transactionWrapper(
|
return await transactionWrapper(
|
||||||
@ -72,6 +75,14 @@ export class SignupService {
|
|||||||
undefined,
|
undefined,
|
||||||
manager,
|
manager,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// add user to default group
|
||||||
|
await this.groupUserService.addUserToDefaultGroup(
|
||||||
|
user.id,
|
||||||
|
workspaceId,
|
||||||
|
manager,
|
||||||
|
);
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
},
|
},
|
||||||
this.dataSource,
|
this.dataSource,
|
||||||
@ -99,7 +110,7 @@ export class SignupService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async firstSetup(
|
async initialSetup(
|
||||||
createAdminUserDto: CreateAdminUserDto,
|
createAdminUserDto: CreateAdminUserDto,
|
||||||
manager?: EntityManager,
|
manager?: EntityManager,
|
||||||
): Promise<User> {
|
): Promise<User> {
|
||||||
@ -119,3 +130,11 @@ export class SignupService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create user -
|
||||||
|
// create workspace -
|
||||||
|
// create default group
|
||||||
|
// create space
|
||||||
|
// add group to space instead of user
|
||||||
|
|
||||||
|
// add new users to default group
|
||||||
|
|||||||
@ -10,3 +10,7 @@ export class CreateGroupDto {
|
|||||||
@IsString()
|
@IsString()
|
||||||
description?: string;
|
description?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum DefaultGroup {
|
||||||
|
EVERYONE = 'users',
|
||||||
|
}
|
||||||
|
|||||||
@ -20,7 +20,7 @@ export class GroupUser {
|
|||||||
@Column()
|
@Column()
|
||||||
userId: string;
|
userId: string;
|
||||||
|
|
||||||
@ManyToOne(() => User, (user) => user.groups, {
|
@ManyToOne(() => User, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn({ name: 'userId' })
|
@JoinColumn({ name: 'userId' })
|
||||||
|
|||||||
@ -11,8 +11,11 @@ import {
|
|||||||
import { GroupUser } from './group-user.entity';
|
import { GroupUser } from './group-user.entity';
|
||||||
import { Workspace } from '../../workspace/entities/workspace.entity';
|
import { Workspace } from '../../workspace/entities/workspace.entity';
|
||||||
import { User } from '../../user/entities/user.entity';
|
import { User } from '../../user/entities/user.entity';
|
||||||
|
import { Unique } from 'typeorm';
|
||||||
|
import { SpaceGroup } from '../../space/entities/space-group.entity';
|
||||||
|
|
||||||
@Entity('groups')
|
@Entity('groups')
|
||||||
|
@Unique(['name', 'workspaceId'])
|
||||||
export class Group {
|
export class Group {
|
||||||
@PrimaryGeneratedColumn('uuid')
|
@PrimaryGeneratedColumn('uuid')
|
||||||
id: string;
|
id: string;
|
||||||
@ -23,6 +26,9 @@ export class Group {
|
|||||||
@Column({ type: 'text', nullable: true })
|
@Column({ type: 'text', nullable: true })
|
||||||
description: string;
|
description: string;
|
||||||
|
|
||||||
|
@Column({ type: 'boolean', default: false })
|
||||||
|
isDefault: boolean;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
|
|
||||||
@ -32,7 +38,7 @@ export class Group {
|
|||||||
@JoinColumn({ name: 'workspaceId' })
|
@JoinColumn({ name: 'workspaceId' })
|
||||||
workspace: Workspace;
|
workspace: Workspace;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
creatorId: string;
|
creatorId: string;
|
||||||
|
|
||||||
@ManyToOne(() => User)
|
@ManyToOne(() => User)
|
||||||
@ -48,5 +54,8 @@ export class Group {
|
|||||||
@OneToMany(() => GroupUser, (groupUser) => groupUser.group)
|
@OneToMany(() => GroupUser, (groupUser) => groupUser.group)
|
||||||
groupUsers: GroupUser[];
|
groupUsers: GroupUser[];
|
||||||
|
|
||||||
|
@OneToMany(() => SpaceGroup, (spaceGroup) => spaceGroup.group)
|
||||||
|
spaces: SpaceGroup[];
|
||||||
|
|
||||||
userCount?: number;
|
userCount?: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -119,11 +119,12 @@ export class GroupController {
|
|||||||
removeGroupMember(
|
removeGroupMember(
|
||||||
@Body() removeGroupUserDto: RemoveGroupUserDto,
|
@Body() removeGroupUserDto: RemoveGroupUserDto,
|
||||||
//@AuthUser() user: User,
|
//@AuthUser() user: User,
|
||||||
//@CurrentWorkspace() workspace: Workspace,
|
@AuthWorkspace() workspace: Workspace,
|
||||||
) {
|
) {
|
||||||
return this.groupUserService.removeUserFromGroup(
|
return this.groupUserService.removeUserFromGroup(
|
||||||
removeGroupUserDto.userId,
|
removeGroupUserDto.userId,
|
||||||
removeGroupUserDto.groupId,
|
removeGroupUserDto.groupId,
|
||||||
|
workspace.id,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,5 +17,6 @@ import { GroupUserService } from './services/group-user.service';
|
|||||||
GroupRepository,
|
GroupRepository,
|
||||||
GroupUserRepository,
|
GroupUserRepository,
|
||||||
],
|
],
|
||||||
|
exports: [GroupService, GroupUserService],
|
||||||
})
|
})
|
||||||
export class GroupModule {}
|
export class GroupModule {}
|
||||||
|
|||||||
@ -27,7 +27,7 @@ export class GroupUserService {
|
|||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
paginationOptions: PaginationOptions,
|
paginationOptions: PaginationOptions,
|
||||||
): Promise<PaginatedResult<User>> {
|
): Promise<PaginatedResult<User>> {
|
||||||
await this.groupService.validateGroup(groupId, workspaceId);
|
await this.groupService.findAndValidateGroup(groupId, workspaceId);
|
||||||
|
|
||||||
const [groupUsers, count] = await this.groupUserRepository.findAndCount({
|
const [groupUsers, count] = await this.groupUserRepository.findAndCount({
|
||||||
relations: ['user'],
|
relations: ['user'],
|
||||||
@ -49,16 +49,36 @@ export class GroupUserService {
|
|||||||
return new PaginatedResult(users, paginationMeta);
|
return new PaginatedResult(users, paginationMeta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async addUserToDefaultGroup(
|
||||||
|
userId: string,
|
||||||
|
workspaceId: string,
|
||||||
|
manager?: EntityManager,
|
||||||
|
): Promise<void> {
|
||||||
|
return await transactionWrapper(
|
||||||
|
async (manager) => {
|
||||||
|
const defaultGroup = await this.groupService.getDefaultGroup(
|
||||||
|
workspaceId,
|
||||||
|
manager,
|
||||||
|
);
|
||||||
|
await this.addUserToGroup(
|
||||||
|
userId,
|
||||||
|
defaultGroup.id,
|
||||||
|
workspaceId,
|
||||||
|
manager,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
this.dataSource,
|
||||||
|
manager,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async addUserToGroup(
|
async addUserToGroup(
|
||||||
userId: string,
|
userId: string,
|
||||||
groupId: string,
|
groupId: string,
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
manager?: EntityManager,
|
manager?: EntityManager,
|
||||||
): Promise<any> {
|
): Promise<GroupUser> {
|
||||||
let addedUser;
|
return await transactionWrapper(
|
||||||
|
|
||||||
/*
|
|
||||||
await transactionWrapper(
|
|
||||||
async (manager) => {
|
async (manager) => {
|
||||||
const group = await manager.findOneBy(Group, {
|
const group = await manager.findOneBy(Group, {
|
||||||
id: groupId,
|
id: groupId,
|
||||||
@ -69,21 +89,18 @@ export class GroupUserService {
|
|||||||
throw new NotFoundException('Group not found');
|
throw new NotFoundException('Group not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
const userExists = await manager.exists(User, {
|
const find = await manager.findOne(User, {
|
||||||
where: { id: userId },
|
where: { id: userId },
|
||||||
});
|
});
|
||||||
if (!userExists) {
|
|
||||||
throw new NotFoundException('User not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
// only workspace users can be added to workspace groups
|
console.log(find);
|
||||||
const workspaceUser = await manager.findOneBy(WorkspaceUser, {
|
|
||||||
userId: userId,
|
const userExists = await manager.exists(User, {
|
||||||
workspaceId: workspaceId,
|
where: { id: userId, workspaceId },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!workspaceUser) {
|
if (!userExists) {
|
||||||
throw new NotFoundException('User is not a member of this workspace');
|
throw new NotFoundException('User not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
const existingGroupUser = await manager.findOneBy(GroupUser, {
|
const existingGroupUser = await manager.findOneBy(GroupUser, {
|
||||||
@ -101,16 +118,29 @@ export class GroupUserService {
|
|||||||
groupUser.userId = userId;
|
groupUser.userId = userId;
|
||||||
groupUser.groupId = groupId;
|
groupUser.groupId = groupId;
|
||||||
|
|
||||||
addedUser = await manager.save(groupUser);
|
return manager.save(groupUser);
|
||||||
},
|
},
|
||||||
this.dataSource,
|
this.dataSource,
|
||||||
manager,
|
manager,
|
||||||
);
|
);
|
||||||
*/
|
|
||||||
return addedUser;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeUserFromGroup(userId: string, groupId: string): Promise<void> {
|
async removeUserFromGroup(
|
||||||
|
userId: string,
|
||||||
|
groupId: string,
|
||||||
|
workspaceId: string,
|
||||||
|
): Promise<void> {
|
||||||
|
const group = await this.groupService.findAndValidateGroup(
|
||||||
|
groupId,
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (group.isDefault) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
'You cannot remove users from a default group',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const groupUser = await this.getGroupUser(userId, groupId);
|
const groupUser = await this.getGroupUser(userId, groupId);
|
||||||
|
|
||||||
if (!groupUser) {
|
if (!groupUser) {
|
||||||
@ -129,12 +159,4 @@ export class GroupUserService {
|
|||||||
groupId,
|
groupId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getGroupUserCount(groupId: string): Promise<number> {
|
|
||||||
return await this.groupUserRepository.count({
|
|
||||||
where: {
|
|
||||||
groupId: groupId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
import {
|
||||||
import { CreateGroupDto } from '../dto/create-group.dto';
|
BadRequestException,
|
||||||
|
Injectable,
|
||||||
|
NotFoundException,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { CreateGroupDto, DefaultGroup } from '../dto/create-group.dto';
|
||||||
import { GroupRepository } from '../respositories/group.repository';
|
import { GroupRepository } from '../respositories/group.repository';
|
||||||
import { Group } from '../entities/group.entity';
|
import { Group } from '../entities/group.entity';
|
||||||
import { plainToInstance } from 'class-transformer';
|
import { plainToInstance } from 'class-transformer';
|
||||||
@ -8,10 +12,15 @@ import { PaginationMetaDto } from '../../../helpers/pagination/pagination-meta-d
|
|||||||
import { PaginatedResult } from '../../../helpers/pagination/paginated-result';
|
import { PaginatedResult } from '../../../helpers/pagination/paginated-result';
|
||||||
import { PaginationOptions } from '../../../helpers/pagination/pagination-options';
|
import { PaginationOptions } from '../../../helpers/pagination/pagination-options';
|
||||||
import { UpdateGroupDto } from '../dto/update-group.dto';
|
import { UpdateGroupDto } from '../dto/update-group.dto';
|
||||||
|
import { DataSource, EntityManager } from 'typeorm';
|
||||||
|
import { transactionWrapper } from '../../../helpers/db.helper';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GroupService {
|
export class GroupService {
|
||||||
constructor(private groupRepository: GroupRepository) {}
|
constructor(
|
||||||
|
private groupRepository: GroupRepository,
|
||||||
|
private dataSource: DataSource,
|
||||||
|
) {}
|
||||||
|
|
||||||
async createGroup(
|
async createGroup(
|
||||||
authUser: User,
|
authUser: User,
|
||||||
@ -22,9 +31,52 @@ export class GroupService {
|
|||||||
group.creatorId = authUser.id;
|
group.creatorId = authUser.id;
|
||||||
group.workspaceId = workspaceId;
|
group.workspaceId = workspaceId;
|
||||||
|
|
||||||
|
const groupExists = await this.findGroupByName(
|
||||||
|
createGroupDto.name,
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
if (groupExists) {
|
||||||
|
throw new BadRequestException('Group name already exists');
|
||||||
|
}
|
||||||
|
|
||||||
return await this.groupRepository.save(group);
|
return await this.groupRepository.save(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async createDefaultGroup(
|
||||||
|
workspaceId: string,
|
||||||
|
userId?: string,
|
||||||
|
manager?: EntityManager,
|
||||||
|
): Promise<Group> {
|
||||||
|
return await transactionWrapper(
|
||||||
|
async (manager: EntityManager) => {
|
||||||
|
const group = new Group();
|
||||||
|
group.name = DefaultGroup.EVERYONE;
|
||||||
|
group.isDefault = true;
|
||||||
|
group.creatorId = userId ?? null;
|
||||||
|
group.workspaceId = workspaceId;
|
||||||
|
return await manager.save(group);
|
||||||
|
},
|
||||||
|
this.dataSource,
|
||||||
|
manager,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getDefaultGroup(
|
||||||
|
workspaceId: string,
|
||||||
|
manager: EntityManager,
|
||||||
|
): Promise<Group> {
|
||||||
|
return await transactionWrapper(
|
||||||
|
async (manager: EntityManager) => {
|
||||||
|
return await manager.findOneBy(Group, {
|
||||||
|
isDefault: true,
|
||||||
|
workspaceId,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
this.dataSource,
|
||||||
|
manager,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async updateGroup(
|
async updateGroup(
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
updateGroupDto: UpdateGroupDto,
|
updateGroupDto: UpdateGroupDto,
|
||||||
@ -38,6 +90,18 @@ export class GroupService {
|
|||||||
throw new NotFoundException('Group not found');
|
throw new NotFoundException('Group not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (group.isDefault) {
|
||||||
|
throw new BadRequestException('You cannot update a default group');
|
||||||
|
}
|
||||||
|
|
||||||
|
const groupExists = await this.findGroupByName(
|
||||||
|
updateGroupDto.name,
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
if (groupExists) {
|
||||||
|
throw new BadRequestException('Group name already exists');
|
||||||
|
}
|
||||||
|
|
||||||
if (updateGroupDto.name) {
|
if (updateGroupDto.name) {
|
||||||
group.name = updateGroupDto.name;
|
group.name = updateGroupDto.name;
|
||||||
}
|
}
|
||||||
@ -90,19 +154,38 @@ export class GroupService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async deleteGroup(groupId: string, workspaceId: string): Promise<void> {
|
async deleteGroup(groupId: string, workspaceId: string): Promise<void> {
|
||||||
await this.validateGroup(groupId, workspaceId);
|
const group = await this.findAndValidateGroup(groupId, workspaceId);
|
||||||
|
if (group.isDefault) {
|
||||||
|
throw new BadRequestException('You cannot delete a default group');
|
||||||
|
}
|
||||||
await this.groupRepository.delete(groupId);
|
await this.groupRepository.delete(groupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async validateGroup(groupId: string, workspaceId: string): Promise<void> {
|
async findAndValidateGroup(
|
||||||
const groupExists = await this.groupRepository.exists({
|
groupId: string,
|
||||||
|
workspaceId: string,
|
||||||
|
): Promise<Group> {
|
||||||
|
const group = await this.groupRepository.findOne({
|
||||||
where: {
|
where: {
|
||||||
id: groupId,
|
id: groupId,
|
||||||
workspaceId: workspaceId,
|
workspaceId: workspaceId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (!groupExists) {
|
if (!group) {
|
||||||
throw new NotFoundException('Group not found');
|
throw new NotFoundException('Group not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
async findGroupByName(
|
||||||
|
groupName: string,
|
||||||
|
workspaceId: string,
|
||||||
|
): Promise<Group> {
|
||||||
|
return this.groupRepository
|
||||||
|
.createQueryBuilder('group')
|
||||||
|
.where('LOWER(group.name) = LOWER(:groupName)', { groupName })
|
||||||
|
.andWhere('group.workspaceId = :workspaceId', { workspaceId })
|
||||||
|
.getOne();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
45
apps/server/src/core/space/entities/space-group.entity.ts
Normal file
45
apps/server/src/core/space/entities/space-group.entity.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
ManyToOne,
|
||||||
|
JoinColumn,
|
||||||
|
Unique,
|
||||||
|
} from 'typeorm';
|
||||||
|
import { Space } from './space.entity';
|
||||||
|
import { Group } from '../../group/entities/group.entity';
|
||||||
|
|
||||||
|
@Entity('space_groups')
|
||||||
|
@Unique(['spaceId', 'groupId'])
|
||||||
|
export class SpaceGroup {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
groupId: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => Group, (group) => group.spaces, {
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
})
|
||||||
|
@JoinColumn({ name: 'groupId' })
|
||||||
|
group: Group;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
spaceId: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => Space, (space) => space.spaceGroups, {
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
})
|
||||||
|
space: Space;
|
||||||
|
|
||||||
|
@Column({ length: 100, nullable: true })
|
||||||
|
role: string;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt: Date;
|
||||||
|
}
|
||||||
@ -14,6 +14,7 @@ import { Workspace } from '../../workspace/entities/workspace.entity';
|
|||||||
import { SpaceUser } from './space-user.entity';
|
import { SpaceUser } from './space-user.entity';
|
||||||
import { Page } from '../../page/entities/page.entity';
|
import { Page } from '../../page/entities/page.entity';
|
||||||
import { SpacePrivacy, SpaceRole } from '../../../helpers/types/permission';
|
import { SpacePrivacy, SpaceRole } from '../../../helpers/types/permission';
|
||||||
|
import { SpaceGroup } from './space-group.entity';
|
||||||
|
|
||||||
@Entity('spaces')
|
@Entity('spaces')
|
||||||
@Unique(['slug', 'workspaceId'])
|
@Unique(['slug', 'workspaceId'])
|
||||||
@ -42,7 +43,7 @@ export class Space {
|
|||||||
@Column()
|
@Column()
|
||||||
creatorId: string;
|
creatorId: string;
|
||||||
|
|
||||||
@ManyToOne(() => User, (user) => user.spaces)
|
@ManyToOne(() => User)
|
||||||
@JoinColumn({ name: 'creatorId' })
|
@JoinColumn({ name: 'creatorId' })
|
||||||
creator: User;
|
creator: User;
|
||||||
|
|
||||||
@ -58,6 +59,9 @@ export class Space {
|
|||||||
@OneToMany(() => SpaceUser, (spaceUser) => spaceUser.space)
|
@OneToMany(() => SpaceUser, (spaceUser) => spaceUser.space)
|
||||||
spaceUsers: SpaceUser[];
|
spaceUsers: SpaceUser[];
|
||||||
|
|
||||||
|
@OneToMany(() => SpaceGroup, (spaceGroup) => spaceGroup.space)
|
||||||
|
spaceGroups: SpaceGroup[];
|
||||||
|
|
||||||
@OneToMany(() => Page, (page) => page.space)
|
@OneToMany(() => Page, (page) => page.space)
|
||||||
pages: Page[];
|
pages: Page[];
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { DataSource, Repository } from 'typeorm';
|
||||||
|
import { SpaceGroup } from '../entities/space-group.entity';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SpaceGroupRepository extends Repository<SpaceGroup> {
|
||||||
|
constructor(private dataSource: DataSource) {
|
||||||
|
super(SpaceGroup, dataSource.createEntityManager());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -57,6 +57,7 @@ export class SpaceController {
|
|||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
@Post('members')
|
@Post('members')
|
||||||
async getSpaceMembers(
|
async getSpaceMembers(
|
||||||
|
// todo: accept type? users | groups
|
||||||
@Body() spaceIdDto: SpaceIdDto,
|
@Body() spaceIdDto: SpaceIdDto,
|
||||||
@Body()
|
@Body()
|
||||||
pagination: PaginationOptions,
|
pagination: PaginationOptions,
|
||||||
|
|||||||
@ -6,11 +6,18 @@ import { Space } from './entities/space.entity';
|
|||||||
import { SpaceUser } from './entities/space-user.entity';
|
import { SpaceUser } from './entities/space-user.entity';
|
||||||
import { SpaceRepository } from './repositories/space.repository';
|
import { SpaceRepository } from './repositories/space.repository';
|
||||||
import { SpaceUserRepository } from './repositories/space-user.repository';
|
import { SpaceUserRepository } from './repositories/space-user.repository';
|
||||||
|
import { SpaceGroup } from './entities/space-group.entity';
|
||||||
|
import { SpaceGroupRepository } from './repositories/space-group.repository';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TypeOrmModule.forFeature([Space, SpaceUser])],
|
imports: [TypeOrmModule.forFeature([Space, SpaceUser, SpaceGroup])],
|
||||||
controllers: [SpaceController],
|
controllers: [SpaceController],
|
||||||
providers: [SpaceService, SpaceRepository, SpaceUserRepository],
|
providers: [
|
||||||
exports: [SpaceService, SpaceRepository, SpaceUserRepository],
|
SpaceService,
|
||||||
|
SpaceRepository,
|
||||||
|
SpaceUserRepository,
|
||||||
|
SpaceGroupRepository,
|
||||||
|
],
|
||||||
|
exports: [SpaceService],
|
||||||
})
|
})
|
||||||
export class SpaceModule {}
|
export class SpaceModule {}
|
||||||
|
|||||||
@ -14,12 +14,16 @@ import { User } from '../user/entities/user.entity';
|
|||||||
import { PaginationOptions } from '../../helpers/pagination/pagination-options';
|
import { PaginationOptions } from '../../helpers/pagination/pagination-options';
|
||||||
import { PaginationMetaDto } from '../../helpers/pagination/pagination-meta-dto';
|
import { PaginationMetaDto } from '../../helpers/pagination/pagination-meta-dto';
|
||||||
import { PaginatedResult } from '../../helpers/pagination/paginated-result';
|
import { PaginatedResult } from '../../helpers/pagination/paginated-result';
|
||||||
|
import { SpaceGroupRepository } from './repositories/space-group.repository';
|
||||||
|
import { Group } from '../group/entities/group.entity';
|
||||||
|
import { SpaceGroup } from './entities/space-group.entity';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SpaceService {
|
export class SpaceService {
|
||||||
constructor(
|
constructor(
|
||||||
private spaceRepository: SpaceRepository,
|
private spaceRepository: SpaceRepository,
|
||||||
private spaceUserRepository: SpaceUserRepository,
|
private spaceUserRepository: SpaceUserRepository,
|
||||||
|
private spaceGroupRepository: SpaceGroupRepository,
|
||||||
private dataSource: DataSource,
|
private dataSource: DataSource,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@ -94,7 +98,7 @@ export class SpaceService {
|
|||||||
'space.userCount',
|
'space.userCount',
|
||||||
'space.spaceUsers',
|
'space.spaceUsers',
|
||||||
'spaceUsers',
|
'spaceUsers',
|
||||||
)
|
) // TODO: add groups to userCount
|
||||||
.getOne();
|
.getOne();
|
||||||
|
|
||||||
if (!space) {
|
if (!space) {
|
||||||
@ -115,7 +119,7 @@ export class SpaceService {
|
|||||||
'space.userCount',
|
'space.userCount',
|
||||||
'space.spaceUsers',
|
'space.spaceUsers',
|
||||||
'spaceUsers',
|
'spaceUsers',
|
||||||
)
|
) // TODO: add groups to userCount
|
||||||
.take(paginationOptions.limit)
|
.take(paginationOptions.limit)
|
||||||
.skip(paginationOptions.skip)
|
.skip(paginationOptions.skip)
|
||||||
.getManyAndCount();
|
.getManyAndCount();
|
||||||
@ -178,4 +182,71 @@ export class SpaceService {
|
|||||||
const paginationMeta = new PaginationMetaDto({ count, paginationOptions });
|
const paginationMeta = new PaginationMetaDto({ count, paginationOptions });
|
||||||
return new PaginatedResult(users, paginationMeta);
|
return new PaginatedResult(users, paginationMeta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async addGroupToSpace(
|
||||||
|
groupId: string,
|
||||||
|
spaceId: string,
|
||||||
|
role: string,
|
||||||
|
workspaceId,
|
||||||
|
manager?: EntityManager,
|
||||||
|
): Promise<SpaceGroup> {
|
||||||
|
return await transactionWrapper(
|
||||||
|
async (manager: EntityManager) => {
|
||||||
|
const groupExists = await manager.exists(Group, {
|
||||||
|
where: { id: groupId, workspaceId },
|
||||||
|
});
|
||||||
|
if (!groupExists) {
|
||||||
|
throw new NotFoundException('Group not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingSpaceGroup = await manager.findOneBy(SpaceGroup, {
|
||||||
|
groupId: groupId,
|
||||||
|
spaceId: spaceId,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (existingSpaceGroup) {
|
||||||
|
throw new BadRequestException('Group already added to this space');
|
||||||
|
}
|
||||||
|
|
||||||
|
const spaceGroup = new SpaceGroup();
|
||||||
|
spaceGroup.groupId = groupId;
|
||||||
|
spaceGroup.spaceId = spaceId;
|
||||||
|
spaceGroup.role = role;
|
||||||
|
await manager.save(spaceGroup);
|
||||||
|
|
||||||
|
return spaceGroup;
|
||||||
|
},
|
||||||
|
this.dataSource,
|
||||||
|
manager,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getSpaceGroups(
|
||||||
|
spaceId: string,
|
||||||
|
workspaceId: string,
|
||||||
|
paginationOptions: PaginationOptions,
|
||||||
|
) {
|
||||||
|
const [spaceGroups, count] = await this.spaceGroupRepository.findAndCount({
|
||||||
|
relations: ['group'],
|
||||||
|
where: {
|
||||||
|
space: {
|
||||||
|
id: spaceId,
|
||||||
|
workspaceId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
take: paginationOptions.limit,
|
||||||
|
skip: paginationOptions.skip,
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: add group userCount
|
||||||
|
const groups = spaceGroups.map((spaceGroup) => {
|
||||||
|
return {
|
||||||
|
...spaceGroup.group,
|
||||||
|
spaceRole: spaceGroup.role,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const paginationMeta = new PaginationMetaDto({ count, paginationOptions });
|
||||||
|
return new PaginatedResult(groups, paginationMeta);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,6 @@ import { Page } from '../../page/entities/page.entity';
|
|||||||
import { Comment } from '../../comment/entities/comment.entity';
|
import { Comment } from '../../comment/entities/comment.entity';
|
||||||
import { Space } from '../../space/entities/space.entity';
|
import { Space } from '../../space/entities/space.entity';
|
||||||
import { SpaceUser } from '../../space/entities/space-user.entity';
|
import { SpaceUser } from '../../space/entities/space-user.entity';
|
||||||
import { Group } from '../../group/entities/group.entity';
|
|
||||||
|
|
||||||
@Entity('users')
|
@Entity('users')
|
||||||
@Unique(['email', 'workspaceId'])
|
@Unique(['email', 'workspaceId'])
|
||||||
@ -44,7 +43,9 @@ export class User {
|
|||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
|
|
||||||
@ManyToOne(() => Workspace, (workspace) => workspace.users)
|
@ManyToOne(() => Workspace, (workspace) => workspace.users, {
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
})
|
||||||
workspace: Workspace;
|
workspace: Workspace;
|
||||||
|
|
||||||
@Column({ length: 100, nullable: true })
|
@Column({ length: 100, nullable: true })
|
||||||
@ -68,9 +69,6 @@ export class User {
|
|||||||
@UpdateDateColumn()
|
@UpdateDateColumn()
|
||||||
updatedAt: Date;
|
updatedAt: Date;
|
||||||
|
|
||||||
@OneToMany(() => Group, (group) => group.creator)
|
|
||||||
groups: Group[];
|
|
||||||
|
|
||||||
@OneToMany(() => Page, (page) => page.creator)
|
@OneToMany(() => Page, (page) => page.creator)
|
||||||
createdPages: Page[];
|
createdPages: Page[];
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,8 @@ import { UserRepository } from '../../user/repositories/user.repository';
|
|||||||
import { SpaceRole, UserRole } from '../../../helpers/types/permission';
|
import { SpaceRole, UserRole } from '../../../helpers/types/permission';
|
||||||
import { User } from '../../user/entities/user.entity';
|
import { User } from '../../user/entities/user.entity';
|
||||||
import { EnvironmentService } from '../../../environment/environment.service';
|
import { EnvironmentService } from '../../../environment/environment.service';
|
||||||
import { Space } from '../../space/entities/space.entity';
|
import { GroupService } from '../../group/services/group.service';
|
||||||
|
import { GroupUserService } from '../../group/services/group-user.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class WorkspaceService {
|
export class WorkspaceService {
|
||||||
@ -25,6 +26,8 @@ export class WorkspaceService {
|
|||||||
private workspaceRepository: WorkspaceRepository,
|
private workspaceRepository: WorkspaceRepository,
|
||||||
private userRepository: UserRepository,
|
private userRepository: UserRepository,
|
||||||
private spaceService: SpaceService,
|
private spaceService: SpaceService,
|
||||||
|
private groupService: GroupService,
|
||||||
|
private groupUserService: GroupUserService,
|
||||||
private environmentService: EnvironmentService,
|
private environmentService: EnvironmentService,
|
||||||
|
|
||||||
private dataSource: DataSource,
|
private dataSource: DataSource,
|
||||||
@ -68,12 +71,28 @@ export class WorkspaceService {
|
|||||||
workspace.creatorId = user.id;
|
workspace.creatorId = user.id;
|
||||||
workspace = await manager.save(workspace);
|
workspace = await manager.save(workspace);
|
||||||
|
|
||||||
|
// create default group
|
||||||
|
const group = await this.groupService.createDefaultGroup(
|
||||||
|
workspace.id,
|
||||||
|
user.id,
|
||||||
|
manager,
|
||||||
|
);
|
||||||
|
|
||||||
|
// attach user to workspace
|
||||||
user.workspaceId = workspace.id;
|
user.workspaceId = workspace.id;
|
||||||
user.role = UserRole.OWNER;
|
user.role = UserRole.OWNER;
|
||||||
await manager.save(user);
|
await manager.save(user);
|
||||||
|
|
||||||
|
// add user to default group
|
||||||
|
await this.groupUserService.addUserToGroup(
|
||||||
|
user.id,
|
||||||
|
group.id,
|
||||||
|
workspace.id,
|
||||||
|
manager,
|
||||||
|
);
|
||||||
|
|
||||||
// create default space
|
// create default space
|
||||||
const spaceData: CreateSpaceDto = {
|
const spaceInfo: CreateSpaceDto = {
|
||||||
name: 'General',
|
name: 'General',
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -81,11 +100,11 @@ export class WorkspaceService {
|
|||||||
const createdSpace = await this.spaceService.create(
|
const createdSpace = await this.spaceService.create(
|
||||||
user.id,
|
user.id,
|
||||||
workspace.id,
|
workspace.id,
|
||||||
spaceData,
|
spaceInfo,
|
||||||
manager,
|
manager,
|
||||||
);
|
);
|
||||||
|
|
||||||
// and add user to it too.
|
// and add user to space as owner
|
||||||
await this.spaceService.addUserToSpace(
|
await this.spaceService.addUserToSpace(
|
||||||
user.id,
|
user.id,
|
||||||
createdSpace.id,
|
createdSpace.id,
|
||||||
@ -94,6 +113,15 @@ export class WorkspaceService {
|
|||||||
manager,
|
manager,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// add default group to space as writer
|
||||||
|
await this.spaceService.addGroupToSpace(
|
||||||
|
group.id,
|
||||||
|
createdSpace.id,
|
||||||
|
SpaceRole.WRITER,
|
||||||
|
workspace.id,
|
||||||
|
manager,
|
||||||
|
);
|
||||||
|
|
||||||
workspace.defaultSpaceId = createdSpace.id;
|
workspace.defaultSpaceId = createdSpace.id;
|
||||||
await manager.save(workspace);
|
await manager.save(workspace);
|
||||||
return workspace;
|
return workspace;
|
||||||
@ -108,7 +136,7 @@ export class WorkspaceService {
|
|||||||
workspaceId,
|
workspaceId,
|
||||||
assignedRole?: UserRole,
|
assignedRole?: UserRole,
|
||||||
manager?: EntityManager,
|
manager?: EntityManager,
|
||||||
): Promise<Workspace> {
|
): Promise<void> {
|
||||||
return await transactionWrapper(
|
return await transactionWrapper(
|
||||||
async (manager: EntityManager) => {
|
async (manager: EntityManager) => {
|
||||||
const workspace = await manager.findOneBy(Workspace, {
|
const workspace = await manager.findOneBy(Workspace, {
|
||||||
@ -123,25 +151,7 @@ export class WorkspaceService {
|
|||||||
user.workspaceId = workspace.id;
|
user.workspaceId = workspace.id;
|
||||||
await manager.save(user);
|
await manager.save(user);
|
||||||
|
|
||||||
const space = await manager.findOneBy(Space, {
|
// User is now added to the default space via the default group
|
||||||
id: workspace.defaultSpaceId,
|
|
||||||
workspaceId,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!space) {
|
|
||||||
throw new NotFoundException('Space not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
// add user to default space
|
|
||||||
await this.spaceService.addUserToSpace(
|
|
||||||
user.id,
|
|
||||||
space.id,
|
|
||||||
space.defaultRole,
|
|
||||||
workspace.id,
|
|
||||||
manager,
|
|
||||||
);
|
|
||||||
|
|
||||||
return workspace;
|
|
||||||
},
|
},
|
||||||
this.dataSource,
|
this.dataSource,
|
||||||
manager,
|
manager,
|
||||||
@ -175,9 +185,6 @@ export class WorkspaceService {
|
|||||||
if (!workspace) {
|
if (!workspace) {
|
||||||
throw new NotFoundException('Workspace not found');
|
throw new NotFoundException('Workspace not found');
|
||||||
}
|
}
|
||||||
|
// delete
|
||||||
//TODO
|
|
||||||
// remove all existing users from workspace
|
|
||||||
// delete workspace
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,11 +10,14 @@ import { WorkspaceInvitationService } from './services/workspace-invitation.serv
|
|||||||
import { WorkspaceInvitationRepository } from './repositories/workspace-invitation.repository';
|
import { WorkspaceInvitationRepository } from './repositories/workspace-invitation.repository';
|
||||||
import { WorkspaceUserService } from './services/workspace-user.service';
|
import { WorkspaceUserService } from './services/workspace-user.service';
|
||||||
import { UserModule } from '../user/user.module';
|
import { UserModule } from '../user/user.module';
|
||||||
|
import { GroupModule } from '../group/group.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
TypeOrmModule.forFeature([Workspace, WorkspaceInvitation]),
|
TypeOrmModule.forFeature([Workspace, WorkspaceInvitation]),
|
||||||
SpaceModule, UserModule
|
SpaceModule,
|
||||||
|
UserModule,
|
||||||
|
GroupModule,
|
||||||
],
|
],
|
||||||
controllers: [WorkspaceController],
|
controllers: [WorkspaceController],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@ -0,0 +1,22 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class AddDefaultGroup1710886360227 implements MigrationInterface {
|
||||||
|
name = 'AddDefaultGroup1710886360227'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "groups" ADD "isDefault" boolean NOT NULL DEFAULT false`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "groups" DROP CONSTRAINT "FK_accb24ba8f4f213f33d08e2a20f"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "groups" ALTER COLUMN "creatorId" DROP NOT NULL`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "groups" ADD CONSTRAINT "UQ_c092c7c01795e6ad7af46bf2d24" UNIQUE ("name", "workspaceId")`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "groups" ADD CONSTRAINT "FK_accb24ba8f4f213f33d08e2a20f" FOREIGN KEY ("creatorId") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "groups" DROP CONSTRAINT "FK_accb24ba8f4f213f33d08e2a20f"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "groups" DROP CONSTRAINT "UQ_c092c7c01795e6ad7af46bf2d24"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "groups" ALTER COLUMN "creatorId" SET NOT NULL`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "groups" ADD CONSTRAINT "FK_accb24ba8f4f213f33d08e2a20f" FOREIGN KEY ("creatorId") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "groups" DROP COLUMN "isDefault"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class SpaceGroupsMembership1710892343941 implements MigrationInterface {
|
||||||
|
name = 'SpaceGroupsMembership1710892343941'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`CREATE TABLE "space_groups" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "groupId" uuid NOT NULL, "spaceId" uuid NOT NULL, "role" character varying(100), "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "UQ_68e59d7b983dfefc7d33febe4c3" UNIQUE ("spaceId", "groupId"), CONSTRAINT "PK_31f9b87a8dced378cb68f04836b" PRIMARY KEY ("id"))`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "space_groups" ADD CONSTRAINT "FK_b3950d22b51148de9e14a1e5020" FOREIGN KEY ("groupId") REFERENCES "groups"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "space_groups" ADD CONSTRAINT "FK_80567cbf54af9e8e8ec469d247d" FOREIGN KEY ("spaceId") REFERENCES "spaces"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "space_groups" DROP CONSTRAINT "FK_80567cbf54af9e8e8ec469d247d"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "space_groups" DROP CONSTRAINT "FK_b3950d22b51148de9e14a1e5020"`);
|
||||||
|
await queryRunner.query(`DROP TABLE "space_groups"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class AddWorkspaceCascadeToUser1710894465616 implements MigrationInterface {
|
||||||
|
name = 'AddWorkspaceCascadeToUser1710894465616'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" DROP CONSTRAINT "FK_949fea12b7977a8b2f483bf802a"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" ADD CONSTRAINT "FK_949fea12b7977a8b2f483bf802a" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" DROP CONSTRAINT "FK_949fea12b7977a8b2f483bf802a"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "users" ADD CONSTRAINT "FK_949fea12b7977a8b2f483bf802a" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user