✨New endpoint that is marking user for deletion
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
<env name="PUBSUB_TYPE" value="local" />
|
||||
<env name="SEARCH_DRIVER" value="mongodb" />
|
||||
<env name="STORAGE_LOCAL_PATH" value="/tmp" />
|
||||
<env name="ADMIN_ENDPOINT_SECRET" value="123" />
|
||||
</envs>
|
||||
<scope-kind value="DIRECTORY" />
|
||||
<test-directory value="$PROJECT_DIR$/tdrive/backend/node/test/e2e" />
|
||||
|
||||
+19
-1
@@ -1,4 +1,3 @@
|
||||
import { UserPrimaryKey } from "src/services/user/entities/user";
|
||||
import gr from "../../../../../services/global-resolver";
|
||||
|
||||
import type { ExecutionContext } from "../../../../platform/framework/api/crud-service";
|
||||
@@ -13,6 +12,25 @@ export class AdminDeleteUserController {
|
||||
return this._repos;
|
||||
}
|
||||
|
||||
async markToDelete(
|
||||
userId: string,
|
||||
): Promise<{ status: "failed" | "deleting" | "done"; userId?: string }> {
|
||||
try {
|
||||
await gr.services.console.getClient().userWasDeletedForceLogout(userId);
|
||||
await gr.services.users.markToDeleted({ id: userId });
|
||||
} catch (err) {
|
||||
adminLogger.error({ err, userId }, "[DELETE USER] Error dustin updating user ");
|
||||
return {
|
||||
status: "failed",
|
||||
userId,
|
||||
};
|
||||
}
|
||||
return {
|
||||
status: "done",
|
||||
userId,
|
||||
};
|
||||
}
|
||||
|
||||
/** Begin or forward the deletion process of a user, if `deleteData` is false, only anonymises the user entry */
|
||||
async deleteUser(
|
||||
userId: string,
|
||||
|
||||
@@ -62,6 +62,19 @@ const routes: FastifyPluginCallback = async (fastify: FastifyInstance, _opts, ne
|
||||
|
||||
return { id: userId };
|
||||
});
|
||||
|
||||
fastify.post(`${urlRoot}/mark`, async (request, reply) => {
|
||||
if (!authenticateAdminQuery(request, reply)) return false;
|
||||
|
||||
const { email } = request.body as TUserGetIdByEmailBody;
|
||||
const userId = await controller.getUserIdByEmail(email);
|
||||
|
||||
if (!userId) {
|
||||
return reply.status(404).send({ message: "User not found" });
|
||||
}
|
||||
|
||||
return await controller.markToDelete(userId);
|
||||
});
|
||||
}
|
||||
next();
|
||||
};
|
||||
|
||||
@@ -75,6 +75,10 @@ export default class User {
|
||||
@Column("password", "string")
|
||||
password: string;
|
||||
|
||||
//just mark user as deleted not to be able to login
|
||||
@Column("marked_to_delete", "tdrive_boolean")
|
||||
marked_to_delete: boolean;
|
||||
|
||||
@Column("deleted", "tdrive_boolean")
|
||||
deleted: boolean;
|
||||
|
||||
|
||||
@@ -201,6 +201,12 @@ export class UserServiceImpl {
|
||||
}
|
||||
}
|
||||
|
||||
async markToDeleted(pk: UserPrimaryKey) {
|
||||
const user = await this.get(pk);
|
||||
user.marked_to_delete = true;
|
||||
await this.save(user);
|
||||
}
|
||||
|
||||
async search(
|
||||
pagination: Pagination,
|
||||
options?: SearchUserOptions,
|
||||
|
||||
@@ -15,6 +15,7 @@ export const userObjectSchema = {
|
||||
last_name: { type: "string" },
|
||||
created_at: { type: "number" },
|
||||
deleted: { type: "boolean" },
|
||||
marked_to_delete: { type: "boolean" },
|
||||
delete_process_started_epoch: { type: "number" },
|
||||
|
||||
status: { type: "string" },
|
||||
|
||||
@@ -56,6 +56,7 @@ export interface UserObject {
|
||||
full_name: string;
|
||||
created_at: number;
|
||||
deleted: boolean;
|
||||
marked_to_delete: boolean;
|
||||
status: string; //Single string for the status
|
||||
last_activity: number;
|
||||
last_seen?: number;
|
||||
|
||||
@@ -82,6 +82,7 @@ export class WorkspaceUsersCrudController
|
||||
full_name: [user.first_name, user.last_name].join(" "),
|
||||
created_at: user.creation_date,
|
||||
deleted: Boolean(user.deleted),
|
||||
marked_to_delete: Boolean(user.marked_to_delete),
|
||||
status: user.status_icon,
|
||||
last_activity: user.last_activity,
|
||||
cache: {
|
||||
|
||||
@@ -30,6 +30,7 @@ export async function formatUser(
|
||||
full_name: [user.first_name, user.last_name].join(" "),
|
||||
created_at: user.creation_date,
|
||||
deleted: Boolean(user.deleted),
|
||||
marked_to_delete: Boolean(user.marked_to_delete),
|
||||
delete_process_started_epoch: user.delete_process_started_epoch,
|
||||
status: user.status_icon,
|
||||
last_activity: user.last_activity,
|
||||
|
||||
@@ -30,9 +30,11 @@ type TokenPayload = {
|
||||
|
||||
export type User = {
|
||||
id: string;
|
||||
email?: string;
|
||||
first_name?: string;
|
||||
isWorkspaceModerator?: boolean;
|
||||
deleted?: boolean,
|
||||
marked_to_delete?: boolean;
|
||||
delete_process_started_epoch?: number,
|
||||
preferences?: {
|
||||
language?: string;
|
||||
|
||||
@@ -301,10 +301,32 @@ describe("The users deletion API", () => {
|
||||
});
|
||||
|
||||
it("should have no objects left other than user (and untestable files)", async () => {
|
||||
expect(await (await Promise.all(
|
||||
Object.entries(listByUserIn)
|
||||
.flatMap(async ([key, fn]) => (await fn(myUserId)).getEntities().map(e => ({"": e.constructor.name, ...e})))
|
||||
)).flat()).toHaveLength(0);
|
||||
expect((await Promise.all(
|
||||
Object.entries(listByUserIn)
|
||||
.flatMap(async ([_, fn]) => (await fn(myUserId)).getEntities().map(e => ({"": e.constructor.name, ...e})))
|
||||
)).flat()).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("'existing user with to_delete flag' should return 404 if user is not found", async () => {
|
||||
const secret = adminConfig.endpointSecret;
|
||||
const email = "notexistingemail@test.com";
|
||||
const response = await platform!.app.inject({
|
||||
method: "POST",
|
||||
url: `/admin/api/user/delete/mark`,
|
||||
body: { secret, email },
|
||||
});
|
||||
expect(response.statusCode).toBe(404);
|
||||
});
|
||||
|
||||
it("'existing user with to_delete flag' should return 200", async () => {
|
||||
const user = await UserApi.getInstance(platform);
|
||||
const response = await platform!.app.inject({
|
||||
method: "POST",
|
||||
url: `/admin/api/user/delete/mark`,
|
||||
body: { secret: adminConfig.endpointSecret, email: (await user.getUser()).email },
|
||||
});
|
||||
expect(response.statusCode).toBe(200);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user