import { injectable } from '@cloudbeaver/core-di' ; import { SessionDataResource } from '@cloudbeaver/core-root' ; import type { AuthProviderConfiguration , UserInfo } from '@cloudbeaver/core-sdk' ; import { openCenteredPopup } from '@cloudbeaver/core-utils' ; import { AuthProvidersResource } from './AuthProvidersResource' ; import type { IAuthCredentials } from './IAuthCredentials' ; import { UserInfoResource } from './UserInfoResource' ; interface IActiveSSOAuthentication { configuration : AuthProviderConfiguration ; window : Window ; promise : Promise < UserInfo | null > ; } @ injectable ( ) export class AuthInfoService { get userInfo ( ) : UserInfo | null { return this . userInfoResource . data ; } get userAuthConfigurations ( ) : AuthProviderConfiguration [ ] { const tokens = this . userInfo ?. authTokens ; const result = [ ] ; if ( ! tokens ) { return result ; } for ( const token of tokens ) { if ( token . authConfiguration ) { const provider = this . authProvidersResource . values . find ( provider => provider . id === token . authProvider ) ; if ( provider ) { const configuration = provider . configurations ?. find ( configuration => configuration . id === token . authConfiguration ) ; if ( configuration ) { result . push ( configuration ) ; } } } } return result ; } private activeSSO : Map < string , IActiveSSOAuthentication > ; constructor ( private readonly userInfoResource , private readonly authProvidersResource , private readonly sessionDataResource ) { this . activeSSO = new Map ( ) ; } async login ( provider , credentials , link ? ) { return this . userInfoResource . login ( provider , credentials , link ) ; } async sso ( providerId , configuration ) { return this . ssoAuth ( providerId , configuration ) ; } async logout ( ) { await this . userInfoResource . logout ( ) ; } private async ssoAuth ( providerId , configuration ) { const active = this . activeSSO . get ( configuration . id ) ; if ( active ) { active . window . focus ( ) ; return active . promise ; } const popup = openCenteredPopup ( configuration . signInLink , configuration . id , 600 , 700 , undefined , true ) ; if ( popup ) { popup . focus ( ) ; const task = async ( ) => { await this . waitWindowsClose ( popup ) ; this . sessionDataResource . markOutdated ( ) ; const user = await this . userInfoResource . refresh ( undefined , [ ] ) ; return user ; } ; const active = { configuration , promise : task ( ) , window : popup , } ; this . activeSSO . set ( configuration . id , active ) ; try { return await active . promise ; } finally { this . activeSSO . delete ( configuration . id ) ; } } return Promise . resolve ( null ) ; } private async waitWindowsClose ( window ) { return new Promise ( resolve => { setInterval ( ( ) => { if ( window . closed ) { resolve ( ) ; } } , 100 ) ; } ) ; } }