Skip to content

Commit

Permalink
Merge pull request #74 from cuappdev/deleteaccount
Browse files Browse the repository at this point in the history
Implement deleting accounts
  • Loading branch information
akmatchev authored Feb 29, 2024
2 parents 41ce7e7 + 291cfa7 commit d0ec877
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 78 deletions.
2 changes: 1 addition & 1 deletion ormconfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module.exports = {
entities: [
'src/models/*.ts',
],
synchronize: true,
synchronize: false,
namingStrategy: new SnakeNamingStrategy(),
migrations: [
'src/migrations/*.ts',
Expand Down
7 changes: 6 additions & 1 deletion src/api/controllers/UserController.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Body, CurrentUser, Get, JsonController, Param, Params, Post } from 'routing-controllers';
import { Body, CurrentUser, Get, JsonController, Param, Params, Post, Delete} from 'routing-controllers';

import { UserModel } from '../../models/UserModel';
import { UserService } from '../../services/UserService';
Expand Down Expand Up @@ -58,4 +58,9 @@ export class UserController {
async unblockUser(@Body() blockUserRequest: BlockUserRequest, @CurrentUser() user: UserModel): Promise<GetUserResponse> {
return { user: await this.userService.unblockUser(user, blockUserRequest) }
}

@Delete('id/:id/')
async deleteUser(@Params() params: UuidParam, @CurrentUser() user: UserModel): Promise<GetUserResponse> {
return { user: await this.userService.deleteUser(user, params) };
}
}
74 changes: 0 additions & 74 deletions src/migrations/1707428741047-blocking.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {MigrationInterface, QueryRunner} from "typeorm";

export class init1707427884517 implements MigrationInterface {
name = 'init1707427884517'
export class init1709163288115 implements MigrationInterface {
name = 'init1709163288115'

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`CREATE TABLE "Request" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "title" character varying NOT NULL, "description" character varying NOT NULL, "user" uuid, CONSTRAINT "PK_23de24dc477765bcc099feae8e5" PRIMARY KEY ("id"))`);
Expand All @@ -16,6 +16,9 @@ export class init1707427884517 implements MigrationInterface {
await queryRunner.query(`CREATE TABLE "request_matches_posts" ("matches" uuid NOT NULL, "matched" uuid NOT NULL, CONSTRAINT "PK_7f4c04956dd4e84a3437b2a8018" PRIMARY KEY ("matches", "matched"))`);
await queryRunner.query(`CREATE INDEX "IDX_bfa8c41d1cbae1a3faf7916693" ON "request_matches_posts" ("matches") `);
await queryRunner.query(`CREATE INDEX "IDX_dcf9a982f720a85b68bc354b9f" ON "request_matches_posts" ("matched") `);
await queryRunner.query(`CREATE TABLE "user_blocking_users" ("blockers" uuid NOT NULL, "blocking" uuid NOT NULL, CONSTRAINT "PK_8db623e58cc4bce5fbcc252c66b" PRIMARY KEY ("blockers", "blocking"))`);
await queryRunner.query(`CREATE INDEX "IDX_fab66ba7c0e58e67b0d67f1c23" ON "user_blocking_users" ("blockers") `);
await queryRunner.query(`CREATE INDEX "IDX_b5c7223aa162c5ccd1867056f7" ON "user_blocking_users" ("blocking") `);
await queryRunner.query(`ALTER TABLE "Request" ADD CONSTRAINT "FK_db281bd2822e1938f5072960173" FOREIGN KEY ("user") REFERENCES "User"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "Post" ADD CONSTRAINT "FK_2067452f95b084577dae22e17e2" FOREIGN KEY ("user") REFERENCES "User"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "UserSession" ADD CONSTRAINT "FK_a93dfba9168e8addd8a53b9a6c4" FOREIGN KEY ("user") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
Expand All @@ -26,9 +29,13 @@ export class init1707427884517 implements MigrationInterface {
await queryRunner.query(`ALTER TABLE "user_saved_posts" ADD CONSTRAINT "FK_1da3c41687f5a8934c7808ef24d" FOREIGN KEY ("savers") REFERENCES "User"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "request_matches_posts" ADD CONSTRAINT "FK_bfa8c41d1cbae1a3faf79166936" FOREIGN KEY ("matches") REFERENCES "Post"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
await queryRunner.query(`ALTER TABLE "request_matches_posts" ADD CONSTRAINT "FK_dcf9a982f720a85b68bc354b9f8" FOREIGN KEY ("matched") REFERENCES "Request"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "user_blocking_users" ADD CONSTRAINT "FK_fab66ba7c0e58e67b0d67f1c232" FOREIGN KEY ("blockers") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
await queryRunner.query(`ALTER TABLE "user_blocking_users" ADD CONSTRAINT "FK_b5c7223aa162c5ccd1867056f73" FOREIGN KEY ("blocking") REFERENCES "User"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "user_blocking_users" DROP CONSTRAINT "FK_b5c7223aa162c5ccd1867056f73"`);
await queryRunner.query(`ALTER TABLE "user_blocking_users" DROP CONSTRAINT "FK_fab66ba7c0e58e67b0d67f1c232"`);
await queryRunner.query(`ALTER TABLE "request_matches_posts" DROP CONSTRAINT "FK_dcf9a982f720a85b68bc354b9f8"`);
await queryRunner.query(`ALTER TABLE "request_matches_posts" DROP CONSTRAINT "FK_bfa8c41d1cbae1a3faf79166936"`);
await queryRunner.query(`ALTER TABLE "user_saved_posts" DROP CONSTRAINT "FK_1da3c41687f5a8934c7808ef24d"`);
Expand All @@ -39,6 +46,9 @@ export class init1707427884517 implements MigrationInterface {
await queryRunner.query(`ALTER TABLE "UserSession" DROP CONSTRAINT "FK_a93dfba9168e8addd8a53b9a6c4"`);
await queryRunner.query(`ALTER TABLE "Post" DROP CONSTRAINT "FK_2067452f95b084577dae22e17e2"`);
await queryRunner.query(`ALTER TABLE "Request" DROP CONSTRAINT "FK_db281bd2822e1938f5072960173"`);
await queryRunner.query(`DROP INDEX "public"."IDX_b5c7223aa162c5ccd1867056f7"`);
await queryRunner.query(`DROP INDEX "public"."IDX_fab66ba7c0e58e67b0d67f1c23"`);
await queryRunner.query(`DROP TABLE "user_blocking_users"`);
await queryRunner.query(`DROP INDEX "public"."IDX_dcf9a982f720a85b68bc354b9f"`);
await queryRunner.query(`DROP INDEX "public"."IDX_bfa8c41d1cbae1a3faf7916693"`);
await queryRunner.query(`DROP TABLE "request_matches_posts"`);
Expand Down
12 changes: 12 additions & 0 deletions src/services/UserService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,16 @@ export class UserService {
return userRepository.unblockUser(user, blocked);
});
}

public async deleteUser(user: UserModel, params: UuidParam): Promise<UserModel> {
return this.transactions.readWrite(async (transactionalEntityManager) => {
const userRepository = Repositories.user(transactionalEntityManager);
const userToDelete = await userRepository.getUserById(params.id);
if (!userToDelete) throw new NotFoundError('User not found!');
if (user.id !== userToDelete.id && !user.admin) {
throw new UnauthorizedError('User does not have permission to delete other users');
}
return userRepository.deleteUser(userToDelete);
});
}
}
60 changes: 60 additions & 0 deletions src/tests/UserTest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,4 +269,64 @@ describe('user tests', () => {
expect(error.message).toBe('User is not blocked!');
}
});

test('delete users - user deletes themselves', async () => {
const admin = UserFactory.fake();
const user = UserFactory.fakeTemplate();
admin.admin = true;

await new DataFactory()
.createUsers(user)
.write();

const preDeleteUserResponse = await userController.getUsers(admin);
expect(preDeleteUserResponse.users).toHaveLength(1);

const getUserResponse = await userController.getUserById(uuidParam);
if (getUserResponse.user != undefined) {
getUserResponse.user.stars = Number(getUserResponse.user.stars);
}
expect(getUserResponse.user).toEqual(expectedUser);

const deleteUserResponse = await userController.deleteUser(uuidParam, user);
if (deleteUserResponse.user != undefined) {
deleteUserResponse.user.stars = Number(deleteUserResponse.user.stars);
}
const getUsersResponse = await userController.getUsers(admin);
expect(getUsersResponse.users).toHaveLength(0);
});

test('delete users - user deletes another user', async () => {
const admin = UserFactory.fake();
const user = UserFactory.fakeTemplate();
admin.admin = true;

await new DataFactory()
.createUsers(admin, user)
.write();

const preDeleteUserResponse = await userController.getUsers(admin);
expect(preDeleteUserResponse.users).toHaveLength(2);

const deleteUserResponse = await userController.deleteUser(uuidParam, admin);
if (deleteUserResponse.user != undefined) {
deleteUserResponse.user.stars = Number(deleteUserResponse.user.stars);
}
const getUsersResponse = await userController.getUsers(admin);
expect(getUsersResponse.users).toHaveLength(1);
});

test('delete users - user that is not an admin tries to delete another user', async () => {
const [user1, user2] = UserFactory.create(2);

await new DataFactory()
.createUsers(user1, user2)
.write();

try {
await userController.deleteUser({id: user2.id}, user1);
} catch (error) {
expect(error.message).toBe('User does not have permission to delete other users');
}
});
});

0 comments on commit d0ec877

Please sign in to comment.