Fix workspace/user deletion (#2648)
* Fix workspace/user deletion * remove logs * add defaultWorkspace check
This commit is contained in:
@ -159,10 +159,18 @@ export class AuthService {
|
|||||||
|
|
||||||
assert(user, "This user doesn't exist", NotFoundException);
|
assert(user, "This user doesn't exist", NotFoundException);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
user.defaultWorkspace,
|
||||||
|
'User has no default workspace',
|
||||||
|
NotFoundException,
|
||||||
|
);
|
||||||
|
|
||||||
// passwordHash is hidden for security reasons
|
// passwordHash is hidden for security reasons
|
||||||
user.passwordHash = '';
|
user.passwordHash = '';
|
||||||
user.workspaceMember = await this.userService.loadWorkspaceMember(user);
|
user.workspaceMember = await this.userService.loadWorkspaceMember(user);
|
||||||
|
|
||||||
|
console.log(user.workspaceMember);
|
||||||
|
|
||||||
const accessToken = await this.tokenService.generateAccessToken(user.id);
|
const accessToken = await this.tokenService.generateAccessToken(user.id);
|
||||||
const refreshToken = await this.tokenService.generateRefreshToken(user.id);
|
const refreshToken = await this.tokenService.generateRefreshToken(user.id);
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,9 @@ export class RefreshToken {
|
|||||||
@PrimaryGeneratedColumn('uuid')
|
@PrimaryGeneratedColumn('uuid')
|
||||||
id: string;
|
id: string;
|
||||||
|
|
||||||
@ManyToOne(() => User, (user) => user.refreshTokens)
|
@ManyToOne(() => User, (user) => user.refreshTokens, {
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
})
|
||||||
@JoinColumn({ name: 'userId' })
|
@JoinColumn({ name: 'userId' })
|
||||||
user: User;
|
user: User;
|
||||||
|
|
||||||
|
|||||||
@ -70,16 +70,14 @@ export class UserService extends TypeOrmQueryService<User> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteUser({
|
async deleteUser(userId: string): Promise<User> {
|
||||||
workspaceId: _workspaceId,
|
const user = await this.userRepository.findOneBy({
|
||||||
userId,
|
id: userId,
|
||||||
}: {
|
});
|
||||||
workspaceId: string;
|
|
||||||
userId: string;
|
|
||||||
}) {
|
|
||||||
const user = await this.userRepository.findBy({ id: userId });
|
|
||||||
assert(user, 'User not found');
|
assert(user, 'User not found');
|
||||||
|
|
||||||
|
await this.userRepository.delete(user.id);
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,10 +63,14 @@ export class User {
|
|||||||
deletedAt: Date;
|
deletedAt: Date;
|
||||||
|
|
||||||
@Field(() => Workspace, { nullable: false })
|
@Field(() => Workspace, { nullable: false })
|
||||||
@ManyToOne(() => Workspace, (workspace) => workspace.users)
|
@ManyToOne(() => Workspace, (workspace) => workspace.users, {
|
||||||
|
onDelete: 'SET NULL',
|
||||||
|
})
|
||||||
defaultWorkspace: Workspace;
|
defaultWorkspace: Workspace;
|
||||||
|
|
||||||
@OneToMany(() => RefreshToken, (refreshToken) => refreshToken.user)
|
@OneToMany(() => RefreshToken, (refreshToken) => refreshToken.user, {
|
||||||
|
cascade: true,
|
||||||
|
})
|
||||||
refreshTokens: RefreshToken[];
|
refreshTokens: RefreshToken[];
|
||||||
|
|
||||||
@Field(() => UserWorkspaceMember, { nullable: false })
|
@Field(() => UserWorkspaceMember, { nullable: false })
|
||||||
|
|||||||
@ -19,11 +19,9 @@ import { AuthUser } from 'src/decorators/auth-user.decorator';
|
|||||||
import { EnvironmentService } from 'src/integrations/environment/environment.service';
|
import { EnvironmentService } from 'src/integrations/environment/environment.service';
|
||||||
import { streamToBuffer } from 'src/utils/stream-to-buffer';
|
import { streamToBuffer } from 'src/utils/stream-to-buffer';
|
||||||
import { FileUploadService } from 'src/core/file/services/file-upload.service';
|
import { FileUploadService } from 'src/core/file/services/file-upload.service';
|
||||||
import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator';
|
|
||||||
import { assert } from 'src/utils/assert';
|
import { assert } from 'src/utils/assert';
|
||||||
import { JwtAuthGuard } from 'src/guards/jwt.auth.guard';
|
import { JwtAuthGuard } from 'src/guards/jwt.auth.guard';
|
||||||
import { User } from 'src/core/user/user.entity';
|
import { User } from 'src/core/user/user.entity';
|
||||||
import { Workspace } from 'src/core/workspace/workspace.entity';
|
|
||||||
import { UserWorkspaceMember } from 'src/core/user/dtos/workspace-member.dto';
|
import { UserWorkspaceMember } from 'src/core/user/dtos/workspace-member.dto';
|
||||||
|
|
||||||
import { UserService } from './services/user.service';
|
import { UserService } from './services/user.service';
|
||||||
@ -96,10 +94,7 @@ export class UserResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Mutation(() => User)
|
@Mutation(() => User)
|
||||||
async deleteUser(
|
async deleteUser(@AuthUser() { id: userId }: User) {
|
||||||
@AuthUser() { id: userId }: User,
|
return this.userService.deleteUser(userId);
|
||||||
@AuthWorkspace() { id: workspaceId }: Workspace,
|
|
||||||
) {
|
|
||||||
return this.userService.deleteUser({ userId, workspaceId });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,6 +22,7 @@ export class WorkspaceService extends TypeOrmQueryService<Workspace> {
|
|||||||
assert(workspace, 'Workspace not found');
|
assert(workspace, 'Workspace not found');
|
||||||
|
|
||||||
await this.workspaceManagerService.delete(id);
|
await this.workspaceManagerService.delete(id);
|
||||||
|
await this.workspaceRepository.delete(id);
|
||||||
|
|
||||||
return workspace;
|
return workspace;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,16 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class AddCascadeDeleteOnRefreshTokenUser1700661180856 implements MigrationInterface {
|
||||||
|
name = 'AddCascadeDeleteOnRefreshTokenUser1700661180856'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "core"."refreshToken" DROP CONSTRAINT "FK_7008a2b0fb083127f60b5f4448e"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "core"."refreshToken" ADD CONSTRAINT "FK_7008a2b0fb083127f60b5f4448e" FOREIGN KEY ("userId") REFERENCES "core"."user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "core"."refreshToken" DROP CONSTRAINT "FK_7008a2b0fb083127f60b5f4448e"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "core"."refreshToken" ADD CONSTRAINT "FK_7008a2b0fb083127f60b5f4448e" FOREIGN KEY ("userId") REFERENCES "core"."user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class AddWorkspaceDeleteCascadeSetNullInUser1700663611659 implements MigrationInterface {
|
||||||
|
name = 'AddWorkspaceDeleteCascadeSetNullInUser1700663611659'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "core"."user" DROP CONSTRAINT "FK_2ec910029395fa7655621c88908"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "core"."user" ADD CONSTRAINT "FK_2ec910029395fa7655621c88908" FOREIGN KEY ("defaultWorkspaceId") REFERENCES "core"."workspace"("id") ON DELETE SET NULL ON UPDATE NO ACTION`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "core"."user" DROP CONSTRAINT "FK_2ec910029395fa7655621c88908"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "core"."user" ADD CONSTRAINT "FK_2ec910029395fa7655621c88908" FOREIGN KEY ("defaultWorkspaceId") REFERENCES "core"."workspace"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class AddCascadeDeleteOnRelationObject1700661538754 implements MigrationInterface {
|
||||||
|
name = 'AddCascadeDeleteOnRelationObject1700661538754'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "metadata"."relationMetadata" DROP CONSTRAINT "FK_0f781f589e5a527b8f3d3a4b824"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "metadata"."relationMetadata" DROP CONSTRAINT "FK_f2a0acd3a548ee446a1a35df44d"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "metadata"."relationMetadata" ADD CONSTRAINT "FK_f2a0acd3a548ee446a1a35df44d" FOREIGN KEY ("fromObjectMetadataId") REFERENCES "metadata"."objectMetadata"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "metadata"."relationMetadata" ADD CONSTRAINT "FK_0f781f589e5a527b8f3d3a4b824" FOREIGN KEY ("toObjectMetadataId") REFERENCES "metadata"."objectMetadata"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "metadata"."relationMetadata" DROP CONSTRAINT "FK_0f781f589e5a527b8f3d3a4b824"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "metadata"."relationMetadata" DROP CONSTRAINT "FK_f2a0acd3a548ee446a1a35df44d"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "metadata"."relationMetadata" ADD CONSTRAINT "FK_f2a0acd3a548ee446a1a35df44d" FOREIGN KEY ("fromObjectMetadataId") REFERENCES "metadata"."objectMetadata"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "metadata"."relationMetadata" ADD CONSTRAINT "FK_0f781f589e5a527b8f3d3a4b824" FOREIGN KEY ("toObjectMetadataId") REFERENCES "metadata"."objectMetadata"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -75,12 +75,18 @@ export class ObjectMetadataEntity implements ObjectMetadataInterface {
|
|||||||
@OneToMany(
|
@OneToMany(
|
||||||
() => RelationMetadataEntity,
|
() => RelationMetadataEntity,
|
||||||
(relation: RelationMetadataEntity) => relation.fromObjectMetadata,
|
(relation: RelationMetadataEntity) => relation.fromObjectMetadata,
|
||||||
|
{
|
||||||
|
cascade: true,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
fromRelations: RelationMetadataEntity[];
|
fromRelations: RelationMetadataEntity[];
|
||||||
|
|
||||||
@OneToMany(
|
@OneToMany(
|
||||||
() => RelationMetadataEntity,
|
() => RelationMetadataEntity,
|
||||||
(relation: RelationMetadataEntity) => relation.toObjectMetadata,
|
(relation: RelationMetadataEntity) => relation.toObjectMetadata,
|
||||||
|
{
|
||||||
|
cascade: true,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
toRelations: RelationMetadataEntity[];
|
toRelations: RelationMetadataEntity[];
|
||||||
|
|
||||||
|
|||||||
@ -46,12 +46,18 @@ export class RelationMetadataEntity implements RelationMetadataInterface {
|
|||||||
@ManyToOne(
|
@ManyToOne(
|
||||||
() => ObjectMetadataEntity,
|
() => ObjectMetadataEntity,
|
||||||
(object: ObjectMetadataEntity) => object.fromRelations,
|
(object: ObjectMetadataEntity) => object.fromRelations,
|
||||||
|
{
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
},
|
||||||
)
|
)
|
||||||
fromObjectMetadata: ObjectMetadataEntity;
|
fromObjectMetadata: ObjectMetadataEntity;
|
||||||
|
|
||||||
@ManyToOne(
|
@ManyToOne(
|
||||||
() => ObjectMetadataEntity,
|
() => ObjectMetadataEntity,
|
||||||
(object: ObjectMetadataEntity) => object.toRelations,
|
(object: ObjectMetadataEntity) => object.toRelations,
|
||||||
|
{
|
||||||
|
onDelete: 'CASCADE',
|
||||||
|
},
|
||||||
)
|
)
|
||||||
toObjectMetadata: ObjectMetadataEntity;
|
toObjectMetadata: ObjectMetadataEntity;
|
||||||
|
|
||||||
|
|||||||
@ -255,7 +255,6 @@ export class WorkspaceManagerService {
|
|||||||
*/
|
*/
|
||||||
public async delete(workspaceId: string): Promise<void> {
|
public async delete(workspaceId: string): Promise<void> {
|
||||||
// Delete data from metadata tables
|
// Delete data from metadata tables
|
||||||
await this.fieldMetadataService.deleteFieldsMetadata(workspaceId);
|
|
||||||
await this.objectMetadataService.deleteObjectsMetadata(workspaceId);
|
await this.objectMetadataService.deleteObjectsMetadata(workspaceId);
|
||||||
await this.workspaceMigrationService.delete(workspaceId);
|
await this.workspaceMigrationService.delete(workspaceId);
|
||||||
await this.dataSourceService.delete(workspaceId);
|
await this.dataSourceService.delete(workspaceId);
|
||||||
|
|||||||
Reference in New Issue
Block a user