|
|
|
|
@@ -1,14 +1,20 @@
|
|
|
|
|
import { HttpClient } from '@angular/common/http';
|
|
|
|
|
import { Component, computed, effect, inject, input, output, signal } from '@angular/core';
|
|
|
|
|
import { FASTCHECK_API } from '../api';
|
|
|
|
|
import { USERS_VITANOVA_API } from '../api';
|
|
|
|
|
import { TranslatePipe } from '../translate/translate.pipe';
|
|
|
|
|
|
|
|
|
|
interface WebSessionResponse {
|
|
|
|
|
sessionId: string;
|
|
|
|
|
userId: string;
|
|
|
|
|
expires: string;
|
|
|
|
|
userSessionId: string;
|
|
|
|
|
Status: boolean;
|
|
|
|
|
sessionId?: string;
|
|
|
|
|
webSessionID?: string;
|
|
|
|
|
webSessionId?: string;
|
|
|
|
|
userId?: string;
|
|
|
|
|
userID?: string;
|
|
|
|
|
telegramID?: string;
|
|
|
|
|
expires?: string;
|
|
|
|
|
userSessionId?: string;
|
|
|
|
|
userSessionID?: string;
|
|
|
|
|
Status?: boolean;
|
|
|
|
|
status?: boolean | string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export type AuthDialogMode = 'payment' | 'login' | 'new';
|
|
|
|
|
@@ -31,7 +37,6 @@ export class AuthDialogComponent {
|
|
|
|
|
private readonly http = inject(HttpClient);
|
|
|
|
|
private readonly telegramBot = 'myAMLKYCBOT';
|
|
|
|
|
private readonly sessionStorageKey = 'fc_session';
|
|
|
|
|
private readonly maxPollAttempts = 100;
|
|
|
|
|
|
|
|
|
|
open = input(false);
|
|
|
|
|
mode = input<AuthDialogMode>('login');
|
|
|
|
|
@@ -61,7 +66,6 @@ export class AuthDialogComponent {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private pollHandle: ReturnType<typeof setInterval> | null = null;
|
|
|
|
|
private pollAttempts = 0;
|
|
|
|
|
private wasOpen = false;
|
|
|
|
|
private authenticated = false;
|
|
|
|
|
|
|
|
|
|
@@ -106,7 +110,6 @@ export class AuthDialogComponent {
|
|
|
|
|
private startAuthFlow(): void {
|
|
|
|
|
this.stopPolling();
|
|
|
|
|
this.authenticated = false;
|
|
|
|
|
this.pollAttempts = 0;
|
|
|
|
|
this.messageKey.set('');
|
|
|
|
|
this.webSessionId.set('');
|
|
|
|
|
this.state.set('checking');
|
|
|
|
|
@@ -121,9 +124,9 @@ export class AuthDialogComponent {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private checkExistingSession(sessionId: string): void {
|
|
|
|
|
this.http.get<WebSessionResponse>(`${FASTCHECK_API}/websession/${sessionId}`).subscribe({
|
|
|
|
|
this.http.get<WebSessionResponse>(`${USERS_VITANOVA_API}/users/sessions/${sessionId}`).subscribe({
|
|
|
|
|
next: (response) => {
|
|
|
|
|
if (response?.Status) {
|
|
|
|
|
if (this.isAuthorized(response)) {
|
|
|
|
|
this.webSessionId.set(sessionId);
|
|
|
|
|
this.handleAuthorized(response, sessionId);
|
|
|
|
|
return;
|
|
|
|
|
@@ -141,26 +144,30 @@ export class AuthDialogComponent {
|
|
|
|
|
|
|
|
|
|
private createSession(): void {
|
|
|
|
|
this.state.set('loading');
|
|
|
|
|
this.http.get<WebSessionResponse>(`${FASTCHECK_API}/websession`).subscribe({
|
|
|
|
|
const sessionId = this.createGuid();
|
|
|
|
|
this.webSessionId.set(sessionId);
|
|
|
|
|
|
|
|
|
|
this.http.post<WebSessionResponse>(`${USERS_VITANOVA_API}/users/sessions`, {
|
|
|
|
|
webSessionID: sessionId,
|
|
|
|
|
sessionId
|
|
|
|
|
}).subscribe({
|
|
|
|
|
next: (response) => {
|
|
|
|
|
const sessionId = response?.sessionId ?? '';
|
|
|
|
|
if (!sessionId) {
|
|
|
|
|
const responseSessionId = this.getSessionId(response) || sessionId;
|
|
|
|
|
if (!responseSessionId) {
|
|
|
|
|
this.messageKey.set('auth.session_failed');
|
|
|
|
|
this.state.set('error');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.webSessionId.set(sessionId);
|
|
|
|
|
this.webSessionId.set(responseSessionId);
|
|
|
|
|
|
|
|
|
|
if (this.isMobile) {
|
|
|
|
|
this.state.set('checking');
|
|
|
|
|
window.location.href = this.telegramLink();
|
|
|
|
|
this.startPolling(sessionId);
|
|
|
|
|
if (this.isAuthorized(response)) {
|
|
|
|
|
this.handleAuthorized(response, responseSessionId);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.state.set('ready');
|
|
|
|
|
this.startPolling(sessionId);
|
|
|
|
|
this.startPolling(responseSessionId);
|
|
|
|
|
},
|
|
|
|
|
error: () => {
|
|
|
|
|
this.messageKey.set('auth.session_failed');
|
|
|
|
|
@@ -171,19 +178,10 @@ export class AuthDialogComponent {
|
|
|
|
|
|
|
|
|
|
private startPolling(sessionId: string): void {
|
|
|
|
|
this.stopPolling();
|
|
|
|
|
this.pollAttempts = 0;
|
|
|
|
|
this.pollHandle = setInterval(() => {
|
|
|
|
|
this.pollAttempts += 1;
|
|
|
|
|
if (this.pollAttempts >= this.maxPollAttempts) {
|
|
|
|
|
this.stopPolling();
|
|
|
|
|
this.messageKey.set('auth.expired');
|
|
|
|
|
this.state.set('expired');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.http.get<WebSessionResponse>(`${FASTCHECK_API}/websession/${sessionId}`).subscribe({
|
|
|
|
|
this.http.get<WebSessionResponse>(`${USERS_VITANOVA_API}/users/sessions/${sessionId}`).subscribe({
|
|
|
|
|
next: (response) => {
|
|
|
|
|
if (!response?.Status) return;
|
|
|
|
|
if (!this.isAuthorized(response)) return;
|
|
|
|
|
this.handleAuthorized(response, sessionId);
|
|
|
|
|
},
|
|
|
|
|
error: () => undefined
|
|
|
|
|
@@ -200,8 +198,8 @@ export class AuthDialogComponent {
|
|
|
|
|
this.state.set('checking');
|
|
|
|
|
this.authorized.emit({
|
|
|
|
|
sessionId,
|
|
|
|
|
userId: response.userId ?? '',
|
|
|
|
|
userSessionId: response.userSessionId ?? ''
|
|
|
|
|
userId: response.userId ?? response.userID ?? response.telegramID ?? '',
|
|
|
|
|
userSessionId: response.userSessionId ?? response.userSessionID ?? ''
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -212,7 +210,6 @@ export class AuthDialogComponent {
|
|
|
|
|
this.webSessionId.set('');
|
|
|
|
|
this.state.set('loading');
|
|
|
|
|
this.authenticated = false;
|
|
|
|
|
this.pollAttempts = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private cleanupSession(persistSession: boolean): void {
|
|
|
|
|
@@ -232,14 +229,33 @@ export class AuthDialogComponent {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.http
|
|
|
|
|
.request('DELETE', `${FASTCHECK_API}/websession/${sessionId}`, {
|
|
|
|
|
body: { sessionId }
|
|
|
|
|
})
|
|
|
|
|
.delete(`${USERS_VITANOVA_API}/users/sessions/${sessionId}`)
|
|
|
|
|
.subscribe({ error: () => undefined });
|
|
|
|
|
|
|
|
|
|
localStorage.removeItem(this.sessionStorageKey);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private getSessionId(response: WebSessionResponse | null | undefined): string {
|
|
|
|
|
return response?.webSessionID ?? response?.webSessionId ?? response?.sessionId ?? '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private isAuthorized(response: WebSessionResponse | null | undefined): boolean {
|
|
|
|
|
const status = response?.Status ?? response?.status;
|
|
|
|
|
return status === true || String(status).toLowerCase() === 'true';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private createGuid(): string {
|
|
|
|
|
if (typeof crypto !== 'undefined' && 'randomUUID' in crypto) {
|
|
|
|
|
return crypto.randomUUID();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (char) => {
|
|
|
|
|
const randomValue = Math.floor(Math.random() * 16);
|
|
|
|
|
const value = char === 'x' ? randomValue : (randomValue & 0x3) | 0x8;
|
|
|
|
|
return value.toString(16);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private stopPolling(): void {
|
|
|
|
|
if (this.pollHandle === null) return;
|
|
|
|
|
clearInterval(this.pollHandle);
|
|
|
|
|
|