🐛 Accept username in request of API delete user

This commit is contained in:
lethemanh
2025-03-22 23:38:47 +07:00
committed by Anton Shepilov
parent 1f975f1ed5
commit bebf337d28
4 changed files with 59 additions and 25 deletions
@@ -1,3 +1,4 @@
import { UserPrimaryKey } from "src/services/user/entities/user";
import gr from "../../../../../services/global-resolver";
import type { ExecutionContext } from "../../../../platform/framework/api/crud-service";
@@ -13,27 +14,50 @@ export class AdminDeleteUserController {
}
/** Begin or forward the deletion process of a user, if `deleteData` is false, only anonymises the user entry */
async deleteUser(userId: string, deleteData: boolean): Promise<"failed" | "deleting" | "done"> {
async deleteUser(
userId: string,
deleteData: boolean,
username?: string,
): Promise<{ status: "failed" | "deleting" | "done"; userId?: string }> {
try {
if (
await gr.services.users.anonymizeAndDelete(
{ id: userId },
{
user: { server_request: true },
} as unknown as ExecutionContext,
deleteData,
)
)
return "done";
let pk: UserPrimaryKey = { id: userId };
if (username) {
pk = { username_canonical: username };
}
const data = await gr.services.users.anonymizeAndDelete(
pk,
{
user: { server_request: true },
} as unknown as ExecutionContext,
deleteData,
);
if (data.isDeleted)
return {
status: "done",
userId: data.userId,
};
const existingUser = await (await this.getRepos()).user.findOne({ id: userId });
if (existingUser?.deleted) {
if (existingUser.delete_process_started_epoch > 0) return "deleting";
if (existingUser.delete_process_started_epoch > 0) {
return {
status: "deleting",
userId: existingUser.id,
};
}
}
} catch (err) {
adminLogger.error({ err, userId }, "User deletion error");
return "failed";
adminLogger.error("[DELETE USER] ", JSON.stringify({ err, userId }), "User deletion error");
return {
status: "failed",
userId,
};
}
return "done";
return {
status: "done",
userId,
};
}
/** Get an array of 2 item arrays with `[ user IDs, delete_process_started_epoch ]` that are incompletely deleted */
@@ -14,15 +14,19 @@ function authenticateAdminQuery(request: FastifyRequest, reply: FastifyReply) {
return true;
}
type TUserDeleteQueryBody = TQueryBody & { userId: string; deleteData: boolean };
type TUserDeleteQueryBody = TQueryBody & { userId: string; deleteData: boolean; username?: string };
function getUserIfValidQuery(request: FastifyRequest, reply: FastifyReply) {
if (!authenticateAdminQuery(request, reply)) return { userId: "", deleteData: false };
const body = request.body as TUserDeleteQueryBody;
if (!body.userId?.length) {
if (!body.userId?.length && !body.username) {
reply.status(400).send();
return { userId: "", deleteData: false };
return { userId: "", username: "", deleteData: false };
}
return body;
return {
userId: body.userId || "",
username: body.username,
deleteData: body.deleteData,
};
}
const routes: FastifyPluginCallback = async (fastify: FastifyInstance, _opts, next) => {
@@ -31,13 +35,13 @@ const routes: FastifyPluginCallback = async (fastify: FastifyInstance, _opts, ne
const controller = new AdminDeleteUserController();
if (config?.endpointSecret?.length) {
fastify.post(urlRoot, async (request, reply) => {
const { userId, deleteData } = getUserIfValidQuery(request, reply);
if (!userId) return false;
const { userId, deleteData, username } = getUserIfValidQuery(request, reply);
if (!userId && !username) return false;
if (userId == "e2e_simulate_timeout")
return new Promise(() => {
return;
});
return { status: await controller.deleteUser(userId, deleteData) };
return await controller.deleteUser(userId, deleteData, username);
});
fastify.post(`${urlRoot}/pending`, async (request, reply) => {
@@ -149,9 +149,12 @@ export type UserNotificationPreferences = {
};
};
export type UserPrimaryKey = Pick<User, "id">;
export type UserPrimaryKey = {
id?: uuid;
username_canonical?: string;
};
export function getInstance(user: Partial<User>): User {
user.creation_date = !isNumber(user.creation_date) ? Date.now() : user.creation_date;
user.creation_date = !isNumber(user?.creation_date) ? Date.now() : user?.creation_date;
return merge(new User(), user);
}
@@ -185,7 +185,10 @@ export class UserServiceImpl {
user: user,
});
return deleteData && (await gr.platformServices.admin.deleteUser(userCopy));
return {
isDeleted: deleteData && (await gr.platformServices.admin.deleteUser(userCopy)),
userId: user.id,
};
}
}