diff --git a/.graphqlconfig.yml b/.graphqlconfig.yml index 1d5af2ad..532bb43c 100644 --- a/.graphqlconfig.yml +++ b/.graphqlconfig.yml @@ -1,5 +1,5 @@ projects: - bookstorev2: + BookstoreBeta: schemaPath: src/graphql/schema.json includes: - src/graphql/**/*.js diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..a21bbe5d --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "program": "${workspaceFolder}/start" + } + ] +} \ No newline at end of file diff --git a/amplify/.config/project-config.json b/amplify/.config/project-config.json index c251f5f9..c4701a7f 100644 --- a/amplify/.config/project-config.json +++ b/amplify/.config/project-config.json @@ -1,5 +1,5 @@ { - "projectName": "bookstorev2", + "projectName": "BookstoreBeta", "version": "3.0", "frontend": "javascript", "javascript": { diff --git a/amplify/backend/api/bookstorev2/parameters.json b/amplify/backend/api/BookstoreBeta/parameters.json similarity index 72% rename from amplify/backend/api/bookstorev2/parameters.json rename to amplify/backend/api/BookstoreBeta/parameters.json index de6abf37..35f8136b 100644 --- a/amplify/backend/api/bookstorev2/parameters.json +++ b/amplify/backend/api/BookstoreBeta/parameters.json @@ -1,10 +1,10 @@ { - "AppSyncApiName": "bookstorev2", + "AppSyncApiName": "BookstoreBeta", "DynamoDBBillingMode": "PAY_PER_REQUEST", "DynamoDBEnableServerSideEncryption": "false", "AuthCognitoUserPoolId": { "Fn::GetAtt": [ - "authbookstorev26c74adc1", + "authBookstoreAuth", "Outputs.UserPoolId" ] } diff --git a/amplify/backend/api/bookstorev2/schema.graphql b/amplify/backend/api/BookstoreBeta/schema.graphql similarity index 79% rename from amplify/backend/api/bookstorev2/schema.graphql rename to amplify/backend/api/BookstoreBeta/schema.graphql index 2a3c6e8c..207e0e00 100644 --- a/amplify/backend/api/bookstorev2/schema.graphql +++ b/amplify/backend/api/BookstoreBeta/schema.graphql @@ -15,8 +15,8 @@ type Book id: ID! title: String! description: String - imageURL: String - author: String! + image: String + author: String featured: Boolean price: Float orders: [BookOrder] @connection(keyName:"byBook", fields:["id"]) @@ -24,8 +24,8 @@ type Book type BookOrder @model(queries: null, subscriptions: null) - @key(name: "byBook", fields: ["bookId", "orderId"]) - @key(name: "byOrder", fields: ["orderId", "bookId"]) + @key(name: "byBook", fields: ["book_id", "order_id"]) + @key(name: "byOrder", fields: ["order_id", "book_id"]) @auth( rules: [ # allow admins to create bookorders for customers by using customer email in lambda @@ -34,10 +34,10 @@ type BookOrder ] ){ id: ID! - bookId: ID! - orderId: ID! - book: Book @connection(fields: ["bookId"]) - order: Order @connection(fields: ["orderId"]) + book_id: ID! + order_id: ID! + book: Book @connection(fields: ["book_id"]) + order: Order @connection(fields: ["order_id"]) } type Order @@ -66,7 +66,7 @@ enum OrderStatus{ } input CartItem { - id: ID + id: ID! title: String image: String price: Float @@ -77,12 +77,12 @@ input ProcessOrderInput { id: ID! cart: [CartItem] total: Float! - tokenId: String! + token: String! address: String } type Mutation{ processOrder(input: ProcessOrderInput!): OrderStatus - @function(name: "process-stripe-payment-${env}") - @function(name: "create-order-${env}") + @function(name: "collectPaymentLambda-${env}") + @function(name: "createOrderLambda-${env}") } \ No newline at end of file diff --git a/amplify/backend/api/bookstorev2/stacks/CustomResources.json b/amplify/backend/api/BookstoreBeta/stacks/CustomResources.json similarity index 100% rename from amplify/backend/api/bookstorev2/stacks/CustomResources.json rename to amplify/backend/api/BookstoreBeta/stacks/CustomResources.json diff --git a/amplify/backend/api/bookstorev2/transform.conf.json b/amplify/backend/api/BookstoreBeta/transform.conf.json similarity index 100% rename from amplify/backend/api/bookstorev2/transform.conf.json rename to amplify/backend/api/BookstoreBeta/transform.conf.json diff --git a/amplify/backend/auth/bookstorev26c74adc1/bookstorev26c74adc1-cloudformation-template.yml b/amplify/backend/auth/BookstoreAuth/BookstoreAuth-cloudformation-template.yml similarity index 86% rename from amplify/backend/auth/bookstorev26c74adc1/bookstorev26c74adc1-cloudformation-template.yml rename to amplify/backend/auth/BookstoreAuth/BookstoreAuth-cloudformation-template.yml index d7eef6ba..bfbebd44 100644 --- a/amplify/backend/auth/bookstorev26c74adc1/bookstorev26c74adc1-cloudformation-template.yml +++ b/amplify/backend/auth/BookstoreAuth/BookstoreAuth-cloudformation-template.yml @@ -74,20 +74,35 @@ Parameters: userpoolClientSetAttributes: Type: String - sharedId: + useDefault: + Type: String + + authSelections: Type: String resourceName: Type: String + + userPoolGroups: + Type: String - authSelections: + adminQueries: Type: String - - useDefault: + + triggers: Type: String - + + hostedUI: + Type: String + userPoolGroupList: Type: CommaDelimitedList + + parentStack: + Type: String + + permissions: + Type: CommaDelimitedList dependsOn: Type: CommaDelimitedList @@ -103,7 +118,7 @@ Resources: # Created to allow the UserPool SMS Config to publish via the Simple Notification Service during MFA Process Type: AWS::IAM::Role Properties: - RoleName: !If [ShouldNotCreateEnvResources, 'bookst6c74adc1_sns-role', !Join ['',[ 'sns', '6c74adc1', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]] + RoleName: !If [ShouldNotCreateEnvResources, 'Bookste1218640_sns-role', !Join ['',[ 'sns', 'undefined', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]] AssumeRolePolicyDocument: Version: "2012-10-17" Statement: @@ -115,10 +130,10 @@ Resources: - "sts:AssumeRole" Condition: StringEquals: - sts:ExternalId: bookst6c74adc1_role_external_id + sts:ExternalId: Bookste1218640_role_external_id Policies: - - PolicyName: bookst6c74adc1-sns-policy + PolicyName: Bookste1218640-sns-policy PolicyDocument: Version: "2012-10-17" Statement: @@ -143,6 +158,11 @@ Resources: Required: true Mutable: true + - + Name: name + Required: true + Mutable: true + @@ -164,15 +184,30 @@ Resources: SmsVerificationMessage: !Ref smsVerificationMessage SmsConfiguration: SnsCallerArn: !GetAtt SNSRole.Arn - ExternalId: bookst6c74adc1_role_external_id + ExternalId: Bookste1218640_role_external_id + + + + + + + + + + + # Updating lambda role with permissions to Cognito + UserPoolClientWeb: # Created provide application access to user pool # Depends on UserPool for ID reference Type: "AWS::Cognito::UserPoolClient" Properties: - ClientName: bookst6c74adc1_app_clientWeb + ClientName: Bookste1218640_app_clientWeb + + ReadAttributes: !Ref userpoolClientReadAttributes + WriteAttributes: !Ref userpoolClientWriteAttributes RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity UserPoolId: !Ref UserPool @@ -182,7 +217,10 @@ Resources: # Depends on UserPool for ID reference Type: "AWS::Cognito::UserPoolClient" Properties: - ClientName: bookst6c74adc1_app_client + ClientName: Bookste1218640_app_client + + ReadAttributes: !Ref userpoolClientReadAttributes + WriteAttributes: !Ref userpoolClientWriteAttributes GenerateSecret: !Ref userpoolClientGenerateSecret RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity @@ -193,7 +231,7 @@ Resources: # Created to execute Lambda which gets userpool app client config values Type: 'AWS::IAM::Role' Properties: - RoleName: !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',['upClientLambdaRole', '6c74adc1', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]] + RoleName: !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',['upClientLambdaRole', 'undefined', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]] AssumeRolePolicyDocument: Version: '2012-10-17' Statement: @@ -247,7 +285,7 @@ Resources: # Marked as depending on UserPoolClientRole for easier to understand CFN sequencing Type: 'AWS::IAM::Policy' Properties: - PolicyName: bookst6c74adc1_userpoolclient_lambda_iam_policy + PolicyName: Bookste1218640_userpoolclient_lambda_iam_policy Roles: - !Ref UserPoolClientRole PolicyDocument: @@ -264,7 +302,7 @@ Resources: # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing Type: 'AWS::IAM::Policy' Properties: - PolicyName: bookst6c74adc1_userpoolclient_lambda_log_policy + PolicyName: Bookste1218640_userpoolclient_lambda_log_policy Roles: - !Ref UserPoolClientRole PolicyDocument: @@ -304,7 +342,7 @@ Resources: # Always created Type: AWS::Cognito::IdentityPool Properties: - IdentityPoolName: !If [ShouldNotCreateEnvResources, 'bookstorev26c74adc1_identitypool_6c74adc1', !Join ['',['bookstorev26c74adc1_identitypool_6c74adc1', '__', !Ref env]]] + IdentityPoolName: !If [ShouldNotCreateEnvResources, 'BookstoreAuth_identitypool_ba954e84', !Join ['',['BookstoreAuth_identitypool_ba954e84', '__', !Ref env]]] CognitoIdentityProviders: - ClientId: !Ref UserPoolClient diff --git a/amplify/backend/auth/bookstorev26c74adc1/parameters.json b/amplify/backend/auth/BookstoreAuth/parameters.json similarity index 62% rename from amplify/backend/auth/bookstorev26c74adc1/parameters.json rename to amplify/backend/auth/BookstoreAuth/parameters.json index 47093761..29630138 100644 --- a/amplify/backend/auth/bookstorev26c74adc1/parameters.json +++ b/amplify/backend/auth/BookstoreAuth/parameters.json @@ -1,8 +1,8 @@ { - "identityPoolName": "bookstorev26c74adc1_identitypool_6c74adc1", + "identityPoolName": "BookstoreAuth_identitypool_ba954e84", "allowUnauthenticatedIdentities": true, - "resourceNameTruncated": "bookst6c74adc1", - "userPoolName": "bookstorev26c74adc1_userpool_6c74adc1", + "resourceNameTruncated": "Bookste1218640", + "userPoolName": "BookstoreBetaAuth", "autoVerifiedAttributes": [ "email" ], @@ -18,21 +18,31 @@ "passwordPolicyMinLength": 8, "passwordPolicyCharacters": [], "requiredAttributes": [ - "email" + "email", + "name" ], "userpoolClientGenerateSecret": true, "userpoolClientRefreshTokenValidity": 30, "userpoolClientWriteAttributes": [ - "email" + "email", + "name" ], "userpoolClientReadAttributes": [ - "email" + "email", + "name" ], - "userpoolClientLambdaRole": "bookst6c74adc1_userpoolclient_lambda_role", - "userpoolClientSetAttributes": false, - "sharedId": "6c74adc1", - "resourceName": "bookstorev26c74adc1", + "userpoolClientLambdaRole": "Bookste1218640_userpoolclient_lambda_role", + "userpoolClientSetAttributes": true, + "useDefault": "manual", "authSelections": "identityPoolAndUserPool", + "resourceName": "BookstoreAuth", + "userPoolGroups": true, + "adminQueries": false, + "triggers": "{}", + "hostedUI": false, + "userPoolGroupList": [ + "Admin" + ], "authRoleArn": { "Fn::GetAtt": [ "AuthRole", @@ -45,7 +55,9 @@ "Arn" ] }, - "useDefault": "default", - "userPoolGroupList": [], + "parentStack": { + "Ref": "AWS::StackId" + }, + "permissions": [], "dependsOn": [] } \ No newline at end of file diff --git a/amplify/backend/auth/userPoolGroups/parameters.json b/amplify/backend/auth/userPoolGroups/parameters.json new file mode 100644 index 00000000..baa5c1d9 --- /dev/null +++ b/amplify/backend/auth/userPoolGroups/parameters.json @@ -0,0 +1,14 @@ +{ + "AuthRoleArn": { + "Fn::GetAtt": [ + "AuthRole", + "Arn" + ] + }, + "UnauthRoleArn": { + "Fn::GetAtt": [ + "UnauthRole", + "Arn" + ] + } +} \ No newline at end of file diff --git a/amplify/backend/auth/userPoolGroups/template.json b/amplify/backend/auth/userPoolGroups/template.json new file mode 100644 index 00000000..644fbccc --- /dev/null +++ b/amplify/backend/auth/userPoolGroups/template.json @@ -0,0 +1,311 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Parameters": { + "authBookstoreAuthUserPoolId": { + "Type": "String", + "Default": "authBookstoreAuthUserPoolId" + }, + + "authBookstoreAuthIdentityPoolId": { + "Type": "String", + "Default": "authBookstoreAuthIdentityPoolId" + }, + + "authBookstoreAuthAppClientID": { + "Type": "String", + "Default": "authBookstoreAuthAppClientID" + }, + "authBookstoreAuthAppClientIDWeb": { + "Type": "String", + "Default": "authBookstoreAuthAppClientIDWeb" + }, + "AuthRoleArn": { + "Type": "String" + }, + "UnauthRoleArn": { + "Type": "String" + }, + "env": { + "Type": "String" + } + }, + "Conditions": { + "ShouldNotCreateEnvResources": { + "Fn::Equals": [ + { + "Ref": "env" + }, + "NONE" + ] + } + }, + "Resources": { + + "AdminGroup": { + "Type" : "AWS::Cognito::UserPoolGroup", + "Properties" : { + "GroupName" : "Admin", + "Precedence" : 1, + + "RoleArn" : { + "Fn::GetAtt": [ + "AdminGroupRole", + "Arn" + ] + }, + + "UserPoolId" : { + "Ref": "authBookstoreAuthUserPoolId" + } + } + }, + + "AdminGroupRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "RoleName":{ + "Fn::Join": [ + "", + [ + { + "Ref": "authBookstoreAuthUserPoolId" + }, + "-AdminGroupRole" + ] + ] + }, + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "", + "Effect": "Allow", + "Principal": { + "Federated": "cognito-identity.amazonaws.com" + }, + "Action": "sts:AssumeRoleWithWebIdentity", + "Condition": { + "StringEquals": {"cognito-identity.amazonaws.com:aud": {"Ref":"authBookstoreAuthIdentityPoolId"}}, + "ForAnyValue:StringLike": {"cognito-identity.amazonaws.com:amr": "authenticated"} + } + } + ] + } + } + }, + + + + "LambdaExecutionRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "RoleName": { + "Fn::If": [ + "ShouldNotCreateEnvResources", + { + + }, + { + + "Fn::Join": [ + "", + [ + + "BookstoreAuth", + "-ExecutionRole-", + { + "Ref": "env" + } + ] + ] + } + ] + }, + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": [ + "lambda.amazonaws.com" + ] + }, + "Action": [ + "sts:AssumeRole" + ] + } + ] + }, + "Policies": [ + { + "PolicyName": "UserGroupLogPolicy", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Resource": "arn:aws:logs:*:*:*" + } + ] + } + }, + { + "PolicyName": "UserGroupExecutionPolicy", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "cognito-identity:SetIdentityPoolRoles", + "cognito-identity:ListIdentityPools", + "cognito-identity:describeIdentityPool" + + ], + "Resource": "*" + } + ] + } + }, + { + "PolicyName": "UserGroupPassRolePolicy", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "iam:PassRole" + ], + "Resource": "*" + } + ] + } + } + ] + } + }, + "RoleMapFunction": { + "Type": "AWS::Lambda::Function", + "DependsOn": ["LambdaExecutionRole"], + "Properties": { + "Code": { + "ZipFile": { + "Fn::Join": [ + "\n", + [ + "const response = require('cfn-response');", + "const AWS = require('aws-sdk');", + "exports.handler = (event, context) => {", + "if (event.RequestType == 'Delete') {", + " response.send(event, context, response.SUCCESS, {message: 'Request type delete'})", + "};", + "if (event.RequestType == 'Create' || event.RequestType == 'Update') {", + " let { identityPoolId, appClientID, appClientIDWeb, userPoolId, region } = event.ResourceProperties;", + " try {", + " const cognitoidentity = new AWS.CognitoIdentity();", + " let params = {", + " IdentityPoolId: identityPoolId,", + " Roles: {", + " 'authenticated': event.ResourceProperties.AuthRoleArn,", + " 'unauthenticated': event.ResourceProperties.UnauthRoleArn,", + " },", + " RoleMappings: {}", + " };", + " if (appClientIDWeb) {", + " params.RoleMappings[`cognito-idp.${region}.amazonaws.com/${userPoolId}:${appClientIDWeb}`] = {", + " Type: 'Token',", + " AmbiguousRoleResolution: 'AuthenticatedRole',", + " }", + " }", + " if (appClientID) {", + " params.RoleMappings[`cognito-idp.${region}.amazonaws.com/${userPoolId}:${appClientID}`] = {", + " Type: 'Token',", + " AmbiguousRoleResolution: 'AuthenticatedRole',", + " }", + " }", + " cognitoidentity.setIdentityPoolRoles(params).promise();", + " response.send(event, context, response.SUCCESS, {message: 'Successfully updated identity pool.'})", + " } catch(err) {", + + " response.send(event, context, response.FAILED, {message: 'Error updating identity pool'});", + " }", + " };", + "};" + + ] + ] + } + }, + "Handler": "index.handler", + "Runtime": "nodejs10.x", + "Timeout": "300", + "Role": { + "Fn::GetAtt": [ + "LambdaExecutionRole", + "Arn" + ] + } + } + }, + "RoleMapFunctionInput": { + "Type": "Custom::LambdaCallout", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "RoleMapFunction", + "Arn" + ] + }, + "AuthRoleArn": { + "Ref": "AuthRoleArn" + }, + "UnauthRoleArn": { + "Ref": "UnauthRoleArn" + }, + "identityPoolId": { + "Ref": "authBookstoreAuthIdentityPoolId" + }, + "userPoolId": { + "Ref": "authBookstoreAuthUserPoolId" + }, + "appClientIDWeb": { + "Ref": "authBookstoreAuthAppClientIDWeb" + }, + "appClientID": { + "Ref": "authBookstoreAuthAppClientID" + }, + "region": { + "Ref": "AWS::Region" + }, + "env": { + "Ref": "env" + } + }, + "DependsOn": ["RoleMapFunction"] + } + + }, + + "Outputs": { + + "AdminGroupRole": { + "Value": { + "Fn::GetAtt": [ + "AdminGroupRole", + "Arn" + ] + } + + } + + + } + +} diff --git a/amplify/backend/auth/userPoolGroups/user-pool-group-precedence.json b/amplify/backend/auth/userPoolGroups/user-pool-group-precedence.json new file mode 100644 index 00000000..21e9c986 --- /dev/null +++ b/amplify/backend/auth/userPoolGroups/user-pool-group-precedence.json @@ -0,0 +1,6 @@ +[ + { + "groupName": "Admin", + "precedence": 1 + } +] \ No newline at end of file diff --git a/amplify/backend/backend-config.json b/amplify/backend/backend-config.json index 313eeae2..97a2dd70 100644 --- a/amplify/backend/backend-config.json +++ b/amplify/backend/backend-config.json @@ -1,20 +1,35 @@ { "auth": { - "bookstorev26c74adc1": { + "userPoolGroups": { + "service": "Cognito-UserPool-Groups", + "providerPlugin": "awscloudformation", + "dependsOn": [ + { + "category": "auth", + "resourceName": "BookstoreAuth", + "attributes": [ + "UserPoolId", + "AppClientIDWeb", + "AppClientID", + "IdentityPoolId" + ] + } + ] + }, + "BookstoreAuth": { "service": "Cognito", "providerPlugin": "awscloudformation", - "dependsOn": [], - "customAuth": false + "dependsOn": [] } }, "storage": { - "s34587bb48": { + "BookstoreBetaImages": { "service": "S3", "providerPlugin": "awscloudformation" } }, "api": { - "bookstorev2": { + "BookstoreBeta": { "service": "AppSync", "providerPlugin": "awscloudformation", "output": { @@ -23,15 +38,15 @@ { "authenticationType": "API_KEY", "apiKeyConfig": { - "description": "public access to books", - "apiKeyExpirationDays": 7 + "description": "anyone can see the books before logging in", + "apiKeyExpirationDays": "365" } } ], "defaultAuthentication": { "authenticationType": "AMAZON_COGNITO_USER_POOLS", "userPoolConfig": { - "userPoolId": "authbookstorev26c74adc1" + "userPoolId": "authBookstoreAuth" } } } @@ -39,12 +54,12 @@ } }, "function": { - "bookstorev2929dc805": { + "CollectPayment": { "build": true, "providerPlugin": "awscloudformation", "service": "Lambda" }, - "bookstorev269302e96": { + "CreateOrder": { "build": true, "providerPlugin": "awscloudformation", "service": "Lambda" diff --git a/amplify/backend/function/bookstorev2929dc805/bookstorev2929dc805-cloudformation-template.json b/amplify/backend/function/CollectPayment/CollectPayment-cloudformation-template.json similarity index 91% rename from amplify/backend/function/bookstorev2929dc805/bookstorev2929dc805-cloudformation-template.json rename to amplify/backend/function/CollectPayment/CollectPayment-cloudformation-template.json index db4af71f..fa8463c1 100644 --- a/amplify/backend/function/bookstorev2929dc805/bookstorev2929dc805-cloudformation-template.json +++ b/amplify/backend/function/CollectPayment/CollectPayment-cloudformation-template.json @@ -33,12 +33,12 @@ "FunctionName": { "Fn::If": [ "ShouldNotCreateEnvResources", - "process-stripe-payment", + "collectPaymentLambda", { "Fn::Join": [ "", [ - "process-stripe-payment", + "collectPaymentLambda", "-", { "Ref": "env" @@ -67,8 +67,8 @@ "Runtime": "nodejs12.x", "Timeout": "25", "Code": { - "S3Bucket": "amplify-bookstorev2-dev-154551-deployment", - "S3Key": "amplify-builds/bookstorev2929dc805-6a7a5076576452737370-build.zip" + "S3Bucket": "amplify-bookstorebeta-dev-164506-deployment", + "S3Key": "amplify-builds/CollectPayment-6c49795457384a524144-build.zip" } } }, @@ -78,12 +78,12 @@ "RoleName": { "Fn::If": [ "ShouldNotCreateEnvResources", - "bookstorev2LambdaRole48ede694", + "bookstorebetaLambdaRole1cc00497", { "Fn::Join": [ "", [ - "bookstorev2LambdaRole48ede694", + "bookstorebetaLambdaRole1cc00497", "-", { "Ref": "env" diff --git a/amplify/backend/function/bookstorev269302e96/amplify.state b/amplify/backend/function/CollectPayment/amplify.state similarity index 100% rename from amplify/backend/function/bookstorev269302e96/amplify.state rename to amplify/backend/function/CollectPayment/amplify.state diff --git a/amplify/backend/function/bookstorev269302e96/function-parameters.json b/amplify/backend/function/CollectPayment/function-parameters.json similarity index 100% rename from amplify/backend/function/bookstorev269302e96/function-parameters.json rename to amplify/backend/function/CollectPayment/function-parameters.json diff --git a/amplify/backend/function/bookstorev269302e96/parameters.json b/amplify/backend/function/CollectPayment/parameters.json similarity index 100% rename from amplify/backend/function/bookstorev269302e96/parameters.json rename to amplify/backend/function/CollectPayment/parameters.json diff --git a/amplify/backend/function/bookstorev269302e96/src/event.json b/amplify/backend/function/CollectPayment/src/event.json similarity index 100% rename from amplify/backend/function/bookstorev269302e96/src/event.json rename to amplify/backend/function/CollectPayment/src/event.json diff --git a/amplify/backend/function/bookstorev2929dc805/src/index.js b/amplify/backend/function/CollectPayment/src/index.js similarity index 53% rename from amplify/backend/function/bookstorev2929dc805/src/index.js rename to amplify/backend/function/CollectPayment/src/index.js index c99a4dc4..c37d06b4 100644 --- a/amplify/backend/function/bookstorev2929dc805/src/index.js +++ b/amplify/backend/function/CollectPayment/src/index.js @@ -1,20 +1,18 @@ - -// Use SSM when you implement const stripe = require('stripe')('sk_test_51GyWX6KxUqRqwqPQ7XRtDWcdWhoRP0uEbuHD9C5RGocCQFb9PwolGCTNgWnQCww2qtz5OVfIPGJpg0mibHtvYW1z00VgZLH97s'); exports.handler = async (event) => { try { - const { username } = event.identity.claims; - const { id, cart, total, address, tokenId } = event.arguments.input; + const { email } = event.identity.claims; + const { id, cart, total, address, token } = event.arguments.input; await stripe.charges.create({ amount: total * 100, currency: "usd", - source: tokenId, - description: `Order ${new Date()} by ${username}` + source: token, + description: `Order ${new Date()} by ${email}` }) - return { id, cart, total, address, username }; + return { id, cart, total, address, email }; } catch (err) { throw new Error(err); } -}; +}; \ No newline at end of file diff --git a/amplify/backend/function/bookstorev2929dc805/src/package-lock.json b/amplify/backend/function/CollectPayment/src/package-lock.json similarity index 62% rename from amplify/backend/function/bookstorev2929dc805/src/package-lock.json rename to amplify/backend/function/CollectPayment/src/package-lock.json index 35a55946..17e0307a 100644 --- a/amplify/backend/function/bookstorev2929dc805/src/package-lock.json +++ b/amplify/backend/function/CollectPayment/src/package-lock.json @@ -1,13 +1,13 @@ { - "name": "process-stripe-payment", + "name": "collectPaymentLambda", "version": "2.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { "@types/node": { - "version": "14.0.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.14.tgz", - "integrity": "sha512-syUgf67ZQpaJj01/tRTknkMNoBBLWJOBODF0Zm4NrXmiSuxjymFrxnTu1QVYRubhVkRcZLYZG8STTwJRdVm/WQ==" + "version": "14.0.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.18.tgz", + "integrity": "sha512-0Z3nS5acM0cIV4JPzrj9g/GH0Et5vmADWtip3YOXOp1NpOLU8V3KoZDc8ny9c1pe/YSYYzQkAWob6dyV/EWg4g==" }, "qs": { "version": "6.9.4", @@ -15,9 +15,9 @@ "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==" }, "stripe": { - "version": "8.68.0", - "resolved": "https://registry.npmjs.org/stripe/-/stripe-8.68.0.tgz", - "integrity": "sha512-NjVf4dA5ACCbE3susJH7KpT+4EbE1nBSwTjMhi9rT+xhrm9xEtx21lufoYWLkezuPN4O3LIPv4eXJQGaa6SrdQ==", + "version": "8.69.0", + "resolved": "https://registry.npmjs.org/stripe/-/stripe-8.69.0.tgz", + "integrity": "sha512-RD/oW1cwMBHOYFN5gs8ehbEkMFg8tJPByQzVyibJxng5t6PxsEWtV+p5QM28aoT/XKSA7+EwCcDNmH1uPw4OMg==", "requires": { "@types/node": ">=8.1.0", "qs": "^6.6.0" diff --git a/amplify/backend/function/bookstorev2929dc805/src/package.json b/amplify/backend/function/CollectPayment/src/package.json similarity index 72% rename from amplify/backend/function/bookstorev2929dc805/src/package.json rename to amplify/backend/function/CollectPayment/src/package.json index 6faaf1f5..34525d4e 100644 --- a/amplify/backend/function/bookstorev2929dc805/src/package.json +++ b/amplify/backend/function/CollectPayment/src/package.json @@ -1,10 +1,10 @@ { - "name": "process-stripe-payment", + "name": "collectPaymentLambda", "version": "2.0.0", "description": "Lambda function generated by Amplify", "main": "index.js", "license": "Apache-2.0", "dependencies": { - "stripe": "^8.68.0" + "stripe": "^8.69.0" } } diff --git a/amplify/backend/function/bookstorev269302e96/bookstorev269302e96-cloudformation-template.json b/amplify/backend/function/CreateOrder/CreateOrder-cloudformation-template.json similarity index 91% rename from amplify/backend/function/bookstorev269302e96/bookstorev269302e96-cloudformation-template.json rename to amplify/backend/function/CreateOrder/CreateOrder-cloudformation-template.json index 3fea663d..21c4f88e 100644 --- a/amplify/backend/function/bookstorev269302e96/bookstorev269302e96-cloudformation-template.json +++ b/amplify/backend/function/CreateOrder/CreateOrder-cloudformation-template.json @@ -33,12 +33,12 @@ "FunctionName": { "Fn::If": [ "ShouldNotCreateEnvResources", - "create-order", + "createOrderLambda", { "Fn::Join": [ "", [ - "create-order", + "createOrderLambda", "-", { "Ref": "env" @@ -67,8 +67,8 @@ "Runtime": "nodejs12.x", "Timeout": "25", "Code": { - "S3Bucket": "amplify-bookstorev2-dev-154551-deployment", - "S3Key": "amplify-builds/bookstorev269302e96-5575367175684f477673-build.zip" + "S3Bucket": "amplify-bookstorebeta-dev-164506-deployment", + "S3Key": "amplify-builds/CreateOrder-53675546503930684141-build.zip" } } }, @@ -78,12 +78,12 @@ "RoleName": { "Fn::If": [ "ShouldNotCreateEnvResources", - "bookstorev2LambdaRole59551f5a", + "bookstorebetaLambdaRole17a69330", { "Fn::Join": [ "", [ - "bookstorev2LambdaRole59551f5a", + "bookstorebetaLambdaRole17a69330", "-", { "Ref": "env" diff --git a/amplify/backend/function/bookstorev2929dc805/amplify.state b/amplify/backend/function/CreateOrder/amplify.state similarity index 100% rename from amplify/backend/function/bookstorev2929dc805/amplify.state rename to amplify/backend/function/CreateOrder/amplify.state diff --git a/amplify/backend/function/bookstorev2929dc805/function-parameters.json b/amplify/backend/function/CreateOrder/function-parameters.json similarity index 100% rename from amplify/backend/function/bookstorev2929dc805/function-parameters.json rename to amplify/backend/function/CreateOrder/function-parameters.json diff --git a/amplify/backend/function/bookstorev2929dc805/parameters.json b/amplify/backend/function/CreateOrder/parameters.json similarity index 100% rename from amplify/backend/function/bookstorev2929dc805/parameters.json rename to amplify/backend/function/CreateOrder/parameters.json diff --git a/amplify/backend/function/bookstorev2929dc805/src/event.json b/amplify/backend/function/CreateOrder/src/event.json similarity index 100% rename from amplify/backend/function/bookstorev2929dc805/src/event.json rename to amplify/backend/function/CreateOrder/src/event.json diff --git a/amplify/backend/function/bookstorev269302e96/src/index.js b/amplify/backend/function/CreateOrder/src/index.js similarity index 98% rename from amplify/backend/function/bookstorev269302e96/src/index.js rename to amplify/backend/function/CreateOrder/src/index.js index 3c1f150f..940ec616 100644 --- a/amplify/backend/function/bookstorev269302e96/src/index.js +++ b/amplify/backend/function/CreateOrder/src/index.js @@ -1,5 +1,3 @@ - - exports.handler = async (event) => { // Get the stashed body from first function // Create the order @@ -10,4 +8,4 @@ exports.handler = async (event) => { console.log(test); return "SUCCESS" -}; +}; \ No newline at end of file diff --git a/amplify/backend/function/bookstorev269302e96/src/package-lock.json b/amplify/backend/function/CreateOrder/src/package-lock.json similarity index 61% rename from amplify/backend/function/bookstorev269302e96/src/package-lock.json rename to amplify/backend/function/CreateOrder/src/package-lock.json index da82fc25..a1afca92 100644 --- a/amplify/backend/function/bookstorev269302e96/src/package-lock.json +++ b/amplify/backend/function/CreateOrder/src/package-lock.json @@ -1,5 +1,5 @@ { - "name": "create-order", + "name": "createOrderLambda", "version": "2.0.0", "lockfileVersion": 1 } diff --git a/amplify/backend/function/bookstorev269302e96/src/package.json b/amplify/backend/function/CreateOrder/src/package.json similarity index 80% rename from amplify/backend/function/bookstorev269302e96/src/package.json rename to amplify/backend/function/CreateOrder/src/package.json index 4b3953eb..966a99c9 100644 --- a/amplify/backend/function/bookstorev269302e96/src/package.json +++ b/amplify/backend/function/CreateOrder/src/package.json @@ -1,5 +1,5 @@ { - "name": "create-order", + "name": "createOrderLambda", "version": "2.0.0", "description": "Lambda function generated by Amplify", "main": "index.js", diff --git a/amplify/backend/storage/s34587bb48/parameters.json b/amplify/backend/storage/BookstoreBetaImages/parameters.json similarity index 68% rename from amplify/backend/storage/s34587bb48/parameters.json rename to amplify/backend/storage/BookstoreBetaImages/parameters.json index fbebf04b..64f4ddfe 100644 --- a/amplify/backend/storage/s34587bb48/parameters.json +++ b/amplify/backend/storage/BookstoreBetaImages/parameters.json @@ -1,7 +1,7 @@ { - "bucketName": "bookstorev22a1ec7d43239443cb859d386a6e826ee", - "authPolicyName": "s3_amplify_4587bb48", - "unauthPolicyName": "s3_amplify_4587bb48", + "bucketName": "bookstorebetaf3d8ad08b9594f14befd2b6017cfe176", + "authPolicyName": "s3_amplify_cb77cfd8", + "unauthPolicyName": "s3_amplify_cb77cfd8", "authRoleName": { "Ref": "AuthRoleName" }, @@ -19,15 +19,15 @@ "s3:DeleteObject" ], "s3PermissionsAuthenticatedPublic": "s3:PutObject,s3:GetObject,s3:DeleteObject", - "s3PublicPolicy": "Public_policy_8d37eb31", + "s3PublicPolicy": "Public_policy_fa391ab3", "s3PermissionsAuthenticatedUploads": "s3:PutObject", - "s3UploadsPolicy": "Uploads_policy_8d37eb31", + "s3UploadsPolicy": "Uploads_policy_fa391ab3", "s3PermissionsAuthenticatedProtected": "s3:PutObject,s3:GetObject,s3:DeleteObject", - "s3ProtectedPolicy": "Protected_policy_a2b1f1d6", + "s3ProtectedPolicy": "Protected_policy_0873a09f", "s3PermissionsAuthenticatedPrivate": "s3:PutObject,s3:GetObject,s3:DeleteObject", - "s3PrivatePolicy": "Private_policy_a2b1f1d6", + "s3PrivatePolicy": "Private_policy_0873a09f", "AuthenticatedAllowList": "ALLOW", - "s3ReadPolicy": "read_policy_8d37eb31", + "s3ReadPolicy": "read_policy_fa391ab3", "s3PermissionsGuestPublic": "s3:GetObject", "s3PermissionsGuestUploads": "DISALLOW", "GuestAllowList": "ALLOW", diff --git a/amplify/backend/storage/s34587bb48/s3-cloudformation-template.json b/amplify/backend/storage/BookstoreBetaImages/s3-cloudformation-template.json similarity index 100% rename from amplify/backend/storage/s34587bb48/s3-cloudformation-template.json rename to amplify/backend/storage/BookstoreBetaImages/s3-cloudformation-template.json diff --git a/amplify/backend/storage/s34587bb48/storage-params.json b/amplify/backend/storage/BookstoreBetaImages/storage-params.json similarity index 100% rename from amplify/backend/storage/s34587bb48/storage-params.json rename to amplify/backend/storage/BookstoreBetaImages/storage-params.json diff --git a/amplify/team-provider-info.json b/amplify/team-provider-info.json index d0c1356a..0f25f0ff 100644 --- a/amplify/team-provider-info.json +++ b/amplify/team-provider-info.json @@ -1,19 +1,19 @@ { "dev": { "awscloudformation": { - "AuthRoleName": "amplify-bookstorev2-dev-154551-authRole", - "UnauthRoleArn": "arn:aws:iam::885121665536:role/amplify-bookstorev2-dev-154551-unauthRole", - "AuthRoleArn": "arn:aws:iam::885121665536:role/amplify-bookstorev2-dev-154551-authRole", + "AuthRoleName": "amplify-bookstorebeta-dev-164506-authRole", + "UnauthRoleArn": "arn:aws:iam::885121665536:role/amplify-bookstorebeta-dev-164506-unauthRole", + "AuthRoleArn": "arn:aws:iam::885121665536:role/amplify-bookstorebeta-dev-164506-authRole", "Region": "us-east-1", - "DeploymentBucketName": "amplify-bookstorev2-dev-154551-deployment", - "UnauthRoleName": "amplify-bookstorev2-dev-154551-unauthRole", - "StackName": "amplify-bookstorev2-dev-154551", - "StackId": "arn:aws:cloudformation:us-east-1:885121665536:stack/amplify-bookstorev2-dev-154551/88482db0-b9f1-11ea-8de6-0ed2247e0ea9", - "AmplifyAppId": "d1qmkpm0i2g6fh" + "DeploymentBucketName": "amplify-bookstorebeta-dev-164506-deployment", + "UnauthRoleName": "amplify-bookstorebeta-dev-164506-unauthRole", + "StackName": "amplify-bookstorebeta-dev-164506", + "StackId": "arn:aws:cloudformation:us-east-1:885121665536:stack/amplify-bookstorebeta-dev-164506/21ae14e0-c043-11ea-a1f5-0a99e59b1983", + "AmplifyAppId": "d3cg91ics947ee" }, "categories": { "auth": { - "bookstorev26c74adc1": {} + "BookstoreAuth": {} } } } diff --git a/code-snippets/BookOrders.gql b/code-snippets/BookOrders.gql new file mode 100644 index 00000000..5a79c606 --- /dev/null +++ b/code-snippets/BookOrders.gql @@ -0,0 +1,65 @@ +# A user will their own bookorder lists +# query{ +# listOrders{ +# items{ +# total +# books{ +# items{ +# book{ +# title +# image +# price +# author +# } +# } +# } +# } +# } +# } + +# But admin can get all the orders of all the users and add filters too. +# query{ +# listOrders(filter: { +# user: { +# eq: "Manoj Fernando" +# } +# }){ +# items{ +# total +# books{ +# items{ +# book{ +# title +# image +# price +# author +# } +# } +# } +# } +# } +# } + + +# mutation{ +# createBookOrder(input: { +# id: "bo123" +# book_id: "673309be-1769-493f-9d15-4f75e010bde1" +# order_id: "1001" +# }){ +# order_id +# book_id +# } +# } + +# mutation{ +# createOrder(input: { +# id: "1001" +# user: "Manoj Fernando" +# total: 95.90 +# }){ +# id +# user +# total +# } +# } \ No newline at end of file diff --git a/code-snippets/CreateOrderLambda.js b/code-snippets/CreateOrderLambda.js new file mode 100644 index 00000000..da6c9fe3 --- /dev/null +++ b/code-snippets/CreateOrderLambda.js @@ -0,0 +1,59 @@ + +// 1. Create order with following inputs +// id, __typename = "Order", createdAt, customer="customer email", total="Order total", updatedAt, user="User name or full name for searching" +var params = { + TableName : 'BookOrder-we6cwg6juveevi6sihqok72ayi-dev', + Item: { + id: '', + __typename: "Order", + customer: "", + total: 40.33, + updatedAt: + } + }; + + var documentClient = new AWS.DynamoDB.DocumentClient(); + + documentClient.put(params, function(err, data) { + if (err) console.log(err); + else console.log(data); + }); + + +// 2. Create bookOrder - The link between order and books. This could be a buld update +// id, __typename="BookOrder", book_id, order_id, customer="customer email", createdAt, updatedAt + +const getBookOrderItems = () => { + let bookOrders = []; + + // add them in a loop + const order1 = { + PutRequest: { + Item: { + id: 'unique ID', //hash key + __typename: 'BookOrder', + book_id: "", + order_id: "", + customer: "", + createdAt: new Date(), + updatedAt: new Date() + } + } + } + + bookOrders.push(order1); + return bookOrders; +} + +var params = { + RequestItems: { + 'BookOrder-we6cwg6juveevi6sihqok72ayi-dev': getBookOrderItems() + } + }; + + var documentClient = new AWS.DynamoDB.DocumentClient(); + + documentClient.batchWrite(params, function(err, data) { + if (err) console.log(err); + else console.log(data); + }); \ No newline at end of file diff --git a/code-snippets/MakePaymentLambda.js b/code-snippets/MakePaymentLambda.js new file mode 100644 index 00000000..50b56c29 --- /dev/null +++ b/code-snippets/MakePaymentLambda.js @@ -0,0 +1,35 @@ +const { CognitoIdentityServiceProvider } = require('aws-sdk'); +const cognitoIdentityServiceProvider = new CognitoIdentityServiceProvider(); +const stripe = require('stripe')('sk_test_51GyWX6KxUqRqwqPQ7XRtDWcdWhoRP0uEbuHD9C5RGocCQFb9PwolGCTNgWnQCww2qtz5OVfIPGJpg0mibHtvYW1z00VgZLH97s'); + +const getUserEmail = async(event) => { + const params = { + UserPoolId: "us-east-1_xZjPvMKSW", + Username: event.identity.claims.username, + }; + const user = await cognitoIdentityServiceProvider.adminGetUser(params).promise(); + const { Value: email } = user.UserAttributes.find(attr => { + if (attr.Name === 'email') { + return attr.Value; + } + }); + return email; +} + +exports.handler = async(event) => { + try { + const { id, cart, total, address, token } = event.arguments.input; + const email = await getUserEmail(event); + + await stripe.charges.create({ + amount: total * 100, + currency: "usd", + source: token, + description: `Order ${new Date()} by ${email}` + }) + return { id, cart, total, address, email }; + } + catch (err) { + throw new Error(err); + } +}; diff --git a/package-lock.json b/package-lock.json index e7b6a5f4..63caaa32 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16280,6 +16280,22 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==" }, + "stripe": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/stripe/-/stripe-8.68.0.tgz", + "integrity": "sha512-NjVf4dA5ACCbE3susJH7KpT+4EbE1nBSwTjMhi9rT+xhrm9xEtx21lufoYWLkezuPN4O3LIPv4eXJQGaa6SrdQ==", + "requires": { + "@types/node": ">=8.1.0", + "qs": "^6.6.0" + }, + "dependencies": { + "qs": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", + "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==" + } + } + }, "style-loader": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", diff --git a/package.json b/package.json index 82a56e92..a10a296c 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "react-router-dom": "^5.1.2", "react-scripts": "3.4.1", "react-stripe-elements": "^6.0.1", + "stripe": "^8.68.0", "uuid": "^8.2.0" }, "scripts": { diff --git a/src/api/mutations.js b/src/api/mutations.js index 2160e02f..4d0d3a75 100644 --- a/src/api/mutations.js +++ b/src/api/mutations.js @@ -13,15 +13,15 @@ export const createBook = /* GraphQL */ ` id title description - imageURL + image author featured price orders { items { id - bookId - orderId + book_id + order_id createdAt updatedAt } @@ -41,15 +41,15 @@ export const updateBook = /* GraphQL */ ` id title description - imageURL + image author featured price orders { items { id - bookId - orderId + book_id + order_id createdAt updatedAt } @@ -69,15 +69,15 @@ export const deleteBook = /* GraphQL */ ` id title description - imageURL + image author featured price orders { items { id - bookId - orderId + book_id + order_id createdAt updatedAt } @@ -95,8 +95,8 @@ export const createBookOrder = /* GraphQL */ ` ) { createBookOrder(input: $input, condition: $condition) { id - bookId - orderId + book_id + order_id order { id user @@ -114,7 +114,7 @@ export const createBookOrder = /* GraphQL */ ` id title description - imageURL + image author featured price @@ -134,8 +134,8 @@ export const updateBookOrder = /* GraphQL */ ` ) { updateBookOrder(input: $input, condition: $condition) { id - bookId - orderId + book_id + order_id order { id user @@ -153,7 +153,7 @@ export const updateBookOrder = /* GraphQL */ ` id title description - imageURL + image author featured price @@ -173,8 +173,8 @@ export const deleteBookOrder = /* GraphQL */ ` ) { deleteBookOrder(input: $input, condition: $condition) { id - bookId - orderId + book_id + order_id order { id user @@ -192,7 +192,7 @@ export const deleteBookOrder = /* GraphQL */ ` id title description - imageURL + image author featured price @@ -218,8 +218,8 @@ export const createOrder = /* GraphQL */ ` books { items { id - bookId - orderId + book_id + order_id createdAt updatedAt } @@ -243,8 +243,8 @@ export const updateOrder = /* GraphQL */ ` books { items { id - bookId - orderId + book_id + order_id createdAt updatedAt } @@ -268,8 +268,8 @@ export const deleteOrder = /* GraphQL */ ` books { items { id - bookId - orderId + book_id + order_id createdAt updatedAt } diff --git a/src/api/queries.js b/src/api/queries.js index 351420a2..6f7c6a86 100644 --- a/src/api/queries.js +++ b/src/api/queries.js @@ -11,8 +11,8 @@ export const getOrder = /* GraphQL */ ` books { items { id - bookId - orderId + book_id + order_id createdAt updatedAt } @@ -56,7 +56,7 @@ export const listBooks = /* GraphQL */ ` id title description - imageURL + image author featured price @@ -73,15 +73,15 @@ export const getBook = /* GraphQL */ ` id title description - imageURL + image author featured price orders { items { id - bookId - orderId + book_id + order_id createdAt updatedAt } diff --git a/src/api/subscriptions.js b/src/api/subscriptions.js index 9245631b..541cdbce 100644 --- a/src/api/subscriptions.js +++ b/src/api/subscriptions.js @@ -7,7 +7,7 @@ export const onCreateBook = /* GraphQL */ ` id title description - imageURL + image author featured price @@ -22,7 +22,7 @@ export const onUpdateBook = /* GraphQL */ ` id title description - imageURL + image author featured price @@ -37,7 +37,7 @@ export const onDeleteBook = /* GraphQL */ ` id title description - imageURL + image author featured price diff --git a/src/components/CheckoutForm.js b/src/components/CheckoutForm.js index cd136c54..03f29452 100644 --- a/src/components/CheckoutForm.js +++ b/src/components/CheckoutForm.js @@ -28,13 +28,13 @@ const CARD_ELEMENT_OPTIONS = { const CheckoutForm = () => { const { cart, total } = useContext(CartContext); const { checkout } = useContext(BookContext); - const [orderDetails, setOrderDetails] = useState({ cart, total, address: null, tokenId: null }); + const [orderDetails, setOrderDetails] = useState({ cart, total, address: null, token: null }); const [error, setError] = useState(null); const stripe = useStripe(); const elements = useElements(); useEffect(() => { - if (orderDetails.tokenId) { + if (orderDetails.token) { checkout(orderDetails); } }, [orderDetails]) @@ -59,9 +59,8 @@ const CheckoutForm = () => { } else { setError(null); // Send the token to your server. - debugger const token = result.token; - setOrderDetails({ ...orderDetails, tokenId: token.id }); + setOrderDetails({ ...orderDetails, token: token.id }); } }; diff --git a/src/context/cart.js b/src/context/cart.js index 7b50ca94..c7814ea2 100644 --- a/src/context/cart.js +++ b/src/context/cart.js @@ -35,7 +35,7 @@ const CartProvider = ({ children }) => { } const addToCart = (book) => { - const { id, title, price, imageURL: image } = book; + const { id, title, price, image } = book; const cartItem = [...cart].find(item => item.id === id); if (cartItem) { increaseAmount(id); diff --git a/src/graphql/mutations.js b/src/graphql/mutations.js index d5ba33cf..d0f401b8 100644 --- a/src/graphql/mutations.js +++ b/src/graphql/mutations.js @@ -15,15 +15,15 @@ export const createBook = /* GraphQL */ ` id title description - imageURL + image author featured price orders { items { id - bookId - orderId + book_id + order_id createdAt updatedAt } @@ -43,15 +43,15 @@ export const updateBook = /* GraphQL */ ` id title description - imageURL + image author featured price orders { items { id - bookId - orderId + book_id + order_id createdAt updatedAt } @@ -71,15 +71,15 @@ export const deleteBook = /* GraphQL */ ` id title description - imageURL + image author featured price orders { items { id - bookId - orderId + book_id + order_id createdAt updatedAt } @@ -97,8 +97,8 @@ export const createBookOrder = /* GraphQL */ ` ) { createBookOrder(input: $input, condition: $condition) { id - bookId - orderId + book_id + order_id order { id user @@ -116,7 +116,7 @@ export const createBookOrder = /* GraphQL */ ` id title description - imageURL + image author featured price @@ -136,8 +136,8 @@ export const updateBookOrder = /* GraphQL */ ` ) { updateBookOrder(input: $input, condition: $condition) { id - bookId - orderId + book_id + order_id order { id user @@ -155,7 +155,7 @@ export const updateBookOrder = /* GraphQL */ ` id title description - imageURL + image author featured price @@ -175,8 +175,8 @@ export const deleteBookOrder = /* GraphQL */ ` ) { deleteBookOrder(input: $input, condition: $condition) { id - bookId - orderId + book_id + order_id order { id user @@ -194,7 +194,7 @@ export const deleteBookOrder = /* GraphQL */ ` id title description - imageURL + image author featured price @@ -220,8 +220,8 @@ export const createOrder = /* GraphQL */ ` books { items { id - bookId - orderId + book_id + order_id createdAt updatedAt } @@ -245,8 +245,8 @@ export const updateOrder = /* GraphQL */ ` books { items { id - bookId - orderId + book_id + order_id createdAt updatedAt } @@ -270,8 +270,8 @@ export const deleteOrder = /* GraphQL */ ` books { items { id - bookId - orderId + book_id + order_id createdAt updatedAt } diff --git a/src/graphql/queries.js b/src/graphql/queries.js index 72dcae78..decdcbfd 100644 --- a/src/graphql/queries.js +++ b/src/graphql/queries.js @@ -11,8 +11,8 @@ export const getOrder = /* GraphQL */ ` books { items { id - bookId - orderId + book_id + order_id createdAt updatedAt } @@ -56,7 +56,7 @@ export const listBooks = /* GraphQL */ ` id title description - imageURL + image author featured price @@ -76,15 +76,15 @@ export const getBook = /* GraphQL */ ` id title description - imageURL + image author featured price orders { items { id - bookId - orderId + book_id + order_id createdAt updatedAt } diff --git a/src/graphql/schema.json b/src/graphql/schema.json index b0d16084..747869c5 100644 --- a/src/graphql/schema.json +++ b/src/graphql/schema.json @@ -201,7 +201,7 @@ "name" : "books", "description" : null, "args" : [ { - "name" : "bookId", + "name" : "book_id", "description" : null, "type" : { "kind" : "INPUT_OBJECT", @@ -370,7 +370,7 @@ "isDeprecated" : false, "deprecationReason" : null }, { - "name" : "bookId", + "name" : "book_id", "description" : null, "args" : [ ], "type" : { @@ -385,7 +385,7 @@ "isDeprecated" : false, "deprecationReason" : null }, { - "name" : "orderId", + "name" : "order_id", "description" : null, "args" : [ ], "type" : { @@ -511,7 +511,7 @@ "isDeprecated" : false, "deprecationReason" : null }, { - "name" : "imageURL", + "name" : "image", "description" : null, "args" : [ ], "type" : { @@ -526,13 +526,9 @@ "description" : null, "args" : [ ], "type" : { - "kind" : "NON_NULL", - "name" : null, - "ofType" : { - "kind" : "SCALAR", - "name" : "String", - "ofType" : null - } + "kind" : "SCALAR", + "name" : "String", + "ofType" : null }, "isDeprecated" : false, "deprecationReason" : null @@ -562,7 +558,7 @@ "name" : "orders", "description" : null, "args" : [ { - "name" : "orderId", + "name" : "order_id", "description" : null, "type" : { "kind" : "INPUT_OBJECT", @@ -749,7 +745,7 @@ }, "defaultValue" : null }, { - "name" : "bookId", + "name" : "book_id", "description" : null, "type" : { "kind" : "INPUT_OBJECT", @@ -758,7 +754,7 @@ }, "defaultValue" : null }, { - "name" : "orderId", + "name" : "order_id", "description" : null, "type" : { "kind" : "INPUT_OBJECT", @@ -1505,7 +1501,7 @@ }, "defaultValue" : null }, { - "name" : "imageURL", + "name" : "image", "description" : null, "type" : { "kind" : "INPUT_OBJECT", @@ -2018,7 +2014,7 @@ }, "defaultValue" : null }, { - "name" : "tokenId", + "name" : "token", "description" : null, "type" : { "kind" : "NON_NULL", @@ -2052,9 +2048,13 @@ "name" : "id", "description" : null, "type" : { - "kind" : "SCALAR", - "name" : "ID", - "ofType" : null + "kind" : "NON_NULL", + "name" : null, + "ofType" : { + "kind" : "SCALAR", + "name" : "ID", + "ofType" : null + } }, "defaultValue" : null }, { @@ -2134,7 +2134,7 @@ }, "defaultValue" : null }, { - "name" : "imageURL", + "name" : "image", "description" : null, "type" : { "kind" : "SCALAR", @@ -2146,13 +2146,9 @@ "name" : "author", "description" : null, "type" : { - "kind" : "NON_NULL", - "name" : null, - "ofType" : { - "kind" : "SCALAR", - "name" : "String", - "ofType" : null - } + "kind" : "SCALAR", + "name" : "String", + "ofType" : null }, "defaultValue" : null }, { @@ -2201,7 +2197,7 @@ }, "defaultValue" : null }, { - "name" : "imageURL", + "name" : "image", "description" : null, "type" : { "kind" : "INPUT_OBJECT", @@ -2312,7 +2308,7 @@ }, "defaultValue" : null }, { - "name" : "imageURL", + "name" : "image", "description" : null, "type" : { "kind" : "SCALAR", @@ -2384,7 +2380,7 @@ }, "defaultValue" : null }, { - "name" : "bookId", + "name" : "book_id", "description" : null, "type" : { "kind" : "NON_NULL", @@ -2397,7 +2393,7 @@ }, "defaultValue" : null }, { - "name" : "orderId", + "name" : "order_id", "description" : null, "type" : { "kind" : "NON_NULL", @@ -2419,7 +2415,7 @@ "description" : null, "fields" : null, "inputFields" : [ { - "name" : "bookId", + "name" : "book_id", "description" : null, "type" : { "kind" : "INPUT_OBJECT", @@ -2428,7 +2424,7 @@ }, "defaultValue" : null }, { - "name" : "orderId", + "name" : "order_id", "description" : null, "type" : { "kind" : "INPUT_OBJECT", @@ -2494,7 +2490,7 @@ }, "defaultValue" : null }, { - "name" : "bookId", + "name" : "book_id", "description" : null, "type" : { "kind" : "SCALAR", @@ -2503,7 +2499,7 @@ }, "defaultValue" : null }, { - "name" : "orderId", + "name" : "order_id", "description" : null, "type" : { "kind" : "SCALAR", diff --git a/src/graphql/subscriptions.js b/src/graphql/subscriptions.js deleted file mode 100644 index 9245631b..00000000 --- a/src/graphql/subscriptions.js +++ /dev/null @@ -1,48 +0,0 @@ -/* eslint-disable */ -// this is an auto generated file. This will be overwritten - -export const onCreateBook = /* GraphQL */ ` - subscription OnCreateBook { - onCreateBook { - id - title - description - imageURL - author - featured - price - createdAt - updatedAt - } - } -`; -export const onUpdateBook = /* GraphQL */ ` - subscription OnUpdateBook { - onUpdateBook { - id - title - description - imageURL - author - featured - price - createdAt - updatedAt - } - } -`; -export const onDeleteBook = /* GraphQL */ ` - subscription OnDeleteBook { - onDeleteBook { - id - title - description - imageURL - author - featured - price - createdAt - updatedAt - } - } -`; diff --git a/src/index.css b/src/index.css index 15cc017b..a1f5f8c0 100644 --- a/src/index.css +++ b/src/index.css @@ -91,7 +91,7 @@ nav ul { background-repeat: no-repeat; background-size: cover; background-position: center; - min-height: 45vh; + min-height: 43vh; color: white; display: flex; flex-direction: column; @@ -127,7 +127,6 @@ nav ul { text-align: center; width: 90%; margin: auto; - padding: 20px 0 0 0; } .book { @@ -137,14 +136,14 @@ nav ul { align-items: center; box-shadow: 0px 10px 10px rgba(0, 0, 0, 0.1), 0px 20px 20px rgba(0, 0, 0, 0.1); width: 22rem; - height: 30rem; + height: 28rem; margin: 3rem 4rem; border-top: 1px solid #efefef; background: floralwhite; } .featured-list { - justify-content: flex-start; + justify-content: space-evenly; } .featured-book { @@ -201,8 +200,8 @@ nav ul { /* Admin Section */ -.add-book { - width: 90%; +.admin-wrapper { + width: 70%; margin: auto; text-align: center; } @@ -252,8 +251,14 @@ nav ul { text-align: left; } -.title-form, .description-form, .author-form, .price-form, .submit-form { - padding: 2rem; +.title-form, .description-form, .author-form, .price-form, .submit-form, .featured-form { + padding: 0.7rem; +} + +.form-fields .featured-checkbox{ + width: 2rem; + position: relative; + top: 1.4rem; } .submit-form { @@ -273,7 +278,7 @@ nav ul { flex-direction: column; } -.cart-item{ +.cart-item { margin: 2rem 0rem; display: flex; justify-content: space-around; @@ -281,11 +286,11 @@ nav ul { flex-wrap: wrap; } -.cart-item .image{ +.cart-item .image { flex: 1 1 10rem; } -.cart-item img{ +.cart-item img { width: 10rem; } @@ -293,23 +298,30 @@ nav ul { flex: 2 1 10rem; } -.cart-item .amount{ +.cart-item .amount { flex: 1 1 10rem; } +.cart-empty { + position: absolute; + top: 48%; + left: 40%; +} + /* Checkout Section */ -.checkout { - width: 50%; + +.checkout-wrapper { + width: 60%; margin: auto; } -.checkout-form{ +.checkout-form { display: flex; flex-direction: column; margin: 3rem 0; } -.stripe-section{ +.stripe-section { margin-top: 2rem; } diff --git a/src/pages/Admin.js b/src/pages/Admin.js index e5c2897c..78616498 100644 --- a/src/pages/Admin.js +++ b/src/pages/Admin.js @@ -2,8 +2,7 @@ import React, { useState } from 'react' import { v4 as uuidv4 } from 'uuid'; // Amplify API import { API, graphqlOperation, Storage } from "aws-amplify"; -import { withAuthenticator } from '@aws-amplify/ui-react' -import { AmplifyAuthenticator, AmplifySignIn, AmplifySignOut } from '@aws-amplify/ui-react'; +import { AmplifyAuthenticator, AmplifySignIn, AmplifySignOut, AmplifySignUp } from '@aws-amplify/ui-react'; import { createBook } from '../api/mutations' // import { listBooks } from '../graphql/queries' import config from '../aws-exports' @@ -15,16 +14,15 @@ const { const Admin = () => { - const [imageURL, setImageURL] = useState(null); - const [setLoading] = useState(false); - const [bookDetails, setBookDetails] = useState({ title: "", description: "", imageURL: "", author: "", price: "" }); + const [image, setImage] = useState(null); + const [bookDetails, setBookDetails] = useState({ title: "", description: "", image: "", author: "", price: "" }); const handleSubmit = async (e) => { e.preventDefault(); - console.log(bookDetails); try { if (!bookDetails.title || !bookDetails.price) return await API.graphql(graphqlOperation(createBook, { input: bookDetails })) + setBookDetails({ title: "", description: "", image: "", author: "", price: "" }) } catch (err) { console.log('error creating todo:', err) } @@ -38,90 +36,128 @@ const Admin = () => { const key = `images/${uuidv4()}${name}.${extension}`; const url = `https://${bucket}.s3.${region}.amazonaws.com/public/${key}` try { - setLoading(true); // Upload the file to s3 with private access level. await Storage.put(key, file, { level: 'public', contentType: file.type }); // Retrieve the uploaded file to display - const imageURL = await Storage.get(key, { level: 'public' }) - setImageURL(imageURL); - setBookDetails({ ...bookDetails, imageURL: url }); - setLoading(false); + const image = await Storage.get(key, { level: 'public' }) + setImage(image); + setBookDetails({ ...bookDetails, image: url }); } catch (err) { console.log(err); } } return ( - - -
-
-

Add New Book

- -
-
-
- {imageURL ? : handleImageUpload(e)} />} +
+ + + +
+
+

Add New Book

+ +
+ +
+ {image ? : handleImageUpload(e)} />} -
-
-
-

-

setBookDetails({ ...bookDetails, title: e.target.value })} - required - />

-
-

-