🐛 Accept username in request of API delete user
This commit is contained in:
committed by
Anton Shepilov
parent
1f975f1ed5
commit
bebf337d28
+35
-11
@@ -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 },
|
||||
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,
|
||||
)
|
||||
)
|
||||
return "done";
|
||||
);
|
||||
|
||||
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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user