b5-api-client 0.0.26 → 0.0.27
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/P2PMarketplaceAPIClient.d.ts +11 -3
- package/dist/P2PMarketplaceAPIClient.js +79 -59
- package/dist/auth/FirebaseLoginService.d.ts +9 -0
- package/dist/auth/FirebaseLoginService.js +178 -46
- package/dist/auth/LoginService.d.ts +2 -0
- package/dist/types.d.ts +5 -1
- package/package.json +1 -1
- package/src/P2PMarketplaceAPIClient.ts +93 -58
- package/src/auth/FirebaseLoginService.ts +219 -49
- package/src/auth/LoginService.ts +2 -0
- package/src/types.ts +6 -1
|
@@ -1,10 +1,19 @@
|
|
|
1
|
-
import { CreateOrderRequest, CreateUserRequest, Order, OrderResponse, TakeOrderRequest, TestEventParams, UpdateOrderRequest, TransactionStatusResponse, RateUserRequest, OrderEventsResponse, PushNotificationsRegisterRequest, ConfigResponse, DashboardMetricsResponse, UsersResponse, GetOrdersParams, CreateDisputeRequest, DisputesResponse, OrderOffersResponse, TransactionRequest, KioscoinOperationResponse, UpdateUserSettingsRequest, NotificationsResponse } from './types';
|
|
1
|
+
import { CreateOrderRequest, CreateUserRequest, Order, OrderResponse, TakeOrderRequest, TestEventParams, UpdateOrderRequest, TransactionStatusResponse, RateUserRequest, OrderEventsResponse, PushNotificationsRegisterRequest, ConfigResponse, DashboardMetricsResponse, UsersResponse, GetOrdersParams, CreateDisputeRequest, DisputesResponse, OrderOffersResponse, TransactionRequest, KioscoinOperationResponse, UpdateUserSettingsRequest, NotificationsResponse, VerifyEmailRequest } from './types';
|
|
2
|
+
export interface AuthTokenProvider {
|
|
3
|
+
getToken(): Promise<string | null>;
|
|
4
|
+
refreshToken(): Promise<string | null>;
|
|
5
|
+
onRefreshFailure?(error: unknown): void;
|
|
6
|
+
}
|
|
2
7
|
declare class P2PMarketplaceAPIClient {
|
|
3
8
|
private readonly client;
|
|
4
9
|
private readonly defaultHeaders;
|
|
10
|
+
private authTokenProvider?;
|
|
11
|
+
private refreshTokenPromise?;
|
|
5
12
|
constructor(baseURL: string, timeout?: number);
|
|
13
|
+
setAuthTokenProvider(provider?: AuthTokenProvider): void;
|
|
6
14
|
private mergeHeaders;
|
|
7
15
|
private createConfig;
|
|
16
|
+
private getRefreshedToken;
|
|
8
17
|
get<T>(url: string, headers?: Record<string, string>): Promise<T>;
|
|
9
18
|
post<T>(url: string, data: any, headers?: Record<string, string>): Promise<T>;
|
|
10
19
|
getOrders(props: GetOrdersParams, headers?: Record<string, string>): Promise<OrderResponse>;
|
|
@@ -16,6 +25,7 @@ declare class P2PMarketplaceAPIClient {
|
|
|
16
25
|
getUser(userId: string, headers?: Record<string, string>): Promise<UsersResponse>;
|
|
17
26
|
rateUser(rateUserRequest: RateUserRequest, headers?: Record<string, string>): Promise<any>;
|
|
18
27
|
updateUserSettings(request: UpdateUserSettingsRequest, headers?: Record<string, string>): Promise<UsersResponse>;
|
|
28
|
+
verifyUserEmail(request: VerifyEmailRequest, headers?: Record<string, string>): Promise<UsersResponse>;
|
|
19
29
|
registerPushToken(registerRequest: PushNotificationsRegisterRequest, headers?: Record<string, string>): Promise<any>;
|
|
20
30
|
listNotifications(limit?: number, offset?: number, headers?: Record<string, string>): Promise<NotificationsResponse>;
|
|
21
31
|
markNotificationAsRead(notificationId: string, headers?: Record<string, string>): Promise<NotificationsResponse>;
|
|
@@ -24,8 +34,6 @@ declare class P2PMarketplaceAPIClient {
|
|
|
24
34
|
getDashboardMetrics(headers?: Record<string, string>): Promise<DashboardMetricsResponse>;
|
|
25
35
|
getOrderOffers(headers?: Record<string, string>): Promise<OrderOffersResponse>;
|
|
26
36
|
pointOfSaleTransact(request: TransactionRequest, headers?: Record<string, string>): Promise<KioscoinOperationResponse>;
|
|
27
|
-
testLockFunds(order: Order, testParams?: TestEventParams, headers?: Record<string, string>): Promise<void>;
|
|
28
|
-
testReleaseFunds(order: Order, testParams?: TestEventParams, headers?: Record<string, string>): Promise<void>;
|
|
29
37
|
releaseFunds(order: Order, testParams?: TestEventParams, headers?: Record<string, string>): Promise<string>;
|
|
30
38
|
getTransactionStatus(txHash: string, headers?: Record<string, string>): Promise<TransactionStatusResponse>;
|
|
31
39
|
createDispute(request: CreateDisputeRequest, headers?: Record<string, string>): Promise<DisputesResponse>;
|
|
@@ -25,12 +25,29 @@ class P2PMarketplaceAPIClient {
|
|
|
25
25
|
'x-blockchain': 'rsk_testnet'
|
|
26
26
|
};
|
|
27
27
|
// Add a request interceptor to transform request data to snake_case
|
|
28
|
-
this.client.interceptors.request.use((config) => {
|
|
28
|
+
this.client.interceptors.request.use((config) => __awaiter(this, void 0, void 0, function* () {
|
|
29
29
|
if (config.data) {
|
|
30
30
|
config.data = toSnakeCase(config.data);
|
|
31
31
|
}
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
const provider = this.authTokenProvider;
|
|
33
|
+
if (!provider) {
|
|
34
|
+
return config;
|
|
35
|
+
}
|
|
36
|
+
return provider
|
|
37
|
+
.getToken()
|
|
38
|
+
.then((token) => {
|
|
39
|
+
var _a;
|
|
40
|
+
if (token) {
|
|
41
|
+
config.headers = (_a = config.headers) !== null && _a !== void 0 ? _a : {};
|
|
42
|
+
config.headers['Authorization'] = `Bearer ${token}`;
|
|
43
|
+
}
|
|
44
|
+
return config;
|
|
45
|
+
})
|
|
46
|
+
.catch((error) => {
|
|
47
|
+
console.warn('[P2PMarketplaceAPIClient] Failed to obtain auth token before request:', error);
|
|
48
|
+
return config;
|
|
49
|
+
});
|
|
50
|
+
}), (error) => {
|
|
34
51
|
return Promise.reject(error);
|
|
35
52
|
});
|
|
36
53
|
// Add a response interceptor to transform response data to camelCase
|
|
@@ -39,9 +56,37 @@ class P2PMarketplaceAPIClient {
|
|
|
39
56
|
response.data = toCamelCase(response.data);
|
|
40
57
|
}
|
|
41
58
|
return response;
|
|
42
|
-
}, (error) => {
|
|
43
|
-
|
|
44
|
-
|
|
59
|
+
}, (error) => __awaiter(this, void 0, void 0, function* () {
|
|
60
|
+
var _a, _b;
|
|
61
|
+
const { response, config } = error;
|
|
62
|
+
if (!this.authTokenProvider || (response === null || response === void 0 ? void 0 : response.status) !== 401 || !config) {
|
|
63
|
+
return Promise.reject(error);
|
|
64
|
+
}
|
|
65
|
+
const originalRequest = config;
|
|
66
|
+
if (originalRequest._retry) {
|
|
67
|
+
return Promise.reject(error);
|
|
68
|
+
}
|
|
69
|
+
originalRequest._retry = true;
|
|
70
|
+
try {
|
|
71
|
+
const newToken = yield this.getRefreshedToken();
|
|
72
|
+
if (!newToken) {
|
|
73
|
+
return Promise.reject(error);
|
|
74
|
+
}
|
|
75
|
+
originalRequest.headers = (_a = originalRequest.headers) !== null && _a !== void 0 ? _a : {};
|
|
76
|
+
originalRequest.headers['Authorization'] = `Bearer ${newToken}`;
|
|
77
|
+
return this.client(originalRequest);
|
|
78
|
+
}
|
|
79
|
+
catch (refreshError) {
|
|
80
|
+
if ((_b = this.authTokenProvider) === null || _b === void 0 ? void 0 : _b.onRefreshFailure) {
|
|
81
|
+
this.authTokenProvider.onRefreshFailure(refreshError);
|
|
82
|
+
}
|
|
83
|
+
return Promise.reject(error);
|
|
84
|
+
}
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
setAuthTokenProvider(provider) {
|
|
88
|
+
this.authTokenProvider = provider;
|
|
89
|
+
this.refreshTokenPromise = undefined;
|
|
45
90
|
}
|
|
46
91
|
mergeHeaders(customHeaders) {
|
|
47
92
|
return Object.assign(Object.assign({}, this.defaultHeaders), customHeaders);
|
|
@@ -51,6 +96,28 @@ class P2PMarketplaceAPIClient {
|
|
|
51
96
|
headers: this.mergeHeaders(headers)
|
|
52
97
|
};
|
|
53
98
|
}
|
|
99
|
+
getRefreshedToken() {
|
|
100
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
101
|
+
if (!this.authTokenProvider) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
if (!this.refreshTokenPromise) {
|
|
105
|
+
this.refreshTokenPromise = this.authTokenProvider
|
|
106
|
+
.refreshToken()
|
|
107
|
+
.catch((error) => {
|
|
108
|
+
var _a;
|
|
109
|
+
if ((_a = this.authTokenProvider) === null || _a === void 0 ? void 0 : _a.onRefreshFailure) {
|
|
110
|
+
this.authTokenProvider.onRefreshFailure(error);
|
|
111
|
+
}
|
|
112
|
+
throw error;
|
|
113
|
+
})
|
|
114
|
+
.finally(() => {
|
|
115
|
+
this.refreshTokenPromise = undefined;
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return this.refreshTokenPromise;
|
|
119
|
+
});
|
|
120
|
+
}
|
|
54
121
|
get(url, headers) {
|
|
55
122
|
return __awaiter(this, void 0, void 0, function* () {
|
|
56
123
|
const config = this.createConfig(headers);
|
|
@@ -157,6 +224,12 @@ class P2PMarketplaceAPIClient {
|
|
|
157
224
|
return this.post(url, request, headers);
|
|
158
225
|
});
|
|
159
226
|
}
|
|
227
|
+
verifyUserEmail(request, headers) {
|
|
228
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
229
|
+
const url = '/api/users/verify_email';
|
|
230
|
+
return this.post(url, request, headers);
|
|
231
|
+
});
|
|
232
|
+
}
|
|
160
233
|
registerPushToken(registerRequest, headers) {
|
|
161
234
|
return __awaiter(this, void 0, void 0, function* () {
|
|
162
235
|
const url = `/api/notifications/register-push`;
|
|
@@ -205,59 +278,6 @@ class P2PMarketplaceAPIClient {
|
|
|
205
278
|
return this.post(url, request, headers);
|
|
206
279
|
});
|
|
207
280
|
}
|
|
208
|
-
testLockFunds(order, testParams, headers) {
|
|
209
|
-
var _a, _b, _c, _d;
|
|
210
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
211
|
-
const orderEvent = {
|
|
212
|
-
type: "LOCKED",
|
|
213
|
-
orderId: (_a = order.id) !== null && _a !== void 0 ? _a : "",
|
|
214
|
-
buyerAddress: (_b = order.buyerAddress) !== null && _b !== void 0 ? _b : "",
|
|
215
|
-
amount: (_d = (_c = order.amount) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : "0",
|
|
216
|
-
transaction: {
|
|
217
|
-
hash: "0x976d8c61b958e286d907a2e1c5ffde8c9316800ab4de1396a54927a39dc533a2",
|
|
218
|
-
},
|
|
219
|
-
tokenContractAddress: "0xee5e8291b551603a19ef41eea69ae49592ed14f8",
|
|
220
|
-
buyerHash: "02809d5cc2ec09a7503ef77358654a5bfc958e08c04ecb33f412884c0933be68",
|
|
221
|
-
sellerAddress: "0x2A4E89D18C2742FEDC65444d339cC5fAF3dE4dF1",
|
|
222
|
-
sellerHash: "4b3560738b8e3cb8a0a30ac664b12de2ace977c62ade94bc08a37fe5b93bf34b",
|
|
223
|
-
fee: "30000000000000000",
|
|
224
|
-
timestamp: new Date().toISOString(),
|
|
225
|
-
};
|
|
226
|
-
const url = "api/events/simulate/lock";
|
|
227
|
-
try {
|
|
228
|
-
yield this.post(url, orderEvent, headers);
|
|
229
|
-
}
|
|
230
|
-
catch (error) {
|
|
231
|
-
console.error("Error locking funds:", error);
|
|
232
|
-
throw new Error("Failed to lock funds");
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
testReleaseFunds(order, testParams, headers) {
|
|
237
|
-
var _a, _b, _c, _d;
|
|
238
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
239
|
-
const releaseOrderEvent = {
|
|
240
|
-
type: "RELEASED",
|
|
241
|
-
orderId: (_a = order.id) !== null && _a !== void 0 ? _a : "",
|
|
242
|
-
buyerAddress: (_b = order.buyerAddress) !== null && _b !== void 0 ? _b : "",
|
|
243
|
-
amount: (_d = (_c = order.amount) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : "0",
|
|
244
|
-
transaction: {
|
|
245
|
-
hash: "0xeab4797bf0e13dff0bda481503a544698127c5f97dd826c465ebdb41bcfec3f5",
|
|
246
|
-
},
|
|
247
|
-
tokenContractAddress: "0xee5e8291b551603a19ef41eea69ae49592ed14f8",
|
|
248
|
-
adminAction: true,
|
|
249
|
-
timestamp: new Date().toISOString(),
|
|
250
|
-
};
|
|
251
|
-
const url = "api/events/simulate/release";
|
|
252
|
-
try {
|
|
253
|
-
yield this.post(url, releaseOrderEvent, headers);
|
|
254
|
-
}
|
|
255
|
-
catch (error) {
|
|
256
|
-
console.error("Error releasing funds:", error);
|
|
257
|
-
throw new Error("Failed to release funds");
|
|
258
|
-
}
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
281
|
releaseFunds(order, testParams, headers) {
|
|
262
282
|
var _a;
|
|
263
283
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -52,10 +52,18 @@ export declare class FirebaseUnifiedService implements LoginService {
|
|
|
52
52
|
private messaging;
|
|
53
53
|
private auth;
|
|
54
54
|
private readonly actionCodeSettings;
|
|
55
|
+
private readonly emailVerificationUrl;
|
|
56
|
+
private readonly emailVerificationContinueUrl?;
|
|
55
57
|
private client;
|
|
58
|
+
private readonly initializationPromise;
|
|
56
59
|
constructor(client: P2PMarketplaceAPIClient, config?: FirebaseLoginServiceConfig);
|
|
57
60
|
private initializeFirebase;
|
|
61
|
+
private ensureAuthInstance;
|
|
62
|
+
private buildAuthTokenProvider;
|
|
58
63
|
private fetchFirebaseConfig;
|
|
64
|
+
private buildEmailVerificationSettings;
|
|
65
|
+
private buildEmailVerificationUrl;
|
|
66
|
+
private ensureBackendVerification;
|
|
59
67
|
requestNotificationPermission(): Promise<string | null>;
|
|
60
68
|
fetchToken(): Promise<string | null>;
|
|
61
69
|
onMessageListener(callback: (payload: any) => void): void;
|
|
@@ -72,6 +80,7 @@ export declare class FirebaseUnifiedService implements LoginService {
|
|
|
72
80
|
isSignInWithEmailLink(): boolean;
|
|
73
81
|
signInWithEmailLink(email: string): Promise<AuthResult>;
|
|
74
82
|
getEmailForSignIn(): string | null;
|
|
83
|
+
applyEmailVerificationCode(oobCode: string): Promise<void>;
|
|
75
84
|
private _createSuccessAuthResult;
|
|
76
85
|
private getUserFromBackend;
|
|
77
86
|
private createUserInBackend;
|
|
@@ -8,12 +8,26 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var _a;
|
|
11
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
13
|
exports.FirebaseUnifiedService = exports.AuthResult = exports.UserData = exports.AuthState = exports.AuthProvider = void 0;
|
|
13
14
|
const app_1 = require("firebase/app");
|
|
14
15
|
const auth_1 = require("firebase/auth");
|
|
15
16
|
const messaging_1 = require("firebase/messaging");
|
|
16
17
|
const UserContext_1 = require("./UserContext");
|
|
18
|
+
const DEFAULT_EMAIL_VERIFICATION_PAGE = (_a = process.env.NEXT_PUBLIC_EMAIL_VERIFICATION_URL) !== null && _a !== void 0 ? _a : "http://localhost:3000/auth/email-verified";
|
|
19
|
+
const trimTrailingSlash = (value) => value.replace(/\/+$/, "");
|
|
20
|
+
const appendQueryParams = (base, params) => {
|
|
21
|
+
const query = Object.entries(params)
|
|
22
|
+
.filter(([, value]) => value !== undefined && value !== null)
|
|
23
|
+
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
|
|
24
|
+
.join("&");
|
|
25
|
+
if (!query) {
|
|
26
|
+
return base;
|
|
27
|
+
}
|
|
28
|
+
const separator = base.includes("?") ? "&" : "?";
|
|
29
|
+
return `${base}${separator}${query}`;
|
|
30
|
+
};
|
|
17
31
|
// Auth provider type for better type safety
|
|
18
32
|
var AuthProvider;
|
|
19
33
|
(function (AuthProvider) {
|
|
@@ -75,19 +89,28 @@ class AuthResult {
|
|
|
75
89
|
exports.AuthResult = AuthResult;
|
|
76
90
|
class FirebaseUnifiedService {
|
|
77
91
|
constructor(client, config) {
|
|
78
|
-
var _a;
|
|
92
|
+
var _a, _b, _c, _d, _e;
|
|
79
93
|
this.app = null;
|
|
80
94
|
this.messaging = null;
|
|
81
95
|
this.auth = null;
|
|
82
96
|
this.client = client;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
97
|
+
const fallbackVerificationPage = (_a = config === null || config === void 0 ? void 0 : config.emailVerificationUrl) !== null && _a !== void 0 ? _a : DEFAULT_EMAIL_VERIFICATION_PAGE;
|
|
98
|
+
this.emailVerificationUrl = trimTrailingSlash(fallbackVerificationPage);
|
|
99
|
+
this.emailVerificationContinueUrl = config === null || config === void 0 ? void 0 : config.emailVerificationContinueUrl;
|
|
100
|
+
const configuredActionSettings = config === null || config === void 0 ? void 0 : config.actionCodeSettings;
|
|
101
|
+
const defaultActionUrl = (_d = (_c = (_b = configuredActionSettings === null || configuredActionSettings === void 0 ? void 0 : configuredActionSettings.url) !== null && _b !== void 0 ? _b : process.env.REACT_APP_EMAIL_LINK_URL) !== null && _c !== void 0 ? _c : process.env.NEXT_PUBLIC_EMAIL_LINK_URL) !== null && _d !== void 0 ? _d : "http://localhost:3000/auth/verify-email";
|
|
102
|
+
this.actionCodeSettings = {
|
|
103
|
+
url: defaultActionUrl,
|
|
104
|
+
handleCodeInApp: (_e = configuredActionSettings === null || configuredActionSettings === void 0 ? void 0 : configuredActionSettings.handleCodeInApp) !== null && _e !== void 0 ? _e : true,
|
|
86
105
|
};
|
|
87
|
-
this.initializeFirebase();
|
|
106
|
+
this.initializationPromise = this.initializeFirebase();
|
|
107
|
+
this.client.setAuthTokenProvider(this.buildAuthTokenProvider());
|
|
88
108
|
}
|
|
89
109
|
initializeFirebase() {
|
|
90
110
|
return __awaiter(this, void 0, void 0, function* () {
|
|
111
|
+
if (this.app) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
91
114
|
try {
|
|
92
115
|
const firebaseConfig = yield this.fetchFirebaseConfig();
|
|
93
116
|
this.app = (0, app_1.initializeApp)(firebaseConfig);
|
|
@@ -98,6 +121,42 @@ class FirebaseUnifiedService {
|
|
|
98
121
|
}
|
|
99
122
|
});
|
|
100
123
|
}
|
|
124
|
+
ensureAuthInstance() {
|
|
125
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
126
|
+
try {
|
|
127
|
+
yield this.initializationPromise;
|
|
128
|
+
}
|
|
129
|
+
catch (_error) {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
return this.auth;
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
buildAuthTokenProvider() {
|
|
136
|
+
return {
|
|
137
|
+
getToken: () => __awaiter(this, void 0, void 0, function* () {
|
|
138
|
+
const auth = yield this.ensureAuthInstance();
|
|
139
|
+
const currentUser = auth === null || auth === void 0 ? void 0 : auth.currentUser;
|
|
140
|
+
if (!currentUser) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
return currentUser.getIdToken();
|
|
144
|
+
}),
|
|
145
|
+
refreshToken: () => __awaiter(this, void 0, void 0, function* () {
|
|
146
|
+
const auth = yield this.ensureAuthInstance();
|
|
147
|
+
const currentUser = auth === null || auth === void 0 ? void 0 : auth.currentUser;
|
|
148
|
+
if (!currentUser) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
const refreshedToken = yield currentUser.getIdToken(true);
|
|
152
|
+
UserContext_1.userContext.updateUser({ idToken: refreshedToken });
|
|
153
|
+
return refreshedToken;
|
|
154
|
+
}),
|
|
155
|
+
onRefreshFailure: (error) => {
|
|
156
|
+
console.error("Failed to refresh Firebase ID token:", error);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
}
|
|
101
160
|
fetchFirebaseConfig() {
|
|
102
161
|
return __awaiter(this, void 0, void 0, function* () {
|
|
103
162
|
try {
|
|
@@ -110,6 +169,54 @@ class FirebaseUnifiedService {
|
|
|
110
169
|
}
|
|
111
170
|
});
|
|
112
171
|
}
|
|
172
|
+
buildEmailVerificationSettings(loginId) {
|
|
173
|
+
return {
|
|
174
|
+
url: this.buildEmailVerificationUrl(loginId),
|
|
175
|
+
handleCodeInApp: false,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
buildEmailVerificationUrl(loginId) {
|
|
179
|
+
return appendQueryParams(this.emailVerificationUrl, {
|
|
180
|
+
loginId,
|
|
181
|
+
continueUrl: this.emailVerificationContinueUrl,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
ensureBackendVerification(firebaseUser, backendUser, idToken) {
|
|
185
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
186
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
187
|
+
const firebaseVerified = firebaseUser.emailVerified;
|
|
188
|
+
const backendVerified = (_b = (_a = backendUser.settings) === null || _a === void 0 ? void 0 : _a.hasVerified) !== null && _b !== void 0 ? _b : false;
|
|
189
|
+
if (!firebaseVerified || backendVerified) {
|
|
190
|
+
return backendUser;
|
|
191
|
+
}
|
|
192
|
+
if (!backendUser.id) {
|
|
193
|
+
console.warn("Missing backend user id when attempting to mark verification status.");
|
|
194
|
+
return backendUser;
|
|
195
|
+
}
|
|
196
|
+
const settingsUpdate = {
|
|
197
|
+
paymentMethods: ((_d = (_c = backendUser.settings) === null || _c === void 0 ? void 0 : _c.paymentMethods) !== null && _d !== void 0 ? _d : []).map((method) => (Object.assign({}, method))),
|
|
198
|
+
hasVerified: true,
|
|
199
|
+
};
|
|
200
|
+
const preferredToken = (_e = backendUser.settings) === null || _e === void 0 ? void 0 : _e.preferredTokenCode;
|
|
201
|
+
if (preferredToken !== undefined && preferredToken !== null) {
|
|
202
|
+
settingsUpdate.preferredTokenCode = preferredToken;
|
|
203
|
+
}
|
|
204
|
+
const request = {
|
|
205
|
+
userId: backendUser.id,
|
|
206
|
+
settings: settingsUpdate,
|
|
207
|
+
};
|
|
208
|
+
try {
|
|
209
|
+
const response = yield this.client.updateUserSettings(request, {
|
|
210
|
+
Authorization: `Bearer ${idToken}`,
|
|
211
|
+
});
|
|
212
|
+
return (_g = (_f = response.users) === null || _f === void 0 ? void 0 : _f[0]) !== null && _g !== void 0 ? _g : backendUser;
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
console.error("Failed to update backend verification status:", error);
|
|
216
|
+
return backendUser;
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
113
220
|
// Messaging methods
|
|
114
221
|
requestNotificationPermission() {
|
|
115
222
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -169,22 +276,24 @@ class FirebaseUnifiedService {
|
|
|
169
276
|
signInWithEmail(email, password) {
|
|
170
277
|
return __awaiter(this, void 0, void 0, function* () {
|
|
171
278
|
try {
|
|
172
|
-
|
|
279
|
+
const auth = yield this.ensureAuthInstance();
|
|
280
|
+
if (!auth) {
|
|
173
281
|
console.error("Firebase Auth not initialized");
|
|
174
282
|
return AuthResult.failure("Firebase Auth not initialized");
|
|
175
283
|
}
|
|
176
|
-
const userCredential = yield (0, auth_1.signInWithEmailAndPassword)(
|
|
284
|
+
const userCredential = yield (0, auth_1.signInWithEmailAndPassword)(auth, email, password);
|
|
177
285
|
const idToken = yield userCredential.user.getIdToken();
|
|
178
286
|
const backendUser = yield this.getUserFromBackend(userCredential.user.uid, idToken);
|
|
179
287
|
if (backendUser) {
|
|
180
|
-
const
|
|
288
|
+
const syncedBackendUser = yield this.ensureBackendVerification(userCredential.user, backendUser, idToken);
|
|
289
|
+
const authResult = this._createSuccessAuthResult(userCredential.user, syncedBackendUser, AuthProvider.EMAIL, idToken);
|
|
181
290
|
// Update UserContext
|
|
182
291
|
UserContext_1.userContext.setUser({
|
|
183
292
|
id: userCredential.user.uid,
|
|
184
|
-
username:
|
|
293
|
+
username: syncedBackendUser.username || '',
|
|
185
294
|
email: userCredential.user.email || '',
|
|
186
|
-
idToken
|
|
187
|
-
isAdmin:
|
|
295
|
+
idToken,
|
|
296
|
+
isAdmin: syncedBackendUser.admin || false
|
|
188
297
|
});
|
|
189
298
|
return authResult;
|
|
190
299
|
}
|
|
@@ -205,15 +314,16 @@ class FirebaseUnifiedService {
|
|
|
205
314
|
createUserWithEmail(email, password, username) {
|
|
206
315
|
return __awaiter(this, void 0, void 0, function* () {
|
|
207
316
|
try {
|
|
208
|
-
|
|
317
|
+
const auth = yield this.ensureAuthInstance();
|
|
318
|
+
if (!auth) {
|
|
209
319
|
return AuthResult.failure("Firebase Auth not initialized");
|
|
210
320
|
}
|
|
211
321
|
// First create the user in Firebase
|
|
212
|
-
const userCredential = yield (0, auth_1.createUserWithEmailAndPassword)(
|
|
322
|
+
const userCredential = yield (0, auth_1.createUserWithEmailAndPassword)(auth, email, password);
|
|
213
323
|
const user = userCredential.user;
|
|
214
324
|
const idToken = yield user.getIdToken();
|
|
215
325
|
// Send email verification
|
|
216
|
-
yield (0, auth_1.sendEmailVerification)(user);
|
|
326
|
+
yield (0, auth_1.sendEmailVerification)(user, this.buildEmailVerificationSettings(user.uid));
|
|
217
327
|
const backendUser = yield this.createUserInBackend(user.uid, username, idToken);
|
|
218
328
|
if (backendUser) {
|
|
219
329
|
return this._createSuccessAuthResult(user, backendUser, AuthProvider.EMAIL, idToken);
|
|
@@ -231,18 +341,20 @@ class FirebaseUnifiedService {
|
|
|
231
341
|
signInWithGoogle() {
|
|
232
342
|
return __awaiter(this, void 0, void 0, function* () {
|
|
233
343
|
try {
|
|
234
|
-
|
|
344
|
+
const auth = yield this.ensureAuthInstance();
|
|
345
|
+
if (!auth) {
|
|
235
346
|
return AuthResult.failure("Firebase Auth not initialized");
|
|
236
347
|
}
|
|
237
348
|
const provider = new auth_1.GoogleAuthProvider();
|
|
238
|
-
const userCredential = yield (0, auth_1.signInWithPopup)(
|
|
349
|
+
const userCredential = yield (0, auth_1.signInWithPopup)(auth, provider);
|
|
239
350
|
const user = userCredential.user;
|
|
240
|
-
// Get or create user in your Kotlin backend
|
|
241
|
-
const backendUser = yield this.getUserFromBackend(user.uid, user.displayName || '');
|
|
242
351
|
const idToken = yield user.getIdToken();
|
|
352
|
+
// Get or create user in your Kotlin backend
|
|
353
|
+
const backendUser = yield this.getUserFromBackend(user.uid, idToken);
|
|
243
354
|
if (backendUser) {
|
|
355
|
+
const syncedBackendUser = yield this.ensureBackendVerification(user, backendUser, idToken);
|
|
244
356
|
// Use the new helper method
|
|
245
|
-
return this._createSuccessAuthResult(user,
|
|
357
|
+
return this._createSuccessAuthResult(user, syncedBackendUser, AuthProvider.GOOGLE, idToken);
|
|
246
358
|
}
|
|
247
359
|
else {
|
|
248
360
|
return AuthResult.failure('Failed to get or create user in backend');
|
|
@@ -257,18 +369,20 @@ class FirebaseUnifiedService {
|
|
|
257
369
|
signInWithFacebook() {
|
|
258
370
|
return __awaiter(this, void 0, void 0, function* () {
|
|
259
371
|
try {
|
|
260
|
-
|
|
372
|
+
const auth = yield this.ensureAuthInstance();
|
|
373
|
+
if (!auth) {
|
|
261
374
|
return AuthResult.failure("Firebase Auth not initialized");
|
|
262
375
|
}
|
|
263
376
|
const provider = new auth_1.FacebookAuthProvider();
|
|
264
|
-
const userCredential = yield (0, auth_1.signInWithPopup)(
|
|
377
|
+
const userCredential = yield (0, auth_1.signInWithPopup)(auth, provider);
|
|
265
378
|
const user = userCredential.user;
|
|
266
|
-
// Get or create user in your Kotlin backend
|
|
267
|
-
const backendUser = yield this.getUserFromBackend(user.uid, user.displayName || '');
|
|
268
379
|
const idToken = yield user.getIdToken();
|
|
380
|
+
// Get or create user in your Kotlin backend
|
|
381
|
+
const backendUser = yield this.getUserFromBackend(user.uid, idToken);
|
|
269
382
|
if (backendUser) {
|
|
383
|
+
const syncedBackendUser = yield this.ensureBackendVerification(user, backendUser, idToken);
|
|
270
384
|
// Use the new helper method
|
|
271
|
-
return this._createSuccessAuthResult(user,
|
|
385
|
+
return this._createSuccessAuthResult(user, syncedBackendUser, AuthProvider.FACEBOOK, idToken);
|
|
272
386
|
}
|
|
273
387
|
else {
|
|
274
388
|
return AuthResult.failure('Failed to get or create user in backend');
|
|
@@ -283,18 +397,20 @@ class FirebaseUnifiedService {
|
|
|
283
397
|
signInWithTwitter() {
|
|
284
398
|
return __awaiter(this, void 0, void 0, function* () {
|
|
285
399
|
try {
|
|
286
|
-
|
|
400
|
+
const auth = yield this.ensureAuthInstance();
|
|
401
|
+
if (!auth) {
|
|
287
402
|
return AuthResult.failure("Firebase Auth not initialized");
|
|
288
403
|
}
|
|
289
404
|
const provider = new auth_1.TwitterAuthProvider();
|
|
290
|
-
const userCredential = yield (0, auth_1.signInWithPopup)(
|
|
405
|
+
const userCredential = yield (0, auth_1.signInWithPopup)(auth, provider);
|
|
291
406
|
const user = userCredential.user;
|
|
292
|
-
// Get or create user in your Kotlin backend
|
|
293
|
-
const backendUser = yield this.getUserFromBackend(user.uid, user.displayName || '');
|
|
294
407
|
const idToken = yield user.getIdToken();
|
|
408
|
+
// Get or create user in your Kotlin backend
|
|
409
|
+
const backendUser = yield this.getUserFromBackend(user.uid, idToken);
|
|
295
410
|
if (backendUser) {
|
|
411
|
+
const syncedBackendUser = yield this.ensureBackendVerification(user, backendUser, idToken);
|
|
296
412
|
// Use the new helper method
|
|
297
|
-
return this._createSuccessAuthResult(user,
|
|
413
|
+
return this._createSuccessAuthResult(user, syncedBackendUser, AuthProvider.TWITTER, idToken);
|
|
298
414
|
}
|
|
299
415
|
else {
|
|
300
416
|
return AuthResult.failure('Failed to get or create user in backend');
|
|
@@ -309,12 +425,13 @@ class FirebaseUnifiedService {
|
|
|
309
425
|
sendEmailVerification() {
|
|
310
426
|
return __awaiter(this, void 0, void 0, function* () {
|
|
311
427
|
try {
|
|
312
|
-
|
|
428
|
+
const auth = yield this.ensureAuthInstance();
|
|
429
|
+
if (!auth) {
|
|
313
430
|
return false;
|
|
314
431
|
}
|
|
315
|
-
const user =
|
|
432
|
+
const user = auth.currentUser;
|
|
316
433
|
if (user) {
|
|
317
|
-
yield (0, auth_1.sendEmailVerification)(user);
|
|
434
|
+
yield (0, auth_1.sendEmailVerification)(user, this.buildEmailVerificationSettings(user.uid));
|
|
318
435
|
return true;
|
|
319
436
|
}
|
|
320
437
|
return false;
|
|
@@ -328,10 +445,11 @@ class FirebaseUnifiedService {
|
|
|
328
445
|
sendPasswordResetEmail(email) {
|
|
329
446
|
return __awaiter(this, void 0, void 0, function* () {
|
|
330
447
|
try {
|
|
331
|
-
|
|
448
|
+
const auth = yield this.ensureAuthInstance();
|
|
449
|
+
if (!auth) {
|
|
332
450
|
return false;
|
|
333
451
|
}
|
|
334
|
-
yield (0, auth_1.sendPasswordResetEmail)(
|
|
452
|
+
yield (0, auth_1.sendPasswordResetEmail)(auth, email);
|
|
335
453
|
return true;
|
|
336
454
|
}
|
|
337
455
|
catch (error) {
|
|
@@ -343,10 +461,12 @@ class FirebaseUnifiedService {
|
|
|
343
461
|
signOut() {
|
|
344
462
|
return __awaiter(this, void 0, void 0, function* () {
|
|
345
463
|
try {
|
|
346
|
-
|
|
464
|
+
const auth = yield this.ensureAuthInstance();
|
|
465
|
+
if (!auth) {
|
|
466
|
+
UserContext_1.userContext.clearUser();
|
|
347
467
|
return;
|
|
348
468
|
}
|
|
349
|
-
yield (0, auth_1.signOut)(
|
|
469
|
+
yield (0, auth_1.signOut)(auth);
|
|
350
470
|
// Clear UserContext
|
|
351
471
|
UserContext_1.userContext.clearUser();
|
|
352
472
|
}
|
|
@@ -364,10 +484,11 @@ class FirebaseUnifiedService {
|
|
|
364
484
|
sendSignInLinkToEmail(email) {
|
|
365
485
|
return __awaiter(this, void 0, void 0, function* () {
|
|
366
486
|
try {
|
|
367
|
-
|
|
487
|
+
const auth = yield this.ensureAuthInstance();
|
|
488
|
+
if (!auth) {
|
|
368
489
|
return false;
|
|
369
490
|
}
|
|
370
|
-
yield (0, auth_1.sendSignInLinkToEmail)(
|
|
491
|
+
yield (0, auth_1.sendSignInLinkToEmail)(auth, email, this.actionCodeSettings);
|
|
371
492
|
// Save the email locally to use it later when the user clicks the link
|
|
372
493
|
window.localStorage.setItem('emailForSignIn', email);
|
|
373
494
|
return true;
|
|
@@ -387,22 +508,24 @@ class FirebaseUnifiedService {
|
|
|
387
508
|
signInWithEmailLink(email) {
|
|
388
509
|
return __awaiter(this, void 0, void 0, function* () {
|
|
389
510
|
try {
|
|
390
|
-
|
|
511
|
+
const auth = yield this.ensureAuthInstance();
|
|
512
|
+
if (!auth) {
|
|
391
513
|
return AuthResult.failure("Firebase Auth not initialized");
|
|
392
514
|
}
|
|
393
|
-
if (!
|
|
515
|
+
if (!(0, auth_1.isSignInWithEmailLink)(auth, window.location.href)) {
|
|
394
516
|
return AuthResult.failure("Invalid sign-in link");
|
|
395
517
|
}
|
|
396
|
-
const userCredential = yield (0, auth_1.signInWithEmailLink)(
|
|
518
|
+
const userCredential = yield (0, auth_1.signInWithEmailLink)(auth, email, window.location.href);
|
|
397
519
|
const user = userCredential.user;
|
|
398
520
|
// Clear the email from localStorage
|
|
399
521
|
window.localStorage.removeItem('emailForSignIn');
|
|
400
|
-
// Get or create user in your Kotlin backend
|
|
401
|
-
const backendUser = yield this.getUserFromBackend(user.uid, user.displayName || '');
|
|
402
522
|
const idToken = yield user.getIdToken();
|
|
523
|
+
// Get or create user in your Kotlin backend
|
|
524
|
+
const backendUser = yield this.getUserFromBackend(user.uid, idToken);
|
|
403
525
|
if (backendUser) {
|
|
526
|
+
const syncedBackendUser = yield this.ensureBackendVerification(user, backendUser, idToken);
|
|
404
527
|
// Use the new helper method
|
|
405
|
-
return this._createSuccessAuthResult(user,
|
|
528
|
+
return this._createSuccessAuthResult(user, syncedBackendUser, AuthProvider.EMAIL, idToken);
|
|
406
529
|
}
|
|
407
530
|
else {
|
|
408
531
|
return AuthResult.failure('Failed to get or create user in backend');
|
|
@@ -417,17 +540,26 @@ class FirebaseUnifiedService {
|
|
|
417
540
|
getEmailForSignIn() {
|
|
418
541
|
return window.localStorage.getItem('emailForSignIn');
|
|
419
542
|
}
|
|
543
|
+
applyEmailVerificationCode(oobCode) {
|
|
544
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
545
|
+
const auth = yield this.ensureAuthInstance();
|
|
546
|
+
if (!auth) {
|
|
547
|
+
throw new Error("Firebase Auth not initialized");
|
|
548
|
+
}
|
|
549
|
+
yield (0, auth_1.applyActionCode)(auth, oobCode);
|
|
550
|
+
});
|
|
551
|
+
}
|
|
420
552
|
// Helper method to create success AuthResult
|
|
421
553
|
_createSuccessAuthResult(user, backendUser, provider, idToken) {
|
|
422
554
|
const userData = UserData.create(user.uid, user.email || '', backendUser.username || '', user.emailVerified, idToken, backendUser.admin || false);
|
|
423
555
|
return AuthResult.success(backendUser, userData, provider);
|
|
424
556
|
}
|
|
425
557
|
// Backend integration methods
|
|
426
|
-
getUserFromBackend(userId,
|
|
558
|
+
getUserFromBackend(userId, authToken) {
|
|
427
559
|
return __awaiter(this, void 0, void 0, function* () {
|
|
428
560
|
try {
|
|
429
561
|
const response = yield this.client.getUser(userId, {
|
|
430
|
-
Authorization: `Bearer ${
|
|
562
|
+
Authorization: `Bearer ${authToken}`,
|
|
431
563
|
});
|
|
432
564
|
return response.users[0];
|
|
433
565
|
}
|
|
@@ -17,5 +17,7 @@ export interface FirebaseLoginServiceConfig {
|
|
|
17
17
|
url: string;
|
|
18
18
|
handleCodeInApp: boolean;
|
|
19
19
|
};
|
|
20
|
+
emailVerificationUrl?: string;
|
|
21
|
+
emailVerificationContinueUrl?: string;
|
|
20
22
|
}
|
|
21
23
|
export declare function createLoginService(config: LoginServiceConfig): LoginService;
|