Skip to content

Commit b7c442e

Browse files
authored
fix(auth): Add ConfirmSignUpOptions for confirmSignUp API method (#1357)
1 parent c103704 commit b7c442e

File tree

12 files changed

+369
-15
lines changed

12 files changed

+369
-15
lines changed

aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/AWSCognitoAuthPlugin.java

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import com.amplifyframework.auth.AuthUserAttribute;
3535
import com.amplifyframework.auth.AuthUserAttributeKey;
3636
import com.amplifyframework.auth.cognito.options.AWSCognitoAuthConfirmSignInOptions;
37+
import com.amplifyframework.auth.cognito.options.AWSCognitoAuthConfirmSignUpOptions;
3738
import com.amplifyframework.auth.cognito.options.AWSCognitoAuthSignInOptions;
3839
import com.amplifyframework.auth.cognito.options.AWSCognitoAuthSignOutOptions;
3940
import com.amplifyframework.auth.cognito.options.AWSCognitoAuthSignUpOptions;
@@ -42,6 +43,7 @@
4243
import com.amplifyframework.auth.cognito.util.CognitoAuthExceptionConverter;
4344
import com.amplifyframework.auth.cognito.util.SignInStateConverter;
4445
import com.amplifyframework.auth.options.AuthConfirmSignInOptions;
46+
import com.amplifyframework.auth.options.AuthConfirmSignUpOptions;
4547
import com.amplifyframework.auth.options.AuthSignInOptions;
4648
import com.amplifyframework.auth.options.AuthSignOutOptions;
4749
import com.amplifyframework.auth.options.AuthSignUpOptions;
@@ -125,7 +127,7 @@ public final class AWSCognitoAuthPlugin extends AuthPlugin<AWSMobileClient> {
125127
public AWSCognitoAuthPlugin() {
126128
this.awsMobileClient = AWSMobileClient.getInstance();
127129
}
128-
130+
129131
@VisibleForTesting
130132
AWSCognitoAuthPlugin(AWSMobileClient instance, String userId) {
131133
this.awsMobileClient = instance;
@@ -304,12 +306,20 @@ public void onError(Exception error) {
304306

305307
@Override
306308
public void confirmSignUp(
307-
@NonNull String username,
308-
@NonNull String confirmationCode,
309-
@NonNull final Consumer<AuthSignUpResult> onSuccess,
310-
@NonNull final Consumer<AuthException> onException
309+
@NonNull String username,
310+
@NonNull String confirmationCode,
311+
@NonNull AuthConfirmSignUpOptions options,
312+
@NonNull final Consumer<AuthSignUpResult> onSuccess,
313+
@NonNull final Consumer<AuthException> onException
311314
) {
312-
awsMobileClient.confirmSignUp(username, confirmationCode, new Callback<SignUpResult>() {
315+
final Map<String, String> clientMetadata = new HashMap<>();
316+
317+
if (options instanceof AWSCognitoAuthConfirmSignUpOptions) {
318+
AWSCognitoAuthConfirmSignUpOptions cognitoOptions = (AWSCognitoAuthConfirmSignUpOptions) options;
319+
clientMetadata.putAll(cognitoOptions.getClientMetadata());
320+
}
321+
322+
awsMobileClient.confirmSignUp(username, confirmationCode, clientMetadata, new Callback<SignUpResult>() {
313323
@Override
314324
public void onResult(SignUpResult result) {
315325
onSuccess.accept(convertSignUpResult(result, username));
@@ -324,6 +334,16 @@ public void onError(Exception error) {
324334
});
325335
}
326336

337+
@Override
338+
public void confirmSignUp(
339+
@NonNull String username,
340+
@NonNull String confirmationCode,
341+
@NonNull final Consumer<AuthSignUpResult> onSuccess,
342+
@NonNull final Consumer<AuthException> onException
343+
) {
344+
confirmSignUp(username, confirmationCode, AuthConfirmSignUpOptions.defaults(), onSuccess, onException);
345+
}
346+
327347
@Override
328348
public void resendSignUpCode(
329349
@NonNull String username,
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package com.amplifyframework.auth.cognito.options;
17+
18+
import androidx.annotation.NonNull;
19+
import androidx.core.util.ObjectsCompat;
20+
21+
import com.amplifyframework.auth.options.AuthConfirmSignUpOptions;
22+
import com.amplifyframework.util.Immutable;
23+
24+
import java.util.HashMap;
25+
import java.util.Map;
26+
import java.util.Objects;
27+
28+
/**
29+
* Cognito extension of confirm sign up options to add the platform specific fields.
30+
*/
31+
public final class AWSCognitoAuthConfirmSignUpOptions extends AuthConfirmSignUpOptions {
32+
private final Map<String, String> clientMetadata;
33+
34+
/**
35+
* Advanced options for confirming sign up.
36+
* @param clientMetadata Additional custom attributes to be sent to the service such as information about the client
37+
*/
38+
protected AWSCognitoAuthConfirmSignUpOptions(
39+
Map<String, String> clientMetadata
40+
) {
41+
this.clientMetadata = clientMetadata;
42+
}
43+
44+
/**
45+
* Get custom attributes to be sent to the service such as information about the client.
46+
* @return custom attributes to be sent to the service such as information about the client
47+
*/
48+
@NonNull
49+
public Map<String, String> getClientMetadata() {
50+
return clientMetadata;
51+
}
52+
53+
/**
54+
* Get a builder object.
55+
* @return a builder object.
56+
*/
57+
@NonNull
58+
public static CognitoBuilder builder() {
59+
return new CognitoBuilder();
60+
}
61+
62+
@Override
63+
public int hashCode() {
64+
return ObjectsCompat.hash(
65+
getClientMetadata()
66+
);
67+
}
68+
69+
@Override
70+
public boolean equals(Object obj) {
71+
if (this == obj) {
72+
return true;
73+
} else if (obj == null || getClass() != obj.getClass()) {
74+
return false;
75+
} else {
76+
AWSCognitoAuthConfirmSignUpOptions authConfirmSignUpOptions = (AWSCognitoAuthConfirmSignUpOptions) obj;
77+
return ObjectsCompat.equals(getClientMetadata(), authConfirmSignUpOptions.getClientMetadata());
78+
}
79+
}
80+
81+
@Override
82+
public String toString() {
83+
return "AWSCognitoAuthConfirmSignUpOptions{" +
84+
"metadata=" + clientMetadata +
85+
'}';
86+
}
87+
88+
/**
89+
* The builder for this class.
90+
*/
91+
public static final class CognitoBuilder extends Builder<CognitoBuilder> {
92+
private final Map<String, String> clientMetadata;
93+
94+
/**
95+
* Constructor for the builder.
96+
*/
97+
public CognitoBuilder() {
98+
super();
99+
this.clientMetadata = new HashMap<>();
100+
}
101+
102+
/**
103+
* Returns the type of builder this is to support proper flow with it being an extended class.
104+
* @return the type of builder this is to support proper flow with it being an extended class.
105+
*/
106+
@Override
107+
public CognitoBuilder getThis() {
108+
return this;
109+
}
110+
111+
/**
112+
* Set the metadata field for the object being built.
113+
* @param clientMetadata Custom user metadata to be sent with the sign up request.
114+
* @return The builder object to continue building.
115+
*/
116+
@NonNull
117+
public CognitoBuilder clientMetadata(@NonNull Map<String, String> clientMetadata) {
118+
Objects.requireNonNull(clientMetadata);
119+
this.clientMetadata.clear();
120+
this.clientMetadata.putAll(clientMetadata);
121+
return getThis();
122+
}
123+
124+
/**
125+
* Construct and return the object with the values set in the builder.
126+
* @return a new instance of AWSCognitoAuthConfirmSignUpOptions with the values specified in the builder.
127+
*/
128+
@NonNull
129+
public AWSCognitoAuthConfirmSignUpOptions build() {
130+
return new AWSCognitoAuthConfirmSignUpOptions(
131+
Immutable.of(clientMetadata));
132+
}
133+
}
134+
}

aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/AuthComponentTest.java

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.amplifyframework.auth.AuthUserAttribute;
3131
import com.amplifyframework.auth.AuthUserAttributeKey;
3232
import com.amplifyframework.auth.cognito.options.AWSCognitoAuthConfirmSignInOptions;
33+
import com.amplifyframework.auth.cognito.options.AWSCognitoAuthConfirmSignUpOptions;
3334
import com.amplifyframework.auth.cognito.options.AWSCognitoAuthSignInOptions;
3435
import com.amplifyframework.auth.cognito.options.AWSCognitoAuthSignOutOptions;
3536
import com.amplifyframework.auth.cognito.options.AWSCognitoAuthSignUpOptions;
@@ -242,15 +243,55 @@ public void confirmSignUp() throws AuthException {
242243
);
243244

244245
doAnswer(invocation -> {
245-
Callback<SignUpResult> callback = invocation.getArgument(2);
246+
Callback<SignUpResult> callback = invocation.getArgument(3);
246247
callback.onResult(amcResult);
247248
return null;
248-
}).when(mobileClient).confirmSignUp(any(), any(), Mockito.<Callback<SignUpResult>>any());
249+
}).when(mobileClient).confirmSignUp(any(), any(), any(), Mockito.<Callback<SignUpResult>>any());
249250

250251
AuthSignUpResult result = synchronousAuth.confirmSignUp(USERNAME, CONFIRMATION_CODE);
251252
validateSignUpResult(result, AuthSignUpStep.DONE);
252253
verify(mobileClient)
253-
.confirmSignUp(eq(USERNAME), eq(CONFIRMATION_CODE), Mockito.<Callback<SignUpResult>>any());
254+
.confirmSignUp(eq(USERNAME), eq(CONFIRMATION_CODE), any(), Mockito.<Callback<SignUpResult>>any());
255+
}
256+
257+
/**
258+
* Tests that the confirmSignUp method of the Auth wrapper of AWSMobileClient (AMC) calls AMC.confirmSignUp with
259+
* the username and confirmation code and options it received.
260+
* Also ensures that in the onResult case, the success callback receives a valid AuthSignUpResult.
261+
* @throws AuthException test fails if this gets thrown since method should succeed
262+
*/
263+
@Test
264+
public void confirmSignUpWithOptions() throws AuthException {
265+
SignUpResult amcResult = new SignUpResult(
266+
true,
267+
new UserCodeDeliveryDetails(
268+
DESTINATION,
269+
DELIVERY_MEDIUM,
270+
ATTRIBUTE_NAME
271+
),
272+
USER_SUB
273+
);
274+
275+
AWSCognitoAuthConfirmSignUpOptions.CognitoBuilder options = AWSCognitoAuthConfirmSignUpOptions.builder();
276+
Map<String, String> clientMetadata = new HashMap<String, String>();
277+
clientMetadata.put("testKey", "testValue");
278+
options.clientMetadata(clientMetadata);
279+
AWSCognitoAuthConfirmSignUpOptions builtOptions = options.build();
280+
281+
doAnswer(invocation -> {
282+
Callback<SignUpResult> callback = invocation.getArgument(3);
283+
callback.onResult(amcResult);
284+
return null;
285+
}).when(mobileClient).confirmSignUp(any(), any(), any(), Mockito.<Callback<SignUpResult>>any());
286+
287+
AuthSignUpResult result = synchronousAuth.confirmSignUp(USERNAME, CONFIRMATION_CODE, builtOptions);
288+
validateSignUpResult(result, AuthSignUpStep.DONE);
289+
verify(mobileClient)
290+
.confirmSignUp(
291+
eq(USERNAME),
292+
eq(CONFIRMATION_CODE),
293+
eq(clientMetadata),
294+
Mockito.<Callback<SignUpResult>>any());
254295
}
255296

256297
/**

core-kotlin/src/main/java/com/amplifyframework/kotlin/auth/Auth.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import com.amplifyframework.auth.AuthUser
2626
import com.amplifyframework.auth.AuthUserAttribute
2727
import com.amplifyframework.auth.AuthUserAttributeKey
2828
import com.amplifyframework.auth.options.AuthConfirmSignInOptions
29+
import com.amplifyframework.auth.options.AuthConfirmSignUpOptions
2930
import com.amplifyframework.auth.options.AuthSignInOptions
3031
import com.amplifyframework.auth.options.AuthSignOutOptions
3132
import com.amplifyframework.auth.options.AuthSignUpOptions
@@ -68,11 +69,17 @@ interface Auth {
6869
* @param username A login identifier e.g. `tony44`; or an email/phone number,
6970
* depending on configuration
7071
* @param confirmationCode The confirmation code the user received
72+
* @param options Advanced options such as a map of auth information for custom auth,
73+
* If not provided, default options will be used
7174
* @return A sign-up result; if the code has been confirmed successfully, the result
7275
* will show true for isSignUpComplete().
7376
*/
7477
@Throws(AuthException::class)
75-
suspend fun confirmSignUp(username: String, confirmationCode: String): AuthSignUpResult
78+
suspend fun confirmSignUp(
79+
username: String,
80+
confirmationCode: String,
81+
options: AuthConfirmSignUpOptions = AuthConfirmSignUpOptions.defaults()
82+
): AuthSignUpResult
7683

7784
/**
7885
* If the user's code expires or they just missed it, this method can

core-kotlin/src/main/java/com/amplifyframework/kotlin/auth/KotlinAuthFacade.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import com.amplifyframework.auth.AuthUser
2626
import com.amplifyframework.auth.AuthUserAttribute
2727
import com.amplifyframework.auth.AuthUserAttributeKey
2828
import com.amplifyframework.auth.options.AuthConfirmSignInOptions
29+
import com.amplifyframework.auth.options.AuthConfirmSignUpOptions
2930
import com.amplifyframework.auth.options.AuthSignInOptions
3031
import com.amplifyframework.auth.options.AuthSignOutOptions
3132
import com.amplifyframework.auth.options.AuthSignUpOptions
@@ -58,12 +59,14 @@ class KotlinAuthFacade(private val delegate: Delegate = Amplify.Auth) : Auth {
5859

5960
override suspend fun confirmSignUp(
6061
username: String,
61-
confirmationCode: String
62+
confirmationCode: String,
63+
options: AuthConfirmSignUpOptions
6264
): AuthSignUpResult {
6365
return suspendCoroutine { continuation ->
6466
delegate.confirmSignUp(
6567
username,
6668
confirmationCode,
69+
options,
6770
{ continuation.resume(it) },
6871
{ continuation.resumeWithException(it) }
6972
)

core-kotlin/src/test/java/com/amplifyframework/kotlin/auth/KotlinAuthFacadeTest.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,9 @@ class KotlinAuthFacadeTest {
9797
val code = "CoolCode599"
9898
val signUpResult = mockk<AuthSignUpResult>()
9999
every {
100-
delegate.confirmSignUp(eq(username), eq(code), any(), any())
100+
delegate.confirmSignUp(eq(username), eq(code), any(), any(), any())
101101
} answers {
102-
val indexOfResultConsumer = 2
102+
val indexOfResultConsumer = 3
103103
val onResult = it.invocation.args[indexOfResultConsumer] as Consumer<AuthSignUpResult>
104104
onResult.accept(signUpResult)
105105
}
@@ -116,9 +116,9 @@ class KotlinAuthFacadeTest {
116116
val code = "CoolCode599"
117117
val error = AuthException("uh", "oh")
118118
every {
119-
delegate.confirmSignUp(eq(username), eq(code), any(), any())
119+
delegate.confirmSignUp(eq(username), eq(code), any(), any(), any())
120120
} answers {
121-
val indexOfErrorConsumer = 3
121+
val indexOfErrorConsumer = 4
122122
val onError = it.invocation.args[indexOfErrorConsumer] as Consumer<AuthException>
123123
onError.accept(error)
124124
}

core/src/main/java/com/amplifyframework/auth/AuthCategory.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import androidx.annotation.Nullable;
2222

2323
import com.amplifyframework.auth.options.AuthConfirmSignInOptions;
24+
import com.amplifyframework.auth.options.AuthConfirmSignUpOptions;
2425
import com.amplifyframework.auth.options.AuthSignInOptions;
2526
import com.amplifyframework.auth.options.AuthSignOutOptions;
2627
import com.amplifyframework.auth.options.AuthSignUpOptions;
@@ -61,6 +62,17 @@ public void signUp(
6162
getSelectedPlugin().signUp(username, password, options, onSuccess, onError);
6263
}
6364

65+
@Override
66+
public void confirmSignUp(
67+
@NonNull String username,
68+
@NonNull String confirmationCode,
69+
@NonNull AuthConfirmSignUpOptions options,
70+
@NonNull Consumer<AuthSignUpResult> onSuccess,
71+
@NonNull Consumer<AuthException> onError
72+
) {
73+
getSelectedPlugin().confirmSignUp(username, confirmationCode, options, onSuccess, onError);
74+
}
75+
6476
@Override
6577
public void confirmSignUp(
6678
@NonNull String username,

0 commit comments

Comments
 (0)