User is not authorized to perform: dynamodb:CreateTable on resource: - aws-lambda

When I tried to run my lambda function register which queries the table example_user, it will throw the error below. My code is only trying to get data from the table example_user and not create any table.
{"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"AccessDeniedException: User: arn:aws:sts::577777777777:assumed-role/example-user-api-dev-ap-southeast-1-lambdaRole/example-user-api-dev-register is not authorized to perform: dynamodb:CreateTable on resource: arn:aws:dynamodb:ap-southeast-1:577777777777:table/example_user","reason":{"errorType":"AccessDeniedException","errorMessage":"User: arn:aws:sts::577777777777:assumed-role/example-user-api-dev-ap-southeast-1-lambdaRole/example-user-api-dev-register is not authorized to perform: dynamodb:CreateTable on resource: arn:aws:dynamodb:ap-southeast-1:577777777777:table/example_user"
The error was thrown after 13 UserController with email
This is my codes:
User.js
const schema = new dynamoose.Schema({
"email": String,
"uid": String,
"name": String,
"gender": {
"type": Number,
"default": 0
},
"profileImageType": {
"type": Number,
"default": 0
},
"profileImage": String,
"accountType": Number,
}, {
"saveUnknown": true,
"timestamps": true
});
module.exports = dynamoose.model('example_user', schema);
UserController.js
const User = require("./User.js");
exports.getProfile = async function(email,res){
console.log("13 UserController with email " + email)
var profile = await User.get(email)
console.log("15 profile")
console.log(profile)
if (profile){
return profile;
}else{
return false;
}
};
Below is a snippet from my serverless.yml file
iamRoleStatements:
- Effect: "Allow"
Action:
- "s3:*"
Resource:
- "arn:aws:s3:::profiles.example.app/*"
- Effect: "Allow"
Action:
- dynamodb:Query
- dynamodb:Scan
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
Resource:
- "arn:aws:dynamodb:ap-southeast-1:577777777777:table/example_user"

You should be able to do dynamoose.model('example_user', schema, {"create": false}) to get away from the need to create a table https://dynamoosejs.com/guide/Model/

Related

AWS AppSync Mapping Template DynamoDB Query doesn't work

I'm using AWS CDK version 2.64.0 to configure AWS AppSync to setup my GraphQL API.
I created my graphql.schema with the following configuration:
type message {
id_message: String!
id_collection: String!
id_user: String!
created_at: String!
text: String!
}
type Query {
getMessages(idCollectionIdUser: String!): [ message! ]
}
And then I used the configuration above to create my GraphQL API using these commands:
const api = new appsync.GraphqlApi(this, 'GraphQLDatabase', {
name: 'my-graphql-database',
schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'schema.graphql')),
xrayEnabled: true,
});
I also created one dynamodb table (with one global secondary index) using the following commands:
const messageTable = new dynamodb.Table(this, 'MessageTable', {
partitionKey: {
name: 'id_message',
type: dynamodb.AttributeType.STRING,
},
tableName: 'message.dynamodb-table',
removalPolicy: RemovalPolicy.DESTROY,
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
});
messageTable.addGlobalSecondaryIndex({
indexName: 'id_collection-id_user-created_at-index',
partitionKey: {
name: 'id_collection-id_user',
type: dynamodb.AttributeType.STRING,
},
sortKey: {
name: 'created_at',
type: dynamodb.AttributeType.NUMBER,
},
projectionType: ProjectionType.ALL,
});
Then I added the dynamodb table as datasource for the graphql database:
const messageDataSource = api.addDynamoDbDataSource('messageDataSource', messageTable);
I'm now trying to create a resolver to get all the messages created by the user in a collection with the following code:
messageDataSource.createResolver('QueryGetMessagesResolver', {
typeName: 'Query',
fieldName: 'getMessages',
requestMappingTemplate: appsync.MappingTemplate.dynamoDbQuery(
appsync.KeyCondition.eq('id_collection-id_user', 'idCollectionIdUser'),
'id_collection-id_user-created_at-index',
false,
),
responseMappingTemplate: appsync.MappingTemplate.dynamoDbResultList(),
});
When I test my graph api, I always get this error:
ExpressionAttributeNames contains invalid key: Syntax error; key: "#id_collection-id_user"
What am I doing wrong?

UnknownOperationException: GraphQl Appsync with AWS API Gateway

I have integrated API Gateway as a proxy to AWS AppSync data plane via AWS CDK. I am trying to test the connection between API Gateway and AWS Appsync. I am getting to UnknownOperationException while testing calling appsync endpoint via the API gateway.
Below are the code snippet
const api = new appsync.GraphqlApi(this, 'UserApi', {
name: 'user-appsync-api',
schema: appsync.Schema.fromAsset('lib/graphql/schema.graphql'),
authorizationConfig: {
defaultAuthorization: {
authorizationType: appsync.AuthorizationType.API_KEY,
apiKeyConfig: {
expires: cdk.Expiration.after(cdk.Duration.days(365))
}
},
},
xrayEnabled: true,
});
const createUserAPIGraphQl = apigateway.root.addResource('user-graphql');
createUserAPIGraphQl.addMethod("POST", new apigw.AwsIntegration({
service: 'appsync-api',
region: 'us-east-1',
subdomain: 'adsdasdsadasdasd',
integrationHttpMethod: 'POST',
path: 'user-graphql',
options: {
passthroughBehavior: PassthroughBehavior.WHEN_NO_TEMPLATES,
credentialsRole: ApiGatewayAppSyncRole,
integrationResponses: [{
statusCode: '200'
}]
},
}
), {
methodResponses: [
{
statusCode: '200',
responseModels: {
'application/json': Model.EMPTY_MODEL
}
},
]
});
RequestBody
{
"query": "query getNoteById { getNoteById(noteId: \"001\") { id }}"
}
Error:
{
"errors": [
{
"errorType": "UnknownOperationException",
"message": "Unknown Operation Request."
}
]
}
API Gateway Logs:
Mon Jul 11 10:20:21 UTC 2022 : Endpoint response body before transformations:
{
"errors" : [ {
"errorType" : "UnknownOperationException",
"message" : "Unknown Operation Request."
} ]
}

Partial Update Mutations(GraphQL)

How can I be able to update a node with only one field change and leave the rest of the fields alone?
My User Type
type User {
id: ID!
user_id: String!
username: String!
email: String!
role: Role!
isVerified: Boolean!
}
My Input Types
input UserUpdateInput {
user_id: String
username: String
email: String
password: String
role: Role
isVerified: Boolean
}
input UserWhereUniqueInput {
id: ID
user_id: String
email: String
}
My Mutation type
type Mutation {
updateUser(data: UserUpdateInput!, where: UserWhereUniqueInput): User
}
My Resolver
function updateUser(root, args, context, info){
return context.db.mutation.updateUser({
data: args.data,
where: {
id: args.where.id
}
}, info)
}
This is the request am sending on the GraphQL playground
mutation{
updateUser(
data: {
isVerified: true
}
where:{
user_id : "afc485b"
}
)
{
isVerified
}
}
This is the error am getting
{
"errors": [
{
"message": "Cannot read property 'mutation' of undefined",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"updateUser"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"TypeError: Cannot read property 'mutation' of undefined"
Someone help me. What am I missing?
After updating my server as suggested by Daniel Rearden on the answer section, am getting a new error
{
"message": "Cannot read property 'updateUser' of undefined",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"updateUser"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"TypeError: Cannot read property 'updateUser' of undefined"
The error is the result of not correctly adding the db property to you context. Assuming you're still using version 1, your code should look something like this:
const { prisma } = require('./generated/prisma-client')
const server = new ApolloServer({
...
context: {
db: prisma,
},
})
First thing I notice is you GQL query is not correct.
Yours:
mutation{
updateUser(
data: {
isVerified: true
}
where:{
user_id : "afc485b"
}
)
{
isVerified
}
}
after the word "mutation" you set a name to the call, i.e.
"UpdateUser" but can literally be anything. for each part of the
where clause you need to make the check value an object, i.e.
where: { myProperty: {eq: "some value"}}
So your query should be more like this:
mutation UpdateUser {
updateUser(
data: {isVerified: true}
where:{user_id : {eq: "afc485b"}}
)
{
isVerified
}
}
Hope that helps a little... I didn't fully read the rest but thought this would help with the initial error you were getting.

AWS Cognito's SMS Multi Factor Authentication returns invalid code or auth state

I am trying to implement authentication built on Cognito using their Go SDK. I have been able to get basic username/password authentication to work, but when I add in 2-factor authentication using SMS I am getting stuck.
Steps to reproduce :
I create the user with a username/password and email verification
I validate the email address
I set the phone number and request a verification code
I verify the phone number
I enable 2-factor authentication (via SMS)
I try to sign in and receive the SMS_MFA challenge
I receive the code on my phone and call AdminRespondToAuthChallenge
Problem, I receive an error :
CodeMismatchException: Invalid code or auth state for the user.
status code: 400, request id: 1513894e-8efa-11e8-a8f8-97e5e083c03b
The SMS verification code is certainly correct, so it seems that it must be something to do with the auth state.
The calls to Cognito look like this:
c.cip.SignUp(&cognitoidentityprovider.SignUpInput{
ClientId: aws.String(c.clientID),
Username: aws.String(username),
Password: aws.String(password),
UserAttributes: []*cognitoidentityprovider.AttributeType{
{
Name: aws.String("email"),
Value: aws.String(email),
},
{
Name: aws.String("name"),
Value: aws.String(fullName),
},
},
})
c.cip.ConfirmSignUp(&cognitoidentityprovider.ConfirmSignUpInput{
ClientId: aws.String(c.clientID),
Username: aws.String(username),
ConfirmationCode: aws.String(code),
})
//Add the phone number
c.cip.AdminUpdateUserAttributes(&cognitoidentityprovider.AdminUpdateUserAttributesInput{
UserPoolId: aws.String(c.userPoolID),
Username: aws.String(username),
UserAttributes: []*cognitoidentityprovider.AttributeType{
{
Name: aws.String("phone_number"),
Value: aws.String(phoneNumber),
},
},
})
//Request a verification code
c.cip.GetUserAttributeVerificationCode(&cognitoidentityprovider.GetUserAttributeVerificationCodeInput{
AccessToken: aws.String(accessToken),
AttributeName: aws.String("phone_number"),
})
//Verify the phone number
c.cip.VerifyUserAttribute(&cognitoidentityprovider.VerifyUserAttributeInput{
AccessToken: aws.String(accessToken),
AttributeName: aws.String("phone_number"),
Code: aws.String(code),
})
//Enable SMS 2-factor auth c.cip.AdminSetUserSettings(&cognitoidentityprovider.AdminSetUserSettingsInput{
UserPoolId: aws.String(c.userPoolID),
Username: aws.String(username),
MFAOptions: []*cognitoidentityprovider.MFAOptionType{
&cognitoidentityprovider.MFAOptionType{
AttributeName: aws.String("phone_number"),
DeliveryMedium: aws.String("SMS"),
},
},
})
c.cip.AdminInitiateAuth(&cognitoidentityprovider.AdminInitiateAuthInput{
ClientId: aws.String(c.clientID),
UserPoolId: aws.String(c.userPoolID),
AuthFlow: aws.String("ADMIN_NO_SRP_AUTH"),
AuthParameters: map[string]*string{
"USERNAME": aws.String(username),
"PASSWORD": aws.String(password),
},
})
c.cip.AdminRespondToAuthChallenge(&cognitoidentityprovider.AdminRespondToAuthChallengeInput{
ClientId: aws.String(c.clientID),
UserPoolId: aws.String(c.userPoolID),
ChallengeName: aws.String("SMS_MFA"),
Session: aws.String(session),
ChallengeResponses: map[string]*string{
"USERNAME": aws.String(username),
"SMS_MFA_CODE": aws.String(code),
},
})
Doing a GetUser call shows the current state of the user:
User = {
Enabled: true,
MFAOptions: [{
AttributeName: "phone_number",
DeliveryMedium: "SMS"
}],
PreferredMfaSetting: "SMS_MFA",
UserAttributes: [
{
Name: "sub",
Value: "bd2bb8bc-dfe6-4216-829c-5ae975ce24e5"
},
{
Name: "email_verified",
Value: "true"
},
{
Name: "name",
Value: "Ben Vogan"
},
{
Name: "phone_number_verified",
Value: "true"
},
{
Name: "phone_number",
Value: "<redacted>"
},
{
Name: "email",
Value: "<redacted>"
}
],
UserCreateDate: 2018-07-24 03:29:49 +0000 UTC,
UserLastModifiedDate: 2018-07-24 04:19:51 +0000 UTC,
UserMFASettingList: ["SMS_MFA"],
UserStatus: "CONFIRMED",
Username: "bd2bb8bc-dfe6-4216-829c-5ae975ce24e5"
}
I do not know if there is a way to query the user's auth state so that I can verify that.
The AWS documentation and unhelpful errors are driving me insane so any help would be greatly appreciated!
Thanks.
Your questions seems ambiguous.
step 2 you are
I set the phone number and request a verification code
I verify the phone number
this is nothing but MFA in Cognito. if you have configured the pool correctly.
You cannot have both phone for login and MFA. that doesn't make sense.
but if you have phone for login, then Cognito will send SMS every time with code. password is only for email logins.

How to set role when register a new user using strapi?

I'm try register an user and i would like to know how can i set role as Administrator.
I tried
user: {
username: "elialber",
email: "falecom#elialber.com.br",
password: "123456789",
role: ???
}
I'm using Angular5 and just api strapi
step 1: Go to node_modules/strapi-plugin-users-permissions/controllers/Auth.js
step 2: Go to on line 457(in my code)
step 3: Comment params.role=role.id; like (//params.role = role.id;)
and now you can pass role id like 1 or 2 or 3 as follow
{
"blocked":false,
"confirmed":true,
"username":"aziz",
"email":"musa#binarymarvels.com",
"password":"musa01010",
"role": 2
}
and now I receive a response like:
{
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MzQsImlhdCI6MTYwMjUzMzk0MSwiZXhwIjoxNjA1MTI1OTQxfQ.xM2tmP8PUcwABiW9lmxkjkmcmdmckMB8wlQ1YsBOQI",
"user": {
"id": 34,
"username": "aziz",
"email": "musa#binarymarvels.com",
"provider": "local",
"confirmed": true,
"blocked": false,
"role": {
"id": 2,
"name": "Public",
"description": "Default role given to the unauthenticated user.",
"type": "public"
},
"created_at": "2020-10-12T20:19:01.285Z",
"updated_at": "2020-10-12T20:19:01.299Z"
}
}
In Strapi Admin:
Roles & Permissions -> Advances settings
Set the field Default role for authenticated users to "Administrator"
One can write a custom endpoint to update user role, and add a corresponding controller action like below:
module.exports = {
updateUserRole: async ctx => {
return await strapi.services.auth.updateUserRole (ctx.request.body.user,
ctx.request.body.roleType);
}
};
auth service to update user role can be defined in api/auth/services/Auth.js as below:
module.exports = {
updateUserRole: async (userid, roleType) => {
const role = await strapi.query('role', 'users-permissions').findOne({ type:roleType }, []);
if ( role ) {
strapi.query('user', 'users-permissions').update({ id: userid }, { role: role.id });
return true;
}
return false;
}
};
You can do it like this
user: {
username: "elialber",
email: "falecom#elialber.com.br",
password: "123456789",
role: {
_id: "5afac95f0eabf75b64c6ef92" // role id that your app generate
}}
https://github.com/strapi/strapi/blob/master/packages/strapi-plugin-users-permissions/controllers/Auth.js#L261
Add following code to root/plugins/users-permissions/controllers/Auth.js in front of line 261
const roleType = params.role || settings.default_role
and change line 261
const role = hasAdmin === false ? root : await strapi.query('role', 'users-permissions').findOne({ type: roleType }, []);
post will like
{
"username": "test user",
"email": "qqqqqq#gmail.com",
"password": "qqqqqq",
"role": "boss"
}
boss <--- role created from admin panel
worked on strapi v-3.0.0-alpha.25.2

Resources