mirror of
https://github.com/docmost/docmost.git
synced 2025-11-22 04:01:12 +10:00
switch to nx monorepo
This commit is contained in:
@ -0,0 +1,20 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { WorkspaceController } from './workspace.controller';
|
||||
import { WorkspaceService } from '../services/workspace.service';
|
||||
|
||||
describe('WorkspaceController', () => {
|
||||
let controller: WorkspaceController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [WorkspaceController],
|
||||
providers: [WorkspaceService],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<WorkspaceController>(WorkspaceController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,120 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
HttpCode,
|
||||
HttpStatus,
|
||||
Post,
|
||||
Req,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { WorkspaceService } from '../services/workspace.service';
|
||||
import { FastifyRequest } from 'fastify';
|
||||
import { JwtGuard } from '../../auth/guards/JwtGuard';
|
||||
import { UpdateWorkspaceDto } from '../dto/update-workspace.dto';
|
||||
import { CreateWorkspaceDto } from '../dto/create-workspace.dto';
|
||||
import { DeleteWorkspaceDto } from '../dto/delete-workspace.dto';
|
||||
import { UpdateWorkspaceUserRoleDto } from '../dto/update-workspace-user-role.dto';
|
||||
import { RemoveWorkspaceUserDto } from '../dto/remove-workspace-user.dto';
|
||||
import { AddWorkspaceUserDto } from '../dto/add-workspace-user.dto';
|
||||
|
||||
@UseGuards(JwtGuard)
|
||||
@Controller('workspace')
|
||||
export class WorkspaceController {
|
||||
constructor(private readonly workspaceService: WorkspaceService) {}
|
||||
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post('create')
|
||||
async createWorkspace(
|
||||
@Req() req: FastifyRequest,
|
||||
@Body() createWorkspaceDto: CreateWorkspaceDto,
|
||||
) {
|
||||
const jwtPayload = req['user'];
|
||||
const userId = jwtPayload.sub;
|
||||
return this.workspaceService.create(userId, createWorkspaceDto);
|
||||
}
|
||||
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post('update')
|
||||
async updateWorkspace(
|
||||
@Req() req: FastifyRequest,
|
||||
@Body() updateWorkspaceDto: UpdateWorkspaceDto,
|
||||
) {
|
||||
const jwtPayload = req['user'];
|
||||
const workspaceId = (
|
||||
await this.workspaceService.getUserCurrentWorkspace(jwtPayload.sub)
|
||||
).id;
|
||||
|
||||
return this.workspaceService.update(workspaceId, updateWorkspaceDto);
|
||||
}
|
||||
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post('delete')
|
||||
async deleteWorkspace(@Body() deleteWorkspaceDto: DeleteWorkspaceDto) {
|
||||
return this.workspaceService.delete(deleteWorkspaceDto);
|
||||
}
|
||||
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Get('members')
|
||||
async getWorkspaceMembers(@Req() req: FastifyRequest) {
|
||||
const jwtPayload = req['user'];
|
||||
const workspaceId = (
|
||||
await this.workspaceService.getUserCurrentWorkspace(jwtPayload.sub)
|
||||
).id;
|
||||
|
||||
return this.workspaceService.getWorkspaceUsers(workspaceId);
|
||||
}
|
||||
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post('members/add')
|
||||
async addWorkspaceMember(
|
||||
@Req() req: FastifyRequest,
|
||||
@Body() addWorkspaceUserDto: AddWorkspaceUserDto,
|
||||
) {
|
||||
const jwtPayload = req['user'];
|
||||
const workspaceId = (
|
||||
await this.workspaceService.getUserCurrentWorkspace(jwtPayload.sub)
|
||||
).id;
|
||||
|
||||
return this.workspaceService.addUserToWorkspace(
|
||||
addWorkspaceUserDto.userId,
|
||||
workspaceId,
|
||||
addWorkspaceUserDto.role,
|
||||
);
|
||||
}
|
||||
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Delete('members/delete')
|
||||
async removeWorkspaceMember(
|
||||
@Req() req: FastifyRequest,
|
||||
@Body() removeWorkspaceUserDto: RemoveWorkspaceUserDto,
|
||||
) {
|
||||
const jwtPayload = req['user'];
|
||||
const workspaceId = (
|
||||
await this.workspaceService.getUserCurrentWorkspace(jwtPayload.sub)
|
||||
).id;
|
||||
|
||||
return this.workspaceService.removeUserFromWorkspace(
|
||||
removeWorkspaceUserDto.userId,
|
||||
workspaceId,
|
||||
);
|
||||
}
|
||||
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post('members/role')
|
||||
async updateWorkspaceMemberRole(
|
||||
@Req() req: FastifyRequest,
|
||||
@Body() workspaceUserRoleDto: UpdateWorkspaceUserRoleDto,
|
||||
) {
|
||||
const jwtPayload = req['user'];
|
||||
const workspaceId = (
|
||||
await this.workspaceService.getUserCurrentWorkspace(jwtPayload.sub)
|
||||
).id;
|
||||
|
||||
return this.workspaceService.updateWorkspaceUserRole(
|
||||
workspaceUserRoleDto,
|
||||
workspaceId,
|
||||
);
|
||||
}
|
||||
}
|
||||
11
apps/server/src/core/workspace/dto/add-workspace-user.dto.ts
Normal file
11
apps/server/src/core/workspace/dto/add-workspace-user.dto.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { IsNotEmpty, IsString, IsUUID } from 'class-validator';
|
||||
|
||||
export class AddWorkspaceUserDto {
|
||||
@IsNotEmpty()
|
||||
@IsUUID()
|
||||
userId: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
role: string;
|
||||
}
|
||||
18
apps/server/src/core/workspace/dto/create-workspace.dto.ts
Normal file
18
apps/server/src/core/workspace/dto/create-workspace.dto.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { IsOptional, IsString, MaxLength, MinLength } from 'class-validator';
|
||||
|
||||
export class CreateWorkspaceDto {
|
||||
@MinLength(4)
|
||||
@MaxLength(64)
|
||||
@IsString()
|
||||
name: string;
|
||||
|
||||
@IsOptional()
|
||||
@MinLength(4)
|
||||
@MaxLength(30)
|
||||
@IsString()
|
||||
hostname?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
description?: string;
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
import { IsString } from 'class-validator';
|
||||
|
||||
export class DeleteWorkspaceDto {
|
||||
@IsString()
|
||||
workspaceId: string;
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
import { IsNotEmpty, IsUUID } from 'class-validator';
|
||||
|
||||
export class RemoveWorkspaceUserDto {
|
||||
@IsNotEmpty()
|
||||
@IsUUID()
|
||||
userId: string;
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
import { IsNotEmpty, IsString, IsUUID } from 'class-validator';
|
||||
|
||||
export class UpdateWorkspaceUserRoleDto {
|
||||
@IsNotEmpty()
|
||||
@IsUUID()
|
||||
userId: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
role: string;
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
import { PartialType } from '@nestjs/mapped-types';
|
||||
import { CreateWorkspaceDto } from './create-workspace.dto';
|
||||
import { IsOptional, IsString } from 'class-validator';
|
||||
|
||||
export class UpdateWorkspaceDto extends PartialType(CreateWorkspaceDto) {
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
logo: string;
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
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;
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
import {
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
ManyToOne,
|
||||
JoinColumn,
|
||||
Unique,
|
||||
} from 'typeorm';
|
||||
import { Workspace } from './workspace.entity';
|
||||
import { User } from '../../user/entities/user.entity';
|
||||
|
||||
@Entity('workspace_users')
|
||||
@Unique(['workspaceId', 'userId'])
|
||||
export class WorkspaceUser {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column()
|
||||
userId: string;
|
||||
|
||||
@ManyToOne(() => User, (user) => user.workspaceUsers, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn({ name: 'userId' })
|
||||
user: User;
|
||||
|
||||
@Column()
|
||||
workspaceId: string;
|
||||
|
||||
@ManyToOne(() => Workspace, (workspace) => workspace.workspaceUsers, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn({ name: 'workspaceId' })
|
||||
workspace: Workspace;
|
||||
|
||||
@Column({ length: 100, nullable: true })
|
||||
role: string;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn()
|
||||
updatedAt: Date;
|
||||
}
|
||||
73
apps/server/src/core/workspace/entities/workspace.entity.ts
Normal file
73
apps/server/src/core/workspace/entities/workspace.entity.ts
Normal file
@ -0,0 +1,73 @@
|
||||
import {
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
JoinColumn,
|
||||
} from 'typeorm';
|
||||
import { User } from '../../user/entities/user.entity';
|
||||
import { WorkspaceUser } from './workspace-user.entity';
|
||||
import { Page } from '../../page/entities/page.entity';
|
||||
import { WorkspaceInvitation } from './workspace-invitation.entity';
|
||||
import { Comment } from '../../comment/entities/comment.entity';
|
||||
|
||||
@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()
|
||||
creatorId: string;
|
||||
|
||||
@ManyToOne(() => User, (user) => user.workspaces)
|
||||
@JoinColumn({ name: 'creatorId' })
|
||||
creator: User;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn()
|
||||
updatedAt: Date;
|
||||
|
||||
@OneToMany(() => WorkspaceUser, (workspaceUser) => workspaceUser.workspace)
|
||||
workspaceUsers: WorkspaceUser[];
|
||||
|
||||
@OneToMany(
|
||||
() => WorkspaceInvitation,
|
||||
(workspaceInvitation) => workspaceInvitation.workspace,
|
||||
)
|
||||
workspaceInvitations: WorkspaceInvitation[];
|
||||
|
||||
@OneToMany(() => Page, (page) => page.workspace)
|
||||
pages: Page[];
|
||||
|
||||
@OneToMany(() => Comment, (comment) => comment.workspace)
|
||||
comments: Comment[];
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { DataSource, Repository } from 'typeorm';
|
||||
import { WorkspaceUser } from '../entities/workspace-user.entity';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceUserRepository extends Repository<WorkspaceUser> {
|
||||
constructor(private dataSource: DataSource) {
|
||||
super(WorkspaceUser, dataSource.createEntityManager());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
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) {
|
||||
return this.findOneBy({ id: workspaceId });
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { WorkspaceService } from './workspace.service';
|
||||
|
||||
describe('WorkspaceService', () => {
|
||||
let service: WorkspaceService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [WorkspaceService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<WorkspaceService>(WorkspaceService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
201
apps/server/src/core/workspace/services/workspace.service.ts
Normal file
201
apps/server/src/core/workspace/services/workspace.service.ts
Normal file
@ -0,0 +1,201 @@
|
||||
import {
|
||||
BadRequestException,
|
||||
Injectable,
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { CreateWorkspaceDto } from '../dto/create-workspace.dto';
|
||||
import { WorkspaceRepository } from '../repositories/workspace.repository';
|
||||
import { WorkspaceUserRepository } from '../repositories/workspace-user.repository';
|
||||
import { WorkspaceUser } from '../entities/workspace-user.entity';
|
||||
import { Workspace } from '../entities/workspace.entity';
|
||||
import { plainToInstance } from 'class-transformer';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { generateHostname } from '../workspace.util';
|
||||
import { UpdateWorkspaceDto } from '../dto/update-workspace.dto';
|
||||
import { DeleteWorkspaceDto } from '../dto/delete-workspace.dto';
|
||||
import { UpdateWorkspaceUserRoleDto } from '../dto/update-workspace-user-role.dto';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceService {
|
||||
constructor(
|
||||
private workspaceRepository: WorkspaceRepository,
|
||||
private workspaceUserRepository: WorkspaceUserRepository,
|
||||
) {}
|
||||
|
||||
async findById(workspaceId: string): Promise<Workspace> {
|
||||
return this.workspaceRepository.findById(workspaceId);
|
||||
}
|
||||
|
||||
async save(workspace: Workspace) {
|
||||
return this.workspaceRepository.save(workspace);
|
||||
}
|
||||
|
||||
async create(
|
||||
userId: string,
|
||||
createWorkspaceDto?: CreateWorkspaceDto,
|
||||
): Promise<Workspace> {
|
||||
let workspace: Workspace;
|
||||
|
||||
if (createWorkspaceDto) {
|
||||
workspace = plainToInstance(Workspace, createWorkspaceDto);
|
||||
} else {
|
||||
workspace = new Workspace();
|
||||
}
|
||||
|
||||
workspace.inviteCode = uuid();
|
||||
workspace.creatorId = userId;
|
||||
|
||||
if (workspace.name && !workspace.hostname?.trim()) {
|
||||
workspace.hostname = generateHostname(createWorkspaceDto.name);
|
||||
}
|
||||
|
||||
workspace = await this.workspaceRepository.save(workspace);
|
||||
await this.addUserToWorkspace(userId, workspace.id, 'owner');
|
||||
|
||||
return workspace;
|
||||
}
|
||||
|
||||
async update(
|
||||
workspaceId: string,
|
||||
updateWorkspaceDto: UpdateWorkspaceDto,
|
||||
): Promise<Workspace> {
|
||||
const workspace = await this.workspaceRepository.findById(workspaceId);
|
||||
if (!workspace) {
|
||||
throw new NotFoundException('Workspace not found');
|
||||
}
|
||||
|
||||
if (updateWorkspaceDto.name) {
|
||||
workspace.name = updateWorkspaceDto.name;
|
||||
}
|
||||
|
||||
if (updateWorkspaceDto.logo) {
|
||||
workspace.logo = updateWorkspaceDto.logo;
|
||||
}
|
||||
|
||||
return this.workspaceRepository.save(workspace);
|
||||
}
|
||||
|
||||
async delete(deleteWorkspaceDto: DeleteWorkspaceDto): Promise<void> {
|
||||
const workspace = await this.workspaceRepository.findById(
|
||||
deleteWorkspaceDto.workspaceId,
|
||||
);
|
||||
if (!workspace) {
|
||||
throw new NotFoundException('Workspace not found');
|
||||
}
|
||||
|
||||
//TODO
|
||||
// remove all existing users from workspace
|
||||
// delete workspace
|
||||
}
|
||||
|
||||
async addUserToWorkspace(
|
||||
userId: string,
|
||||
workspaceId: string,
|
||||
role: string,
|
||||
): Promise<WorkspaceUser> {
|
||||
const existingWorkspaceUser = await this.workspaceUserRepository.findOne({
|
||||
where: { userId: userId, workspaceId: workspaceId },
|
||||
});
|
||||
|
||||
if (existingWorkspaceUser) {
|
||||
throw new BadRequestException('User already added to this workspace');
|
||||
}
|
||||
|
||||
const workspaceUser = new WorkspaceUser();
|
||||
workspaceUser.userId = userId;
|
||||
workspaceUser.workspaceId = workspaceId;
|
||||
workspaceUser.role = role;
|
||||
|
||||
return this.workspaceUserRepository.save(workspaceUser);
|
||||
}
|
||||
|
||||
async updateWorkspaceUserRole(
|
||||
workspaceUserRoleDto: UpdateWorkspaceUserRoleDto,
|
||||
workspaceId: string,
|
||||
) {
|
||||
const workspaceUser = await this.workspaceUserRepository.findOne({
|
||||
where: { userId: workspaceUserRoleDto.userId, workspaceId: workspaceId },
|
||||
});
|
||||
|
||||
if (!workspaceUser) {
|
||||
throw new BadRequestException('user is not a member of this workspace');
|
||||
}
|
||||
|
||||
if (workspaceUser.role === workspaceUserRoleDto.role) {
|
||||
return workspaceUser;
|
||||
}
|
||||
|
||||
workspaceUser.role = workspaceUserRoleDto.role;
|
||||
// TODO: if there is only one workspace owner, prevent the role change
|
||||
|
||||
return this.workspaceUserRepository.save(workspaceUser);
|
||||
}
|
||||
|
||||
async removeUserFromWorkspace(
|
||||
userId: string,
|
||||
workspaceId: string,
|
||||
): Promise<void> {
|
||||
await this.validateWorkspaceMember(userId, workspaceId);
|
||||
|
||||
await this.workspaceUserRepository.delete({
|
||||
userId,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
async getUserCurrentWorkspace(userId: string): Promise<Workspace> {
|
||||
// TODO: use workspaceId and fetch workspace based on the id
|
||||
// we currently assume the user belongs to one workspace
|
||||
const userWorkspace = await this.workspaceUserRepository.findOne({
|
||||
where: { userId: userId },
|
||||
relations: ['workspace'],
|
||||
});
|
||||
|
||||
return userWorkspace.workspace;
|
||||
}
|
||||
|
||||
async getUserWorkspaces(userId: string): Promise<Workspace[]> {
|
||||
const workspaces = await this.workspaceUserRepository.find({
|
||||
where: { userId: userId },
|
||||
relations: ['workspace'],
|
||||
});
|
||||
|
||||
return workspaces.map(
|
||||
(userWorkspace: WorkspaceUser) => userWorkspace.workspace,
|
||||
);
|
||||
}
|
||||
|
||||
async getWorkspaceUsers(workspaceId: string) {
|
||||
const workspace = await this.workspaceRepository.findOne({
|
||||
where: { id: workspaceId },
|
||||
relations: ['workspaceUsers', 'workspaceUsers.user'],
|
||||
});
|
||||
|
||||
if (!workspace) {
|
||||
throw new BadRequestException('Invalid workspace');
|
||||
}
|
||||
|
||||
const users = workspace.workspaceUsers.map((workspaceUser) => {
|
||||
workspaceUser.user.password = '';
|
||||
return {
|
||||
...workspaceUser.user,
|
||||
workspaceRole: workspaceUser.role,
|
||||
};
|
||||
});
|
||||
|
||||
return { users };
|
||||
}
|
||||
|
||||
async validateWorkspaceMember(
|
||||
userId: string,
|
||||
workspaceId: string,
|
||||
): Promise<void> {
|
||||
const workspaceUser = await this.workspaceUserRepository.findOne({
|
||||
where: { userId, workspaceId },
|
||||
});
|
||||
|
||||
if (!workspaceUser) {
|
||||
throw new BadRequestException('User is not a member of this workspace');
|
||||
}
|
||||
}
|
||||
}
|
||||
21
apps/server/src/core/workspace/workspace.module.ts
Normal file
21
apps/server/src/core/workspace/workspace.module.ts
Normal file
@ -0,0 +1,21 @@
|
||||
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 { WorkspaceUser } from './entities/workspace-user.entity';
|
||||
import { WorkspaceInvitation } from './entities/workspace-invitation.entity';
|
||||
import { WorkspaceUserRepository } from './repositories/workspace-user.repository';
|
||||
import { AuthModule } from '../auth/auth.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Workspace, WorkspaceUser, WorkspaceInvitation]),
|
||||
AuthModule,
|
||||
],
|
||||
controllers: [WorkspaceController],
|
||||
providers: [WorkspaceService, WorkspaceRepository, WorkspaceUserRepository],
|
||||
exports: [WorkspaceService, WorkspaceRepository, WorkspaceUserRepository],
|
||||
})
|
||||
export class WorkspaceModule {}
|
||||
5
apps/server/src/core/workspace/workspace.util.ts
Normal file
5
apps/server/src/core/workspace/workspace.util.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export function generateHostname(name: string): string {
|
||||
let hostname = name.replace(/[^a-z0-9]/gi, '').toLowerCase();
|
||||
hostname = hostname.substring(0, 30);
|
||||
return hostname;
|
||||
}
|
||||
Reference in New Issue
Block a user