Reputation: 51
I'm read all the Amplify Gen 2 Documentation but I don't find how to list all registered users in application.
It's because need to create a admin page to list all users with his roles in Angular.
I think that probably can do this with lambda functions or something like that but I don't find nothing about that.
Thanks for all!
I'm read all the documentation: https://docs.amplify.aws/angular/build-a-backend/auth/connect-your-frontend/
Upvotes: 2
Views: 672
Reputation: 1
You can implement a lambda function that uses the CognitoIdentityProviderClient from the aws-sdk to get the user list. And then define a custom query that calls the function:
data/resource/list-users-handler/handler.ts
import { env } from '$amplify/env/list-users-handler';
import type { Schema } from '../resource';
import {
CognitoIdentityProviderClient,
ListUsersCommand,
} from '@aws-sdk/client-cognito-identity-provider';
const client = new CognitoIdentityProviderClient();
export const handler: Schema['usersList']['functionHandler'] = async () => {
const command = new ListUsersCommand({
UserPoolId: env.AMPLIFY_AUTH_USERPOOL_ID,
});
const response = await client.send(command);
// Ensure the return type of the function matches the one defined in the query
const Users: Schema['UsersResponse']['type'] = {
users:
response.Users?.map((user) => {
return {
Username: user.Username || '',
UserStatus: user.UserStatus || '',
UserCreateDate: user.UserCreateDate?.toISOString() || '',
UserLastModifiedDate: user.UserLastModifiedDate?.toISOString() || '',
Enabled: user.Enabled || false,
Attributes:
user.Attributes?.map((attribute) => {
return {
Name: attribute.Name || '',
Value: attribute.Value || '',
};
}) || [],
};
}) || [],
};
return Users;
};
data/resources.ts
import {
type ClientSchema,
a,
defineData,
defineFunction,
} from '@aws-amplify/backend';
export const usersListHandler = defineFunction({
name: 'list-users-handler',
entry: 'list-users-handler/handler.ts',
});
const schema = a.schema({
UserAttribute: a.customType({
Name: a.string(),
Value: a.string(),
}),
User: a.customType({
Attributes: a.ref('UserAttribute').array(),
Enabled: a.boolean(),
UserCreateDate: a.datetime(),
UserLastModifiedDate: a.datetime(),
UserStatus: a.string(),
Username: a.string(),
}),
UsersResponse: a.customType({
users: a.ref('User').array(),
}),
usersList: a
.query()
// return type of the query
.returns(a.ref('UsersResponse'))
// only allow users in the ADMIN group to call the API
.authorization((allow) => [allow.group('ADMINS')])
.handler(a.handler.function(usersListHandler)),
});
export type Schema = ClientSchema<typeof schema>;
// Set the authorization mode to user pool
export const data = defineData({
schema,
authorizationModes: {
defaultAuthorizationMode: 'userPool',
},
});
Then you need to authorize the lambda function so it can get the user list from the cognito user pool.
auth/resource.ts
import { defineAuth } from '@aws-amplify/backend';
import { usersListHandler } from '../data/resource';
export const auth = defineAuth({
loginWith: {
email: true,
},
userAttributes: {
givenName: {
required: true,
mutable: true,
},
familyName: {
required: true,
mutable: true,
},
},
groups: ['ADMINS', 'USERS'],
access: (allow) => [
allow.resource(usersListHandler).to(['listUsers']),
],
});
backend.ts
import { defineBackend } from '@aws-amplify/backend';
import { auth } from './auth/resource';
import { data } from './data/resource';
const backend = defineBackend({
auth,
data,
});
Finally you can acces the query API from the frontend like this:
import { generateClient } from 'aws-amplify/api';
const client = generateClient<Schema>();
const { data, errors } = await client.queries.usersList({
authMode: 'userPool',
});
if (errors) {
console.error(errors);
} else if (data) {
console.log(data);
} else {
console.warn('No data or errors found');
}
Upvotes: 0
Reputation: 51
The solution is create custom function that return all users by Cognito Pool and assign manually the permission to this function:
cognito-idp:ListUsers
backend.ts
import { defineBackend } from '@aws-amplify/backend';
import { auth } from './auth/resource';
import { data } from './data/resource';
import * as iam from "aws-cdk-lib/aws-iam";
import {listUsers} from "./data/list-users/resource";
import {PolicyStatement} from "aws-cdk-lib/aws-iam";
const backend = defineBackend({
auth,
data,
listUsers
});
const lambdaFunction = backend.listUsers.resources.lambda;
lambdaFunction.role?.attachInlinePolicy(
new iam.Policy(backend.auth.resources.userPool, "AllowListUsers", {
statements: [
new iam.PolicyStatement({
actions: ["cognito-idp:ListUsers"],
resources: [backend.auth.resources.userPool.userPoolArn],
}),
],
})
);
auth/resource.ts
import { defineAuth } from '@aws-amplify/backend';
import {addUserToGroup} from "../data/add-user-to-group/resource";
import {listUsers} from "../data/list-users/resource";
export const auth = defineAuth({
loginWith: {
email: true,
},
groups: ["ADMINS"],
access: (allow) => [
allow.resource(addUserToGroup).to(["addUserToGroup"]),
allow.resource(listUsers).to(["manageUsers"]),
],
});
data/list-users/resource.ts
import { defineFunction } from "@aws-amplify/backend"
export const listUsers = defineFunction({
name: "list-users",
})
data/list-users/handler.ts
import { env } from "$amplify/env/list-users"
import type { Schema } from "../resource"
import { CognitoIdentityProviderClient, ListUsersCommand } from "@aws-sdk/client-cognito-identity-provider";
type Handler = Schema["listUsers"]["functionHandler"]
const client = new CognitoIdentityProviderClient()
export const handler: Handler = async (event) => {
const command = new ListUsersCommand({ UserPoolId: env.AMPLIFY_AUTH_USERPOOL_ID });
const response = await client.send(command)
return response;
}
Upvotes: 0