Skip to content

Commit

Permalink
feat(auth): add updateUserAttributes (batch) (#601)
Browse files Browse the repository at this point in the history
* feat: add auth.updateUserAttributes

* Apply suggestions from code review

Co-authored-by: Chris F <[email protected]>

* address pr comments

* refactor android user attributes

* consolidate user attr logic on iOS

* refactor deliveryDetails serialization

* add missing newline

* revert missing attribute changes

* update serializeAuthUpdateAttributeResult for nil

* move comment to to of file

* bump amplify-android to 1.17.7

Co-authored-by: Chris F <[email protected]>
  • Loading branch information
Jordan-Nelson and cshfang authored Jun 8, 2021
1 parent 4209c80 commit 8b0893c
Show file tree
Hide file tree
Showing 39 changed files with 1,105 additions and 134 deletions.
4 changes: 2 additions & 2 deletions packages/amplify_analytics_pinpoint/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ dependencies {
api amplifyCore

implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.amplifyframework:aws-analytics-pinpoint:1.17.4'
implementation 'com.amplifyframework:aws-auth-cognito:1.17.4'
implementation 'com.amplifyframework:aws-analytics-pinpoint:1.17.7'
implementation 'com.amplifyframework:aws-auth-cognito:1.17.7'
testImplementation 'junit:junit:4.13'
testImplementation 'org.mockito:mockito-core:3.1.0'
testImplementation 'org.mockito:mockito-inline:3.1.0'
Expand Down
4 changes: 2 additions & 2 deletions packages/amplify_api/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ dependencies {
api amplifyCore

implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "com.amplifyframework:aws-api:1.17.4"
implementation "com.amplifyframework:aws-api-appsync:1.17.4"
implementation "com.amplifyframework:aws-api:1.17.7"
implementation "com.amplifyframework:aws-api-appsync:1.17.7"

testImplementation 'junit:junit:4.13'
testImplementation 'org.mockito:mockito-core:3.1.0'
Expand Down
2 changes: 1 addition & 1 deletion packages/amplify_auth_cognito/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ android {
dependencies {
api amplifyCore
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.amplifyframework:aws-auth-cognito:1.17.4'
implementation 'com.amplifyframework:aws-auth-cognito:1.17.7'
testImplementation 'junit:junit:4.13'
testImplementation 'org.mockito:mockito-core:3.1.0'
testImplementation 'org.mockito:mockito-inline:3.1.0'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ import com.amazonaws.amplify.amplify_auth_cognito.types.FlutterSignInWithWebUIRe
import com.amazonaws.amplify.amplify_auth_cognito.types.FlutterFetchUserAttributesResult
import com.amazonaws.amplify.amplify_auth_cognito.types.FlutterUpdateUserAttributeRequest
import com.amazonaws.amplify.amplify_auth_cognito.types.FlutterUpdateUserAttributeResult
import com.amazonaws.amplify.amplify_auth_cognito.types.FlutterUpdateUserAttributesRequest
import com.amazonaws.amplify.amplify_auth_cognito.types.FlutterUpdateUserAttributesResult
import com.amazonaws.amplify.amplify_auth_cognito.types.FlutterConfirmUserAttributeRequest
import com.amazonaws.amplify.amplify_auth_cognito.types.FlutterResendUserAttributeConfirmationCodeRequest
import com.amazonaws.amplify.amplify_auth_cognito.types.FlutterResendUserAttributeConfirmationCodeResult
Expand All @@ -58,6 +60,7 @@ import com.amplifyframework.auth.result.AuthSignInResult
import com.amplifyframework.auth.result.AuthSignUpResult
import com.amplifyframework.auth.result.AuthUpdateAttributeResult
import com.amplifyframework.auth.AuthUserAttribute
import com.amplifyframework.auth.AuthUserAttributeKey
import com.amplifyframework.auth.AuthCodeDeliveryDetails
import com.amplifyframework.core.Amplify
import io.flutter.embedding.engine.plugins.FlutterPlugin
Expand Down Expand Up @@ -173,6 +176,7 @@ public class AuthCognito : FlutterPlugin, ActivityAware, MethodCallHandler, Plug
"fetchUserAttributes" -> onFetchUserAttributes(result)
"signInWithWebUI" -> onSignInWithWebUI(result, data)
"updateUserAttribute" -> onUpdateUserAttribute(result, data)
"updateUserAttributes" -> onUpdateUserAttributes(result, data)
"confirmUserAttribute" -> onConfirmUserAttribute(result, data)
"resendUserAttributeConfirmationCode" -> onResendUserAttributeConfirmationCode(result, data)
else -> result.notImplemented()
Expand Down Expand Up @@ -449,6 +453,20 @@ public class AuthCognito : FlutterPlugin, ActivityAware, MethodCallHandler, Plug
}
}

private fun onUpdateUserAttributes (@NonNull flutterResult: Result, @NonNull request: HashMap<String, *>) {
try {
FlutterUpdateUserAttributesRequest.validate(request)
var req = FlutterUpdateUserAttributesRequest(request)
Amplify.Auth.updateUserAttributes(
req.attributes,
{ result -> prepareUpdateUserAttributesResult(flutterResult, result) },
{ error -> errorHandler.handleAuthError(flutterResult, error) }
);
} catch (e: Exception) {
errorHandler.prepareGenericException(flutterResult, e)
}
}

private fun onConfirmUserAttribute (@NonNull flutterResult: Result, @NonNull request: HashMap<String, *>) {
try {
FlutterConfirmUserAttributeRequest.validate(request)
Expand Down Expand Up @@ -554,6 +572,13 @@ public class AuthCognito : FlutterPlugin, ActivityAware, MethodCallHandler, Plug
}
}

fun prepareUpdateUserAttributesResult(@NonNull flutterResult: Result, @NonNull result: Map<AuthUserAttributeKey, AuthUpdateAttributeResult>) {
var updateUserAttributesResult = FlutterUpdateUserAttributesResult(result);
Handler (Looper.getMainLooper()).post {
flutterResult.success(updateUserAttributesResult.toValueMap());
}
}

fun prepareConfirmUserAttributeResult(@NonNull flutterResult: Result) {
var parsedResult = mutableMapOf<String, Any>();
Handler (Looper.getMainLooper()).post {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

package com.amazonaws.amplify.amplify_auth_cognito.types

import com.amazonaws.amplify.amplify_auth_cognito.utils.createAuthUserAttributeKey
import com.amplifyframework.auth.AuthUserAttributeKey
import com.amazonaws.amplify.amplify_core.exception.ExceptionMessages
import com.amazonaws.amplify.amplify_core.exception.InvalidRequestException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

package com.amazonaws.amplify.amplify_auth_cognito.types

import com.amazonaws.amplify.amplify_auth_cognito.utils.createAuthUserAttributeKey
import com.amplifyframework.auth.AuthUserAttributeKey
import com.amazonaws.amplify.amplify_core.exception.ExceptionMessages
import com.amazonaws.amplify.amplify_core.exception.InvalidRequestException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package com.amazonaws.amplify.amplify_auth_cognito.types

import androidx.annotation.NonNull
import com.amazonaws.amplify.amplify_auth_cognito.utils.createAuthUserAttribute
import com.amazonaws.amplify.amplify_core.exception.ExceptionMessages
import com.amazonaws.amplify.amplify_core.exception.InvalidRequestException
import com.amplifyframework.AmplifyException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package com.amazonaws.amplify.amplify_auth_cognito.types

import androidx.annotation.NonNull
import com.amazonaws.amplify.amplify_auth_cognito.utils.createAuthUserAttribute
import com.amazonaws.amplify.amplify_auth_cognito.utils.validateUserAttribute
import com.amazonaws.amplify.amplify_core.exception.ExceptionMessages
import com.amazonaws.amplify.amplify_core.exception.InvalidRequestException
import com.amplifyframework.auth.AuthUserAttribute
Expand All @@ -33,21 +35,14 @@ data class FlutterUpdateUserAttributeRequest(val map: HashMap<String, *>) {

companion object {
private const val validationErrorMessage: String = "UpdateUserAttributeRequest Request malformed."
fun validate(req : HashMap<String, *>?) {
fun validate(req: HashMap<String, *>?) {
if (req == null) {
throw InvalidRequestException(validationErrorMessage, ExceptionMessages.missingAttribute.format("request map"))
} else if (!req.containsKey("attribute") || req["attribute"] !is HashMap<*, *>) {
throw InvalidRequestException(validationErrorMessage, ExceptionMessages.missingAttribute.format( "attribute" ))
throw InvalidRequestException(validationErrorMessage, ExceptionMessages.missingAttribute.format("attribute"))
} else {
val attribute = req["attribute"] as HashMap<*, *>;
if (!attribute.containsKey("value")) {
throw InvalidRequestException(validationErrorMessage, ExceptionMessages.missingAttribute.format( "value" ))
} else if (!attribute.containsKey("userAttributeKey")) {
throw InvalidRequestException(validationErrorMessage, ExceptionMessages.missingAttribute.format( "userAttributeKey" ))
} else if (attribute["value"] !is String) {
// Android SDK expects a string for user attr values, regardless of the configuration in cognito
throw InvalidRequestException(validationErrorMessage, "Attribute value is not a String.")
}
validateUserAttribute(attribute, validationErrorMessage)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,13 @@

package com.amazonaws.amplify.amplify_auth_cognito.types

import com.amazonaws.amplify.amplify_auth_cognito.utils.serializeAuthUpdateAttributeResult
import com.amplifyframework.auth.result.AuthUpdateAttributeResult
import com.google.gson.Gson

data class FlutterUpdateUserAttributeResult(private val raw: AuthUpdateAttributeResult) {
val isUpdated: Boolean = raw.isUpdated
val nextStep: Map<String, Any> = setNextStep();

private fun setNextStep(): Map<String, Any> {
return mapOf(
"updateAttributeStep" to raw.nextStep.updateAttributeStep.toString(),
"additionalInfo" to Gson().toJson(raw.nextStep.additionalInfo),
"codeDeliveryDetails" to mapOf(
"destination" to (raw.nextStep.codeDeliveryDetails?.destination ?: ""),
"deliveryMedium" to (raw.nextStep.codeDeliveryDetails?.deliveryMedium?.name ?: ""),
"attributeName" to (raw.nextStep.codeDeliveryDetails?.attributeName ?: "")
)
)
}
val result: AuthUpdateAttributeResult = raw;

fun toValueMap(): Map<String, Any> {
return mapOf(
"isUpdated" to this.isUpdated,
"nextStep" to this.nextStep
)
return serializeAuthUpdateAttributeResult(result)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package com.amazonaws.amplify.amplify_auth_cognito.types

import com.amazonaws.amplify.amplify_auth_cognito.utils.createAuthUserAttribute
import com.amazonaws.amplify.amplify_auth_cognito.utils.validateUserAttribute
import com.amazonaws.amplify.amplify_core.exception.ExceptionMessages
import com.amazonaws.amplify.amplify_core.exception.InvalidRequestException
import com.amplifyframework.auth.AuthUserAttribute

data class FlutterUpdateUserAttributesRequest(val map: HashMap<String, *>) {

val attributes: List<AuthUserAttribute> = (map["attributes"] as List<HashMap<*, *>>)
.map { createAuthUserAttribute(it["userAttributeKey"] as String, it["value"] as String) }

companion object {
private const val validationErrorMessage: String = "UpdateUserAttributesRequest Request malformed."
fun validate(req: HashMap<String, *>?) {
if (req == null) {
throw InvalidRequestException(validationErrorMessage, ExceptionMessages.missingAttribute.format("request map"))
} else if (!req.containsKey("attributes") || req["attributes"] !is List<*>) {
throw InvalidRequestException(validationErrorMessage, ExceptionMessages.missingAttribute.format("attributes"))
} else {
val attributes = req["attributes"] as List<HashMap<*, *>>
if (attributes.isEmpty()) {
throw InvalidRequestException(validationErrorMessage, "The request must have at least one attribute.")
} else {
attributes.forEach { validateUserAttribute(it, validationErrorMessage) }
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package com.amazonaws.amplify.amplify_auth_cognito.types

import com.amazonaws.amplify.amplify_auth_cognito.utils.serializeAuthUpdateAttributeResult
import com.amplifyframework.auth.AuthUserAttributeKey
import com.amplifyframework.auth.result.AuthUpdateAttributeResult

data class FlutterUpdateUserAttributesResult(private val raw: Map<AuthUserAttributeKey, AuthUpdateAttributeResult>) {
val attributes: Map<AuthUserAttributeKey, AuthUpdateAttributeResult> = raw;

fun toValueMap(): Map<String, Any> {
return attributes.entries.associate {
it.key.keyString to serializeAuthUpdateAttributeResult(it.value)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/


package com.amazonaws.amplify.amplify_auth_cognito.utils

import com.amplifyframework.auth.AuthCodeDeliveryDetails

fun serializeAuthCodeDeliveryDetails(deliveryDetails: AuthCodeDeliveryDetails?): Map<String, Any> {
return mapOf(
"destination" to (deliveryDetails?.destination ?: ""),
"deliveryMedium" to (deliveryDetails?.deliveryMedium?.name
?: ""),
"attributeName" to (deliveryDetails?.attributeName ?: "")
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/

package com.amazonaws.amplify.amplify_auth_cognito.types
package com.amazonaws.amplify.amplify_auth_cognito.utils

import com.amplifyframework.auth.AuthUserAttribute
import com.amplifyframework.auth.AuthUserAttributeKey
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package com.amazonaws.amplify.amplify_auth_cognito.utils

import com.amplifyframework.auth.result.AuthUpdateAttributeResult
import com.amplifyframework.auth.result.step.AuthNextUpdateAttributeStep
import com.google.gson.Gson

fun serializeAuthUpdateAttributeResult(result: AuthUpdateAttributeResult): Map<String, Any> {
return mapOf(
"isUpdated" to result.isUpdated,
"nextStep" to serializeAuthUpdateAttributeStep(result.nextStep)
)
}

fun serializeAuthUpdateAttributeStep(nextStep: AuthNextUpdateAttributeStep): Map<String, Any> {
return mapOf(
"updateAttributeStep" to nextStep.updateAttributeStep.toString(),
"additionalInfo" to Gson().toJson(nextStep.additionalInfo),
"codeDeliveryDetails" to serializeAuthCodeDeliveryDetails(nextStep.codeDeliveryDetails)
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package com.amazonaws.amplify.amplify_auth_cognito.utils

import com.amazonaws.amplify.amplify_core.exception.ExceptionMessages
import com.amazonaws.amplify.amplify_core.exception.InvalidRequestException

fun validateUserAttribute(attribute: HashMap<*, *>, validationErrorMessage: String) {
if (!attribute.containsKey("value")) {
throw InvalidRequestException(validationErrorMessage, ExceptionMessages.missingAttribute.format("value"))
} else if (!attribute.containsKey("userAttributeKey")) {
throw InvalidRequestException(validationErrorMessage, ExceptionMessages.missingAttribute.format("userAttributeKey"))
} else if (attribute["value"] !is String) {
// Android SDK expects a string for user attr values, regardless of the configuration in cognito
throw InvalidRequestException(validationErrorMessage, "Attribute value is not a String.")
}
}
Loading

0 comments on commit 8b0893c

Please sign in to comment.