Merge pull request #3364 from omnivore-app/fix/delete-user

fix: change user email address after user deleted account
This commit is contained in:
Hongbo Wu
2024-01-15 11:35:57 +08:00
committed by GitHub
3 changed files with 37 additions and 7 deletions

View File

@ -42,7 +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 { softDeleteUser } from '../../services/user'
import { authorized, userDataToUser } from '../../utils/helpers'
import { validateUsername } from '../../utils/usernamePolicy'
import { WithDataSourcesContext } from '../types'
@ -320,10 +320,8 @@ export const deleteAccountResolver = authorized<
DeleteAccountError,
MutationDeleteAccountArgs
>(async (_, { userID }, { log }) => {
// soft delete user
const result = await updateUser(userID, {
status: StatusType.Deleted,
})
// soft delete user and change email address for user to sign up again
const result = await softDeleteUser(userID)
if (!result.affected) {
log.error('Error deleting user account')

View File

@ -1,4 +1,5 @@
import { DeepPartial, FindOptionsWhere, In } from 'typeorm'
import { Profile } from '../entity/profile'
import { StatusType, User } from '../entity/user'
import { authTrx, getRepository, queryBuilderToRawSql } from '../repository'
import { userRepository } from '../repository/user'
@ -22,6 +23,32 @@ export const updateUser = async (userId: string, update: Partial<User>) => {
)
}
export const softDeleteUser = async (userId: string) => {
return authTrx(
async (t) => {
// change email address and username for user to sign up again
await t.getRepository(Profile).update(
{
user: {
id: userId,
},
},
{
username: `deleted_user_${userId}`,
}
)
return t.getRepository(User).update(userId, {
status: StatusType.Deleted,
email: `deleted_user_${userId}@omnivore.app`,
sourceUserId: `deleted_user_${userId}`,
})
},
undefined,
userId
)
}
export const findActiveUser = async (id: string): Promise<User | null> => {
return userRepository.findOneBy({ id, status: StatusType.Active })
}

View File

@ -1,10 +1,11 @@
import { expect } from 'chai'
import 'mocha'
import { User } from '../../src/entity/user'
import { StatusType, User } from '../../src/entity/user'
import {
UpdateUserErrorCode,
UpdateUserProfileErrorCode,
} from '../../src/generated/graphql'
import { userRepository } from '../../src/repository/user'
import { findProfile } from '../../src/services/profile'
import { deleteUser, findActiveUser } from '../../src/services/user'
import { hashPassword } from '../../src/utils/auth'
@ -272,11 +273,15 @@ describe('User API', () => {
})
context('when user id is valid', () => {
it('deletes user and responds with 200', async () => {
it('deletes user and changes email address', async () => {
const response = await graphqlRequest(query(userId), authToken).expect(
200
)
expect(response.body.data.deleteAccount.userID).to.eql(userId)
const user = await userRepository.findOneBy({ id: userId })
expect(user?.status).to.eql(StatusType.Deleted)
expect(user?.email).to.eql(`deleted_user_${userId}@omnivore.app`)
})
})