Skip to content
This repository was archived by the owner on Apr 4, 2023. It is now read-only.

Commit 5fcca8c

Browse files
Add Email Link Authentication #665
1 parent 87d854b commit 5fcca8c

File tree

6 files changed

+198
-100
lines changed

6 files changed

+198
-100
lines changed

demo/app/App_Resources/iOS/GoogleService-Info.plist

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,18 @@
2323
<key>STORAGE_BUCKET</key>
2424
<string>n-plugin-test.appspot.com</string>
2525
<key>IS_ADS_ENABLED</key>
26-
<true/>
26+
<true></true>
2727
<key>IS_ANALYTICS_ENABLED</key>
28-
<false/>
28+
<false></false>
2929
<key>IS_APPINVITE_ENABLED</key>
30-
<false/>
30+
<false></false>
3131
<key>IS_GCM_ENABLED</key>
32-
<true/>
32+
<true></true>
3333
<key>IS_SIGNIN_ENABLED</key>
34-
<true/>
34+
<true></true>
3535
<key>GOOGLE_APP_ID</key>
3636
<string>1:1052836194035:ios:443e3741d53b6bc3</string>
3737
<key>DATABASE_URL</key>
3838
<string>https://n-plugin-test.firebaseio.com</string>
3939
</dict>
40-
</plist>
40+
</plist>

demo/app/main-page.xml

Lines changed: 83 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
<TabViewItem.view>
7070
<ScrollView>
7171
<GridLayout columns="*, *"
72-
rows="auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto"
72+
rows="auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto"
7373
horizontalAlignment="stretch"
7474
class="tab-content">
7575

@@ -105,103 +105,97 @@
105105
<Label row="11" col="0" text="User email/phone:" class="message"/>
106106
<Label row="11" col="1" text="{{ userEmailOrPhone }}" class="message" textWrap="true"/>
107107

108-
<Button row="12" col="0" text="send email conf" tap="{{ doSendEmailVerification }}" class="button"/>
109-
<Button row="12" col="1" text="logout" tap="{{ doLogout }}" class="button"/>
110-
111-
<Label row="13" colSpan="2" text="Methods on path /users" class="subtitle"/>
112-
113-
<Button row="14" col="0" text="auto-sync: ON" tap="{{ doKeepUsersInSyncOn }}" class="button button-user"/>
114-
<Button row="14" col="1" text="auto-sync: OFF" tap="{{ doKeepUsersInSyncOff }}"
115-
class="button button-user"/>
116-
117-
<Button row="15" col="0" text="add childlistener" tap="{{ doAddChildEventListenerForUsers }}"
118-
class="button button-user"/>
119-
<Button row="15" col="1" text="store by push" tap="{{ doUserStoreByPush }}" class="button button-user"/>
120-
121-
<Button row="16" col="0" text="query users once" tap="{{ doQueryUsers }}" class="button button-user"/>
122-
<Button row="16" col="1" text="delete path" tap="{{ doRemoveUsers }}" class="button button-user"/>
123-
124-
<Button row="17" colSpan="2" text="del childlistener" tap="{{ doRemoveChildEventListenerForUsers }}"
125-
class="button button-user"/>
126-
127-
<Label row="18" colSpan="2" text="Methods on path /companies" class="subtitle"/>
128-
129-
<Button row="19" col="0" text="add valuelistener" tap="{{ doAddValueEventListenerForCompanies }}"
130-
class="button button-company"/>
131-
<Button row="19" col="1" text="store by setValue" tap="{{ doStoreCompaniesBySetValue }}"
132-
class="button button-company"/>
133-
134-
<Button row="20" col="0" text="query with range" tap="{{ doQueryBulgarianCompanies }}"
135-
class="button button-company"/>
136-
<Button row="20" col="1" text="remove path" tap="{{ doRemoveCompanies }}" class="button button-company"/>
137-
138-
<Button row="21" col="0" text="del valuelistener" tap="{{ doRemoveValueEventListenersForCompanies }}" class="button button-company"/>
139-
<Button row="21" col="1" text="get value" tap="{{ doGetValueForCompanies }}" class="button button-company"/>
140-
141-
<Label row="22" col="0" text="Last update path:" class="message"/>
142-
<Label row="22" col="1" text="{{ path }}" class="message" textWrap="true"/>
143-
144-
<Label row="23" col="0" text="Type:" class="message"/>
145-
<Label row="23" col="1" text="{{ type }}" class="message"/>
146-
147-
<Label row="24" col="0" text="Key:" class="message"/>
148-
<Label row="24" col="1" text="{{ key }}" class="message" textWrap="true"/>
149-
150-
<Label row="25" col="0" text="Value:" class="message"/>
151-
<Label row="25" col="1" text="{{ value }}" class="message" textWrap="true"/>
152-
153-
<Label row="26" colSpan="2" text="Google Cloud Storage" class="subtitle"/>
154-
<Button row="27" col="0" text="upload file" tap="{{ doUploadFile }}" class="button button-storage"/>
155-
<Button row="27" col="1" text="download file" tap="{{ doDownloadFile }}" class="button button-storage"/>
156-
<Button row="28" col="0" text="get download url" tap="{{ doGetDownloadUrl }}"
157-
class="button button-storage"/>
158-
<Button row="28" col="1" text="delete remote file" tap="{{ doDeleteFile }}"
159-
class="button button-storage"/>
160-
161-
<Label row="29" colSpan="2" text="Analytics" class="subtitle"/>
162-
<Button row="30" col="0" text="log event" tap="{{ doLogAnayticsEvent }}" class="button button-analytics"/>
163-
<Button row="30" col="1" text="set user property" tap="{{ doSetAnalyticsUserProperty }}"
164-
class="button button-analytics"/>
165-
<Button row="31" col="0" text="set Screen A" tap="{{ doSetScreenNameA }}"
166-
class="button button-analytics"/>
167-
<Button row="31" col="1" text="set Screen B" tap="{{ doSetScreenNameB }}"
168-
class="button button-analytics"/>
169-
170-
<Label row="32" colSpan="2" text="AdMob" class="subtitle"/>
171-
<Button row="33" col="0" text="show banner" tap="{{ doShowAdMobBanner }}" class="button button-admob"/>
172-
<Button row="33" col="1" text="show interstitial" tap="{{ doShowAdMobInterstitial }}"
173-
class="button button-admob"/>
174-
<Button row="34" colSpan="2" text="hide banner" tap="{{ doHideAdMobBanner }}"
175-
class="button button-admob"/>
176-
177-
<Label row="35" colSpan="2" text="Firebase Cloud Messaging" class="subtitle"/>
178-
<Button row="36" col="0" text="add push handlers" tap="{{ doRegisterPushHandlers }}"
179-
class="button button-messaging"/>
180-
<Button row="36" col="1" text="get current token" tap="{{ doGetCurrentPushToken }}"
181-
class="button button-messaging"/>
182-
<Button row="37" col="0" text="topic subscribe" tap="{{ doSubscribeToTopic }}"
183-
class="button button-messaging"/>
184-
<Button row="37" col="1" text="topic unsubscribe" tap="{{ doUnsubscribeFromTopic }}"
185-
class="button button-messaging"/>
186-
187-
<Label row="38" colSpan="2" text="Firebase Crash Reporing" class="subtitle"/>
188-
<Button row="39" col="0" text="log message" tap="{{ doLogMessage }}" class="button button-crash"/>
108+
<Button row="12" col="0" text="email login link" tap="{{ doLoginByEmailLink }}" class="button"/>
109+
<Button row="12" col="1" text="send email conf" tap="{{ doSendEmailVerification }}" class="button"/>
110+
111+
<Button row="13" colSpan="2" text="logout" tap="{{ doLogout }}" class="button"/>
112+
113+
<Label row="14" colSpan="2" text="Methods on path /users" class="subtitle"/>
114+
115+
<Button row="15" col="0" text="auto-sync: ON" tap="{{ doKeepUsersInSyncOn }}" class="button button-user"/>
116+
<Button row="15" col="1" text="auto-sync: OFF" tap="{{ doKeepUsersInSyncOff }}" class="button button-user"/>
117+
118+
<Button row="16" col="0" text="add childlistener" tap="{{ doAddChildEventListenerForUsers }}" class="button button-user"/>
119+
<Button row="16" col="1" text="store by push" tap="{{ doUserStoreByPush }}" class="button button-user"/>
120+
121+
<Button row="17" col="0" text="query users once" tap="{{ doQueryUsers }}" class="button button-user"/>
122+
<Button row="17" col="1" text="delete path" tap="{{ doRemoveUsers }}" class="button button-user"/>
123+
124+
<Button row="18" colSpan="2" text="del childlistener" tap="{{ doRemoveChildEventListenerForUsers }}" class="button button-user"/>
125+
126+
<Label row="19" colSpan="2" text="Methods on path /companies" class="subtitle"/>
127+
128+
<Button row="20" col="0" text="add valuelistener" tap="{{ doAddValueEventListenerForCompanies }}" class="button button-company"/>
129+
<Button row="20" col="1" text="store by setValue" tap="{{ doStoreCompaniesBySetValue }}" class="button button-company"/>
130+
131+
<Button row="21" col="0" text="query with range" tap="{{ doQueryBulgarianCompanies }}" class="button button-company"/>
132+
<Button row="21" col="1" text="remove path" tap="{{ doRemoveCompanies }}" class="button button-company"/>
133+
134+
<Button row="22" col="0" text="del valuelistener" tap="{{ doRemoveValueEventListenersForCompanies }}" class="button button-company"/>
135+
<Button row="22" col="1" text="get value" tap="{{ doGetValueForCompanies }}" class="button button-company"/>
136+
137+
<Label row="23" col="0" text="Last update path:" class="message"/>
138+
<Label row="23" col="1" text="{{ path }}" class="message" textWrap="true"/>
139+
140+
<Label row="24" col="0" text="Type:" class="message"/>
141+
<Label row="24" col="1" text="{{ type }}" class="message"/>
142+
143+
<Label row="25" col="0" text="Key:" class="message"/>
144+
<Label row="25" col="1" text="{{ key }}" class="message" textWrap="true"/>
145+
146+
<Label row="26" col="0" text="Value:" class="message"/>
147+
<Label row="26" col="1" text="{{ value }}" class="message" textWrap="true"/>
148+
149+
<Label row="27" colSpan="2" text="Google Cloud Storage" class="subtitle"/>
150+
151+
<Button row="28" col="0" text="upload file" tap="{{ doUploadFile }}" class="button button-storage"/>
152+
<Button row="28" col="1" text="download file" tap="{{ doDownloadFile }}" class="button button-storage"/>
153+
154+
<Button row="29" col="0" text="get download url" tap="{{ doGetDownloadUrl }}" class="button button-storage"/>
155+
<Button row="29" col="1" text="delete remote file" tap="{{ doDeleteFile }}" class="button button-storage"/>
156+
157+
<Label row="30" colSpan="2" text="Analytics" class="subtitle"/>
158+
159+
<Button row="31" col="0" text="log event" tap="{{ doLogAnayticsEvent }}" class="button button-analytics"/>
160+
<Button row="31" col="1" text="set user property" tap="{{ doSetAnalyticsUserProperty }}" class="button button-analytics"/>
161+
162+
<Button row="32" col="0" text="set Screen A" tap="{{ doSetScreenNameA }}" class="button button-analytics"/>
163+
<Button row="32" col="1" text="set Screen B" tap="{{ doSetScreenNameB }}" class="button button-analytics"/>
164+
165+
<Label row="33" colSpan="2" text="AdMob" class="subtitle"/>
166+
167+
<Button row="34" col="0" text="show banner" tap="{{ doShowAdMobBanner }}" class="button button-admob"/>
168+
<Button row="34" col="1" text="show interstitial" tap="{{ doShowAdMobInterstitial }}" class="button button-admob"/>
169+
170+
<Button row="35" colSpan="2" text="hide banner" tap="{{ doHideAdMobBanner }}" class="button button-admob"/>
171+
172+
<Label row="36" colSpan="2" text="Firebase Cloud Messaging" class="subtitle"/>
173+
174+
<Button row="37" col="0" text="add push handlers" tap="{{ doRegisterPushHandlers }}" class="button button-messaging"/>
175+
<Button row="37" col="1" text="get current token" tap="{{ doGetCurrentPushToken }}" class="button button-messaging"/>
176+
177+
<Button row="38" col="0" text="topic subscribe" tap="{{ doSubscribeToTopic }}" class="button button-messaging"/>
178+
<Button row="38" col="1" text="topic unsubscribe" tap="{{ doUnsubscribeFromTopic }}" class="button button-messaging"/>
179+
180+
<Label row="39" colSpan="2" text="Firebase Crash Reporing" class="subtitle"/>
181+
182+
<Button row="40" col="0" text="log message" tap="{{ doLogMessage }}" class="button button-crash"/>
189183
<iOS>
190-
<Button row="39" col="1" text="force crash" tap="{{ doForceCrashIOS }}" class="button button-crash"/>
184+
<Button row="40" col="1" text="force crash :)" tap="{{ doForceCrashIOS }}" class="button button-crash"/>
191185
</iOS>
192186
<Android>
193-
<Button row="39" col="1" text="force crash :)" tap="{{ doForceCrashAndroid }}"
194-
class="button button-crash"/>
187+
<Button row="40" col="1" text="force crash :)" tap="{{ doForceCrashAndroid }}" class="button button-crash"/>
195188
</Android>
196189

197-
<Label row="40" colSpan="2" text="Firebase Invites" class="subtitle"/>
198-
<Button row="41" col="0" text="send invitation" tap="{{ sendInvitation }}" class="button button-invites"/>
199-
<Button row="41" col="1" text="get invitation" tap="{{ getInvitation }}" class="button button-invites"/>
190+
<Label row="41" colSpan="2" text="Firebase Invites" class="subtitle"/>
191+
192+
<Button row="42" col="0" text="send invitation" tap="{{ sendInvitation }}" class="button button-invites"/>
193+
<Button row="42" col="1" text="get invitation" tap="{{ getInvitation }}" class="button button-invites"/>
200194
</GridLayout>
201195

202196
</ScrollView>
203197
</TabViewItem.view>
204198
</TabViewItem>
205199
</TabView.items>
206200
</TabView>
207-
</Page>
201+
</Page>

demo/app/main-view-model.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,41 @@ export class HelloWorldModel extends Observable {
776776
});
777777
}
778778

779+
public doLoginByEmailLink(): void {
780+
prompt(
781+
"The email address to send the link to",
782+
""
783+
).then(promptResult => {
784+
if (!promptResult.result) {
785+
return;
786+
}
787+
788+
console.log(">> using promptResult.text: " + promptResult.text);
789+
firebase.login({
790+
// note that you need to enable phone login in your firebase instance
791+
type: firebase.LoginType.EMAIL_LINK,
792+
emailLinkOptions: {
793+
email: promptResult.text
794+
}
795+
}).then(
796+
result => {
797+
alert({
798+
title: "Email link sent",
799+
message: "Check your email :)",
800+
okButtonText: "Cool"
801+
});
802+
},
803+
errorMessage => {
804+
alert({
805+
title: "Email link login error",
806+
message: errorMessage,
807+
okButtonText: "OK, damn shame"
808+
});
809+
}
810+
);
811+
});
812+
}
813+
779814
public doLoginByFacebook(): void {
780815
firebase.login({
781816
// note that you need to enable Facebook auth in your firebase instance

src/firebase-common.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { prompt } from "tns-core-modules/ui/dialogs";
22
import { firestore } from "./firebase";
3+
import * as applicationSettings from "tns-core-modules/application-settings";
34

45
export const firebase: any = {
56
initialized: false,
@@ -49,7 +50,8 @@ export const firebase: any = {
4950
PHONE: "phone",
5051
CUSTOM: "custom",
5152
FACEBOOK: "facebook",
52-
GOOGLE: "google"
53+
GOOGLE: "google",
54+
EMAIL_LINK: "emailLink"
5355
},
5456
QueryOrderByType: {
5557
KEY: "key",
@@ -97,6 +99,12 @@ export const firebase: any = {
9799
}
98100
});
99101
},
102+
rememberEmailForEmailLinkLogin: (email: string) => {
103+
applicationSettings.setString("FirebasePlugin.EmailLinkLogin", email);
104+
},
105+
getRememberedEmailForEmailLinkLogin: () => {
106+
return applicationSettings.getString("FirebasePlugin.EmailLinkLogin");
107+
},
100108
strongTypeify: value => {
101109
if (value === "true") {
102110
value = true;

src/firebase.d.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,12 @@ export enum LoginType {
3131
* as well as uncommenting the SDK includes in include.gradle (Android) and Podfile (iOS).
3232
* You can pass in an optional 'googleOptions' object to set a 'hostedDomain'.
3333
*/
34-
GOOGLE
34+
GOOGLE,
35+
/**
36+
* This requires you to pass in the 'emailLinkOptions' as well.
37+
* Note that 'Firebase Dynamic Links' must be enabled for this login type to work.
38+
*/
39+
EMAIL_LINK
3540
}
3641

3742
/**
@@ -177,6 +182,10 @@ export interface FirebasePasswordLoginOptions {
177182
password: string;
178183
}
179184

185+
export interface FirebaseEmailLinkLoginOptions {
186+
email: string;
187+
}
188+
180189
export interface FirebasePhoneLoginOptions {
181190
phoneNumber: string;
182191
/**
@@ -218,6 +227,7 @@ export interface FirebaseCustomLoginOptions {
218227
export interface LoginOptions {
219228
type: LoginType;
220229
passwordOptions?: FirebasePasswordLoginOptions;
230+
emailLinkOptions?: FirebaseEmailLinkLoginOptions;
221231
phoneOptions?: FirebasePhoneLoginOptions;
222232
googleOptions?: FirebaseGoogleLoginOptions;
223233
facebookOptions?: FirebaseFacebookLoginOptions;

0 commit comments

Comments
 (0)