release: @marketplaces/auth 0.1.0 (built from main)
This commit is contained in:
161
dist/telegram/auth.service.js
vendored
Normal file
161
dist/telegram/auth.service.js
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
import { Injectable, signal, computed, inject } from '@angular/core';
|
||||
import { tap } from 'rxjs';
|
||||
import { TelegramSessionApiService } from './telegram-session-api.service';
|
||||
const WEB_SESSION_COOKIE = 'webSessionID';
|
||||
const WEB_SESSION_COOKIE_MAX_AGE_SECONDS = 60 * 60;
|
||||
/** Customer-facing Telegram QR/session auth. Distinct storage/state from AdminAuthService by design. */
|
||||
let AuthService = class AuthService {
|
||||
constructor() {
|
||||
this.api = inject(TelegramSessionApiService);
|
||||
this.sessionSignal = signal(null);
|
||||
this.statusSignal = signal('unknown');
|
||||
this.showLoginSignal = signal(false);
|
||||
/** Current auth session */
|
||||
this.session = this.sessionSignal.asReadonly();
|
||||
/** Current auth status */
|
||||
this.status = this.statusSignal.asReadonly();
|
||||
/** Whether user is fully authenticated */
|
||||
this.isAuthenticated = computed(() => this.statusSignal() === 'authenticated');
|
||||
/** Whether to show login dialog */
|
||||
this.showLoginDialog = this.showLoginSignal.asReadonly();
|
||||
/** Display name of authenticated user */
|
||||
this.displayName = computed(() => this.sessionSignal()?.displayName ?? null);
|
||||
// On init, check existing session via cookie
|
||||
this.checkSession();
|
||||
}
|
||||
/** Check the current webSessionID cookie against the auth backend. */
|
||||
checkSession() {
|
||||
const webSessionID = this.getStoredWebSessionID();
|
||||
if (!webSessionID) {
|
||||
this.clearAuthState('unauthenticated');
|
||||
return;
|
||||
}
|
||||
this.statusSignal.set('checking');
|
||||
this.checkSessionOnce(webSessionID).subscribe(session => {
|
||||
if (!session?.active) {
|
||||
this.clearAuthState('unauthenticated');
|
||||
}
|
||||
});
|
||||
}
|
||||
/** Check session without updating internal state beyond activating on success (used for polling). */
|
||||
checkSessionOnce(webSessionID = this.getStoredWebSessionID()) {
|
||||
return this.api.checkSessionOnce(webSessionID).pipe(tap(session => {
|
||||
if (session?.active) {
|
||||
this.activateSession(session);
|
||||
}
|
||||
}));
|
||||
}
|
||||
/**
|
||||
* Called after user completes Telegram login.
|
||||
*/
|
||||
onTelegramLoginComplete() {
|
||||
this.hideLogin();
|
||||
if (!this.isAuthenticated()) {
|
||||
this.checkSession();
|
||||
}
|
||||
}
|
||||
/** Generate the Telegram login URL for bot-based auth */
|
||||
getTelegramLoginUrl(webSessionID) {
|
||||
return this.api.getBotLoginUrl(webSessionID);
|
||||
}
|
||||
/** Generate a Telegram app deep link for mobile login without opening a browser tab. */
|
||||
getTelegramAppLoginUrl(webSessionID) {
|
||||
return this.api.getBotAppLoginUrl(webSessionID);
|
||||
}
|
||||
/** Create a backend web session and return the Telegram start link for it. */
|
||||
createWebSession() {
|
||||
return this.api.createSession();
|
||||
}
|
||||
/** Show login dialog (called when user tries to pay without being logged in) */
|
||||
requestLogin() {
|
||||
this.showLoginSignal.set(true);
|
||||
}
|
||||
/** Hide login dialog */
|
||||
hideLogin() {
|
||||
this.showLoginSignal.set(false);
|
||||
}
|
||||
/** Logout — clears session on backend and locally */
|
||||
logout() {
|
||||
const webSessionID = this.sessionSignal()?.sessionId || this.getStoredWebSessionID();
|
||||
if (!webSessionID) {
|
||||
this.clearAuthState('unauthenticated');
|
||||
return;
|
||||
}
|
||||
this.api.logout(webSessionID).subscribe(() => {
|
||||
this.clearAuthState('unauthenticated');
|
||||
});
|
||||
}
|
||||
activateSession(session) {
|
||||
this.sessionSignal.set(session);
|
||||
this.statusSignal.set('authenticated');
|
||||
this.setStoredWebSessionID(session.sessionId);
|
||||
this.scheduleSessionRefresh(session.expires);
|
||||
}
|
||||
clearAuthState(status) {
|
||||
this.sessionSignal.set(null);
|
||||
this.statusSignal.set(status);
|
||||
this.clearStoredWebSessionID();
|
||||
this.clearSessionRefresh();
|
||||
}
|
||||
/** Schedule a session re-check before it expires */
|
||||
scheduleSessionRefresh(expiresAt) {
|
||||
this.clearSessionRefresh();
|
||||
const expiresMs = new Date(expiresAt).getTime();
|
||||
const nowMs = Date.now();
|
||||
// Re-check 60 seconds before expiry, minimum 30s from now
|
||||
const refreshIn = Number.isFinite(expiresMs)
|
||||
? Math.max(expiresMs - nowMs - 60_000, 30_000)
|
||||
: WEB_SESSION_COOKIE_MAX_AGE_SECONDS * 1000;
|
||||
this.sessionCheckTimer = setTimeout(() => {
|
||||
this.checkSession();
|
||||
}, refreshIn);
|
||||
}
|
||||
clearSessionRefresh() {
|
||||
if (this.sessionCheckTimer) {
|
||||
clearTimeout(this.sessionCheckTimer);
|
||||
this.sessionCheckTimer = undefined;
|
||||
}
|
||||
}
|
||||
getStoredWebSessionID() {
|
||||
if (typeof document === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
const cookie = document.cookie
|
||||
.split('; ')
|
||||
.find(row => row.startsWith(`${WEB_SESSION_COOKIE}=`));
|
||||
if (!cookie) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return decodeURIComponent(cookie.substring(WEB_SESSION_COOKIE.length + 1));
|
||||
}
|
||||
catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
setStoredWebSessionID(webSessionID) {
|
||||
if (typeof document === 'undefined') {
|
||||
return;
|
||||
}
|
||||
const secure = typeof window !== 'undefined' && window.location.protocol === 'https:' ? '; Secure' : '';
|
||||
document.cookie = `${WEB_SESSION_COOKIE}=${encodeURIComponent(webSessionID)}; Max-Age=${WEB_SESSION_COOKIE_MAX_AGE_SECONDS}; Path=/; SameSite=Lax${secure}`;
|
||||
}
|
||||
clearStoredWebSessionID() {
|
||||
if (typeof document === 'undefined') {
|
||||
return;
|
||||
}
|
||||
document.cookie = `${WEB_SESSION_COOKIE}=; Max-Age=0; Path=/; SameSite=Lax`;
|
||||
}
|
||||
};
|
||||
AuthService = __decorate([
|
||||
Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
], AuthService);
|
||||
export { AuthService };
|
||||
Reference in New Issue
Block a user