feat(api): show a user pool's Lambda triggers

This commit is contained in:
Zakaria
2026-10-24 02:07:18 -04:00
parent 954e2e8a47
commit d411f632c9
5 changed files with 107 additions and 0 deletions
@@ -125,9 +125,31 @@ describe('AwsUserPoolsAdapter', () => {
mfaConfiguration: 'OFF',
deletionProtection: 'INACTIVE',
appClients: [{clientId: 'a8e5c7d38d3b4a1a97c9d822de', clientName: 'orders-users-client'}],
lambdaTriggers: [],
})
})
test('lists the pool\'s Lambda triggers in sign-in order, with the trigger version when set', async () => {
const arn = (name: string) => `arn:aws:lambda:us-east-1:000000000000:function:${name}`
const {client} = stubCognito((command) => {
if (command instanceof DescribeUserPoolCommand) return {UserPool: {...pool, LambdaConfig: {
PreTokenGeneration: arn('claims'),
PreTokenGenerationConfig: {LambdaArn: arn('claims'), LambdaVersion: 'V2_0'},
PreSignUp: `${arn('signup')}:live`,
CustomEmailSender: {LambdaArn: arn('mailer'), LambdaVersion: 'V1_0'},
KMSKeyID: 'arn:aws:kms:us-east-1:000000000000:key/1',
}}}
return {}
})
const resource = await new AwsUserPoolsAdapter(client).get(POOL_ID)
expect(resource?.metadata.lambdaTriggers).toEqual([
{trigger: 'PreSignUp', label: 'Pre sign-up', functionArn: `${arn('signup')}:live`, functionName: 'signup', version: null},
{trigger: 'PreTokenGeneration', label: 'Pre token generation', functionArn: arn('claims'), functionName: 'claims', version: 'V2_0'},
{trigger: 'CustomEmailSender', label: 'Custom email sender', functionArn: arn('mailer'), functionName: 'mailer', version: 'V1_0'},
])
})
test('counts users itself, since the runtime leaves EstimatedNumberOfUsers at 0', async () => {
const {client} = stubCognito((command) => {
if (command instanceof DescribeUserPoolCommand) return {UserPool: {...pool, EstimatedNumberOfUsers: 0}}
@@ -460,10 +460,43 @@ function toResource(pool: UserPoolType, clients: UserPoolClientDescription[], us
mfaConfiguration: pool.MfaConfiguration ?? null,
deletionProtection: pool.DeletionProtection ?? null,
appClients: clients.map((client) => ({clientId: client.ClientId ?? '', clientName: client.ClientName ?? ''})),
lambdaTriggers: lambdaTriggersOf(pool.LambdaConfig),
},
}
}
// Labels as the AWS console names them, in the order a sign-up and sign-in reach them.
const LAMBDA_TRIGGERS = [
['PreSignUp', 'Pre sign-up'],
['UserMigration', 'User migration'],
['CustomMessage', 'Custom message'],
['PostConfirmation', 'Post confirmation'],
['PreAuthentication', 'Pre authentication'],
['DefineAuthChallenge', 'Define auth challenge'],
['CreateAuthChallenge', 'Create auth challenge'],
['VerifyAuthChallengeResponse', 'Verify auth challenge response'],
['PostAuthentication', 'Post authentication'],
['PreTokenGeneration', 'Pre token generation'],
['CustomEmailSender', 'Custom email sender'],
['CustomSMSSender', 'Custom SMS sender'],
] as const
type LambdaTrigger = {trigger: string; label: string; functionArn: string; functionName: string; version: string | null}
function lambdaTriggersOf(config: UserPoolType['LambdaConfig']): LambdaTrigger[] {
if (!config) return []
return LAMBDA_TRIGGERS.flatMap(([trigger, label]) => {
// PreTokenGenerationConfig carries the trigger version and supersedes the older PreTokenGeneration field.
const versioned = trigger === 'PreTokenGeneration' ? config.PreTokenGenerationConfig
: trigger === 'CustomEmailSender' ? config.CustomEmailSender
: trigger === 'CustomSMSSender' ? config.CustomSMSSender
: undefined
const functionArn = versioned?.LambdaArn ?? config[trigger]
if (typeof functionArn !== 'string' || !functionArn) return []
return [{trigger, label, functionArn, functionName: functionArn.split(':')[6] ?? functionArn, version: versioned?.LambdaVersion ?? null}]
})
}
function toUserItem(
username: string | undefined,
attributes: AttributeType[] | undefined,