Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[*.{kt,kts}]
#this is to match java checkstyle
max_line_length=120
5 changes: 5 additions & 0 deletions authenticator/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ android {
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
}

compileOptions {
coreLibraryDesugaringEnabled true
}

publishing {
singleVariant("release") {
withSourcesJar()
Expand All @@ -24,6 +28,7 @@ dependencies {
implementation dependency.androidx.uiTooling
implementation dependency.androidx.lifecycle_ktx
implementation dependency.androidx.compose.viewmodel
coreLibraryDesugaring dependency.android.desugar

testImplementation dependency.test.androidx.espresso
testImplementation dependency.test.androidx.junit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ import com.amplifyframework.auth.result.step.AuthResetPasswordStep
import com.amplifyframework.auth.result.step.AuthSignInStep
import com.amplifyframework.auth.result.step.AuthSignUpStep
import com.amplifyframework.core.Amplify
import com.amplifyframework.ui.authenticator.amplify.AmplifyAuthConfiguration
import com.amplifyframework.ui.authenticator.amplify.toAttributeKey
import com.amplifyframework.ui.authenticator.amplify.toFieldKey
import com.amplifyframework.ui.authenticator.amplify.toVerifiedAttributeKey
import com.amplifyframework.ui.authenticator.auth.AmplifyAuthConfiguration
import com.amplifyframework.ui.authenticator.auth.toAttributeKey
import com.amplifyframework.ui.authenticator.auth.toFieldKey
import com.amplifyframework.ui.authenticator.auth.toVerifiedAttributeKey
import com.amplifyframework.ui.authenticator.enums.AuthenticatorInitialStep
import com.amplifyframework.ui.authenticator.enums.AuthenticatorStep
import com.amplifyframework.ui.authenticator.forms.FieldError
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright 2023 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.amplifyframework.ui.authenticator.auth

import androidx.annotation.IntRange
import com.amplifyframework.auth.AuthUserAttributeKey
import com.amplifyframework.ui.authenticator.forms.FieldKey

internal enum class SignInMethod {
Username, Email, PhoneNumber
}

internal enum class VerificationMechanism {
PhoneNumber, Email
}

internal data class PasswordCriteria(
@IntRange(from = 6, to = 99) val length: Int,
val requiresNumber: Boolean,
val requiresSpecial: Boolean,
val requiresUpper: Boolean,
val requiresLower: Boolean
)

/**
* This is a temporary mock of the information we'll need to get from Amplify during start up
*/
internal class AmplifyAuthConfiguration(
val signInMethod: SignInMethod,
val signUpAttributes: List<AuthUserAttributeKey>,
val passwordCriteria: PasswordCriteria,
val verificationMechanisms: Set<VerificationMechanism>
)

internal fun SignInMethod.toFieldKey() = when (this) {
SignInMethod.Username -> FieldKey.Username
SignInMethod.Email -> FieldKey.Email
SignInMethod.PhoneNumber -> FieldKey.PhoneNumber
}

internal fun VerificationMechanism.toAttributeKey() = when (this) {
VerificationMechanism.PhoneNumber -> AuthUserAttributeKey.phoneNumber()
VerificationMechanism.Email -> AuthUserAttributeKey.email()
}

internal fun VerificationMechanism.toVerifiedAttributeKey() = when (this) {
VerificationMechanism.PhoneNumber -> AuthUserAttributeKey.phoneNumberVerified()
VerificationMechanism.Email -> AuthUserAttributeKey.emailVerified()
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package com.amplifyframework.ui.authenticator.forms
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.ui.text.input.KeyboardType
import java.util.*

/**
* An [FieldConfig] specifies the metadata for an input field within the Authenticator composable. The
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
package com.amplifyframework.ui.authenticator.forms

import android.util.Patterns
import com.amplifyframework.ui.authenticator.amplify.PasswordCriteria
import com.amplifyframework.ui.authenticator.auth.PasswordCriteria
import com.amplifyframework.ui.authenticator.forms.FieldError.InvalidFormat
import com.amplifyframework.ui.authenticator.forms.FieldError.PasswordsDoNotMatch
import com.amplifyframework.ui.authenticator.forms.FieldKey.Password
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ package com.amplifyframework.ui.authenticator.forms
import androidx.compose.runtime.Composable
import androidx.compose.ui.text.input.KeyboardType
import com.amplifyframework.auth.AuthUserAttributeKey
import com.amplifyframework.ui.authenticator.amplify.SignInMethod
import com.amplifyframework.ui.authenticator.amplify.toFieldKey
import com.amplifyframework.ui.authenticator.auth.SignInMethod
import com.amplifyframework.ui.authenticator.auth.toFieldKey

internal data class FormData(val fields: List<FieldConfig>)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ import com.amplifyframework.auth.AuthUser
import com.amplifyframework.auth.AuthUserAttribute
import com.amplifyframework.auth.AuthUserAttributeKey
import com.amplifyframework.auth.result.AuthSignOutResult
import com.amplifyframework.ui.authenticator.amplify.AmplifyAuthConfiguration
import com.amplifyframework.ui.authenticator.amplify.PasswordCriteria
import com.amplifyframework.ui.authenticator.amplify.SignInMethod
import com.amplifyframework.ui.authenticator.amplify.toFieldKey
import com.amplifyframework.ui.authenticator.auth.AmplifyAuthConfiguration
import com.amplifyframework.ui.authenticator.auth.PasswordCriteria
import com.amplifyframework.ui.authenticator.auth.SignInMethod
import com.amplifyframework.ui.authenticator.auth.toFieldKey
import com.amplifyframework.ui.authenticator.enums.AuthenticatorInitialStep
import com.amplifyframework.ui.authenticator.forms.FieldKey
import com.amplifyframework.ui.authenticator.forms.FieldValidators
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,11 @@ internal open class StringResolver {
FieldKey.Website -> stringResource(R.string.amplify_ui_authenticator_field_label_website)
FieldKey.PhoneNumber -> stringResource(R.string.amplify_ui_authenticator_field_label_phone_number)
FieldKey.Nickname -> stringResource(R.string.amplify_ui_authenticator_field_label_nickname)
FieldKey.PreferredUsername -> stringResource(R.string.amplify_ui_authenticator_field_label_preferred_username)
FieldKey.PreferredUsername ->
stringResource(R.string.amplify_ui_authenticator_field_label_preferred_username)
FieldKey.Profile -> stringResource(R.string.amplify_ui_authenticator_field_label_profile)
FieldKey.VerificationAttribute -> stringResource(R.string.amplify_ui_authenticator_field_label_verification_attribute)
FieldKey.VerificationAttribute ->
stringResource(R.string.amplify_ui_authenticator_field_label_verification_attribute)
else -> ""
}
}
Expand All @@ -68,7 +70,8 @@ internal open class StringResolver {
@ReadOnlyComposable
open fun hint(config: FieldConfig): String? {
return config.hint ?: when {
config.key == FieldKey.ConfirmPassword -> stringResource(R.string.amplify_ui_authenticator_field_hint_password_confirm)
config.key == FieldKey.ConfirmPassword ->
stringResource(R.string.amplify_ui_authenticator_field_hint_password_confirm)
config is FieldConfig.Date -> "yyyy-mm-dd"
else -> {
val label = label(config)
Expand Down Expand Up @@ -105,7 +108,8 @@ internal open class StringResolver {
}
errorText
}
FieldError.PasswordsDoNotMatch -> stringResource(R.string.amplify_ui_authenticator_field_warn_unmatched_password)
FieldError.PasswordsDoNotMatch ->
stringResource(R.string.amplify_ui_authenticator_field_warn_unmatched_password)
FieldError.MissingRequired -> {
val label = title(config)
stringResource(R.string.amplify_ui_authenticator_field_warn_empty, label)
Expand All @@ -130,6 +134,7 @@ internal open class StringResolver {
}
}

@Suppress("UNUSED_EXPRESSION")
@Composable
@ReadOnlyComposable
open fun error(error: AuthException): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ import kotlinx.coroutines.launch
fun PasswordReset(
state: PasswordResetState,
modifier: Modifier = Modifier,
headerContent: @Composable (PasswordResetState) -> Unit = { AuthenticatorTitle(stringResource(R.string.amplify_ui_authenticator_title_password_reset)) },
headerContent: @Composable (PasswordResetState) -> Unit = {
AuthenticatorTitle(stringResource(R.string.amplify_ui_authenticator_title_password_reset))
},
footerContent: @Composable (PasswordResetState) -> Unit = { PasswordResetFooter(it) }
) {
val scope = rememberCoroutineScope()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ import kotlinx.coroutines.launch
fun PasswordResetConfirm(
state: PasswordResetConfirmState,
modifier: Modifier = Modifier,
headerContent: @Composable (PasswordResetConfirmState) -> Unit = { AuthenticatorTitle(stringResource(R.string.amplify_ui_authenticator_title_password_reset)) },
headerContent: @Composable (PasswordResetConfirmState) -> Unit = {
AuthenticatorTitle(stringResource(R.string.amplify_ui_authenticator_title_password_reset))
},
footerContent: @Composable (PasswordResetConfirmState) -> Unit = { PasswordResetConfirmFooter(it) },
deliveryNoticeContent: @Composable (details: AuthCodeDeliveryDetails?) -> Unit = { DeliveryDetails(it) }
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ import com.amplifyframework.ui.authenticator.forms.MutableFieldState
import com.amplifyframework.ui.authenticator.strings.StringResolver
import com.amplifyframework.ui.authenticator.util.dialCodeFor
import com.amplifyframework.ui.authenticator.util.dialCodeList
import java.util.*
import java.util.Locale

@Stable
private class PhoneNumberFieldState(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ import kotlinx.coroutines.launch
fun SignIn(
state: SignInState,
modifier: Modifier = Modifier,
headerContent: @Composable (SignInState) -> Unit = { AuthenticatorTitle(stringResource(R.string.amplify_ui_authenticator_title_signin)) },
headerContent: @Composable (SignInState) -> Unit = {
AuthenticatorTitle(stringResource(R.string.amplify_ui_authenticator_title_signin))
},
footerContent: @Composable (SignInState) -> Unit = { SignInFooter(it) }
) {
val scope = rememberCoroutineScope()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ import kotlinx.coroutines.launch
fun SignInConfirmCustom(
state: SignInConfirmCustomState,
modifier: Modifier = Modifier,
headerContent: @Composable (state: SignInConfirmCustomState) -> Unit = { AuthenticatorTitle(stringResource(R.string.amplify_ui_authenticator_title_signin_confirm_mfa)) },
headerContent: @Composable (state: SignInConfirmCustomState) -> Unit = {
AuthenticatorTitle(stringResource(R.string.amplify_ui_authenticator_title_signin_confirm_mfa))
},
footerContent: @Composable (state: SignInConfirmCustomState) -> Unit = { SignInConfirmCustomFooter(it) },
deliveryDetailsContent: @Composable (details: AuthCodeDeliveryDetails?) -> Unit = { DeliveryDetails(it) }
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ import kotlinx.coroutines.launch
fun SignInConfirmMfa(
state: SignInConfirmMfaState,
modifier: Modifier = Modifier,
headerContent: @Composable (state: SignInConfirmMfaState) -> Unit = { AuthenticatorTitle(stringResource(R.string.amplify_ui_authenticator_title_signin_confirm_mfa)) },
headerContent: @Composable (state: SignInConfirmMfaState) -> Unit = {
AuthenticatorTitle(stringResource(R.string.amplify_ui_authenticator_title_signin_confirm_mfa))
},
footerContent: @Composable (state: SignInConfirmMfaState) -> Unit = { SignInConfirmMfaFooter(it) },
deliveryNoticeContent: @Composable (details: AuthCodeDeliveryDetails?) -> Unit = { DeliveryDetails(details = it) }
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ import kotlinx.coroutines.launch
fun SignUp(
state: SignUpState,
modifier: Modifier = Modifier,
headerContent: @Composable (SignUpState) -> Unit = { AuthenticatorTitle(stringResource(R.string.amplify_ui_authenticator_title_signup)) },
headerContent: @Composable (SignUpState) -> Unit = {
AuthenticatorTitle(stringResource(R.string.amplify_ui_authenticator_title_signup))
},
footerContent: @Composable (SignUpState) -> Unit = { SignUpFooter(it) }
) {
val scope = rememberCoroutineScope()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ import kotlinx.coroutines.launch
fun SignUpConfirm(
state: SignUpConfirmState,
modifier: Modifier = Modifier,
headerContent: @Composable (SignUpConfirmState) -> Unit = { AuthenticatorTitle(stringResource(R.string.amplify_ui_authenticator_title_signup_confirm)) },
headerContent: @Composable (SignUpConfirmState) -> Unit = {
AuthenticatorTitle(stringResource(R.string.amplify_ui_authenticator_title_signup_confirm))
},
footerContent: @Composable (SignUpConfirmState) -> Unit = { SignUpConfirmFooter(it) },
deliveryNoticeContent: @Composable (AuthCodeDeliveryDetails?) -> Unit = { DeliveryDetails(it) }
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ import kotlinx.coroutines.launch
fun VerifyUser(
state: VerifyUserState,
modifier: Modifier = Modifier,
headerContent: @Composable (VerifyUserState) -> Unit = { AuthenticatorTitle(stringResource(R.string.amplify_ui_authenticator_title_verify_user)) },
headerContent: @Composable (VerifyUserState) -> Unit = {
AuthenticatorTitle(stringResource(R.string.amplify_ui_authenticator_title_verify_user))
},
footerContent: @Composable (VerifyUserState) -> Unit = { VerifyUserFooter(it) }
) {
val scope = rememberCoroutineScope()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ import kotlinx.coroutines.launch
fun VerifyUserConfirm(
state: VerifyUserConfirmState,
modifier: Modifier = Modifier,
headerContent: @Composable (VerifyUserConfirmState) -> Unit = { AuthenticatorTitle(stringResource(R.string.amplify_ui_authenticator_title_verify_user)) },
headerContent: @Composable (VerifyUserConfirmState) -> Unit = {
AuthenticatorTitle(stringResource(R.string.amplify_ui_authenticator_title_verify_user))
},
footerContent: @Composable (VerifyUserConfirmState) -> Unit = {
VerifyUserConfirmFooter(it)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,17 @@ import com.amplifyframework.hub.HubChannel
import com.amplifyframework.hub.HubEvent
import com.amplifyframework.hub.HubEventFilter
import com.amplifyframework.ui.authenticator.BuildConfig
import com.amplifyframework.ui.authenticator.amplify.AmplifyAuthConfiguration
import com.amplifyframework.ui.authenticator.amplify.PasswordCriteria
import com.amplifyframework.ui.authenticator.amplify.SignInMethod
import com.amplifyframework.ui.authenticator.amplify.VerificationMechanism
import com.amplifyframework.ui.authenticator.auth.AmplifyAuthConfiguration
import com.amplifyframework.ui.authenticator.auth.PasswordCriteria
import com.amplifyframework.ui.authenticator.auth.SignInMethod
import com.amplifyframework.ui.authenticator.auth.VerificationMechanism
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.channels.trySendBlocking
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import org.json.JSONException
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine

/**
* An abstraction of the Amplify.Auth API that allows us to use coroutines with no exceptions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,4 @@ internal class ExpiredCodeMessage(
*/
internal class NetworkErrorMessage(
override val cause: AuthException
): AuthenticatorMessageImpl(R.string.amplify_ui_authenticator_error_network), AuthenticatorMessage.Error
) : AuthenticatorMessageImpl(R.string.amplify_ui_authenticator_error_network), AuthenticatorMessage.Error
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* 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.
*/
*/ // ktlint-disable filename

package com.amplifyframework.ui.authenticator.util

Expand All @@ -24,7 +24,10 @@ import com.amplifyframework.ui.authenticator.forms.FieldError
// or an InvalidFormat if none
internal fun InvalidPasswordException.toFieldError(): FieldError {
val cause = this.cause
return if (cause is aws.sdk.kotlin.services.cognitoidentityprovider.model.InvalidPasswordException && cause.localizedMessage != null) {
return if (
cause is aws.sdk.kotlin.services.cognitoidentityprovider.model.InvalidPasswordException &&
cause.localizedMessage != null
) {
FieldError.Custom(cause.localizedMessage!!)
} else {
FieldError.InvalidFormat
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ import com.amplifyframework.auth.AuthException
*/
class MissingConfigurationException : AuthException(
"Missing auth configuration",
"Make sure the Auth plugin is added and Amplify.configure is called. See https://docs.amplify.aws/lib/auth/getting-started/q/platform/android/ for details"
"Make sure the Auth plugin is added and Amplify.configure is called. See " +
"https://docs.amplify.aws/lib/auth/getting-started/q/platform/android/ for details"
)
1 change: 0 additions & 1 deletion authenticator/src/main/res/values/messages.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
-->

<resources>
<string name="amplify_ui_authenticator_message_account_created">Account created</string>
<string name="amplify_ui_authenticator_message_password_reset">Password has been reset</string>
<string name="amplify_ui_authenticator_message_code_sent">Confirmation code sent</string>
</resources>
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ ext {
auth: "com.amplifyframework:aws-auth-cognito:$amplifyVersion",
predictions: "com.amplifyframework:aws-predictions:$amplifyVersion",
],
android: [
desugar: "com.android.tools:desugar_jdk_libs:1.1.8"
],
androidx: [
camera: [
core: "androidx.camera:camera-core:$cameraXVersion",
Expand Down