diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index b40952a..46d458c 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -7,11 +7,11 @@ - + - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 28966ce..dca0bdc 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -26,6 +26,9 @@ + + + diff --git a/amplify/.config/project-config.json b/amplify/.config/project-config.json index 8119c68..900607a 100644 --- a/amplify/.config/project-config.json +++ b/amplify/.config/project-config.json @@ -1,13 +1,13 @@ { - "projectName": "thrifty", + "providers": [ + "awscloudformation" + ], + "projectName": "thrifty2", "version": "3.1", "frontend": "android", "android": { "config": { "ResDir": "app/src/main/res" } - }, - "providers": [ - "awscloudformation" - ] + } } \ No newline at end of file diff --git a/amplify/README.md b/amplify/README.md deleted file mode 100644 index 7c0a9e2..0000000 --- a/amplify/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Getting Started with Amplify CLI -This directory was generated by [Amplify CLI](https://docs.amplify.aws/cli). - -Helpful resources: -- Amplify documentation: https://docs.amplify.aws -- Amplify CLI documentation: https://docs.amplify.aws/cli -- More details on this folder & generated files: https://docs.amplify.aws/cli/reference/files -- Join Amplify's community: https://amplify.aws/community/ diff --git a/amplify/backend/api/thrifty/.migration-backup/schema.graphql b/amplify/backend/api/thrifty/.migration-backup/schema.graphql deleted file mode 100644 index edc9ad0..0000000 --- a/amplify/backend/api/thrifty/.migration-backup/schema.graphql +++ /dev/null @@ -1,28 +0,0 @@ -type Product @model @auth(rules: [{allow: public}]) @key(name: "byCategory", fields: ["categoryID"]) { - id: ID! - title: String! - description: String! - price: String! - size: String! - color: String! - image: String! - categoryID: ID -} - -type Favorite @model @auth(rules: [{allow: public}]) @key(name: "byUser", fields: ["userID"]) { - id: ID! - userID: ID - Product: Product @connection -} - -type Category @model @auth(rules: [{allow: public}]) { - id: ID! - name: String! - Products: [Product] @connection(keyName: "byCategory", fields: ["id"]) -} - -type User @model @auth(rules: [{allow: public}]) { - id: ID! - email: String! - Favorites: [Favorite] @connection(keyName: "byUser", fields: ["id"]) -} diff --git a/amplify/backend/api/thrifty/parameters.json b/amplify/backend/api/thrifty/parameters.json deleted file mode 100644 index 2b477e2..0000000 --- a/amplify/backend/api/thrifty/parameters.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "AppSyncApiName": "thrifty", - "DynamoDBBillingMode": "PAY_PER_REQUEST", - "DynamoDBEnableServerSideEncryption": false -} \ No newline at end of file diff --git a/amplify/backend/api/thrifty/cli-inputs.json b/amplify/backend/api/thrifty2/cli-inputs.json similarity index 52% rename from amplify/backend/api/thrifty/cli-inputs.json rename to amplify/backend/api/thrifty2/cli-inputs.json index 7f9c285..a956ae3 100644 --- a/amplify/backend/api/thrifty/cli-inputs.json +++ b/amplify/backend/api/thrifty2/cli-inputs.json @@ -1,23 +1,24 @@ { "version": 1, "serviceConfiguration": { - "apiName": "thrifty", "serviceName": "AppSync", - "gqlSchemaPath": "/tmp/amplify-2e97eeff-bfb1-4790-87ca-b286e0a41ce2/amplify/backend/api/thrifty/schema.graphql", "defaultAuthType": { "mode": "API_KEY", - "keyDescription": "api key description", - "expirationTime": 30 + "expirationTime": 35, + "apiKeyExpirationDate": "2022-01-06T02:02:46.260Z", + "keyDescription": "ssdmh" }, - "additionalAuthTypes": [ - { - "mode": "AWS_IAM" - } - ], "conflictResolution": { "defaultResolutionStrategy": { "type": "AUTOMERGE" } - } + }, + "apiName": "thrifty2", + "gqlSchemaPath": "/mnt/c/Users/STUDENT/AndroidStudioProjects/thrifty/amplify/backend/api/thrifty2/schema.graphql", + "additionalAuthTypes": [ + { + "mode": "AWS_IAM" + } + ] } } \ No newline at end of file diff --git a/amplify/backend/api/thrifty2/parameters.json b/amplify/backend/api/thrifty2/parameters.json new file mode 100644 index 0000000..254946c --- /dev/null +++ b/amplify/backend/api/thrifty2/parameters.json @@ -0,0 +1,12 @@ +{ + "AppSyncApiName": "thrifty2", + "DynamoDBBillingMode": "PAY_PER_REQUEST", + "DynamoDBEnableServerSideEncryption": false, + "AuthCognitoUserPoolId": { + "Fn::GetAtt": [ + "auththrifty23c488d7e", + "Outputs.UserPoolId" + ] + }, + "AuthModeLastUpdated": "2021-12-01T23:40:42.562Z" +} \ No newline at end of file diff --git a/amplify/backend/api/thrifty/resolvers/README.md b/amplify/backend/api/thrifty2/resolvers/README.md similarity index 100% rename from amplify/backend/api/thrifty/resolvers/README.md rename to amplify/backend/api/thrifty2/resolvers/README.md diff --git a/amplify/backend/api/thrifty/schema.graphql b/amplify/backend/api/thrifty2/schema.graphql similarity index 100% rename from amplify/backend/api/thrifty/schema.graphql rename to amplify/backend/api/thrifty2/schema.graphql diff --git a/amplify/backend/api/thrifty/stacks/CustomResources.json b/amplify/backend/api/thrifty2/stacks/CustomResources.json similarity index 100% rename from amplify/backend/api/thrifty/stacks/CustomResources.json rename to amplify/backend/api/thrifty2/stacks/CustomResources.json diff --git a/amplify/backend/api/thrifty/transform.conf.json b/amplify/backend/api/thrifty2/transform.conf.json similarity index 100% rename from amplify/backend/api/thrifty/transform.conf.json rename to amplify/backend/api/thrifty2/transform.conf.json diff --git a/amplify/backend/auth/thrifty880b2640/cli-inputs.json b/amplify/backend/auth/thrifty23c488d7e/parameters.json similarity index 59% rename from amplify/backend/auth/thrifty880b2640/cli-inputs.json rename to amplify/backend/auth/thrifty23c488d7e/parameters.json index 3132851..a91ddc4 100644 --- a/amplify/backend/auth/thrifty880b2640/cli-inputs.json +++ b/amplify/backend/auth/thrifty23c488d7e/parameters.json @@ -1,16 +1,14 @@ { - "version": "1", - "cognitoConfig": { - "identityPoolName": "thrifty880b2640_identitypool_880b2640", - "allowUnauthenticatedIdentities": true, - "resourceNameTruncated": "thrift880b2640", - "userPoolName": "thrifty880b2640_userpool_880b2640", + "identityPoolName": "thrifty23c488d7e_identitypool_3c488d7e", + "allowUnauthenticatedIdentities": false, + "resourceNameTruncated": "thrift3c488d7e", + "userPoolName": "thrifty23c488d7e_userpool_3c488d7e", "autoVerifiedAttributes": [ - "email" + "email" ], "mfaConfiguration": "OFF", "mfaTypes": [ - "SMS Text Message" + "SMS Text Message" ], "smsAuthenticationMessage": "Your authentication code is {####}", "smsVerificationMessage": "Your verification code is {####}", @@ -20,42 +18,40 @@ "passwordPolicyMinLength": 8, "passwordPolicyCharacters": [], "requiredAttributes": [ - "email" + "email" ], "aliasAttributes": [], "userpoolClientGenerateSecret": false, "userpoolClientRefreshTokenValidity": 30, "userpoolClientWriteAttributes": [ - "email" + "email" ], "userpoolClientReadAttributes": [ - "email" + "email" ], - "userpoolClientLambdaRole": "thrift880b2640_userpoolclient_lambda_role", + "userpoolClientLambdaRole": "thrift3c488d7e_userpoolclient_lambda_role", "userpoolClientSetAttributes": false, - "sharedId": "880b2640", - "resourceName": "thrifty880b2640", + "sharedId": "3c488d7e", + "resourceName": "thrifty23c488d7e", "authSelections": "identityPoolAndUserPool", + "authRoleArn": { + "Fn::GetAtt": [ + "AuthRole", + "Arn" + ] + }, + "unauthRoleArn": { + "Fn::GetAtt": [ + "UnauthRole", + "Arn" + ] + }, "useDefault": "default", "usernameAttributes": [ - "email" + "email" ], "userPoolGroupList": [], "serviceName": "Cognito", - "useEnabledMfas": false, - "authRoleArn": { - "Fn::GetAtt": [ - "AuthRole", - "Arn" - ] - }, - "unauthRoleArn": { - "Fn::GetAtt": [ - "UnauthRole", - "Arn" - ] - }, - "breakCircularDependency": false, + "usernameCaseSensitive": false, "dependsOn": [] - } } \ No newline at end of file diff --git a/amplify/backend/auth/thrifty23c488d7e/thrifty23c488d7e-cloudformation-template.yml b/amplify/backend/auth/thrifty23c488d7e/thrifty23c488d7e-cloudformation-template.yml new file mode 100644 index 0000000..cc8fd58 --- /dev/null +++ b/amplify/backend/auth/thrifty23c488d7e/thrifty23c488d7e-cloudformation-template.yml @@ -0,0 +1,433 @@ + +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 + + + aliasAttributes: + 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 + + + userPoolGroupList: + Type: CommaDelimitedList + + + serviceName: + Type: String + + + + usernameCaseSensitive: + Type: String + + + dependsOn: + Type: CommaDelimitedList + +Conditions: + ShouldNotCreateEnvResources: !Equals [ !Ref env, NONE ] + + ShouldOutputAppClientSecrets: !Equals [!Ref userpoolClientGenerateSecret, true ] + + +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, 'thrift3c488d7e_sns-role', !Join ['',[ 'sns', '3c488d7e', !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: thrift3c488d7e_role_external_id + Policies: + - + PolicyName: thrift3c488d7e-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]]] + + + UsernameConfiguration: + CaseSensitive: false + + Schema: + + - + Name: email + Required: true + Mutable: true + + + + + AutoVerifiedAttributes: + + - email + + + + 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 + SmsAuthenticationMessage: !Ref smsAuthenticationMessage + SmsConfiguration: + SnsCallerArn: !GetAtt SNSRole.Arn + ExternalId: thrift3c488d7e_role_external_id + + + UserPoolClientWeb: + # Created provide application access to user pool + # Depends on UserPool for ID reference + Type: "AWS::Cognito::UserPoolClient" + Properties: + ClientName: thrift3c488d7e_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: thrift3c488d7e_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', '3c488d7e', !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: nodejs12.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: thrift3c488d7e_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: thrift3c488d7e_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, 'thrifty23c488d7e_identitypool_3c488d7e', !Join ['',['thrifty23c488d7e_identitypool_3c488d7e', '__', !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 + UserPoolArn: + Value: !GetAtt UserPool.Arn + Description: Arn 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 + Condition: ShouldOutputAppClientSecrets + + + + + + + + diff --git a/amplify/backend/backend-config.json b/amplify/backend/backend-config.json index b97b80b..1c24ae3 100644 --- a/amplify/backend/backend-config.json +++ b/amplify/backend/backend-config.json @@ -1,18 +1,24 @@ { "api": { - "thrifty": { + "thrifty2": { "service": "AppSync", "providerPlugin": "awscloudformation", "output": { "authConfig": { "defaultAuthentication": { - "authenticationType": "API_KEY", - "apiKeyConfig": { - "apiKeyExpirationDays": 30, - "description": "api key description" + "authenticationType": "AMAZON_COGNITO_USER_POOLS", + "userPoolConfig": { + "userPoolId": "auththrifty23c488d7e" } }, "additionalAuthenticationProviders": [ + { + "authenticationType": "API_KEY", + "apiKeyConfig": { + "apiKeyExpirationDays": 30, + "description": "api key description" + } + }, { "authenticationType": "AWS_IAM" } @@ -22,14 +28,13 @@ } }, "auth": { - "thrifty880b2640": { + "thrifty23c488d7e": { "service": "Cognito", "providerPlugin": "awscloudformation", "dependsOn": [], "customAuth": false, "frontendAuthConfig": { - "socialProviders": [], - "usernameAttributes": [ + "loginMechanisms": [ "EMAIL" ], "signupAttributes": [ @@ -50,10 +55,9 @@ } }, "storage": { - "s3729634dc": { + "s370dc9769": { "service": "S3", - "providerPlugin": "awscloudformation", - "dependsOn": [] + "providerPlugin": "awscloudformation" } } } \ No newline at end of file diff --git a/amplify/backend/storage/s370dc9769/parameters.json b/amplify/backend/storage/s370dc9769/parameters.json new file mode 100644 index 0000000..3c516e2 --- /dev/null +++ b/amplify/backend/storage/s370dc9769/parameters.json @@ -0,0 +1,35 @@ +{ + "bucketName": "thrifty247548cdc463d4e43b8b9b7d31a4af078", + "authPolicyName": "s3_amplify_70dc9769", + "unauthPolicyName": "s3_amplify_70dc9769", + "authRoleName": { + "Ref": "AuthRoleName" + }, + "unauthRoleName": { + "Ref": "UnauthRoleName" + }, + "selectedGuestPermissions": [ + "s3:GetObject", + "s3:ListBucket" + ], + "selectedAuthenticatedPermissions": [ + "s3:PutObject", + "s3:GetObject", + "s3:ListBucket", + "s3:DeleteObject" + ], + "s3PermissionsAuthenticatedPublic": "s3:PutObject,s3:GetObject,s3:DeleteObject", + "s3PublicPolicy": "Public_policy_1ea55534", + "s3PermissionsAuthenticatedUploads": "s3:PutObject", + "s3UploadsPolicy": "Uploads_policy_1ea55534", + "s3PermissionsAuthenticatedProtected": "s3:PutObject,s3:GetObject,s3:DeleteObject", + "s3ProtectedPolicy": "Protected_policy_1ea55534", + "s3PermissionsAuthenticatedPrivate": "s3:PutObject,s3:GetObject,s3:DeleteObject", + "s3PrivatePolicy": "Private_policy_1ea55534", + "AuthenticatedAllowList": "ALLOW", + "s3ReadPolicy": "read_policy_1ea55534", + "s3PermissionsGuestPublic": "DISALLOW", + "s3PermissionsGuestUploads": "DISALLOW", + "GuestAllowList": "DISALLOW", + "triggerFunction": "NONE" +} \ No newline at end of file diff --git a/amplify/backend/storage/s370dc9769/s3-cloudformation-template.json b/amplify/backend/storage/s370dc9769/s3-cloudformation-template.json new file mode 100644 index 0000000..112e432 --- /dev/null +++ b/amplify/backend/storage/s370dc9769/s3-cloudformation-template.json @@ -0,0 +1,657 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "S3 resource stack creation using Amplify CLI", + "Parameters": { + "bucketName": { + "Type": "String" + }, + "authPolicyName": { + "Type": "String" + }, + "unauthPolicyName": { + "Type": "String" + }, + "authRoleName": { + "Type": "String" + }, + "unauthRoleName": { + "Type": "String" + }, + "s3PublicPolicy": { + "Type": "String", + "Default" : "NONE" + }, + "s3PrivatePolicy": { + "Type": "String", + "Default" : "NONE" + }, + "s3ProtectedPolicy": { + "Type": "String", + "Default" : "NONE" + }, + "s3UploadsPolicy": { + "Type": "String", + "Default" : "NONE" + }, + "s3ReadPolicy": { + "Type": "String", + "Default" : "NONE" + }, + "s3PermissionsAuthenticatedPublic": { + "Type": "String", + "Default" : "DISALLOW" + }, + "s3PermissionsAuthenticatedProtected": { + "Type": "String", + "Default" : "DISALLOW" + }, + "s3PermissionsAuthenticatedPrivate": { + "Type": "String", + "Default" : "DISALLOW" + }, + "s3PermissionsAuthenticatedUploads": { + "Type": "String", + "Default" : "DISALLOW" + }, + "s3PermissionsGuestPublic": { + "Type": "String", + "Default" : "DISALLOW" + }, + "s3PermissionsGuestUploads": { + "Type": "String", + "Default" : "DISALLOW" }, + "AuthenticatedAllowList": { + "Type": "String", + "Default" : "DISALLOW" + }, + "GuestAllowList": { + "Type": "String", + "Default" : "DISALLOW" + }, + "selectedGuestPermissions": { + "Type": "CommaDelimitedList", + "Default" : "NONE" + }, + "selectedAuthenticatedPermissions": { + "Type": "CommaDelimitedList", + "Default" : "NONE" + }, + "env": { + "Type": "String" + }, + "triggerFunction": { + "Type": "String" + } + + + }, + "Conditions": { + "ShouldNotCreateEnvResources": { + "Fn::Equals": [ + { + "Ref": "env" + }, + "NONE" + ] + }, + "CreateAuthPublic": { + "Fn::Not" : [{ + "Fn::Equals" : [ + {"Ref" : "s3PermissionsAuthenticatedPublic"}, + "DISALLOW" + ] + }] + }, + "CreateAuthProtected": { + "Fn::Not" : [{ + "Fn::Equals" : [ + {"Ref" : "s3PermissionsAuthenticatedProtected"}, + "DISALLOW" + ] + }] + }, + "CreateAuthPrivate": { + "Fn::Not" : [{ + "Fn::Equals" : [ + {"Ref" : "s3PermissionsAuthenticatedPrivate"}, + "DISALLOW" + ] + }] + }, + "CreateAuthUploads": { + "Fn::Not" : [{ + "Fn::Equals" : [ + {"Ref" : "s3PermissionsAuthenticatedUploads"}, + "DISALLOW" + ] + }] + }, + "CreateGuestPublic": { + "Fn::Not" : [{ + "Fn::Equals" : [ + {"Ref" : "s3PermissionsGuestPublic"}, + "DISALLOW" + ] + }] + }, + "CreateGuestUploads": { + "Fn::Not" : [{ + "Fn::Equals" : [ + {"Ref" : "s3PermissionsGuestUploads"}, + "DISALLOW" + ] + }] + }, + "AuthReadAndList": { + "Fn::Not" : [{ + "Fn::Equals" : [ + {"Ref" : "AuthenticatedAllowList"}, + "DISALLOW" + ] + }] + }, + "GuestReadAndList": { + "Fn::Not" : [{ + "Fn::Equals" : [ + {"Ref" : "GuestAllowList"}, + "DISALLOW" + ] + }] + } + }, + "Resources": { + "S3Bucket": { + "Type": "AWS::S3::Bucket", + + "DeletionPolicy" : "Retain", + "Properties": { + "BucketName": { + "Fn::If": [ + "ShouldNotCreateEnvResources", + { + "Ref": "bucketName" + }, + { + "Fn::Join": [ + "", + [ + { + "Ref": "bucketName" + }, + { + "Fn::Select": [ + 3, + { + "Fn::Split": [ + "-", + { + "Ref": "AWS::StackName" + } + ] + } + ] + }, + "-", + { + "Ref": "env" + } + ] + ] + } + ] + }, + + "CorsConfiguration": { + "CorsRules": [ + { + "AllowedHeaders": [ + "*" + ], + "AllowedMethods": [ + "GET", + "HEAD", + "PUT", + "POST", + "DELETE" + ], + "AllowedOrigins": [ + "*" + ], + "ExposedHeaders": [ + "x-amz-server-side-encryption", + "x-amz-request-id", + "x-amz-id-2", + "ETag" + ], + "Id": "S3CORSRuleId1", + "MaxAge": "3000" + } + ] + } + } + }, + + + "S3AuthPublicPolicy": { + "DependsOn": [ + "S3Bucket" + ], + "Condition": "CreateAuthPublic", + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyName": { + "Ref": "s3PublicPolicy" + }, + "Roles": [ + { + "Ref": "authRoleName" + } + ], + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": { + "Fn::Split" : [ "," , { + "Ref": "s3PermissionsAuthenticatedPublic" + } ] + }, + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "S3Bucket" + }, + "/public/*" + ] + ] + } + ] + } + ] + } + } + }, + "S3AuthProtectedPolicy": { + "DependsOn": [ + "S3Bucket" + ], + "Condition": "CreateAuthProtected", + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyName": { + "Ref": "s3ProtectedPolicy" + }, + "Roles": [ + { + "Ref": "authRoleName" + } + ], + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": { + "Fn::Split" : [ "," , { + "Ref": "s3PermissionsAuthenticatedProtected" + } ] + }, + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "S3Bucket" + }, + "/protected/${cognito-identity.amazonaws.com:sub}/*" + ] + ] + } + ] + } + ] + } + } + }, + "S3AuthPrivatePolicy": { + "DependsOn": [ + "S3Bucket" + ], + "Condition": "CreateAuthPrivate", + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyName": { + "Ref": "s3PrivatePolicy" + }, + "Roles": [ + { + "Ref": "authRoleName" + } + ], + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": { + "Fn::Split" : [ "," , { + "Ref": "s3PermissionsAuthenticatedPrivate" + } ] + }, + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "S3Bucket" + }, + "/private/${cognito-identity.amazonaws.com:sub}/*" + ] + ] + } + ] + } + ] + } + } + }, + "S3AuthUploadPolicy": { + "DependsOn": [ + "S3Bucket" + ], + "Condition": "CreateAuthUploads", + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyName": { + "Ref": "s3UploadsPolicy" + }, + "Roles": [ + { + "Ref": "authRoleName" + } + ], + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": { + "Fn::Split" : [ "," , { + "Ref": "s3PermissionsAuthenticatedUploads" + } ] + }, + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "S3Bucket" + }, + "/uploads/*" + ] + ] + } + ] + } + ] + } + } + }, + "S3AuthReadPolicy": { + "DependsOn": [ + "S3Bucket" + ], + "Condition": "AuthReadAndList", + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyName": { + "Ref": "s3ReadPolicy" + }, + "Roles": [ + { + "Ref": "authRoleName" + } + ], + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:GetObject" + ], + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "S3Bucket" + }, + "/protected/*" + ] + ] + } + ] + }, + { + "Effect": "Allow", + "Action": [ + "s3:ListBucket" + ], + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "S3Bucket" + } + ] + ] + } + ], + "Condition": { + "StringLike": { + "s3:prefix": [ + "public/", + "public/*", + "protected/", + "protected/*", + "private/${cognito-identity.amazonaws.com:sub}/", + "private/${cognito-identity.amazonaws.com:sub}/*" + ] + } + } + } + ] + } + } + }, + "S3GuestPublicPolicy": { + "DependsOn": [ + "S3Bucket" + ], + "Condition": "CreateGuestPublic", + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyName": { + "Ref": "s3PublicPolicy" + }, + "Roles": [ + { + "Ref": "unauthRoleName" + } + ], + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": { + "Fn::Split" : [ "," , { + "Ref": "s3PermissionsGuestPublic" + } ] + }, + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "S3Bucket" + }, + "/public/*" + ] + ] + } + ] + } + ] + } + } + }, + "S3GuestUploadPolicy": { + "DependsOn": [ + "S3Bucket" + ], + "Condition": "CreateGuestUploads", + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyName": { + "Ref": "s3UploadsPolicy" + }, + "Roles": [ + { + "Ref": "unauthRoleName" + } + ], + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": { + "Fn::Split" : [ "," , { + "Ref": "s3PermissionsGuestUploads" + } ] + }, + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "S3Bucket" + }, + "/uploads/*" + ] + ] + } + ] + } + ] + } + } + }, + "S3GuestReadPolicy": { + "DependsOn": [ + "S3Bucket" + ], + "Condition": "GuestReadAndList", + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyName": { + "Ref": "s3ReadPolicy" + }, + "Roles": [ + { + "Ref": "unauthRoleName" + } + ], + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:GetObject" + ], + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "S3Bucket" + }, + "/protected/*" + ] + ] + } + ] + }, + { + "Effect": "Allow", + "Action": [ + "s3:ListBucket" + ], + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "S3Bucket" + } + ] + ] + } + ], + "Condition": { + "StringLike": { + "s3:prefix": [ + "public/", + "public/*", + "protected/", + "protected/*" + ] + } + } + } + ] + } + } + } + }, + "Outputs": { + "BucketName": { + "Value": { + "Ref": "S3Bucket" + }, + "Description": "Bucket name for the S3 bucket" + }, + "Region": { + "Value": { + "Ref": "AWS::Region" + } + } + } +} diff --git a/amplify/backend/storage/s370dc9769/storage-params.json b/amplify/backend/storage/s370dc9769/storage-params.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/amplify/backend/storage/s370dc9769/storage-params.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/amplify/backend/storage/s3729634dc/cli-inputs.json b/amplify/backend/storage/s3729634dc/cli-inputs.json deleted file mode 100644 index dca860a..0000000 --- a/amplify/backend/storage/s3729634dc/cli-inputs.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "resourceName": "s3729634dc", - "policyUUID": "729634dc", - "bucketName": "thriftyd7168981e1464cb390e147a4f72cb3f5", - "storageAccess": "authAndGuest", - "guestAccess": [ - "CREATE_AND_UPDATE", - "READ", - "DELETE" - ], - "authAccess": [ - "CREATE_AND_UPDATE", - "READ", - "DELETE" - ], - "triggerFunction": "NONE", - "groupAccess": {} -} \ No newline at end of file diff --git a/amplify/backend/types/amplify-dependent-resources-ref.d.ts b/amplify/backend/types/amplify-dependent-resources-ref.d.ts index e460eb9..ed6ad2d 100644 --- a/amplify/backend/types/amplify-dependent-resources-ref.d.ts +++ b/amplify/backend/types/amplify-dependent-resources-ref.d.ts @@ -1,25 +1,23 @@ export type AmplifyDependentResourcesAttributes = { "api": { - "thrifty": { - "GraphQLAPIKeyOutput": "string", + "thrifty2": { "GraphQLAPIIdOutput": "string", "GraphQLAPIEndpointOutput": "string" } }, "auth": { - "thrifty880b2640": { + "thrifty23c488d7e": { "IdentityPoolId": "string", "IdentityPoolName": "string", "UserPoolId": "string", "UserPoolArn": "string", "UserPoolName": "string", "AppClientIDWeb": "string", - "AppClientID": "string", - "CreatedSNSRole": "string" + "AppClientID": "string" } }, "storage": { - "s3729634dc": { + "s370dc9769": { "BucketName": "string", "Region": "string" } diff --git a/amplify/cli.json b/amplify/cli.json index a2b57f6..1b1a4f5 100644 --- a/amplify/cli.json +++ b/amplify/cli.json @@ -1,51 +1,48 @@ { - "features": { - "graphqltransformer": { - "addmissingownerfields": false, - "improvepluralization": false, - "validatetypenamereservedwords": true, - "useexperimentalpipelinedtransformer": true, - "enableiterativegsiupdates": false, - "secondarykeyasgsi": false, - "skipoverridemutationinputtypes": false, - "transformerversion": 2, - "suppressschemamigrationprompt": true - }, - "frontend-ios": { - "enablexcodeintegration": false - }, - "auth": { - "enablecaseinsensitivity": false, - "useinclusiveterminology": false, - "breakcirculardependency": false, - "forcealiasattributes": false, - "useenabledmfas": false - }, - "codegen": { - "useappsyncmodelgenplugin": false, - "usedocsgeneratorplugin": false, - "usetypesgeneratorplugin": false, - "cleangeneratedmodelsdirectory": false, - "retaincasestyle": false, - "addtimestampfields": false, - "handlelistnullabilitytransparently": false, - "emitauthprovider": false, - "generateindexrules": false, - "enabledartnullsafety": false - }, - "appsync": { - "generategraphqlpermissions": false - }, - "latestregionsupport": { - "pinpoint": 0, - "translate": 0, - "transcribe": 0, - "rekognition": 0, - "textract": 0, - "comprehend": 0 - }, - "project": { - "overrides": true + "features": { + "graphqltransformer": { + "addmissingownerfields": true, + "improvepluralization": false, + "validatetypenamereservedwords": true, + "useexperimentalpipelinedtransformer": false, + "enableiterativegsiupdates": true, + "secondarykeyasgsi": true, + "skipoverridemutationinputtypes": true + }, + "frontend-ios": { + "enablexcodeintegration": true + }, + "auth": { + "enablecaseinsensitivity": true, + "useinclusiveterminology": true, + "breakcirculardependency": true, + "forcealiasattributes": false + }, + "codegen": { + "useappsyncmodelgenplugin": true, + "usedocsgeneratorplugin": true, + "usetypesgeneratorplugin": true, + "cleangeneratedmodelsdirectory": true, + "retaincasestyle": true, + "addtimestampfields": true, + "handlelistnullabilitytransparently": true, + "emitauthprovider": true, + "generateindexrules": true, + "enabledartnullsafety": true + }, + "appsync": { + "generategraphqlpermissions": true + }, + "latestregionsupport": { + "pinpoint": 1, + "translate": 1, + "transcribe": 1, + "rekognition": 1, + "textract": 1, + "comprehend": 1 + }, + "project": { + "overrides": true + } } - } } \ No newline at end of file diff --git a/amplify/team-provider-info.json b/amplify/team-provider-info.json index d233e91..63268b5 100644 --- a/amplify/team-provider-info.json +++ b/amplify/team-provider-info.json @@ -1,20 +1,19 @@ { - "dev": { + "app": { "awscloudformation": { - "AuthRoleName": "amplify-thrifty-dev-121359-authRole", - "UnauthRoleArn": "arn:aws:iam::459760485083:role/amplify-thrifty-dev-121359-unauthRole", - "AuthRoleArn": "arn:aws:iam::459760485083:role/amplify-thrifty-dev-121359-authRole", + "AuthRoleName": "amplify-thrifty2-app-11615-authRole", + "UnauthRoleArn": "arn:aws:iam::459760485083:role/amplify-thrifty2-app-11615-unauthRole", + "AuthRoleArn": "arn:aws:iam::459760485083:role/amplify-thrifty2-app-11615-authRole", "Region": "eu-central-1", - "DeploymentBucketName": "amplify-thrifty-dev-121359-deployment", - "UnauthRoleName": "amplify-thrifty-dev-121359-unauthRole", - "StackName": "amplify-thrifty-dev-121359", - "StackId": "arn:aws:cloudformation:eu-central-1:459760485083:stack/amplify-thrifty-dev-121359/6a2ae600-528f-11ec-802c-0258f60c3dac", - "AmplifyAppId": "d1168v675m5389" + "DeploymentBucketName": "amplify-thrifty2-app-11615-deployment", + "UnauthRoleName": "amplify-thrifty2-app-11615-unauthRole", + "StackName": "amplify-thrifty2-app-11615", + "StackId": "arn:aws:cloudformation:eu-central-1:459760485083:stack/amplify-thrifty2-app-11615/b0f400e0-52fc-11ec-b5ff-0a4e79c28f7a", + "AmplifyAppId": "d5gnyjf8rb4i4" }, "categories": { "auth": { - "thrifty880b2640": {}, - "true": {} + "thrifty23c488d7e": {} } } } diff --git a/app/build.gradle b/app/build.gradle index a5e0539..550a404 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -97,6 +97,13 @@ dependencies { // location implementation 'com.google.android.gms:play-services-location:18.0.0' implementation 'com.google.android.gms:play-services-maps:18.0.0' + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation 'com.android.support.constraint:constraint-layout:2.0.4' + implementation 'com.google.firebase:firebase-database:20.0.3' + implementation 'com.google.firebase:firebase-auth:21.0.1' + implementation 'com.google.android.gms:play-services-maps:18.0.0' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' } apply plugin: 'com.google.gms.google-services' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e829941..40b52ce 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,17 @@ + + + + + + + + + + + + + @@ -66,6 +83,15 @@ + + + \ No newline at end of file diff --git a/app/src/main/java/com/amplifyframework/datastore/generated/model/AmplifyModelProvider.java b/app/src/main/java/com/amplifyframework/datastore/generated/model/AmplifyModelProvider.java index 350f6e7..c5569f5 100644 --- a/app/src/main/java/com/amplifyframework/datastore/generated/model/AmplifyModelProvider.java +++ b/app/src/main/java/com/amplifyframework/datastore/generated/model/AmplifyModelProvider.java @@ -13,7 +13,7 @@ */ public final class AmplifyModelProvider implements ModelProvider { - private static final String AMPLIFY_MODEL_VERSION = "60f05c329e96e718a1c603e8ce306b24"; + private static final String AMPLIFY_MODEL_VERSION = "52523adac5d643063a009102021f267d"; private static AmplifyModelProvider amplifyGeneratedModelInstance; private AmplifyModelProvider() { @@ -34,7 +34,7 @@ public static AmplifyModelProvider getInstance() { @Override public Set> models() { final Set> modifiableSet = new HashSet<>( - Arrays.>asList(Product.class, UserCart.class, User.class, Favourites.class, Category.class) + Arrays.>asList(Favorite.class, User.class, Category.class, Product.class) ); return Immutable.of(modifiableSet); diff --git a/app/src/main/java/com/amplifyframework/datastore/generated/model/Category.java b/app/src/main/java/com/amplifyframework/datastore/generated/model/Category.java index 41adec4..534b2a4 100644 --- a/app/src/main/java/com/amplifyframework/datastore/generated/model/Category.java +++ b/app/src/main/java/com/amplifyframework/datastore/generated/model/Category.java @@ -1,5 +1,6 @@ package com.amplifyframework.datastore.generated.model; +import com.amplifyframework.core.model.temporal.Temporal; import java.util.List; import java.util.UUID; @@ -21,13 +22,15 @@ /** This is an auto generated class representing the Category type in your schema. */ @SuppressWarnings("all") @ModelConfig(pluralName = "Categories", authRules = { - @AuthRule(allow = AuthStrategy.PUBLIC, operations = { ModelOperation.CREATE, ModelOperation.UPDATE, ModelOperation.DELETE, ModelOperation.READ }) + @AuthRule(allow = AuthStrategy.PRIVATE, operations = { ModelOperation.CREATE, ModelOperation.UPDATE, ModelOperation.DELETE, ModelOperation.READ }) }) public final class Category implements Model { - public static final QueryField ID = field("id"); - public static final QueryField NAME = field("name"); + public static final QueryField ID = field("Category", "id"); + public static final QueryField NAME = field("Category", "name"); private final @ModelField(targetType="ID", isRequired = true) String id; private final @ModelField(targetType="String", isRequired = true) String name; + private @ModelField(targetType="AWSDateTime", isReadOnly = true) Temporal.DateTime createdAt; + private @ModelField(targetType="AWSDateTime", isReadOnly = true) Temporal.DateTime updatedAt; public String getId() { return id; } @@ -36,6 +39,14 @@ public String getName() { return name; } + public Temporal.DateTime getCreatedAt() { + return createdAt; + } + + public Temporal.DateTime getUpdatedAt() { + return updatedAt; + } + private Category(String id, String name) { this.id = id; this.name = name; @@ -50,7 +61,9 @@ public boolean equals(Object obj) { } else { Category category = (Category) obj; return ObjectsCompat.equals(getId(), category.getId()) && - ObjectsCompat.equals(getName(), category.getName()); + ObjectsCompat.equals(getName(), category.getName()) && + ObjectsCompat.equals(getCreatedAt(), category.getCreatedAt()) && + ObjectsCompat.equals(getUpdatedAt(), category.getUpdatedAt()); } } @@ -59,6 +72,8 @@ public int hashCode() { return new StringBuilder() .append(getId()) .append(getName()) + .append(getCreatedAt()) + .append(getUpdatedAt()) .toString() .hashCode(); } @@ -68,7 +83,9 @@ public String toString() { return new StringBuilder() .append("Category {") .append("id=" + String.valueOf(getId()) + ", ") - .append("name=" + String.valueOf(getName())) + .append("name=" + String.valueOf(getName()) + ", ") + .append("createdAt=" + String.valueOf(getCreatedAt()) + ", ") + .append("updatedAt=" + String.valueOf(getUpdatedAt())) .append("}") .toString(); } @@ -84,18 +101,8 @@ public static NameStep builder() { * in a relationship. * @param id the id of the existing item this instance will represent * @return an instance of this model with only ID populated - * @throws IllegalArgumentException Checks that ID is in the proper format */ public static Category justId(String id) { - try { - UUID.fromString(id); // Check that ID is in the UUID format - if not an exception is thrown - } catch (Exception exception) { - throw new IllegalArgumentException( - "Model IDs must be unique in the format of UUID. This method is for creating instances " + - "of an existing object with only its ID field for sending as a mutation parameter. When " + - "creating a new object, use the standard builder method and leave the ID field blank." - ); - } return new Category( id, null @@ -113,7 +120,7 @@ public interface NameStep { public interface BuildStep { Category build(); - BuildStep id(String id) throws IllegalArgumentException; + BuildStep id(String id); } @@ -137,22 +144,11 @@ public BuildStep name(String name) { } /** - * WARNING: Do not set ID when creating a new object. Leave this blank and one will be auto generated for you. - * This should only be set when referring to an already existing object. * @param id id * @return Current Builder instance, for fluent method chaining - * @throws IllegalArgumentException Checks that ID is in the proper format */ - public BuildStep id(String id) throws IllegalArgumentException { + public BuildStep id(String id) { this.id = id; - - try { - UUID.fromString(id); // Check that ID is in the UUID format - if not an exception is thrown - } catch (Exception exception) { - throw new IllegalArgumentException("Model IDs must be unique in the format of UUID.", - exception); - } - return this; } } diff --git a/app/src/main/java/com/amplifyframework/datastore/generated/model/Favorite.java b/app/src/main/java/com/amplifyframework/datastore/generated/model/Favorite.java index 2eafb21..58c2d7b 100644 --- a/app/src/main/java/com/amplifyframework/datastore/generated/model/Favorite.java +++ b/app/src/main/java/com/amplifyframework/datastore/generated/model/Favorite.java @@ -1,5 +1,6 @@ package com.amplifyframework.datastore.generated.model; +import com.amplifyframework.core.model.temporal.Temporal; import java.util.List; import java.util.UUID; @@ -21,23 +22,69 @@ /** This is an auto generated class representing the Favorite type in your schema. */ @SuppressWarnings("all") @ModelConfig(pluralName = "Favorites", authRules = { - @AuthRule(allow = AuthStrategy.PUBLIC, operations = { ModelOperation.CREATE, ModelOperation.UPDATE, ModelOperation.DELETE, ModelOperation.READ }) + @AuthRule(allow = AuthStrategy.PRIVATE, operations = { ModelOperation.CREATE, ModelOperation.UPDATE, ModelOperation.DELETE, ModelOperation.READ }) }) +@Index(name = "byUser", fields = {"userID"}) public final class Favorite implements Model { - public static final QueryField ID = field("id"); - public static final QueryField USER_ID = field("userID"); + public static final QueryField ID = field("Favorite", "id"); + public static final QueryField TITLE_FAV = field("Favorite", "titleFav"); + public static final QueryField IMAGE_FAV = field("Favorite", "imageFav"); + public static final QueryField PRICE_FAV = field("Favorite", "priceFav"); + public static final QueryField SIZE_FAV = field("Favorite", "sizeFav"); + public static final QueryField CATEGORY_FAV = field("Favorite", "categoryFav"); + public static final QueryField USER_ID = field("Favorite", "userID"); private final @ModelField(targetType="ID", isRequired = true) String id; + private final @ModelField(targetType="String", isRequired = true) String titleFav; + private final @ModelField(targetType="String", isRequired = true) String imageFav; + private final @ModelField(targetType="String", isRequired = true) String priceFav; + private final @ModelField(targetType="String", isRequired = true) String sizeFav; + private final @ModelField(targetType="String", isRequired = true) String categoryFav; private final @ModelField(targetType="ID") String userID; + private @ModelField(targetType="AWSDateTime", isReadOnly = true) Temporal.DateTime createdAt; + private @ModelField(targetType="AWSDateTime", isReadOnly = true) Temporal.DateTime updatedAt; public String getId() { return id; } + public String getTitleFav() { + return titleFav; + } + + public String getImageFav() { + return imageFav; + } + + public String getPriceFav() { + return priceFav; + } + + public String getSizeFav() { + return sizeFav; + } + + public String getCategoryFav() { + return categoryFav; + } + public String getUserId() { return userID; } - private Favorite(String id, String userID) { + public Temporal.DateTime getCreatedAt() { + return createdAt; + } + + public Temporal.DateTime getUpdatedAt() { + return updatedAt; + } + + private Favorite(String id, String titleFav, String imageFav, String priceFav, String sizeFav, String categoryFav, String userID) { this.id = id; + this.titleFav = titleFav; + this.imageFav = imageFav; + this.priceFav = priceFav; + this.sizeFav = sizeFav; + this.categoryFav = categoryFav; this.userID = userID; } @@ -50,7 +97,14 @@ public boolean equals(Object obj) { } else { Favorite favorite = (Favorite) obj; return ObjectsCompat.equals(getId(), favorite.getId()) && - ObjectsCompat.equals(getUserId(), favorite.getUserId()); + ObjectsCompat.equals(getTitleFav(), favorite.getTitleFav()) && + ObjectsCompat.equals(getImageFav(), favorite.getImageFav()) && + ObjectsCompat.equals(getPriceFav(), favorite.getPriceFav()) && + ObjectsCompat.equals(getSizeFav(), favorite.getSizeFav()) && + ObjectsCompat.equals(getCategoryFav(), favorite.getCategoryFav()) && + ObjectsCompat.equals(getUserId(), favorite.getUserId()) && + ObjectsCompat.equals(getCreatedAt(), favorite.getCreatedAt()) && + ObjectsCompat.equals(getUpdatedAt(), favorite.getUpdatedAt()); } } @@ -58,7 +112,14 @@ public boolean equals(Object obj) { public int hashCode() { return new StringBuilder() .append(getId()) + .append(getTitleFav()) + .append(getImageFav()) + .append(getPriceFav()) + .append(getSizeFav()) + .append(getCategoryFav()) .append(getUserId()) + .append(getCreatedAt()) + .append(getUpdatedAt()) .toString() .hashCode(); } @@ -68,12 +129,19 @@ public String toString() { return new StringBuilder() .append("Favorite {") .append("id=" + String.valueOf(getId()) + ", ") - .append("userID=" + String.valueOf(getUserId())) + .append("titleFav=" + String.valueOf(getTitleFav()) + ", ") + .append("imageFav=" + String.valueOf(getImageFav()) + ", ") + .append("priceFav=" + String.valueOf(getPriceFav()) + ", ") + .append("sizeFav=" + String.valueOf(getSizeFav()) + ", ") + .append("categoryFav=" + String.valueOf(getCategoryFav()) + ", ") + .append("userID=" + String.valueOf(getUserId()) + ", ") + .append("createdAt=" + String.valueOf(getCreatedAt()) + ", ") + .append("updatedAt=" + String.valueOf(getUpdatedAt())) .append("}") .toString(); } - public static BuildStep builder() { + public static TitleFavStep builder() { return new Builder(); } @@ -84,37 +152,67 @@ public static BuildStep builder() { * in a relationship. * @param id the id of the existing item this instance will represent * @return an instance of this model with only ID populated - * @throws IllegalArgumentException Checks that ID is in the proper format */ public static Favorite justId(String id) { - try { - UUID.fromString(id); // Check that ID is in the UUID format - if not an exception is thrown - } catch (Exception exception) { - throw new IllegalArgumentException( - "Model IDs must be unique in the format of UUID. This method is for creating instances " + - "of an existing object with only its ID field for sending as a mutation parameter. When " + - "creating a new object, use the standard builder method and leave the ID field blank." - ); - } return new Favorite( id, + null, + null, + null, + null, + null, null ); } public CopyOfBuilder copyOfBuilder() { return new CopyOfBuilder(id, + titleFav, + imageFav, + priceFav, + sizeFav, + categoryFav, userID); } + public interface TitleFavStep { + ImageFavStep titleFav(String titleFav); + } + + + public interface ImageFavStep { + PriceFavStep imageFav(String imageFav); + } + + + public interface PriceFavStep { + SizeFavStep priceFav(String priceFav); + } + + + public interface SizeFavStep { + CategoryFavStep sizeFav(String sizeFav); + } + + + public interface CategoryFavStep { + BuildStep categoryFav(String categoryFav); + } + + public interface BuildStep { Favorite build(); - BuildStep id(String id) throws IllegalArgumentException; + BuildStep id(String id); BuildStep userId(String userId); } - public static class Builder implements BuildStep { + public static class Builder implements TitleFavStep, ImageFavStep, PriceFavStep, SizeFavStep, CategoryFavStep, BuildStep { private String id; + private String titleFav; + private String imageFav; + private String priceFav; + private String sizeFav; + private String categoryFav; private String userID; @Override public Favorite build() { @@ -122,9 +220,49 @@ public Favorite build() { return new Favorite( id, + titleFav, + imageFav, + priceFav, + sizeFav, + categoryFav, userID); } + @Override + public ImageFavStep titleFav(String titleFav) { + Objects.requireNonNull(titleFav); + this.titleFav = titleFav; + return this; + } + + @Override + public PriceFavStep imageFav(String imageFav) { + Objects.requireNonNull(imageFav); + this.imageFav = imageFav; + return this; + } + + @Override + public SizeFavStep priceFav(String priceFav) { + Objects.requireNonNull(priceFav); + this.priceFav = priceFav; + return this; + } + + @Override + public CategoryFavStep sizeFav(String sizeFav) { + Objects.requireNonNull(sizeFav); + this.sizeFav = sizeFav; + return this; + } + + @Override + public BuildStep categoryFav(String categoryFav) { + Objects.requireNonNull(categoryFav); + this.categoryFav = categoryFav; + return this; + } + @Override public BuildStep userId(String userId) { this.userID = userId; @@ -132,31 +270,50 @@ public BuildStep userId(String userId) { } /** - * WARNING: Do not set ID when creating a new object. Leave this blank and one will be auto generated for you. - * This should only be set when referring to an already existing object. * @param id id * @return Current Builder instance, for fluent method chaining - * @throws IllegalArgumentException Checks that ID is in the proper format */ - public BuildStep id(String id) throws IllegalArgumentException { + public BuildStep id(String id) { this.id = id; - - try { - UUID.fromString(id); // Check that ID is in the UUID format - if not an exception is thrown - } catch (Exception exception) { - throw new IllegalArgumentException("Model IDs must be unique in the format of UUID.", - exception); - } - return this; } } public final class CopyOfBuilder extends Builder { - private CopyOfBuilder(String id, String userId) { + private CopyOfBuilder(String id, String titleFav, String imageFav, String priceFav, String sizeFav, String categoryFav, String userId) { super.id(id); - super.userId(userId); + super.titleFav(titleFav) + .imageFav(imageFav) + .priceFav(priceFav) + .sizeFav(sizeFav) + .categoryFav(categoryFav) + .userId(userId); + } + + @Override + public CopyOfBuilder titleFav(String titleFav) { + return (CopyOfBuilder) super.titleFav(titleFav); + } + + @Override + public CopyOfBuilder imageFav(String imageFav) { + return (CopyOfBuilder) super.imageFav(imageFav); + } + + @Override + public CopyOfBuilder priceFav(String priceFav) { + return (CopyOfBuilder) super.priceFav(priceFav); + } + + @Override + public CopyOfBuilder sizeFav(String sizeFav) { + return (CopyOfBuilder) super.sizeFav(sizeFav); + } + + @Override + public CopyOfBuilder categoryFav(String categoryFav) { + return (CopyOfBuilder) super.categoryFav(categoryFav); } @Override diff --git a/app/src/main/java/com/amplifyframework/datastore/generated/model/Product.java b/app/src/main/java/com/amplifyframework/datastore/generated/model/Product.java index 3eb4d4e..0cc6a03 100644 --- a/app/src/main/java/com/amplifyframework/datastore/generated/model/Product.java +++ b/app/src/main/java/com/amplifyframework/datastore/generated/model/Product.java @@ -1,5 +1,6 @@ package com.amplifyframework.datastore.generated.model; +import com.amplifyframework.core.model.temporal.Temporal; import java.util.List; import java.util.UUID; @@ -21,25 +22,28 @@ /** This is an auto generated class representing the Product type in your schema. */ @SuppressWarnings("all") @ModelConfig(pluralName = "Products", authRules = { - @AuthRule(allow = AuthStrategy.PUBLIC, operations = { ModelOperation.CREATE, ModelOperation.UPDATE, ModelOperation.DELETE, ModelOperation.READ }) + @AuthRule(allow = AuthStrategy.PRIVATE, operations = { ModelOperation.CREATE, ModelOperation.UPDATE, ModelOperation.DELETE, ModelOperation.READ }) }) +@Index(name = "byCategory", fields = {"categoryID"}) public final class Product implements Model { - public static final QueryField ID = field("id"); - public static final QueryField TITLE = field("title"); - public static final QueryField DESCRIPTION = field("description"); - public static final QueryField PRICE = field("price"); - public static final QueryField SIZE = field("size"); - public static final QueryField COLOR = field("color"); - public static final QueryField IMAGE = field("image"); - public static final QueryField CATEGORY_ID = field("categoryID"); + public static final QueryField ID = field("Product", "id"); + public static final QueryField TITLE = field("Product", "title"); + public static final QueryField DESCRIPTION = field("Product", "description"); + public static final QueryField PRICE = field("Product", "price"); + public static final QueryField SIZE = field("Product", "size"); + public static final QueryField COLOR = field("Product", "color"); + public static final QueryField CATEGORY_ID = field("Product", "categoryID"); + public static final QueryField IMAGE = field("Product", "image"); private final @ModelField(targetType="ID", isRequired = true) String id; private final @ModelField(targetType="String", isRequired = true) String title; private final @ModelField(targetType="String", isRequired = true) String description; private final @ModelField(targetType="String", isRequired = true) String price; private final @ModelField(targetType="String", isRequired = true) String size; private final @ModelField(targetType="String", isRequired = true) String color; - private final @ModelField(targetType="String", isRequired = true) String image; private final @ModelField(targetType="ID") String categoryID; + private final @ModelField(targetType="String", isRequired = true) String image; + private @ModelField(targetType="AWSDateTime", isReadOnly = true) Temporal.DateTime createdAt; + private @ModelField(targetType="AWSDateTime", isReadOnly = true) Temporal.DateTime updatedAt; public String getId() { return id; } @@ -64,23 +68,31 @@ public String getColor() { return color; } + public String getCategoryId() { + return categoryID; + } + public String getImage() { return image; } - public String getCategoryId() { - return categoryID; + public Temporal.DateTime getCreatedAt() { + return createdAt; } - private Product(String id, String title, String description, String price, String size, String color, String image, String categoryID) { + public Temporal.DateTime getUpdatedAt() { + return updatedAt; + } + + private Product(String id, String title, String description, String price, String size, String color, String categoryID, String image) { this.id = id; this.title = title; this.description = description; this.price = price; this.size = size; this.color = color; - this.image = image; this.categoryID = categoryID; + this.image = image; } @Override @@ -97,8 +109,10 @@ public boolean equals(Object obj) { ObjectsCompat.equals(getPrice(), product.getPrice()) && ObjectsCompat.equals(getSize(), product.getSize()) && ObjectsCompat.equals(getColor(), product.getColor()) && + ObjectsCompat.equals(getCategoryId(), product.getCategoryId()) && ObjectsCompat.equals(getImage(), product.getImage()) && - ObjectsCompat.equals(getCategoryId(), product.getCategoryId()); + ObjectsCompat.equals(getCreatedAt(), product.getCreatedAt()) && + ObjectsCompat.equals(getUpdatedAt(), product.getUpdatedAt()); } } @@ -111,8 +125,10 @@ public int hashCode() { .append(getPrice()) .append(getSize()) .append(getColor()) - .append(getImage()) .append(getCategoryId()) + .append(getImage()) + .append(getCreatedAt()) + .append(getUpdatedAt()) .toString() .hashCode(); } @@ -127,8 +143,10 @@ public String toString() { .append("price=" + String.valueOf(getPrice()) + ", ") .append("size=" + String.valueOf(getSize()) + ", ") .append("color=" + String.valueOf(getColor()) + ", ") + .append("categoryID=" + String.valueOf(getCategoryId()) + ", ") .append("image=" + String.valueOf(getImage()) + ", ") - .append("categoryID=" + String.valueOf(getCategoryId())) + .append("createdAt=" + String.valueOf(getCreatedAt()) + ", ") + .append("updatedAt=" + String.valueOf(getUpdatedAt())) .append("}") .toString(); } @@ -144,18 +162,8 @@ public static TitleStep builder() { * in a relationship. * @param id the id of the existing item this instance will represent * @return an instance of this model with only ID populated - * @throws IllegalArgumentException Checks that ID is in the proper format */ public static Product justId(String id) { - try { - UUID.fromString(id); // Check that ID is in the UUID format - if not an exception is thrown - } catch (Exception exception) { - throw new IllegalArgumentException( - "Model IDs must be unique in the format of UUID. This method is for creating instances " + - "of an existing object with only its ID field for sending as a mutation parameter. When " + - "creating a new object, use the standard builder method and leave the ID field blank." - ); - } return new Product( id, null, @@ -175,8 +183,8 @@ public CopyOfBuilder copyOfBuilder() { price, size, color, - image, - categoryID); + categoryID, + image); } public interface TitleStep { DescriptionStep title(String title); @@ -210,7 +218,7 @@ public interface ImageStep { public interface BuildStep { Product build(); - BuildStep id(String id) throws IllegalArgumentException; + BuildStep id(String id); BuildStep categoryId(String categoryId); } @@ -235,8 +243,8 @@ public Product build() { price, size, color, - image, - categoryID); + categoryID, + image); } @Override @@ -288,29 +296,18 @@ public BuildStep categoryId(String categoryId) { } /** - * WARNING: Do not set ID when creating a new object. Leave this blank and one will be auto generated for you. - * This should only be set when referring to an already existing object. * @param id id * @return Current Builder instance, for fluent method chaining - * @throws IllegalArgumentException Checks that ID is in the proper format */ - public BuildStep id(String id) throws IllegalArgumentException { + public BuildStep id(String id) { this.id = id; - - try { - UUID.fromString(id); // Check that ID is in the UUID format - if not an exception is thrown - } catch (Exception exception) { - throw new IllegalArgumentException("Model IDs must be unique in the format of UUID.", - exception); - } - return this; } } public final class CopyOfBuilder extends Builder { - private CopyOfBuilder(String id, String title, String description, String price, String size, String color, String image, String categoryId) { + private CopyOfBuilder(String id, String title, String description, String price, String size, String color, String categoryId, String image) { super.id(id); super.title(title) .description(description) diff --git a/app/src/main/java/com/amplifyframework/datastore/generated/model/User.java b/app/src/main/java/com/amplifyframework/datastore/generated/model/User.java index 521cbfe..1b7bb0b 100644 --- a/app/src/main/java/com/amplifyframework/datastore/generated/model/User.java +++ b/app/src/main/java/com/amplifyframework/datastore/generated/model/User.java @@ -1,5 +1,6 @@ package com.amplifyframework.datastore.generated.model; +import com.amplifyframework.core.model.temporal.Temporal; import java.util.List; import java.util.UUID; @@ -21,13 +22,15 @@ /** This is an auto generated class representing the User type in your schema. */ @SuppressWarnings("all") @ModelConfig(pluralName = "Users", authRules = { - @AuthRule(allow = AuthStrategy.PUBLIC, operations = { ModelOperation.CREATE, ModelOperation.UPDATE, ModelOperation.DELETE, ModelOperation.READ }) + @AuthRule(allow = AuthStrategy.PRIVATE, operations = { ModelOperation.CREATE, ModelOperation.UPDATE, ModelOperation.DELETE, ModelOperation.READ }) }) public final class User implements Model { - public static final QueryField ID = field("id"); - public static final QueryField EMAIL = field("email"); + public static final QueryField ID = field("User", "id"); + public static final QueryField EMAIL = field("User", "email"); private final @ModelField(targetType="ID", isRequired = true) String id; private final @ModelField(targetType="String", isRequired = true) String email; + private @ModelField(targetType="AWSDateTime", isReadOnly = true) Temporal.DateTime createdAt; + private @ModelField(targetType="AWSDateTime", isReadOnly = true) Temporal.DateTime updatedAt; public String getId() { return id; } @@ -36,6 +39,14 @@ public String getEmail() { return email; } + public Temporal.DateTime getCreatedAt() { + return createdAt; + } + + public Temporal.DateTime getUpdatedAt() { + return updatedAt; + } + private User(String id, String email) { this.id = id; this.email = email; @@ -50,7 +61,9 @@ public boolean equals(Object obj) { } else { User user = (User) obj; return ObjectsCompat.equals(getId(), user.getId()) && - ObjectsCompat.equals(getEmail(), user.getEmail()); + ObjectsCompat.equals(getEmail(), user.getEmail()) && + ObjectsCompat.equals(getCreatedAt(), user.getCreatedAt()) && + ObjectsCompat.equals(getUpdatedAt(), user.getUpdatedAt()); } } @@ -59,6 +72,8 @@ public int hashCode() { return new StringBuilder() .append(getId()) .append(getEmail()) + .append(getCreatedAt()) + .append(getUpdatedAt()) .toString() .hashCode(); } @@ -68,7 +83,9 @@ public String toString() { return new StringBuilder() .append("User {") .append("id=" + String.valueOf(getId()) + ", ") - .append("email=" + String.valueOf(getEmail())) + .append("email=" + String.valueOf(getEmail()) + ", ") + .append("createdAt=" + String.valueOf(getCreatedAt()) + ", ") + .append("updatedAt=" + String.valueOf(getUpdatedAt())) .append("}") .toString(); } @@ -84,18 +101,8 @@ public static EmailStep builder() { * in a relationship. * @param id the id of the existing item this instance will represent * @return an instance of this model with only ID populated - * @throws IllegalArgumentException Checks that ID is in the proper format */ public static User justId(String id) { - try { - UUID.fromString(id); // Check that ID is in the UUID format - if not an exception is thrown - } catch (Exception exception) { - throw new IllegalArgumentException( - "Model IDs must be unique in the format of UUID. This method is for creating instances " + - "of an existing object with only its ID field for sending as a mutation parameter. When " + - "creating a new object, use the standard builder method and leave the ID field blank." - ); - } return new User( id, null @@ -113,7 +120,7 @@ public interface EmailStep { public interface BuildStep { User build(); - BuildStep id(String id) throws IllegalArgumentException; + BuildStep id(String id); } @@ -137,22 +144,11 @@ public BuildStep email(String email) { } /** - * WARNING: Do not set ID when creating a new object. Leave this blank and one will be auto generated for you. - * This should only be set when referring to an already existing object. * @param id id * @return Current Builder instance, for fluent method chaining - * @throws IllegalArgumentException Checks that ID is in the proper format */ - public BuildStep id(String id) throws IllegalArgumentException { + public BuildStep id(String id) { this.id = id; - - try { - UUID.fromString(id); // Check that ID is in the UUID format - if not an exception is thrown - } catch (Exception exception) { - throw new IllegalArgumentException("Model IDs must be unique in the format of UUID.", - exception); - } - return this; } } diff --git a/app/src/main/java/com/example/thrifty/GPSTracker.java b/app/src/main/java/com/example/thrifty/GPSTracker.java new file mode 100644 index 0000000..b00cfdb --- /dev/null +++ b/app/src/main/java/com/example/thrifty/GPSTracker.java @@ -0,0 +1,188 @@ +package com.example.thrifty; + +import android.annotation.SuppressLint; +import android.app.AlertDialog; +import android.app.Service; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.os.Bundle; +import android.os.IBinder; +import android.provider.Settings; + +/** + * Created by tulsi on 4/7/2018. + */ +public class GPSTracker extends Service implements LocationListener { + + private final Context mContext; + + // flag for GPS status + boolean isGPSEnabled = false; + // flag for GPS status + boolean canGetLocation = false; + Location location; // location + double latitude; // latitude + double longitude; // longitude + + // The minimum distance to change Updates in meters + private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters + + // The minimum time between updates in milliseconds + private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute + + // Declaring a Location Manager + protected LocationManager locationManager; + + public GPSTracker(Context context) { + this.mContext = context; + getLocation(); + } + + @SuppressLint("MissingPermission") + public Location getLocation() { + try { + locationManager = (LocationManager) mContext + .getSystemService(LOCATION_SERVICE); + // getting GPS status + isGPSEnabled = locationManager + .isProviderEnabled(LocationManager.GPS_PROVIDER); + + // if GPS Enabled get lat/long using GPS Services + if (isGPSEnabled) { + this.canGetLocation = true; + if (location == null) { + locationManager.requestLocationUpdates( + LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, + MIN_DISTANCE_CHANGE_FOR_UPDATES, this); + if (locationManager != null) { + location = locationManager + .getLastKnownLocation(LocationManager.GPS_PROVIDER); + if (location != null) { + latitude = location.getLatitude(); + longitude = location.getLongitude(); + } + } + } + } + + } catch (Exception e) { + e.printStackTrace(); + } + + return location; + } + + /** + * Stop using GPS listener Calling this function will stop using GPS in your + * app + * */ + public void stopUsingGPS() { + if (locationManager != null) { + locationManager.removeUpdates(GPSTracker.this); + } + } + + /** + * Function to get latitude + * */ + public double getLatitude() { + if (location != null) { + latitude = location.getLatitude(); + } + + // return latitude + return latitude; + } + + /** + * Function to get longitude + * */ + public double getLongitude() { + if (location != null) { + longitude = location.getLongitude(); + } + + // return longitude + return longitude; + } + + /** + * Function to check GPS/wifi enabled + * + * @return boolean + * */ + public boolean canGetLocation() { + return this.canGetLocation; + } + + /** + * Function to show settings alert dialog On pressing Settings button will + * lauch Settings Options + * */ + public void showSettingsAlert() { + AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext); + + // Setting Dialog Title + alertDialog.setTitle("GPS is settings"); + + // Setting Dialog Message + alertDialog + .setMessage("GPS is not enabled. Do you want to go to settings menu?"); + + // On pressing Settings button + alertDialog.setPositiveButton("Settings", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + Intent intent = new Intent( + Settings.ACTION_LOCATION_SOURCE_SETTINGS); + mContext.startActivity(intent); + } + }); + + // on pressing cancel button + alertDialog.setNegativeButton("Cancel", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + dialog.cancel(); + } + }); + + // Showing Alert Message + alertDialog.show(); + } + + @Override + public void onLocationChanged(Location arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void onProviderDisabled(String arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void onProviderEnabled(String arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void onStatusChanged(String arg0, int arg1, Bundle arg2) { + // TODO Auto-generated method stub + + } + + @Override + public IBinder onBind(Intent arg0) { + // TODO Auto-generated method stub + return null; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/thrifty/MainActivity.java b/app/src/main/java/com/example/thrifty/MainActivity.java index 03cfcde..47e5cde 100644 --- a/app/src/main/java/com/example/thrifty/MainActivity.java +++ b/app/src/main/java/com/example/thrifty/MainActivity.java @@ -93,6 +93,13 @@ public void onClick(View view) { startActivity(intent); } }); +// findViewById(R.id.map).setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View view) { +// Intent intent = new Intent(MainActivity.this, Tracking.class); +// startActivity(intent); +// } +// }); } diff --git a/app/src/main/java/com/example/thrifty/MapsActivity.java b/app/src/main/java/com/example/thrifty/MapsActivity.java new file mode 100644 index 0000000..55ba192 --- /dev/null +++ b/app/src/main/java/com/example/thrifty/MapsActivity.java @@ -0,0 +1,62 @@ +package com.example.thrifty; + +import android.os.Bundle; + +import androidx.fragment.app.FragmentActivity; + +import com.google.android.gms.maps.CameraUpdate; +import com.google.android.gms.maps.CameraUpdateFactory; +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.OnMapReadyCallback; +import com.google.android.gms.maps.SupportMapFragment; +import com.google.android.gms.maps.model.BitmapDescriptorFactory; +import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.MarkerOptions; + +public class MapsActivity extends FragmentActivity implements OnMapReadyCallback { + + private GoogleMap mMap; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_maps); + // Obtain the SupportMapFragment and get notified when the map is ready to be used. + SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() + .findFragmentById(R.id.map); + mapFragment.getMapAsync(this); + } + + + /** + * Manipulates the map once available. + * This callback is triggered when the map is ready to be used. + * This is where we can add markers or lines, add listeners or move the camera. In this case, + * we just add a marker near Sydney, Australia. + * If Google Play services is not installed on the device, the user will be prompted to install + * it inside the SupportMapFragment. This method will only be triggered once the user has + * installed Google Play services and returned to the app. + */ + @Override + public void onMapReady(GoogleMap googleMap) { + mMap = googleMap; + + // Add a marker in Sydney and move the camera + LatLng sydney = new LatLng(37.391219,-121.930); + MarkerOptions marker = new MarkerOptions().position(sydney).title("Anuradha Rajashekar"); + marker.icon(BitmapDescriptorFactory.fromResource(R.drawable.userplaceholder)); + mMap.addMarker(marker); + // mMap.addMarker(new MarkerOptions().position(sydney).title("Anuradha's location")); + mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney)); + mMap.animateCamera(CameraUpdateFactory.zoomTo(17.0f)); + + /* LatLng location2 = new LatLng(37.402276,-121.942161); + mMap.addMarker(new MarkerOptions().position(location2).title("Anuradha's new location")); + mMap.moveCamera(CameraUpdateFactory.newLatLng(location2));*/ + + //zoom into a particular position + CameraUpdate zoom = CameraUpdateFactory.zoomTo(12); + mMap.moveCamera(zoom); + mMap.animateCamera(zoom); + } +} diff --git a/app/src/main/java/com/example/thrifty/ProductView.java b/app/src/main/java/com/example/thrifty/ProductView.java index 178663e..63f7057 100644 --- a/app/src/main/java/com/example/thrifty/ProductView.java +++ b/app/src/main/java/com/example/thrifty/ProductView.java @@ -1,11 +1,19 @@ package com.example.thrifty; import androidx.appcompat.app.AppCompatActivity; +import androidx.core.content.FileProvider; import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.net.Uri; import android.os.Bundle; import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.ImageView; import android.widget.TextView; +import android.widget.Toast; import android.widget.Toolbar; import com.amplifyframework.AmplifyException; @@ -15,6 +23,9 @@ import com.amplifyframework.datastore.AWSDataStorePlugin; import com.amplifyframework.storage.s3.AWSS3StoragePlugin; +import java.io.File; +import java.io.FileOutputStream; + public class ProductView extends AppCompatActivity { @Override @@ -51,7 +62,59 @@ protected void onCreate(Bundle savedInstanceState) { textView.setText(title); priceTxt.setText(price); categoryTxt.setText(category); + Button share = findViewById(R.id.share); + ImageView imageView = findViewById(R.id.itemImage); + + // initialising text field where we will enter data + share.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + // Now share image function will be called + // here we will be passing the text to share + // Getting drawable value from image + BitmapDrawable bitmapDrawable = (BitmapDrawable) imageView.getDrawable(); + Bitmap bitmap = bitmapDrawable.getBitmap(); + shareImageandText(bitmap); + } + }); + + + } + private void shareImageandText(Bitmap bitmap) { + Uri uri = getmageToShare(bitmap); + Intent intent = new Intent(Intent.ACTION_SEND); + + // putting uri of image to be shared + intent.putExtra(Intent.EXTRA_STREAM, uri); + // adding text to share + intent.putExtra(Intent.EXTRA_TEXT, "Sharing Image"); + // Add subject Here + intent.putExtra(Intent.EXTRA_SUBJECT, "Subject Here"); + + // setting type to image + intent.setType("image/png"); + + // calling startactivity() to share + startActivity(Intent.createChooser(intent, "Share Via")); + } + + // Retrieving the url to share + private Uri getmageToShare(Bitmap bitmap) { + File imagefolder = new File(getCacheDir(), "images"); + Uri uri = null; + try { + imagefolder.mkdirs(); + File file = new File(imagefolder, "shared_image.png"); + FileOutputStream outputStream = new FileOutputStream(file); + bitmap.compress(Bitmap.CompressFormat.PNG, 90, outputStream); + outputStream.flush(); + outputStream.close(); + uri = FileProvider.getUriForFile(this, "com.anni.shareimage.fileprovider", file); + } catch (Exception e) { + Toast.makeText(this, "" + e.getMessage(), Toast.LENGTH_LONG).show(); + } + return uri; } } \ No newline at end of file diff --git a/app/src/main/java/com/example/thrifty/Tracking.java b/app/src/main/java/com/example/thrifty/Tracking.java new file mode 100644 index 0000000..ac5fea2 --- /dev/null +++ b/app/src/main/java/com/example/thrifty/Tracking.java @@ -0,0 +1,68 @@ +package com.example.thrifty; + +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.database.FirebaseDatabase; + +public class Tracking extends AppCompatActivity { + + private Button btnShowLocation,btnshowMap; + FirebaseDatabase database; + DatabaseReference myRef; + + private static final int REQUEST_CODE_PERMISSION =2; + String mPermission = android.Manifest.permission.ACCESS_FINE_LOCATION; + GPSTracker gps; + TextView location; + String value =null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_tracking); + + try{ + if (ActivityCompat.checkSelfPermission(this,mPermission)!= PackageManager.PERMISSION_GRANTED){ + ActivityCompat.requestPermissions(this,new String[]{mPermission},REQUEST_CODE_PERMISSION); + } + }catch (Exception e){ + e.printStackTrace(); + } + btnShowLocation=(Button)findViewById(R.id.button); + btnshowMap=(Button)findViewById(R.id.button2); + btnShowLocation.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + gps = new GPSTracker(Tracking.this); + location=(TextView)findViewById(R.id.Location); + if (gps.canGetLocation()){ + double latitude = gps.getLatitude(); + double longitude = gps.getLongitude(); + database = FirebaseDatabase.getInstance(); + location.setText(latitude+""+longitude); + myRef = database.getReference("Location"); + myRef.setValue(latitude+","+longitude); + }else{ + gps.showSettingsAlert(); + } + } + + }); + } + + public void Map(View view){ + + + Intent intent=new Intent(getApplicationContext(),MapsActivity.class); + startActivity(intent); + } +} diff --git a/app/src/main/res/drawable-v24/userplaceholder.png b/app/src/main/res/drawable-v24/userplaceholder.png new file mode 100644 index 0000000..62ad490 Binary files /dev/null and b/app/src/main/res/drawable-v24/userplaceholder.png differ diff --git a/app/src/main/res/drawable/image1.png b/app/src/main/res/drawable/image1.png new file mode 100644 index 0000000..4a0fa16 Binary files /dev/null and b/app/src/main/res/drawable/image1.png differ diff --git a/app/src/main/res/drawable/userplaceholder.png b/app/src/main/res/drawable/userplaceholder.png new file mode 100644 index 0000000..62ad490 Binary files /dev/null and b/app/src/main/res/drawable/userplaceholder.png differ diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 2ae910d..e18e687 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -90,6 +90,9 @@ android:layout_marginStart="10dp" android:layout_marginTop="10dp" android:layout_marginEnd="10dp" /> + + + @@ -136,4 +139,14 @@ app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.975" /> + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_maps.xml b/app/src/main/res/layout/activity_maps.xml new file mode 100644 index 0000000..39c3086 --- /dev/null +++ b/app/src/main/res/layout/activity_maps.xml @@ -0,0 +1,7 @@ + diff --git a/app/src/main/res/layout/activity_product_view.xml b/app/src/main/res/layout/activity_product_view.xml index 7a42762..d90128f 100644 --- a/app/src/main/res/layout/activity_product_view.xml +++ b/app/src/main/res/layout/activity_product_view.xml @@ -42,10 +42,10 @@ android:layout_below="@+id/addToCart" android:layout_marginStart="20dp" android:layout_marginEnd="20dp" + android:layout_marginBottom="10dp" android:elevation="5dp" android:padding="10dp" - android:text="Add To Wishlist" - android:layout_marginBottom="10dp"/> + android:text="Add To Wishlist" /> + android:layout_marginTop="10dp" + android:src="@drawable/image1"/> + +