soft delete user by calling delete account api

This commit is contained in:
Hongbo Wu 2023-10-16 15:24:53 +08:00
parent 4ae6c476f8
commit e54c1c81a1
6 changed files with 85 additions and 6 deletions

View file

@ -22,6 +22,7 @@ export enum RegistrationType {
export enum StatusType {
Active = 'ACTIVE',
Pending = 'PENDING',
Deleted = 'DELETED',
}
@Entity()

View file

@ -1,5 +1,9 @@
import * as jwt from 'jsonwebtoken'
import { RegistrationType, User as UserEntity } from '../../entity/user'
import {
RegistrationType,
StatusType,
User as UserEntity,
} from '../../entity/user'
import { env } from '../../env'
import {
DeleteAccountError,
@ -38,6 +42,7 @@ import {
import { userRepository } from '../../repository/user'
import { createUser } from '../../services/create_user'
import { sendVerificationEmail } from '../../services/send_emails'
import { updateUser } from '../../services/user'
import { authorized, userDataToUser } from '../../utils/helpers'
import { validateUsername } from '../../utils/usernamePolicy'
import { WithDataSourcesContext } from '../types'
@ -313,9 +318,10 @@ export const deleteAccountResolver = authorized<
DeleteAccountSuccess,
DeleteAccountError,
MutationDeleteAccountArgs
>(async (_, { userID }, { authTrx, log }) => {
const result = await authTrx(async (t) => {
return t.withRepository(userRepository).delete(userID)
>(async (_, { userID }, { log }) => {
// soft delete user
const result = await updateUser(userID, {
status: StatusType.Deleted,
})
if (!result.affected) {
log.error('Error deleting user account')

View file

@ -13,7 +13,7 @@ export const deleteUser = async (userId: string) => {
}
export const updateUser = async (userId: string, update: Partial<User>) => {
await authTrx(
return authTrx(
async (t) => t.getRepository(User).update(userId, update),
undefined,
userId

View file

@ -9,7 +9,7 @@ import { findProfile } from '../../src/services/profile'
import { deleteUser, findUser } from '../../src/services/user'
import { hashPassword } from '../../src/utils/auth'
import { createTestUser } from '../db'
import { graphqlRequest, request } from '../util'
import { generateFakeUuid, graphqlRequest, request } from '../util'
describe('User API', () => {
const correctPassword = 'fakePassword'
@ -238,4 +238,58 @@ describe('User API', () => {
return graphqlRequest(query, invalidAuthToken).expect(500)
})
})
describe('Delete account', () => {
const query = (userId: string) => `
mutation {
deleteAccount(
userID: "${userId}"
) {
... on DeleteAccountSuccess {
userID
}
... on DeleteAccountError {
errorCodes
}
}
}
`
let userId: string
let authToken: string
before(async () => {
const user = await createTestUser('to_delete_user')
const res = await request
.post('/local/debug/fake-user-login')
.send({ fakeEmail: user.email })
userId = user.id
authToken = res.body.authToken
})
after(async () => {
await deleteUser(userId)
})
context('when user id is valid', () => {
it('deletes user and responds with 200', async () => {
const response = await graphqlRequest(query(userId), authToken).expect(
200
)
expect(response.body.data.deleteAccount.userID).to.eql(userId)
})
})
context('when user not found', () => {
it('responds with error code UserNotFound', async () => {
const response = await graphqlRequest(
query(generateFakeUuid()),
authToken
).expect(200)
expect(response.body.data.deleteAccount.errorCodes).to.eql([
'USER_NOT_FOUND',
])
})
})
})
})

View file

@ -0,0 +1,9 @@
-- Type: DO
-- Name: alter_user_status_type
-- Description: Add DELETED to the user_status_type enum
BEGIN;
ALTER TYPE user_status_type ADD VALUE 'DELETED';
COMMIT;

View file

@ -0,0 +1,9 @@
-- Type: UNDO
-- Name: alter_user_status_type
-- Description: Add DELETED to the user_status_type enum
BEGIN;
ALTER TYPE user_status_type DROP VALUE IF EXISTS 'DELETED';
COMMIT;