diff --git a/Listify/.gitignore b/Listify/.gitignore index 603b140..49b1255 100644 --- a/Listify/.gitignore +++ b/Listify/.gitignore @@ -12,3 +12,19 @@ /captures .externalNativeBuild .cxx + +#amplify +amplify/\#current-cloud-backend +amplify/.config/local-* +amplify/mock-data +amplify/backend/amplify-meta.json +amplify/backend/awscloudformation +build/ +dist/ +node_modules/ +aws-exports.js +awsconfiguration.json +amplifyconfiguration.json +amplify-build-config.json +amplify-gradle-config.json +amplifytools.xcconfig \ No newline at end of file diff --git a/Listify/.idea/misc.xml b/Listify/.idea/misc.xml index 892046b..fdae1d0 100644 --- a/Listify/.idea/misc.xml +++ b/Listify/.idea/misc.xml @@ -1,6 +1,6 @@ - + diff --git a/Listify/amplify/.config/project-config.json b/Listify/amplify/.config/project-config.json new file mode 100644 index 0000000..a201d20 --- /dev/null +++ b/Listify/amplify/.config/project-config.json @@ -0,0 +1,13 @@ +{ + "projectName": "Listify", + "version": "3.0", + "frontend": "android", + "android": { + "config": { + "ResDir": "app/src/main/res" + } + }, + "providers": [ + "awscloudformation" + ] +} \ No newline at end of file diff --git a/Listify/amplify/backend/auth/listifyf4fad454/listifyf4fad454-cloudformation-template.yml b/Listify/amplify/backend/auth/listifyf4fad454/listifyf4fad454-cloudformation-template.yml new file mode 100644 index 0000000..95c418b --- /dev/null +++ b/Listify/amplify/backend/auth/listifyf4fad454/listifyf4fad454-cloudformation-template.yml @@ -0,0 +1,396 @@ +AWSTemplateFormatVersion: 2010-09-09 + +Parameters: + env: + Type: String + authRoleArn: + Type: String + unauthRoleArn: + Type: String + + + + + identityPoolName: + Type: String + + allowUnauthenticatedIdentities: + Type: String + + resourceNameTruncated: + Type: String + + userPoolName: + Type: String + + autoVerifiedAttributes: + Type: CommaDelimitedList + + mfaConfiguration: + Type: String + + mfaTypes: + Type: CommaDelimitedList + + smsAuthenticationMessage: + Type: String + + smsVerificationMessage: + Type: String + + emailVerificationSubject: + Type: String + + emailVerificationMessage: + Type: String + + defaultPasswordPolicy: + Type: String + + passwordPolicyMinLength: + Type: Number + + passwordPolicyCharacters: + Type: CommaDelimitedList + + requiredAttributes: + Type: CommaDelimitedList + + userpoolClientGenerateSecret: + Type: String + + userpoolClientRefreshTokenValidity: + Type: Number + + userpoolClientWriteAttributes: + Type: CommaDelimitedList + + userpoolClientReadAttributes: + Type: CommaDelimitedList + + userpoolClientLambdaRole: + Type: String + + userpoolClientSetAttributes: + Type: String + + sharedId: + Type: String + + resourceName: + Type: String + + authSelections: + Type: String + + useDefault: + Type: String + + usernameAttributes: + Type: CommaDelimitedList + + triggers: + Type: String + + userPoolGroupList: + Type: CommaDelimitedList + + serviceName: + Type: String + + parentStack: + Type: String + + permissions: + Type: CommaDelimitedList + + dependsOn: + Type: CommaDelimitedList + +Conditions: + ShouldNotCreateEnvResources: !Equals [ !Ref env, NONE ] + +Resources: + + + # BEGIN SNS ROLE RESOURCE + SNSRole: + # Created to allow the UserPool SMS Config to publish via the Simple Notification Service during MFA Process + Type: AWS::IAM::Role + Properties: + RoleName: !If [ShouldNotCreateEnvResources, 'listiff4fad454_sns-role', !Join ['',[ 'sns', 'f4fad454', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]] + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Sid: "" + Effect: "Allow" + Principal: + Service: "cognito-idp.amazonaws.com" + Action: + - "sts:AssumeRole" + Condition: + StringEquals: + sts:ExternalId: listiff4fad454_role_external_id + Policies: + - + PolicyName: listiff4fad454-sns-policy + PolicyDocument: + Version: "2012-10-17" + Statement: + - + Effect: "Allow" + Action: + - "sns:Publish" + Resource: "*" + # BEGIN USER POOL RESOURCES + UserPool: + # Created upon user selection + # Depends on SNS Role for Arn if MFA is enabled + Type: AWS::Cognito::UserPool + UpdateReplacePolicy: Retain + Properties: + UserPoolName: !If [ShouldNotCreateEnvResources, !Ref userPoolName, !Join ['',[!Ref userPoolName, '-', !Ref env]]] + + Schema: + + - + Name: email + Required: true + Mutable: true + + + + + AutoVerifiedAttributes: !Ref autoVerifiedAttributes + + + EmailVerificationMessage: !Ref emailVerificationMessage + EmailVerificationSubject: !Ref emailVerificationSubject + + Policies: + PasswordPolicy: + MinimumLength: !Ref passwordPolicyMinLength + RequireLowercase: false + RequireNumbers: false + RequireSymbols: false + RequireUppercase: false + + UsernameAttributes: !Ref usernameAttributes + + MfaConfiguration: !Ref mfaConfiguration + SmsVerificationMessage: !Ref smsVerificationMessage + SmsConfiguration: + SnsCallerArn: !GetAtt SNSRole.Arn + ExternalId: listiff4fad454_role_external_id + + + + + + + + + + + + # Updating lambda role with permissions to Cognito + + + UserPoolClientWeb: + # Created provide application access to user pool + # Depends on UserPool for ID reference + Type: "AWS::Cognito::UserPoolClient" + Properties: + ClientName: listiff4fad454_app_clientWeb + + RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity + UserPoolId: !Ref UserPool + DependsOn: UserPool + UserPoolClient: + # Created provide application access to user pool + # Depends on UserPool for ID reference + Type: "AWS::Cognito::UserPoolClient" + Properties: + ClientName: listiff4fad454_app_client + + GenerateSecret: !Ref userpoolClientGenerateSecret + RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity + UserPoolId: !Ref UserPool + DependsOn: UserPool + # BEGIN USER POOL LAMBDA RESOURCES + UserPoolClientRole: + # Created to execute Lambda which gets userpool app client config values + Type: 'AWS::IAM::Role' + Properties: + RoleName: !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',['upClientLambdaRole', 'f4fad454', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]] + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: + - lambda.amazonaws.com + Action: + - 'sts:AssumeRole' + DependsOn: UserPoolClient + UserPoolClientLambda: + # Lambda which gets userpool app client config values + # Depends on UserPool for id + # Depends on UserPoolClientRole for role ARN + Type: 'AWS::Lambda::Function' + Properties: + Code: + ZipFile: !Join + - |+ + - - 'const response = require(''cfn-response'');' + - 'const aws = require(''aws-sdk'');' + - 'const identity = new aws.CognitoIdentityServiceProvider();' + - 'exports.handler = (event, context, callback) => {' + - ' if (event.RequestType == ''Delete'') { ' + - ' response.send(event, context, response.SUCCESS, {})' + - ' }' + - ' if (event.RequestType == ''Update'' || event.RequestType == ''Create'') {' + - ' const params = {' + - ' ClientId: event.ResourceProperties.clientId,' + - ' UserPoolId: event.ResourceProperties.userpoolId' + - ' };' + - ' identity.describeUserPoolClient(params).promise()' + - ' .then((res) => {' + - ' response.send(event, context, response.SUCCESS, {''appSecret'': res.UserPoolClient.ClientSecret});' + - ' })' + - ' .catch((err) => {' + - ' response.send(event, context, response.FAILED, {err});' + - ' });' + - ' }' + - '};' + Handler: index.handler + Runtime: nodejs10.x + Timeout: '300' + Role: !GetAtt + - UserPoolClientRole + - Arn + DependsOn: UserPoolClientRole + UserPoolClientLambdaPolicy: + # Sets userpool policy for the role that executes the Userpool Client Lambda + # Depends on UserPool for Arn + # Marked as depending on UserPoolClientRole for easier to understand CFN sequencing + Type: 'AWS::IAM::Policy' + Properties: + PolicyName: listiff4fad454_userpoolclient_lambda_iam_policy + Roles: + - !Ref UserPoolClientRole + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - 'cognito-idp:DescribeUserPoolClient' + Resource: !GetAtt UserPool.Arn + DependsOn: UserPoolClientLambda + UserPoolClientLogPolicy: + # Sets log policy for the role that executes the Userpool Client Lambda + # Depends on UserPool for Arn + # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing + Type: 'AWS::IAM::Policy' + Properties: + PolicyName: listiff4fad454_userpoolclient_lambda_log_policy + Roles: + - !Ref UserPoolClientRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - 'logs:CreateLogGroup' + - 'logs:CreateLogStream' + - 'logs:PutLogEvents' + Resource: !Sub + - arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:* + - { region: !Ref "AWS::Region", account: !Ref "AWS::AccountId", lambda: !Ref UserPoolClientLambda} + DependsOn: UserPoolClientLambdaPolicy + UserPoolClientInputs: + # Values passed to Userpool client Lambda + # Depends on UserPool for Id + # Depends on UserPoolClient for Id + # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing + Type: 'Custom::LambdaCallout' + Properties: + ServiceToken: !GetAtt UserPoolClientLambda.Arn + clientId: !Ref UserPoolClient + userpoolId: !Ref UserPool + DependsOn: UserPoolClientLogPolicy + + + + + + + + # BEGIN IDENTITY POOL RESOURCES + + + IdentityPool: + # Always created + Type: AWS::Cognito::IdentityPool + Properties: + IdentityPoolName: !If [ShouldNotCreateEnvResources, 'listifyf4fad454_identitypool_f4fad454', !Join ['',['listifyf4fad454_identitypool_f4fad454', '__', !Ref env]]] + + CognitoIdentityProviders: + - ClientId: !Ref UserPoolClient + ProviderName: !Sub + - cognito-idp.${region}.amazonaws.com/${client} + - { region: !Ref "AWS::Region", client: !Ref UserPool} + - ClientId: !Ref UserPoolClientWeb + ProviderName: !Sub + - cognito-idp.${region}.amazonaws.com/${client} + - { region: !Ref "AWS::Region", client: !Ref UserPool} + + AllowUnauthenticatedIdentities: !Ref allowUnauthenticatedIdentities + + + DependsOn: UserPoolClientInputs + + + IdentityPoolRoleMap: + # Created to map Auth and Unauth roles to the identity pool + # Depends on Identity Pool for ID ref + Type: AWS::Cognito::IdentityPoolRoleAttachment + Properties: + IdentityPoolId: !Ref IdentityPool + Roles: + unauthenticated: !Ref unauthRoleArn + authenticated: !Ref authRoleArn + DependsOn: IdentityPool + + +Outputs : + + IdentityPoolId: + Value: !Ref 'IdentityPool' + Description: Id for the identity pool + IdentityPoolName: + Value: !GetAtt IdentityPool.Name + + + + + UserPoolId: + Value: !Ref 'UserPool' + Description: Id for the user pool + UserPoolName: + Value: !Ref userPoolName + AppClientIDWeb: + Value: !Ref 'UserPoolClientWeb' + Description: The user pool app client id for web + AppClientID: + Value: !Ref 'UserPoolClient' + Description: The user pool app client id + AppClientSecret: + Value: !GetAtt UserPoolClientInputs.appSecret + + + + + + + diff --git a/Listify/amplify/backend/auth/listifyf4fad454/parameters.json b/Listify/amplify/backend/auth/listifyf4fad454/parameters.json new file mode 100644 index 0000000..1118f10 --- /dev/null +++ b/Listify/amplify/backend/auth/listifyf4fad454/parameters.json @@ -0,0 +1,60 @@ +{ + "identityPoolName": "listifyf4fad454_identitypool_f4fad454", + "allowUnauthenticatedIdentities": false, + "resourceNameTruncated": "listiff4fad454", + "userPoolName": "listifyf4fad454_userpool_f4fad454", + "autoVerifiedAttributes": [ + "email" + ], + "mfaConfiguration": "OFF", + "mfaTypes": [ + "SMS Text Message" + ], + "smsAuthenticationMessage": "Your authentication code is {####}", + "smsVerificationMessage": "Your verification code is {####}", + "emailVerificationSubject": "Your verification code", + "emailVerificationMessage": "Your verification code is {####}", + "defaultPasswordPolicy": false, + "passwordPolicyMinLength": 8, + "passwordPolicyCharacters": [], + "requiredAttributes": [ + "email" + ], + "userpoolClientGenerateSecret": true, + "userpoolClientRefreshTokenValidity": 30, + "userpoolClientWriteAttributes": [ + "email" + ], + "userpoolClientReadAttributes": [ + "email" + ], + "userpoolClientLambdaRole": "listiff4fad454_userpoolclient_lambda_role", + "userpoolClientSetAttributes": false, + "sharedId": "f4fad454", + "resourceName": "listifyf4fad454", + "authSelections": "identityPoolAndUserPool", + "authRoleArn": { + "Fn::GetAtt": [ + "AuthRole", + "Arn" + ] + }, + "unauthRoleArn": { + "Fn::GetAtt": [ + "UnauthRole", + "Arn" + ] + }, + "useDefault": "default", + "usernameAttributes": [ + "email" + ], + "triggers": "{}", + "userPoolGroupList": [], + "serviceName": "Cognito", + "parentStack": { + "Ref": "AWS::StackId" + }, + "permissions": [], + "dependsOn": [] +} \ No newline at end of file diff --git a/Listify/amplify/backend/backend-config.json b/Listify/amplify/backend/backend-config.json new file mode 100644 index 0000000..8b34cae --- /dev/null +++ b/Listify/amplify/backend/backend-config.json @@ -0,0 +1,10 @@ +{ + "auth": { + "listifyf4fad454": { + "service": "Cognito", + "providerPlugin": "awscloudformation", + "dependsOn": [], + "customAuth": false + } + } +} \ No newline at end of file diff --git a/Listify/amplify/backend/tags.json b/Listify/amplify/backend/tags.json new file mode 100644 index 0000000..b9321d7 --- /dev/null +++ b/Listify/amplify/backend/tags.json @@ -0,0 +1,10 @@ +[ + { + "Key": "user:Stack", + "Value": "{project-env}" + }, + { + "Key": "user:Application", + "Value": "{project-name}" + } +] \ No newline at end of file diff --git a/Listify/amplify/cli.json b/Listify/amplify/cli.json new file mode 100644 index 0000000..876a6e2 --- /dev/null +++ b/Listify/amplify/cli.json @@ -0,0 +1,3 @@ +{ + "features": {} +} \ No newline at end of file diff --git a/Listify/amplify/team-provider-info.json b/Listify/amplify/team-provider-info.json new file mode 100644 index 0000000..2ff66cd --- /dev/null +++ b/Listify/amplify/team-provider-info.json @@ -0,0 +1,20 @@ +{ + "dev": { + "awscloudformation": { + "AuthRoleName": "amplify-listify-dev-134836-authRole", + "UnauthRoleArn": "arn:aws:iam::569815541706:role/amplify-listify-dev-134836-unauthRole", + "AuthRoleArn": "arn:aws:iam::569815541706:role/amplify-listify-dev-134836-authRole", + "Region": "us-east-2", + "DeploymentBucketName": "amplify-listify-dev-134836-deployment", + "UnauthRoleName": "amplify-listify-dev-134836-unauthRole", + "StackName": "amplify-listify-dev-134836", + "StackId": "arn:aws:cloudformation:us-east-2:569815541706:stack/amplify-listify-dev-134836/5980b520-faa0-11ea-a89c-0650659cf0f8", + "AmplifyAppId": "dbnznhwtkbqz6" + }, + "categories": { + "auth": { + "listifyf4fad454": {} + } + } + } +} \ No newline at end of file diff --git a/Listify/app/build.gradle b/Listify/app/build.gradle index f56ecf1..4e13596 100644 --- a/Listify/app/build.gradle +++ b/Listify/app/build.gradle @@ -14,6 +14,13 @@ android { testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } + compileOptions { + // Support for Java 8 features + coreLibraryDesugaringEnabled true + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + buildTypes { release { minifyEnabled false @@ -34,5 +41,8 @@ dependencies { testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + implementation 'com.amplifyframework:core:1.3.2' + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' + implementation 'com.amplifyframework:aws-auth-cognito:1.3.2' } \ No newline at end of file diff --git a/Listify/app/src/main/AndroidManifest.xml b/Listify/app/src/main/AndroidManifest.xml index 7672ac7..3c75eac 100644 --- a/Listify/app/src/main/AndroidManifest.xml +++ b/Listify/app/src/main/AndroidManifest.xml @@ -3,6 +3,7 @@ package="com.example.listify"> setAuthSession(result), + error -> setAuthError(error) + ); + throwIfAuthError(); + } + + + public void setAuthSession(AuthSession toSet) { + authSession = toSet; + } + + public void setAuthError(AuthException newError) { + authError = newError; + waiting = false; + } + + public void throwIfAuthError() throws AuthException{ + while (waiting); + if (authError == null) { + return; + } + AuthException toThrow = authError; + authError = null; + throw toThrow; + } + + public void setAuthSignUpResult(AuthSignUpResult toSet) { + authSignUpResult = toSet; + } + + public void startSignup(String email, String password) throws AuthException { + this.email = email; + this.password = password; + waiting = true; + Amplify.Auth.signUp( + email, + password, + AuthSignUpOptions.builder().build(), + result -> setAuthSignUpResult(result), + error -> setAuthError(error) + ); + throwIfAuthError(); + + } + + public void confirmSignUp(String confirmationCode) { + Amplify.Auth.confirmSignUp( + email, + confirmationCode, + result -> Log.i("AuthQuickstart", result.isSignUpComplete() ? "Confirm signUp succeeded" : "Confirm sign up not complete"), + error -> Log.e("AuthQuickstart", error.toString()) + ); + } + + public void signIn(String email, String password) { + Amplify.Auth.signIn( + email, + password, + result -> Log.i("AuthQuickstart", result.isSignInComplete() ? "Sign in succeeded" : "Sign in not complete"), + error -> Log.e("AuthQuickstart", error.toString()) + ); + } + + + + +} diff --git a/Listify/app/src/main/java/com/example/listify/Listify.java b/Listify/app/src/main/java/com/example/listify/Listify.java new file mode 100644 index 0000000..20e6d11 --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/Listify.java @@ -0,0 +1,20 @@ +package com.example.listify; + +import android.util.Log; +import com.amplifyframework.AmplifyException; +import com.amplifyframework.auth.cognito.AWSCognitoAuthPlugin; +import com.amplifyframework.core.Amplify; + +public class Listify extends android.app.Application { + public void onCreate() { + super.onCreate(); + + try { + Amplify.addPlugin(new AWSCognitoAuthPlugin()); + Amplify.configure(getApplicationContext()); + Log.i("MyAmplifyApp", "Initialized Amplify"); + } catch (AmplifyException error) { + Log.e("MyAmplifyApp", "Could not initialize Amplify", error); + } + } +} diff --git a/Listify/app/src/main/java/com/example/listify/MainActivity.java b/Listify/app/src/main/java/com/example/listify/MainActivity.java index f63de5b..3145a02 100644 --- a/Listify/app/src/main/java/com/example/listify/MainActivity.java +++ b/Listify/app/src/main/java/com/example/listify/MainActivity.java @@ -1,9 +1,13 @@ package com.example.listify; import android.os.Bundle; +import android.util.Log; import android.view.View; import android.view.Menu; +import com.amplifyframework.auth.AuthUserAttributeKey; +import com.amplifyframework.auth.options.AuthSignUpOptions; +import com.amplifyframework.core.Amplify; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.snackbar.Snackbar; import com.google.android.material.navigation.NavigationView; @@ -23,6 +27,12 @@ public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + //------------------------------Auth Testing---------------------------------------------// + + + + + //------------------------------------------------------------------------------------------// setContentView(R.layout.activity_main); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar);