Merge pull request #8945 from backstage/identity/reliable-methods
[Identity] Wait for implementation instead of throwing
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/core-app-api': patch
|
||||
---
|
||||
|
||||
Asynchronous methods on the identity API can now reliably be called at any time, including early in the bootstrap process or prior to successful sign-in.
|
||||
|
||||
Previously in such situations, a `Tried to access IdentityApi before app was loaded` error would be thrown. Now, those methods will wait and resolve eventually (as soon as a concrete identity API is provided).
|
||||
@@ -47,10 +47,19 @@ type CompatibilityIdentityApi = IdentityApi & {
|
||||
*/
|
||||
export class AppIdentityProxy implements IdentityApi {
|
||||
private target?: CompatibilityIdentityApi;
|
||||
private waitForTarget: Promise<CompatibilityIdentityApi>;
|
||||
private resolveTarget: (api: CompatibilityIdentityApi) => void = () => {};
|
||||
|
||||
constructor() {
|
||||
this.waitForTarget = new Promise<CompatibilityIdentityApi>(resolve => {
|
||||
this.resolveTarget = resolve;
|
||||
});
|
||||
}
|
||||
|
||||
// This is called by the app manager once the sign-in page provides us with an implementation
|
||||
setTarget(identityApi: CompatibilityIdentityApi) {
|
||||
this.target = identityApi;
|
||||
this.resolveTarget(identityApi);
|
||||
}
|
||||
|
||||
getUserId(): string {
|
||||
@@ -76,17 +85,13 @@ export class AppIdentityProxy implements IdentityApi {
|
||||
}
|
||||
|
||||
async getProfileInfo(): Promise<ProfileInfo> {
|
||||
if (!this.target) {
|
||||
throw mkError('getProfileInfo');
|
||||
}
|
||||
return this.target.getProfileInfo();
|
||||
return this.waitForTarget.then(target => target.getProfileInfo());
|
||||
}
|
||||
|
||||
async getBackstageIdentity(): Promise<BackstageUserIdentity> {
|
||||
if (!this.target) {
|
||||
throw mkError('getBackstageIdentity');
|
||||
}
|
||||
const identity = await this.target.getBackstageIdentity();
|
||||
const identity = await this.waitForTarget.then(target =>
|
||||
target.getBackstageIdentity(),
|
||||
);
|
||||
if (!identity.userEntityRef.match(/^.*:.*\/.*$/)) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
@@ -99,28 +104,21 @@ export class AppIdentityProxy implements IdentityApi {
|
||||
}
|
||||
|
||||
async getCredentials(): Promise<{ token?: string | undefined }> {
|
||||
if (!this.target) {
|
||||
throw mkError('getCredentials');
|
||||
}
|
||||
return this.target.getCredentials();
|
||||
return this.waitForTarget.then(target => target.getCredentials());
|
||||
}
|
||||
|
||||
async getIdToken(): Promise<string | undefined> {
|
||||
if (!this.target) {
|
||||
throw mkError('getIdToken');
|
||||
}
|
||||
if (!this.target.getIdToken) {
|
||||
throw new Error('IdentityApi does not implement getIdToken');
|
||||
}
|
||||
logDeprecation('getIdToken');
|
||||
return this.target.getIdToken();
|
||||
return this.waitForTarget.then(target => {
|
||||
if (!target.getIdToken) {
|
||||
throw new Error('IdentityApi does not implement getIdToken');
|
||||
}
|
||||
logDeprecation('getIdToken');
|
||||
return target.getIdToken();
|
||||
});
|
||||
}
|
||||
|
||||
async signOut(): Promise<void> {
|
||||
if (!this.target) {
|
||||
throw mkError('signOut');
|
||||
}
|
||||
await this.target.signOut();
|
||||
await this.waitForTarget.then(target => target.signOut());
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user