Merge pull request #8945 from backstage/identity/reliable-methods

[Identity] Wait for implementation instead of throwing
This commit is contained in:
Patrik Oldsberg
2022-01-24 17:09:25 +01:00
committed by GitHub
2 changed files with 29 additions and 24 deletions
+7
View File
@@ -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();
}
}