├── .expo-shared └── assets.json ├── .graphqlconfig.yml ├── .idea ├── amplifyProject.iml ├── misc.xml ├── modules.xml └── vcs.xml ├── .watchmanconfig ├── App.js ├── amplify ├── #current-cloud-backend │ ├── amplify-meta.json │ ├── api │ │ └── todoApi │ │ │ ├── build │ │ │ ├── cloudformation-template.json │ │ │ ├── parameters.json │ │ │ └── schema.graphql │ │ │ └── schema.graphql │ └── backend-config.json ├── backend │ ├── amplify-meta.json │ ├── api │ │ └── todoApi │ │ │ ├── build │ │ │ ├── cloudformation-template.json │ │ │ ├── parameters.json │ │ │ └── schema.graphql │ │ │ └── schema.graphql │ ├── auth │ │ └── amplifyprojectb3fea6ea │ │ │ ├── amplifyprojectb3fea6ea-cloudformation-template.yml │ │ │ └── parameters.json │ ├── awscloudformation │ │ └── nested-cloudformation-stack.yml │ └── backend-config.json └── team-provider-info.json ├── aws-exports.js ├── package-lock.json ├── package.json └── src ├── components ├── Bottom.js ├── Dialog.js ├── Header.js ├── OAuthButton.js ├── Todos.js ├── actions.js ├── dialogReducer.js ├── filterReducer.js ├── forgotPassword │ ├── ForgotPassword.js │ └── ForgotPasswordConfirm.js ├── helpers.js ├── reducers.js ├── signIn │ └── SignIn.js ├── signUp │ ├── SignUp.js │ └── SignUpConfirm.js └── store.js ├── graphql ├── mutations.js ├── queries.js ├── schema.json └── subscriptions.js ├── navigation ├── appFlowNav.js ├── authNavigation.js ├── forgotPassword.js └── index.js └── screens └── HomeScreen.js /.expo-shared/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "f9155ac790fd02fadcdeca367b02581c04a353aa6d5aa84409a59f6804c87acd": true, 3 | "89ed26367cdb9b771858e026f2eb95bfdb90e5ae943e716575327ec325f39c44": true 4 | } -------------------------------------------------------------------------------- /.graphqlconfig.yml: -------------------------------------------------------------------------------- 1 | projects: 2 | todoApi: 3 | schemaPath: src/graphql/schema.json 4 | includes: 5 | - src/graphql/**/*.js 6 | excludes: 7 | - ./amplify/** 8 | extensions: 9 | amplify: 10 | codeGenTarget: javascript 11 | generatedFileName: '' 12 | docsFilePath: src/graphql 13 | -------------------------------------------------------------------------------- /.idea/amplifyProject.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Provider} from 'react-redux'; 3 | import {store} from './src/components/store'; 4 | import HomeScreen from "./src/screens/HomeScreen"; 5 | import Amplify from 'aws-amplify'; 6 | import Navigation from './src/navigation'; 7 | 8 | import awsconfig from './aws-exports'; 9 | import { withAuthenticator } from 'aws-amplify-react-native'; 10 | 11 | Amplify.configure(awsconfig); 12 | 13 | 14 | const App = () => { 15 | return ( 16 | 17 | {/**/} 18 | {/* */} 19 | {/**/} 20 | 21 | 22 | 23 | ); 24 | }; 25 | 26 | export default App; -------------------------------------------------------------------------------- /amplify/#current-cloud-backend/amplify-meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "providers": { 3 | "awscloudformation": { 4 | "AuthRoleName": "amplifyproject-test-20190919143906-authRole", 5 | "UnauthRoleArn": "arn:aws:iam::082042224423:role/amplifyproject-test-20190919143906-unauthRole", 6 | "AuthRoleArn": "arn:aws:iam::082042224423:role/amplifyproject-test-20190919143906-authRole", 7 | "Region": "us-east-1", 8 | "DeploymentBucketName": "amplifyproject-test-20190919143906-deployment", 9 | "UnauthRoleName": "amplifyproject-test-20190919143906-unauthRole", 10 | "StackName": "amplifyproject-test-20190919143906", 11 | "StackId": "arn:aws:cloudformation:us-east-1:082042224423:stack/amplifyproject-test-20190919143906/17196b80-dad2-11e9-a39a-0e8cd4caae34" 12 | } 13 | }, 14 | "api": { 15 | "todoApi": { 16 | "service": "AppSync", 17 | "providerPlugin": "awscloudformation", 18 | "output": { 19 | "authConfig": { 20 | "additionalAuthenticationProviders": [], 21 | "defaultAuthentication": { 22 | "authenticationType": "API_KEY", 23 | "apiKeyConfig": { 24 | "description": "API key desc", 25 | "apiKeyExpirationDays": 180 26 | } 27 | } 28 | }, 29 | "GraphQLAPIIdOutput": "uuhw536vujaphbrqpfajkp32nm", 30 | "GraphQLAPIEndpointOutput": "https://6oqacvdcd5ehbkhflibujnjzpy.appsync-api.us-east-1.amazonaws.com/graphql", 31 | "GraphQLAPIKeyOutput": "da2-iawhwbfha5c3dhf3efuwpxphxy" 32 | }, 33 | "providerMetadata": { 34 | "s3TemplateURL": "https://s3.amazonaws.com/amplifyproject-test-20190919143906-deployment/amplify-cfn-templates/api/cloudformation-template.json", 35 | "logicalId": "apitodoApi" 36 | }, 37 | "lastPushTimeStamp": "2019-10-01T09:09:30.142Z", 38 | "lastPushDirHash": "mxXk6l5KNOtkouTdh7lzbjTwibM=" 39 | } 40 | }, 41 | "auth": { 42 | "amplifyprojectb3fea6ea": { 43 | "service": "Cognito", 44 | "providerPlugin": "awscloudformation", 45 | "dependsOn": [], 46 | "providerMetadata": { 47 | "s3TemplateURL": "https://s3.amazonaws.com/amplifyproject-test-20190919143906-deployment/amplify-cfn-templates/auth/amplifyprojectb3fea6ea-cloudformation-template.yml", 48 | "logicalId": "authamplifyprojectb3fea6ea" 49 | }, 50 | "lastPushTimeStamp": "2019-10-01T09:09:30.144Z", 51 | "output": { 52 | "AppClientSecret": "eq1842m668qrllirihf2ef9du1tpgg4h253oujo5plc4vdilbqd", 53 | "UserPoolId": "us-east-1_JEGRSXJ1m", 54 | "AppClientIDWeb": "1siqsh7nie77r156gmpve4bdh5", 55 | "AppClientID": "30mmpk81nmdg900fqci2fr2jqi", 56 | "HostedUIDomain": "amplifyprojectb3fea6ea-b3fea6ea-test", 57 | "IdentityPoolId": "us-east-1:4b34cfd5-e707-4432-9a9c-49a6b2eb4723", 58 | "IdentityPoolName": "amplifyprojectb3fea6ea_identitypool_b3fea6ea__test", 59 | "OAuthMetadata": "{\"AllowedOAuthFlows\":[\"code\"],\"AllowedOAuthScopes\":[\"phone\",\"email\",\"openid\",\"profile\",\"aws.cognito.signin.user.admin\"],\"CallbackURLs\":[\"https://192.168.0.80:19006/\"],\"LogoutURLs\":[\"https://192.168.0.80:19006/\"]}", 60 | "UserPoolName": "amplifyprojectb3fea6ea_userpool_b3fea6ea" 61 | }, 62 | "lastPushDirHash": "CIyQxc9lLwnKX9iCcKX/cNkb+3s=" 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /amplify/#current-cloud-backend/api/todoApi/build/cloudformation-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Description": "An auto-generated nested stack.", 4 | "Metadata": {}, 5 | "Parameters": { 6 | "DynamoDBModelTableReadIOPS": { 7 | "Type": "Number", 8 | "Description": "The number of read IOPS the table should support.", 9 | "Default": 5 10 | }, 11 | "DynamoDBModelTableWriteIOPS": { 12 | "Type": "Number", 13 | "Description": "The number of write IOPS the table should support.", 14 | "Default": 5 15 | }, 16 | "DynamoDBBillingMode": { 17 | "Type": "String", 18 | "Description": "Configure @model types to create DynamoDB tables with PAY_PER_REQUEST or PROVISIONED billing modes.", 19 | "Default": "PAY_PER_REQUEST", 20 | "AllowedValues": [ 21 | "PAY_PER_REQUEST", 22 | "PROVISIONED" 23 | ] 24 | }, 25 | "DynamoDBEnablePointInTimeRecovery": { 26 | "Type": "String", 27 | "Description": "Whether to enable Point in Time Recovery on the table", 28 | "Default": "false", 29 | "AllowedValues": [ 30 | "true", 31 | "false" 32 | ] 33 | }, 34 | "DynamoDBEnableServerSideEncryption": { 35 | "Type": "String", 36 | "Description": "Enable server side encryption powered by KMS.", 37 | "Default": "true", 38 | "AllowedValues": [ 39 | "true", 40 | "false" 41 | ] 42 | }, 43 | "AppSyncApiName": { 44 | "Type": "String", 45 | "Description": "The name of the AppSync API", 46 | "Default": "AppSyncSimpleTransform" 47 | }, 48 | "APIKeyExpirationEpoch": { 49 | "Type": "Number", 50 | "Description": "The epoch time in seconds when the API Key should expire. Setting this to 0 will default to 180 days from the deployment date. Setting this to -1 will not create an API Key.", 51 | "Default": 0, 52 | "MinValue": -1 53 | }, 54 | "CreateAPIKey": { 55 | "Type": "Number", 56 | "Description": "The boolean value to control if an API Key will be created or not. The value of the property is automatically set by the CLI. If the value is set to 0 no API Key will be created.", 57 | "Default": 0, 58 | "MinValue": 0, 59 | "MaxValue": 1 60 | }, 61 | "AuthCognitoUserPoolId": { 62 | "Type": "String", 63 | "Description": "The id of an existing User Pool to connect. If this is changed, a user pool will not be created for you.", 64 | "Default": "NONE" 65 | }, 66 | "env": { 67 | "Type": "String", 68 | "Description": "The environment name. e.g. Dev, Test, or Production", 69 | "Default": "NONE" 70 | }, 71 | "S3DeploymentBucket": { 72 | "Type": "String", 73 | "Description": "The S3 bucket containing all deployment assets for the project." 74 | }, 75 | "S3DeploymentRootKey": { 76 | "Type": "String", 77 | "Description": "An S3 key relative to the S3DeploymentBucket that points to the root of the deployment directory." 78 | } 79 | }, 80 | "Resources": { 81 | "GraphQLAPI": { 82 | "Type": "AWS::AppSync::GraphQLApi", 83 | "Properties": { 84 | "Name": { 85 | "Fn::If": [ 86 | "HasEnvironmentParameter", 87 | { 88 | "Fn::Join": [ 89 | "-", 90 | [ 91 | { 92 | "Ref": "AppSyncApiName" 93 | }, 94 | { 95 | "Ref": "env" 96 | } 97 | ] 98 | ] 99 | }, 100 | { 101 | "Ref": "AppSyncApiName" 102 | } 103 | ] 104 | }, 105 | "AuthenticationType": "API_KEY" 106 | } 107 | }, 108 | "GraphQLAPIKey": { 109 | "Type": "AWS::AppSync::ApiKey", 110 | "Properties": { 111 | "ApiId": { 112 | "Fn::GetAtt": [ 113 | "GraphQLAPI", 114 | "ApiId" 115 | ] 116 | }, 117 | "Description": "API key desc", 118 | "Expires": { 119 | "Fn::If": [ 120 | "APIKeyExpirationEpochIsPositive", 121 | { 122 | "Ref": "APIKeyExpirationEpoch" 123 | }, 124 | 1584889985 125 | ] 126 | } 127 | }, 128 | "Condition": "ShouldCreateAPIKey" 129 | }, 130 | "GraphQLSchema": { 131 | "Type": "AWS::AppSync::GraphQLSchema", 132 | "Properties": { 133 | "ApiId": { 134 | "Fn::GetAtt": [ 135 | "GraphQLAPI", 136 | "ApiId" 137 | ] 138 | }, 139 | "DefinitionS3Location": { 140 | "Fn::Sub": [ 141 | "s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/schema.graphql", 142 | { 143 | "S3DeploymentBucket": { 144 | "Ref": "S3DeploymentBucket" 145 | }, 146 | "S3DeploymentRootKey": { 147 | "Ref": "S3DeploymentRootKey" 148 | } 149 | } 150 | ] 151 | } 152 | } 153 | }, 154 | "Todo": { 155 | "Type": "AWS::CloudFormation::Stack", 156 | "Properties": { 157 | "Parameters": { 158 | "AppSyncApiId": { 159 | "Fn::GetAtt": [ 160 | "GraphQLAPI", 161 | "ApiId" 162 | ] 163 | }, 164 | "DynamoDBModelTableReadIOPS": { 165 | "Ref": "DynamoDBModelTableReadIOPS" 166 | }, 167 | "DynamoDBModelTableWriteIOPS": { 168 | "Ref": "DynamoDBModelTableWriteIOPS" 169 | }, 170 | "DynamoDBBillingMode": { 171 | "Ref": "DynamoDBBillingMode" 172 | }, 173 | "DynamoDBEnablePointInTimeRecovery": { 174 | "Ref": "DynamoDBEnablePointInTimeRecovery" 175 | }, 176 | "DynamoDBEnableServerSideEncryption": { 177 | "Ref": "DynamoDBEnableServerSideEncryption" 178 | }, 179 | "AppSyncApiName": { 180 | "Ref": "AppSyncApiName" 181 | }, 182 | "APIKeyExpirationEpoch": { 183 | "Ref": "APIKeyExpirationEpoch" 184 | }, 185 | "CreateAPIKey": { 186 | "Ref": "CreateAPIKey" 187 | }, 188 | "AuthCognitoUserPoolId": { 189 | "Ref": "AuthCognitoUserPoolId" 190 | }, 191 | "env": { 192 | "Ref": "env" 193 | }, 194 | "S3DeploymentBucket": { 195 | "Ref": "S3DeploymentBucket" 196 | }, 197 | "S3DeploymentRootKey": { 198 | "Ref": "S3DeploymentRootKey" 199 | }, 200 | "GetAttGraphQLAPIApiId": { 201 | "Fn::GetAtt": [ 202 | "GraphQLAPI", 203 | "ApiId" 204 | ] 205 | } 206 | }, 207 | "TemplateURL": { 208 | "Fn::Join": [ 209 | "/", 210 | [ 211 | "https://s3.amazonaws.com", 212 | { 213 | "Ref": "S3DeploymentBucket" 214 | }, 215 | { 216 | "Ref": "S3DeploymentRootKey" 217 | }, 218 | "stacks", 219 | "Todo.json" 220 | ] 221 | ] 222 | } 223 | }, 224 | "DependsOn": [ 225 | "GraphQLSchema" 226 | ] 227 | }, 228 | "CustomResourcesjson": { 229 | "Type": "AWS::CloudFormation::Stack", 230 | "Properties": { 231 | "Parameters": { 232 | "AppSyncApiId": { 233 | "Fn::GetAtt": [ 234 | "GraphQLAPI", 235 | "ApiId" 236 | ] 237 | }, 238 | "AppSyncApiName": { 239 | "Ref": "AppSyncApiName" 240 | }, 241 | "env": { 242 | "Ref": "env" 243 | }, 244 | "S3DeploymentBucket": { 245 | "Ref": "S3DeploymentBucket" 246 | }, 247 | "S3DeploymentRootKey": { 248 | "Ref": "S3DeploymentRootKey" 249 | } 250 | }, 251 | "TemplateURL": { 252 | "Fn::Join": [ 253 | "/", 254 | [ 255 | "https://s3.amazonaws.com", 256 | { 257 | "Ref": "S3DeploymentBucket" 258 | }, 259 | { 260 | "Ref": "S3DeploymentRootKey" 261 | }, 262 | "stacks", 263 | "CustomResources.json" 264 | ] 265 | ] 266 | } 267 | }, 268 | "DependsOn": [ 269 | "GraphQLAPI", 270 | "GraphQLSchema", 271 | "Todo" 272 | ] 273 | } 274 | }, 275 | "Outputs": { 276 | "GraphQLAPIIdOutput": { 277 | "Description": "Your GraphQL API ID.", 278 | "Value": { 279 | "Fn::GetAtt": [ 280 | "GraphQLAPI", 281 | "ApiId" 282 | ] 283 | }, 284 | "Export": { 285 | "Name": { 286 | "Fn::Join": [ 287 | ":", 288 | [ 289 | { 290 | "Ref": "AWS::StackName" 291 | }, 292 | "GraphQLApiId" 293 | ] 294 | ] 295 | } 296 | } 297 | }, 298 | "GraphQLAPIEndpointOutput": { 299 | "Description": "Your GraphQL API endpoint.", 300 | "Value": { 301 | "Fn::GetAtt": [ 302 | "GraphQLAPI", 303 | "GraphQLUrl" 304 | ] 305 | }, 306 | "Export": { 307 | "Name": { 308 | "Fn::Join": [ 309 | ":", 310 | [ 311 | { 312 | "Ref": "AWS::StackName" 313 | }, 314 | "GraphQLApiEndpoint" 315 | ] 316 | ] 317 | } 318 | } 319 | }, 320 | "GraphQLAPIKeyOutput": { 321 | "Description": "Your GraphQL API key. Provide via 'x-api-key' header.", 322 | "Value": { 323 | "Fn::GetAtt": [ 324 | "GraphQLAPIKey", 325 | "ApiKey" 326 | ] 327 | }, 328 | "Export": { 329 | "Name": { 330 | "Fn::Join": [ 331 | ":", 332 | [ 333 | { 334 | "Ref": "AWS::StackName" 335 | }, 336 | "GraphQLApiKey" 337 | ] 338 | ] 339 | } 340 | }, 341 | "Condition": "ShouldCreateAPIKey" 342 | } 343 | }, 344 | "Conditions": { 345 | "ShouldUsePayPerRequestBilling": { 346 | "Fn::Equals": [ 347 | { 348 | "Ref": "DynamoDBBillingMode" 349 | }, 350 | "PAY_PER_REQUEST" 351 | ] 352 | }, 353 | "ShouldUsePointInTimeRecovery": { 354 | "Fn::Equals": [ 355 | { 356 | "Ref": "DynamoDBEnablePointInTimeRecovery" 357 | }, 358 | "true" 359 | ] 360 | }, 361 | "ShouldUseServerSideEncryption": { 362 | "Fn::Equals": [ 363 | { 364 | "Ref": "DynamoDBEnableServerSideEncryption" 365 | }, 366 | "true" 367 | ] 368 | }, 369 | "ShouldCreateAPIKey": { 370 | "Fn::Equals": [ 371 | { 372 | "Ref": "CreateAPIKey" 373 | }, 374 | 1 375 | ] 376 | }, 377 | "APIKeyExpirationEpochIsPositive": { 378 | "Fn::And": [ 379 | { 380 | "Fn::Not": [ 381 | { 382 | "Fn::Equals": [ 383 | { 384 | "Ref": "APIKeyExpirationEpoch" 385 | }, 386 | -1 387 | ] 388 | } 389 | ] 390 | }, 391 | { 392 | "Fn::Not": [ 393 | { 394 | "Fn::Equals": [ 395 | { 396 | "Ref": "APIKeyExpirationEpoch" 397 | }, 398 | 0 399 | ] 400 | } 401 | ] 402 | } 403 | ] 404 | }, 405 | "HasEnvironmentParameter": { 406 | "Fn::Not": [ 407 | { 408 | "Fn::Equals": [ 409 | { 410 | "Ref": "env" 411 | }, 412 | "NONE" 413 | ] 414 | } 415 | ] 416 | } 417 | } 418 | } -------------------------------------------------------------------------------- /amplify/#current-cloud-backend/api/todoApi/build/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "CreateAPIKey": 1, 3 | "AppSyncApiName": "todoApi", 4 | "DynamoDBBillingMode": "PAY_PER_REQUEST", 5 | "DynamoDBEnableServerSideEncryption": "false", 6 | "S3DeploymentBucket": "amplifyproject-test-20190919143906-deployment", 7 | "S3DeploymentRootKey": "amplify-appsync-files/4b4b159fa3fedb4ab8ed48d581bcb35cf038c826" 8 | } -------------------------------------------------------------------------------- /amplify/#current-cloud-backend/api/todoApi/build/schema.graphql: -------------------------------------------------------------------------------- 1 | type Todo { 2 | id: ID! 3 | name: String! 4 | description: String 5 | time: String 6 | completed: Boolean 7 | } 8 | 9 | enum ModelSortDirection { 10 | ASC 11 | DESC 12 | } 13 | 14 | type ModelTodoConnection { 15 | items: [Todo] 16 | nextToken: String 17 | } 18 | 19 | input ModelStringFilterInput { 20 | ne: String 21 | eq: String 22 | le: String 23 | lt: String 24 | ge: String 25 | gt: String 26 | contains: String 27 | notContains: String 28 | between: [String] 29 | beginsWith: String 30 | } 31 | 32 | input ModelIDFilterInput { 33 | ne: ID 34 | eq: ID 35 | le: ID 36 | lt: ID 37 | ge: ID 38 | gt: ID 39 | contains: ID 40 | notContains: ID 41 | between: [ID] 42 | beginsWith: ID 43 | } 44 | 45 | input ModelIntFilterInput { 46 | ne: Int 47 | eq: Int 48 | le: Int 49 | lt: Int 50 | ge: Int 51 | gt: Int 52 | contains: Int 53 | notContains: Int 54 | between: [Int] 55 | } 56 | 57 | input ModelFloatFilterInput { 58 | ne: Float 59 | eq: Float 60 | le: Float 61 | lt: Float 62 | ge: Float 63 | gt: Float 64 | contains: Float 65 | notContains: Float 66 | between: [Float] 67 | } 68 | 69 | input ModelBooleanFilterInput { 70 | ne: Boolean 71 | eq: Boolean 72 | } 73 | 74 | input ModelTodoFilterInput { 75 | id: ModelIDFilterInput 76 | name: ModelStringFilterInput 77 | description: ModelStringFilterInput 78 | time: ModelStringFilterInput 79 | completed: ModelBooleanFilterInput 80 | and: [ModelTodoFilterInput] 81 | or: [ModelTodoFilterInput] 82 | not: ModelTodoFilterInput 83 | } 84 | 85 | type Query { 86 | getTodo(id: ID!): Todo 87 | listTodos(filter: ModelTodoFilterInput, limit: Int, nextToken: String): ModelTodoConnection 88 | } 89 | 90 | input CreateTodoInput { 91 | id: ID 92 | name: String! 93 | description: String 94 | time: String 95 | completed: Boolean 96 | } 97 | 98 | input UpdateTodoInput { 99 | id: ID! 100 | name: String 101 | description: String 102 | time: String 103 | completed: Boolean 104 | } 105 | 106 | input DeleteTodoInput { 107 | id: ID 108 | } 109 | 110 | type Mutation { 111 | createTodo(input: CreateTodoInput!): Todo 112 | updateTodo(input: UpdateTodoInput!): Todo 113 | deleteTodo(input: DeleteTodoInput!): Todo 114 | } 115 | 116 | type Subscription { 117 | onCreateTodo: Todo @aws_subscribe(mutations: ["createTodo"]) 118 | onUpdateTodo: Todo @aws_subscribe(mutations: ["updateTodo"]) 119 | onDeleteTodo: Todo @aws_subscribe(mutations: ["deleteTodo"]) 120 | } 121 | -------------------------------------------------------------------------------- /amplify/#current-cloud-backend/api/todoApi/schema.graphql: -------------------------------------------------------------------------------- 1 | type Todo @model { 2 | id: ID! 3 | name: String! 4 | description: String 5 | time: String 6 | completed: Boolean 7 | 8 | } -------------------------------------------------------------------------------- /amplify/#current-cloud-backend/backend-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "api": { 3 | "todoApi": { 4 | "service": "AppSync", 5 | "providerPlugin": "awscloudformation", 6 | "output": { 7 | "authConfig": { 8 | "additionalAuthenticationProviders": [], 9 | "defaultAuthentication": { 10 | "authenticationType": "API_KEY", 11 | "apiKeyConfig": { 12 | "description": "API key desc", 13 | "apiKeyExpirationDays": 180 14 | } 15 | } 16 | } 17 | } 18 | } 19 | }, 20 | "auth": { 21 | "amplifyprojectb3fea6ea": { 22 | "service": "Cognito", 23 | "providerPlugin": "awscloudformation", 24 | "dependsOn": [] 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /amplify/backend/amplify-meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "providers": { 3 | "awscloudformation": { 4 | "AuthRoleName": "amplifyproject-test-20190919143906-authRole", 5 | "UnauthRoleArn": "arn:aws:iam::082042224423:role/amplifyproject-test-20190919143906-unauthRole", 6 | "AuthRoleArn": "arn:aws:iam::082042224423:role/amplifyproject-test-20190919143906-authRole", 7 | "Region": "us-east-1", 8 | "DeploymentBucketName": "amplifyproject-test-20190919143906-deployment", 9 | "UnauthRoleName": "amplifyproject-test-20190919143906-unauthRole", 10 | "StackName": "amplifyproject-test-20190919143906", 11 | "StackId": "arn:aws:cloudformation:us-east-1:082042224423:stack/amplifyproject-test-20190919143906/17196b80-dad2-11e9-a39a-0e8cd4caae34" 12 | } 13 | }, 14 | "api": { 15 | "todoApi": { 16 | "service": "AppSync", 17 | "providerPlugin": "awscloudformation", 18 | "output": { 19 | "authConfig": { 20 | "additionalAuthenticationProviders": [], 21 | "defaultAuthentication": { 22 | "authenticationType": "API_KEY", 23 | "apiKeyConfig": { 24 | "description": "API key desc", 25 | "apiKeyExpirationDays": 180 26 | } 27 | } 28 | }, 29 | "GraphQLAPIIdOutput": "uuhw536vujaphbrqpfajkp32nm", 30 | "GraphQLAPIEndpointOutput": "https://6oqacvdcd5ehbkhflibujnjzpy.appsync-api.us-east-1.amazonaws.com/graphql", 31 | "GraphQLAPIKeyOutput": "da2-iawhwbfha5c3dhf3efuwpxphxy" 32 | }, 33 | "providerMetadata": { 34 | "s3TemplateURL": "https://s3.amazonaws.com/amplifyproject-test-20190919143906-deployment/amplify-cfn-templates/api/cloudformation-template.json", 35 | "logicalId": "apitodoApi" 36 | }, 37 | "lastPushTimeStamp": "2019-10-01T09:09:30.142Z", 38 | "lastPushDirHash": "mxXk6l5KNOtkouTdh7lzbjTwibM=" 39 | } 40 | }, 41 | "auth": { 42 | "amplifyprojectb3fea6ea": { 43 | "service": "Cognito", 44 | "providerPlugin": "awscloudformation", 45 | "dependsOn": [], 46 | "providerMetadata": { 47 | "s3TemplateURL": "https://s3.amazonaws.com/amplifyproject-test-20190919143906-deployment/amplify-cfn-templates/auth/amplifyprojectb3fea6ea-cloudformation-template.yml", 48 | "logicalId": "authamplifyprojectb3fea6ea" 49 | }, 50 | "lastPushTimeStamp": "2019-10-01T09:09:30.144Z", 51 | "output": { 52 | "AppClientSecret": "eq1842m668qrllirihf2ef9du1tpgg4h253oujo5plc4vdilbqd", 53 | "UserPoolId": "us-east-1_JEGRSXJ1m", 54 | "AppClientIDWeb": "1siqsh7nie77r156gmpve4bdh5", 55 | "AppClientID": "30mmpk81nmdg900fqci2fr2jqi", 56 | "HostedUIDomain": "amplifyprojectb3fea6ea-b3fea6ea-test", 57 | "IdentityPoolId": "us-east-1:4b34cfd5-e707-4432-9a9c-49a6b2eb4723", 58 | "IdentityPoolName": "amplifyprojectb3fea6ea_identitypool_b3fea6ea__test", 59 | "OAuthMetadata": "{\"AllowedOAuthFlows\":[\"code\"],\"AllowedOAuthScopes\":[\"phone\",\"email\",\"openid\",\"profile\",\"aws.cognito.signin.user.admin\"],\"CallbackURLs\":[\"https://192.168.0.80:19006/\"],\"LogoutURLs\":[\"https://192.168.0.80:19006/\"]}", 60 | "UserPoolName": "amplifyprojectb3fea6ea_userpool_b3fea6ea" 61 | }, 62 | "lastPushDirHash": "CIyQxc9lLwnKX9iCcKX/cNkb+3s=" 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /amplify/backend/api/todoApi/build/cloudformation-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Description": "An auto-generated nested stack.", 4 | "Metadata": {}, 5 | "Parameters": { 6 | "DynamoDBModelTableReadIOPS": { 7 | "Type": "Number", 8 | "Description": "The number of read IOPS the table should support.", 9 | "Default": 5 10 | }, 11 | "DynamoDBModelTableWriteIOPS": { 12 | "Type": "Number", 13 | "Description": "The number of write IOPS the table should support.", 14 | "Default": 5 15 | }, 16 | "DynamoDBBillingMode": { 17 | "Type": "String", 18 | "Description": "Configure @model types to create DynamoDB tables with PAY_PER_REQUEST or PROVISIONED billing modes.", 19 | "Default": "PAY_PER_REQUEST", 20 | "AllowedValues": [ 21 | "PAY_PER_REQUEST", 22 | "PROVISIONED" 23 | ] 24 | }, 25 | "DynamoDBEnablePointInTimeRecovery": { 26 | "Type": "String", 27 | "Description": "Whether to enable Point in Time Recovery on the table", 28 | "Default": "false", 29 | "AllowedValues": [ 30 | "true", 31 | "false" 32 | ] 33 | }, 34 | "DynamoDBEnableServerSideEncryption": { 35 | "Type": "String", 36 | "Description": "Enable server side encryption powered by KMS.", 37 | "Default": "true", 38 | "AllowedValues": [ 39 | "true", 40 | "false" 41 | ] 42 | }, 43 | "AppSyncApiName": { 44 | "Type": "String", 45 | "Description": "The name of the AppSync API", 46 | "Default": "AppSyncSimpleTransform" 47 | }, 48 | "APIKeyExpirationEpoch": { 49 | "Type": "Number", 50 | "Description": "The epoch time in seconds when the API Key should expire. Setting this to 0 will default to 180 days from the deployment date. Setting this to -1 will not create an API Key.", 51 | "Default": 0, 52 | "MinValue": -1 53 | }, 54 | "CreateAPIKey": { 55 | "Type": "Number", 56 | "Description": "The boolean value to control if an API Key will be created or not. The value of the property is automatically set by the CLI. If the value is set to 0 no API Key will be created.", 57 | "Default": 0, 58 | "MinValue": 0, 59 | "MaxValue": 1 60 | }, 61 | "AuthCognitoUserPoolId": { 62 | "Type": "String", 63 | "Description": "The id of an existing User Pool to connect. If this is changed, a user pool will not be created for you.", 64 | "Default": "NONE" 65 | }, 66 | "env": { 67 | "Type": "String", 68 | "Description": "The environment name. e.g. Dev, Test, or Production", 69 | "Default": "NONE" 70 | }, 71 | "S3DeploymentBucket": { 72 | "Type": "String", 73 | "Description": "The S3 bucket containing all deployment assets for the project." 74 | }, 75 | "S3DeploymentRootKey": { 76 | "Type": "String", 77 | "Description": "An S3 key relative to the S3DeploymentBucket that points to the root of the deployment directory." 78 | } 79 | }, 80 | "Resources": { 81 | "GraphQLAPI": { 82 | "Type": "AWS::AppSync::GraphQLApi", 83 | "Properties": { 84 | "Name": { 85 | "Fn::If": [ 86 | "HasEnvironmentParameter", 87 | { 88 | "Fn::Join": [ 89 | "-", 90 | [ 91 | { 92 | "Ref": "AppSyncApiName" 93 | }, 94 | { 95 | "Ref": "env" 96 | } 97 | ] 98 | ] 99 | }, 100 | { 101 | "Ref": "AppSyncApiName" 102 | } 103 | ] 104 | }, 105 | "AuthenticationType": "API_KEY" 106 | } 107 | }, 108 | "GraphQLAPIKey": { 109 | "Type": "AWS::AppSync::ApiKey", 110 | "Properties": { 111 | "ApiId": { 112 | "Fn::GetAtt": [ 113 | "GraphQLAPI", 114 | "ApiId" 115 | ] 116 | }, 117 | "Description": "API key desc", 118 | "Expires": { 119 | "Fn::If": [ 120 | "APIKeyExpirationEpochIsPositive", 121 | { 122 | "Ref": "APIKeyExpirationEpoch" 123 | }, 124 | 1584889985 125 | ] 126 | } 127 | }, 128 | "Condition": "ShouldCreateAPIKey" 129 | }, 130 | "GraphQLSchema": { 131 | "Type": "AWS::AppSync::GraphQLSchema", 132 | "Properties": { 133 | "ApiId": { 134 | "Fn::GetAtt": [ 135 | "GraphQLAPI", 136 | "ApiId" 137 | ] 138 | }, 139 | "DefinitionS3Location": { 140 | "Fn::Sub": [ 141 | "s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/schema.graphql", 142 | { 143 | "S3DeploymentBucket": { 144 | "Ref": "S3DeploymentBucket" 145 | }, 146 | "S3DeploymentRootKey": { 147 | "Ref": "S3DeploymentRootKey" 148 | } 149 | } 150 | ] 151 | } 152 | } 153 | }, 154 | "Todo": { 155 | "Type": "AWS::CloudFormation::Stack", 156 | "Properties": { 157 | "Parameters": { 158 | "AppSyncApiId": { 159 | "Fn::GetAtt": [ 160 | "GraphQLAPI", 161 | "ApiId" 162 | ] 163 | }, 164 | "DynamoDBModelTableReadIOPS": { 165 | "Ref": "DynamoDBModelTableReadIOPS" 166 | }, 167 | "DynamoDBModelTableWriteIOPS": { 168 | "Ref": "DynamoDBModelTableWriteIOPS" 169 | }, 170 | "DynamoDBBillingMode": { 171 | "Ref": "DynamoDBBillingMode" 172 | }, 173 | "DynamoDBEnablePointInTimeRecovery": { 174 | "Ref": "DynamoDBEnablePointInTimeRecovery" 175 | }, 176 | "DynamoDBEnableServerSideEncryption": { 177 | "Ref": "DynamoDBEnableServerSideEncryption" 178 | }, 179 | "AppSyncApiName": { 180 | "Ref": "AppSyncApiName" 181 | }, 182 | "APIKeyExpirationEpoch": { 183 | "Ref": "APIKeyExpirationEpoch" 184 | }, 185 | "CreateAPIKey": { 186 | "Ref": "CreateAPIKey" 187 | }, 188 | "AuthCognitoUserPoolId": { 189 | "Ref": "AuthCognitoUserPoolId" 190 | }, 191 | "env": { 192 | "Ref": "env" 193 | }, 194 | "S3DeploymentBucket": { 195 | "Ref": "S3DeploymentBucket" 196 | }, 197 | "S3DeploymentRootKey": { 198 | "Ref": "S3DeploymentRootKey" 199 | }, 200 | "GetAttGraphQLAPIApiId": { 201 | "Fn::GetAtt": [ 202 | "GraphQLAPI", 203 | "ApiId" 204 | ] 205 | } 206 | }, 207 | "TemplateURL": { 208 | "Fn::Join": [ 209 | "/", 210 | [ 211 | "https://s3.amazonaws.com", 212 | { 213 | "Ref": "S3DeploymentBucket" 214 | }, 215 | { 216 | "Ref": "S3DeploymentRootKey" 217 | }, 218 | "stacks", 219 | "Todo.json" 220 | ] 221 | ] 222 | } 223 | }, 224 | "DependsOn": [ 225 | "GraphQLSchema" 226 | ] 227 | }, 228 | "CustomResourcesjson": { 229 | "Type": "AWS::CloudFormation::Stack", 230 | "Properties": { 231 | "Parameters": { 232 | "AppSyncApiId": { 233 | "Fn::GetAtt": [ 234 | "GraphQLAPI", 235 | "ApiId" 236 | ] 237 | }, 238 | "AppSyncApiName": { 239 | "Ref": "AppSyncApiName" 240 | }, 241 | "env": { 242 | "Ref": "env" 243 | }, 244 | "S3DeploymentBucket": { 245 | "Ref": "S3DeploymentBucket" 246 | }, 247 | "S3DeploymentRootKey": { 248 | "Ref": "S3DeploymentRootKey" 249 | } 250 | }, 251 | "TemplateURL": { 252 | "Fn::Join": [ 253 | "/", 254 | [ 255 | "https://s3.amazonaws.com", 256 | { 257 | "Ref": "S3DeploymentBucket" 258 | }, 259 | { 260 | "Ref": "S3DeploymentRootKey" 261 | }, 262 | "stacks", 263 | "CustomResources.json" 264 | ] 265 | ] 266 | } 267 | }, 268 | "DependsOn": [ 269 | "GraphQLAPI", 270 | "GraphQLSchema", 271 | "Todo" 272 | ] 273 | } 274 | }, 275 | "Outputs": { 276 | "GraphQLAPIIdOutput": { 277 | "Description": "Your GraphQL API ID.", 278 | "Value": { 279 | "Fn::GetAtt": [ 280 | "GraphQLAPI", 281 | "ApiId" 282 | ] 283 | }, 284 | "Export": { 285 | "Name": { 286 | "Fn::Join": [ 287 | ":", 288 | [ 289 | { 290 | "Ref": "AWS::StackName" 291 | }, 292 | "GraphQLApiId" 293 | ] 294 | ] 295 | } 296 | } 297 | }, 298 | "GraphQLAPIEndpointOutput": { 299 | "Description": "Your GraphQL API endpoint.", 300 | "Value": { 301 | "Fn::GetAtt": [ 302 | "GraphQLAPI", 303 | "GraphQLUrl" 304 | ] 305 | }, 306 | "Export": { 307 | "Name": { 308 | "Fn::Join": [ 309 | ":", 310 | [ 311 | { 312 | "Ref": "AWS::StackName" 313 | }, 314 | "GraphQLApiEndpoint" 315 | ] 316 | ] 317 | } 318 | } 319 | }, 320 | "GraphQLAPIKeyOutput": { 321 | "Description": "Your GraphQL API key. Provide via 'x-api-key' header.", 322 | "Value": { 323 | "Fn::GetAtt": [ 324 | "GraphQLAPIKey", 325 | "ApiKey" 326 | ] 327 | }, 328 | "Export": { 329 | "Name": { 330 | "Fn::Join": [ 331 | ":", 332 | [ 333 | { 334 | "Ref": "AWS::StackName" 335 | }, 336 | "GraphQLApiKey" 337 | ] 338 | ] 339 | } 340 | }, 341 | "Condition": "ShouldCreateAPIKey" 342 | } 343 | }, 344 | "Conditions": { 345 | "ShouldUsePayPerRequestBilling": { 346 | "Fn::Equals": [ 347 | { 348 | "Ref": "DynamoDBBillingMode" 349 | }, 350 | "PAY_PER_REQUEST" 351 | ] 352 | }, 353 | "ShouldUsePointInTimeRecovery": { 354 | "Fn::Equals": [ 355 | { 356 | "Ref": "DynamoDBEnablePointInTimeRecovery" 357 | }, 358 | "true" 359 | ] 360 | }, 361 | "ShouldUseServerSideEncryption": { 362 | "Fn::Equals": [ 363 | { 364 | "Ref": "DynamoDBEnableServerSideEncryption" 365 | }, 366 | "true" 367 | ] 368 | }, 369 | "ShouldCreateAPIKey": { 370 | "Fn::Equals": [ 371 | { 372 | "Ref": "CreateAPIKey" 373 | }, 374 | 1 375 | ] 376 | }, 377 | "APIKeyExpirationEpochIsPositive": { 378 | "Fn::And": [ 379 | { 380 | "Fn::Not": [ 381 | { 382 | "Fn::Equals": [ 383 | { 384 | "Ref": "APIKeyExpirationEpoch" 385 | }, 386 | -1 387 | ] 388 | } 389 | ] 390 | }, 391 | { 392 | "Fn::Not": [ 393 | { 394 | "Fn::Equals": [ 395 | { 396 | "Ref": "APIKeyExpirationEpoch" 397 | }, 398 | 0 399 | ] 400 | } 401 | ] 402 | } 403 | ] 404 | }, 405 | "HasEnvironmentParameter": { 406 | "Fn::Not": [ 407 | { 408 | "Fn::Equals": [ 409 | { 410 | "Ref": "env" 411 | }, 412 | "NONE" 413 | ] 414 | } 415 | ] 416 | } 417 | } 418 | } -------------------------------------------------------------------------------- /amplify/backend/api/todoApi/build/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "CreateAPIKey": 1, 3 | "AppSyncApiName": "todoApi", 4 | "DynamoDBBillingMode": "PAY_PER_REQUEST", 5 | "DynamoDBEnableServerSideEncryption": "false", 6 | "S3DeploymentBucket": "amplifyproject-test-20190919143906-deployment", 7 | "S3DeploymentRootKey": "amplify-appsync-files/4b4b159fa3fedb4ab8ed48d581bcb35cf038c826" 8 | } -------------------------------------------------------------------------------- /amplify/backend/api/todoApi/build/schema.graphql: -------------------------------------------------------------------------------- 1 | type Todo { 2 | id: ID! 3 | name: String! 4 | description: String 5 | time: String 6 | completed: Boolean 7 | } 8 | 9 | enum ModelSortDirection { 10 | ASC 11 | DESC 12 | } 13 | 14 | type ModelTodoConnection { 15 | items: [Todo] 16 | nextToken: String 17 | } 18 | 19 | input ModelStringFilterInput { 20 | ne: String 21 | eq: String 22 | le: String 23 | lt: String 24 | ge: String 25 | gt: String 26 | contains: String 27 | notContains: String 28 | between: [String] 29 | beginsWith: String 30 | } 31 | 32 | input ModelIDFilterInput { 33 | ne: ID 34 | eq: ID 35 | le: ID 36 | lt: ID 37 | ge: ID 38 | gt: ID 39 | contains: ID 40 | notContains: ID 41 | between: [ID] 42 | beginsWith: ID 43 | } 44 | 45 | input ModelIntFilterInput { 46 | ne: Int 47 | eq: Int 48 | le: Int 49 | lt: Int 50 | ge: Int 51 | gt: Int 52 | contains: Int 53 | notContains: Int 54 | between: [Int] 55 | } 56 | 57 | input ModelFloatFilterInput { 58 | ne: Float 59 | eq: Float 60 | le: Float 61 | lt: Float 62 | ge: Float 63 | gt: Float 64 | contains: Float 65 | notContains: Float 66 | between: [Float] 67 | } 68 | 69 | input ModelBooleanFilterInput { 70 | ne: Boolean 71 | eq: Boolean 72 | } 73 | 74 | input ModelTodoFilterInput { 75 | id: ModelIDFilterInput 76 | name: ModelStringFilterInput 77 | description: ModelStringFilterInput 78 | time: ModelStringFilterInput 79 | completed: ModelBooleanFilterInput 80 | and: [ModelTodoFilterInput] 81 | or: [ModelTodoFilterInput] 82 | not: ModelTodoFilterInput 83 | } 84 | 85 | type Query { 86 | getTodo(id: ID!): Todo 87 | listTodos(filter: ModelTodoFilterInput, limit: Int, nextToken: String): ModelTodoConnection 88 | } 89 | 90 | input CreateTodoInput { 91 | id: ID 92 | name: String! 93 | description: String 94 | time: String 95 | completed: Boolean 96 | } 97 | 98 | input UpdateTodoInput { 99 | id: ID! 100 | name: String 101 | description: String 102 | time: String 103 | completed: Boolean 104 | } 105 | 106 | input DeleteTodoInput { 107 | id: ID 108 | } 109 | 110 | type Mutation { 111 | createTodo(input: CreateTodoInput!): Todo 112 | updateTodo(input: UpdateTodoInput!): Todo 113 | deleteTodo(input: DeleteTodoInput!): Todo 114 | } 115 | 116 | type Subscription { 117 | onCreateTodo: Todo @aws_subscribe(mutations: ["createTodo"]) 118 | onUpdateTodo: Todo @aws_subscribe(mutations: ["updateTodo"]) 119 | onDeleteTodo: Todo @aws_subscribe(mutations: ["deleteTodo"]) 120 | } 121 | -------------------------------------------------------------------------------- /amplify/backend/api/todoApi/schema.graphql: -------------------------------------------------------------------------------- 1 | type Todo @model { 2 | id: ID! 3 | name: String! 4 | description: String 5 | time: String 6 | completed: Boolean 7 | 8 | } -------------------------------------------------------------------------------- /amplify/backend/auth/amplifyprojectb3fea6ea/amplifyprojectb3fea6ea-cloudformation-template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | 3 | Parameters: 4 | env: 5 | Type: String 6 | authRoleArn: 7 | Type: String 8 | unauthRoleArn: 9 | Type: String 10 | 11 | 12 | 13 | 14 | identityPoolName: 15 | Type: String 16 | 17 | allowUnauthenticatedIdentities: 18 | Type: String 19 | 20 | resourceNameTruncated: 21 | Type: String 22 | 23 | userPoolName: 24 | Type: String 25 | 26 | autoVerifiedAttributes: 27 | Type: CommaDelimitedList 28 | 29 | mfaConfiguration: 30 | Type: String 31 | 32 | mfaTypes: 33 | Type: CommaDelimitedList 34 | 35 | smsAuthenticationMessage: 36 | Type: String 37 | 38 | smsVerificationMessage: 39 | Type: String 40 | 41 | emailVerificationSubject: 42 | Type: String 43 | 44 | emailVerificationMessage: 45 | Type: String 46 | 47 | defaultPasswordPolicy: 48 | Type: String 49 | 50 | passwordPolicyMinLength: 51 | Type: Number 52 | 53 | passwordPolicyCharacters: 54 | Type: CommaDelimitedList 55 | 56 | requiredAttributes: 57 | Type: CommaDelimitedList 58 | 59 | userpoolClientGenerateSecret: 60 | Type: String 61 | 62 | userpoolClientRefreshTokenValidity: 63 | Type: Number 64 | 65 | userpoolClientWriteAttributes: 66 | Type: CommaDelimitedList 67 | 68 | userpoolClientReadAttributes: 69 | Type: CommaDelimitedList 70 | 71 | userpoolClientLambdaRole: 72 | Type: String 73 | 74 | userpoolClientSetAttributes: 75 | Type: String 76 | 77 | resourceName: 78 | Type: String 79 | 80 | authSelections: 81 | Type: String 82 | 83 | useDefault: 84 | Type: String 85 | 86 | hostedUI: 87 | Type: String 88 | 89 | hostedUIDomainName: 90 | Type: String 91 | 92 | authProvidersUserPool: 93 | Type: CommaDelimitedList 94 | 95 | hostedUIProviderMeta: 96 | Type: String 97 | 98 | hostedUIProviderCreds: 99 | Type: String 100 | 101 | oAuthMetadata: 102 | Type: String 103 | 104 | dependsOn: 105 | Type: CommaDelimitedList 106 | 107 | Conditions: 108 | ShouldNotCreateEnvResources: !Equals [ !Ref env, NONE ] 109 | 110 | Resources: 111 | 112 | 113 | # BEGIN SNS ROLE RESOURCE 114 | SNSRole: 115 | # Created to allow the UserPool SMS Config to publish via the Simple Notification Service during MFA Process 116 | Type: AWS::IAM::Role 117 | Properties: 118 | RoleName: !If [ShouldNotCreateEnvResources, 'amplifb3fea6ea_sns-role', !Join ['',['amplifb3fea6ea_sns-role', '-', !Ref env]]] 119 | AssumeRolePolicyDocument: 120 | Version: "2012-10-17" 121 | Statement: 122 | - Sid: "" 123 | Effect: "Allow" 124 | Principal: 125 | Service: "cognito-idp.amazonaws.com" 126 | Action: 127 | - "sts:AssumeRole" 128 | Condition: 129 | StringEquals: 130 | sts:ExternalId: amplifb3fea6ea_role_external_id 131 | Policies: 132 | - 133 | PolicyName: amplifb3fea6ea-sns-policy 134 | PolicyDocument: 135 | Version: "2012-10-17" 136 | Statement: 137 | - 138 | Effect: "Allow" 139 | Action: 140 | - "sns:Publish" 141 | Resource: "*" 142 | # BEGIN USER POOL RESOURCES 143 | UserPool: 144 | # Created upon user selection 145 | # Depends on SNS Role for Arn if MFA is enabled 146 | Type: AWS::Cognito::UserPool 147 | UpdateReplacePolicy: Retain 148 | Properties: 149 | UserPoolName: !If [ShouldNotCreateEnvResources, !Ref userPoolName, !Join ['',[!Ref userPoolName, '-', !Ref env]]] 150 | 151 | Schema: 152 | 153 | - 154 | Name: email 155 | Required: true 156 | Mutable: true 157 | 158 | 159 | 160 | 161 | AutoVerifiedAttributes: !Ref autoVerifiedAttributes 162 | 163 | 164 | EmailVerificationMessage: !Ref emailVerificationMessage 165 | EmailVerificationSubject: !Ref emailVerificationSubject 166 | 167 | Policies: 168 | PasswordPolicy: 169 | MinimumLength: !Ref passwordPolicyMinLength 170 | RequireLowercase: false 171 | RequireNumbers: false 172 | RequireSymbols: false 173 | RequireUppercase: false 174 | 175 | MfaConfiguration: !Ref mfaConfiguration 176 | SmsVerificationMessage: !Ref smsVerificationMessage 177 | SmsConfiguration: 178 | SnsCallerArn: !GetAtt SNSRole.Arn 179 | ExternalId: amplifb3fea6ea_role_external_id 180 | 181 | 182 | UserPoolClientWeb: 183 | # Created provide application access to user pool 184 | # Depends on UserPool for ID reference 185 | Type: "AWS::Cognito::UserPoolClient" 186 | Properties: 187 | ClientName: amplifb3fea6ea_app_clientWeb 188 | 189 | RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity 190 | UserPoolId: !Ref UserPool 191 | DependsOn: UserPool 192 | UserPoolClient: 193 | # Created provide application access to user pool 194 | # Depends on UserPool for ID reference 195 | Type: "AWS::Cognito::UserPoolClient" 196 | Properties: 197 | ClientName: amplifb3fea6ea_app_client 198 | 199 | GenerateSecret: !Ref userpoolClientGenerateSecret 200 | RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity 201 | UserPoolId: !Ref UserPool 202 | DependsOn: UserPool 203 | # BEGIN USER POOL LAMBDA RESOURCES 204 | UserPoolClientRole: 205 | # Created to execute Lambda which gets userpool app client config values 206 | Type: 'AWS::IAM::Role' 207 | Properties: 208 | RoleName: !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',[!Ref userpoolClientLambdaRole, '-', !Ref env]]] 209 | AssumeRolePolicyDocument: 210 | Version: '2012-10-17' 211 | Statement: 212 | - Effect: Allow 213 | Principal: 214 | Service: 215 | - lambda.amazonaws.com 216 | Action: 217 | - 'sts:AssumeRole' 218 | DependsOn: UserPoolClient 219 | UserPoolClientLambda: 220 | # Lambda which gets userpool app client config values 221 | # Depends on UserPool for id 222 | # Depends on UserPoolClientRole for role ARN 223 | Type: 'AWS::Lambda::Function' 224 | Properties: 225 | Code: 226 | ZipFile: !Join 227 | - |+ 228 | - - 'const response = require(''cfn-response'');' 229 | - 'const aws = require(''aws-sdk'');' 230 | - 'const identity = new aws.CognitoIdentityServiceProvider();' 231 | - 'exports.handler = (event, context, callback) => {' 232 | - ' if (event.RequestType == ''Delete'') { ' 233 | - ' response.send(event, context, response.SUCCESS, {})' 234 | - ' }' 235 | - ' if (event.RequestType == ''Update'' || event.RequestType == ''Create'') {' 236 | - ' const params = {' 237 | - ' ClientId: event.ResourceProperties.clientId,' 238 | - ' UserPoolId: event.ResourceProperties.userpoolId' 239 | - ' };' 240 | - ' identity.describeUserPoolClient(params).promise()' 241 | - ' .then((res) => {' 242 | - ' response.send(event, context, response.SUCCESS, {''appSecret'': res.UserPoolClient.ClientSecret});' 243 | - ' })' 244 | - ' .catch((err) => {' 245 | - ' response.send(event, context, response.FAILED, {err});' 246 | - ' });' 247 | - ' }' 248 | - '};' 249 | Handler: index.handler 250 | Runtime: nodejs8.10 251 | Timeout: '300' 252 | Role: !GetAtt 253 | - UserPoolClientRole 254 | - Arn 255 | DependsOn: UserPoolClientRole 256 | UserPoolClientLambdaPolicy: 257 | # Sets userpool policy for the role that executes the Userpool Client Lambda 258 | # Depends on UserPool for Arn 259 | # Marked as depending on UserPoolClientRole for easier to understand CFN sequencing 260 | Type: 'AWS::IAM::Policy' 261 | Properties: 262 | PolicyName: amplifb3fea6ea_userpoolclient_lambda_iam_policy 263 | Roles: 264 | - !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',[!Ref userpoolClientLambdaRole, '-', !Ref env]]] 265 | PolicyDocument: 266 | Version: '2012-10-17' 267 | Statement: 268 | - Effect: Allow 269 | Action: 270 | - 'cognito-idp:DescribeUserPoolClient' 271 | Resource: !GetAtt UserPool.Arn 272 | DependsOn: UserPoolClientLambda 273 | UserPoolClientLogPolicy: 274 | # Sets log policy for the role that executes the Userpool Client Lambda 275 | # Depends on UserPool for Arn 276 | # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing 277 | Type: 'AWS::IAM::Policy' 278 | Properties: 279 | PolicyName: amplifb3fea6ea_userpoolclient_lambda_log_policy 280 | Roles: 281 | - !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',[!Ref userpoolClientLambdaRole, '-', !Ref env]]] 282 | PolicyDocument: 283 | Version: 2012-10-17 284 | Statement: 285 | - Effect: Allow 286 | Action: 287 | - 'logs:CreateLogGroup' 288 | - 'logs:CreateLogStream' 289 | - 'logs:PutLogEvents' 290 | Resource: !Sub 291 | - arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:* 292 | - { region: !Ref "AWS::Region", account: !Ref "AWS::AccountId", lambda: !Ref UserPoolClientLambda} 293 | DependsOn: UserPoolClientLambdaPolicy 294 | UserPoolClientInputs: 295 | # Values passed to Userpool client Lambda 296 | # Depends on UserPool for Id 297 | # Depends on UserPoolClient for Id 298 | # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing 299 | Type: 'Custom::LambdaCallout' 300 | Properties: 301 | ServiceToken: !GetAtt UserPoolClientLambda.Arn 302 | clientId: !Ref UserPoolClient 303 | userpoolId: !Ref UserPool 304 | DependsOn: UserPoolClientLogPolicy 305 | 306 | HostedUICustomResource: 307 | Type: 'AWS::Lambda::Function' 308 | Properties: 309 | Code: 310 | ZipFile: !Join 311 | - |+ 312 | - - 'const response = require(''cfn-response'');' 313 | - 'const aws = require(''aws-sdk'');' 314 | - 'const identity = new aws.CognitoIdentityServiceProvider();' 315 | - 'exports.handler = (event, context, callback) => {' 316 | - ' const userPoolId = event.ResourceProperties.userPoolId;' 317 | - ' const inputDomainName = event.ResourceProperties.hostedUIDomainName;' 318 | - ' let deleteUserPoolDomain = (domainName) => {' 319 | - ' let params = { Domain: domainName, UserPoolId: userPoolId };' 320 | - ' return identity.deleteUserPoolDomain(params).promise();' 321 | - ' };' 322 | - ' if (event.RequestType == ''Delete'') {' 323 | - ' deleteUserPoolDomain(inputDomainName)' 324 | - ' .then(() => {response.send(event, context, response.SUCCESS, {})})' 325 | - ' .catch((err) => { console.log(err); response.send(event, context, response.FAILED, {err}) });' 326 | - ' }' 327 | - ' if (event.RequestType == ''Update'' || event.RequestType == ''Create'') {' 328 | - ' let checkDomainAvailability = (domainName) => {' 329 | - ' let params = { Domain: domainName };' 330 | - ' return identity.describeUserPoolDomain(params).promise().then((res) => {' 331 | - ' if (res.DomainDescription && res.DomainDescription.UserPool) {' 332 | - ' return false;' 333 | - ' }' 334 | - ' return true;' 335 | - ' }).catch((err) => { return false; });' 336 | - ' };' 337 | - ' let createUserPoolDomain = (domainName) => {' 338 | - ' let params = { Domain: domainName, UserPoolId: userPoolId };' 339 | - ' return identity.createUserPoolDomain(params).promise();' 340 | - ' };' 341 | - ' identity.describeUserPool({UserPoolId: userPoolId }).promise().then((result) => {' 342 | - ' if (inputDomainName) {' 343 | - ' if (result.UserPool.Domain === inputDomainName) {' 344 | - ' return;' 345 | - ' } else {' 346 | - ' if (!result.UserPool.Domain) {' 347 | - ' return checkDomainAvailability(inputDomainName).then((isDomainAvailable) => {' 348 | - ' if (isDomainAvailable) {' 349 | - ' return createUserPoolDomain(inputDomainName);' 350 | - ' } else {' 351 | - ' throw new Error(''Domain not available'');' 352 | - ' }' 353 | - ' });' 354 | - ' } else {' 355 | - ' return checkDomainAvailability(inputDomainName).then((isDomainAvailable) => {' 356 | - ' if (isDomainAvailable) {' 357 | - ' return deleteUserPoolDomain(result.UserPool.Domain).then(() => createUserPoolDomain(inputDomainName));' 358 | - ' } else {' 359 | - ' throw new Error(''Domain not available'');' 360 | - ' }' 361 | - ' });' 362 | - ' }' 363 | - ' }' 364 | - ' } else {' 365 | - ' if (result.UserPool.Domain) {' 366 | - ' return deleteUserPoolDomain(result.UserPool.Domain);' 367 | - ' }' 368 | - ' }' 369 | - ' }).then(() => {response.send(event, context, response.SUCCESS, {})}).catch((err) => {' 370 | - ' console.log(err); response.send(event, context, response.FAILED, {err});' 371 | - ' });' 372 | - '}}' 373 | 374 | 375 | Handler: index.handler 376 | Runtime: nodejs8.10 377 | Timeout: '300' 378 | Role: !GetAtt 379 | - UserPoolClientRole 380 | - Arn 381 | DependsOn: UserPoolClientRole 382 | 383 | HostedUICustomResourcePolicy: 384 | Type: 'AWS::IAM::Policy' 385 | Properties: 386 | PolicyName: !Join ['-',[!Ref UserPool, 'hostedUI']] 387 | Roles: 388 | - !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',[!Ref userpoolClientLambdaRole, '-', !Ref env]]] 389 | PolicyDocument: 390 | Version: '2012-10-17' 391 | Statement: 392 | - Effect: Allow 393 | Action: 394 | - 'cognito-idp:CreateUserPoolDomain' 395 | - 'cognito-idp:DescribeUserPool' 396 | - 'cognito-idp:DeleteUserPoolDomain' 397 | Resource: !GetAtt UserPool.Arn 398 | - Effect: Allow 399 | Action: 400 | - 'cognito-idp:DescribeUserPoolDomain' 401 | Resource: '*' 402 | DependsOn: HostedUICustomResource 403 | HostedUICustomResourceLogPolicy: 404 | Type: 'AWS::IAM::Policy' 405 | Properties: 406 | PolicyName: !Join ['-',[!Ref UserPool, 'hostedUILogPolicy']] 407 | Roles: 408 | - !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',[!Ref userpoolClientLambdaRole, '-', !Ref env]]] 409 | PolicyDocument: 410 | Version: 2012-10-17 411 | Statement: 412 | - Effect: Allow 413 | Action: 414 | - 'logs:CreateLogGroup' 415 | - 'logs:CreateLogStream' 416 | - 'logs:PutLogEvents' 417 | Resource: !Sub 418 | - arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:* 419 | - { region: !Ref "AWS::Region", account: !Ref "AWS::AccountId", lambda: !Ref HostedUICustomResource} 420 | DependsOn: HostedUICustomResourcePolicy 421 | HostedUICustomResourceInputs: 422 | Type: 'Custom::LambdaCallout' 423 | Properties: 424 | ServiceToken: !GetAtt HostedUICustomResource.Arn 425 | userPoolId: !Ref UserPool 426 | hostedUIDomainName: !If [ShouldNotCreateEnvResources, !Ref hostedUIDomainName, !Join ['-',[!Ref hostedUIDomainName, !Ref env]]] 427 | DependsOn: HostedUICustomResourceLogPolicy 428 | 429 | 430 | 431 | HostedUIProvidersCustomResource: 432 | Type: 'AWS::Lambda::Function' 433 | Properties: 434 | Code: 435 | ZipFile: !Join 436 | - |+ 437 | - - 'const response = require(''cfn-response'');' 438 | - 'const aws = require(''aws-sdk'');' 439 | - 'const identity = new aws.CognitoIdentityServiceProvider();' 440 | - 'exports.handler = (event, context, callback) => {' 441 | - 'try{' 442 | - ' const userPoolId = event.ResourceProperties.userPoolId;' 443 | - ' let hostedUIProviderMeta = JSON.parse(event.ResourceProperties.hostedUIProviderMeta);' 444 | - ' let hostedUIProviderCreds = JSON.parse(event.ResourceProperties.hostedUIProviderCreds);' 445 | - ' if (event.RequestType == ''Delete'') {' 446 | - ' response.send(event, context, response.SUCCESS, {});' 447 | - ' }' 448 | - ' if (event.RequestType == ''Update'' || event.RequestType == ''Create'') {' 449 | - ' let getRequestParams = (providerName) => {' 450 | - ' let providerMetaIndex = hostedUIProviderMeta.findIndex((provider) => provider.ProviderName === providerName);' 451 | - ' let providerMeta = hostedUIProviderMeta[providerMetaIndex];' 452 | - ' let providerCredsIndex = hostedUIProviderCreds.findIndex((provider) => provider.ProviderName === providerName);' 453 | - ' let providerCreds = hostedUIProviderCreds[providerCredsIndex];' 454 | - ' let requestParams = {' 455 | - ' ProviderDetails: {' 456 | - ' ''client_id'': providerCreds.client_id,' 457 | - ' ''client_secret'': providerCreds.client_secret,' 458 | - ' ''authorize_scopes'': providerMeta.authorize_scopes' 459 | - ' },' 460 | - ' ProviderName: providerMeta.ProviderName,' 461 | - ' UserPoolId: userPoolId,' 462 | - ' AttributeMapping: providerMeta.AttributeMapping' 463 | - ' };' 464 | - ' return requestParams;' 465 | - ' };' 466 | - ' let createIdentityProvider = (providerName) => {' 467 | - ' let requestParams = getRequestParams(providerName);' 468 | - ' requestParams.ProviderType = requestParams.ProviderName;' 469 | - ' return identity.createIdentityProvider(requestParams).promise();' 470 | - ' };' 471 | - ' let updateIdentityProvider = (providerName) => {' 472 | - ' let requestParams = getRequestParams(providerName);' 473 | - ' return identity.updateIdentityProvider(requestParams).promise();' 474 | - ' };' 475 | - ' let deleteIdentityProvider = (providerName) => {' 476 | - ' let params = {ProviderName: providerName, UserPoolId: userPoolId};' 477 | - ' return identity.deleteIdentityProvider(params).promise();' 478 | - ' };' 479 | - ' let providerPromises = [];' 480 | - ' identity.listIdentityProviders({UserPoolId: userPoolId, MaxResults: 60}).promise()' 481 | - ' .then((result) => {' 482 | - ' let providerList = result.Providers.map(provider => provider.ProviderName);' 483 | - ' let providerListInParameters = hostedUIProviderMeta.map(provider => provider.ProviderName);' 484 | - ' hostedUIProviderMeta.forEach((providerMetadata) => {' 485 | - ' if(providerList.indexOf(providerMetadata.ProviderName) > -1) {' 486 | - ' providerPromises.push(updateIdentityProvider(providerMetadata.ProviderName));' 487 | - ' } else {' 488 | - ' providerPromises.push(createIdentityProvider(providerMetadata.ProviderName));' 489 | - ' }' 490 | - ' });' 491 | - ' providerList.forEach((provider) => {' 492 | - ' if(providerListInParameters.indexOf(provider) < 0) {' 493 | - ' providerPromises.push(deleteIdentityProvider(provider));' 494 | - ' }' 495 | - ' });' 496 | - ' return Promise.all(providerPromises);' 497 | - ' }).then(() => {response.send(event, context, response.SUCCESS, {})}).catch((err) => {' 498 | - ' console.log(err.stack); response.send(event, context, response.FAILED, {err})' 499 | - ' });' 500 | - ' } ' 501 | - ' } catch(err) { console.log(err.stack); response.send(event, context, response.FAILED, {err});};' 502 | - '} ' 503 | 504 | Handler: index.handler 505 | Runtime: nodejs8.10 506 | Timeout: '300' 507 | Role: !GetAtt 508 | - UserPoolClientRole 509 | - Arn 510 | DependsOn: UserPoolClientRole 511 | 512 | HostedUIProvidersCustomResourcePolicy: 513 | Type: 'AWS::IAM::Policy' 514 | Properties: 515 | PolicyName: !Join ['-',[!Ref UserPool, 'hostedUIProvider']] 516 | Roles: 517 | - !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',[!Ref userpoolClientLambdaRole, '-', !Ref env]]] 518 | PolicyDocument: 519 | Version: '2012-10-17' 520 | Statement: 521 | - Effect: Allow 522 | Action: 523 | - 'cognito-idp:CreateIdentityProvider' 524 | - 'cognito-idp:UpdateIdentityProvider' 525 | - 'cognito-idp:ListIdentityProviders' 526 | - 'cognito-idp:DeleteIdentityProvider' 527 | Resource: !GetAtt UserPool.Arn 528 | DependsOn: HostedUIProvidersCustomResource 529 | 530 | HostedUIProvidersCustomResourceLogPolicy: 531 | Type: 'AWS::IAM::Policy' 532 | Properties: 533 | PolicyName: !Join ['-',[!Ref UserPool, 'hostedUIProviderLogPolicy']] 534 | Roles: 535 | - !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',[!Ref userpoolClientLambdaRole, '-', !Ref env]]] 536 | PolicyDocument: 537 | Version: 2012-10-17 538 | Statement: 539 | - Effect: Allow 540 | Action: 541 | - 'logs:CreateLogGroup' 542 | - 'logs:CreateLogStream' 543 | - 'logs:PutLogEvents' 544 | Resource: !Sub 545 | - arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:* 546 | - { region: !Ref "AWS::Region", account: !Ref "AWS::AccountId", lambda: !Ref HostedUIProvidersCustomResource} 547 | DependsOn: HostedUIProvidersCustomResourcePolicy 548 | 549 | HostedUIProvidersCustomResourceInputs: 550 | Type: 'Custom::LambdaCallout' 551 | Properties: 552 | ServiceToken: !GetAtt HostedUIProvidersCustomResource.Arn 553 | userPoolId: !Ref UserPool 554 | hostedUIProviderMeta: !Ref hostedUIProviderMeta 555 | hostedUIProviderCreds: !Ref hostedUIProviderCreds 556 | DependsOn: HostedUIProvidersCustomResourceLogPolicy 557 | 558 | 559 | OAuthCustomResource: 560 | Type: 'AWS::Lambda::Function' 561 | Properties: 562 | Code: 563 | ZipFile: !Join 564 | - |+ 565 | - - 'const response = require(''cfn-response'');' 566 | - 'const aws = require(''aws-sdk'');' 567 | - 'const identity = new aws.CognitoIdentityServiceProvider();' 568 | - 'exports.handler = (event, context, callback) => {' 569 | - 'try{' 570 | - ' const userPoolId = event.ResourceProperties.userPoolId;' 571 | - ' let webClientId = event.ResourceProperties.webClientId;' 572 | - ' let nativeClientId = event.ResourceProperties.nativeClientId;' 573 | - ' let hostedUIProviderMeta = JSON.parse(event.ResourceProperties.hostedUIProviderMeta);' 574 | - ' let oAuthMetadata = JSON.parse(event.ResourceProperties.oAuthMetadata);' 575 | - ' let providerList = hostedUIProviderMeta.map(provider => provider.ProviderName);' 576 | - ' providerList.push(''COGNITO'');' 577 | - ' if (event.RequestType == ''Delete'') {' 578 | - ' response.send(event, context, response.SUCCESS, {});' 579 | - ' }' 580 | - ' if (event.RequestType == ''Update'' || event.RequestType == ''Create'') {' 581 | - ' let params = {' 582 | - ' UserPoolId: userPoolId,' 583 | - ' AllowedOAuthFlows: oAuthMetadata.AllowedOAuthFlows,' 584 | - ' AllowedOAuthFlowsUserPoolClient: true,' 585 | - ' AllowedOAuthScopes: oAuthMetadata.AllowedOAuthScopes,' 586 | - ' CallbackURLs: oAuthMetadata.CallbackURLs,' 587 | - ' LogoutURLs: oAuthMetadata.LogoutURLs,' 588 | - ' SupportedIdentityProviders: providerList' 589 | - ' };' 590 | - ' let updateUserPoolClientPromises = [];' 591 | - ' params.ClientId = webClientId;' 592 | - ' updateUserPoolClientPromises.push(identity.updateUserPoolClient(params).promise());' 593 | - ' params.ClientId = nativeClientId;' 594 | - ' updateUserPoolClientPromises.push(identity.updateUserPoolClient(params).promise());' 595 | - ' Promise.all(updateUserPoolClientPromises)' 596 | - ' .then(() => {response.send(event, context, response.SUCCESS, {})}).catch((err) => {' 597 | - ' console.log(err.stack); response.send(event, context, response.FAILED, {err});' 598 | - ' });' 599 | - ' }' 600 | - '} catch(err) { console.log(err.stack); response.send(event, context, response.FAILED, {err});};' 601 | - '}' 602 | 603 | Handler: index.handler 604 | Runtime: nodejs8.10 605 | Timeout: '300' 606 | Role: !GetAtt 607 | - UserPoolClientRole 608 | - Arn 609 | DependsOn: HostedUIProvidersCustomResourceInputs 610 | 611 | OAuthCustomResourcePolicy: 612 | Type: 'AWS::IAM::Policy' 613 | Properties: 614 | PolicyName: !Join ['-',[!Ref UserPool, 'OAuth']] 615 | Roles: 616 | - !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',[!Ref userpoolClientLambdaRole, '-', !Ref env]]] 617 | PolicyDocument: 618 | Version: '2012-10-17' 619 | Statement: 620 | - Effect: Allow 621 | Action: 622 | - 'cognito-idp:UpdateUserPoolClient' 623 | Resource: !GetAtt UserPool.Arn 624 | DependsOn: OAuthCustomResource 625 | 626 | OAuthCustomResourceLogPolicy: 627 | Type: 'AWS::IAM::Policy' 628 | Properties: 629 | PolicyName: !Join ['-',[!Ref UserPool, 'OAuthLogPolicy']] 630 | Roles: 631 | - !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',[!Ref userpoolClientLambdaRole, '-', !Ref env]]] 632 | PolicyDocument: 633 | Version: 2012-10-17 634 | Statement: 635 | - Effect: Allow 636 | Action: 637 | - 'logs:CreateLogGroup' 638 | - 'logs:CreateLogStream' 639 | - 'logs:PutLogEvents' 640 | Resource: !Sub 641 | - arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:* 642 | - { region: !Ref "AWS::Region", account: !Ref "AWS::AccountId", lambda: !Ref OAuthCustomResource} 643 | DependsOn: OAuthCustomResourcePolicy 644 | 645 | OAuthCustomResourceInputs: 646 | Type: 'Custom::LambdaCallout' 647 | Properties: 648 | ServiceToken: !GetAtt OAuthCustomResource.Arn 649 | userPoolId: !Ref UserPool 650 | hostedUIProviderMeta: !Ref hostedUIProviderMeta 651 | oAuthMetadata: !Ref oAuthMetadata 652 | webClientId: !Ref 'UserPoolClientWeb' 653 | nativeClientId: !Ref 'UserPoolClient' 654 | DependsOn: OAuthCustomResourceLogPolicy 655 | 656 | 657 | 658 | 659 | # BEGIN IDENTITY POOL RESOURCES 660 | 661 | 662 | IdentityPool: 663 | # Always created 664 | Type: AWS::Cognito::IdentityPool 665 | Properties: 666 | IdentityPoolName: !If [ShouldNotCreateEnvResources, 'amplifyprojectb3fea6ea_identitypool_b3fea6ea', !Join ['',['amplifyprojectb3fea6ea_identitypool_b3fea6ea', '__', !Ref env]]] 667 | 668 | CognitoIdentityProviders: 669 | - ClientId: !Ref UserPoolClient 670 | ProviderName: !Sub 671 | - cognito-idp.${region}.amazonaws.com/${client} 672 | - { region: !Ref "AWS::Region", client: !Ref UserPool} 673 | - ClientId: !Ref UserPoolClientWeb 674 | ProviderName: !Sub 675 | - cognito-idp.${region}.amazonaws.com/${client} 676 | - { region: !Ref "AWS::Region", client: !Ref UserPool} 677 | 678 | AllowUnauthenticatedIdentities: !Ref allowUnauthenticatedIdentities 679 | 680 | 681 | DependsOn: UserPoolClientInputs 682 | 683 | 684 | IdentityPoolRoleMap: 685 | # Created to map Auth and Unauth roles to the identity pool 686 | # Depends on Identity Pool for ID ref 687 | Type: AWS::Cognito::IdentityPoolRoleAttachment 688 | Properties: 689 | IdentityPoolId: !Ref IdentityPool 690 | Roles: 691 | unauthenticated: !Ref unauthRoleArn 692 | authenticated: !Ref authRoleArn 693 | DependsOn: IdentityPool 694 | 695 | 696 | Outputs : 697 | 698 | IdentityPoolId: 699 | Value: !Ref 'IdentityPool' 700 | Description: Id for the identity pool 701 | IdentityPoolName: 702 | Value: !GetAtt IdentityPool.Name 703 | 704 | 705 | HostedUIDomain: 706 | Value: !If [ShouldNotCreateEnvResources, !Ref hostedUIDomainName, !Join ['-',[!Ref hostedUIDomainName, !Ref env]]] 707 | 708 | 709 | OAuthMetadata: 710 | Value: !Ref oAuthMetadata 711 | 712 | 713 | UserPoolId: 714 | Value: !Ref 'UserPool' 715 | Description: Id for the user pool 716 | UserPoolName: 717 | Value: !Ref userPoolName 718 | AppClientIDWeb: 719 | Value: !Ref 'UserPoolClientWeb' 720 | Description: The user pool app client id for web 721 | AppClientID: 722 | Value: !Ref 'UserPoolClient' 723 | Description: The user pool app client id 724 | AppClientSecret: 725 | Value: !GetAtt UserPoolClientInputs.appSecret 726 | 727 | 728 | 729 | 730 | 731 | 732 | -------------------------------------------------------------------------------- /amplify/backend/auth/amplifyprojectb3fea6ea/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "identityPoolName": "amplifyprojectb3fea6ea_identitypool_b3fea6ea", 3 | "allowUnauthenticatedIdentities": false, 4 | "resourceNameTruncated": "amplifb3fea6ea", 5 | "userPoolName": "amplifyprojectb3fea6ea_userpool_b3fea6ea", 6 | "autoVerifiedAttributes": [ 7 | "email" 8 | ], 9 | "mfaConfiguration": "OFF", 10 | "mfaTypes": [ 11 | "SMS Text Message" 12 | ], 13 | "smsAuthenticationMessage": "Your authentication code is {####}", 14 | "smsVerificationMessage": "Your verification code is {####}", 15 | "emailVerificationSubject": "Your verification code", 16 | "emailVerificationMessage": "Your verification code is {####}", 17 | "defaultPasswordPolicy": false, 18 | "passwordPolicyMinLength": 8, 19 | "passwordPolicyCharacters": [], 20 | "requiredAttributes": [ 21 | "email" 22 | ], 23 | "userpoolClientGenerateSecret": true, 24 | "userpoolClientRefreshTokenValidity": 30, 25 | "userpoolClientWriteAttributes": [ 26 | "email" 27 | ], 28 | "userpoolClientReadAttributes": [ 29 | "email" 30 | ], 31 | "userpoolClientLambdaRole": "amplifb3fea6ea_userpoolclient_lambda_role", 32 | "userpoolClientSetAttributes": false, 33 | "resourceName": "amplifyprojectb3fea6ea", 34 | "authSelections": "identityPoolAndUserPool", 35 | "authRoleArn": { 36 | "Fn::GetAtt": [ 37 | "AuthRole", 38 | "Arn" 39 | ] 40 | }, 41 | "unauthRoleArn": { 42 | "Fn::GetAtt": [ 43 | "UnauthRole", 44 | "Arn" 45 | ] 46 | }, 47 | "useDefault": "defaultSocial", 48 | "hostedUI": true, 49 | "hostedUIDomainName": "amplifyprojectb3fea6ea-b3fea6ea", 50 | "authProvidersUserPool": [ 51 | "Facebook", 52 | "Google", 53 | "LoginWithAmazon" 54 | ], 55 | "hostedUIProviderMeta": "[{\"ProviderName\":\"Facebook\",\"authorize_scopes\":\"email,public_profile\",\"AttributeMapping\":{\"email\":\"email\",\"username\":\"id\"}},{\"ProviderName\":\"Google\",\"authorize_scopes\":\"openid email profile\",\"AttributeMapping\":{\"email\":\"email\",\"username\":\"sub\"}},{\"ProviderName\":\"LoginWithAmazon\",\"authorize_scopes\":\"profile profile:user_id\",\"AttributeMapping\":{\"email\":\"email\",\"username\":\"user_id\"}}]", 56 | "oAuthMetadata": "{\"AllowedOAuthFlows\":[\"code\"],\"AllowedOAuthScopes\":[\"phone\",\"email\",\"openid\",\"profile\",\"aws.cognito.signin.user.admin\"],\"CallbackURLs\":[\"https://192.168.0.80:19006/\"],\"LogoutURLs\":[\"https://192.168.0.80:19006/\"]}", 57 | "dependsOn": [] 58 | } -------------------------------------------------------------------------------- /amplify/backend/awscloudformation/nested-cloudformation-stack.yml: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Description": "Root stack for the Amplify AWS CloudFormation provider", 4 | "Parameters": { 5 | "DeploymentBucketName": { 6 | "Description": "Name of the common deployment bucket provided by the parent stack", 7 | "Type": "String", 8 | "Default": "DeploymentBucket" 9 | }, 10 | "AuthRoleName": { 11 | "Type": "String", 12 | "Default": "AuthRoleName" 13 | }, 14 | "UnauthRoleName": { 15 | "Type": "String", 16 | "Default": "UnauthRoleName" 17 | } 18 | }, 19 | "Resources": { 20 | "DeploymentBucket": { 21 | "Type": "AWS::S3::Bucket", 22 | "DeletionPolicy": "Retain", 23 | "Properties": { 24 | "BucketName": { 25 | "Ref": "DeploymentBucketName" 26 | } 27 | } 28 | }, 29 | "AuthRole": { 30 | "Type": "AWS::IAM::Role", 31 | "Properties": { 32 | "RoleName": { 33 | "Ref": "AuthRoleName" 34 | }, 35 | "AssumeRolePolicyDocument": { 36 | "Version": "2012-10-17", 37 | "Statement": [ 38 | { 39 | "Sid": "", 40 | "Effect": "Deny", 41 | "Principal": { 42 | "Federated": "cognito-identity.amazonaws.com" 43 | }, 44 | "Action": "sts:AssumeRoleWithWebIdentity" 45 | } 46 | ] 47 | } 48 | } 49 | }, 50 | "UnauthRole": { 51 | "Type": "AWS::IAM::Role", 52 | "Properties": { 53 | "RoleName": { 54 | "Ref": "UnauthRoleName" 55 | }, 56 | "AssumeRolePolicyDocument": { 57 | "Version": "2012-10-17", 58 | "Statement": [ 59 | { 60 | "Sid": "", 61 | "Effect": "Deny", 62 | "Principal": { 63 | "Federated": "cognito-identity.amazonaws.com" 64 | }, 65 | "Action": "sts:AssumeRoleWithWebIdentity" 66 | } 67 | ] 68 | } 69 | } 70 | }, 71 | "apitodoApi": { 72 | "Type": "AWS::CloudFormation::Stack", 73 | "Properties": { 74 | "TemplateURL": "https://s3.amazonaws.com/amplifyproject-test-20190919143906-deployment/amplify-cfn-templates/api/cloudformation-template.json", 75 | "Parameters": { 76 | "CreateAPIKey": 1, 77 | "AppSyncApiName": "todoApi", 78 | "DynamoDBBillingMode": "PAY_PER_REQUEST", 79 | "DynamoDBEnableServerSideEncryption": "false", 80 | "S3DeploymentBucket": "amplifyproject-test-20190919143906-deployment", 81 | "S3DeploymentRootKey": "amplify-appsync-files/4b4b159fa3fedb4ab8ed48d581bcb35cf038c826", 82 | "env": "test" 83 | } 84 | } 85 | }, 86 | "authamplifyprojectb3fea6ea": { 87 | "Type": "AWS::CloudFormation::Stack", 88 | "Properties": { 89 | "TemplateURL": "https://s3.amazonaws.com/amplifyproject-test-20190919143906-deployment/amplify-cfn-templates/auth/amplifyprojectb3fea6ea-cloudformation-template.yml", 90 | "Parameters": { 91 | "identityPoolName": "amplifyprojectb3fea6ea_identitypool_b3fea6ea", 92 | "allowUnauthenticatedIdentities": false, 93 | "resourceNameTruncated": "amplifb3fea6ea", 94 | "userPoolName": "amplifyprojectb3fea6ea_userpool_b3fea6ea", 95 | "autoVerifiedAttributes": "email", 96 | "mfaConfiguration": "OFF", 97 | "mfaTypes": "SMS Text Message", 98 | "smsAuthenticationMessage": "Your authentication code is {####}", 99 | "smsVerificationMessage": "Your verification code is {####}", 100 | "emailVerificationSubject": "Your verification code", 101 | "emailVerificationMessage": "Your verification code is {####}", 102 | "defaultPasswordPolicy": false, 103 | "passwordPolicyMinLength": 8, 104 | "passwordPolicyCharacters": "", 105 | "requiredAttributes": "email", 106 | "userpoolClientGenerateSecret": true, 107 | "userpoolClientRefreshTokenValidity": 30, 108 | "userpoolClientWriteAttributes": "email", 109 | "userpoolClientReadAttributes": "email", 110 | "userpoolClientLambdaRole": "amplifb3fea6ea_userpoolclient_lambda_role", 111 | "userpoolClientSetAttributes": false, 112 | "resourceName": "amplifyprojectb3fea6ea", 113 | "authSelections": "identityPoolAndUserPool", 114 | "authRoleArn": { 115 | "Fn::GetAtt": [ 116 | "AuthRole", 117 | "Arn" 118 | ] 119 | }, 120 | "unauthRoleArn": { 121 | "Fn::GetAtt": [ 122 | "UnauthRole", 123 | "Arn" 124 | ] 125 | }, 126 | "useDefault": "defaultSocial", 127 | "hostedUI": true, 128 | "hostedUIDomainName": "amplifyprojectb3fea6ea-b3fea6ea", 129 | "authProvidersUserPool": "Facebook,Google,LoginWithAmazon", 130 | "hostedUIProviderMeta": "[{\"ProviderName\":\"Facebook\",\"authorize_scopes\":\"email,public_profile\",\"AttributeMapping\":{\"email\":\"email\",\"username\":\"id\"}},{\"ProviderName\":\"Google\",\"authorize_scopes\":\"openid email profile\",\"AttributeMapping\":{\"email\":\"email\",\"username\":\"sub\"}},{\"ProviderName\":\"LoginWithAmazon\",\"authorize_scopes\":\"profile profile:user_id\",\"AttributeMapping\":{\"email\":\"email\",\"username\":\"user_id\"}}]", 131 | "oAuthMetadata": "{\"AllowedOAuthFlows\":[\"code\"],\"AllowedOAuthScopes\":[\"phone\",\"email\",\"openid\",\"profile\",\"aws.cognito.signin.user.admin\"],\"CallbackURLs\":[\"https://192.168.0.80:19006/\"],\"LogoutURLs\":[\"https://192.168.0.80:19006/\"]}", 132 | "dependsOn": "", 133 | "hostedUIProviderCreds": "[{\"ProviderName\":\"Facebook\",\"client_id\":\"394347568157898\",\"client_secret\":\"dc2cd59e4b92c604344015e0035dc062\"},{\"ProviderName\":\"Google\",\"client_id\":\"86848591885-pcvo4gsh7dfq09o7igoeacrhqdko5o2g.apps.googleusercontent.com\",\"client_secret\":\"lkuzCgvOYtsheVaP8P8BI9_t\"},{\"ProviderName\":\"LoginWithAmazon\",\"client_id\":\"amzn1.application-oa2-client.30d31882e1794c68b4984697305c0e43\",\"client_secret\":\"d8b9e79ca1eb83d40b2a0e85db3280c7b49a8252a322373e4dfb09b0c4c3557e\"}]", 134 | "env": "test" 135 | } 136 | } 137 | }, 138 | "UpdateRolesWithIDPFunction": { 139 | "DependsOn": [ 140 | "AuthRole", 141 | "UnauthRole", 142 | "authamplifyprojectb3fea6ea" 143 | ], 144 | "Type": "AWS::Lambda::Function", 145 | "Properties": { 146 | "Code": { 147 | "ZipFile": { 148 | "Fn::Join": [ 149 | "\n", 150 | [ 151 | "const response = require('cfn-response');", 152 | "const aws = require('aws-sdk');", 153 | "let responseData = {};", 154 | "exports.handler = function(event, context) {", 155 | " try {", 156 | " let authRoleName = event.ResourceProperties.authRoleName;", 157 | " let unauthRoleName = event.ResourceProperties.unauthRoleName;", 158 | " let idpId = event.ResourceProperties.idpId;", 159 | " let promises = [];", 160 | " let authParamsJson = { 'Version': '2012-10-17','Statement': [{'Effect': 'Allow','Principal': {'Federated': 'cognito-identity.amazonaws.com'},'Action': 'sts:AssumeRoleWithWebIdentity','Condition': {'StringEquals': {'cognito-identity.amazonaws.com:aud': idpId},'ForAnyValue:StringLike': {'cognito-identity.amazonaws.com:amr': 'authenticated'}}}]};", 161 | " let unauthParamsJson = { 'Version': '2012-10-17','Statement': [{'Effect': 'Allow','Principal': {'Federated': 'cognito-identity.amazonaws.com'},'Action': 'sts:AssumeRoleWithWebIdentity','Condition': {'StringEquals': {'cognito-identity.amazonaws.com:aud': idpId},'ForAnyValue:StringLike': {'cognito-identity.amazonaws.com:amr': 'unauthenticated'}}}]};", 162 | " if (event.RequestType == 'Delete') {", 163 | " delete authParamsJson.Statement.Condition;", 164 | " delete unauthParamsJson.Statement.Condition;", 165 | " let authParams = { PolicyDocument: JSON.stringify(authParamsJson),RoleName: authRoleName};", 166 | " let unauthParams = {PolicyDocument: JSON.stringify(unauthParamsJson),RoleName: unauthRoleName};", 167 | " const iam = new aws.IAM({ apiVersion: '2010-05-08', region: event.ResourceProperties.region});", 168 | " promises.push(iam.updateAssumeRolePolicy(authParams).promise());", 169 | " promises.push(iam.updateAssumeRolePolicy(unauthParams).promise());", 170 | " Promise.all(promises)", 171 | " .then((res) => {", 172 | " console.log(\"delete\" + res);", 173 | " console.log(\"response data\" + JSON.stringify(res));", 174 | " response.send(event, context, response.SUCCESS, res);", 175 | " });", 176 | " }", 177 | " if (event.RequestType == 'Update' || event.RequestType == 'Create') {", 178 | " const iam = new aws.IAM({ apiVersion: '2010-05-08', region: event.ResourceProperties.region});", 179 | " let authParams = { PolicyDocument: JSON.stringify(authParamsJson),RoleName: authRoleName};", 180 | " let unauthParams = {PolicyDocument: JSON.stringify(unauthParamsJson),RoleName: unauthRoleName};", 181 | " promises.push(iam.updateAssumeRolePolicy(authParams).promise());", 182 | " promises.push(iam.updateAssumeRolePolicy(unauthParams).promise());", 183 | " Promise.all(promises)", 184 | " .then((res) => {", 185 | " console.log(\"createORupdate\" + res);", 186 | " console.log(\"response data\" + JSON.stringify(res));", 187 | " response.send(event, context, response.SUCCESS, {});", 188 | " });", 189 | " }", 190 | " } catch(err) {", 191 | " console.log(err.stack);", 192 | " responseData = {Error: err};", 193 | " response.send(event, context, response.FAILED, responseData);", 194 | " throw err;", 195 | " }", 196 | "};" 197 | ] 198 | ] 199 | } 200 | }, 201 | "Handler": "index.handler", 202 | "Runtime": "nodejs8.10", 203 | "Timeout": "300", 204 | "Role": { 205 | "Fn::GetAtt": [ 206 | "UpdateRolesWithIDPFunctionRole", 207 | "Arn" 208 | ] 209 | } 210 | } 211 | }, 212 | "UpdateRolesWithIDPFunctionOutputs": { 213 | "Type": "Custom::LambdaCallout", 214 | "Properties": { 215 | "ServiceToken": { 216 | "Fn::GetAtt": [ 217 | "UpdateRolesWithIDPFunction", 218 | "Arn" 219 | ] 220 | }, 221 | "region": { 222 | "Ref": "AWS::Region" 223 | }, 224 | "idpId": { 225 | "Fn::GetAtt": [ 226 | "authamplifyprojectb3fea6ea", 227 | "Outputs.IdentityPoolId" 228 | ] 229 | }, 230 | "authRoleName": { 231 | "Ref": "AuthRoleName" 232 | }, 233 | "unauthRoleName": { 234 | "Ref": "UnauthRoleName" 235 | } 236 | } 237 | }, 238 | "UpdateRolesWithIDPFunctionRole": { 239 | "Type": "AWS::IAM::Role", 240 | "Properties": { 241 | "RoleName": { 242 | "Fn::Join": [ 243 | "", 244 | [ 245 | { 246 | "Ref": "AuthRoleName" 247 | }, 248 | "-idp" 249 | ] 250 | ] 251 | }, 252 | "AssumeRolePolicyDocument": { 253 | "Version": "2012-10-17", 254 | "Statement": [ 255 | { 256 | "Effect": "Allow", 257 | "Principal": { 258 | "Service": [ 259 | "lambda.amazonaws.com" 260 | ] 261 | }, 262 | "Action": [ 263 | "sts:AssumeRole" 264 | ] 265 | } 266 | ] 267 | }, 268 | "Policies": [ 269 | { 270 | "PolicyName": "UpdateRolesWithIDPFunctionPolicy", 271 | "PolicyDocument": { 272 | "Version": "2012-10-17", 273 | "Statement": [ 274 | { 275 | "Effect": "Allow", 276 | "Action": [ 277 | "logs:CreateLogGroup", 278 | "logs:CreateLogStream", 279 | "logs:PutLogEvents" 280 | ], 281 | "Resource": "arn:aws:logs:*:*:*" 282 | }, 283 | { 284 | "Effect": "Allow", 285 | "Action": "iam:UpdateAssumeRolePolicy", 286 | "Resource": { 287 | "Fn::GetAtt": [ 288 | "AuthRole", 289 | "Arn" 290 | ] 291 | } 292 | }, 293 | { 294 | "Effect": "Allow", 295 | "Action": "iam:UpdateAssumeRolePolicy", 296 | "Resource": { 297 | "Fn::GetAtt": [ 298 | "UnauthRole", 299 | "Arn" 300 | ] 301 | } 302 | } 303 | ] 304 | } 305 | } 306 | ] 307 | } 308 | } 309 | }, 310 | "Outputs": { 311 | "Region": { 312 | "Description": "CloudFormation provider root stack Region", 313 | "Value": { 314 | "Ref": "AWS::Region" 315 | }, 316 | "Export": { 317 | "Name": { 318 | "Fn::Sub": "${AWS::StackName}-Region" 319 | } 320 | } 321 | }, 322 | "StackName": { 323 | "Description": "CloudFormation provider root stack ID", 324 | "Value": { 325 | "Ref": "AWS::StackName" 326 | }, 327 | "Export": { 328 | "Name": { 329 | "Fn::Sub": "${AWS::StackName}-StackName" 330 | } 331 | } 332 | }, 333 | "StackId": { 334 | "Description": "CloudFormation provider root stack name", 335 | "Value": { 336 | "Ref": "AWS::StackId" 337 | }, 338 | "Export": { 339 | "Name": { 340 | "Fn::Sub": "${AWS::StackName}-StackId" 341 | } 342 | } 343 | }, 344 | "DeploymentBucketName": { 345 | "Description": "CloudFormation provider root stack deployment bucket name", 346 | "Value": { 347 | "Ref": "DeploymentBucketName" 348 | }, 349 | "Export": { 350 | "Name": { 351 | "Fn::Sub": "${AWS::StackName}-DeploymentBucketName" 352 | } 353 | } 354 | }, 355 | "AuthRoleArn": { 356 | "Value": { 357 | "Fn::GetAtt": [ 358 | "AuthRole", 359 | "Arn" 360 | ] 361 | } 362 | }, 363 | "UnauthRoleArn": { 364 | "Value": { 365 | "Fn::GetAtt": [ 366 | "UnauthRole", 367 | "Arn" 368 | ] 369 | } 370 | }, 371 | "AuthRoleName": { 372 | "Value": { 373 | "Ref": "AuthRole" 374 | } 375 | }, 376 | "UnauthRoleName": { 377 | "Value": { 378 | "Ref": "UnauthRole" 379 | } 380 | } 381 | } 382 | } -------------------------------------------------------------------------------- /amplify/backend/backend-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "api": { 3 | "todoApi": { 4 | "service": "AppSync", 5 | "providerPlugin": "awscloudformation", 6 | "output": { 7 | "authConfig": { 8 | "additionalAuthenticationProviders": [], 9 | "defaultAuthentication": { 10 | "authenticationType": "API_KEY", 11 | "apiKeyConfig": { 12 | "description": "API key desc", 13 | "apiKeyExpirationDays": 180 14 | } 15 | } 16 | } 17 | } 18 | } 19 | }, 20 | "auth": { 21 | "amplifyprojectb3fea6ea": { 22 | "service": "Cognito", 23 | "providerPlugin": "awscloudformation", 24 | "dependsOn": [] 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /amplify/team-provider-info.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": { 3 | "awscloudformation": { 4 | "AuthRoleName": "amplifyproject-test-20190919143906-authRole", 5 | "UnauthRoleArn": "arn:aws:iam::082042224423:role/amplifyproject-test-20190919143906-unauthRole", 6 | "AuthRoleArn": "arn:aws:iam::082042224423:role/amplifyproject-test-20190919143906-authRole", 7 | "Region": "us-east-1", 8 | "DeploymentBucketName": "amplifyproject-test-20190919143906-deployment", 9 | "UnauthRoleName": "amplifyproject-test-20190919143906-unauthRole", 10 | "StackName": "amplifyproject-test-20190919143906", 11 | "StackId": "arn:aws:cloudformation:us-east-1:082042224423:stack/amplifyproject-test-20190919143906/17196b80-dad2-11e9-a39a-0e8cd4caae34" 12 | }, 13 | "categories": { 14 | "auth": { 15 | "amplifyprojectb3fea6ea": { 16 | "hostedUIProviderCreds": "[{\"ProviderName\":\"Facebook\",\"client_id\":\"394347568157898\",\"client_secret\":\"dc2cd59e4b92c604344015e0035dc062\"},{\"ProviderName\":\"Google\",\"client_id\":\"86848591885-pcvo4gsh7dfq09o7igoeacrhqdko5o2g.apps.googleusercontent.com\",\"client_secret\":\"lkuzCgvOYtsheVaP8P8BI9_t\"},{\"ProviderName\":\"LoginWithAmazon\",\"client_id\":\"amzn1.application-oa2-client.30d31882e1794c68b4984697305c0e43\",\"client_secret\":\"d8b9e79ca1eb83d40b2a0e85db3280c7b49a8252a322373e4dfb09b0c4c3557e\"}]" 17 | } 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /aws-exports.js: -------------------------------------------------------------------------------- 1 | // WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten. 2 | 3 | const awsmobile = { 4 | "aws_project_region": "us-east-1", 5 | "aws_appsync_graphqlEndpoint": "https://6oqacvdcd5ehbkhflibujnjzpy.appsync-api.us-east-1.amazonaws.com/graphql", 6 | "aws_appsync_region": "us-east-1", 7 | "aws_appsync_authenticationType": "API_KEY", 8 | "aws_appsync_apiKey": "da2-iawhwbfha5c3dhf3efuwpxphxy", 9 | "aws_cognito_identity_pool_id": "us-east-1:4b34cfd5-e707-4432-9a9c-49a6b2eb4723", 10 | "aws_cognito_region": "us-east-1", 11 | "aws_user_pools_id": "us-east-1_JEGRSXJ1m", 12 | "aws_user_pools_web_client_id": "1siqsh7nie77r156gmpve4bdh5", 13 | "oauth": { 14 | "domain": "amplifyprojectb3fea6ea-b3fea6ea-test.auth.us-east-1.amazoncognito.com", 15 | "scope": [ 16 | "phone", 17 | "email", 18 | "openid", 19 | "profile", 20 | "aws.cognito.signin.user.admin" 21 | ], 22 | "redirectSignIn": "https://192.168.0.80:19006/", 23 | "redirectSignOut": "https://192.168.0.80:19006/", 24 | "responseType": "code" 25 | }, 26 | "federationTarget": "COGNITO_USER_POOLS" 27 | }; 28 | 29 | 30 | export default awsmobile; 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "node_modules/expo/AppEntry.js", 3 | "scripts": { 4 | "start": "expo start", 5 | "android": "expo start --android", 6 | "ios": "expo start --ios", 7 | "web": "expo start --web", 8 | "eject": "expo eject" 9 | }, 10 | "dependencies": { 11 | "@aws-amplify/api": "^1.1.3", 12 | "@aws-amplify/pubsub": "^1.1.2", 13 | "aws-amplify": "^1.1.40", 14 | "aws-amplify-react-native": "^2.1.19", 15 | "expo": "^34.0.1", 16 | "formik": "^1.5.8", 17 | "react": "16.8.3", 18 | "react-dom": "^16.8.6", 19 | "react-native": "https://github.com/expo/react-native/archive/sdk-34.0.0.tar.gz", 20 | "react-native-gesture-handler": "^1.4.1", 21 | "react-native-reanimated": "^1.3.0", 22 | "react-native-screens": "^2.0.0-alpha.3", 23 | "react-native-web": "^0.11.4", 24 | "react-navigation-stack": "^1.9.3", 25 | "react-redux": "^7.1.1", 26 | "redux": "^4.0.4", 27 | "redux-devtools-extension": "^2.13.8", 28 | "redux-thunk": "^2.3.0", 29 | "yup": "^0.27.0" 30 | }, 31 | "devDependencies": { 32 | "babel-preset-expo": "^6.0.0", 33 | "react-navigation": "^4.0.10" 34 | }, 35 | "private": true 36 | } 37 | -------------------------------------------------------------------------------- /src/components/Bottom.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {View, Button, StyleSheet} from 'react-native'; 3 | import {connect} from 'react-redux'; 4 | import {setFilter} from "./actions"; 5 | 6 | const Bottom = ({setFilter}) => { 7 | return ( 8 | 9 | 10 | 10 | ) 11 | } 12 | } 13 | 14 | export default withOAuth(OAuthButton); -------------------------------------------------------------------------------- /src/components/Todos.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {View, SafeAreaView, FlatList, StyleSheet, Text, TouchableHighlight, TouchableOpacity} from 'react-native'; 3 | import ActivityIndicator from "./ActivityIndicator"; 4 | import {connect} from 'react-redux'; 5 | import {listTodos} from "../graphql/queries"; 6 | import {fetchQuery, onUpdateTodoSubscription} from "./actions"; 7 | import {updateTodo} from "../graphql/mutations"; 8 | import {onUpdateTodo} from "../graphql/subscriptions"; 9 | import {graphQLOperation} from './helpers'; 10 | 11 | class Todos extends Component { 12 | state = { 13 | updateTodoSubscription: null 14 | }; 15 | 16 | getData() { 17 | this.props.getTodos(listTodos); 18 | }; 19 | 20 | componentDidMount() { 21 | const updateTodoSubscription = this.props.onUpdateTodoSubscription(onUpdateTodo) ; 22 | this.setState({updateTodoSubscription}); 23 | this.getData(); 24 | }; 25 | 26 | componentWillUnmount() { 27 | this.state.updateTodoSubscription.unsubscribe(); 28 | }; 29 | 30 | handleTodoPress = todo => { 31 | graphQLOperation(updateTodo, {input: {...todo, time: '05.06.1995', completed: !todo.completed}}) 32 | .catch(error => { 33 | console.log(error); 34 | console.log('Todos 24'); 35 | }); 36 | }; 37 | 38 | filterTodos = () => { 39 | const {todos, filter} = this.props; 40 | switch (filter) { 41 | case 'all': return todos; 42 | case 'active': return todos.filter(todo => !todo.completed); 43 | case 'completed': return todos.filter(todo => todo.completed); 44 | default: return todos; 45 | } 46 | }; 47 | 48 | render() { 49 | const {loading} = this.props; 50 | 51 | const listData = this.filterTodos().map(todo => ({ 52 | id: todo.id, 53 | name: todo.name, 54 | description: todo.description, 55 | time: todo.time, 56 | active: todo.active, 57 | all: todo.all, 58 | completed: todo.completed 59 | })); 60 | 61 | if(loading) 62 | return ; 63 | 64 | return ( 65 | true)} 68 | > 69 | 70 | item.id} 72 | data={listData} 73 | renderItem={({item, index, separators}) => ( 74 | {this.handleTodoPress(item)}} 76 | // onShowUnderlay={separators.highlight} 77 | // onHideUnderlay={separators.unhighlight} 78 | > 79 | 80 | 83 | {item.name} 84 | 85 | 86 | )} 87 | /> 88 | 89 | 90 | 91 | 92 | ); 93 | } 94 | 95 | }; 96 | 97 | const styles = StyleSheet.create({ 98 | container: { 99 | flex: 1, 100 | width: '100%', 101 | alignItems: 'flex-start', 102 | marginLeft: 5, 103 | // borderColor: 'black', 104 | // borderWidth: 2 105 | // height: 100 106 | }, 107 | text: { 108 | fontSize: 22, 109 | }, 110 | completedTodo: { 111 | textDecorationLine: 'line-through' 112 | } 113 | }) 114 | 115 | const mapStateToProps = state => ({ 116 | todos: state.queryReducer.todos, 117 | loading: state.queryReducer.loading, 118 | filter: state.filterReducer.filter 119 | }); 120 | 121 | const mapDispatchToProps = (dispatch) => ({ 122 | getTodos: (data) => dispatch(fetchQuery(data)), 123 | onUpdateTodoSubscription: newTodo => dispatch(onUpdateTodoSubscription(newTodo)), 124 | }) ; 125 | 126 | export default connect(mapStateToProps, mapDispatchToProps)(Todos); -------------------------------------------------------------------------------- /src/components/actions.js: -------------------------------------------------------------------------------- 1 | import {graphQLOperation} from './helpers'; 2 | 3 | export const QUERY = "QUERY"; 4 | export const SUBSCRIPTION_ON_CREATE_TODO = "SUBSCRIPTION_ON_CREATE_TODO"; 5 | export const SUBSCRIPTION_ON_UPDATE_TODO = 'SUBSCRIPTION_ON_UPDATE_TODO'; 6 | export const FETCH_QUERY_BEGINNING = 'FETCH_QUERY_BEGINNING'; 7 | export const FETCH_QUERY_SUCCESS = 'FETCH_QUERY_SUCCESS'; 8 | export const FETCH_QUERY_FAIL = 'FETCH_QUERY_FAIL'; 9 | export const SET_FILTER = 'SET_FILTER'; 10 | export const ADD_TODOS = 'ADD_TODOS'; 11 | export const SET_DIALOG = 'SET_DIALOG'; 12 | 13 | const add_Todos = todos => ({ 14 | type: ADD_TODOS, 15 | payload: { 16 | todos 17 | } 18 | }); 19 | 20 | const fetchQueryBeginning = () => { 21 | return { 22 | type: FETCH_QUERY_BEGINNING 23 | } 24 | }; 25 | 26 | const fetchQuerySuccess = data => { 27 | // console.log(data); 28 | return { 29 | type: FETCH_QUERY_SUCCESS, 30 | payload: { 31 | todos: data.data.listTodos.items 32 | } 33 | } 34 | }; 35 | 36 | const fetchQueryFail = error => { 37 | return { 38 | type: FETCH_QUERY_FAIL, 39 | payload: { 40 | error: error 41 | } 42 | } 43 | }; 44 | 45 | export const setFilter = filter => { 46 | return { 47 | type: SET_FILTER, 48 | payload: { 49 | filter 50 | } 51 | } 52 | }; 53 | 54 | const getLists = async (listTodos, nextToken = null) => { 55 | return graphQLOperation(listTodos, nextToken); 56 | }; 57 | 58 | export const fetchQuery = (listTodos) => { 59 | return async dispatch => { 60 | dispatch(fetchQueryBeginning()); 61 | 62 | getLists(listTodos) 63 | .then(async result => { 64 | console.log('actions 73'); 65 | console.log(result.data.listTodos.nextToken); 66 | dispatch(fetchQuerySuccess(result)); 67 | // getLists(listTodos, {nextToken: result.data.listTodos.nextToken}).then(result => dispatch(fetchQuerySuccess(result))) 68 | // dispatch(fetchQuerySuccess(result)); 69 | }) 70 | .catch(error => { 71 | dispatch(fetchQueryFail(error)) 72 | }); 73 | } 74 | }; 75 | 76 | const createTodoSubscription = (data) => ({ 77 | type: SUBSCRIPTION_ON_CREATE_TODO, 78 | payload: { 79 | todo: data 80 | } 81 | }); 82 | 83 | export const onCreateTodoSubscription = subscription => { 84 | return dispatch => { 85 | return graphQLOperation(subscription).subscribe({ 86 | next: eventData => { 87 | const todo = eventData.value.data.onCreateTodo; 88 | dispatch(createTodoSubscription(todo)); 89 | dispatch(setDialog(true, 'Todo was created', todo.name)); 90 | 91 | console.log(todo); 92 | console.log('actions 91'); 93 | } 94 | }) 95 | } 96 | }; 97 | 98 | const updateTodoSubscription = (data) => ({ 99 | type: SUBSCRIPTION_ON_UPDATE_TODO, 100 | payload: { 101 | newTodo: data 102 | } 103 | }); 104 | 105 | export const onUpdateTodoSubscription = (subscription) => { 106 | return dispatch => { 107 | return graphQLOperation(subscription).subscribe({ 108 | next: eventData => { 109 | const todo = eventData.value.data.onUpdateTodo; 110 | dispatch(updateTodoSubscription(todo)); 111 | console.log(todo); 112 | console.log('actions 112'); 113 | 114 | } 115 | }); 116 | } 117 | }; 118 | 119 | export const setDialog = (value, title, message) => ({ 120 | type: SET_DIALOG, 121 | payload: { 122 | showDialog: value, 123 | title, 124 | message 125 | } 126 | }); 127 | 128 | -------------------------------------------------------------------------------- /src/components/dialogReducer.js: -------------------------------------------------------------------------------- 1 | import {SET_DIALOG, QUERY } from './actions'; 2 | 3 | const initialState = { 4 | showDialog: false, 5 | title: '', 6 | message: '', 7 | }; 8 | 9 | const dialogReducer = (state=initialState, action) => { 10 | const {type, payload} = action; 11 | console.log(state); 12 | console.log('dialogreducer 18'); 13 | switch(type) { 14 | case SET_DIALOG: return {...state, showDialog: true, title: payload.title, message: payload.message}; 15 | default: return state; 16 | } 17 | }; 18 | 19 | export default dialogReducer; -------------------------------------------------------------------------------- /src/components/filterReducer.js: -------------------------------------------------------------------------------- 1 | import {SET_FILTER} from "./actions"; 2 | 3 | const INITIAL_VALUE = { 4 | filter: '' 5 | }; 6 | 7 | export const filterReducer = (state=INITIAL_VALUE, action) => { 8 | const {type, payload} = action; 9 | switch (type) { 10 | case SET_FILTER: return {...state, filter: payload.filter}; 11 | default: return state; 12 | } 13 | }; -------------------------------------------------------------------------------- /src/components/forgotPassword/ForgotPassword.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {Formik} from 'formik'; 3 | import {View, Text, TextInput, StyleSheet, Button} from "react-native"; 4 | import * as Yup from "yup"; 5 | 6 | class ForgotPassword extends Component { 7 | static navigationOptions = { 8 | title: 'forgot', 9 | // header: null , 10 | }; 11 | 12 | state = { 13 | showCodeInput: false 14 | }; 15 | 16 | onSubmit = (values) => { 17 | alert(JSON.stringify(values, null, 2)); 18 | window.setTimeout(()=>{this.props.navigation.navigate('ForgotPasswordConfirm')}, 3000); 19 | }; 20 | 21 | render() { 22 | const initialValues = { 23 | username: '', 24 | }; 25 | const VALIDATION_SCHEMA = Yup.object().shape({ 26 | username: Yup.string().required('Required').min(3, 'Too short'), 27 | }); 28 | 29 | return ( 30 | 31 | 36 | {({handleChange, handleSubmit, values, errors, touched, handleBlur, isSubmitting}) => ( 37 | 38 | 39 | 40 | Username * 41 | 42 | 50 | {errors.username && touched.username ? {errors.username} : null} 51 | 52 | 53 | 54 |