b5-api-client 0.0.23 → 0.0.24
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.
- package/dist/FirebaseLoginService.d.ts +76 -0
- package/dist/FirebaseLoginService.js +456 -0
- package/dist/UserContext.d.ts +20 -0
- package/dist/UserContext.js +26 -0
- package/dist/auth/FirebaseLoginService.d.ts +76 -0
- package/dist/auth/FirebaseLoginService.js +456 -0
- package/dist/auth/LoginService.d.ts +21 -0
- package/dist/auth/LoginService.js +12 -0
- package/dist/auth/UserContext.d.ts +20 -0
- package/dist/auth/UserContext.js +26 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +7 -1
- package/package.json +3 -2
- package/src/FirebaseLoginService.ts +496 -0
- package/src/auth/FirebaseLoginService.ts +496 -0
- package/src/auth/LoginService.ts +35 -0
- package/src/auth/UserContext.ts +41 -0
- package/src/index.ts +4 -1
|
@@ -0,0 +1,496 @@
|
|
|
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
|
+
}
|