@backstage/core-app-api 0.5.0 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/dist/index.d.ts +6 -11
- package/dist/index.esm.js +51 -185
- package/dist/index.esm.js.map +1 -1
- package/package.json +19 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# @backstage/core-app-api
|
|
2
2
|
|
|
3
|
+
## 0.5.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5
|
|
8
|
+
- c77c5c7eb6: Added `backstage.role` to `package.json`
|
|
9
|
+
- Updated dependencies
|
|
10
|
+
- @backstage/core-plugin-api@0.6.1
|
|
11
|
+
- @backstage/config@0.1.14
|
|
12
|
+
- @backstage/types@0.1.2
|
|
13
|
+
- @backstage/version-bridge@0.1.2
|
|
14
|
+
|
|
15
|
+
## 0.5.2
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- 40775bd263: Switched out the `GithubAuth` implementation to use the common `OAuth2` implementation. This relies on the simultaneous change in `@backstage/plugin-auth-backend` that enabled access token storage in cookies rather than the current solution that's based on `LocalStorage`.
|
|
20
|
+
|
|
21
|
+
> **NOTE:** Make sure you upgrade the `auth-backend` deployment before or at the same time as you deploy this change.
|
|
22
|
+
|
|
23
|
+
## 0.5.2-next.0
|
|
24
|
+
|
|
25
|
+
### Patch Changes
|
|
26
|
+
|
|
27
|
+
- 40775bd263: Switched out the `GithubAuth` implementation to use the common `OAuth2` implementation. This relies on the simultaneous change in `@backstage/plugin-auth-backend` that enabled access token storage in cookies rather than the current solution that's based on `LocalStorage`.
|
|
28
|
+
|
|
29
|
+
> **NOTE:** Make sure you upgrade the `auth-backend` deployment before or at the same time as you deploy this change.
|
|
30
|
+
|
|
31
|
+
## 0.5.1
|
|
32
|
+
|
|
33
|
+
### Patch Changes
|
|
34
|
+
|
|
35
|
+
- f959c22787: 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.
|
|
36
|
+
|
|
37
|
+
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).
|
|
38
|
+
|
|
3
39
|
## 0.5.0
|
|
4
40
|
|
|
5
41
|
### Minor Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode, PropsWithChildren, ComponentType } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
-
import { ApiHolder, ApiRef, ApiFactory, AnyApiRef, ProfileInfo, BackstageIdentityResponse, OAuthRequestApi, DiscoveryApi, AuthProviderInfo,
|
|
3
|
+
import { ApiHolder, ApiRef, ApiFactory, AnyApiRef, ProfileInfo, BackstageIdentityResponse, OAuthRequestApi, DiscoveryApi, AuthProviderInfo, githubAuthApiRef, gitlabAuthApiRef, googleAuthApiRef, OAuthApi, OpenIdConnectApi, ProfileInfoApi, BackstageIdentityApi, SessionApi, SessionState, AuthRequestOptions, oktaAuthApiRef, auth0AuthApiRef, microsoftAuthApiRef, oneloginAuthApiRef, bitbucketAuthApiRef, atlassianAuthApiRef, AlertApi, AlertMessage, AnalyticsApi, AnalyticsEvent, AppThemeApi, AppTheme, ErrorApi, ErrorApiError, ErrorApiErrorContext, FeatureFlagsApi, FeatureFlag, FeatureFlagsSaveOptions, FetchApi, IdentityApi, OAuthRequesterOptions, OAuthRequester, PendingOAuthRequest, StorageApi, StorageValueSnapshot, BackstagePlugin, IconComponent, ExternalRouteRef, AnyApiFactory, RouteRef, SubRouteRef } from '@backstage/core-plugin-api';
|
|
4
4
|
import * as _backstage_types from '@backstage/types';
|
|
5
5
|
import { Observable, JsonValue } from '@backstage/types';
|
|
6
6
|
import { Config, AppConfig } from '@backstage/config';
|
|
@@ -130,16 +130,11 @@ declare type AuthApiCreateOptions = {
|
|
|
130
130
|
*
|
|
131
131
|
* @public
|
|
132
132
|
*/
|
|
133
|
-
declare class GithubAuth
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
signOut(): Promise<void>;
|
|
139
|
-
sessionState$(): Observable<SessionState>;
|
|
140
|
-
getAccessToken(scope?: string, options?: AuthRequestOptions): Promise<string>;
|
|
141
|
-
getBackstageIdentity(options?: AuthRequestOptions): Promise<BackstageIdentityResponse | undefined>;
|
|
142
|
-
getProfile(options?: AuthRequestOptions): Promise<ProfileInfo | undefined>;
|
|
133
|
+
declare class GithubAuth {
|
|
134
|
+
static create(options: OAuthApiCreateOptions): typeof githubAuthApiRef.T;
|
|
135
|
+
/**
|
|
136
|
+
* @deprecated This method is deprecated and will be removed in a future release.
|
|
137
|
+
*/
|
|
143
138
|
static normalizeScope(scope?: string): Set<string>;
|
|
144
139
|
}
|
|
145
140
|
|
package/dist/index.esm.js
CHANGED
|
@@ -725,167 +725,7 @@ class AuthSessionStore {
|
|
|
725
725
|
}
|
|
726
726
|
}
|
|
727
727
|
|
|
728
|
-
class OptionalRefreshSessionManagerMux {
|
|
729
|
-
constructor(options) {
|
|
730
|
-
this.stateTracker = new SessionStateTracker();
|
|
731
|
-
this.sessionCanRefresh = options.sessionCanRefresh;
|
|
732
|
-
this.staticSessionManager = options.staticSessionManager;
|
|
733
|
-
this.refreshingSessionManager = options.refreshingSessionManager;
|
|
734
|
-
}
|
|
735
|
-
async getSession(options) {
|
|
736
|
-
const staticSession = await this.staticSessionManager.getSession({
|
|
737
|
-
...options,
|
|
738
|
-
optional: true
|
|
739
|
-
});
|
|
740
|
-
if (staticSession) {
|
|
741
|
-
this.stateTracker.setIsSignedIn(true);
|
|
742
|
-
return staticSession;
|
|
743
|
-
}
|
|
744
|
-
const session = await this.refreshingSessionManager.getSession(options);
|
|
745
|
-
if (!session) {
|
|
746
|
-
this.stateTracker.setIsSignedIn(false);
|
|
747
|
-
return void 0;
|
|
748
|
-
}
|
|
749
|
-
if (this.sessionCanRefresh(session)) {
|
|
750
|
-
this.stateTracker.setIsSignedIn(true);
|
|
751
|
-
return session;
|
|
752
|
-
}
|
|
753
|
-
this.staticSessionManager.setSession(session);
|
|
754
|
-
this.stateTracker.setIsSignedIn(true);
|
|
755
|
-
return session;
|
|
756
|
-
}
|
|
757
|
-
async removeSession() {
|
|
758
|
-
await Promise.all([
|
|
759
|
-
this.refreshingSessionManager.removeSession(),
|
|
760
|
-
this.staticSessionManager.removeSession()
|
|
761
|
-
]);
|
|
762
|
-
this.stateTracker.setIsSignedIn(false);
|
|
763
|
-
}
|
|
764
|
-
sessionState$() {
|
|
765
|
-
return this.stateTracker.sessionState$();
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
const githubSessionSchema = z.object({
|
|
770
|
-
providerInfo: z.object({
|
|
771
|
-
accessToken: z.string(),
|
|
772
|
-
scopes: z.set(z.string()),
|
|
773
|
-
expiresAt: z.date().optional()
|
|
774
|
-
}),
|
|
775
|
-
profile: z.object({
|
|
776
|
-
email: z.string().optional(),
|
|
777
|
-
displayName: z.string().optional(),
|
|
778
|
-
picture: z.string().optional()
|
|
779
|
-
}),
|
|
780
|
-
backstageIdentity: z.object({
|
|
781
|
-
id: z.string(),
|
|
782
|
-
token: z.string(),
|
|
783
|
-
identity: z.object({
|
|
784
|
-
type: z.literal("user"),
|
|
785
|
-
userEntityRef: z.string(),
|
|
786
|
-
ownershipEntityRefs: z.array(z.string())
|
|
787
|
-
})
|
|
788
|
-
})
|
|
789
|
-
});
|
|
790
|
-
|
|
791
728
|
const DEFAULT_PROVIDER$a = {
|
|
792
|
-
id: "github",
|
|
793
|
-
title: "GitHub",
|
|
794
|
-
icon: () => null
|
|
795
|
-
};
|
|
796
|
-
class GithubAuth {
|
|
797
|
-
constructor(sessionManager) {
|
|
798
|
-
this.sessionManager = sessionManager;
|
|
799
|
-
}
|
|
800
|
-
static create(options) {
|
|
801
|
-
const {
|
|
802
|
-
discoveryApi,
|
|
803
|
-
environment = "development",
|
|
804
|
-
provider = DEFAULT_PROVIDER$a,
|
|
805
|
-
oauthRequestApi,
|
|
806
|
-
defaultScopes = ["read:user"]
|
|
807
|
-
} = options;
|
|
808
|
-
const connector = new DefaultAuthConnector({
|
|
809
|
-
discoveryApi,
|
|
810
|
-
environment,
|
|
811
|
-
provider,
|
|
812
|
-
oauthRequestApi,
|
|
813
|
-
sessionTransform(res) {
|
|
814
|
-
return {
|
|
815
|
-
...res,
|
|
816
|
-
providerInfo: {
|
|
817
|
-
accessToken: res.providerInfo.accessToken,
|
|
818
|
-
scopes: GithubAuth.normalizeScope(res.providerInfo.scope),
|
|
819
|
-
expiresAt: res.providerInfo.expiresInSeconds ? new Date(Date.now() + res.providerInfo.expiresInSeconds * 1e3) : void 0
|
|
820
|
-
}
|
|
821
|
-
};
|
|
822
|
-
}
|
|
823
|
-
});
|
|
824
|
-
const refreshingSessionManager = new RefreshingAuthSessionManager({
|
|
825
|
-
connector,
|
|
826
|
-
defaultScopes: new Set(defaultScopes),
|
|
827
|
-
sessionScopes: (session) => session.providerInfo.scopes,
|
|
828
|
-
sessionShouldRefresh: (session) => {
|
|
829
|
-
const { expiresAt } = session.providerInfo;
|
|
830
|
-
if (!expiresAt) {
|
|
831
|
-
return false;
|
|
832
|
-
}
|
|
833
|
-
const expiresInSec = (expiresAt.getTime() - Date.now()) / 1e3;
|
|
834
|
-
return expiresInSec < 60 * 5;
|
|
835
|
-
}
|
|
836
|
-
});
|
|
837
|
-
const staticSessionManager = new AuthSessionStore({
|
|
838
|
-
manager: new StaticAuthSessionManager({
|
|
839
|
-
connector,
|
|
840
|
-
defaultScopes: new Set(defaultScopes),
|
|
841
|
-
sessionScopes: (session) => session.providerInfo.scopes
|
|
842
|
-
}),
|
|
843
|
-
storageKey: `${provider.id}Session`,
|
|
844
|
-
schema: githubSessionSchema,
|
|
845
|
-
sessionScopes: (session) => session.providerInfo.scopes
|
|
846
|
-
});
|
|
847
|
-
const sessionManagerMux = new OptionalRefreshSessionManagerMux({
|
|
848
|
-
refreshingSessionManager,
|
|
849
|
-
staticSessionManager,
|
|
850
|
-
sessionCanRefresh: (session) => session.providerInfo.expiresAt !== void 0
|
|
851
|
-
});
|
|
852
|
-
return new GithubAuth(sessionManagerMux);
|
|
853
|
-
}
|
|
854
|
-
async signIn() {
|
|
855
|
-
await this.getAccessToken();
|
|
856
|
-
}
|
|
857
|
-
async signOut() {
|
|
858
|
-
await this.sessionManager.removeSession();
|
|
859
|
-
}
|
|
860
|
-
sessionState$() {
|
|
861
|
-
return this.sessionManager.sessionState$();
|
|
862
|
-
}
|
|
863
|
-
async getAccessToken(scope, options) {
|
|
864
|
-
var _a;
|
|
865
|
-
const session = await this.sessionManager.getSession({
|
|
866
|
-
...options,
|
|
867
|
-
scopes: GithubAuth.normalizeScope(scope)
|
|
868
|
-
});
|
|
869
|
-
return (_a = session == null ? void 0 : session.providerInfo.accessToken) != null ? _a : "";
|
|
870
|
-
}
|
|
871
|
-
async getBackstageIdentity(options = {}) {
|
|
872
|
-
const session = await this.sessionManager.getSession(options);
|
|
873
|
-
return session == null ? void 0 : session.backstageIdentity;
|
|
874
|
-
}
|
|
875
|
-
async getProfile(options = {}) {
|
|
876
|
-
const session = await this.sessionManager.getSession(options);
|
|
877
|
-
return session == null ? void 0 : session.profile;
|
|
878
|
-
}
|
|
879
|
-
static normalizeScope(scope) {
|
|
880
|
-
if (!scope) {
|
|
881
|
-
return /* @__PURE__ */ new Set();
|
|
882
|
-
}
|
|
883
|
-
const scopeList = Array.isArray(scope) ? scope : scope.split(/[\s|,]/).filter(Boolean);
|
|
884
|
-
return new Set(scopeList);
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
const DEFAULT_PROVIDER$9 = {
|
|
889
729
|
id: "oauth2",
|
|
890
730
|
title: "Your Identity Provider",
|
|
891
731
|
icon: () => null
|
|
@@ -895,7 +735,7 @@ class OAuth2 {
|
|
|
895
735
|
const {
|
|
896
736
|
discoveryApi,
|
|
897
737
|
environment = "development",
|
|
898
|
-
provider = DEFAULT_PROVIDER$
|
|
738
|
+
provider = DEFAULT_PROVIDER$a,
|
|
899
739
|
oauthRequestApi,
|
|
900
740
|
defaultScopes = [],
|
|
901
741
|
scopeTransform = (x) => x
|
|
@@ -972,6 +812,37 @@ class OAuth2 {
|
|
|
972
812
|
}
|
|
973
813
|
}
|
|
974
814
|
|
|
815
|
+
const DEFAULT_PROVIDER$9 = {
|
|
816
|
+
id: "github",
|
|
817
|
+
title: "GitHub",
|
|
818
|
+
icon: () => null
|
|
819
|
+
};
|
|
820
|
+
class GithubAuth {
|
|
821
|
+
static create(options) {
|
|
822
|
+
const {
|
|
823
|
+
discoveryApi,
|
|
824
|
+
environment = "development",
|
|
825
|
+
provider = DEFAULT_PROVIDER$9,
|
|
826
|
+
oauthRequestApi,
|
|
827
|
+
defaultScopes = ["read:user"]
|
|
828
|
+
} = options;
|
|
829
|
+
return OAuth2.create({
|
|
830
|
+
discoveryApi,
|
|
831
|
+
oauthRequestApi,
|
|
832
|
+
provider,
|
|
833
|
+
environment,
|
|
834
|
+
defaultScopes
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
static normalizeScope(scope) {
|
|
838
|
+
if (!scope) {
|
|
839
|
+
return /* @__PURE__ */ new Set();
|
|
840
|
+
}
|
|
841
|
+
const scopeList = Array.isArray(scope) ? scope : scope.split(/[\s|,]/).filter(Boolean);
|
|
842
|
+
return new Set(scopeList);
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
|
|
975
846
|
const DEFAULT_PROVIDER$8 = {
|
|
976
847
|
id: "gitlab",
|
|
977
848
|
title: "GitLab",
|
|
@@ -2211,8 +2082,16 @@ function logDeprecation(thing) {
|
|
|
2211
2082
|
console.warn(`WARNING: Call to ${thing} is deprecated and will break in the future`);
|
|
2212
2083
|
}
|
|
2213
2084
|
class AppIdentityProxy {
|
|
2085
|
+
constructor() {
|
|
2086
|
+
this.resolveTarget = () => {
|
|
2087
|
+
};
|
|
2088
|
+
this.waitForTarget = new Promise((resolve) => {
|
|
2089
|
+
this.resolveTarget = resolve;
|
|
2090
|
+
});
|
|
2091
|
+
}
|
|
2214
2092
|
setTarget(identityApi) {
|
|
2215
2093
|
this.target = identityApi;
|
|
2094
|
+
this.resolveTarget(identityApi);
|
|
2216
2095
|
}
|
|
2217
2096
|
getUserId() {
|
|
2218
2097
|
if (!this.target) {
|
|
@@ -2235,42 +2114,29 @@ class AppIdentityProxy {
|
|
|
2235
2114
|
return this.target.getProfile();
|
|
2236
2115
|
}
|
|
2237
2116
|
async getProfileInfo() {
|
|
2238
|
-
|
|
2239
|
-
throw mkError("getProfileInfo");
|
|
2240
|
-
}
|
|
2241
|
-
return this.target.getProfileInfo();
|
|
2117
|
+
return this.waitForTarget.then((target) => target.getProfileInfo());
|
|
2242
2118
|
}
|
|
2243
2119
|
async getBackstageIdentity() {
|
|
2244
|
-
|
|
2245
|
-
throw mkError("getBackstageIdentity");
|
|
2246
|
-
}
|
|
2247
|
-
const identity = await this.target.getBackstageIdentity();
|
|
2120
|
+
const identity = await this.waitForTarget.then((target) => target.getBackstageIdentity());
|
|
2248
2121
|
if (!identity.userEntityRef.match(/^.*:.*\/.*$/)) {
|
|
2249
2122
|
console.warn(`WARNING: The App IdentityApi provided an invalid userEntityRef, '${identity.userEntityRef}'. It must be a full Entity Reference of the form '<kind>:<namespace>/<name>'.`);
|
|
2250
2123
|
}
|
|
2251
2124
|
return identity;
|
|
2252
2125
|
}
|
|
2253
2126
|
async getCredentials() {
|
|
2254
|
-
|
|
2255
|
-
throw mkError("getCredentials");
|
|
2256
|
-
}
|
|
2257
|
-
return this.target.getCredentials();
|
|
2127
|
+
return this.waitForTarget.then((target) => target.getCredentials());
|
|
2258
2128
|
}
|
|
2259
2129
|
async getIdToken() {
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
return this.target.getIdToken();
|
|
2130
|
+
return this.waitForTarget.then((target) => {
|
|
2131
|
+
if (!target.getIdToken) {
|
|
2132
|
+
throw new Error("IdentityApi does not implement getIdToken");
|
|
2133
|
+
}
|
|
2134
|
+
logDeprecation("getIdToken");
|
|
2135
|
+
return target.getIdToken();
|
|
2136
|
+
});
|
|
2268
2137
|
}
|
|
2269
2138
|
async signOut() {
|
|
2270
|
-
|
|
2271
|
-
throw mkError("signOut");
|
|
2272
|
-
}
|
|
2273
|
-
await this.target.signOut();
|
|
2139
|
+
await this.waitForTarget.then((target) => target.signOut());
|
|
2274
2140
|
location.reload();
|
|
2275
2141
|
}
|
|
2276
2142
|
}
|