1
+ /*
2
+ * Copyright 2016 Google Inc. All Rights Reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5
+ * in compliance with the License. You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software distributed under the
10
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11
+ * express or implied. See the License for the specific language governing permissions and
12
+ * limitations under the License.
13
+ */
14
+ package com.firebase.ui.auth.ui.email
15
+
16
+ import android.app.AlertDialog
17
+ import android.content.Context
18
+ import android.content.Intent
19
+ import android.os.Bundle
20
+ import androidx.annotation.NonNull
21
+ import androidx.annotation.Nullable
22
+ import androidx.annotation.RestrictTo
23
+ import androidx.lifecycle.ViewModelProvider
24
+ import com.firebase.ui.auth.ErrorCodes
25
+ import com.firebase.ui.auth.FirebaseAuthAnonymousUpgradeException
26
+ import com.firebase.ui.auth.FirebaseUiException
27
+ import com.firebase.ui.auth.IdpResponse
28
+ import com.firebase.ui.auth.R
29
+ import com.firebase.ui.auth.data.model.FlowParameters
30
+ import com.firebase.ui.auth.data.model.UserCancellationException
31
+ import com.firebase.ui.auth.ui.InvisibleActivityBase
32
+ import com.firebase.ui.auth.util.ExtraConstants
33
+ import com.firebase.ui.auth.viewmodel.RequestCodes
34
+ import com.firebase.ui.auth.viewmodel.ResourceObserver
35
+ import com.firebase.ui.auth.viewmodel.email.EmailLinkSignInHandler
36
+ import com.google.firebase.auth.FirebaseAuthInvalidCredentialsException
37
+
38
+ // Assuming EmailLinkErrorRecoveryActivity exists in your project.
39
+ import com.firebase.ui.auth.ui.email.EmailLinkErrorRecoveryActivity
40
+
41
+ @RestrictTo(RestrictTo .Scope .LIBRARY_GROUP )
42
+ class EmailLinkCatcherActivity : InvisibleActivityBase () {
43
+
44
+ private lateinit var mHandler: EmailLinkSignInHandler
45
+
46
+ companion object {
47
+ @JvmStatic
48
+ fun createIntent (context : Context , flowParams : FlowParameters ): Intent {
49
+ return createBaseIntent(context, EmailLinkCatcherActivity ::class .java, flowParams)
50
+ }
51
+ }
52
+
53
+ override fun onCreate (@Nullable savedInstanceState : Bundle ? ) {
54
+ super .onCreate(savedInstanceState)
55
+
56
+ initHandler()
57
+
58
+ if (getFlowParams().emailLink != null ) {
59
+ mHandler.startSignIn()
60
+ }
61
+ }
62
+
63
+ private fun initHandler () {
64
+ mHandler = ViewModelProvider (this ).get(EmailLinkSignInHandler ::class .java)
65
+ mHandler.init (getFlowParams())
66
+ mHandler.operation.observe(this , object : ResourceObserver <IdpResponse >(this ) {
67
+ override fun onSuccess (@NonNull response : IdpResponse ) {
68
+ finish(RESULT_OK , response.toIntent())
69
+ }
70
+
71
+ override fun onFailure (@NonNull e : Exception ) {
72
+ when {
73
+ e is UserCancellationException -> finish(RESULT_CANCELED , null )
74
+ e is FirebaseAuthAnonymousUpgradeException -> {
75
+ val res = e.response
76
+ finish(RESULT_CANCELED , Intent ().putExtra(ExtraConstants .IDP_RESPONSE , res))
77
+ }
78
+ e is FirebaseUiException -> {
79
+ val errorCode = e.errorCode
80
+ when (errorCode) {
81
+ ErrorCodes .EMAIL_LINK_WRONG_DEVICE_ERROR ,
82
+ ErrorCodes .INVALID_EMAIL_LINK_ERROR ,
83
+ ErrorCodes .EMAIL_LINK_DIFFERENT_ANONYMOUS_USER_ERROR ->
84
+ buildAlertDialog(errorCode).show()
85
+ ErrorCodes .EMAIL_LINK_PROMPT_FOR_EMAIL_ERROR ,
86
+ ErrorCodes .EMAIL_MISMATCH_ERROR ->
87
+ startErrorRecoveryFlow(RequestCodes .EMAIL_LINK_PROMPT_FOR_EMAIL_FLOW )
88
+ ErrorCodes .EMAIL_LINK_CROSS_DEVICE_LINKING_ERROR ->
89
+ startErrorRecoveryFlow(RequestCodes .EMAIL_LINK_CROSS_DEVICE_LINKING_FLOW )
90
+ else -> finish(RESULT_CANCELED , IdpResponse .getErrorIntent(e))
91
+ }
92
+ }
93
+ e is FirebaseAuthInvalidCredentialsException ->
94
+ startErrorRecoveryFlow(RequestCodes .EMAIL_LINK_PROMPT_FOR_EMAIL_FLOW )
95
+ else -> finish(RESULT_CANCELED , IdpResponse .getErrorIntent(e))
96
+ }
97
+ }
98
+ })
99
+ }
100
+
101
+ /* *
102
+ * @param flow must be one of RequestCodes.EMAIL_LINK_PROMPT_FOR_EMAIL_FLOW or
103
+ * RequestCodes.EMAIL_LINK_CROSS_DEVICE_LINKING_FLOW
104
+ */
105
+ private fun startErrorRecoveryFlow (flow : Int ) {
106
+ if (flow != RequestCodes .EMAIL_LINK_CROSS_DEVICE_LINKING_FLOW &&
107
+ flow != RequestCodes .EMAIL_LINK_PROMPT_FOR_EMAIL_FLOW
108
+ ) {
109
+ throw IllegalStateException (
110
+ " Invalid flow param. It must be either " +
111
+ " RequestCodes.EMAIL_LINK_CROSS_DEVICE_LINKING_FLOW or " +
112
+ " RequestCodes.EMAIL_LINK_PROMPT_FOR_EMAIL_FLOW"
113
+ )
114
+ }
115
+ val intent = EmailLinkErrorRecoveryActivity .createIntent(applicationContext, getFlowParams(), flow)
116
+ startActivityForResult(intent, flow)
117
+ }
118
+
119
+ private fun buildAlertDialog (errorCode : Int ): AlertDialog {
120
+ val builder = AlertDialog .Builder (this )
121
+ val (titleText, messageText) = when (errorCode) {
122
+ ErrorCodes .EMAIL_LINK_DIFFERENT_ANONYMOUS_USER_ERROR -> Pair (
123
+ getString(R .string.fui_email_link_different_anonymous_user_header),
124
+ getString(R .string.fui_email_link_different_anonymous_user_message)
125
+ )
126
+ ErrorCodes .INVALID_EMAIL_LINK_ERROR -> Pair (
127
+ getString(R .string.fui_email_link_invalid_link_header),
128
+ getString(R .string.fui_email_link_invalid_link_message)
129
+ )
130
+ else -> Pair (
131
+ getString(R .string.fui_email_link_wrong_device_header),
132
+ getString(R .string.fui_email_link_wrong_device_message)
133
+ )
134
+ }
135
+ return builder.setTitle(titleText)
136
+ .setMessage(messageText)
137
+ .setPositiveButton(R .string.fui_email_link_dismiss_button) { _, _ ->
138
+ finish(errorCode, null )
139
+ }
140
+ .create()
141
+ }
142
+
143
+ override fun onActivityResult (requestCode : Int , resultCode : Int , @Nullable data : Intent ? ) {
144
+ super .onActivityResult(requestCode, resultCode, data)
145
+ if (requestCode == RequestCodes .EMAIL_LINK_PROMPT_FOR_EMAIL_FLOW ||
146
+ requestCode == RequestCodes .EMAIL_LINK_CROSS_DEVICE_LINKING_FLOW
147
+ ) {
148
+ val response = IdpResponse .fromResultIntent(data)
149
+ // CheckActionCode is called before starting this flow, so we only get here
150
+ // if the sign in link is valid – it can only fail by being cancelled.
151
+ if (resultCode == RESULT_OK ) {
152
+ finish(RESULT_OK , response?.toIntent())
153
+ } else {
154
+ finish(RESULT_CANCELED , null )
155
+ }
156
+ }
157
+ }
158
+ }
0 commit comments