b5-api-client 0.0.24 → 0.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -22,8 +22,9 @@ export declare class UserData {
|
|
|
22
22
|
readonly username: string;
|
|
23
23
|
readonly isEmailVerified: boolean;
|
|
24
24
|
readonly idToken: string | null;
|
|
25
|
+
readonly isAdmin: boolean;
|
|
25
26
|
private constructor();
|
|
26
|
-
static create(id: string, email: string, username: string, isEmailVerified: boolean, idToken: string | null): UserData;
|
|
27
|
+
static create(id: string, email: string, username: string, isEmailVerified: boolean, idToken: string | null, isAdmin: boolean): UserData;
|
|
27
28
|
withEmailVerified(): UserData;
|
|
28
29
|
}
|
|
29
30
|
export declare class AuthResult {
|
|
@@ -32,6 +33,7 @@ export declare class AuthResult {
|
|
|
32
33
|
readonly userData: UserData | null;
|
|
33
34
|
readonly error: string | null;
|
|
34
35
|
readonly provider: AuthProvider | null;
|
|
36
|
+
readonly isAdmin: boolean;
|
|
35
37
|
private constructor();
|
|
36
38
|
static success(user: KioscoinUser, userData: UserData, provider: AuthProvider): AuthResult;
|
|
37
39
|
static failure(error: string): AuthResult;
|
|
@@ -39,35 +39,37 @@ class AuthState {
|
|
|
39
39
|
exports.AuthState = AuthState;
|
|
40
40
|
// Enhanced UserData class with additional safety
|
|
41
41
|
class UserData {
|
|
42
|
-
constructor(id, email, username, isEmailVerified, idToken) {
|
|
42
|
+
constructor(id, email, username, isEmailVerified, idToken, isAdmin) {
|
|
43
43
|
this.id = id;
|
|
44
44
|
this.email = email;
|
|
45
45
|
this.username = username;
|
|
46
46
|
this.isEmailVerified = isEmailVerified;
|
|
47
47
|
this.idToken = idToken;
|
|
48
|
+
this.isAdmin = isAdmin;
|
|
48
49
|
}
|
|
49
|
-
static create(id, email, username, isEmailVerified, idToken) {
|
|
50
|
-
return new UserData(id, email, username, isEmailVerified, idToken);
|
|
50
|
+
static create(id, email, username, isEmailVerified, idToken, isAdmin) {
|
|
51
|
+
return new UserData(id, email, username, isEmailVerified, idToken, isAdmin);
|
|
51
52
|
}
|
|
52
53
|
withEmailVerified() {
|
|
53
|
-
return new UserData(this.id, this.email, this.username, true, this.idToken);
|
|
54
|
+
return new UserData(this.id, this.email, this.username, true, this.idToken, this.isAdmin);
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
57
|
exports.UserData = UserData;
|
|
57
58
|
// Enhanced AuthResult class
|
|
58
59
|
class AuthResult {
|
|
59
|
-
constructor(success, user, userData, error, provider) {
|
|
60
|
+
constructor(success, user, userData, error, provider, isAdmin) {
|
|
60
61
|
this.success = success;
|
|
61
62
|
this.user = user;
|
|
62
63
|
this.userData = userData;
|
|
63
64
|
this.error = error;
|
|
64
65
|
this.provider = provider;
|
|
66
|
+
this.isAdmin = isAdmin;
|
|
65
67
|
}
|
|
66
68
|
static success(user, userData, provider) {
|
|
67
|
-
return new AuthResult(true, user, userData, null, provider);
|
|
69
|
+
return new AuthResult(true, user, userData, null, provider, userData.isAdmin);
|
|
68
70
|
}
|
|
69
71
|
static failure(error) {
|
|
70
|
-
return new AuthResult(false, null, null, error, null);
|
|
72
|
+
return new AuthResult(false, null, null, error, null, false);
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
exports.AuthResult = AuthResult;
|
|
@@ -181,7 +183,8 @@ class FirebaseUnifiedService {
|
|
|
181
183
|
id: userCredential.user.uid,
|
|
182
184
|
username: backendUser.username || '',
|
|
183
185
|
email: userCredential.user.email || '',
|
|
184
|
-
idToken: idToken
|
|
186
|
+
idToken: idToken,
|
|
187
|
+
isAdmin: backendUser.admin || false
|
|
185
188
|
});
|
|
186
189
|
return authResult;
|
|
187
190
|
}
|
|
@@ -416,7 +419,7 @@ class FirebaseUnifiedService {
|
|
|
416
419
|
}
|
|
417
420
|
// Helper method to create success AuthResult
|
|
418
421
|
_createSuccessAuthResult(user, backendUser, provider, idToken) {
|
|
419
|
-
const userData = UserData.create(user.uid, user.email || '', backendUser.username || '', user.emailVerified, idToken);
|
|
422
|
+
const userData = UserData.create(user.uid, user.email || '', backendUser.username || '', user.emailVerified, idToken, backendUser.admin || false);
|
|
420
423
|
return AuthResult.success(backendUser, userData, provider);
|
|
421
424
|
}
|
|
422
425
|
// Backend integration methods
|
package/package.json
CHANGED
|
@@ -55,7 +55,8 @@ export class UserData {
|
|
|
55
55
|
public readonly email: string,
|
|
56
56
|
public readonly username: string,
|
|
57
57
|
public readonly isEmailVerified: boolean,
|
|
58
|
-
public readonly idToken: string | null
|
|
58
|
+
public readonly idToken: string | null,
|
|
59
|
+
public readonly isAdmin: boolean
|
|
59
60
|
) { }
|
|
60
61
|
|
|
61
62
|
static create(
|
|
@@ -63,14 +64,16 @@ export class UserData {
|
|
|
63
64
|
email: string,
|
|
64
65
|
username: string,
|
|
65
66
|
isEmailVerified: boolean,
|
|
66
|
-
idToken: string | null
|
|
67
|
+
idToken: string | null,
|
|
68
|
+
isAdmin: boolean
|
|
67
69
|
): UserData {
|
|
68
70
|
return new UserData(
|
|
69
71
|
id,
|
|
70
72
|
email,
|
|
71
73
|
username,
|
|
72
74
|
isEmailVerified,
|
|
73
|
-
idToken
|
|
75
|
+
idToken,
|
|
76
|
+
isAdmin
|
|
74
77
|
);
|
|
75
78
|
}
|
|
76
79
|
|
|
@@ -80,7 +83,8 @@ export class UserData {
|
|
|
80
83
|
this.email,
|
|
81
84
|
this.username,
|
|
82
85
|
true,
|
|
83
|
-
this.idToken
|
|
86
|
+
this.idToken,
|
|
87
|
+
this.isAdmin
|
|
84
88
|
);
|
|
85
89
|
}
|
|
86
90
|
}
|
|
@@ -92,15 +96,16 @@ export class AuthResult {
|
|
|
92
96
|
public readonly user: KioscoinUser | null,
|
|
93
97
|
public readonly userData: UserData | null,
|
|
94
98
|
public readonly error: string | null,
|
|
95
|
-
public readonly provider: AuthProvider | null
|
|
99
|
+
public readonly provider: AuthProvider | null,
|
|
100
|
+
public readonly isAdmin: boolean
|
|
96
101
|
) { }
|
|
97
102
|
|
|
98
103
|
static success(user: KioscoinUser, userData: UserData, provider: AuthProvider): AuthResult {
|
|
99
|
-
return new AuthResult(true, user, userData, null, provider);
|
|
104
|
+
return new AuthResult(true, user, userData, null, provider, userData.isAdmin);
|
|
100
105
|
}
|
|
101
106
|
|
|
102
107
|
static failure(error: string): AuthResult {
|
|
103
|
-
return new AuthResult(false, null, null, error, null);
|
|
108
|
+
return new AuthResult(false, null, null, error, null, false);
|
|
104
109
|
}
|
|
105
110
|
}
|
|
106
111
|
|
|
@@ -220,7 +225,8 @@ export class FirebaseUnifiedService implements LoginService {
|
|
|
220
225
|
id: userCredential.user.uid,
|
|
221
226
|
username: backendUser.username || '',
|
|
222
227
|
email: userCredential.user.email || '',
|
|
223
|
-
idToken: idToken
|
|
228
|
+
idToken: idToken,
|
|
229
|
+
isAdmin: backendUser.admin || false
|
|
224
230
|
});
|
|
225
231
|
return authResult;
|
|
226
232
|
} else {
|
|
@@ -460,7 +466,8 @@ export class FirebaseUnifiedService implements LoginService {
|
|
|
460
466
|
user.email || '',
|
|
461
467
|
backendUser.username || '',
|
|
462
468
|
user.emailVerified,
|
|
463
|
-
idToken
|
|
469
|
+
idToken,
|
|
470
|
+
backendUser.admin || false
|
|
464
471
|
);
|
|
465
472
|
return AuthResult.success(backendUser, userData, provider);
|
|
466
473
|
}
|
package/src/auth/UserContext.ts
CHANGED
|
@@ -1,496 +0,0 @@
|
|
|
1
|
-
import { initializeApp } from "firebase/app";
|
|
2
|
-
import {
|
|
3
|
-
getAuth,
|
|
4
|
-
signInWithEmailAndPassword,
|
|
5
|
-
createUserWithEmailAndPassword,
|
|
6
|
-
sendEmailVerification,
|
|
7
|
-
sendPasswordResetEmail,
|
|
8
|
-
signOut,
|
|
9
|
-
User,
|
|
10
|
-
GoogleAuthProvider,
|
|
11
|
-
FacebookAuthProvider,
|
|
12
|
-
TwitterAuthProvider,
|
|
13
|
-
signInWithPopup,
|
|
14
|
-
isSignInWithEmailLink,
|
|
15
|
-
sendSignInLinkToEmail,
|
|
16
|
-
signInWithEmailLink,
|
|
17
|
-
Auth
|
|
18
|
-
} from "firebase/auth";
|
|
19
|
-
import { getMessaging, getToken, onMessage, MessagePayload } from "firebase/messaging";
|
|
20
|
-
import { CreateUserRequest, KioscoinUser } from "./types";
|
|
21
|
-
import P2PMarketplaceAPIClient from "./P2PMarketplaceAPIClient";
|
|
22
|
-
import { FirebaseLoginServiceConfig, LoginService } from "./auth/LoginService";
|
|
23
|
-
import { userContext } from './auth/UserContext';
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
// Auth provider type for better type safety
|
|
27
|
-
export enum AuthProvider {
|
|
28
|
-
EMAIL = 'EMAIL',
|
|
29
|
-
GOOGLE = 'GOOGLE',
|
|
30
|
-
FACEBOOK = 'FACEBOOK',
|
|
31
|
-
TWITTER = 'TWITTER'
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Immutable auth state class
|
|
35
|
-
export class AuthState {
|
|
36
|
-
private constructor(
|
|
37
|
-
public readonly isAuthenticated: boolean,
|
|
38
|
-
public readonly user: UserData | null,
|
|
39
|
-
public readonly provider: AuthProvider | null
|
|
40
|
-
) { }
|
|
41
|
-
|
|
42
|
-
static authenticated(user: UserData, provider: AuthProvider): AuthState {
|
|
43
|
-
return new AuthState(true, user, provider);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
static unauthenticated(): AuthState {
|
|
47
|
-
return new AuthState(false, null, null);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Enhanced UserData class with additional safety
|
|
52
|
-
export class UserData {
|
|
53
|
-
private constructor(
|
|
54
|
-
public readonly id: string,
|
|
55
|
-
public readonly email: string,
|
|
56
|
-
public readonly username: string,
|
|
57
|
-
public readonly isEmailVerified: boolean,
|
|
58
|
-
public readonly idToken: string | null
|
|
59
|
-
) { }
|
|
60
|
-
|
|
61
|
-
static create(
|
|
62
|
-
id: string,
|
|
63
|
-
email: string,
|
|
64
|
-
username: string,
|
|
65
|
-
isEmailVerified: boolean,
|
|
66
|
-
idToken: string | null
|
|
67
|
-
): UserData {
|
|
68
|
-
return new UserData(
|
|
69
|
-
id,
|
|
70
|
-
email,
|
|
71
|
-
username,
|
|
72
|
-
isEmailVerified,
|
|
73
|
-
idToken
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
withEmailVerified(): UserData {
|
|
78
|
-
return new UserData(
|
|
79
|
-
this.id,
|
|
80
|
-
this.email,
|
|
81
|
-
this.username,
|
|
82
|
-
true,
|
|
83
|
-
this.idToken
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Enhanced AuthResult class
|
|
89
|
-
export class AuthResult {
|
|
90
|
-
private constructor(
|
|
91
|
-
public readonly success: boolean,
|
|
92
|
-
public readonly user: KioscoinUser | null,
|
|
93
|
-
public readonly userData: UserData | null,
|
|
94
|
-
public readonly error: string | null,
|
|
95
|
-
public readonly provider: AuthProvider | null
|
|
96
|
-
) { }
|
|
97
|
-
|
|
98
|
-
static success(user: KioscoinUser, userData: UserData, provider: AuthProvider): AuthResult {
|
|
99
|
-
return new AuthResult(true, user, userData, null, provider);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
static failure(error: string): AuthResult {
|
|
103
|
-
return new AuthResult(false, null, null, error, null);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export interface FirebaseConfig {
|
|
108
|
-
apiKey: string;
|
|
109
|
-
authDomain: string;
|
|
110
|
-
projectId: string;
|
|
111
|
-
storageBucket: string;
|
|
112
|
-
messagingSenderId: string;
|
|
113
|
-
appId: string;
|
|
114
|
-
measurementId?: string;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export class FirebaseUnifiedService implements LoginService {
|
|
118
|
-
private app: ReturnType<typeof initializeApp> | null = null;
|
|
119
|
-
private messaging: ReturnType<typeof getMessaging> | null = null;
|
|
120
|
-
private auth: Auth | null = null;
|
|
121
|
-
private readonly actionCodeSettings: { url: string; handleCodeInApp: boolean };
|
|
122
|
-
private client: P2PMarketplaceAPIClient;
|
|
123
|
-
|
|
124
|
-
constructor(client: P2PMarketplaceAPIClient, config?: FirebaseLoginServiceConfig) {
|
|
125
|
-
this.client = client;
|
|
126
|
-
this.actionCodeSettings = config?.actionCodeSettings ?? {
|
|
127
|
-
url: 'http://localhost:3000/auth/verify-email',
|
|
128
|
-
handleCodeInApp: true,
|
|
129
|
-
};
|
|
130
|
-
this.initializeFirebase();
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
private async initializeFirebase() {
|
|
134
|
-
try {
|
|
135
|
-
const firebaseConfig = await this.fetchFirebaseConfig();
|
|
136
|
-
this.app = initializeApp(firebaseConfig);
|
|
137
|
-
this.auth = getAuth(this.app);
|
|
138
|
-
} catch (error) {
|
|
139
|
-
console.error("Failed to initialize Firebase app:", error);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
private async fetchFirebaseConfig(): Promise<FirebaseConfig> {
|
|
144
|
-
try {
|
|
145
|
-
const response = await this.client.getConfig<{ firebase: FirebaseConfig }>();
|
|
146
|
-
return response.config.firebase;
|
|
147
|
-
} catch (error) {
|
|
148
|
-
console.error("Error fetching Firebase configuration:", error);
|
|
149
|
-
throw new Error("Failed to initialize Firebase configuration");
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Messaging methods
|
|
154
|
-
public async requestNotificationPermission(): Promise<string | null> {
|
|
155
|
-
if (!this.app) {
|
|
156
|
-
await this.initializeFirebase();
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (!this.messaging) {
|
|
160
|
-
console.warn("Messaging is not available");
|
|
161
|
-
return null;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
try {
|
|
165
|
-
const permission = await Notification.requestPermission();
|
|
166
|
-
if (permission === "granted") {
|
|
167
|
-
const token = await getToken(this.messaging, {
|
|
168
|
-
vapidKey: process.env.REACT_APP_FIREBASE_VAPID_KEY,
|
|
169
|
-
});
|
|
170
|
-
return token;
|
|
171
|
-
}
|
|
172
|
-
return null;
|
|
173
|
-
} catch (error) {
|
|
174
|
-
console.error("Failed to get notification token:", error);
|
|
175
|
-
return null;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
async fetchToken(): Promise<string | null> {
|
|
179
|
-
try {
|
|
180
|
-
if (!this.messaging && this.app) {
|
|
181
|
-
this.messaging = getMessaging(this.app);
|
|
182
|
-
}
|
|
183
|
-
if (this.messaging) {
|
|
184
|
-
const currentToken = await getToken(this.messaging);
|
|
185
|
-
return currentToken;
|
|
186
|
-
}
|
|
187
|
-
return null;
|
|
188
|
-
} catch (error) {
|
|
189
|
-
console.error("An error occurred while retrieving token. ", error);
|
|
190
|
-
return null;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
onMessageListener(callback: (payload: any) => void) {
|
|
195
|
-
if (!this.messaging && this.app) {
|
|
196
|
-
this.messaging = getMessaging(this.app);
|
|
197
|
-
}
|
|
198
|
-
if (this.messaging) {
|
|
199
|
-
onMessage(this.messaging, callback);
|
|
200
|
-
} else {
|
|
201
|
-
console.error("Messaging is not initialized.");
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// Authentication methods
|
|
206
|
-
async signInWithEmail(email: string, password: string): Promise<AuthResult> {
|
|
207
|
-
try {
|
|
208
|
-
if (!this.auth) {
|
|
209
|
-
console.error("Firebase Auth not initialized");
|
|
210
|
-
return AuthResult.failure("Firebase Auth not initialized");
|
|
211
|
-
}
|
|
212
|
-
const userCredential = await signInWithEmailAndPassword(this.auth, email, password);
|
|
213
|
-
const idToken = await userCredential.user.getIdToken();
|
|
214
|
-
const backendUser = await this.getUserFromBackend(userCredential.user.uid, idToken);
|
|
215
|
-
|
|
216
|
-
if (backendUser) {
|
|
217
|
-
const authResult = this._createSuccessAuthResult(userCredential.user, backendUser, AuthProvider.EMAIL, idToken);
|
|
218
|
-
// Update UserContext
|
|
219
|
-
userContext.setUser({
|
|
220
|
-
id: userCredential.user.uid,
|
|
221
|
-
username: backendUser.username || '',
|
|
222
|
-
email: userCredential.user.email || '',
|
|
223
|
-
idToken: idToken
|
|
224
|
-
});
|
|
225
|
-
return authResult;
|
|
226
|
-
} else {
|
|
227
|
-
return AuthResult.failure('User not found in backend');
|
|
228
|
-
}
|
|
229
|
-
} catch (error: any) {
|
|
230
|
-
console.error('Detailed error signing in with email:', {
|
|
231
|
-
code: error.code,
|
|
232
|
-
message: error.message,
|
|
233
|
-
fullError: error
|
|
234
|
-
});
|
|
235
|
-
return AuthResult.failure(error.message || 'Authentication failed');
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
async createUserWithEmail(email: string, password: string, username: string): Promise<AuthResult> {
|
|
240
|
-
try {
|
|
241
|
-
if (!this.auth) {
|
|
242
|
-
return AuthResult.failure("Firebase Auth not initialized");
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// First create the user in Firebase
|
|
246
|
-
const userCredential = await createUserWithEmailAndPassword(this.auth, email, password);
|
|
247
|
-
const user = userCredential.user;
|
|
248
|
-
const idToken = await user.getIdToken();
|
|
249
|
-
// Send email verification
|
|
250
|
-
await sendEmailVerification(user);
|
|
251
|
-
|
|
252
|
-
const backendUser = await this.createUserInBackend(user.uid, username, idToken);
|
|
253
|
-
|
|
254
|
-
if (backendUser) {
|
|
255
|
-
return this._createSuccessAuthResult(user, backendUser, AuthProvider.EMAIL, idToken);
|
|
256
|
-
} else {
|
|
257
|
-
return AuthResult.failure('Failed to create user in backend');
|
|
258
|
-
}
|
|
259
|
-
} catch (error: any) {
|
|
260
|
-
console.error('Error creating user with email:', error);
|
|
261
|
-
return AuthResult.failure(error.message || 'User creation failed');
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
async signInWithGoogle(): Promise<AuthResult> {
|
|
266
|
-
try {
|
|
267
|
-
if (!this.auth) {
|
|
268
|
-
return AuthResult.failure("Firebase Auth not initialized");
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
const provider = new GoogleAuthProvider();
|
|
272
|
-
const userCredential = await signInWithPopup(this.auth, provider);
|
|
273
|
-
const user = userCredential.user;
|
|
274
|
-
|
|
275
|
-
// Get or create user in your Kotlin backend
|
|
276
|
-
const backendUser = await this.getUserFromBackend(user.uid, user.displayName || '');
|
|
277
|
-
const idToken = await user.getIdToken();
|
|
278
|
-
if (backendUser) {
|
|
279
|
-
// Use the new helper method
|
|
280
|
-
return this._createSuccessAuthResult(user, backendUser, AuthProvider.GOOGLE, idToken);
|
|
281
|
-
} else {
|
|
282
|
-
return AuthResult.failure('Failed to get or create user in backend');
|
|
283
|
-
}
|
|
284
|
-
} catch (error: any) {
|
|
285
|
-
console.error('Error signing in with Google:', error);
|
|
286
|
-
return AuthResult.failure(error.message || 'Google authentication failed');
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
async signInWithFacebook(): Promise<AuthResult> {
|
|
291
|
-
try {
|
|
292
|
-
if (!this.auth) {
|
|
293
|
-
return AuthResult.failure("Firebase Auth not initialized");
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
const provider = new FacebookAuthProvider();
|
|
297
|
-
const userCredential = await signInWithPopup(this.auth, provider);
|
|
298
|
-
const user = userCredential.user;
|
|
299
|
-
|
|
300
|
-
// Get or create user in your Kotlin backend
|
|
301
|
-
const backendUser = await this.getUserFromBackend(user.uid, user.displayName || '');
|
|
302
|
-
const idToken = await user.getIdToken();
|
|
303
|
-
if (backendUser) {
|
|
304
|
-
// Use the new helper method
|
|
305
|
-
return this._createSuccessAuthResult(user, backendUser, AuthProvider.FACEBOOK, idToken);
|
|
306
|
-
} else {
|
|
307
|
-
return AuthResult.failure('Failed to get or create user in backend');
|
|
308
|
-
}
|
|
309
|
-
} catch (error: any) {
|
|
310
|
-
console.error('Error signing in with Facebook:', error);
|
|
311
|
-
return AuthResult.failure(error.message || 'Facebook authentication failed');
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
async signInWithTwitter(): Promise<AuthResult> {
|
|
316
|
-
try {
|
|
317
|
-
if (!this.auth) {
|
|
318
|
-
return AuthResult.failure("Firebase Auth not initialized");
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
const provider = new TwitterAuthProvider();
|
|
322
|
-
const userCredential = await signInWithPopup(this.auth, provider);
|
|
323
|
-
const user = userCredential.user;
|
|
324
|
-
|
|
325
|
-
// Get or create user in your Kotlin backend
|
|
326
|
-
const backendUser = await this.getUserFromBackend(user.uid, user.displayName || '');
|
|
327
|
-
const idToken = await user.getIdToken();
|
|
328
|
-
if (backendUser) {
|
|
329
|
-
// Use the new helper method
|
|
330
|
-
return this._createSuccessAuthResult(user, backendUser, AuthProvider.TWITTER, idToken);
|
|
331
|
-
} else {
|
|
332
|
-
return AuthResult.failure('Failed to get or create user in backend');
|
|
333
|
-
}
|
|
334
|
-
} catch (error: any) {
|
|
335
|
-
console.error('Error signing in with Twitter:', error);
|
|
336
|
-
return AuthResult.failure(error.message || 'Twitter authentication failed');
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
async sendEmailVerification(): Promise<boolean> {
|
|
341
|
-
try {
|
|
342
|
-
if (!this.auth) {
|
|
343
|
-
return false;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
const user = this.auth.currentUser;
|
|
347
|
-
if (user) {
|
|
348
|
-
await sendEmailVerification(user);
|
|
349
|
-
return true;
|
|
350
|
-
}
|
|
351
|
-
return false;
|
|
352
|
-
} catch (error) {
|
|
353
|
-
console.error('Error sending email verification:', error);
|
|
354
|
-
return false;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
async sendPasswordResetEmail(email: string): Promise<boolean> {
|
|
359
|
-
try {
|
|
360
|
-
if (!this.auth) {
|
|
361
|
-
return false;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
await sendPasswordResetEmail(this.auth, email);
|
|
365
|
-
return true;
|
|
366
|
-
} catch (error) {
|
|
367
|
-
console.error('Error sending password reset email:', error);
|
|
368
|
-
return false;
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
async signOut(): Promise<void> {
|
|
373
|
-
try {
|
|
374
|
-
if (!this.auth) {
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
await signOut(this.auth);
|
|
379
|
-
// Clear UserContext
|
|
380
|
-
userContext.clearUser();
|
|
381
|
-
} catch (error) {
|
|
382
|
-
console.error('Error signing out:', error);
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
getCurrentUser(): User | null {
|
|
387
|
-
if (!this.auth) {
|
|
388
|
-
return null;
|
|
389
|
-
}
|
|
390
|
-
return this.auth.currentUser;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
async sendSignInLinkToEmail(email: string): Promise<boolean> {
|
|
394
|
-
try {
|
|
395
|
-
if (!this.auth) {
|
|
396
|
-
return false;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
await sendSignInLinkToEmail(this.auth, email, this.actionCodeSettings);
|
|
400
|
-
// Save the email locally to use it later when the user clicks the link
|
|
401
|
-
window.localStorage.setItem('emailForSignIn', email);
|
|
402
|
-
return true;
|
|
403
|
-
} catch (error: any) {
|
|
404
|
-
console.error('Error sending sign-in link to email:', error);
|
|
405
|
-
return false;
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
isSignInWithEmailLink(): boolean {
|
|
410
|
-
if (!this.auth) {
|
|
411
|
-
return false;
|
|
412
|
-
}
|
|
413
|
-
return isSignInWithEmailLink(this.auth, window.location.href);
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
async signInWithEmailLink(email: string): Promise<AuthResult> {
|
|
417
|
-
try {
|
|
418
|
-
if (!this.auth) {
|
|
419
|
-
return AuthResult.failure("Firebase Auth not initialized");
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
if (!this.isSignInWithEmailLink()) {
|
|
423
|
-
return AuthResult.failure("Invalid sign-in link");
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
const userCredential = await signInWithEmailLink(this.auth, email, window.location.href);
|
|
427
|
-
const user = userCredential.user;
|
|
428
|
-
|
|
429
|
-
// Clear the email from localStorage
|
|
430
|
-
window.localStorage.removeItem('emailForSignIn');
|
|
431
|
-
|
|
432
|
-
// Get or create user in your Kotlin backend
|
|
433
|
-
const backendUser = await this.getUserFromBackend(user.uid, user.displayName || '');
|
|
434
|
-
const idToken = await user.getIdToken();
|
|
435
|
-
if (backendUser) {
|
|
436
|
-
// Use the new helper method
|
|
437
|
-
return this._createSuccessAuthResult(user, backendUser, AuthProvider.EMAIL, idToken);
|
|
438
|
-
} else {
|
|
439
|
-
return AuthResult.failure('Failed to get or create user in backend');
|
|
440
|
-
}
|
|
441
|
-
} catch (error: any) {
|
|
442
|
-
console.error('Error signing in with email link:', error);
|
|
443
|
-
return AuthResult.failure(error.message || 'Email link authentication failed');
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
getEmailForSignIn(): string | null {
|
|
448
|
-
return window.localStorage.getItem('emailForSignIn');
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
// Helper method to create success AuthResult
|
|
452
|
-
private _createSuccessAuthResult(
|
|
453
|
-
user: User,
|
|
454
|
-
backendUser: KioscoinUser,
|
|
455
|
-
provider: AuthProvider,
|
|
456
|
-
idToken: string
|
|
457
|
-
): AuthResult {
|
|
458
|
-
const userData = UserData.create(
|
|
459
|
-
user.uid,
|
|
460
|
-
user.email || '',
|
|
461
|
-
backendUser.username || '',
|
|
462
|
-
user.emailVerified,
|
|
463
|
-
idToken
|
|
464
|
-
);
|
|
465
|
-
return AuthResult.success(backendUser, userData, provider);
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
// Backend integration methods
|
|
469
|
-
private async getUserFromBackend(userId: string, loginId: string): Promise<KioscoinUser | null> {
|
|
470
|
-
try {
|
|
471
|
-
const response = await this.client.getUser(userId, {
|
|
472
|
-
Authorization: `Bearer ${loginId}`,
|
|
473
|
-
});
|
|
474
|
-
return response.users[0];
|
|
475
|
-
} catch (error) {
|
|
476
|
-
console.error('Error getting user from backend:', error);
|
|
477
|
-
return null;
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
private async createUserInBackend(userId: string, username: string, idToken: string): Promise<KioscoinUser | null> {
|
|
482
|
-
try {
|
|
483
|
-
const createUserRequest: CreateUserRequest = {
|
|
484
|
-
id: userId,
|
|
485
|
-
username: username
|
|
486
|
-
}
|
|
487
|
-
const response = await this.client.createUser(createUserRequest, {
|
|
488
|
-
Authorization: `Bearer ${idToken}`
|
|
489
|
-
});
|
|
490
|
-
return response.users[0];
|
|
491
|
-
} catch (error) {
|
|
492
|
-
console.error('Error creating user in backend:', error);
|
|
493
|
-
return null;
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
}
|