Skip to content

Commit

Permalink
feat(api): support for DeleteUserPool
Browse files Browse the repository at this point in the history
  • Loading branch information
jagregory committed Feb 16, 2022
1 parent f5bca87 commit 9dd6f2d
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 7 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ A _Good Enough_ offline emulator for [Amazon Cognito](https://aws.amazon.com/cog
| DeleteResourceServer ||
| DeleteUser | ✅² |
| DeleteUserAttributes ||
| DeleteUserPool | |
| DeleteUserPool | ✅² |
| DeleteUserPoolClient | ✅² |
| DeleteUserPoolDomain ||
| DescribeIdentityProvider ||
Expand Down
41 changes: 41 additions & 0 deletions integration-tests/aws-sdk/deleteUserPool.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { withCognitoSdk } from "./setup";

describe(
"CognitoIdentityServiceProvider.deleteUserPool",
withCognitoSdk((Cognito) => {
it("deletes a group", async () => {
const client = Cognito();

// create the user pool
const up = await client
.createUserPool({
PoolName: "newPool",
})
.promise();

const listResponse = await client
.listUserPools({
MaxResults: 1,
})
.promise();

expect(listResponse.UserPools).toEqual([
expect.objectContaining({
Id: up.UserPool?.Id,
}),
]);

await client
.deleteUserPool({
UserPoolId: up.UserPool?.Id!,
})
.promise();

const listResponseAfter = await client
.listUserPools({ MaxResults: 1 })
.promise();

expect(listResponseAfter.UserPools).toHaveLength(0);
});
})
);
2 changes: 1 addition & 1 deletion integration-tests/aws-sdk/deleteUserPoolClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { withCognitoSdk } from "./setup";
describe(
"CognitoIdentityServiceProvider.deleteUserPoolClient",
withCognitoSdk((Cognito) => {
it("deletes a group", async () => {
it("deletes a user pool client", async () => {
const client = Cognito();

// create the user pool client
Expand Down
18 changes: 18 additions & 0 deletions integration-tests/cognitoService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,22 @@ describe("Cognito Service", () => {
{ ...USER_POOL_AWS_DEFAULTS, Id: "test-pool-3" },
]);
});

it("deletes user pools", async () => {
const cognitoService = await factory.create(TestContext, {});

const up1 = await cognitoService.getUserPool(TestContext, "test-pool-1");
const up2 = await cognitoService.getUserPool(TestContext, "test-pool-2");

expect(fs.existsSync(`${dataDirectory}/test-pool-1.json`)).toBe(true);
expect(fs.existsSync(`${dataDirectory}/test-pool-2.json`)).toBe(true);

await cognitoService.deleteUserPool(TestContext, up1.config);

expect(fs.existsSync(`${dataDirectory}/test-pool-1.json`)).not.toBe(true);

await cognitoService.deleteUserPool(TestContext, up2.config);

expect(fs.existsSync(`${dataDirectory}/test-pool-2.json`)).not.toBe(true);
});
});
1 change: 1 addition & 0 deletions src/__tests__/mockCognitoService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const newMockCognitoService = (
userPoolClient: UserPoolService = newMockUserPoolService()
): jest.Mocked<CognitoService> => ({
createUserPool: jest.fn(),
deleteUserPool: jest.fn(),
getAppClient: jest.fn(),
getUserPool: jest.fn().mockResolvedValue(userPoolClient),
getUserPoolForClientId: jest.fn().mockResolvedValue(userPoolClient),
Expand Down
18 changes: 13 additions & 5 deletions src/services/cognitoService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ import {
UserPoolService,
UserPoolServiceFactory,
} from "./userPoolService";
import fs from "fs";
import { promisify } from "util";

const readdir = promisify(fs.readdir);
import fs from "fs/promises";

const CLIENTS_DATABASE_NAME = "clients";

Expand Down Expand Up @@ -265,6 +262,7 @@ export const USER_POOL_AWS_DEFAULTS: UserPoolDefaults = {

export interface CognitoService {
createUserPool(ctx: Context, userPool: UserPool): Promise<UserPool>;
deleteUserPool(ctx: Context, userPool: UserPool): Promise<void>;
getAppClient(ctx: Context, clientId: string): Promise<AppClient | null>;
getUserPool(ctx: Context, userPoolId: string): Promise<UserPoolService>;
getUserPoolForClientId(
Expand Down Expand Up @@ -325,6 +323,14 @@ export class CognitoServiceImpl implements CognitoService {
return service.config;
}

public async deleteUserPool(ctx: Context, userPool: UserPool): Promise<void> {
ctx.logger.debug(
{ userPoolId: userPool.Id },
"CognitoServiceImpl.deleteUserPool"
);
await fs.rm(path.join(this.dataDirectory, `${userPool.Id}.json`));
}

public async getUserPool(
ctx: Context,
userPoolId: string
Expand Down Expand Up @@ -378,7 +384,9 @@ export class CognitoServiceImpl implements CognitoService {

public async listUserPools(ctx: Context): Promise<readonly UserPool[]> {
ctx.logger.debug("CognitoServiceImpl.listUserPools");
const entries = await readdir(this.dataDirectory, { withFileTypes: true });
const entries = await fs.readdir(this.dataDirectory, {
withFileTypes: true,
});

return Promise.all(
entries
Expand Down
38 changes: 38 additions & 0 deletions src/targets/deleteUserPool.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { newMockCognitoService } from "../__tests__/mockCognitoService";
import { newMockUserPoolService } from "../__tests__/mockUserPoolService";
import { TestContext } from "../__tests__/testContext";
import * as TDB from "../__tests__/testDataBuilder";
import { CognitoService } from "../services";
import { DeleteUserPool, DeleteUserPoolTarget } from "./deleteUserPool";

describe("DeleteUserPool target", () => {
let deleteUserPool: DeleteUserPoolTarget;
let mockCognitoService: jest.Mocked<CognitoService>;

beforeEach(() => {
mockCognitoService = newMockCognitoService(newMockUserPoolService());

deleteUserPool = DeleteUserPool({
cognito: mockCognitoService,
});
});

it("deletes a user pool client", async () => {
const userPool = TDB.userPool();

mockCognitoService.getUserPool.mockResolvedValue(
newMockUserPoolService(userPool)
);

await deleteUserPool(TestContext, {
UserPoolId: "test",
});

expect(mockCognitoService.deleteUserPool).toHaveBeenCalledWith(
TestContext,
userPool
);
});

it.todo("throws if the user pool doesn't exist");
});
22 changes: 22 additions & 0 deletions src/targets/deleteUserPool.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { DeleteUserPoolRequest } from "aws-sdk/clients/cognitoidentityserviceprovider";
import { ResourceNotFoundError } from "../errors";
import { Services } from "../services";
import { Target } from "./Target";

export type DeleteUserPoolTarget = Target<DeleteUserPoolRequest, {}>;

type DeleteUserPoolServices = Pick<Services, "cognito">;

export const DeleteUserPool =
({ cognito }: DeleteUserPoolServices): DeleteUserPoolTarget =>
async (ctx, req) => {
// TODO: from the docs "Calling this action requires developer credentials.", can we enforce this?
const userPool = await cognito.getUserPool(ctx, req.UserPoolId);
if (!userPool) {
throw new ResourceNotFoundError();
}

await cognito.deleteUserPool(ctx, userPool.config);

return {};
};
2 changes: 2 additions & 0 deletions src/targets/targets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { CreateUserPoolClient } from "./createUserPoolClient";
import { DeleteGroup } from "./deleteGroup";
import { DeleteUser } from "./deleteUser";
import { DeleteUserAttributes } from "./deleteUserAttributes";
import { DeleteUserPool } from "./deleteUserPool";
import { DeleteUserPoolClient } from "./deleteUserPoolClient";
import { DescribeUserPoolClient } from "./describeUserPoolClient";
import { ForgotPassword } from "./forgotPassword";
Expand Down Expand Up @@ -59,6 +60,7 @@ export const Targets = {
DeleteGroup,
DeleteUser,
DeleteUserAttributes,
DeleteUserPool,
DeleteUserPoolClient,
DescribeUserPoolClient,
ForgotPassword,
Expand Down

0 comments on commit 9dd6f2d

Please sign in to comment.