import { Injectable, inject } from '@angular/core'; import { Router } from '@angular/router'; import { Store } from '@ngrx/store'; import { firstValueFrom } from 'rxjs'; import { selectCurrentUser } from '../../../../store/users/users.selectors'; import { ServerDirectoryFacade } from '../../../server-directory'; import { AUTH_MODE_AUTHORIZE, buildLoginReturnQueryParams } from '../../domain/logic/auth-navigation.rules'; import { isSameSignalServerUrl } from '../../domain/logic/signal-server-auth-failure.rules'; import { SignalServerAuthService } from './signal-server-auth.service'; @Injectable({ providedIn: 'root' }) export class SignalServerAuthorizeService { private readonly router = inject(Router); private readonly store = inject(Store); private readonly serverDirectory = inject(ServerDirectoryFacade); private readonly signalServerAuth = inject(SignalServerAuthService); async ensureCredentialForServerUrl(serverUrl: string): Promise { if (this.signalServerAuth.hasValidCredential(serverUrl)) { return true; } const currentUser = await firstValueFrom(this.store.select(selectCurrentUser)); if (!currentUser) { return false; } if (isSameSignalServerUrl(serverUrl, currentUser.homeSignalServerUrl)) { // The home account is never auto-provisioned or re-authorized as a // foreign account. Resurrect the credential from the legacy token store // (session-restore case); a genuinely missing home session is handled by // the session-expiry flow, not the authorize login page. this.signalServerAuth.migrateHomeCredential(currentUser); return this.signalServerAuth.hasValidCredential(serverUrl); } let result; try { result = await this.signalServerAuth.ensureProvisioned(serverUrl, currentUser); } catch { return false; } if (result.kind === 'existing' || result.kind === 'provisioned') { return true; } // Automatic recovery must never turn a healthy home session into a generic // foreign-server login redirect. The contextual caller renders the // per-server recovery action; explicit authorization remains available in // Network settings. return false; } async navigateToAuthorize(serverUrl: string, returnUrl: string): Promise { const endpoint = this.serverDirectory.ensureServerEndpoint({ name: this.buildEndpointName(serverUrl), url: serverUrl }); await this.router.navigate(['/login'], { queryParams: buildLoginReturnQueryParams(returnUrl, undefined, { mode: AUTH_MODE_AUTHORIZE, serverId: endpoint.id }) }); } private buildEndpointName(serverUrl: string): string { try { return new URL(serverUrl).hostname; } catch { return serverUrl; } } }