Skip to content

Commit

Permalink
feat(api): Remove user endpoint (#2249)
Browse files Browse the repository at this point in the history
* feat: Grant platformAdmin user update permissions

* feat: Delete user endpoint

* test: Add API tests for new endpoint
  • Loading branch information
DafyddLlyr authored Oct 2, 2023
1 parent 4c84b41 commit a059f60
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 13 deletions.
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
8 changes: 4 additions & 4 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

0 comments on commit a059f60

Please sign in to comment.