Skip to content

Commit

Permalink
feat: implement DeleteUserPoolCommand and DeleteUserPoolClientCommand
Browse files Browse the repository at this point in the history
  • Loading branch information
solufa committed Dec 29, 2024
1 parent 5ec2689 commit c8935a8
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 4 deletions.
8 changes: 4 additions & 4 deletions IMPLEMENTATION_COVERAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## cognito-idp

<details>
<summary> 26% implemented </summary>
<summary> 29% implemented </summary>

- [ ] AddCustomAttributes
- [ ] AdminAddUserToGroup
Expand Down Expand Up @@ -49,8 +49,8 @@
- [ ] DeleteResourceServer
- [ ] DeleteUser
- [x] DeleteUserAttributes
- [ ] DeleteUserPool
- [ ] DeleteUserPoolClient
- [x] DeleteUserPool
- [x] DeleteUserPoolClient
- [ ] DeleteUserPoolDomain
- [ ] DescribeIdentityProvider
- [ ] DescribeResourceServer
Expand Down Expand Up @@ -79,7 +79,7 @@
- [ ] ListResourceServers
- [ ] ListTagsForResource
- [ ] ListUserImportJobs
- [ ] ListUserPoolClients
- [x] ListUserPoolClients
- [x] ListUserPools
- [x] ListUsers
- [ ] ListUsersInGroup
Expand Down
3 changes: 3 additions & 0 deletions server/api/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ const useCases: {
'AWSCognitoIdentityProviderService.RevokeToken': authUseCase.revokeToken,
'AWSCognitoIdentityProviderService.ResendConfirmationCode': signUpUseCase.resendConfirmationCode,
'AWSCognitoIdentityProviderService.ListUserPools': userPoolUseCase.listUserPools,
'AWSCognitoIdentityProviderService.ListUserPoolClients': userPoolUseCase.listUserPoolClients,
'AWSCognitoIdentityProviderService.CreateUserPool': userPoolUseCase.createUserPool,
'AWSCognitoIdentityProviderService.CreateUserPoolClient': userPoolUseCase.createUserPoolClient,
'AWSCognitoIdentityProviderService.DeleteUserPool': userPoolUseCase.deleteUserPool,
'AWSCognitoIdentityProviderService.DeleteUserPoolClient': userPoolUseCase.deleteUserPoolClient,
'AWSCognitoIdentityProviderService.ListUsers': authUseCase.listUsers,
'AWSCognitoIdentityProviderService.AdminGetUser': adminUseCase.getUser,
'AWSCognitoIdentityProviderService.AdminCreateUser': adminUseCase.createUser,
Expand Down
19 changes: 19 additions & 0 deletions server/common/types/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ import type {
CreateUserPoolResponse,
DeleteUserAttributesRequest,
DeleteUserAttributesResponse,
DeleteUserPoolClientRequest,
DeleteUserPoolRequest,
GetUserResponse,
ListUserPoolClientsRequest,
ListUserPoolClientsResponse,
ListUserPoolsRequest,
ListUserPoolsResponse,
ListUsersRequest,
Expand Down Expand Up @@ -65,13 +69,25 @@ export type ListUsersTarget = TargetBody<ListUsersRequest, ListUsersResponse>;

export type ListUserPoolsTarget = TargetBody<ListUserPoolsRequest, ListUserPoolsResponse>;

export type ListUserPoolClientsTarget = TargetBody<
ListUserPoolClientsRequest,
ListUserPoolClientsResponse
>;

export type CreateUserPoolTarget = TargetBody<CreateUserPoolRequest, CreateUserPoolResponse>;

export type CreateUserPoolClientTarget = TargetBody<
CreateUserPoolClientRequest,
CreateUserPoolClientResponse
>;

export type DeleteUserPoolTarget = TargetBody<DeleteUserPoolRequest, Record<string, never>>;

export type DeleteUserPoolClientTarget = TargetBody<
DeleteUserPoolClientRequest,
Record<string, never>
>;

export type AdminGetUserTarget = TargetBody<AdminGetUserRequest, AdminGetUserResponse>;

export type AdminCreateUserTarget = TargetBody<AdminCreateUserRequest, AdminCreateUserResponse>;
Expand Down Expand Up @@ -158,8 +174,11 @@ export type AmzTargets = {
'AWSCognitoIdentityProviderService.ResendConfirmationCode': ResendConfirmationCodeTarget;
'AWSCognitoIdentityProviderService.ListUsers': ListUsersTarget;
'AWSCognitoIdentityProviderService.ListUserPools': ListUserPoolsTarget;
'AWSCognitoIdentityProviderService.ListUserPoolClients': ListUserPoolClientsTarget;
'AWSCognitoIdentityProviderService.CreateUserPool': CreateUserPoolTarget;
'AWSCognitoIdentityProviderService.CreateUserPoolClient': CreateUserPoolClientTarget;
'AWSCognitoIdentityProviderService.DeleteUserPool': DeleteUserPoolTarget;
'AWSCognitoIdentityProviderService.DeleteUserPoolClient': DeleteUserPoolClientTarget;
'AWSCognitoIdentityProviderService.AdminGetUser': AdminGetUserTarget;
'AWSCognitoIdentityProviderService.AdminCreateUser': AdminCreateUserTarget;
'AWSCognitoIdentityProviderService.AdminDeleteUser': AdminDeleteUserTarget;
Expand Down
12 changes: 12 additions & 0 deletions server/domain/userPool/repository/userPoolCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,16 @@ export const userPoolCommand = {
},
});
},
delete: async (tx: Prisma.TransactionClient, pool: UserPoolEntity): Promise<void> => {
await tx.userAttribute.deleteMany({ where: { User: { userPoolId: pool.id } } });
await tx.user.deleteMany({ where: { userPoolId: pool.id } });
await tx.userPoolClient.deleteMany({ where: { userPoolId: pool.id } });
await tx.userPool.delete({ where: { id: pool.id } });
},
deleteClient: async (
tx: Prisma.TransactionClient,
poolClient: UserPoolClientEntity,
): Promise<void> => {
await tx.userPoolClient.delete({ where: { id: poolClient.id } });
},
};
8 changes: 8 additions & 0 deletions server/domain/userPool/repository/userPoolQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ import { toUserPoolClientEntity, toUserPoolEntity } from './toUserPoolEntity';
export const userPoolQuery = {
listAll: (tx: Prisma.TransactionClient, limit?: number): Promise<UserPoolEntity[]> =>
tx.userPool.findMany({ take: limit }).then((pools) => pools.map(toUserPoolEntity)),
listClientAll: (
tx: Prisma.TransactionClient,
userPoolId: string,
limit?: number,
): Promise<UserPoolClientEntity[]> =>
tx.userPoolClient
.findMany({ where: { userPoolId }, take: limit })
.then((clients) => clients.map(toUserPoolClientEntity)),
findById: (tx: Prisma.TransactionClient, userPoolId: string): Promise<UserPoolEntity> =>
tx.userPool.findUniqueOrThrow({ where: { id: userPoolId } }).then(toUserPoolEntity),
findJwks: (tx: Prisma.TransactionClient, userPoolId: string): Promise<Jwks> =>
Expand Down
38 changes: 38 additions & 0 deletions server/domain/userPool/useCase/userPoolUseCase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import assert from 'assert';
import type {
CreateUserPoolClientTarget,
CreateUserPoolTarget,
DeleteUserPoolClientTarget,
DeleteUserPoolTarget,
ListUserPoolClientsTarget,
ListUserPoolsTarget,
} from 'common/types/auth';
import { DEFAULT_USER_POOL_CLIENT_ID, DEFAULT_USER_POOL_ID } from 'service/envValues';
Expand Down Expand Up @@ -40,6 +43,15 @@ export const userPoolUseCase = {

return { UserPools: pools.map((p) => ({ Id: p.id, Name: p.name })) };
},
listUserPoolClients: async (
req: ListUserPoolClientsTarget['reqBody'],
): Promise<ListUserPoolClientsTarget['resBody']> => {
assert(req.UserPoolId);

const clients = await userPoolQuery.listClientAll(prismaClient, req.UserPoolId, req.MaxResults);

return { UserPoolClients: clients.map((c) => ({ ClientId: c.id, ClientName: c.name })) };
},
createUserPool: (
req: CreateUserPoolTarget['reqBody'],
): Promise<CreateUserPoolTarget['resBody']> =>
Expand All @@ -66,4 +78,30 @@ export const userPoolUseCase = {
UserPoolClient: { ClientId: client.id, UserPoolId: pool.id, ClientName: client.name },
};
}),
deleteUserPool: (
req: DeleteUserPoolTarget['reqBody'],
): Promise<DeleteUserPoolTarget['resBody']> =>
transaction(async (tx) => {
assert(req.UserPoolId);

const pool = await userPoolQuery.findById(tx, req.UserPoolId);

await userPoolCommand.delete(tx, pool);

return {};
}),
deleteUserPoolClient: (
req: DeleteUserPoolClientTarget['reqBody'],
): Promise<DeleteUserPoolClientTarget['resBody']> =>
transaction(async (tx) => {
assert(req.ClientId);

const client = await userPoolQuery.findClientById(tx, req.ClientId);

assert(client.userPoolId === req.UserPoolId);

await userPoolCommand.deleteClient(tx, client);

return {};
}),
};
56 changes: 56 additions & 0 deletions server/tests/sdk/pool.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import {
AdminCreateUserCommand,
CreateUserPoolClientCommand,
CreateUserPoolCommand,
DeleteUserPoolClientCommand,
DeleteUserPoolCommand,
ListUserPoolClientsCommand,
ListUserPoolsCommand,
} from '@aws-sdk/client-cognito-identity-provider';
import { cognitoClient } from 'service/cognito';
import { expect, test } from 'vitest';
Expand All @@ -14,3 +19,54 @@ test(CreateUserPoolCommand.name, async () => {
expect(pool.UserPool?.Name === 'testPool').toBeTruthy();
expect(client.UserPoolClient?.ClientName === 'testClient').toBeTruthy();
});

// eslint-disable-next-line complexity
test(DeleteUserPoolCommand.name, async () => {
const pool = await cognitoClient.send(new CreateUserPoolCommand({ PoolName: 'testPool' }));

await cognitoClient.send(
new CreateUserPoolClientCommand({ ClientName: 'testClient', UserPoolId: pool.UserPool?.Id }),
);
await cognitoClient.send(
new AdminCreateUserCommand({
UserPoolId: pool.UserPool?.Id,
Username: 'test',
UserAttributes: [{ Name: 'email', Value: '[email protected]' }],
}),
);

const res1 = await cognitoClient.send(new ListUserPoolsCommand({ MaxResults: 100 }));

await cognitoClient.send(new DeleteUserPoolCommand({ UserPoolId: pool.UserPool?.Id }));

const res2 = await cognitoClient.send(new ListUserPoolsCommand({ MaxResults: 100 }));

expect(res1.UserPools?.length).toBe(2);
expect(res2.UserPools?.length).toBe(1);
});

// eslint-disable-next-line complexity
test(DeleteUserPoolClientCommand.name, async () => {
const pool = await cognitoClient.send(new CreateUserPoolCommand({ PoolName: 'testPool' }));
const client = await cognitoClient.send(
new CreateUserPoolClientCommand({ ClientName: 'testClient', UserPoolId: pool.UserPool?.Id }),
);

const res1 = await cognitoClient.send(
new ListUserPoolClientsCommand({ UserPoolId: pool.UserPool?.Id, MaxResults: 100 }),
);

await cognitoClient.send(
new DeleteUserPoolClientCommand({
ClientId: client.UserPoolClient?.ClientId,
UserPoolId: pool.UserPool?.Id,
}),
);

const res2 = await cognitoClient.send(
new ListUserPoolClientsCommand({ UserPoolId: pool.UserPool?.Id, MaxResults: 100 }),
);

expect(res1.UserPoolClients?.length).toBe(1);
expect(res2.UserPoolClients?.length).toBe(0);
});

0 comments on commit c8935a8

Please sign in to comment.