-
Notifications
You must be signed in to change notification settings - Fork 108
/
CredentialStoreClient.kt
124 lines (114 loc) · 5.44 KB
/
CredentialStoreClient.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
* Copyright 2022 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.auth.cognito
import android.content.Context
import com.amplifyframework.auth.cognito.data.AWSCognitoAuthCredentialStore
import com.amplifyframework.auth.cognito.data.AWSCognitoLegacyCredentialStore
import com.amplifyframework.logging.Logger
import com.amplifyframework.statemachine.StateChangeListenerToken
import com.amplifyframework.statemachine.codegen.data.AmplifyCredential
import com.amplifyframework.statemachine.codegen.data.AuthConfiguration
import com.amplifyframework.statemachine.codegen.data.CredentialType
import com.amplifyframework.statemachine.codegen.events.CredentialStoreEvent
import com.amplifyframework.statemachine.codegen.states.CredentialStoreState
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
internal interface StoreClientBehavior {
suspend fun loadCredentials(credentialType: CredentialType): AmplifyCredential
suspend fun storeCredentials(credentialType: CredentialType, amplifyCredential: AmplifyCredential)
suspend fun clearCredentials(credentialType: CredentialType)
}
internal class CredentialStoreClient(configuration: AuthConfiguration, context: Context, val logger: Logger) :
StoreClientBehavior {
private val credentialStoreStateMachine = createCredentialStoreStateMachine(configuration, context)
private fun createCredentialStoreStateMachine(
configuration: AuthConfiguration,
context: Context
): CredentialStoreStateMachine {
val awsCognitoAuthCredentialStore = AWSCognitoAuthCredentialStore(context.applicationContext, configuration)
val legacyCredentialStore = AWSCognitoLegacyCredentialStore(context.applicationContext, configuration)
val credentialStoreEnvironment =
CredentialStoreEnvironment(awsCognitoAuthCredentialStore, legacyCredentialStore, logger)
return CredentialStoreStateMachine(credentialStoreEnvironment)
}
private fun listenForResult(
event: CredentialStoreEvent,
onSuccess: (Result<AmplifyCredential>) -> Unit,
onError: (Exception) -> Unit
) {
var capturedSuccess: Result<AmplifyCredential>? = null
var capturedError: Exception? = null
var token: StateChangeListenerToken? = StateChangeListenerToken()
credentialStoreStateMachine.listen(
token as StateChangeListenerToken,
{ storeState ->
logger.verbose("Credential Store State Change: $storeState")
when (storeState) {
is CredentialStoreState.Success -> {
capturedSuccess = Result.success(storeState.storedCredentials)
}
is CredentialStoreState.Error -> {
capturedError = storeState.error
}
is CredentialStoreState.Idle -> {
val success = capturedSuccess
val error = capturedError
if (success != null && token != null) {
credentialStoreStateMachine.cancel(token as StateChangeListenerToken)
token = null
onSuccess(success)
} else if (error != null && token != null) {
credentialStoreStateMachine.cancel(token as StateChangeListenerToken)
onError(error)
}
}
else -> Unit
}
},
{
credentialStoreStateMachine.send(event)
}
)
}
override suspend fun loadCredentials(credentialType: CredentialType): AmplifyCredential {
return suspendCoroutine { continuation ->
listenForResult(
CredentialStoreEvent(CredentialStoreEvent.EventType.LoadCredentialStore(credentialType)),
{ continuation.resumeWith(it) },
{ continuation.resumeWithException(it) }
)
}
}
override suspend fun storeCredentials(credentialType: CredentialType, amplifyCredential: AmplifyCredential) {
return suspendCoroutine { continuation ->
listenForResult(
CredentialStoreEvent(
CredentialStoreEvent.EventType.StoreCredentials(credentialType, amplifyCredential)
),
{ continuation.resumeWith(Result.success(Unit)) },
{ continuation.resumeWithException(it) }
)
}
}
override suspend fun clearCredentials(credentialType: CredentialType) {
return suspendCoroutine { continuation ->
listenForResult(
CredentialStoreEvent(CredentialStoreEvent.EventType.ClearCredentialStore(credentialType)),
{ continuation.resumeWith(Result.success(Unit)) },
{ continuation.resumeWithException(it) }
)
}
}
}