Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(api): Remove user endpoint #2249

Merged
merged 3 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions api.planx.uk/modules/user/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,33 @@ export const createUser: CreateUser = async (req, res, next) => {
);
}
};

export const deleteUserSchema = z.object({
params: z.object({
email: z.string().trim().email().toLowerCase(),
}),
});

export type DeleteUser = ValidatedRequestHandler<
typeof deleteUserSchema,
UserResponse
>;

export const deleteUser: DeleteUser = async (req, res, next) => {
try {
const { email } = req.params;
const $client = getClient();

const user = await $client.user.getByEmail(email);
if (!user) throw Error(`No user matching email ${email} found`);

const isSuccessful = await $client.user.delete(user.id);
if (!isSuccessful) throw Error("Request to delete user failed");

return res.send({ message: "Successfully deleted user" });
} catch (error) {
return next(
new ServerError({ message: "Failed to delete user", cause: error }),
);
}
};
19 changes: 19 additions & 0 deletions api.planx.uk/modules/user/docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,22 @@ paths:
$ref: "#/components/responses/SuccessMessage"
"500":
$ref: "#/components/responses/ErrorMessage"
/user/{email}:
delete:
summary: Delete a user
description: "Requires authentication via a Cloudflare WARP client
\n\n
Please login at [https://api.editor.planx.uk/user](https://api.editor.planx.uk/user)"
tags: ["user"]
parameters:
- in: path
name: email
type: string
format: email
example: [email protected]
description: Email address of the user to be deleted
responses:
"200":
$ref: "#/components/responses/SuccessMessage"
"500":
$ref: "#/components/responses/ErrorMessage"
67 changes: 64 additions & 3 deletions api.planx.uk/modules/user/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,24 @@ import supertest from "supertest";
import app from "../../server";
import { authHeader } from "../../tests/mockJWT";

const mockCreateUser = jest.fn();

const mockUser = {
firstName: "Bilbo",
lastName: "Baggins",
email: "bilbo@bagend.sh",
email: "bilbo[email protected]",
isPlatformAdmin: false,
};

const mockCreateUser = jest.fn();
const mockDeleteUser = jest.fn();
const mockGetByEmail = jest.fn().mockResolvedValue(mockUser);

jest.mock("@opensystemslab/planx-core", () => {
return {
CoreDomainClient: jest.fn().mockImplementation(() => ({
user: {
create: () => mockCreateUser(),
delete: () => mockDeleteUser(),
getByEmail: () => mockGetByEmail(),
},
})),
};
Expand Down Expand Up @@ -66,3 +70,60 @@ describe("Create user endpoint", () => {
});
});
});

describe("Delete user endpoint", () => {
it("requires authentication", async () => {
await supertest(app).delete("/user/[email protected]").expect(401);
});

it("requires the 'platformAdmin' role", async () => {
await supertest(app)
.delete("/user/[email protected]")
.set(authHeader({ role: "teamEditor" }))
.expect(403);
});

it("handles an invalid email", async () => {
mockGetByEmail.mockResolvedValueOnce(null);

await supertest(app)
.delete("/user/[email protected]")
.set(auth)
.expect(500)
.then((res) => {
expect(mockGetByEmail).toHaveBeenCalled();
expect(res.body).toHaveProperty("error");
expect(res.body.error).toMatch(/Failed to delete user/);
});
});

it("handles a failure to delete the user", async () => {
mockDeleteUser.mockResolvedValueOnce(false);

await supertest(app)
.delete("/user/[email protected]")
.set(auth)
.expect(500)
.then((res) => {
expect(mockGetByEmail).toHaveBeenCalled();
expect(mockDeleteUser).toHaveBeenCalled();
expect(res.body).toHaveProperty("error");
expect(res.body.error).toMatch(/Failed to delete user/);
});
});

it("can successfully delete a user", async () => {
mockDeleteUser.mockResolvedValue(true);

await supertest(app)
.delete("/user/[email protected]")
.set(auth)
.expect(200)
.then((res) => {
expect(mockGetByEmail).toHaveBeenCalled();
expect(mockDeleteUser).toHaveBeenCalled();
expect(res.body).toHaveProperty("message");
expect(res.body.message).toMatch(/Successfully deleted user/);
});
});
});
8 changes: 7 additions & 1 deletion api.planx.uk/modules/user/routes.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { Router } from "express";
import { usePlatformAdminAuth } from "../auth/middleware";
import { validate } from "../../shared/middleware/validate";
import { createUserSchema, createUser } from "./controller";
import {
createUserSchema,
createUser,
deleteUserSchema,
deleteUser,
} from "./controller";

const router = Router();

router.use(usePlatformAdminAuth);
router.put("/", validate(createUserSchema), createUser);
router.delete("/:email", validate(deleteUserSchema), deleteUser);

export default router;
2 changes: 1 addition & 1 deletion api.planx.uk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"dependencies": {
"@airbrake/node": "^2.1.8",
"@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#44420b9",
"@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#3d395fa",
"@types/isomorphic-fetch": "^0.0.36",
"adm-zip": "^0.5.10",
"aws-sdk": "^2.1467.0",
Expand Down
15 changes: 7 additions & 8 deletions api.planx.uk/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions hasura.planx.uk/metadata/tables.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1148,3 +1148,10 @@
filter:
id:
_eq: x-hasura-user-id
update_permissions:
- role: platformAdmin
permission:
columns:
- email
filter: {}
check: {}
8 changes: 4 additions & 4 deletions hasura.planx.uk/tests/users.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ describe("users", () => {
expect(i.queries).toContain("users");
});

test("can creates users", () => {
test("can create and update users", () => {
expect(i.mutations).toContain("insert_users");
expect(i.mutations).toContain("update_users_by_pk");
expect(i.mutations).toContain("update_users");
});

test("cannot update or delete users", () => {
expect(i.mutations).not.toContain("update_users_by_pk");
expect(i.mutations).not.toContain("update_users");
test("cannot delete users", () => {
expect(i.mutations).not.toContain("delete_users");
});
});
Expand Down
Loading