├── amplify ├── backend │ ├── storage │ │ └── S3chopperthao │ │ │ ├── storage-params.json │ │ │ ├── parameters.json │ │ │ └── s3-cloudformation-template.json │ ├── tags.json │ ├── backend-config.json │ ├── analytics │ │ └── cloudchopper │ │ │ ├── parameters.json │ │ │ └── pinpoint-cloudformation-template.json │ ├── auth │ │ └── cloudchopperd20aa567 │ │ │ ├── parameters.json │ │ │ └── cloudchopperd20aa567-cloudformation-template.yml │ ├── amplify-meta.json │ └── awscloudformation │ │ ├── build │ │ ├── auth │ │ │ └── cloudchopperd20aa567 │ │ │ │ └── cloudchopperd20aa567-cloudformation-template.yml │ │ └── awscloudformation │ │ │ └── nested-cloudformation-stack.yml │ │ └── nested-cloudformation-stack.yml ├── #current-cloud-backend │ ├── storage │ │ └── S3chopperthao │ │ │ ├── storage-params.json │ │ │ ├── parameters.json │ │ │ └── s3-cloudformation-template.json │ ├── tags.json │ ├── backend-config.json │ ├── analytics │ │ └── cloudchopper │ │ │ └── parameters.json │ ├── auth │ │ └── cloudchopperd20aa567 │ │ │ ├── parameters.json │ │ │ └── cloudchopperd20aa567-cloudformation-template.yml │ └── amplify-meta.json ├── .config │ ├── local-env-info.json │ ├── local-aws-info.json │ └── project-config.json ├── README.md ├── cli.json └── team-provider-info.json ├── ios ├── Runner │ ├── Runner-Bridging-Header.h │ ├── Assets.xcassets │ │ ├── LaunchImage.imageset │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ ├── README.md │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ └── Contents.json │ ├── AppDelegate.swift │ ├── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.storyboard │ └── Info.plist ├── Flutter │ ├── Debug.xcconfig │ ├── Release.xcconfig │ └── AppFrameworkInfo.plist ├── Runner.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── WorkspaceSettings.xcsettings │ │ └── IDEWorkspaceChecks.plist ├── .gitignore └── Podfile ├── images └── image.png ├── android ├── gradle.properties ├── app │ ├── src │ │ ├── main │ │ │ ├── res │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── drawable │ │ │ │ │ └── launch_background.xml │ │ │ │ └── values │ │ │ │ │ └── styles.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── sample_app │ │ │ │ │ └── MainActivity.kt │ │ │ └── AndroidManifest.xml │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ └── profile │ │ │ └── AndroidManifest.xml │ └── build.gradle ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── .gitignore ├── settings.gradle └── build.gradle ├── .metadata ├── .vscode └── settings.json ├── .gitignore ├── lib ├── Pages │ ├── LoadingPage.dart │ ├── MainPage.dart │ └── LandingPage.dart ├── Views │ ├── ImageLineItem.dart │ ├── ErrorView.dart │ ├── ImageUploader.dart │ ├── ImagePreview.dart │ ├── UserView.dart │ ├── SignInView.dart │ └── SignUpView.dart ├── main.dart └── amplifyconfiguration.dart ├── test └── widget_test.dart ├── README.md ├── pubspec.yaml └── pubspec.lock /amplify/backend/storage/S3chopperthao/storage-params.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /amplify/#current-cloud-backend/storage/S3chopperthao/storage-params.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /images/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/images/image.png -------------------------------------------------------------------------------- /amplify/.config/local-env-info.json: -------------------------------------------------------------------------------- 1 | { 2 | "projectPath": "/media/lambiengcode/src/flutter/project/example", 3 | "envName": "dev" 4 | } -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /amplify/.config/local-aws-info.json: -------------------------------------------------------------------------------- 1 | { 2 | "dev": { 3 | "configLevel": "project", 4 | "useProfile": false, 5 | "awsConfigFilePath": "/root/.amplify/awscloudformation/wsmwEeEQlL" 6 | } 7 | } -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /amplify/backend/tags.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Key": "user:Stack", 4 | "Value": "{project-env}" 5 | }, 6 | { 7 | "Key": "user:Application", 8 | "Value": "{project-name}" 9 | } 10 | ] -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambiengcode/flutter_cloud_storage/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /amplify/#current-cloud-backend/tags.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Key": "user:Stack", 4 | "Value": "{project-env}" 5 | }, 6 | { 7 | "Key": "user:Application", 8 | "Value": "{project-name}" 9 | } 10 | ] -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /amplify/.config/project-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "cloudchopper", 3 | "version": "3.1", 4 | "frontend": "flutter", 5 | "flutter": { 6 | "config": { 7 | "ResDir": "./lib/" 8 | } 9 | }, 10 | "providers": [ 11 | "awscloudformation" 12 | ] 13 | } -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip 7 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 8fe7655ed20ffd1395f68e30539a847a01a30351 8 | channel: beta 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "amplify/.config": true, 4 | "amplify/**/*-parameters.json": true, 5 | "amplify/**/amplify.state": true, 6 | "amplify/**/transform.conf.json": true, 7 | "amplify/#current-cloud-backend": true, 8 | "amplify/backend/amplify-meta.json": true, 9 | "amplify/backend/awscloudformation": true 10 | } 11 | } -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /amplify/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Amplify CLI 2 | This directory was generated by [Amplify CLI](https://docs.amplify.aws/cli). 3 | 4 | Helpful resources: 5 | - Amplify documentation: https://docs.amplify.aws 6 | - Amplify CLI documentation: https://docs.amplify.aws/cli 7 | - More details on this folder & generated files: https://docs.amplify.aws/cli/reference/files 8 | - Join Amplify's community: https://amplify.aws/community/ 9 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /amplify/backend/backend-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": { 3 | "cloudchopperd20aa567": { 4 | "service": "Cognito", 5 | "providerPlugin": "awscloudformation", 6 | "dependsOn": [], 7 | "customAuth": false 8 | } 9 | }, 10 | "storage": { 11 | "S3chopperthao": { 12 | "service": "S3", 13 | "providerPlugin": "awscloudformation" 14 | } 15 | }, 16 | "analytics": { 17 | "cloudchopper": { 18 | "service": "Pinpoint", 19 | "providerPlugin": "awscloudformation" 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /amplify/#current-cloud-backend/backend-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": { 3 | "cloudchopperd20aa567": { 4 | "service": "Cognito", 5 | "providerPlugin": "awscloudformation", 6 | "dependsOn": [], 7 | "customAuth": false 8 | } 9 | }, 10 | "storage": { 11 | "S3chopperthao": { 12 | "service": "S3", 13 | "providerPlugin": "awscloudformation" 14 | } 15 | }, 16 | "analytics": { 17 | "cloudchopper": { 18 | "service": "Pinpoint", 19 | "providerPlugin": "awscloudformation" 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Flutter Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | include ':app' 6 | 7 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 8 | def properties = new Properties() 9 | 10 | assert localPropertiesFile.exists() 11 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 12 | 13 | def flutterSdkPath = properties.getProperty("flutter.sdk") 14 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 15 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 16 | -------------------------------------------------------------------------------- /amplify/backend/analytics/cloudchopper/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "appName": "cloudchopper", 3 | "roleName": "pinpointLambdaRoleaaf79265", 4 | "cloudformationPolicyName": "cloudformationPolicyaaf79265", 5 | "cloudWatchPolicyName": "cloudWatchPolicyaaf79265", 6 | "pinpointPolicyName": "pinpointPolicyaaf79265", 7 | "authPolicyName": "pinpoint_amplify_aaf79265", 8 | "unauthPolicyName": "pinpoint_amplify_aaf79265", 9 | "authRoleName": { 10 | "Ref": "AuthRoleName" 11 | }, 12 | "unauthRoleName": { 13 | "Ref": "UnauthRoleName" 14 | }, 15 | "authRoleArn": { 16 | "Fn::GetAtt": [ 17 | "AuthRole", 18 | "Arn" 19 | ] 20 | } 21 | } -------------------------------------------------------------------------------- /amplify/#current-cloud-backend/analytics/cloudchopper/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "appName": "cloudchopper", 3 | "roleName": "pinpointLambdaRoleaaf79265", 4 | "cloudformationPolicyName": "cloudformationPolicyaaf79265", 5 | "cloudWatchPolicyName": "cloudWatchPolicyaaf79265", 6 | "pinpointPolicyName": "pinpointPolicyaaf79265", 7 | "authPolicyName": "pinpoint_amplify_aaf79265", 8 | "unauthPolicyName": "pinpoint_amplify_aaf79265", 9 | "authRoleName": { 10 | "Ref": "AuthRoleName" 11 | }, 12 | "unauthRoleName": { 13 | "Ref": "UnauthRoleName" 14 | }, 15 | "authRoleArn": { 16 | "Fn::GetAtt": [ 17 | "AuthRole", 18 | "Arn" 19 | ] 20 | } 21 | } -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.5.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/example/sample_app/MainActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | package com.example.sample_app 17 | 18 | import io.flutter.embedding.android.FlutterActivity 19 | 20 | class MainActivity: FlutterActivity() { 21 | } 22 | -------------------------------------------------------------------------------- /amplify/cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "features": { 3 | "graphqltransformer": { 4 | "addmissingownerfields": true, 5 | "validatetypenamereservedwords": true, 6 | "useexperimentalpipelinedtransformer": false, 7 | "enableiterativegsiupdates": true, 8 | "secondarykeyasgsi": true, 9 | "skipoverridemutationinputtypes": true 10 | }, 11 | "frontend-ios": { 12 | "enablexcodeintegration": true 13 | }, 14 | "auth": { 15 | "enablecaseinsensitivity": true, 16 | "useinclusiveterminology": true 17 | }, 18 | "codegen": { 19 | "useappsyncmodelgenplugin": true, 20 | "usedocsgeneratorplugin": true, 21 | "usetypesgeneratorplugin": true, 22 | "cleangeneratedmodelsdirectory": true, 23 | "retaincasestyle": true 24 | }, 25 | "appsync": { 26 | "generategraphqlpermissions": true 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Exceptions to above rules. 44 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages -------------------------------------------------------------------------------- /amplify/team-provider-info.json: -------------------------------------------------------------------------------- 1 | { 2 | "dev": { 3 | "awscloudformation": { 4 | "AuthRoleName": "amplify-cloudchopper-dev-204628-authRole", 5 | "UnauthRoleArn": "arn:aws:iam::198101249191:role/amplify-cloudchopper-dev-204628-unauthRole", 6 | "AuthRoleArn": "arn:aws:iam::198101249191:role/amplify-cloudchopper-dev-204628-authRole", 7 | "Region": "ap-southeast-1", 8 | "DeploymentBucketName": "amplify-cloudchopper-dev-204628-deployment", 9 | "UnauthRoleName": "amplify-cloudchopper-dev-204628-unauthRole", 10 | "StackName": "amplify-cloudchopper-dev-204628", 11 | "StackId": "arn:aws:cloudformation:ap-southeast-1:198101249191:stack/amplify-cloudchopper-dev-204628/4ba97a60-bbcd-11eb-b0c7-02ab63576a78", 12 | "AmplifyAppId": "d9myyhl3m04b9" 13 | }, 14 | "categories": { 15 | "auth": { 16 | "cloudchopperd20aa567": {} 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /lib/Pages/LoadingPage.dart: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | import 'package:flutter/cupertino.dart'; 17 | import 'package:flutter/material.dart'; 18 | 19 | class LoadingPage extends StatelessWidget { 20 | @override 21 | Widget build(BuildContext context) { 22 | return Scaffold( 23 | appBar: AppBar(title: Text("Landing Page")), 24 | body: 25 | Center(child: Text("Please Wait. Configuring Amplify Flutter SDK")), 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/Views/ImageLineItem.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'ImagePreview.dart'; 4 | 5 | class ImageLineItem extends StatelessWidget { 6 | final String storageKey; 7 | 8 | const ImageLineItem({ 9 | Key key, 10 | this.storageKey, 11 | }) : super(key: key); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return Padding( 16 | padding: EdgeInsets.all(5.0), 17 | child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ 18 | Text(storageKey), 19 | Spacer(), 20 | ElevatedButton( 21 | child: const Text("open"), 22 | onPressed: () => { 23 | showDialog( 24 | context: context, 25 | builder: (BuildContext context) { 26 | return new SimpleDialog( 27 | title: Text(storageKey), 28 | children: [ImagePreview(storageKey: storageKey)]); 29 | }) 30 | }) 31 | ])); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:sample_app/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /lib/Views/ErrorView.dart: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | import 'package:flutter/material.dart'; 17 | 18 | class ErrorView extends StatelessWidget { 19 | final String error; 20 | 21 | ErrorView(this.error); 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | if (error.isNotEmpty) { 26 | return Column(children: [ 27 | Text('Error: $error', 28 | textAlign: TextAlign.center, 29 | overflow: TextOverflow.visible, 30 | style: TextStyle(fontWeight: FontWeight.bold)), 31 | ]); 32 | } else { 33 | return Container(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/Views/ImageUploader.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'dart:io'; 3 | import 'package:file_picker/file_picker.dart'; 4 | import 'package:amplify_flutter/amplify.dart'; 5 | import 'package:amplify_storage_s3/amplify_storage_s3.dart'; 6 | 7 | class ImageUploader extends StatelessWidget { 8 | void _upload(BuildContext context) async { 9 | try { 10 | print('In upload'); 11 | // Uploading the file with options 12 | File local = await FilePicker.getFile(type: FileType.image); 13 | local.existsSync(); 14 | final key = new DateTime.now().toString(); 15 | Map metadata = {}; 16 | metadata['name'] = 'filename'; 17 | metadata['desc'] = 'A test file'; 18 | S3UploadFileOptions options = S3UploadFileOptions( 19 | accessLevel: StorageAccessLevel.guest, metadata: metadata); 20 | UploadFileResult result = await Amplify.Storage.uploadFile( 21 | key: key, local: local, options: options); 22 | 23 | print('File uploaded. Key: ' + result.key); 24 | Navigator.pop(context, result.key); 25 | } catch (e) { 26 | print('UploadFile Err: ' + e.toString()); 27 | } 28 | } 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | return Column(children: [ 33 | ElevatedButton( 34 | child: const Text("Upload Image"), 35 | onPressed: () { 36 | _upload(context); 37 | }, 38 | ) 39 | ]); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /amplify/backend/storage/S3chopperthao/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "bucketName": "cloudchopper5de8d1549c594acca63ed06abae2d414", 3 | "authPolicyName": "s3_amplify_899f92fa", 4 | "unauthPolicyName": "s3_amplify_899f92fa", 5 | "authRoleName": { 6 | "Ref": "AuthRoleName" 7 | }, 8 | "unauthRoleName": { 9 | "Ref": "UnauthRoleName" 10 | }, 11 | "selectedGuestPermissions": [ 12 | "s3:PutObject", 13 | "s3:GetObject", 14 | "s3:ListBucket", 15 | "s3:DeleteObject" 16 | ], 17 | "selectedAuthenticatedPermissions": [ 18 | "s3:PutObject", 19 | "s3:GetObject", 20 | "s3:ListBucket", 21 | "s3:DeleteObject" 22 | ], 23 | "s3PermissionsAuthenticatedPublic": "s3:PutObject,s3:GetObject,s3:DeleteObject", 24 | "s3PublicPolicy": "Public_policy_7d6cabc6", 25 | "s3PermissionsAuthenticatedUploads": "s3:PutObject", 26 | "s3UploadsPolicy": "Uploads_policy_7d6cabc6", 27 | "s3PermissionsAuthenticatedProtected": "s3:PutObject,s3:GetObject,s3:DeleteObject", 28 | "s3ProtectedPolicy": "Protected_policy_5e148ded", 29 | "s3PermissionsAuthenticatedPrivate": "s3:PutObject,s3:GetObject,s3:DeleteObject", 30 | "s3PrivatePolicy": "Private_policy_5e148ded", 31 | "AuthenticatedAllowList": "ALLOW", 32 | "s3ReadPolicy": "read_policy_7d6cabc6", 33 | "s3PermissionsGuestPublic": "s3:PutObject,s3:GetObject,s3:DeleteObject", 34 | "s3PermissionsGuestUploads": "s3:PutObject", 35 | "GuestAllowList": "ALLOW", 36 | "triggerFunction": "NONE" 37 | } -------------------------------------------------------------------------------- /amplify/#current-cloud-backend/storage/S3chopperthao/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "bucketName": "cloudchopper5de8d1549c594acca63ed06abae2d414", 3 | "authPolicyName": "s3_amplify_899f92fa", 4 | "unauthPolicyName": "s3_amplify_899f92fa", 5 | "authRoleName": { 6 | "Ref": "AuthRoleName" 7 | }, 8 | "unauthRoleName": { 9 | "Ref": "UnauthRoleName" 10 | }, 11 | "selectedGuestPermissions": [ 12 | "s3:PutObject", 13 | "s3:GetObject", 14 | "s3:ListBucket", 15 | "s3:DeleteObject" 16 | ], 17 | "selectedAuthenticatedPermissions": [ 18 | "s3:PutObject", 19 | "s3:GetObject", 20 | "s3:ListBucket", 21 | "s3:DeleteObject" 22 | ], 23 | "s3PermissionsAuthenticatedPublic": "s3:PutObject,s3:GetObject,s3:DeleteObject", 24 | "s3PublicPolicy": "Public_policy_7d6cabc6", 25 | "s3PermissionsAuthenticatedUploads": "s3:PutObject", 26 | "s3UploadsPolicy": "Uploads_policy_7d6cabc6", 27 | "s3PermissionsAuthenticatedProtected": "s3:PutObject,s3:GetObject,s3:DeleteObject", 28 | "s3ProtectedPolicy": "Protected_policy_5e148ded", 29 | "s3PermissionsAuthenticatedPrivate": "s3:PutObject,s3:GetObject,s3:DeleteObject", 30 | "s3PrivatePolicy": "Private_policy_5e148ded", 31 | "AuthenticatedAllowList": "ALLOW", 32 | "s3ReadPolicy": "read_policy_7d6cabc6", 33 | "s3PermissionsGuestPublic": "s3:PutObject,s3:GetObject,s3:DeleteObject", 34 | "s3PermissionsGuestUploads": "s3:PutObject", 35 | "GuestAllowList": "ALLOW", 36 | "triggerFunction": "NONE" 37 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Amplify Flutter Example 2 | 3 | Sample flutter app for getting started with the Amplify Flutter Library. This example uses the Auth, Analytics, and Storage components of the Flutter library. 4 | 5 | Please check out our docs here: 6 | https://docs.amplify.aws/start/q/integration/flutter 7 | 8 | ## Getting Started 9 | 10 | **IMPORTANT** 11 | 12 | **The app will not compile until you use the Amplify CLI to configure AWS resources necessary for running this app, or create your own amplifyconfiguration.dart file using the example in our documentation'.** 13 | 14 | This is because it does not contain an `amplifyconfiguration.dart` file necessary for connecting with AWS services. 15 | 16 | You will need to use Amplify CLI to init the app and configure Analytics, Auth, and Storage. Please follow the instructions here: 17 | 18 | https://docs.amplify.aws/start/getting-started/add-api/q/integration/flutter#setup-aws-cloud-resources-with-amplify-cli 19 | 20 | For this example app you will also need to call `amplify add auth`, and `amplify add storage` with the Amplify CLI and call `amplify push` again. 21 | 22 | Running these steps will generate the `amplifyconfiguration.dart` file within the `lib` folder. 23 | 24 | ## Important Notes 25 | 26 | This is a very basic app that interacts with AWS resources. We did not implement UI showing that the app is "loading" or "uploading" something from AWS. Some operations like logging in or uploading an image can take some time. 27 | 28 | Please note when signing up that you MUST provide a country code for a new user's phone number. For example, if your number is American, you will need to append +1 to the beginning. 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | sample_app 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /lib/Views/ImagePreview.dart: -------------------------------------------------------------------------------- 1 | import 'package:amplify_analytics_pinpoint/amplify_analytics_pinpoint.dart'; 2 | import 'package:amplify_flutter/amplify.dart'; 3 | import 'package:amplify_storage_s3/amplify_storage_s3.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | class ImagePreview extends StatefulWidget { 7 | final String storageKey; 8 | 9 | ImagePreview({Key key, this.storageKey}) : super(key: key); 10 | 11 | @override 12 | _ImagePreviewState createState() => _ImagePreviewState(); 13 | } 14 | 15 | class _ImagePreviewState extends State { 16 | String _imageURL = ''; 17 | 18 | @override 19 | void initState() { 20 | super.initState(); 21 | _getUrl(widget.storageKey); 22 | } 23 | 24 | void _getUrl(String storageKey) async { 25 | try { 26 | print('In getUrl'); 27 | String key = storageKey; 28 | S3GetUrlOptions options = S3GetUrlOptions( 29 | accessLevel: StorageAccessLevel.guest, expires: 10000); 30 | GetUrlResult result = 31 | await Amplify.Storage.getUrl(key: key, options: options); 32 | 33 | setState(() { 34 | _imageURL = result.url; 35 | }); 36 | 37 | print('URL: ' + _imageURL); 38 | AnalyticsEvent event = AnalyticsEvent("image_url_retrieved"); 39 | event.properties.addStringProperty("file_key", storageKey); 40 | Amplify.Analytics.recordEvent(event: event); 41 | } catch (e) { 42 | print('GetUrl Err: ' + e.toString()); 43 | } 44 | } 45 | 46 | @override 47 | Widget build(BuildContext context) { 48 | return Column(children: [ 49 | //Image(image: AssetImage('images/image.png')), 50 | Center(child: Image.network(_imageURL)) 51 | ]); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/Views/UserView.dart: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | import 'package:amplify_auth_cognito/amplify_auth_cognito.dart'; 17 | import 'package:amplify_flutter/amplify.dart'; 18 | import 'package:flutter/material.dart'; 19 | import 'package:sample_app/Pages/LandingPage.dart'; 20 | 21 | class UserView extends StatefulWidget { 22 | @override 23 | _UserProfileState createState() => _UserProfileState(); 24 | } 25 | 26 | class _UserProfileState extends State { 27 | @override 28 | void initState() { 29 | super.initState(); 30 | } 31 | 32 | void _signOut() async { 33 | try { 34 | SignOutResult res = await Amplify.Auth.signOut(); 35 | 36 | Navigator.pushAndRemoveUntil( 37 | context, 38 | MaterialPageRoute(builder: (context) => LandingPage()), 39 | (route) => false); 40 | } on AuthException catch (e) { 41 | print(e); 42 | } 43 | } 44 | 45 | @override 46 | Widget build(BuildContext context) { 47 | return Row( 48 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 49 | children: [ 50 | ElevatedButton(onPressed: _signOut, child: const Text("Log Out")), 51 | ], 52 | ); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /amplify/backend/auth/cloudchopperd20aa567/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "identityPoolName": "cloudchopperd20aa567_identitypool_d20aa567", 3 | "allowUnauthenticatedIdentities": true, 4 | "resourceNameTruncated": "cloudcd20aa567", 5 | "userPoolName": "cloudchopperd20aa567_userpool_d20aa567", 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": false, 24 | "userpoolClientRefreshTokenValidity": 30, 25 | "userpoolClientWriteAttributes": [ 26 | "email" 27 | ], 28 | "userpoolClientReadAttributes": [ 29 | "email" 30 | ], 31 | "userpoolClientLambdaRole": "cloudcd20aa567_userpoolclient_lambda_role", 32 | "userpoolClientSetAttributes": false, 33 | "sharedId": "d20aa567", 34 | "resourceName": "cloudchopperd20aa567", 35 | "authSelections": "identityPoolAndUserPool", 36 | "authRoleArn": { 37 | "Fn::GetAtt": [ 38 | "AuthRole", 39 | "Arn" 40 | ] 41 | }, 42 | "unauthRoleArn": { 43 | "Fn::GetAtt": [ 44 | "UnauthRole", 45 | "Arn" 46 | ] 47 | }, 48 | "useDefault": "default", 49 | "userPoolGroupList": [], 50 | "serviceName": "Cognito", 51 | "usernameCaseSensitive": false, 52 | "dependsOn": [] 53 | } -------------------------------------------------------------------------------- /amplify/#current-cloud-backend/auth/cloudchopperd20aa567/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "identityPoolName": "cloudchopperd20aa567_identitypool_d20aa567", 3 | "allowUnauthenticatedIdentities": true, 4 | "resourceNameTruncated": "cloudcd20aa567", 5 | "userPoolName": "cloudchopperd20aa567_userpool_d20aa567", 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": false, 24 | "userpoolClientRefreshTokenValidity": 30, 25 | "userpoolClientWriteAttributes": [ 26 | "email" 27 | ], 28 | "userpoolClientReadAttributes": [ 29 | "email" 30 | ], 31 | "userpoolClientLambdaRole": "cloudcd20aa567_userpoolclient_lambda_role", 32 | "userpoolClientSetAttributes": false, 33 | "sharedId": "d20aa567", 34 | "resourceName": "cloudchopperd20aa567", 35 | "authSelections": "identityPoolAndUserPool", 36 | "authRoleArn": { 37 | "Fn::GetAtt": [ 38 | "AuthRole", 39 | "Arn" 40 | ] 41 | }, 42 | "unauthRoleArn": { 43 | "Fn::GetAtt": [ 44 | "UnauthRole", 45 | "Arn" 46 | ] 47 | }, 48 | "useDefault": "default", 49 | "userPoolGroupList": [], 50 | "serviceName": "Cognito", 51 | "usernameCaseSensitive": false, 52 | "dependsOn": [] 53 | } -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:amplify_analytics_pinpoint/amplify_analytics_pinpoint.dart'; 2 | import 'package:amplify_auth_cognito/amplify_auth_cognito.dart'; 3 | import 'package:amplify_flutter/amplify.dart'; 4 | import 'package:amplify_storage_s3/amplify_storage_s3.dart'; 5 | import 'package:flutter/material.dart'; 6 | import 'package:sample_app/Pages/LoadingPage.dart'; 7 | import 'Pages/LandingPage.dart'; 8 | import 'amplifyconfiguration.dart'; 9 | 10 | void main() { 11 | runApp(MyApp()); 12 | } 13 | 14 | class MyApp extends StatefulWidget { 15 | @override 16 | State createState() => _MyAppState(); 17 | } 18 | 19 | class _MyAppState extends State { 20 | bool _isAmplifyConfigured = false; 21 | 22 | @override 23 | initState() { 24 | super.initState(); 25 | _initAmplifyFlutter(); 26 | } 27 | 28 | void _initAmplifyFlutter() async { 29 | AmplifyAuthCognito auth = AmplifyAuthCognito(); 30 | AmplifyStorageS3 storage = AmplifyStorageS3(); 31 | AmplifyAnalyticsPinpoint analyticsPinpoint = AmplifyAnalyticsPinpoint(); 32 | 33 | Amplify.addPlugins([auth, storage, analyticsPinpoint]); 34 | 35 | // Initialize AmplifyFlutter 36 | try { 37 | await Amplify.configure(amplifyconfig); 38 | } on AmplifyAlreadyConfiguredException { 39 | print( 40 | "Amplify was already configured. Looks like app restarted on android."); 41 | } 42 | 43 | setState(() { 44 | _isAmplifyConfigured = true; 45 | }); 46 | } 47 | 48 | Widget _display() { 49 | if (_isAmplifyConfigured) { 50 | return LandingPage(); 51 | } else { 52 | return LoadingPage(); 53 | } 54 | } 55 | 56 | @override 57 | Widget build(BuildContext context) { 58 | return MaterialApp( 59 | title: 'Flutter Amplify App', 60 | theme: ThemeData( 61 | primarySwatch: Colors.blue, 62 | visualDensity: VisualDensity.adaptivePlatformDensity, 63 | ), 64 | home: _display(), 65 | ); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 30 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | lintOptions { 36 | disable 'InvalidPackage' 37 | } 38 | 39 | defaultConfig { 40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 41 | applicationId "com.example.sample_app" 42 | minSdkVersion 21 43 | targetSdkVersion 30 44 | versionCode flutterVersionCode.toInteger() 45 | versionName flutterVersionName 46 | } 47 | 48 | buildTypes { 49 | release { 50 | // TODO: Add your own signing config for the release build. 51 | // Signing with the debug keys for now, so `flutter run --release` works. 52 | signingConfig signingConfigs.debug 53 | } 54 | } 55 | } 56 | 57 | flutter { 58 | source '../..' 59 | } 60 | 61 | dependencies { 62 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 63 | } 64 | -------------------------------------------------------------------------------- /lib/Pages/MainPage.dart: -------------------------------------------------------------------------------- 1 | import 'package:amplify_flutter/amplify.dart'; 2 | import 'package:amplify_storage_s3/amplify_storage_s3.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:sample_app/Views/ImageLineItem.dart'; 5 | import 'package:sample_app/Views/ImageUploader.dart'; 6 | import 'package:sample_app/Views/UserView.dart'; 7 | 8 | class MainPage extends StatefulWidget { 9 | @override 10 | _MainPageState createState() => _MainPageState(); 11 | } 12 | 13 | class _MainPageState extends State { 14 | List itemKeys = []; 15 | 16 | @override 17 | void initState() { 18 | super.initState(); 19 | _loadImages(); 20 | } 21 | 22 | void _loadImages() async { 23 | try { 24 | print('In list'); 25 | S3ListOptions options = 26 | S3ListOptions(accessLevel: StorageAccessLevel.guest); 27 | ListResult result = await Amplify.Storage.list(options: options); 28 | 29 | var newList = itemKeys.toList(); 30 | for (StorageItem item in result.items) { 31 | newList.add(item.key); 32 | } 33 | 34 | setState(() { 35 | itemKeys = newList; 36 | }); 37 | } catch (e) { 38 | print('List Err: ' + e.toString()); 39 | } 40 | } 41 | 42 | void _showImageUploader() async { 43 | String key = await showDialog( 44 | context: context, 45 | builder: (BuildContext context) { 46 | return new SimpleDialog( 47 | title: Text("Upload Image"), children: [ImageUploader()]); 48 | }); 49 | 50 | if (key.isNotEmpty) { 51 | var newList = itemKeys.toList(); 52 | newList.add(key); 53 | 54 | setState(() { 55 | itemKeys = newList; 56 | }); 57 | } 58 | } 59 | 60 | @override 61 | Widget build(BuildContext context) { 62 | return Scaffold( 63 | appBar: AppBar( 64 | title: Row( 65 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 66 | children: [Text("Main Page"), UserView()])), 67 | body: ListView.builder( 68 | itemCount: itemKeys.length, 69 | itemBuilder: (context, index) { 70 | return ImageLineItem(storageKey: itemKeys[index]); 71 | }), 72 | floatingActionButton: FloatingActionButton( 73 | onPressed: () { 74 | _showImageUploader(); 75 | }, 76 | tooltip: 'Increment', 77 | child: Icon(Icons.add), 78 | ), 79 | ); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /lib/Pages/LandingPage.dart: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | import 'package:flutter/material.dart'; 17 | 18 | import '../Views/SignInView.dart'; 19 | import '../Views/SignUpView.dart'; 20 | import 'MainPage.dart'; 21 | 22 | class LandingPage extends StatefulWidget { 23 | LandingPage({Key key}) : super(key: key); 24 | 25 | @override 26 | _LandingPageState createState() => _LandingPageState(); 27 | } 28 | 29 | class _LandingPageState extends State { 30 | Future _showDialogForResult( 31 | String text, Function onSuccess, Widget dialogWidget) async { 32 | bool result = await showDialog( 33 | context: context, 34 | builder: (BuildContext context) { 35 | return new SimpleDialog(title: Text(text), children: [ 36 | dialogWidget, 37 | ElevatedButton( 38 | child: const Text("Cancel"), 39 | onPressed: () { 40 | Navigator.pop(context, false); 41 | }, 42 | ), 43 | ]); 44 | }); 45 | 46 | if (result) onSuccess(); 47 | } 48 | 49 | // dialogWidget must return true or false 50 | Widget openDialogButton( 51 | String text, Function onSuccess, Widget dialogWidget) { 52 | return ElevatedButton( 53 | child: Text(text), 54 | onPressed: () { 55 | _showDialogForResult(text, onSuccess, dialogWidget); 56 | }); 57 | } 58 | 59 | void onSignInSuccess() { 60 | Navigator.pushAndRemoveUntil(context, 61 | MaterialPageRoute(builder: (context) => MainPage()), (route) => false); 62 | } 63 | 64 | @override 65 | Widget build(BuildContext context) { 66 | return Scaffold( 67 | appBar: AppBar( 68 | title: Text("Landing Page"), 69 | ), 70 | body: Center( 71 | child: Row( 72 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 73 | children: [ 74 | openDialogButton("Sign In", onSignInSuccess, SignInView()), 75 | openDialogButton( 76 | "Sign Up", () => {print("sign up success")}, SignUpView()) 77 | ], 78 | ))); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 8 | 12 | 19 | 23 | 27 | 32 | 36 | 37 | 38 | 39 | 40 | 41 | 43 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /lib/amplifyconfiguration.dart: -------------------------------------------------------------------------------- 1 | const amplifyconfig = ''' { 2 | "UserAgent": "aws-amplify-cli/2.0", 3 | "Version": "1.0", 4 | "auth": { 5 | "plugins": { 6 | "awsCognitoAuthPlugin": { 7 | "UserAgent": "aws-amplify-cli/0.1.0", 8 | "Version": "0.1.0", 9 | "IdentityManager": { 10 | "Default": {} 11 | }, 12 | "CredentialsProvider": { 13 | "CognitoIdentity": { 14 | "Default": { 15 | "PoolId": "ap-southeast-1:08efc3f6-bb71-4d8f-9ada-8b38f9c77691", 16 | "Region": "ap-southeast-1" 17 | } 18 | } 19 | }, 20 | "CognitoUserPool": { 21 | "Default": { 22 | "PoolId": "ap-southeast-1_9WxFEXgEx", 23 | "AppClientId": "1a8dod847cqa2m5pas3v6c8n5u", 24 | "Region": "ap-southeast-1" 25 | } 26 | }, 27 | "Auth": { 28 | "Default": { 29 | "authenticationFlowType": "USER_SRP_AUTH" 30 | } 31 | }, 32 | "S3TransferUtility": { 33 | "Default": { 34 | "Bucket": "cloudchopper5de8d1549c594acca63ed06abae2d414204628-dev", 35 | "Region": "ap-southeast-1" 36 | } 37 | }, 38 | "PinpointAnalytics": { 39 | "Default": { 40 | "AppId": "269495fe54cb40d8ba1d0a393776a11c", 41 | "Region": "us-west-2" 42 | } 43 | }, 44 | "PinpointTargeting": { 45 | "Default": { 46 | "Region": "us-west-2" 47 | } 48 | } 49 | } 50 | } 51 | }, 52 | "storage": { 53 | "plugins": { 54 | "awsS3StoragePlugin": { 55 | "bucket": "cloudchopper5de8d1549c594acca63ed06abae2d414204628-dev", 56 | "region": "ap-southeast-1", 57 | "defaultAccessLevel": "guest" 58 | } 59 | } 60 | }, 61 | "analytics": { 62 | "plugins": { 63 | "awsPinpointAnalyticsPlugin": { 64 | "pinpointAnalytics": { 65 | "appId": "269495fe54cb40d8ba1d0a393776a11c", 66 | "region": "us-west-2" 67 | }, 68 | "pinpointTargeting": { 69 | "region": "us-west-2" 70 | } 71 | } 72 | } 73 | } 74 | }'''; -------------------------------------------------------------------------------- /amplify/backend/amplify-meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "providers": { 3 | "awscloudformation": { 4 | "AuthRoleName": "amplify-cloudchopper-dev-204628-authRole", 5 | "UnauthRoleArn": "arn:aws:iam::198101249191:role/amplify-cloudchopper-dev-204628-unauthRole", 6 | "AuthRoleArn": "arn:aws:iam::198101249191:role/amplify-cloudchopper-dev-204628-authRole", 7 | "Region": "ap-southeast-1", 8 | "DeploymentBucketName": "amplify-cloudchopper-dev-204628-deployment", 9 | "UnauthRoleName": "amplify-cloudchopper-dev-204628-unauthRole", 10 | "StackName": "amplify-cloudchopper-dev-204628", 11 | "StackId": "arn:aws:cloudformation:ap-southeast-1:198101249191:stack/amplify-cloudchopper-dev-204628/4ba97a60-bbcd-11eb-b0c7-02ab63576a78", 12 | "AmplifyAppId": "d9myyhl3m04b9" 13 | } 14 | }, 15 | "auth": { 16 | "cloudchopperd20aa567": { 17 | "service": "Cognito", 18 | "providerPlugin": "awscloudformation", 19 | "dependsOn": [], 20 | "customAuth": false, 21 | "providerMetadata": { 22 | "s3TemplateURL": "https://s3.amazonaws.com/amplify-cloudchopper-dev-204628-deployment/amplify-cfn-templates/auth/cloudchopperd20aa567-cloudformation-template.yml", 23 | "logicalId": "authcloudchopperd20aa567" 24 | }, 25 | "lastPushTimeStamp": "2021-05-23T14:06:24.114Z", 26 | "output": { 27 | "UserPoolId": "ap-southeast-1_9WxFEXgEx", 28 | "AppClientIDWeb": "7nmsq7nfs8rfcuijt4arnsph4v", 29 | "AppClientID": "1a8dod847cqa2m5pas3v6c8n5u", 30 | "IdentityPoolId": "ap-southeast-1:08efc3f6-bb71-4d8f-9ada-8b38f9c77691", 31 | "IdentityPoolName": "cloudchopperd20aa567_identitypool_d20aa567__dev", 32 | "UserPoolName": "cloudchopperd20aa567_userpool_d20aa567" 33 | }, 34 | "lastPushDirHash": "p1D6cyya+gsMcV8MMLL7VL7ggvo=" 35 | } 36 | }, 37 | "storage": { 38 | "S3chopperthao": { 39 | "service": "S3", 40 | "providerPlugin": "awscloudformation", 41 | "providerMetadata": { 42 | "s3TemplateURL": "https://s3.amazonaws.com/amplify-cloudchopper-dev-204628-deployment/amplify-cfn-templates/storage/s3-cloudformation-template.json", 43 | "logicalId": "storageS3chopperthao" 44 | }, 45 | "lastPushTimeStamp": "2021-05-23T14:06:24.405Z", 46 | "output": { 47 | "BucketName": "cloudchopper5de8d1549c594acca63ed06abae2d414204628-dev", 48 | "Region": "ap-southeast-1" 49 | }, 50 | "lastPushDirHash": "1cDWKe4EN1u8vfYiXo/C/ogNixg=" 51 | } 52 | }, 53 | "analytics": { 54 | "cloudchopper": { 55 | "service": "Pinpoint", 56 | "providerPlugin": "awscloudformation", 57 | "providerMetadata": { 58 | "s3TemplateURL": "https://s3.amazonaws.com/amplify-cloudchopper-dev-204628-deployment/amplify-cfn-templates/analytics/pinpoint-cloudformation-template.json", 59 | "logicalId": "analyticscloudchopper" 60 | }, 61 | "lastPushTimeStamp": "2021-05-23T14:06:24.412Z", 62 | "output": { 63 | "appName": "cloudchopper-dev", 64 | "Region": "us-west-2", 65 | "Id": "269495fe54cb40d8ba1d0a393776a11c" 66 | }, 67 | "lastPushDirHash": "A5pBxCVNfOAGje8cV6s3MGuLm1M=" 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /amplify/#current-cloud-backend/amplify-meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "providers": { 3 | "awscloudformation": { 4 | "AuthRoleName": "amplify-cloudchopper-dev-204628-authRole", 5 | "UnauthRoleArn": "arn:aws:iam::198101249191:role/amplify-cloudchopper-dev-204628-unauthRole", 6 | "AuthRoleArn": "arn:aws:iam::198101249191:role/amplify-cloudchopper-dev-204628-authRole", 7 | "Region": "ap-southeast-1", 8 | "DeploymentBucketName": "amplify-cloudchopper-dev-204628-deployment", 9 | "UnauthRoleName": "amplify-cloudchopper-dev-204628-unauthRole", 10 | "StackName": "amplify-cloudchopper-dev-204628", 11 | "StackId": "arn:aws:cloudformation:ap-southeast-1:198101249191:stack/amplify-cloudchopper-dev-204628/4ba97a60-bbcd-11eb-b0c7-02ab63576a78", 12 | "AmplifyAppId": "d9myyhl3m04b9" 13 | } 14 | }, 15 | "auth": { 16 | "cloudchopperd20aa567": { 17 | "service": "Cognito", 18 | "providerPlugin": "awscloudformation", 19 | "dependsOn": [], 20 | "customAuth": false, 21 | "providerMetadata": { 22 | "s3TemplateURL": "https://s3.amazonaws.com/amplify-cloudchopper-dev-204628-deployment/amplify-cfn-templates/auth/cloudchopperd20aa567-cloudformation-template.yml", 23 | "logicalId": "authcloudchopperd20aa567" 24 | }, 25 | "lastPushTimeStamp": "2021-05-23T14:06:24.114Z", 26 | "output": { 27 | "UserPoolId": "ap-southeast-1_9WxFEXgEx", 28 | "AppClientIDWeb": "7nmsq7nfs8rfcuijt4arnsph4v", 29 | "AppClientID": "1a8dod847cqa2m5pas3v6c8n5u", 30 | "IdentityPoolId": "ap-southeast-1:08efc3f6-bb71-4d8f-9ada-8b38f9c77691", 31 | "IdentityPoolName": "cloudchopperd20aa567_identitypool_d20aa567__dev", 32 | "UserPoolName": "cloudchopperd20aa567_userpool_d20aa567" 33 | }, 34 | "lastPushDirHash": "p1D6cyya+gsMcV8MMLL7VL7ggvo=" 35 | } 36 | }, 37 | "storage": { 38 | "S3chopperthao": { 39 | "service": "S3", 40 | "providerPlugin": "awscloudformation", 41 | "providerMetadata": { 42 | "s3TemplateURL": "https://s3.amazonaws.com/amplify-cloudchopper-dev-204628-deployment/amplify-cfn-templates/storage/s3-cloudformation-template.json", 43 | "logicalId": "storageS3chopperthao" 44 | }, 45 | "lastPushTimeStamp": "2021-05-23T14:06:24.405Z", 46 | "output": { 47 | "BucketName": "cloudchopper5de8d1549c594acca63ed06abae2d414204628-dev", 48 | "Region": "ap-southeast-1" 49 | }, 50 | "lastPushDirHash": "1cDWKe4EN1u8vfYiXo/C/ogNixg=" 51 | } 52 | }, 53 | "analytics": { 54 | "cloudchopper": { 55 | "service": "Pinpoint", 56 | "providerPlugin": "awscloudformation", 57 | "providerMetadata": { 58 | "s3TemplateURL": "https://s3.amazonaws.com/amplify-cloudchopper-dev-204628-deployment/amplify-cfn-templates/analytics/pinpoint-cloudformation-template.json", 59 | "logicalId": "analyticscloudchopper" 60 | }, 61 | "lastPushTimeStamp": "2021-05-23T14:06:24.412Z", 62 | "output": { 63 | "appName": "cloudchopper-dev", 64 | "Region": "us-west-2", 65 | "Id": "269495fe54cb40d8ba1d0a393776a11c" 66 | }, 67 | "lastPushDirHash": "A5pBxCVNfOAGje8cV6s3MGuLm1M=" 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /lib/Views/SignInView.dart: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | import 'package:amplify_auth_cognito/amplify_auth_cognito.dart'; 17 | import 'package:amplify_flutter/amplify.dart'; 18 | import 'package:flutter/material.dart'; 19 | 20 | import 'ErrorView.dart'; 21 | 22 | class SignInView extends StatefulWidget { 23 | @override 24 | _SignInViewState createState() => _SignInViewState(); 25 | } 26 | 27 | class _SignInViewState extends State { 28 | final usernameController = TextEditingController(); 29 | final passwordController = TextEditingController(); 30 | 31 | String _signUpError = ""; 32 | 33 | @override 34 | void initState() { 35 | super.initState(); 36 | } 37 | 38 | void _signIn() async { 39 | try { 40 | await Amplify.Auth.signOut(); 41 | } on AuthException catch (e) { 42 | print(e); 43 | } 44 | 45 | try { 46 | SignInResult res = await Amplify.Auth.signIn( 47 | username: usernameController.text.trim(), 48 | password: passwordController.text.trim()); 49 | Navigator.pop(context, true); 50 | } on AuthException catch (e) { 51 | setState(() { 52 | _signUpError = e.message; 53 | }); 54 | } 55 | } 56 | 57 | @override 58 | Widget build(BuildContext context) { 59 | return Row( 60 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 61 | children: [ 62 | Expanded( 63 | // wrap your Column in Expanded 64 | child: Padding( 65 | padding: EdgeInsets.all(10.0), 66 | child: Column( 67 | children: [ 68 | TextFormField( 69 | controller: usernameController, 70 | decoration: const InputDecoration( 71 | icon: Icon(Icons.person), 72 | hintText: 'Enter your username', 73 | labelText: 'Username *', 74 | ), 75 | ), 76 | TextFormField( 77 | obscureText: true, 78 | controller: passwordController, 79 | decoration: const InputDecoration( 80 | icon: Icon(Icons.lock), 81 | hintText: 'Enter your password', 82 | labelText: 'Password *', 83 | ), 84 | ), 85 | const Padding(padding: EdgeInsets.all(10.0)), 86 | ElevatedButton( 87 | onPressed: _signIn, 88 | child: const Text('Sign In'), 89 | ), 90 | ErrorView(_signUpError) 91 | ], 92 | ), 93 | ), 94 | ), 95 | ], 96 | ); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: sample_app 2 | description: A new Flutter application. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `pub publish`. This is preferred for private packages. 6 | publish_to: "none" # Remove this line if you wish to publish to pub.dev 7 | 8 | # The following defines the version and build number for your application. 9 | # A version number is three numbers separated by dots, like 1.2.43 10 | # followed by an optional build number separated by a +. 11 | # Both the version and the builder number may be overridden in flutter 12 | # build by specifying --build-name and --build-number, respectively. 13 | # In Android, build-name is used as versionName while build-number used as versionCode. 14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 16 | # Read more about iOS versioning at 17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 18 | version: 1.0.0+1 19 | 20 | environment: 21 | sdk: ">=2.7.0 <3.0.0" 22 | flutter: ">=1.10.0" 23 | 24 | dependencies: 25 | flutter: 26 | sdk: flutter 27 | file_picker: ^1.8.0+1 28 | amplify_flutter: 0.1.4 29 | amplify_analytics_pinpoint: 0.1.4 30 | amplify_auth_cognito: 0.1.4 31 | amplify_storage_s3: 0.1.4 32 | # The following adds the Cupertino Icons font to your application. 33 | # Use with the CupertinoIcons class for iOS style icons. 34 | cupertino_icons: ^0.1.3 35 | 36 | dev_dependencies: 37 | flutter_test: 38 | sdk: flutter 39 | 40 | # For information on the generic Dart part of this file, see the 41 | # following page: https://dart.dev/tools/pub/pubspec 42 | 43 | # The following section is specific to Flutter. 44 | flutter: 45 | # The following line ensures that the Material Icons font is 46 | # included with your application, so that you can use the icons in 47 | # the material Icons class. 48 | uses-material-design: true 49 | 50 | # To add assets to your application, add an assets section, like this: 51 | assets: 52 | - images/image.png 53 | # - images/a_dot_ham.jpeg 54 | 55 | # An image asset can refer to one or more resolution-specific "variants", see 56 | # https://flutter.dev/assets-and-images/#resolution-aware. 57 | 58 | # For details regarding adding assets from package dependencies, see 59 | # https://flutter.dev/assets-and-images/#from-packages 60 | 61 | # To add custom fonts to your application, add a fonts section here, 62 | # in this "flutter" section. Each entry in this list should have a 63 | # "family" key with the font family name, and a "fonts" key with a 64 | # list giving the asset and other descriptors for the font. For 65 | # example: 66 | # fonts: 67 | # - family: Schyler 68 | # fonts: 69 | # - asset: fonts/Schyler-Regular.ttf 70 | # - asset: fonts/Schyler-Italic.ttf 71 | # style: italic 72 | # - family: Trajan Pro 73 | # fonts: 74 | # - asset: fonts/TrajanPro.ttf 75 | # - asset: fonts/TrajanPro_Bold.ttf 76 | # weight: 700 77 | # 78 | # For details regarding fonts from package dependencies, 79 | # see https://flutter.dev/custom-fonts/#from-packages 80 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | platform :ios, '11.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def parse_KV_file(file, separator='=') 14 | file_abs_path = File.expand_path(file) 15 | if !File.exists? file_abs_path 16 | return []; 17 | end 18 | generated_key_values = {} 19 | skip_line_start_symbols = ["#", "/"] 20 | File.foreach(file_abs_path) do |line| 21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } 22 | plugin = line.split(pattern=separator) 23 | if plugin.length == 2 24 | podname = plugin[0].strip() 25 | path = plugin[1].strip() 26 | podpath = File.expand_path("#{path}", file_abs_path) 27 | generated_key_values[podname] = podpath 28 | else 29 | puts "Invalid plugin specification: #{line}" 30 | end 31 | end 32 | generated_key_values 33 | end 34 | 35 | target 'Runner' do 36 | use_frameworks! 37 | use_modular_headers! 38 | 39 | # Flutter Pod 40 | 41 | copied_flutter_dir = File.join(__dir__, 'Flutter') 42 | copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework') 43 | copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec') 44 | unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path) 45 | # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet. 46 | # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration. 47 | # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist. 48 | 49 | generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig') 50 | unless File.exist?(generated_xcode_build_settings_path) 51 | raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first" 52 | end 53 | generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path) 54 | cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR']; 55 | 56 | unless File.exist?(copied_framework_path) 57 | FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir) 58 | end 59 | unless File.exist?(copied_podspec_path) 60 | FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir) 61 | end 62 | end 63 | 64 | # Keep pod path relative so it can be checked into Podfile.lock. 65 | pod 'Flutter', :path => 'Flutter' 66 | 67 | # Plugin Pods 68 | 69 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock 70 | # referring to absolute paths on developers' machines. 71 | system('rm -rf .symlinks') 72 | system('mkdir -p .symlinks/plugins') 73 | plugin_pods = parse_KV_file('../.flutter-plugins') 74 | plugin_pods.each do |name, path| 75 | symlink = File.join('.symlinks', 'plugins', name) 76 | File.symlink(path, symlink) 77 | pod name, :path => File.join(symlink, 'ios') 78 | end 79 | end 80 | 81 | post_install do |installer| 82 | installer.pods_project.targets.each do |target| 83 | target.build_configurations.each do |config| 84 | config.build_settings['ENABLE_BITCODE'] = 'NO' 85 | end 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /lib/Views/SignUpView.dart: -------------------------------------------------------------------------------- 1 | import 'package:amplify_auth_cognito/amplify_auth_cognito.dart'; 2 | import 'package:amplify_flutter/amplify.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:sample_app/Views/ErrorView.dart'; 5 | 6 | class SignUpView extends StatefulWidget { 7 | @override 8 | _SignUpViewState createState() => _SignUpViewState(); 9 | } 10 | 11 | class _SignUpViewState extends State { 12 | final usernameController = TextEditingController(); 13 | final passwordController = TextEditingController(); 14 | final emailController = TextEditingController(); 15 | final phoneController = TextEditingController(); 16 | final confirmationCodeController = TextEditingController(); 17 | 18 | String _signUpError = ""; 19 | bool _isSignedUp = false; 20 | 21 | @override 22 | void initState() { 23 | super.initState(); 24 | } 25 | 26 | void _signUp() async { 27 | setState(() { 28 | _signUpError = ""; 29 | }); 30 | 31 | Map userAttributes = { 32 | "email": emailController.text, 33 | "phone_number": phoneController.text, 34 | }; 35 | try { 36 | SignUpResult res = await Amplify.Auth.signUp( 37 | username: usernameController.text.trim(), 38 | password: passwordController.text.trim(), 39 | options: CognitoSignUpOptions(userAttributes: userAttributes)); 40 | 41 | setState(() { 42 | _isSignedUp = true; 43 | }); 44 | } on AuthException catch (error) { 45 | _setError(error); 46 | } 47 | } 48 | 49 | void _confirmSignUp() async { 50 | setState(() { 51 | _signUpError = ""; 52 | }); 53 | 54 | try { 55 | SignUpResult res = await Amplify.Auth.confirmSignUp( 56 | username: usernameController.text.trim(), 57 | confirmationCode: confirmationCodeController.text.trim()); 58 | Navigator.pop(context, true); 59 | } on AuthException catch (error) { 60 | _setError(error); 61 | } 62 | } 63 | 64 | void _setError(AuthException error) { 65 | setState(() { 66 | _signUpError = error.message; 67 | }); 68 | } 69 | 70 | @override 71 | Widget build(BuildContext context) { 72 | return Row( 73 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 74 | children: [ 75 | Expanded( 76 | // wrap your Column in Expanded 77 | child: Padding( 78 | padding: EdgeInsets.all(10.0), 79 | child: Column( 80 | children: [ 81 | Visibility( 82 | visible: !_isSignedUp, 83 | child: Column(children: [ 84 | TextFormField( 85 | controller: usernameController, 86 | decoration: const InputDecoration( 87 | icon: Icon(Icons.person), 88 | hintText: 'Username', 89 | labelText: 'Username *', 90 | ), 91 | ), 92 | TextFormField( 93 | obscureText: true, 94 | controller: passwordController, 95 | decoration: const InputDecoration( 96 | icon: Icon(Icons.lock), 97 | hintText: 'Password', 98 | labelText: 'Password *', 99 | ), 100 | ), 101 | TextFormField( 102 | controller: emailController, 103 | decoration: const InputDecoration( 104 | icon: Icon(Icons.email), 105 | hintText: 'Email', 106 | labelText: 'Email *', 107 | ), 108 | ), 109 | TextFormField( 110 | controller: phoneController, 111 | decoration: const InputDecoration( 112 | icon: Icon(Icons.phone), 113 | hintText: 'Phone number (WITH AREA CODE)', 114 | labelText: 'Phone number *', 115 | ), 116 | ), 117 | ElevatedButton( 118 | onPressed: _signUp, 119 | child: const Text('Sign Up'), 120 | ), 121 | ]), 122 | ), 123 | Visibility( 124 | visible: _isSignedUp, 125 | child: Column(children: [ 126 | TextFormField( 127 | controller: confirmationCodeController, 128 | decoration: const InputDecoration( 129 | icon: Icon(Icons.confirmation_number), 130 | hintText: 'The code we sent you', 131 | labelText: 'Confirmation Code *', 132 | )), 133 | ElevatedButton( 134 | onPressed: _confirmSignUp, 135 | child: const Text('Confirm Sign Up'), 136 | ), 137 | ])), 138 | const Padding(padding: EdgeInsets.all(10.0)), 139 | ErrorView(_signUpError) 140 | ], 141 | ), 142 | ), 143 | ), 144 | ], 145 | ); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | amplify_analytics_pinpoint: 5 | dependency: "direct main" 6 | description: 7 | name: amplify_analytics_pinpoint 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "0.1.4" 11 | amplify_analytics_plugin_interface: 12 | dependency: transitive 13 | description: 14 | name: amplify_analytics_plugin_interface 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "0.1.4" 18 | amplify_api_plugin_interface: 19 | dependency: transitive 20 | description: 21 | name: amplify_api_plugin_interface 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "0.1.4" 25 | amplify_auth_cognito: 26 | dependency: "direct main" 27 | description: 28 | name: amplify_auth_cognito 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "0.1.4" 32 | amplify_auth_plugin_interface: 33 | dependency: transitive 34 | description: 35 | name: amplify_auth_plugin_interface 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "0.1.4" 39 | amplify_core: 40 | dependency: transitive 41 | description: 42 | name: amplify_core 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "0.1.4" 46 | amplify_datastore_plugin_interface: 47 | dependency: transitive 48 | description: 49 | name: amplify_datastore_plugin_interface 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "0.1.4" 53 | amplify_flutter: 54 | dependency: "direct main" 55 | description: 56 | name: amplify_flutter 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "0.1.4" 60 | amplify_storage_plugin_interface: 61 | dependency: transitive 62 | description: 63 | name: amplify_storage_plugin_interface 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "0.1.4" 67 | amplify_storage_s3: 68 | dependency: "direct main" 69 | description: 70 | name: amplify_storage_s3 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "0.1.4" 74 | async: 75 | dependency: transitive 76 | description: 77 | name: async 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "2.6.1" 81 | boolean_selector: 82 | dependency: transitive 83 | description: 84 | name: boolean_selector 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "2.1.0" 88 | characters: 89 | dependency: transitive 90 | description: 91 | name: characters 92 | url: "https://pub.dartlang.org" 93 | source: hosted 94 | version: "1.1.0" 95 | charcode: 96 | dependency: transitive 97 | description: 98 | name: charcode 99 | url: "https://pub.dartlang.org" 100 | source: hosted 101 | version: "1.2.0" 102 | clock: 103 | dependency: transitive 104 | description: 105 | name: clock 106 | url: "https://pub.dartlang.org" 107 | source: hosted 108 | version: "1.1.0" 109 | collection: 110 | dependency: transitive 111 | description: 112 | name: collection 113 | url: "https://pub.dartlang.org" 114 | source: hosted 115 | version: "1.15.0" 116 | crypto: 117 | dependency: transitive 118 | description: 119 | name: crypto 120 | url: "https://pub.dartlang.org" 121 | source: hosted 122 | version: "3.0.1" 123 | cupertino_icons: 124 | dependency: "direct main" 125 | description: 126 | name: cupertino_icons 127 | url: "https://pub.dartlang.org" 128 | source: hosted 129 | version: "0.1.3" 130 | date_time_format: 131 | dependency: transitive 132 | description: 133 | name: date_time_format 134 | url: "https://pub.dartlang.org" 135 | source: hosted 136 | version: "1.1.1+1" 137 | fake_async: 138 | dependency: transitive 139 | description: 140 | name: fake_async 141 | url: "https://pub.dartlang.org" 142 | source: hosted 143 | version: "1.2.0" 144 | file_picker: 145 | dependency: "direct main" 146 | description: 147 | name: file_picker 148 | url: "https://pub.dartlang.org" 149 | source: hosted 150 | version: "1.10.0" 151 | flutter: 152 | dependency: "direct main" 153 | description: flutter 154 | source: sdk 155 | version: "0.0.0" 156 | flutter_plugin_android_lifecycle: 157 | dependency: transitive 158 | description: 159 | name: flutter_plugin_android_lifecycle 160 | url: "https://pub.dartlang.org" 161 | source: hosted 162 | version: "1.0.11" 163 | flutter_test: 164 | dependency: "direct dev" 165 | description: flutter 166 | source: sdk 167 | version: "0.0.0" 168 | matcher: 169 | dependency: transitive 170 | description: 171 | name: matcher 172 | url: "https://pub.dartlang.org" 173 | source: hosted 174 | version: "0.12.10" 175 | meta: 176 | dependency: transitive 177 | description: 178 | name: meta 179 | url: "https://pub.dartlang.org" 180 | source: hosted 181 | version: "1.3.0" 182 | path: 183 | dependency: transitive 184 | description: 185 | name: path 186 | url: "https://pub.dartlang.org" 187 | source: hosted 188 | version: "1.8.0" 189 | plugin_platform_interface: 190 | dependency: transitive 191 | description: 192 | name: plugin_platform_interface 193 | url: "https://pub.dartlang.org" 194 | source: hosted 195 | version: "2.0.0" 196 | sky_engine: 197 | dependency: transitive 198 | description: flutter 199 | source: sdk 200 | version: "0.0.99" 201 | source_span: 202 | dependency: transitive 203 | description: 204 | name: source_span 205 | url: "https://pub.dartlang.org" 206 | source: hosted 207 | version: "1.8.1" 208 | stack_trace: 209 | dependency: transitive 210 | description: 211 | name: stack_trace 212 | url: "https://pub.dartlang.org" 213 | source: hosted 214 | version: "1.10.0" 215 | stream_channel: 216 | dependency: transitive 217 | description: 218 | name: stream_channel 219 | url: "https://pub.dartlang.org" 220 | source: hosted 221 | version: "2.1.0" 222 | string_scanner: 223 | dependency: transitive 224 | description: 225 | name: string_scanner 226 | url: "https://pub.dartlang.org" 227 | source: hosted 228 | version: "1.1.0" 229 | term_glyph: 230 | dependency: transitive 231 | description: 232 | name: term_glyph 233 | url: "https://pub.dartlang.org" 234 | source: hosted 235 | version: "1.2.0" 236 | test_api: 237 | dependency: transitive 238 | description: 239 | name: test_api 240 | url: "https://pub.dartlang.org" 241 | source: hosted 242 | version: "0.3.0" 243 | typed_data: 244 | dependency: transitive 245 | description: 246 | name: typed_data 247 | url: "https://pub.dartlang.org" 248 | source: hosted 249 | version: "1.3.0" 250 | uuid: 251 | dependency: transitive 252 | description: 253 | name: uuid 254 | url: "https://pub.dartlang.org" 255 | source: hosted 256 | version: "3.0.4" 257 | vector_math: 258 | dependency: transitive 259 | description: 260 | name: vector_math 261 | url: "https://pub.dartlang.org" 262 | source: hosted 263 | version: "2.1.0" 264 | sdks: 265 | dart: ">=2.12.0 <3.0.0" 266 | flutter: ">=1.20.0" 267 | -------------------------------------------------------------------------------- /amplify/backend/awscloudformation/build/auth/cloudchopperd20aa567/cloudchopperd20aa567-cloudformation-template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Parameters: 3 | env: 4 | Type: String 5 | authRoleArn: 6 | Type: String 7 | unauthRoleArn: 8 | Type: String 9 | identityPoolName: 10 | Type: String 11 | allowUnauthenticatedIdentities: 12 | Type: String 13 | resourceNameTruncated: 14 | Type: String 15 | userPoolName: 16 | Type: String 17 | autoVerifiedAttributes: 18 | Type: CommaDelimitedList 19 | mfaConfiguration: 20 | Type: String 21 | mfaTypes: 22 | Type: CommaDelimitedList 23 | smsAuthenticationMessage: 24 | Type: String 25 | smsVerificationMessage: 26 | Type: String 27 | emailVerificationSubject: 28 | Type: String 29 | emailVerificationMessage: 30 | Type: String 31 | defaultPasswordPolicy: 32 | Type: String 33 | passwordPolicyMinLength: 34 | Type: Number 35 | passwordPolicyCharacters: 36 | Type: CommaDelimitedList 37 | requiredAttributes: 38 | Type: CommaDelimitedList 39 | userpoolClientGenerateSecret: 40 | Type: String 41 | userpoolClientRefreshTokenValidity: 42 | Type: Number 43 | userpoolClientWriteAttributes: 44 | Type: CommaDelimitedList 45 | userpoolClientReadAttributes: 46 | Type: CommaDelimitedList 47 | userpoolClientLambdaRole: 48 | Type: String 49 | userpoolClientSetAttributes: 50 | Type: String 51 | sharedId: 52 | Type: String 53 | resourceName: 54 | Type: String 55 | authSelections: 56 | Type: String 57 | useDefault: 58 | Type: String 59 | userPoolGroupList: 60 | Type: CommaDelimitedList 61 | serviceName: 62 | Type: String 63 | usernameCaseSensitive: 64 | Type: String 65 | dependsOn: 66 | Type: CommaDelimitedList 67 | Conditions: 68 | ShouldNotCreateEnvResources: 69 | Fn::Equals: 70 | - Ref: env 71 | - NONE 72 | ShouldOutputAppClientSecrets: 73 | Fn::Equals: 74 | - Ref: userpoolClientGenerateSecret 75 | - 'true' 76 | Resources: 77 | SNSRole: 78 | Type: AWS::IAM::Role 79 | Properties: 80 | RoleName: 81 | Fn::If: 82 | - ShouldNotCreateEnvResources 83 | - cloudcd20aa567_sns-role 84 | - Fn::Join: 85 | - '' 86 | - - sns 87 | - d20aa567 88 | - Fn::Select: 89 | - '3' 90 | - Fn::Split: 91 | - '-' 92 | - Ref: AWS::StackName 93 | - '-' 94 | - Ref: env 95 | AssumeRolePolicyDocument: 96 | Version: '2012-10-17' 97 | Statement: 98 | - Sid: '' 99 | Effect: Allow 100 | Principal: 101 | Service: cognito-idp.amazonaws.com 102 | Action: 103 | - sts:AssumeRole 104 | Condition: 105 | StringEquals: 106 | sts:ExternalId: cloudcd20aa567_role_external_id 107 | Policies: 108 | - PolicyName: cloudcd20aa567-sns-policy 109 | PolicyDocument: 110 | Version: '2012-10-17' 111 | Statement: 112 | - Effect: Allow 113 | Action: 114 | - sns:Publish 115 | Resource: '*' 116 | UserPool: 117 | Type: AWS::Cognito::UserPool 118 | UpdateReplacePolicy: Retain 119 | Properties: 120 | UserPoolName: 121 | Fn::If: 122 | - ShouldNotCreateEnvResources 123 | - Ref: userPoolName 124 | - Fn::Join: 125 | - '' 126 | - - Ref: userPoolName 127 | - '-' 128 | - Ref: env 129 | UsernameConfiguration: 130 | CaseSensitive: 'false' 131 | Schema: 132 | - Name: email 133 | Required: 'true' 134 | Mutable: 'true' 135 | AutoVerifiedAttributes: 136 | Ref: autoVerifiedAttributes 137 | EmailVerificationMessage: 138 | Ref: emailVerificationMessage 139 | EmailVerificationSubject: 140 | Ref: emailVerificationSubject 141 | Policies: 142 | PasswordPolicy: 143 | MinimumLength: 144 | Ref: passwordPolicyMinLength 145 | RequireLowercase: 'false' 146 | RequireNumbers: 'false' 147 | RequireSymbols: 'false' 148 | RequireUppercase: 'false' 149 | MfaConfiguration: 150 | Ref: mfaConfiguration 151 | SmsVerificationMessage: 152 | Ref: smsVerificationMessage 153 | SmsAuthenticationMessage: 154 | Ref: smsAuthenticationMessage 155 | SmsConfiguration: 156 | SnsCallerArn: 157 | Fn::GetAtt: 158 | - SNSRole 159 | - Arn 160 | ExternalId: cloudcd20aa567_role_external_id 161 | UserPoolClientWeb: 162 | Type: AWS::Cognito::UserPoolClient 163 | Properties: 164 | ClientName: cloudcd20aa567_app_clientWeb 165 | RefreshTokenValidity: 166 | Ref: userpoolClientRefreshTokenValidity 167 | UserPoolId: 168 | Ref: UserPool 169 | DependsOn: UserPool 170 | UserPoolClient: 171 | Type: AWS::Cognito::UserPoolClient 172 | Properties: 173 | ClientName: cloudcd20aa567_app_client 174 | GenerateSecret: 175 | Ref: userpoolClientGenerateSecret 176 | RefreshTokenValidity: 177 | Ref: userpoolClientRefreshTokenValidity 178 | UserPoolId: 179 | Ref: UserPool 180 | DependsOn: UserPool 181 | UserPoolClientRole: 182 | Type: AWS::IAM::Role 183 | Properties: 184 | RoleName: 185 | Fn::If: 186 | - ShouldNotCreateEnvResources 187 | - Ref: userpoolClientLambdaRole 188 | - Fn::Join: 189 | - '' 190 | - - upClientLambdaRole 191 | - d20aa567 192 | - Fn::Select: 193 | - '3' 194 | - Fn::Split: 195 | - '-' 196 | - Ref: AWS::StackName 197 | - '-' 198 | - Ref: env 199 | AssumeRolePolicyDocument: 200 | Version: '2012-10-17' 201 | Statement: 202 | - Effect: Allow 203 | Principal: 204 | Service: 205 | - lambda.amazonaws.com 206 | Action: 207 | - sts:AssumeRole 208 | DependsOn: UserPoolClient 209 | UserPoolClientLambda: 210 | Type: AWS::Lambda::Function 211 | Properties: 212 | Code: 213 | ZipFile: 214 | Fn::Join: 215 | - '' 216 | - - const response = require('cfn-response'); 217 | - const aws = require('aws-sdk'); 218 | - const identity = new aws.CognitoIdentityServiceProvider(); 219 | - exports.handler = (event, context, callback) => { 220 | - ' if (event.RequestType == ''Delete'') { ' 221 | - ' response.send(event, context, response.SUCCESS, {})' 222 | - ' }' 223 | - ' if (event.RequestType == ''Update'' || event.RequestType == ''Create'') {' 224 | - ' const params = {' 225 | - ' ClientId: event.ResourceProperties.clientId,' 226 | - ' UserPoolId: event.ResourceProperties.userpoolId' 227 | - ' };' 228 | - ' identity.describeUserPoolClient(params).promise()' 229 | - ' .then((res) => {' 230 | - ' response.send(event, context, response.SUCCESS, {''appSecret'': res.UserPoolClient.ClientSecret});' 231 | - ' })' 232 | - ' .catch((err) => {' 233 | - ' response.send(event, context, response.FAILED, {err});' 234 | - ' });' 235 | - ' }' 236 | - '};' 237 | Handler: index.handler 238 | Runtime: nodejs12.x 239 | Timeout: '300' 240 | Role: 241 | Fn::GetAtt: 242 | - UserPoolClientRole 243 | - Arn 244 | DependsOn: UserPoolClientRole 245 | UserPoolClientLambdaPolicy: 246 | Type: AWS::IAM::Policy 247 | Properties: 248 | PolicyName: cloudcd20aa567_userpoolclient_lambda_iam_policy 249 | Roles: 250 | - Ref: UserPoolClientRole 251 | PolicyDocument: 252 | Version: '2012-10-17' 253 | Statement: 254 | - Effect: Allow 255 | Action: 256 | - cognito-idp:DescribeUserPoolClient 257 | Resource: 258 | Fn::GetAtt: 259 | - UserPool 260 | - Arn 261 | DependsOn: UserPoolClientLambda 262 | UserPoolClientLogPolicy: 263 | Type: AWS::IAM::Policy 264 | Properties: 265 | PolicyName: cloudcd20aa567_userpoolclient_lambda_log_policy 266 | Roles: 267 | - Ref: UserPoolClientRole 268 | PolicyDocument: 269 | Version: '2012-10-17' 270 | Statement: 271 | - Effect: Allow 272 | Action: 273 | - logs:CreateLogGroup 274 | - logs:CreateLogStream 275 | - logs:PutLogEvents 276 | Resource: 277 | Fn::Sub: 278 | - >- 279 | arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:* 280 | - region: 281 | Ref: AWS::Region 282 | account: 283 | Ref: AWS::AccountId 284 | lambda: 285 | Ref: UserPoolClientLambda 286 | DependsOn: UserPoolClientLambdaPolicy 287 | UserPoolClientInputs: 288 | Type: Custom::LambdaCallout 289 | Properties: 290 | ServiceToken: 291 | Fn::GetAtt: 292 | - UserPoolClientLambda 293 | - Arn 294 | clientId: 295 | Ref: UserPoolClient 296 | userpoolId: 297 | Ref: UserPool 298 | DependsOn: UserPoolClientLogPolicy 299 | IdentityPool: 300 | Type: AWS::Cognito::IdentityPool 301 | Properties: 302 | IdentityPoolName: 303 | Fn::If: 304 | - ShouldNotCreateEnvResources 305 | - cloudchopperd20aa567_identitypool_d20aa567 306 | - Fn::Join: 307 | - '' 308 | - - cloudchopperd20aa567_identitypool_d20aa567 309 | - __ 310 | - Ref: env 311 | CognitoIdentityProviders: 312 | - ClientId: 313 | Ref: UserPoolClient 314 | ProviderName: 315 | Fn::Sub: 316 | - cognito-idp.${region}.amazonaws.com/${client} 317 | - region: 318 | Ref: AWS::Region 319 | client: 320 | Ref: UserPool 321 | - ClientId: 322 | Ref: UserPoolClientWeb 323 | ProviderName: 324 | Fn::Sub: 325 | - cognito-idp.${region}.amazonaws.com/${client} 326 | - region: 327 | Ref: AWS::Region 328 | client: 329 | Ref: UserPool 330 | AllowUnauthenticatedIdentities: 331 | Ref: allowUnauthenticatedIdentities 332 | DependsOn: UserPoolClientInputs 333 | IdentityPoolRoleMap: 334 | Type: AWS::Cognito::IdentityPoolRoleAttachment 335 | Properties: 336 | IdentityPoolId: 337 | Ref: IdentityPool 338 | Roles: 339 | unauthenticated: 340 | Ref: unauthRoleArn 341 | authenticated: 342 | Ref: authRoleArn 343 | DependsOn: IdentityPool 344 | Outputs: 345 | IdentityPoolId: 346 | Value: 347 | Ref: IdentityPool 348 | Description: Id for the identity pool 349 | IdentityPoolName: 350 | Value: 351 | Fn::GetAtt: 352 | - IdentityPool 353 | - Name 354 | UserPoolId: 355 | Value: 356 | Ref: UserPool 357 | Description: Id for the user pool 358 | UserPoolName: 359 | Value: 360 | Ref: userPoolName 361 | AppClientIDWeb: 362 | Value: 363 | Ref: UserPoolClientWeb 364 | Description: The user pool app client id for web 365 | AppClientID: 366 | Value: 367 | Ref: UserPoolClient 368 | Description: The user pool app client id 369 | AppClientSecret: 370 | Value: 371 | Fn::GetAtt: 372 | - UserPoolClientInputs 373 | - appSecret 374 | Condition: ShouldOutputAppClientSecrets 375 | -------------------------------------------------------------------------------- /amplify/backend/auth/cloudchopperd20aa567/cloudchopperd20aa567-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 | 18 | 19 | allowUnauthenticatedIdentities: 20 | Type: String 21 | 22 | resourceNameTruncated: 23 | Type: String 24 | 25 | 26 | userPoolName: 27 | Type: String 28 | 29 | 30 | 31 | autoVerifiedAttributes: 32 | Type: CommaDelimitedList 33 | 34 | mfaConfiguration: 35 | Type: String 36 | 37 | 38 | 39 | mfaTypes: 40 | Type: CommaDelimitedList 41 | 42 | smsAuthenticationMessage: 43 | Type: String 44 | 45 | 46 | smsVerificationMessage: 47 | Type: String 48 | 49 | 50 | emailVerificationSubject: 51 | Type: String 52 | 53 | 54 | emailVerificationMessage: 55 | Type: String 56 | 57 | 58 | 59 | defaultPasswordPolicy: 60 | Type: String 61 | 62 | 63 | passwordPolicyMinLength: 64 | Type: Number 65 | 66 | 67 | passwordPolicyCharacters: 68 | Type: CommaDelimitedList 69 | 70 | 71 | requiredAttributes: 72 | Type: CommaDelimitedList 73 | 74 | 75 | userpoolClientGenerateSecret: 76 | Type: String 77 | 78 | 79 | userpoolClientRefreshTokenValidity: 80 | Type: Number 81 | 82 | 83 | userpoolClientWriteAttributes: 84 | Type: CommaDelimitedList 85 | 86 | 87 | userpoolClientReadAttributes: 88 | Type: CommaDelimitedList 89 | 90 | userpoolClientLambdaRole: 91 | Type: String 92 | 93 | 94 | 95 | userpoolClientSetAttributes: 96 | Type: String 97 | 98 | sharedId: 99 | Type: String 100 | 101 | 102 | resourceName: 103 | Type: String 104 | 105 | 106 | authSelections: 107 | Type: String 108 | 109 | 110 | 111 | 112 | useDefault: 113 | Type: String 114 | 115 | 116 | 117 | userPoolGroupList: 118 | Type: CommaDelimitedList 119 | 120 | serviceName: 121 | Type: String 122 | 123 | 124 | 125 | usernameCaseSensitive: 126 | Type: String 127 | 128 | 129 | dependsOn: 130 | Type: CommaDelimitedList 131 | 132 | Conditions: 133 | ShouldNotCreateEnvResources: !Equals [ !Ref env, NONE ] 134 | 135 | ShouldOutputAppClientSecrets: !Equals [!Ref userpoolClientGenerateSecret, true ] 136 | 137 | 138 | Resources: 139 | 140 | 141 | # BEGIN SNS ROLE RESOURCE 142 | SNSRole: 143 | # Created to allow the UserPool SMS Config to publish via the Simple Notification Service during MFA Process 144 | Type: AWS::IAM::Role 145 | Properties: 146 | RoleName: !If [ShouldNotCreateEnvResources, 'cloudcd20aa567_sns-role', !Join ['',[ 'sns', 'd20aa567', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]] 147 | AssumeRolePolicyDocument: 148 | Version: "2012-10-17" 149 | Statement: 150 | - Sid: "" 151 | Effect: "Allow" 152 | Principal: 153 | Service: "cognito-idp.amazonaws.com" 154 | Action: 155 | - "sts:AssumeRole" 156 | Condition: 157 | StringEquals: 158 | sts:ExternalId: cloudcd20aa567_role_external_id 159 | Policies: 160 | - 161 | PolicyName: cloudcd20aa567-sns-policy 162 | PolicyDocument: 163 | Version: "2012-10-17" 164 | Statement: 165 | - 166 | Effect: "Allow" 167 | Action: 168 | - "sns:Publish" 169 | Resource: "*" 170 | # BEGIN USER POOL RESOURCES 171 | UserPool: 172 | # Created upon user selection 173 | # Depends on SNS Role for Arn if MFA is enabled 174 | Type: AWS::Cognito::UserPool 175 | UpdateReplacePolicy: Retain 176 | Properties: 177 | UserPoolName: !If [ShouldNotCreateEnvResources, !Ref userPoolName, !Join ['',[!Ref userPoolName, '-', !Ref env]]] 178 | 179 | 180 | UsernameConfiguration: 181 | CaseSensitive: false 182 | 183 | Schema: 184 | 185 | - 186 | Name: email 187 | Required: true 188 | Mutable: true 189 | 190 | 191 | 192 | 193 | AutoVerifiedAttributes: !Ref autoVerifiedAttributes 194 | 195 | 196 | EmailVerificationMessage: !Ref emailVerificationMessage 197 | EmailVerificationSubject: !Ref emailVerificationSubject 198 | 199 | Policies: 200 | PasswordPolicy: 201 | MinimumLength: !Ref passwordPolicyMinLength 202 | RequireLowercase: false 203 | RequireNumbers: false 204 | RequireSymbols: false 205 | RequireUppercase: false 206 | 207 | MfaConfiguration: !Ref mfaConfiguration 208 | SmsVerificationMessage: !Ref smsVerificationMessage 209 | SmsAuthenticationMessage: !Ref smsAuthenticationMessage 210 | SmsConfiguration: 211 | SnsCallerArn: !GetAtt SNSRole.Arn 212 | ExternalId: cloudcd20aa567_role_external_id 213 | 214 | 215 | UserPoolClientWeb: 216 | # Created provide application access to user pool 217 | # Depends on UserPool for ID reference 218 | Type: "AWS::Cognito::UserPoolClient" 219 | Properties: 220 | ClientName: cloudcd20aa567_app_clientWeb 221 | 222 | RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity 223 | UserPoolId: !Ref UserPool 224 | DependsOn: UserPool 225 | UserPoolClient: 226 | # Created provide application access to user pool 227 | # Depends on UserPool for ID reference 228 | Type: "AWS::Cognito::UserPoolClient" 229 | Properties: 230 | ClientName: cloudcd20aa567_app_client 231 | 232 | GenerateSecret: !Ref userpoolClientGenerateSecret 233 | RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity 234 | UserPoolId: !Ref UserPool 235 | DependsOn: UserPool 236 | # BEGIN USER POOL LAMBDA RESOURCES 237 | UserPoolClientRole: 238 | # Created to execute Lambda which gets userpool app client config values 239 | Type: 'AWS::IAM::Role' 240 | Properties: 241 | RoleName: !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',['upClientLambdaRole', 'd20aa567', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]] 242 | AssumeRolePolicyDocument: 243 | Version: '2012-10-17' 244 | Statement: 245 | - Effect: Allow 246 | Principal: 247 | Service: 248 | - lambda.amazonaws.com 249 | Action: 250 | - 'sts:AssumeRole' 251 | DependsOn: UserPoolClient 252 | UserPoolClientLambda: 253 | # Lambda which gets userpool app client config values 254 | # Depends on UserPool for id 255 | # Depends on UserPoolClientRole for role ARN 256 | Type: 'AWS::Lambda::Function' 257 | Properties: 258 | Code: 259 | ZipFile: !Join 260 | - |+ 261 | - - 'const response = require(''cfn-response'');' 262 | - 'const aws = require(''aws-sdk'');' 263 | - 'const identity = new aws.CognitoIdentityServiceProvider();' 264 | - 'exports.handler = (event, context, callback) => {' 265 | - ' if (event.RequestType == ''Delete'') { ' 266 | - ' response.send(event, context, response.SUCCESS, {})' 267 | - ' }' 268 | - ' if (event.RequestType == ''Update'' || event.RequestType == ''Create'') {' 269 | - ' const params = {' 270 | - ' ClientId: event.ResourceProperties.clientId,' 271 | - ' UserPoolId: event.ResourceProperties.userpoolId' 272 | - ' };' 273 | - ' identity.describeUserPoolClient(params).promise()' 274 | - ' .then((res) => {' 275 | - ' response.send(event, context, response.SUCCESS, {''appSecret'': res.UserPoolClient.ClientSecret});' 276 | - ' })' 277 | - ' .catch((err) => {' 278 | - ' response.send(event, context, response.FAILED, {err});' 279 | - ' });' 280 | - ' }' 281 | - '};' 282 | Handler: index.handler 283 | Runtime: nodejs12.x 284 | Timeout: '300' 285 | Role: !GetAtt 286 | - UserPoolClientRole 287 | - Arn 288 | DependsOn: UserPoolClientRole 289 | UserPoolClientLambdaPolicy: 290 | # Sets userpool policy for the role that executes the Userpool Client Lambda 291 | # Depends on UserPool for Arn 292 | # Marked as depending on UserPoolClientRole for easier to understand CFN sequencing 293 | Type: 'AWS::IAM::Policy' 294 | Properties: 295 | PolicyName: cloudcd20aa567_userpoolclient_lambda_iam_policy 296 | Roles: 297 | - !Ref UserPoolClientRole 298 | PolicyDocument: 299 | Version: '2012-10-17' 300 | Statement: 301 | - Effect: Allow 302 | Action: 303 | - 'cognito-idp:DescribeUserPoolClient' 304 | Resource: !GetAtt UserPool.Arn 305 | DependsOn: UserPoolClientLambda 306 | UserPoolClientLogPolicy: 307 | # Sets log policy for the role that executes the Userpool Client Lambda 308 | # Depends on UserPool for Arn 309 | # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing 310 | Type: 'AWS::IAM::Policy' 311 | Properties: 312 | PolicyName: cloudcd20aa567_userpoolclient_lambda_log_policy 313 | Roles: 314 | - !Ref UserPoolClientRole 315 | PolicyDocument: 316 | Version: 2012-10-17 317 | Statement: 318 | - Effect: Allow 319 | Action: 320 | - 'logs:CreateLogGroup' 321 | - 'logs:CreateLogStream' 322 | - 'logs:PutLogEvents' 323 | Resource: !Sub 324 | - arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:* 325 | - { region: !Ref "AWS::Region", account: !Ref "AWS::AccountId", lambda: !Ref UserPoolClientLambda} 326 | DependsOn: UserPoolClientLambdaPolicy 327 | UserPoolClientInputs: 328 | # Values passed to Userpool client Lambda 329 | # Depends on UserPool for Id 330 | # Depends on UserPoolClient for Id 331 | # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing 332 | Type: 'Custom::LambdaCallout' 333 | Properties: 334 | ServiceToken: !GetAtt UserPoolClientLambda.Arn 335 | clientId: !Ref UserPoolClient 336 | userpoolId: !Ref UserPool 337 | DependsOn: UserPoolClientLogPolicy 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | # BEGIN IDENTITY POOL RESOURCES 346 | 347 | 348 | IdentityPool: 349 | # Always created 350 | Type: AWS::Cognito::IdentityPool 351 | Properties: 352 | IdentityPoolName: !If [ShouldNotCreateEnvResources, 'cloudchopperd20aa567_identitypool_d20aa567', !Join ['',['cloudchopperd20aa567_identitypool_d20aa567', '__', !Ref env]]] 353 | 354 | CognitoIdentityProviders: 355 | - ClientId: !Ref UserPoolClient 356 | ProviderName: !Sub 357 | - cognito-idp.${region}.amazonaws.com/${client} 358 | - { region: !Ref "AWS::Region", client: !Ref UserPool} 359 | - ClientId: !Ref UserPoolClientWeb 360 | ProviderName: !Sub 361 | - cognito-idp.${region}.amazonaws.com/${client} 362 | - { region: !Ref "AWS::Region", client: !Ref UserPool} 363 | 364 | AllowUnauthenticatedIdentities: !Ref allowUnauthenticatedIdentities 365 | 366 | 367 | DependsOn: UserPoolClientInputs 368 | 369 | 370 | IdentityPoolRoleMap: 371 | # Created to map Auth and Unauth roles to the identity pool 372 | # Depends on Identity Pool for ID ref 373 | Type: AWS::Cognito::IdentityPoolRoleAttachment 374 | Properties: 375 | IdentityPoolId: !Ref IdentityPool 376 | Roles: 377 | unauthenticated: !Ref unauthRoleArn 378 | authenticated: !Ref authRoleArn 379 | DependsOn: IdentityPool 380 | 381 | 382 | Outputs : 383 | 384 | IdentityPoolId: 385 | Value: !Ref 'IdentityPool' 386 | Description: Id for the identity pool 387 | IdentityPoolName: 388 | Value: !GetAtt IdentityPool.Name 389 | 390 | 391 | 392 | 393 | UserPoolId: 394 | Value: !Ref 'UserPool' 395 | Description: Id for the user pool 396 | UserPoolName: 397 | Value: !Ref userPoolName 398 | AppClientIDWeb: 399 | Value: !Ref 'UserPoolClientWeb' 400 | Description: The user pool app client id for web 401 | AppClientID: 402 | Value: !Ref 'UserPoolClient' 403 | Description: The user pool app client id 404 | AppClientSecret: 405 | Value: !GetAtt UserPoolClientInputs.appSecret 406 | Condition: ShouldOutputAppClientSecrets 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | -------------------------------------------------------------------------------- /amplify/#current-cloud-backend/auth/cloudchopperd20aa567/cloudchopperd20aa567-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 | 18 | 19 | allowUnauthenticatedIdentities: 20 | Type: String 21 | 22 | resourceNameTruncated: 23 | Type: String 24 | 25 | 26 | userPoolName: 27 | Type: String 28 | 29 | 30 | 31 | autoVerifiedAttributes: 32 | Type: CommaDelimitedList 33 | 34 | mfaConfiguration: 35 | Type: String 36 | 37 | 38 | 39 | mfaTypes: 40 | Type: CommaDelimitedList 41 | 42 | smsAuthenticationMessage: 43 | Type: String 44 | 45 | 46 | smsVerificationMessage: 47 | Type: String 48 | 49 | 50 | emailVerificationSubject: 51 | Type: String 52 | 53 | 54 | emailVerificationMessage: 55 | Type: String 56 | 57 | 58 | 59 | defaultPasswordPolicy: 60 | Type: String 61 | 62 | 63 | passwordPolicyMinLength: 64 | Type: Number 65 | 66 | 67 | passwordPolicyCharacters: 68 | Type: CommaDelimitedList 69 | 70 | 71 | requiredAttributes: 72 | Type: CommaDelimitedList 73 | 74 | 75 | userpoolClientGenerateSecret: 76 | Type: String 77 | 78 | 79 | userpoolClientRefreshTokenValidity: 80 | Type: Number 81 | 82 | 83 | userpoolClientWriteAttributes: 84 | Type: CommaDelimitedList 85 | 86 | 87 | userpoolClientReadAttributes: 88 | Type: CommaDelimitedList 89 | 90 | userpoolClientLambdaRole: 91 | Type: String 92 | 93 | 94 | 95 | userpoolClientSetAttributes: 96 | Type: String 97 | 98 | sharedId: 99 | Type: String 100 | 101 | 102 | resourceName: 103 | Type: String 104 | 105 | 106 | authSelections: 107 | Type: String 108 | 109 | 110 | 111 | 112 | useDefault: 113 | Type: String 114 | 115 | 116 | 117 | userPoolGroupList: 118 | Type: CommaDelimitedList 119 | 120 | serviceName: 121 | Type: String 122 | 123 | 124 | 125 | usernameCaseSensitive: 126 | Type: String 127 | 128 | 129 | dependsOn: 130 | Type: CommaDelimitedList 131 | 132 | Conditions: 133 | ShouldNotCreateEnvResources: !Equals [ !Ref env, NONE ] 134 | 135 | ShouldOutputAppClientSecrets: !Equals [!Ref userpoolClientGenerateSecret, true ] 136 | 137 | 138 | Resources: 139 | 140 | 141 | # BEGIN SNS ROLE RESOURCE 142 | SNSRole: 143 | # Created to allow the UserPool SMS Config to publish via the Simple Notification Service during MFA Process 144 | Type: AWS::IAM::Role 145 | Properties: 146 | RoleName: !If [ShouldNotCreateEnvResources, 'cloudcd20aa567_sns-role', !Join ['',[ 'sns', 'd20aa567', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]] 147 | AssumeRolePolicyDocument: 148 | Version: "2012-10-17" 149 | Statement: 150 | - Sid: "" 151 | Effect: "Allow" 152 | Principal: 153 | Service: "cognito-idp.amazonaws.com" 154 | Action: 155 | - "sts:AssumeRole" 156 | Condition: 157 | StringEquals: 158 | sts:ExternalId: cloudcd20aa567_role_external_id 159 | Policies: 160 | - 161 | PolicyName: cloudcd20aa567-sns-policy 162 | PolicyDocument: 163 | Version: "2012-10-17" 164 | Statement: 165 | - 166 | Effect: "Allow" 167 | Action: 168 | - "sns:Publish" 169 | Resource: "*" 170 | # BEGIN USER POOL RESOURCES 171 | UserPool: 172 | # Created upon user selection 173 | # Depends on SNS Role for Arn if MFA is enabled 174 | Type: AWS::Cognito::UserPool 175 | UpdateReplacePolicy: Retain 176 | Properties: 177 | UserPoolName: !If [ShouldNotCreateEnvResources, !Ref userPoolName, !Join ['',[!Ref userPoolName, '-', !Ref env]]] 178 | 179 | 180 | UsernameConfiguration: 181 | CaseSensitive: false 182 | 183 | Schema: 184 | 185 | - 186 | Name: email 187 | Required: true 188 | Mutable: true 189 | 190 | 191 | 192 | 193 | AutoVerifiedAttributes: !Ref autoVerifiedAttributes 194 | 195 | 196 | EmailVerificationMessage: !Ref emailVerificationMessage 197 | EmailVerificationSubject: !Ref emailVerificationSubject 198 | 199 | Policies: 200 | PasswordPolicy: 201 | MinimumLength: !Ref passwordPolicyMinLength 202 | RequireLowercase: false 203 | RequireNumbers: false 204 | RequireSymbols: false 205 | RequireUppercase: false 206 | 207 | MfaConfiguration: !Ref mfaConfiguration 208 | SmsVerificationMessage: !Ref smsVerificationMessage 209 | SmsAuthenticationMessage: !Ref smsAuthenticationMessage 210 | SmsConfiguration: 211 | SnsCallerArn: !GetAtt SNSRole.Arn 212 | ExternalId: cloudcd20aa567_role_external_id 213 | 214 | 215 | UserPoolClientWeb: 216 | # Created provide application access to user pool 217 | # Depends on UserPool for ID reference 218 | Type: "AWS::Cognito::UserPoolClient" 219 | Properties: 220 | ClientName: cloudcd20aa567_app_clientWeb 221 | 222 | RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity 223 | UserPoolId: !Ref UserPool 224 | DependsOn: UserPool 225 | UserPoolClient: 226 | # Created provide application access to user pool 227 | # Depends on UserPool for ID reference 228 | Type: "AWS::Cognito::UserPoolClient" 229 | Properties: 230 | ClientName: cloudcd20aa567_app_client 231 | 232 | GenerateSecret: !Ref userpoolClientGenerateSecret 233 | RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity 234 | UserPoolId: !Ref UserPool 235 | DependsOn: UserPool 236 | # BEGIN USER POOL LAMBDA RESOURCES 237 | UserPoolClientRole: 238 | # Created to execute Lambda which gets userpool app client config values 239 | Type: 'AWS::IAM::Role' 240 | Properties: 241 | RoleName: !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',['upClientLambdaRole', 'd20aa567', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]] 242 | AssumeRolePolicyDocument: 243 | Version: '2012-10-17' 244 | Statement: 245 | - Effect: Allow 246 | Principal: 247 | Service: 248 | - lambda.amazonaws.com 249 | Action: 250 | - 'sts:AssumeRole' 251 | DependsOn: UserPoolClient 252 | UserPoolClientLambda: 253 | # Lambda which gets userpool app client config values 254 | # Depends on UserPool for id 255 | # Depends on UserPoolClientRole for role ARN 256 | Type: 'AWS::Lambda::Function' 257 | Properties: 258 | Code: 259 | ZipFile: !Join 260 | - |+ 261 | - - 'const response = require(''cfn-response'');' 262 | - 'const aws = require(''aws-sdk'');' 263 | - 'const identity = new aws.CognitoIdentityServiceProvider();' 264 | - 'exports.handler = (event, context, callback) => {' 265 | - ' if (event.RequestType == ''Delete'') { ' 266 | - ' response.send(event, context, response.SUCCESS, {})' 267 | - ' }' 268 | - ' if (event.RequestType == ''Update'' || event.RequestType == ''Create'') {' 269 | - ' const params = {' 270 | - ' ClientId: event.ResourceProperties.clientId,' 271 | - ' UserPoolId: event.ResourceProperties.userpoolId' 272 | - ' };' 273 | - ' identity.describeUserPoolClient(params).promise()' 274 | - ' .then((res) => {' 275 | - ' response.send(event, context, response.SUCCESS, {''appSecret'': res.UserPoolClient.ClientSecret});' 276 | - ' })' 277 | - ' .catch((err) => {' 278 | - ' response.send(event, context, response.FAILED, {err});' 279 | - ' });' 280 | - ' }' 281 | - '};' 282 | Handler: index.handler 283 | Runtime: nodejs12.x 284 | Timeout: '300' 285 | Role: !GetAtt 286 | - UserPoolClientRole 287 | - Arn 288 | DependsOn: UserPoolClientRole 289 | UserPoolClientLambdaPolicy: 290 | # Sets userpool policy for the role that executes the Userpool Client Lambda 291 | # Depends on UserPool for Arn 292 | # Marked as depending on UserPoolClientRole for easier to understand CFN sequencing 293 | Type: 'AWS::IAM::Policy' 294 | Properties: 295 | PolicyName: cloudcd20aa567_userpoolclient_lambda_iam_policy 296 | Roles: 297 | - !Ref UserPoolClientRole 298 | PolicyDocument: 299 | Version: '2012-10-17' 300 | Statement: 301 | - Effect: Allow 302 | Action: 303 | - 'cognito-idp:DescribeUserPoolClient' 304 | Resource: !GetAtt UserPool.Arn 305 | DependsOn: UserPoolClientLambda 306 | UserPoolClientLogPolicy: 307 | # Sets log policy for the role that executes the Userpool Client Lambda 308 | # Depends on UserPool for Arn 309 | # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing 310 | Type: 'AWS::IAM::Policy' 311 | Properties: 312 | PolicyName: cloudcd20aa567_userpoolclient_lambda_log_policy 313 | Roles: 314 | - !Ref UserPoolClientRole 315 | PolicyDocument: 316 | Version: 2012-10-17 317 | Statement: 318 | - Effect: Allow 319 | Action: 320 | - 'logs:CreateLogGroup' 321 | - 'logs:CreateLogStream' 322 | - 'logs:PutLogEvents' 323 | Resource: !Sub 324 | - arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:* 325 | - { region: !Ref "AWS::Region", account: !Ref "AWS::AccountId", lambda: !Ref UserPoolClientLambda} 326 | DependsOn: UserPoolClientLambdaPolicy 327 | UserPoolClientInputs: 328 | # Values passed to Userpool client Lambda 329 | # Depends on UserPool for Id 330 | # Depends on UserPoolClient for Id 331 | # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing 332 | Type: 'Custom::LambdaCallout' 333 | Properties: 334 | ServiceToken: !GetAtt UserPoolClientLambda.Arn 335 | clientId: !Ref UserPoolClient 336 | userpoolId: !Ref UserPool 337 | DependsOn: UserPoolClientLogPolicy 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | # BEGIN IDENTITY POOL RESOURCES 346 | 347 | 348 | IdentityPool: 349 | # Always created 350 | Type: AWS::Cognito::IdentityPool 351 | Properties: 352 | IdentityPoolName: !If [ShouldNotCreateEnvResources, 'cloudchopperd20aa567_identitypool_d20aa567', !Join ['',['cloudchopperd20aa567_identitypool_d20aa567', '__', !Ref env]]] 353 | 354 | CognitoIdentityProviders: 355 | - ClientId: !Ref UserPoolClient 356 | ProviderName: !Sub 357 | - cognito-idp.${region}.amazonaws.com/${client} 358 | - { region: !Ref "AWS::Region", client: !Ref UserPool} 359 | - ClientId: !Ref UserPoolClientWeb 360 | ProviderName: !Sub 361 | - cognito-idp.${region}.amazonaws.com/${client} 362 | - { region: !Ref "AWS::Region", client: !Ref UserPool} 363 | 364 | AllowUnauthenticatedIdentities: !Ref allowUnauthenticatedIdentities 365 | 366 | 367 | DependsOn: UserPoolClientInputs 368 | 369 | 370 | IdentityPoolRoleMap: 371 | # Created to map Auth and Unauth roles to the identity pool 372 | # Depends on Identity Pool for ID ref 373 | Type: AWS::Cognito::IdentityPoolRoleAttachment 374 | Properties: 375 | IdentityPoolId: !Ref IdentityPool 376 | Roles: 377 | unauthenticated: !Ref unauthRoleArn 378 | authenticated: !Ref authRoleArn 379 | DependsOn: IdentityPool 380 | 381 | 382 | Outputs : 383 | 384 | IdentityPoolId: 385 | Value: !Ref 'IdentityPool' 386 | Description: Id for the identity pool 387 | IdentityPoolName: 388 | Value: !GetAtt IdentityPool.Name 389 | 390 | 391 | 392 | 393 | UserPoolId: 394 | Value: !Ref 'UserPool' 395 | Description: Id for the user pool 396 | UserPoolName: 397 | Value: !Ref userPoolName 398 | AppClientIDWeb: 399 | Value: !Ref 'UserPoolClientWeb' 400 | Description: The user pool app client id for web 401 | AppClientID: 402 | Value: !Ref 'UserPoolClient' 403 | Description: The user pool app client id 404 | AppClientSecret: 405 | Value: !GetAtt UserPoolClientInputs.appSecret 406 | Condition: ShouldOutputAppClientSecrets 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | -------------------------------------------------------------------------------- /amplify/backend/storage/S3chopperthao/s3-cloudformation-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Description": "S3 resource stack creation using Amplify CLI", 4 | "Parameters": { 5 | "bucketName": { 6 | "Type": "String" 7 | }, 8 | "authPolicyName": { 9 | "Type": "String" 10 | }, 11 | "unauthPolicyName": { 12 | "Type": "String" 13 | }, 14 | "authRoleName": { 15 | "Type": "String" 16 | }, 17 | "unauthRoleName": { 18 | "Type": "String" 19 | }, 20 | "s3PublicPolicy": { 21 | "Type": "String", 22 | "Default" : "NONE" 23 | }, 24 | "s3PrivatePolicy": { 25 | "Type": "String", 26 | "Default" : "NONE" 27 | }, 28 | "s3ProtectedPolicy": { 29 | "Type": "String", 30 | "Default" : "NONE" 31 | }, 32 | "s3UploadsPolicy": { 33 | "Type": "String", 34 | "Default" : "NONE" 35 | }, 36 | "s3ReadPolicy": { 37 | "Type": "String", 38 | "Default" : "NONE" 39 | }, 40 | "s3PermissionsAuthenticatedPublic": { 41 | "Type": "String", 42 | "Default" : "DISALLOW" 43 | }, 44 | "s3PermissionsAuthenticatedProtected": { 45 | "Type": "String", 46 | "Default" : "DISALLOW" 47 | }, 48 | "s3PermissionsAuthenticatedPrivate": { 49 | "Type": "String", 50 | "Default" : "DISALLOW" 51 | }, 52 | "s3PermissionsAuthenticatedUploads": { 53 | "Type": "String", 54 | "Default" : "DISALLOW" 55 | }, 56 | "s3PermissionsGuestPublic": { 57 | "Type": "String", 58 | "Default" : "DISALLOW" 59 | }, 60 | "s3PermissionsGuestUploads": { 61 | "Type": "String", 62 | "Default" : "DISALLOW" }, 63 | "AuthenticatedAllowList": { 64 | "Type": "String", 65 | "Default" : "DISALLOW" 66 | }, 67 | "GuestAllowList": { 68 | "Type": "String", 69 | "Default" : "DISALLOW" 70 | }, 71 | "selectedGuestPermissions": { 72 | "Type": "CommaDelimitedList", 73 | "Default" : "NONE" 74 | }, 75 | "selectedAuthenticatedPermissions": { 76 | "Type": "CommaDelimitedList", 77 | "Default" : "NONE" 78 | }, 79 | "env": { 80 | "Type": "String" 81 | }, 82 | "triggerFunction": { 83 | "Type": "String" 84 | } 85 | 86 | 87 | }, 88 | "Conditions": { 89 | "ShouldNotCreateEnvResources": { 90 | "Fn::Equals": [ 91 | { 92 | "Ref": "env" 93 | }, 94 | "NONE" 95 | ] 96 | }, 97 | "CreateAuthPublic": { 98 | "Fn::Not" : [{ 99 | "Fn::Equals" : [ 100 | {"Ref" : "s3PermissionsAuthenticatedPublic"}, 101 | "DISALLOW" 102 | ] 103 | }] 104 | }, 105 | "CreateAuthProtected": { 106 | "Fn::Not" : [{ 107 | "Fn::Equals" : [ 108 | {"Ref" : "s3PermissionsAuthenticatedProtected"}, 109 | "DISALLOW" 110 | ] 111 | }] 112 | }, 113 | "CreateAuthPrivate": { 114 | "Fn::Not" : [{ 115 | "Fn::Equals" : [ 116 | {"Ref" : "s3PermissionsAuthenticatedPrivate"}, 117 | "DISALLOW" 118 | ] 119 | }] 120 | }, 121 | "CreateAuthUploads": { 122 | "Fn::Not" : [{ 123 | "Fn::Equals" : [ 124 | {"Ref" : "s3PermissionsAuthenticatedUploads"}, 125 | "DISALLOW" 126 | ] 127 | }] 128 | }, 129 | "CreateGuestPublic": { 130 | "Fn::Not" : [{ 131 | "Fn::Equals" : [ 132 | {"Ref" : "s3PermissionsGuestPublic"}, 133 | "DISALLOW" 134 | ] 135 | }] 136 | }, 137 | "CreateGuestUploads": { 138 | "Fn::Not" : [{ 139 | "Fn::Equals" : [ 140 | {"Ref" : "s3PermissionsGuestUploads"}, 141 | "DISALLOW" 142 | ] 143 | }] 144 | }, 145 | "AuthReadAndList": { 146 | "Fn::Not" : [{ 147 | "Fn::Equals" : [ 148 | {"Ref" : "AuthenticatedAllowList"}, 149 | "DISALLOW" 150 | ] 151 | }] 152 | }, 153 | "GuestReadAndList": { 154 | "Fn::Not" : [{ 155 | "Fn::Equals" : [ 156 | {"Ref" : "GuestAllowList"}, 157 | "DISALLOW" 158 | ] 159 | }] 160 | } 161 | }, 162 | "Resources": { 163 | "S3Bucket": { 164 | "Type": "AWS::S3::Bucket", 165 | 166 | "DeletionPolicy" : "Retain", 167 | "Properties": { 168 | "BucketName": { 169 | "Fn::If": [ 170 | "ShouldNotCreateEnvResources", 171 | { 172 | "Ref": "bucketName" 173 | }, 174 | { 175 | "Fn::Join": [ 176 | "", 177 | [ 178 | { 179 | "Ref": "bucketName" 180 | }, 181 | { 182 | "Fn::Select": [ 183 | 3, 184 | { 185 | "Fn::Split": [ 186 | "-", 187 | { 188 | "Ref": "AWS::StackName" 189 | } 190 | ] 191 | } 192 | ] 193 | }, 194 | "-", 195 | { 196 | "Ref": "env" 197 | } 198 | ] 199 | ] 200 | } 201 | ] 202 | }, 203 | 204 | "CorsConfiguration": { 205 | "CorsRules": [ 206 | { 207 | "AllowedHeaders": [ 208 | "*" 209 | ], 210 | "AllowedMethods": [ 211 | "GET", 212 | "HEAD", 213 | "PUT", 214 | "POST", 215 | "DELETE" 216 | ], 217 | "AllowedOrigins": [ 218 | "*" 219 | ], 220 | "ExposedHeaders": [ 221 | "x-amz-server-side-encryption", 222 | "x-amz-request-id", 223 | "x-amz-id-2", 224 | "ETag" 225 | ], 226 | "Id": "S3CORSRuleId1", 227 | "MaxAge": "3000" 228 | } 229 | ] 230 | } 231 | } 232 | }, 233 | 234 | 235 | "S3AuthPublicPolicy": { 236 | "DependsOn": [ 237 | "S3Bucket" 238 | ], 239 | "Condition": "CreateAuthPublic", 240 | "Type": "AWS::IAM::Policy", 241 | "Properties": { 242 | "PolicyName": { 243 | "Ref": "s3PublicPolicy" 244 | }, 245 | "Roles": [ 246 | { 247 | "Ref": "authRoleName" 248 | } 249 | ], 250 | "PolicyDocument": { 251 | "Version": "2012-10-17", 252 | "Statement": [ 253 | { 254 | "Effect": "Allow", 255 | "Action": { 256 | "Fn::Split" : [ "," , { 257 | "Ref": "s3PermissionsAuthenticatedPublic" 258 | } ] 259 | }, 260 | "Resource": [ 261 | { 262 | "Fn::Join": [ 263 | "", 264 | [ 265 | "arn:aws:s3:::", 266 | { 267 | "Ref": "S3Bucket" 268 | }, 269 | "/public/*" 270 | ] 271 | ] 272 | } 273 | ] 274 | } 275 | ] 276 | } 277 | } 278 | }, 279 | "S3AuthProtectedPolicy": { 280 | "DependsOn": [ 281 | "S3Bucket" 282 | ], 283 | "Condition": "CreateAuthProtected", 284 | "Type": "AWS::IAM::Policy", 285 | "Properties": { 286 | "PolicyName": { 287 | "Ref": "s3ProtectedPolicy" 288 | }, 289 | "Roles": [ 290 | { 291 | "Ref": "authRoleName" 292 | } 293 | ], 294 | "PolicyDocument": { 295 | "Version": "2012-10-17", 296 | "Statement": [ 297 | { 298 | "Effect": "Allow", 299 | "Action": { 300 | "Fn::Split" : [ "," , { 301 | "Ref": "s3PermissionsAuthenticatedProtected" 302 | } ] 303 | }, 304 | "Resource": [ 305 | { 306 | "Fn::Join": [ 307 | "", 308 | [ 309 | "arn:aws:s3:::", 310 | { 311 | "Ref": "S3Bucket" 312 | }, 313 | "/protected/${cognito-identity.amazonaws.com:sub}/*" 314 | ] 315 | ] 316 | } 317 | ] 318 | } 319 | ] 320 | } 321 | } 322 | }, 323 | "S3AuthPrivatePolicy": { 324 | "DependsOn": [ 325 | "S3Bucket" 326 | ], 327 | "Condition": "CreateAuthPrivate", 328 | "Type": "AWS::IAM::Policy", 329 | "Properties": { 330 | "PolicyName": { 331 | "Ref": "s3PrivatePolicy" 332 | }, 333 | "Roles": [ 334 | { 335 | "Ref": "authRoleName" 336 | } 337 | ], 338 | "PolicyDocument": { 339 | "Version": "2012-10-17", 340 | "Statement": [ 341 | { 342 | "Effect": "Allow", 343 | "Action": { 344 | "Fn::Split" : [ "," , { 345 | "Ref": "s3PermissionsAuthenticatedPrivate" 346 | } ] 347 | }, 348 | "Resource": [ 349 | { 350 | "Fn::Join": [ 351 | "", 352 | [ 353 | "arn:aws:s3:::", 354 | { 355 | "Ref": "S3Bucket" 356 | }, 357 | "/private/${cognito-identity.amazonaws.com:sub}/*" 358 | ] 359 | ] 360 | } 361 | ] 362 | } 363 | ] 364 | } 365 | } 366 | }, 367 | "S3AuthUploadPolicy": { 368 | "DependsOn": [ 369 | "S3Bucket" 370 | ], 371 | "Condition": "CreateAuthUploads", 372 | "Type": "AWS::IAM::Policy", 373 | "Properties": { 374 | "PolicyName": { 375 | "Ref": "s3UploadsPolicy" 376 | }, 377 | "Roles": [ 378 | { 379 | "Ref": "authRoleName" 380 | } 381 | ], 382 | "PolicyDocument": { 383 | "Version": "2012-10-17", 384 | "Statement": [ 385 | { 386 | "Effect": "Allow", 387 | "Action": { 388 | "Fn::Split" : [ "," , { 389 | "Ref": "s3PermissionsAuthenticatedUploads" 390 | } ] 391 | }, 392 | "Resource": [ 393 | { 394 | "Fn::Join": [ 395 | "", 396 | [ 397 | "arn:aws:s3:::", 398 | { 399 | "Ref": "S3Bucket" 400 | }, 401 | "/uploads/*" 402 | ] 403 | ] 404 | } 405 | ] 406 | } 407 | ] 408 | } 409 | } 410 | }, 411 | "S3AuthReadPolicy": { 412 | "DependsOn": [ 413 | "S3Bucket" 414 | ], 415 | "Condition": "AuthReadAndList", 416 | "Type": "AWS::IAM::Policy", 417 | "Properties": { 418 | "PolicyName": { 419 | "Ref": "s3ReadPolicy" 420 | }, 421 | "Roles": [ 422 | { 423 | "Ref": "authRoleName" 424 | } 425 | ], 426 | "PolicyDocument": { 427 | "Version": "2012-10-17", 428 | "Statement": [ 429 | { 430 | "Effect": "Allow", 431 | "Action": [ 432 | "s3:GetObject" 433 | ], 434 | "Resource": [ 435 | { 436 | "Fn::Join": [ 437 | "", 438 | [ 439 | "arn:aws:s3:::", 440 | { 441 | "Ref": "S3Bucket" 442 | }, 443 | "/protected/*" 444 | ] 445 | ] 446 | } 447 | ] 448 | }, 449 | { 450 | "Effect": "Allow", 451 | "Action": [ 452 | "s3:ListBucket" 453 | ], 454 | "Resource": [ 455 | { 456 | "Fn::Join": [ 457 | "", 458 | [ 459 | "arn:aws:s3:::", 460 | { 461 | "Ref": "S3Bucket" 462 | } 463 | ] 464 | ] 465 | } 466 | ], 467 | "Condition": { 468 | "StringLike": { 469 | "s3:prefix": [ 470 | "public/", 471 | "public/*", 472 | "protected/", 473 | "protected/*", 474 | "private/${cognito-identity.amazonaws.com:sub}/", 475 | "private/${cognito-identity.amazonaws.com:sub}/*" 476 | ] 477 | } 478 | } 479 | } 480 | ] 481 | } 482 | } 483 | }, 484 | "S3GuestPublicPolicy": { 485 | "DependsOn": [ 486 | "S3Bucket" 487 | ], 488 | "Condition": "CreateGuestPublic", 489 | "Type": "AWS::IAM::Policy", 490 | "Properties": { 491 | "PolicyName": { 492 | "Ref": "s3PublicPolicy" 493 | }, 494 | "Roles": [ 495 | { 496 | "Ref": "unauthRoleName" 497 | } 498 | ], 499 | "PolicyDocument": { 500 | "Version": "2012-10-17", 501 | "Statement": [ 502 | { 503 | "Effect": "Allow", 504 | "Action": { 505 | "Fn::Split" : [ "," , { 506 | "Ref": "s3PermissionsGuestPublic" 507 | } ] 508 | }, 509 | "Resource": [ 510 | { 511 | "Fn::Join": [ 512 | "", 513 | [ 514 | "arn:aws:s3:::", 515 | { 516 | "Ref": "S3Bucket" 517 | }, 518 | "/public/*" 519 | ] 520 | ] 521 | } 522 | ] 523 | } 524 | ] 525 | } 526 | } 527 | }, 528 | "S3GuestUploadPolicy": { 529 | "DependsOn": [ 530 | "S3Bucket" 531 | ], 532 | "Condition": "CreateGuestUploads", 533 | "Type": "AWS::IAM::Policy", 534 | "Properties": { 535 | "PolicyName": { 536 | "Ref": "s3UploadsPolicy" 537 | }, 538 | "Roles": [ 539 | { 540 | "Ref": "unauthRoleName" 541 | } 542 | ], 543 | "PolicyDocument": { 544 | "Version": "2012-10-17", 545 | "Statement": [ 546 | { 547 | "Effect": "Allow", 548 | "Action": { 549 | "Fn::Split" : [ "," , { 550 | "Ref": "s3PermissionsGuestUploads" 551 | } ] 552 | }, 553 | "Resource": [ 554 | { 555 | "Fn::Join": [ 556 | "", 557 | [ 558 | "arn:aws:s3:::", 559 | { 560 | "Ref": "S3Bucket" 561 | }, 562 | "/uploads/*" 563 | ] 564 | ] 565 | } 566 | ] 567 | } 568 | ] 569 | } 570 | } 571 | }, 572 | "S3GuestReadPolicy": { 573 | "DependsOn": [ 574 | "S3Bucket" 575 | ], 576 | "Condition": "GuestReadAndList", 577 | "Type": "AWS::IAM::Policy", 578 | "Properties": { 579 | "PolicyName": { 580 | "Ref": "s3ReadPolicy" 581 | }, 582 | "Roles": [ 583 | { 584 | "Ref": "unauthRoleName" 585 | } 586 | ], 587 | "PolicyDocument": { 588 | "Version": "2012-10-17", 589 | "Statement": [ 590 | { 591 | "Effect": "Allow", 592 | "Action": [ 593 | "s3:GetObject" 594 | ], 595 | "Resource": [ 596 | { 597 | "Fn::Join": [ 598 | "", 599 | [ 600 | "arn:aws:s3:::", 601 | { 602 | "Ref": "S3Bucket" 603 | }, 604 | "/protected/*" 605 | ] 606 | ] 607 | } 608 | ] 609 | }, 610 | { 611 | "Effect": "Allow", 612 | "Action": [ 613 | "s3:ListBucket" 614 | ], 615 | "Resource": [ 616 | { 617 | "Fn::Join": [ 618 | "", 619 | [ 620 | "arn:aws:s3:::", 621 | { 622 | "Ref": "S3Bucket" 623 | } 624 | ] 625 | ] 626 | } 627 | ], 628 | "Condition": { 629 | "StringLike": { 630 | "s3:prefix": [ 631 | "public/", 632 | "public/*", 633 | "protected/", 634 | "protected/*" 635 | ] 636 | } 637 | } 638 | } 639 | ] 640 | } 641 | } 642 | } 643 | }, 644 | "Outputs": { 645 | "BucketName": { 646 | "Value": { 647 | "Ref": "S3Bucket" 648 | }, 649 | "Description": "Bucket name for the S3 bucket" 650 | }, 651 | "Region": { 652 | "Value": { 653 | "Ref": "AWS::Region" 654 | } 655 | } 656 | } 657 | } 658 | -------------------------------------------------------------------------------- /amplify/#current-cloud-backend/storage/S3chopperthao/s3-cloudformation-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Description": "S3 resource stack creation using Amplify CLI", 4 | "Parameters": { 5 | "bucketName": { 6 | "Type": "String" 7 | }, 8 | "authPolicyName": { 9 | "Type": "String" 10 | }, 11 | "unauthPolicyName": { 12 | "Type": "String" 13 | }, 14 | "authRoleName": { 15 | "Type": "String" 16 | }, 17 | "unauthRoleName": { 18 | "Type": "String" 19 | }, 20 | "s3PublicPolicy": { 21 | "Type": "String", 22 | "Default" : "NONE" 23 | }, 24 | "s3PrivatePolicy": { 25 | "Type": "String", 26 | "Default" : "NONE" 27 | }, 28 | "s3ProtectedPolicy": { 29 | "Type": "String", 30 | "Default" : "NONE" 31 | }, 32 | "s3UploadsPolicy": { 33 | "Type": "String", 34 | "Default" : "NONE" 35 | }, 36 | "s3ReadPolicy": { 37 | "Type": "String", 38 | "Default" : "NONE" 39 | }, 40 | "s3PermissionsAuthenticatedPublic": { 41 | "Type": "String", 42 | "Default" : "DISALLOW" 43 | }, 44 | "s3PermissionsAuthenticatedProtected": { 45 | "Type": "String", 46 | "Default" : "DISALLOW" 47 | }, 48 | "s3PermissionsAuthenticatedPrivate": { 49 | "Type": "String", 50 | "Default" : "DISALLOW" 51 | }, 52 | "s3PermissionsAuthenticatedUploads": { 53 | "Type": "String", 54 | "Default" : "DISALLOW" 55 | }, 56 | "s3PermissionsGuestPublic": { 57 | "Type": "String", 58 | "Default" : "DISALLOW" 59 | }, 60 | "s3PermissionsGuestUploads": { 61 | "Type": "String", 62 | "Default" : "DISALLOW" }, 63 | "AuthenticatedAllowList": { 64 | "Type": "String", 65 | "Default" : "DISALLOW" 66 | }, 67 | "GuestAllowList": { 68 | "Type": "String", 69 | "Default" : "DISALLOW" 70 | }, 71 | "selectedGuestPermissions": { 72 | "Type": "CommaDelimitedList", 73 | "Default" : "NONE" 74 | }, 75 | "selectedAuthenticatedPermissions": { 76 | "Type": "CommaDelimitedList", 77 | "Default" : "NONE" 78 | }, 79 | "env": { 80 | "Type": "String" 81 | }, 82 | "triggerFunction": { 83 | "Type": "String" 84 | } 85 | 86 | 87 | }, 88 | "Conditions": { 89 | "ShouldNotCreateEnvResources": { 90 | "Fn::Equals": [ 91 | { 92 | "Ref": "env" 93 | }, 94 | "NONE" 95 | ] 96 | }, 97 | "CreateAuthPublic": { 98 | "Fn::Not" : [{ 99 | "Fn::Equals" : [ 100 | {"Ref" : "s3PermissionsAuthenticatedPublic"}, 101 | "DISALLOW" 102 | ] 103 | }] 104 | }, 105 | "CreateAuthProtected": { 106 | "Fn::Not" : [{ 107 | "Fn::Equals" : [ 108 | {"Ref" : "s3PermissionsAuthenticatedProtected"}, 109 | "DISALLOW" 110 | ] 111 | }] 112 | }, 113 | "CreateAuthPrivate": { 114 | "Fn::Not" : [{ 115 | "Fn::Equals" : [ 116 | {"Ref" : "s3PermissionsAuthenticatedPrivate"}, 117 | "DISALLOW" 118 | ] 119 | }] 120 | }, 121 | "CreateAuthUploads": { 122 | "Fn::Not" : [{ 123 | "Fn::Equals" : [ 124 | {"Ref" : "s3PermissionsAuthenticatedUploads"}, 125 | "DISALLOW" 126 | ] 127 | }] 128 | }, 129 | "CreateGuestPublic": { 130 | "Fn::Not" : [{ 131 | "Fn::Equals" : [ 132 | {"Ref" : "s3PermissionsGuestPublic"}, 133 | "DISALLOW" 134 | ] 135 | }] 136 | }, 137 | "CreateGuestUploads": { 138 | "Fn::Not" : [{ 139 | "Fn::Equals" : [ 140 | {"Ref" : "s3PermissionsGuestUploads"}, 141 | "DISALLOW" 142 | ] 143 | }] 144 | }, 145 | "AuthReadAndList": { 146 | "Fn::Not" : [{ 147 | "Fn::Equals" : [ 148 | {"Ref" : "AuthenticatedAllowList"}, 149 | "DISALLOW" 150 | ] 151 | }] 152 | }, 153 | "GuestReadAndList": { 154 | "Fn::Not" : [{ 155 | "Fn::Equals" : [ 156 | {"Ref" : "GuestAllowList"}, 157 | "DISALLOW" 158 | ] 159 | }] 160 | } 161 | }, 162 | "Resources": { 163 | "S3Bucket": { 164 | "Type": "AWS::S3::Bucket", 165 | 166 | "DeletionPolicy" : "Retain", 167 | "Properties": { 168 | "BucketName": { 169 | "Fn::If": [ 170 | "ShouldNotCreateEnvResources", 171 | { 172 | "Ref": "bucketName" 173 | }, 174 | { 175 | "Fn::Join": [ 176 | "", 177 | [ 178 | { 179 | "Ref": "bucketName" 180 | }, 181 | { 182 | "Fn::Select": [ 183 | 3, 184 | { 185 | "Fn::Split": [ 186 | "-", 187 | { 188 | "Ref": "AWS::StackName" 189 | } 190 | ] 191 | } 192 | ] 193 | }, 194 | "-", 195 | { 196 | "Ref": "env" 197 | } 198 | ] 199 | ] 200 | } 201 | ] 202 | }, 203 | 204 | "CorsConfiguration": { 205 | "CorsRules": [ 206 | { 207 | "AllowedHeaders": [ 208 | "*" 209 | ], 210 | "AllowedMethods": [ 211 | "GET", 212 | "HEAD", 213 | "PUT", 214 | "POST", 215 | "DELETE" 216 | ], 217 | "AllowedOrigins": [ 218 | "*" 219 | ], 220 | "ExposedHeaders": [ 221 | "x-amz-server-side-encryption", 222 | "x-amz-request-id", 223 | "x-amz-id-2", 224 | "ETag" 225 | ], 226 | "Id": "S3CORSRuleId1", 227 | "MaxAge": "3000" 228 | } 229 | ] 230 | } 231 | } 232 | }, 233 | 234 | 235 | "S3AuthPublicPolicy": { 236 | "DependsOn": [ 237 | "S3Bucket" 238 | ], 239 | "Condition": "CreateAuthPublic", 240 | "Type": "AWS::IAM::Policy", 241 | "Properties": { 242 | "PolicyName": { 243 | "Ref": "s3PublicPolicy" 244 | }, 245 | "Roles": [ 246 | { 247 | "Ref": "authRoleName" 248 | } 249 | ], 250 | "PolicyDocument": { 251 | "Version": "2012-10-17", 252 | "Statement": [ 253 | { 254 | "Effect": "Allow", 255 | "Action": { 256 | "Fn::Split" : [ "," , { 257 | "Ref": "s3PermissionsAuthenticatedPublic" 258 | } ] 259 | }, 260 | "Resource": [ 261 | { 262 | "Fn::Join": [ 263 | "", 264 | [ 265 | "arn:aws:s3:::", 266 | { 267 | "Ref": "S3Bucket" 268 | }, 269 | "/public/*" 270 | ] 271 | ] 272 | } 273 | ] 274 | } 275 | ] 276 | } 277 | } 278 | }, 279 | "S3AuthProtectedPolicy": { 280 | "DependsOn": [ 281 | "S3Bucket" 282 | ], 283 | "Condition": "CreateAuthProtected", 284 | "Type": "AWS::IAM::Policy", 285 | "Properties": { 286 | "PolicyName": { 287 | "Ref": "s3ProtectedPolicy" 288 | }, 289 | "Roles": [ 290 | { 291 | "Ref": "authRoleName" 292 | } 293 | ], 294 | "PolicyDocument": { 295 | "Version": "2012-10-17", 296 | "Statement": [ 297 | { 298 | "Effect": "Allow", 299 | "Action": { 300 | "Fn::Split" : [ "," , { 301 | "Ref": "s3PermissionsAuthenticatedProtected" 302 | } ] 303 | }, 304 | "Resource": [ 305 | { 306 | "Fn::Join": [ 307 | "", 308 | [ 309 | "arn:aws:s3:::", 310 | { 311 | "Ref": "S3Bucket" 312 | }, 313 | "/protected/${cognito-identity.amazonaws.com:sub}/*" 314 | ] 315 | ] 316 | } 317 | ] 318 | } 319 | ] 320 | } 321 | } 322 | }, 323 | "S3AuthPrivatePolicy": { 324 | "DependsOn": [ 325 | "S3Bucket" 326 | ], 327 | "Condition": "CreateAuthPrivate", 328 | "Type": "AWS::IAM::Policy", 329 | "Properties": { 330 | "PolicyName": { 331 | "Ref": "s3PrivatePolicy" 332 | }, 333 | "Roles": [ 334 | { 335 | "Ref": "authRoleName" 336 | } 337 | ], 338 | "PolicyDocument": { 339 | "Version": "2012-10-17", 340 | "Statement": [ 341 | { 342 | "Effect": "Allow", 343 | "Action": { 344 | "Fn::Split" : [ "," , { 345 | "Ref": "s3PermissionsAuthenticatedPrivate" 346 | } ] 347 | }, 348 | "Resource": [ 349 | { 350 | "Fn::Join": [ 351 | "", 352 | [ 353 | "arn:aws:s3:::", 354 | { 355 | "Ref": "S3Bucket" 356 | }, 357 | "/private/${cognito-identity.amazonaws.com:sub}/*" 358 | ] 359 | ] 360 | } 361 | ] 362 | } 363 | ] 364 | } 365 | } 366 | }, 367 | "S3AuthUploadPolicy": { 368 | "DependsOn": [ 369 | "S3Bucket" 370 | ], 371 | "Condition": "CreateAuthUploads", 372 | "Type": "AWS::IAM::Policy", 373 | "Properties": { 374 | "PolicyName": { 375 | "Ref": "s3UploadsPolicy" 376 | }, 377 | "Roles": [ 378 | { 379 | "Ref": "authRoleName" 380 | } 381 | ], 382 | "PolicyDocument": { 383 | "Version": "2012-10-17", 384 | "Statement": [ 385 | { 386 | "Effect": "Allow", 387 | "Action": { 388 | "Fn::Split" : [ "," , { 389 | "Ref": "s3PermissionsAuthenticatedUploads" 390 | } ] 391 | }, 392 | "Resource": [ 393 | { 394 | "Fn::Join": [ 395 | "", 396 | [ 397 | "arn:aws:s3:::", 398 | { 399 | "Ref": "S3Bucket" 400 | }, 401 | "/uploads/*" 402 | ] 403 | ] 404 | } 405 | ] 406 | } 407 | ] 408 | } 409 | } 410 | }, 411 | "S3AuthReadPolicy": { 412 | "DependsOn": [ 413 | "S3Bucket" 414 | ], 415 | "Condition": "AuthReadAndList", 416 | "Type": "AWS::IAM::Policy", 417 | "Properties": { 418 | "PolicyName": { 419 | "Ref": "s3ReadPolicy" 420 | }, 421 | "Roles": [ 422 | { 423 | "Ref": "authRoleName" 424 | } 425 | ], 426 | "PolicyDocument": { 427 | "Version": "2012-10-17", 428 | "Statement": [ 429 | { 430 | "Effect": "Allow", 431 | "Action": [ 432 | "s3:GetObject" 433 | ], 434 | "Resource": [ 435 | { 436 | "Fn::Join": [ 437 | "", 438 | [ 439 | "arn:aws:s3:::", 440 | { 441 | "Ref": "S3Bucket" 442 | }, 443 | "/protected/*" 444 | ] 445 | ] 446 | } 447 | ] 448 | }, 449 | { 450 | "Effect": "Allow", 451 | "Action": [ 452 | "s3:ListBucket" 453 | ], 454 | "Resource": [ 455 | { 456 | "Fn::Join": [ 457 | "", 458 | [ 459 | "arn:aws:s3:::", 460 | { 461 | "Ref": "S3Bucket" 462 | } 463 | ] 464 | ] 465 | } 466 | ], 467 | "Condition": { 468 | "StringLike": { 469 | "s3:prefix": [ 470 | "public/", 471 | "public/*", 472 | "protected/", 473 | "protected/*", 474 | "private/${cognito-identity.amazonaws.com:sub}/", 475 | "private/${cognito-identity.amazonaws.com:sub}/*" 476 | ] 477 | } 478 | } 479 | } 480 | ] 481 | } 482 | } 483 | }, 484 | "S3GuestPublicPolicy": { 485 | "DependsOn": [ 486 | "S3Bucket" 487 | ], 488 | "Condition": "CreateGuestPublic", 489 | "Type": "AWS::IAM::Policy", 490 | "Properties": { 491 | "PolicyName": { 492 | "Ref": "s3PublicPolicy" 493 | }, 494 | "Roles": [ 495 | { 496 | "Ref": "unauthRoleName" 497 | } 498 | ], 499 | "PolicyDocument": { 500 | "Version": "2012-10-17", 501 | "Statement": [ 502 | { 503 | "Effect": "Allow", 504 | "Action": { 505 | "Fn::Split" : [ "," , { 506 | "Ref": "s3PermissionsGuestPublic" 507 | } ] 508 | }, 509 | "Resource": [ 510 | { 511 | "Fn::Join": [ 512 | "", 513 | [ 514 | "arn:aws:s3:::", 515 | { 516 | "Ref": "S3Bucket" 517 | }, 518 | "/public/*" 519 | ] 520 | ] 521 | } 522 | ] 523 | } 524 | ] 525 | } 526 | } 527 | }, 528 | "S3GuestUploadPolicy": { 529 | "DependsOn": [ 530 | "S3Bucket" 531 | ], 532 | "Condition": "CreateGuestUploads", 533 | "Type": "AWS::IAM::Policy", 534 | "Properties": { 535 | "PolicyName": { 536 | "Ref": "s3UploadsPolicy" 537 | }, 538 | "Roles": [ 539 | { 540 | "Ref": "unauthRoleName" 541 | } 542 | ], 543 | "PolicyDocument": { 544 | "Version": "2012-10-17", 545 | "Statement": [ 546 | { 547 | "Effect": "Allow", 548 | "Action": { 549 | "Fn::Split" : [ "," , { 550 | "Ref": "s3PermissionsGuestUploads" 551 | } ] 552 | }, 553 | "Resource": [ 554 | { 555 | "Fn::Join": [ 556 | "", 557 | [ 558 | "arn:aws:s3:::", 559 | { 560 | "Ref": "S3Bucket" 561 | }, 562 | "/uploads/*" 563 | ] 564 | ] 565 | } 566 | ] 567 | } 568 | ] 569 | } 570 | } 571 | }, 572 | "S3GuestReadPolicy": { 573 | "DependsOn": [ 574 | "S3Bucket" 575 | ], 576 | "Condition": "GuestReadAndList", 577 | "Type": "AWS::IAM::Policy", 578 | "Properties": { 579 | "PolicyName": { 580 | "Ref": "s3ReadPolicy" 581 | }, 582 | "Roles": [ 583 | { 584 | "Ref": "unauthRoleName" 585 | } 586 | ], 587 | "PolicyDocument": { 588 | "Version": "2012-10-17", 589 | "Statement": [ 590 | { 591 | "Effect": "Allow", 592 | "Action": [ 593 | "s3:GetObject" 594 | ], 595 | "Resource": [ 596 | { 597 | "Fn::Join": [ 598 | "", 599 | [ 600 | "arn:aws:s3:::", 601 | { 602 | "Ref": "S3Bucket" 603 | }, 604 | "/protected/*" 605 | ] 606 | ] 607 | } 608 | ] 609 | }, 610 | { 611 | "Effect": "Allow", 612 | "Action": [ 613 | "s3:ListBucket" 614 | ], 615 | "Resource": [ 616 | { 617 | "Fn::Join": [ 618 | "", 619 | [ 620 | "arn:aws:s3:::", 621 | { 622 | "Ref": "S3Bucket" 623 | } 624 | ] 625 | ] 626 | } 627 | ], 628 | "Condition": { 629 | "StringLike": { 630 | "s3:prefix": [ 631 | "public/", 632 | "public/*", 633 | "protected/", 634 | "protected/*" 635 | ] 636 | } 637 | } 638 | } 639 | ] 640 | } 641 | } 642 | } 643 | }, 644 | "Outputs": { 645 | "BucketName": { 646 | "Value": { 647 | "Ref": "S3Bucket" 648 | }, 649 | "Description": "Bucket name for the S3 bucket" 650 | }, 651 | "Region": { 652 | "Value": { 653 | "Ref": "AWS::Region" 654 | } 655 | } 656 | } 657 | } 658 | -------------------------------------------------------------------------------- /amplify/backend/awscloudformation/nested-cloudformation-stack.yml: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Description": "Root Stack for AWS Amplify Console", 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 | "authcloudchopperd20aa567": { 72 | "Type": "AWS::CloudFormation::Stack", 73 | "Properties": { 74 | "TemplateURL": "https://s3.amazonaws.com/amplify-cloudchopper-dev-204628-deployment/amplify-cfn-templates/auth/cloudchopperd20aa567-cloudformation-template.yml", 75 | "Parameters": { 76 | "identityPoolName": "cloudchopperd20aa567_identitypool_d20aa567", 77 | "allowUnauthenticatedIdentities": true, 78 | "resourceNameTruncated": "cloudcd20aa567", 79 | "userPoolName": "cloudchopperd20aa567_userpool_d20aa567", 80 | "autoVerifiedAttributes": "email", 81 | "mfaConfiguration": "OFF", 82 | "mfaTypes": "SMS Text Message", 83 | "smsAuthenticationMessage": "Your authentication code is {####}", 84 | "smsVerificationMessage": "Your verification code is {####}", 85 | "emailVerificationSubject": "Your verification code", 86 | "emailVerificationMessage": "Your verification code is {####}", 87 | "defaultPasswordPolicy": false, 88 | "passwordPolicyMinLength": 8, 89 | "passwordPolicyCharacters": "", 90 | "requiredAttributes": "email", 91 | "userpoolClientGenerateSecret": false, 92 | "userpoolClientRefreshTokenValidity": 30, 93 | "userpoolClientWriteAttributes": "email", 94 | "userpoolClientReadAttributes": "email", 95 | "userpoolClientLambdaRole": "cloudcd20aa567_userpoolclient_lambda_role", 96 | "userpoolClientSetAttributes": false, 97 | "sharedId": "d20aa567", 98 | "resourceName": "cloudchopperd20aa567", 99 | "authSelections": "identityPoolAndUserPool", 100 | "authRoleArn": { 101 | "Fn::GetAtt": [ 102 | "AuthRole", 103 | "Arn" 104 | ] 105 | }, 106 | "unauthRoleArn": { 107 | "Fn::GetAtt": [ 108 | "UnauthRole", 109 | "Arn" 110 | ] 111 | }, 112 | "useDefault": "default", 113 | "userPoolGroupList": "", 114 | "serviceName": "Cognito", 115 | "usernameCaseSensitive": false, 116 | "dependsOn": "", 117 | "env": "dev" 118 | } 119 | } 120 | }, 121 | "storageS3chopperthao": { 122 | "Type": "AWS::CloudFormation::Stack", 123 | "Properties": { 124 | "TemplateURL": "https://s3.amazonaws.com/amplify-cloudchopper-dev-204628-deployment/amplify-cfn-templates/storage/s3-cloudformation-template.json", 125 | "Parameters": { 126 | "bucketName": "cloudchopper5de8d1549c594acca63ed06abae2d414", 127 | "authPolicyName": "s3_amplify_899f92fa", 128 | "unauthPolicyName": "s3_amplify_899f92fa", 129 | "authRoleName": { 130 | "Ref": "AuthRoleName" 131 | }, 132 | "unauthRoleName": { 133 | "Ref": "UnauthRoleName" 134 | }, 135 | "selectedGuestPermissions": "s3:PutObject,s3:GetObject,s3:ListBucket,s3:DeleteObject", 136 | "selectedAuthenticatedPermissions": "s3:PutObject,s3:GetObject,s3:ListBucket,s3:DeleteObject", 137 | "s3PermissionsAuthenticatedPublic": "s3:PutObject,s3:GetObject,s3:DeleteObject", 138 | "s3PublicPolicy": "Public_policy_7d6cabc6", 139 | "s3PermissionsAuthenticatedUploads": "s3:PutObject", 140 | "s3UploadsPolicy": "Uploads_policy_7d6cabc6", 141 | "s3PermissionsAuthenticatedProtected": "s3:PutObject,s3:GetObject,s3:DeleteObject", 142 | "s3ProtectedPolicy": "Protected_policy_5e148ded", 143 | "s3PermissionsAuthenticatedPrivate": "s3:PutObject,s3:GetObject,s3:DeleteObject", 144 | "s3PrivatePolicy": "Private_policy_5e148ded", 145 | "AuthenticatedAllowList": "ALLOW", 146 | "s3ReadPolicy": "read_policy_7d6cabc6", 147 | "s3PermissionsGuestPublic": "s3:PutObject,s3:GetObject,s3:DeleteObject", 148 | "s3PermissionsGuestUploads": "s3:PutObject", 149 | "GuestAllowList": "ALLOW", 150 | "triggerFunction": "NONE", 151 | "env": "dev" 152 | } 153 | } 154 | }, 155 | "analyticscloudchopper": { 156 | "Type": "AWS::CloudFormation::Stack", 157 | "Properties": { 158 | "TemplateURL": "https://s3.amazonaws.com/amplify-cloudchopper-dev-204628-deployment/amplify-cfn-templates/analytics/pinpoint-cloudformation-template.json", 159 | "Parameters": { 160 | "appName": "cloudchopper", 161 | "roleName": "pinpointLambdaRoleaaf79265", 162 | "cloudformationPolicyName": "cloudformationPolicyaaf79265", 163 | "cloudWatchPolicyName": "cloudWatchPolicyaaf79265", 164 | "pinpointPolicyName": "pinpointPolicyaaf79265", 165 | "authPolicyName": "pinpoint_amplify_aaf79265", 166 | "unauthPolicyName": "pinpoint_amplify_aaf79265", 167 | "authRoleName": { 168 | "Ref": "AuthRoleName" 169 | }, 170 | "unauthRoleName": { 171 | "Ref": "UnauthRoleName" 172 | }, 173 | "authRoleArn": { 174 | "Fn::GetAtt": [ 175 | "AuthRole", 176 | "Arn" 177 | ] 178 | }, 179 | "env": "dev" 180 | } 181 | } 182 | }, 183 | "UpdateRolesWithIDPFunction": { 184 | "DependsOn": [ 185 | "AuthRole", 186 | "UnauthRole", 187 | "authcloudchopperd20aa567" 188 | ], 189 | "Type": "AWS::Lambda::Function", 190 | "Properties": { 191 | "Code": { 192 | "ZipFile": { 193 | "Fn::Join": [ 194 | "\n", 195 | [ 196 | "const response = require('cfn-response');", 197 | "const aws = require('aws-sdk');", 198 | "let responseData = {};", 199 | "exports.handler = function(event, context) {", 200 | " try {", 201 | " let authRoleName = event.ResourceProperties.authRoleName;", 202 | " let unauthRoleName = event.ResourceProperties.unauthRoleName;", 203 | " let idpId = event.ResourceProperties.idpId;", 204 | " let promises = [];", 205 | " 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'}}}]};", 206 | " 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'}}}]};", 207 | " if (event.RequestType == 'Delete') {", 208 | " delete authParamsJson.Statement[0].Condition;", 209 | " delete unauthParamsJson.Statement[0].Condition;", 210 | " let authParams = { PolicyDocument: JSON.stringify(authParamsJson),RoleName: authRoleName};", 211 | " let unauthParams = {PolicyDocument: JSON.stringify(unauthParamsJson),RoleName: unauthRoleName};", 212 | " const iam = new aws.IAM({ apiVersion: '2010-05-08', region: event.ResourceProperties.region});", 213 | " promises.push(iam.updateAssumeRolePolicy(authParams).promise());", 214 | " promises.push(iam.updateAssumeRolePolicy(unauthParams).promise());", 215 | " Promise.all(promises)", 216 | " .then((res) => {", 217 | " console.log(\"delete response data\" + JSON.stringify(res));", 218 | " response.send(event, context, response.SUCCESS, {});", 219 | " });", 220 | " }", 221 | " if (event.RequestType == 'Update' || event.RequestType == 'Create') {", 222 | " const iam = new aws.IAM({ apiVersion: '2010-05-08', region: event.ResourceProperties.region});", 223 | " let authParams = { PolicyDocument: JSON.stringify(authParamsJson),RoleName: authRoleName};", 224 | " let unauthParams = {PolicyDocument: JSON.stringify(unauthParamsJson),RoleName: unauthRoleName};", 225 | " promises.push(iam.updateAssumeRolePolicy(authParams).promise());", 226 | " promises.push(iam.updateAssumeRolePolicy(unauthParams).promise());", 227 | " Promise.all(promises)", 228 | " .then((res) => {", 229 | " console.log(\"createORupdate\" + res);", 230 | " console.log(\"response data\" + JSON.stringify(res));", 231 | " response.send(event, context, response.SUCCESS, {});", 232 | " });", 233 | " }", 234 | " } catch(err) {", 235 | " console.log(err.stack);", 236 | " responseData = {Error: err};", 237 | " response.send(event, context, response.FAILED, responseData);", 238 | " throw err;", 239 | " }", 240 | "};" 241 | ] 242 | ] 243 | } 244 | }, 245 | "Handler": "index.handler", 246 | "Runtime": "nodejs12.x", 247 | "Timeout": "300", 248 | "Role": { 249 | "Fn::GetAtt": [ 250 | "UpdateRolesWithIDPFunctionRole", 251 | "Arn" 252 | ] 253 | } 254 | } 255 | }, 256 | "UpdateRolesWithIDPFunctionOutputs": { 257 | "Type": "Custom::LambdaCallout", 258 | "Properties": { 259 | "ServiceToken": { 260 | "Fn::GetAtt": [ 261 | "UpdateRolesWithIDPFunction", 262 | "Arn" 263 | ] 264 | }, 265 | "region": { 266 | "Ref": "AWS::Region" 267 | }, 268 | "idpId": { 269 | "Fn::GetAtt": [ 270 | "authcloudchopperd20aa567", 271 | "Outputs.IdentityPoolId" 272 | ] 273 | }, 274 | "authRoleName": { 275 | "Ref": "AuthRoleName" 276 | }, 277 | "unauthRoleName": { 278 | "Ref": "UnauthRoleName" 279 | } 280 | } 281 | }, 282 | "UpdateRolesWithIDPFunctionRole": { 283 | "Type": "AWS::IAM::Role", 284 | "Properties": { 285 | "RoleName": { 286 | "Fn::Join": [ 287 | "", 288 | [ 289 | { 290 | "Ref": "AuthRoleName" 291 | }, 292 | "-idp" 293 | ] 294 | ] 295 | }, 296 | "AssumeRolePolicyDocument": { 297 | "Version": "2012-10-17", 298 | "Statement": [ 299 | { 300 | "Effect": "Allow", 301 | "Principal": { 302 | "Service": [ 303 | "lambda.amazonaws.com" 304 | ] 305 | }, 306 | "Action": [ 307 | "sts:AssumeRole" 308 | ] 309 | } 310 | ] 311 | }, 312 | "Policies": [ 313 | { 314 | "PolicyName": "UpdateRolesWithIDPFunctionPolicy", 315 | "PolicyDocument": { 316 | "Version": "2012-10-17", 317 | "Statement": [ 318 | { 319 | "Effect": "Allow", 320 | "Action": [ 321 | "logs:CreateLogGroup", 322 | "logs:CreateLogStream", 323 | "logs:PutLogEvents" 324 | ], 325 | "Resource": "arn:aws:logs:*:*:*" 326 | }, 327 | { 328 | "Effect": "Allow", 329 | "Action": "iam:UpdateAssumeRolePolicy", 330 | "Resource": { 331 | "Fn::GetAtt": [ 332 | "AuthRole", 333 | "Arn" 334 | ] 335 | } 336 | }, 337 | { 338 | "Effect": "Allow", 339 | "Action": "iam:UpdateAssumeRolePolicy", 340 | "Resource": { 341 | "Fn::GetAtt": [ 342 | "UnauthRole", 343 | "Arn" 344 | ] 345 | } 346 | } 347 | ] 348 | } 349 | } 350 | ] 351 | } 352 | } 353 | }, 354 | "Outputs": { 355 | "Region": { 356 | "Description": "CloudFormation provider root stack Region", 357 | "Value": { 358 | "Ref": "AWS::Region" 359 | }, 360 | "Export": { 361 | "Name": { 362 | "Fn::Sub": "${AWS::StackName}-Region" 363 | } 364 | } 365 | }, 366 | "StackName": { 367 | "Description": "CloudFormation provider root stack ID", 368 | "Value": { 369 | "Ref": "AWS::StackName" 370 | }, 371 | "Export": { 372 | "Name": { 373 | "Fn::Sub": "${AWS::StackName}-StackName" 374 | } 375 | } 376 | }, 377 | "StackId": { 378 | "Description": "CloudFormation provider root stack name", 379 | "Value": { 380 | "Ref": "AWS::StackId" 381 | }, 382 | "Export": { 383 | "Name": { 384 | "Fn::Sub": "${AWS::StackName}-StackId" 385 | } 386 | } 387 | }, 388 | "DeploymentBucketName": { 389 | "Description": "CloudFormation provider root stack deployment bucket name", 390 | "Value": { 391 | "Ref": "DeploymentBucketName" 392 | }, 393 | "Export": { 394 | "Name": { 395 | "Fn::Sub": "${AWS::StackName}-DeploymentBucketName" 396 | } 397 | } 398 | }, 399 | "AuthRoleArn": { 400 | "Value": { 401 | "Fn::GetAtt": [ 402 | "AuthRole", 403 | "Arn" 404 | ] 405 | } 406 | }, 407 | "UnauthRoleArn": { 408 | "Value": { 409 | "Fn::GetAtt": [ 410 | "UnauthRole", 411 | "Arn" 412 | ] 413 | } 414 | }, 415 | "AuthRoleName": { 416 | "Value": { 417 | "Ref": "AuthRole" 418 | } 419 | }, 420 | "UnauthRoleName": { 421 | "Value": { 422 | "Ref": "UnauthRole" 423 | } 424 | } 425 | } 426 | } -------------------------------------------------------------------------------- /amplify/backend/awscloudformation/build/awscloudformation/nested-cloudformation-stack.yml: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Description": "Root Stack for AWS Amplify Console", 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 | "BucketEncryption": { 28 | "ServerSideEncryptionConfiguration": [ 29 | { 30 | "ServerSideEncryptionByDefault": { 31 | "SSEAlgorithm": "AES256" 32 | } 33 | } 34 | ] 35 | } 36 | } 37 | }, 38 | "AuthRole": { 39 | "Type": "AWS::IAM::Role", 40 | "Properties": { 41 | "RoleName": { 42 | "Ref": "AuthRoleName" 43 | }, 44 | "AssumeRolePolicyDocument": { 45 | "Version": "2012-10-17", 46 | "Statement": [ 47 | { 48 | "Sid": "", 49 | "Effect": "Deny", 50 | "Principal": { 51 | "Federated": "cognito-identity.amazonaws.com" 52 | }, 53 | "Action": "sts:AssumeRoleWithWebIdentity" 54 | } 55 | ] 56 | } 57 | } 58 | }, 59 | "UnauthRole": { 60 | "Type": "AWS::IAM::Role", 61 | "Properties": { 62 | "RoleName": { 63 | "Ref": "UnauthRoleName" 64 | }, 65 | "AssumeRolePolicyDocument": { 66 | "Version": "2012-10-17", 67 | "Statement": [ 68 | { 69 | "Sid": "", 70 | "Effect": "Deny", 71 | "Principal": { 72 | "Federated": "cognito-identity.amazonaws.com" 73 | }, 74 | "Action": "sts:AssumeRoleWithWebIdentity" 75 | } 76 | ] 77 | } 78 | } 79 | }, 80 | "authcloudchopperd20aa567": { 81 | "Type": "AWS::CloudFormation::Stack", 82 | "Properties": { 83 | "TemplateURL": "https://s3.amazonaws.com/amplify-cloudchopper-dev-204628-deployment/amplify-cfn-templates/auth/cloudchopperd20aa567-cloudformation-template.yml", 84 | "Parameters": { 85 | "identityPoolName": "cloudchopperd20aa567_identitypool_d20aa567", 86 | "allowUnauthenticatedIdentities": true, 87 | "resourceNameTruncated": "cloudcd20aa567", 88 | "userPoolName": "cloudchopperd20aa567_userpool_d20aa567", 89 | "autoVerifiedAttributes": "email", 90 | "mfaConfiguration": "OFF", 91 | "mfaTypes": "SMS Text Message", 92 | "smsAuthenticationMessage": "Your authentication code is {####}", 93 | "smsVerificationMessage": "Your verification code is {####}", 94 | "emailVerificationSubject": "Your verification code", 95 | "emailVerificationMessage": "Your verification code is {####}", 96 | "defaultPasswordPolicy": false, 97 | "passwordPolicyMinLength": 8, 98 | "passwordPolicyCharacters": "", 99 | "requiredAttributes": "email", 100 | "userpoolClientGenerateSecret": false, 101 | "userpoolClientRefreshTokenValidity": 30, 102 | "userpoolClientWriteAttributes": "email", 103 | "userpoolClientReadAttributes": "email", 104 | "userpoolClientLambdaRole": "cloudcd20aa567_userpoolclient_lambda_role", 105 | "userpoolClientSetAttributes": false, 106 | "sharedId": "d20aa567", 107 | "resourceName": "cloudchopperd20aa567", 108 | "authSelections": "identityPoolAndUserPool", 109 | "authRoleArn": { 110 | "Fn::GetAtt": [ 111 | "AuthRole", 112 | "Arn" 113 | ] 114 | }, 115 | "unauthRoleArn": { 116 | "Fn::GetAtt": [ 117 | "UnauthRole", 118 | "Arn" 119 | ] 120 | }, 121 | "useDefault": "default", 122 | "userPoolGroupList": "", 123 | "serviceName": "Cognito", 124 | "usernameCaseSensitive": false, 125 | "dependsOn": "", 126 | "env": "dev" 127 | } 128 | } 129 | }, 130 | "storageS3chopperthao": { 131 | "Type": "AWS::CloudFormation::Stack", 132 | "Properties": { 133 | "TemplateURL": "https://s3.amazonaws.com/amplify-cloudchopper-dev-204628-deployment/amplify-cfn-templates/storage/s3-cloudformation-template.json", 134 | "Parameters": { 135 | "bucketName": "cloudchopper5de8d1549c594acca63ed06abae2d414", 136 | "authPolicyName": "s3_amplify_899f92fa", 137 | "unauthPolicyName": "s3_amplify_899f92fa", 138 | "authRoleName": { 139 | "Ref": "AuthRoleName" 140 | }, 141 | "unauthRoleName": { 142 | "Ref": "UnauthRoleName" 143 | }, 144 | "selectedGuestPermissions": "s3:PutObject,s3:GetObject,s3:ListBucket,s3:DeleteObject", 145 | "selectedAuthenticatedPermissions": "s3:PutObject,s3:GetObject,s3:ListBucket,s3:DeleteObject", 146 | "s3PermissionsAuthenticatedPublic": "s3:PutObject,s3:GetObject,s3:DeleteObject", 147 | "s3PublicPolicy": "Public_policy_7d6cabc6", 148 | "s3PermissionsAuthenticatedUploads": "s3:PutObject", 149 | "s3UploadsPolicy": "Uploads_policy_7d6cabc6", 150 | "s3PermissionsAuthenticatedProtected": "s3:PutObject,s3:GetObject,s3:DeleteObject", 151 | "s3ProtectedPolicy": "Protected_policy_5e148ded", 152 | "s3PermissionsAuthenticatedPrivate": "s3:PutObject,s3:GetObject,s3:DeleteObject", 153 | "s3PrivatePolicy": "Private_policy_5e148ded", 154 | "AuthenticatedAllowList": "ALLOW", 155 | "s3ReadPolicy": "read_policy_7d6cabc6", 156 | "s3PermissionsGuestPublic": "s3:PutObject,s3:GetObject,s3:DeleteObject", 157 | "s3PermissionsGuestUploads": "s3:PutObject", 158 | "GuestAllowList": "ALLOW", 159 | "triggerFunction": "NONE", 160 | "env": "dev" 161 | } 162 | } 163 | }, 164 | "analyticscloudchopper": { 165 | "Type": "AWS::CloudFormation::Stack", 166 | "Properties": { 167 | "TemplateURL": "https://s3.amazonaws.com/amplify-cloudchopper-dev-204628-deployment/amplify-cfn-templates/analytics/pinpoint-cloudformation-template.json", 168 | "Parameters": { 169 | "appName": "cloudchopper", 170 | "roleName": "pinpointLambdaRoleaaf79265", 171 | "cloudformationPolicyName": "cloudformationPolicyaaf79265", 172 | "cloudWatchPolicyName": "cloudWatchPolicyaaf79265", 173 | "pinpointPolicyName": "pinpointPolicyaaf79265", 174 | "authPolicyName": "pinpoint_amplify_aaf79265", 175 | "unauthPolicyName": "pinpoint_amplify_aaf79265", 176 | "authRoleName": { 177 | "Ref": "AuthRoleName" 178 | }, 179 | "unauthRoleName": { 180 | "Ref": "UnauthRoleName" 181 | }, 182 | "authRoleArn": { 183 | "Fn::GetAtt": [ 184 | "AuthRole", 185 | "Arn" 186 | ] 187 | }, 188 | "env": "dev" 189 | } 190 | } 191 | }, 192 | "UpdateRolesWithIDPFunction": { 193 | "DependsOn": [ 194 | "AuthRole", 195 | "UnauthRole", 196 | "authcloudchopperd20aa567" 197 | ], 198 | "Type": "AWS::Lambda::Function", 199 | "Properties": { 200 | "Code": { 201 | "ZipFile": { 202 | "Fn::Join": [ 203 | "\n", 204 | [ 205 | "const response = require('cfn-response');", 206 | "const aws = require('aws-sdk');", 207 | "let responseData = {};", 208 | "exports.handler = function(event, context) {", 209 | " try {", 210 | " let authRoleName = event.ResourceProperties.authRoleName;", 211 | " let unauthRoleName = event.ResourceProperties.unauthRoleName;", 212 | " let idpId = event.ResourceProperties.idpId;", 213 | " let promises = [];", 214 | " 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'}}}]};", 215 | " 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'}}}]};", 216 | " if (event.RequestType == 'Delete') {", 217 | " delete authParamsJson.Statement[0].Condition;", 218 | " delete unauthParamsJson.Statement[0].Condition;", 219 | " let authParams = { PolicyDocument: JSON.stringify(authParamsJson),RoleName: authRoleName};", 220 | " let unauthParams = {PolicyDocument: JSON.stringify(unauthParamsJson),RoleName: unauthRoleName};", 221 | " const iam = new aws.IAM({ apiVersion: '2010-05-08', region: event.ResourceProperties.region});", 222 | " promises.push(iam.updateAssumeRolePolicy(authParams).promise());", 223 | " promises.push(iam.updateAssumeRolePolicy(unauthParams).promise());", 224 | " Promise.all(promises)", 225 | " .then((res) => {", 226 | " console.log(\"delete response data\" + JSON.stringify(res));", 227 | " response.send(event, context, response.SUCCESS, {});", 228 | " });", 229 | " }", 230 | " if (event.RequestType == 'Update' || event.RequestType == 'Create') {", 231 | " const iam = new aws.IAM({ apiVersion: '2010-05-08', region: event.ResourceProperties.region});", 232 | " let authParams = { PolicyDocument: JSON.stringify(authParamsJson),RoleName: authRoleName};", 233 | " let unauthParams = {PolicyDocument: JSON.stringify(unauthParamsJson),RoleName: unauthRoleName};", 234 | " promises.push(iam.updateAssumeRolePolicy(authParams).promise());", 235 | " promises.push(iam.updateAssumeRolePolicy(unauthParams).promise());", 236 | " Promise.all(promises)", 237 | " .then((res) => {", 238 | " console.log(\"createORupdate\" + res);", 239 | " console.log(\"response data\" + JSON.stringify(res));", 240 | " response.send(event, context, response.SUCCESS, {});", 241 | " });", 242 | " }", 243 | " } catch(err) {", 244 | " console.log(err.stack);", 245 | " responseData = {Error: err};", 246 | " response.send(event, context, response.FAILED, responseData);", 247 | " throw err;", 248 | " }", 249 | "};" 250 | ] 251 | ] 252 | } 253 | }, 254 | "Handler": "index.handler", 255 | "Runtime": "nodejs12.x", 256 | "Timeout": "300", 257 | "Role": { 258 | "Fn::GetAtt": [ 259 | "UpdateRolesWithIDPFunctionRole", 260 | "Arn" 261 | ] 262 | } 263 | } 264 | }, 265 | "UpdateRolesWithIDPFunctionOutputs": { 266 | "Type": "Custom::LambdaCallout", 267 | "Properties": { 268 | "ServiceToken": { 269 | "Fn::GetAtt": [ 270 | "UpdateRolesWithIDPFunction", 271 | "Arn" 272 | ] 273 | }, 274 | "region": { 275 | "Ref": "AWS::Region" 276 | }, 277 | "idpId": { 278 | "Fn::GetAtt": [ 279 | "authcloudchopperd20aa567", 280 | "Outputs.IdentityPoolId" 281 | ] 282 | }, 283 | "authRoleName": { 284 | "Ref": "AuthRoleName" 285 | }, 286 | "unauthRoleName": { 287 | "Ref": "UnauthRoleName" 288 | } 289 | } 290 | }, 291 | "UpdateRolesWithIDPFunctionRole": { 292 | "Type": "AWS::IAM::Role", 293 | "Properties": { 294 | "RoleName": { 295 | "Fn::Join": [ 296 | "", 297 | [ 298 | { 299 | "Ref": "AuthRoleName" 300 | }, 301 | "-idp" 302 | ] 303 | ] 304 | }, 305 | "AssumeRolePolicyDocument": { 306 | "Version": "2012-10-17", 307 | "Statement": [ 308 | { 309 | "Effect": "Allow", 310 | "Principal": { 311 | "Service": [ 312 | "lambda.amazonaws.com" 313 | ] 314 | }, 315 | "Action": [ 316 | "sts:AssumeRole" 317 | ] 318 | } 319 | ] 320 | }, 321 | "Policies": [ 322 | { 323 | "PolicyName": "UpdateRolesWithIDPFunctionPolicy", 324 | "PolicyDocument": { 325 | "Version": "2012-10-17", 326 | "Statement": [ 327 | { 328 | "Effect": "Allow", 329 | "Action": [ 330 | "logs:CreateLogGroup", 331 | "logs:CreateLogStream", 332 | "logs:PutLogEvents" 333 | ], 334 | "Resource": "arn:aws:logs:*:*:*" 335 | }, 336 | { 337 | "Effect": "Allow", 338 | "Action": "iam:UpdateAssumeRolePolicy", 339 | "Resource": { 340 | "Fn::GetAtt": [ 341 | "AuthRole", 342 | "Arn" 343 | ] 344 | } 345 | }, 346 | { 347 | "Effect": "Allow", 348 | "Action": "iam:UpdateAssumeRolePolicy", 349 | "Resource": { 350 | "Fn::GetAtt": [ 351 | "UnauthRole", 352 | "Arn" 353 | ] 354 | } 355 | } 356 | ] 357 | } 358 | } 359 | ] 360 | } 361 | } 362 | }, 363 | "Outputs": { 364 | "Region": { 365 | "Description": "CloudFormation provider root stack Region", 366 | "Value": { 367 | "Ref": "AWS::Region" 368 | }, 369 | "Export": { 370 | "Name": { 371 | "Fn::Sub": "${AWS::StackName}-Region" 372 | } 373 | } 374 | }, 375 | "StackName": { 376 | "Description": "CloudFormation provider root stack ID", 377 | "Value": { 378 | "Ref": "AWS::StackName" 379 | }, 380 | "Export": { 381 | "Name": { 382 | "Fn::Sub": "${AWS::StackName}-StackName" 383 | } 384 | } 385 | }, 386 | "StackId": { 387 | "Description": "CloudFormation provider root stack name", 388 | "Value": { 389 | "Ref": "AWS::StackId" 390 | }, 391 | "Export": { 392 | "Name": { 393 | "Fn::Sub": "${AWS::StackName}-StackId" 394 | } 395 | } 396 | }, 397 | "DeploymentBucketName": { 398 | "Description": "CloudFormation provider root stack deployment bucket name", 399 | "Value": { 400 | "Ref": "DeploymentBucketName" 401 | }, 402 | "Export": { 403 | "Name": { 404 | "Fn::Sub": "${AWS::StackName}-DeploymentBucketName" 405 | } 406 | } 407 | }, 408 | "AuthRoleArn": { 409 | "Value": { 410 | "Fn::GetAtt": [ 411 | "AuthRole", 412 | "Arn" 413 | ] 414 | } 415 | }, 416 | "UnauthRoleArn": { 417 | "Value": { 418 | "Fn::GetAtt": [ 419 | "UnauthRole", 420 | "Arn" 421 | ] 422 | } 423 | }, 424 | "AuthRoleName": { 425 | "Value": { 426 | "Ref": "AuthRole" 427 | } 428 | }, 429 | "UnauthRoleName": { 430 | "Value": { 431 | "Ref": "UnauthRole" 432 | } 433 | } 434 | } 435 | } -------------------------------------------------------------------------------- /amplify/backend/analytics/cloudchopper/pinpoint-cloudformation-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Description": "Pinpoint resource stack creation using Amplify CLI", 4 | "Parameters": { 5 | "appName": { 6 | "Type": "String" 7 | }, 8 | "appId": { 9 | "Type": "String", 10 | "Default": "NONE" 11 | }, 12 | "roleName": { 13 | "Type": "String" 14 | }, 15 | "cloudformationPolicyName": { 16 | "Type": "String" 17 | }, 18 | "cloudWatchPolicyName": { 19 | "Type": "String" 20 | }, 21 | "pinpointPolicyName": { 22 | "Type": "String" 23 | }, 24 | "authPolicyName": { 25 | "Type": "String" 26 | }, 27 | "unauthPolicyName": { 28 | "Type": "String" 29 | }, 30 | "authRoleName": { 31 | "Type": "String" 32 | }, 33 | "unauthRoleName": { 34 | "Type": "String" 35 | }, 36 | "authRoleArn": { 37 | "Type": "String" 38 | }, 39 | "env": { 40 | "Type": "String" 41 | } 42 | }, 43 | "Metadata": { 44 | "AWS::CloudFormation::Interface": { 45 | "ParameterGroups": [ 46 | { 47 | "Label": { 48 | "default": "Creating pinpoint app" 49 | }, 50 | "Parameters": [ 51 | "appName" 52 | ] 53 | } 54 | ] 55 | } 56 | }, 57 | "Conditions": { 58 | "ShouldCreatePinpointApp": { 59 | "Fn::Equals": [ 60 | { 61 | "Ref": "appId" 62 | }, 63 | "NONE" 64 | ] 65 | }, 66 | "ShouldNotCreateEnvResources": { 67 | "Fn::Equals": [ 68 | { 69 | "Ref": "env" 70 | }, 71 | "NONE" 72 | ] 73 | } 74 | }, 75 | "Resources": { 76 | "LambdaExecutionRole": { 77 | "Condition": "ShouldCreatePinpointApp", 78 | "Type": "AWS::IAM::Role", 79 | "Properties": { 80 | "RoleName": { 81 | "Fn::If": [ 82 | "ShouldNotCreateEnvResources", 83 | { 84 | "Ref": "roleName" 85 | }, 86 | { 87 | "Fn::Join": [ 88 | "", 89 | [ 90 | { 91 | "Ref": "roleName" 92 | }, 93 | "-", 94 | { 95 | "Ref": "env" 96 | } 97 | ] 98 | ] 99 | } 100 | ] 101 | }, 102 | "AssumeRolePolicyDocument": { 103 | "Version": "2012-10-17", 104 | "Statement": [ 105 | { 106 | "Effect": "Allow", 107 | "Principal": { 108 | "Service": [ 109 | "lambda.amazonaws.com" 110 | ] 111 | }, 112 | "Action": [ 113 | "sts:AssumeRole" 114 | ] 115 | } 116 | ] 117 | }, 118 | "Policies": [ 119 | { 120 | "PolicyName": { 121 | "Ref": "cloudWatchPolicyName" 122 | }, 123 | "PolicyDocument": { 124 | "Version": "2012-10-17", 125 | "Statement": [ 126 | { 127 | "Effect": "Allow", 128 | "Action": [ 129 | "logs:CreateLogGroup", 130 | "logs:CreateLogStream", 131 | "logs:PutLogEvents" 132 | ], 133 | "Resource": "arn:aws:logs:*:*:*" 134 | } 135 | ] 136 | } 137 | }, 138 | { 139 | "PolicyName": { 140 | "Ref": "pinpointPolicyName" 141 | }, 142 | "PolicyDocument": { 143 | "Version": "2012-10-17", 144 | "Statement": [ 145 | { 146 | "Effect": "Allow", 147 | "Action": [ 148 | "mobileanalytics:*", 149 | "mobiletargeting:*" 150 | ], 151 | "Resource": "*" 152 | } 153 | ] 154 | } 155 | }, 156 | { 157 | "PolicyName": { 158 | "Ref": "cloudformationPolicyName" 159 | }, 160 | "PolicyDocument": { 161 | "Version": "2012-10-17", 162 | "Statement": [ 163 | { 164 | "Effect": "Allow", 165 | "Action": [ 166 | "cloudformation:*" 167 | ], 168 | "Resource": "*" 169 | } 170 | ] 171 | } 172 | } 173 | ] 174 | } 175 | }, 176 | "PinpointFunction": { 177 | "Type": "AWS::Lambda::Function", 178 | "Condition": "ShouldCreatePinpointApp", 179 | "Properties": { 180 | "Code": { 181 | "ZipFile": { 182 | "Fn::Join": [ 183 | "\n", 184 | [ 185 | "const response = require('cfn-response');", 186 | "const aws = require('aws-sdk');", 187 | "exports.handler = function(event, context) {", 188 | " if (event.RequestType == 'Delete') {", 189 | " const stackID = event.StackId;", 190 | " const cloudFormationClient = new aws.CloudFormation({ apiVersion: '2016-12-01', region: event.ResourceProperties.region });", 191 | " cloudFormationClient.describeStacks({ StackName: stackID }).promise()", 192 | " .then(describeStacksOutput => {", 193 | " let appId;", 194 | " if (describeStacksOutput.Stacks && describeStacksOutput.Stacks.length > 0) {", 195 | " const { Outputs } = describeStacksOutput.Stacks[0];", 196 | " const appIdOutput = Outputs.find((output)=>{ return output.OutputKey === 'Id'});", 197 | " appId = appIdOutput ? appIdOutput.OutputValue : undefined; ", 198 | " }", 199 | " return appId;", 200 | " })", 201 | " .then(appId => {", 202 | " if (appId) {", 203 | " const pinpointClient = new aws.Pinpoint({ apiVersion: '2016-12-01', region: event.ResourceProperties.pingPointRegion });", 204 | " const params = {", 205 | " ApplicationId: appId,", 206 | " };", 207 | " pinpointClient.deleteApp(params).promise();", 208 | " }", 209 | " })", 210 | " .then(()=>{", 211 | " response.send(event, context, response.SUCCESS, {'message': `Successfully deleted pinpoint project`});", 212 | " })", 213 | " .catch(e=>{", 214 | " response.send(event, context, response.FAILED, {'message': `Failed to deleted Pinpoint project`, 'exception': e});", 215 | " }); ", 216 | " }", 217 | " if (event.RequestType == 'Update') {", 218 | " response.send(event, context, response.SUCCESS);", 219 | " return;", 220 | " }", 221 | " if (event.RequestType == 'Create') {", 222 | " const appName = event.ResourceProperties.appName;", 223 | " let responseData = {};", 224 | " const params = {", 225 | " CreateApplicationRequest: {", 226 | " Name: appName", 227 | " }", 228 | " };", 229 | " const pinpoint = new aws.Pinpoint({ apiVersion: '2016-12-01', region: event.ResourceProperties.pingPointRegion });", 230 | " pinpoint.createApp(params).promise()", 231 | " .then((res) => {", 232 | " responseData = res.ApplicationResponse;", 233 | " response.send(event, context, response.SUCCESS, responseData);", 234 | " }).catch((err) => {", 235 | " console.log(err.stack);", 236 | " responseData = {Error: err};", 237 | " response.send(event, context, response.FAILED, responseData);", 238 | " throw err;", 239 | " });", 240 | " }", 241 | "};" 242 | ] 243 | ] 244 | } 245 | }, 246 | "Handler": "index.handler", 247 | "Runtime": "nodejs12.x", 248 | "Timeout": "300", 249 | "Role": { 250 | "Fn::GetAtt": [ 251 | "LambdaExecutionRole", 252 | "Arn" 253 | ] 254 | } 255 | } 256 | }, 257 | "PinpointFunctionOutputs": { 258 | "Type": "Custom::LambdaCallout", 259 | "Condition": "ShouldCreatePinpointApp", 260 | "Properties": { 261 | "ServiceToken": { 262 | "Fn::GetAtt": [ 263 | "PinpointFunction", 264 | "Arn" 265 | ] 266 | }, 267 | "region": { 268 | "Ref": "AWS::Region" 269 | }, 270 | "pingPointRegion": { 271 | "Fn::FindInMap": [ 272 | "RegionMapping", 273 | { 274 | "Ref": "AWS::Region" 275 | }, 276 | "pinpointRegion" 277 | ] 278 | }, 279 | "appName": { 280 | "Fn::If": [ 281 | "ShouldNotCreateEnvResources", 282 | { 283 | "Ref": "appName" 284 | }, 285 | { 286 | "Fn::Join": [ 287 | "", 288 | [ 289 | { 290 | "Ref": "appName" 291 | }, 292 | "-", 293 | { 294 | "Ref": "env" 295 | } 296 | ] 297 | ] 298 | } 299 | ] 300 | } 301 | }, 302 | "DependsOn": "PinpointFunction" 303 | }, 304 | "CognitoUnauthPolicy": { 305 | "Type": "AWS::IAM::Policy", 306 | "Condition": "ShouldCreatePinpointApp", 307 | "Properties": { 308 | "PolicyName": { 309 | "Ref": "unauthPolicyName" 310 | }, 311 | "Roles": [ 312 | { 313 | "Ref": "unauthRoleName" 314 | } 315 | ], 316 | "PolicyDocument": { 317 | "Version": "2012-10-17", 318 | "Statement": [ 319 | { 320 | "Effect": "Allow", 321 | "Action": [ 322 | "mobiletargeting:PutEvents", 323 | "mobiletargeting:UpdateEndpoint" 324 | ], 325 | "Resource": [ 326 | { 327 | "Fn::If": [ 328 | "ShouldCreatePinpointApp", 329 | { 330 | "Fn::Join": [ 331 | "", 332 | [ 333 | "arn:aws:mobiletargeting:*:", 334 | { 335 | "Fn::Select": [ 336 | "4", 337 | { 338 | "Fn::Split": [ 339 | ":", 340 | { 341 | "Ref": "authRoleArn" 342 | } 343 | ] 344 | } 345 | ] 346 | }, 347 | ":apps/", 348 | { 349 | "Fn::GetAtt": [ 350 | "PinpointFunctionOutputs", 351 | "Id" 352 | ] 353 | }, 354 | "*" 355 | ] 356 | ] 357 | }, 358 | { 359 | "Fn::Join": [ 360 | "", 361 | [ 362 | "arn:aws:mobiletargeting:*:", 363 | { 364 | "Fn::Select": [ 365 | "4", 366 | { 367 | "Fn::Split": [ 368 | ":", 369 | { 370 | "Ref": "authRoleArn" 371 | } 372 | ] 373 | } 374 | ] 375 | }, 376 | ":apps/", 377 | { 378 | "Ref": "appId" 379 | }, 380 | "*" 381 | ] 382 | ] 383 | } 384 | ] 385 | } 386 | ] 387 | } 388 | ] 389 | } 390 | } 391 | }, 392 | "CognitoAuthPolicy": { 393 | "Type": "AWS::IAM::Policy", 394 | "Condition": "ShouldCreatePinpointApp", 395 | "Properties": { 396 | "PolicyName": { 397 | "Ref": "authPolicyName" 398 | }, 399 | "Roles": [ 400 | { 401 | "Ref": "authRoleName" 402 | } 403 | ], 404 | "PolicyDocument": { 405 | "Version": "2012-10-17", 406 | "Statement": [ 407 | { 408 | "Effect": "Allow", 409 | "Action": [ 410 | "mobiletargeting:PutEvents", 411 | "mobiletargeting:UpdateEndpoint" 412 | ], 413 | "Resource": [ 414 | { 415 | "Fn::If": [ 416 | "ShouldCreatePinpointApp", 417 | { 418 | "Fn::Join": [ 419 | "", 420 | [ 421 | "arn:aws:mobiletargeting:*:", 422 | { 423 | "Fn::Select": [ 424 | "4", 425 | { 426 | "Fn::Split": [ 427 | ":", 428 | { 429 | "Ref": "authRoleArn" 430 | } 431 | ] 432 | } 433 | ] 434 | }, 435 | ":apps/", 436 | { 437 | "Fn::GetAtt": [ 438 | "PinpointFunctionOutputs", 439 | "Id" 440 | ] 441 | }, 442 | "*" 443 | ] 444 | ] 445 | }, 446 | { 447 | "Fn::Join": [ 448 | "", 449 | [ 450 | "arn:aws:mobiletargeting:*:", 451 | { 452 | "Fn::Select": [ 453 | "4", 454 | { 455 | "Fn::Split": [ 456 | ":", 457 | { 458 | "Ref": "authRoleArn" 459 | } 460 | ] 461 | } 462 | ] 463 | }, 464 | ":apps/", 465 | { 466 | "Ref": "appId" 467 | }, 468 | "*" 469 | ] 470 | ] 471 | } 472 | ] 473 | } 474 | ] 475 | } 476 | ] 477 | } 478 | } 479 | } 480 | }, 481 | "Outputs": { 482 | "Region": { 483 | "Value": { 484 | "Fn::FindInMap": [ 485 | "RegionMapping", 486 | { 487 | "Ref": "AWS::Region" 488 | }, 489 | "pinpointRegion" 490 | ] 491 | } 492 | }, 493 | "Id": { 494 | "Value": { 495 | "Fn::If": [ 496 | "ShouldCreatePinpointApp", 497 | { 498 | "Fn::GetAtt": [ 499 | "PinpointFunctionOutputs", 500 | "Id" 501 | ] 502 | }, 503 | { 504 | "Ref": "appId" 505 | } 506 | ] 507 | } 508 | }, 509 | "appName": { 510 | "Value": { 511 | "Fn::If": [ 512 | "ShouldCreatePinpointApp", 513 | { 514 | "Fn::GetAtt": [ 515 | "PinpointFunctionOutputs", 516 | "Name" 517 | ] 518 | }, 519 | { 520 | "Ref": "appName" 521 | } 522 | ] 523 | } 524 | } 525 | }, 526 | "Mappings": { 527 | "RegionMapping": { 528 | "us-east-1": { 529 | "pinpointRegion": "us-east-1" 530 | }, 531 | "us-east-2": { 532 | "pinpointRegion": "us-east-1" 533 | }, 534 | "sa-east-1": { 535 | "pinpointRegion": "us-east-1" 536 | }, 537 | "ca-central-1": { 538 | "pinpointRegion": "us-east-1" 539 | }, 540 | "us-west-1": { 541 | "pinpointRegion": "us-west-2" 542 | }, 543 | "us-west-2": { 544 | "pinpointRegion": "us-west-2" 545 | }, 546 | "cn-north-1": { 547 | "pinpointRegion": "us-west-2" 548 | }, 549 | "cn-northwest-1": { 550 | "pinpointRegion": "us-west-2" 551 | }, 552 | "ap-south-1": { 553 | "pinpointRegion": "us-west-2" 554 | }, 555 | "ap-northeast-3": { 556 | "pinpointRegion": "us-west-2" 557 | }, 558 | "ap-northeast-2": { 559 | "pinpointRegion": "us-west-2" 560 | }, 561 | "ap-southeast-1": { 562 | "pinpointRegion": "us-west-2" 563 | }, 564 | "ap-southeast-2": { 565 | "pinpointRegion": "us-west-2" 566 | }, 567 | "ap-northeast-1": { 568 | "pinpointRegion": "us-west-2" 569 | }, 570 | "eu-central-1": { 571 | "pinpointRegion": "eu-central-1" 572 | }, 573 | "eu-west-1": { 574 | "pinpointRegion": "eu-west-1" 575 | }, 576 | "eu-west-2": { 577 | "pinpointRegion": "eu-west-1" 578 | }, 579 | "eu-west-3": { 580 | "pinpointRegion": "eu-west-1" 581 | } 582 | } 583 | } 584 | } --------------------------------------------------------------------------------