feat: add login in popup options to config popup width and weigth

Signed-off-by: rui ma <ruima@alauda.io>
This commit is contained in:
rui ma
2023-07-12 18:14:04 +08:00
parent ba3b7d1782
commit a77ddf7ccd
8 changed files with 144 additions and 4 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-app-api': minor
---
add login in popup options to config popup width and height
+13
View File
@@ -101,6 +101,19 @@ export const apis: AnyApiFactory[] = [
},
environment: configApi.getOptionalString('auth.environment'),
defaultScopes: ['openid', 'profile', 'email'],
popupOptions: {
// optional, used to customize login in popup size
size: {
fullscreen: true,
},
/**
* or specify popup width and height
* size: {
width: 1000,
height: 1000,
}
*/
},
}),
}),
/* highlight-add-end */
+16
View File
@@ -526,6 +526,7 @@ export class OAuth2
// @public
export type OAuth2CreateOptions = OAuthApiCreateOptions & {
scopeTransform?: (scopes: string[]) => string[];
popupOptions?: PopupOptions;
};
// @public
@@ -577,6 +578,21 @@ export type OneLoginAuthCreateOptions = {
provider?: AuthProviderInfo;
};
// @public
export type PopupOptions = {
size?:
| {
width: number;
height: number;
fullscreen?: never;
}
| {
width?: never;
height?: never;
fullscreen: boolean;
};
};
// @public
export class SamlAuth
implements ProfileInfoApi, BackstageIdentityApi, SessionApi
@@ -14,7 +14,10 @@
* limitations under the License.
*/
import { DefaultAuthConnector } from '../../../../lib/AuthConnector';
import {
DefaultAuthConnector,
PopupOptions,
} from '../../../../lib/AuthConnector';
import { RefreshingAuthSessionManager } from '../../../../lib/AuthSessionManager';
import { SessionManager } from '../../../../lib/AuthSessionManager/types';
import {
@@ -38,6 +41,7 @@ import { OAuthApiCreateOptions } from '../types';
*/
export type OAuth2CreateOptions = OAuthApiCreateOptions & {
scopeTransform?: (scopes: string[]) => string[];
popupOptions?: PopupOptions;
};
export type OAuth2Response = {
@@ -79,6 +83,7 @@ export default class OAuth2
oauthRequestApi,
defaultScopes = [],
scopeTransform = x => x,
popupOptions,
} = options;
const connector = new DefaultAuthConnector({
@@ -103,6 +108,7 @@ export default class OAuth2
},
};
},
popupOptions,
});
const sessionManager = new RefreshingAuthSessionManager({
@@ -20,6 +20,7 @@ import {
} from '@backstage/core-plugin-api';
export type { OAuth2CreateOptions } from './OAuth2';
export type { PopupOptions } from '../../../../lib/AuthConnector';
/**
* Session information for generic OAuth2 auth.
*
@@ -167,6 +167,80 @@ describe('DefaultAuthConnector', () => {
await expect(sessionPromise).resolves.toBe('my-session');
expect(popupSpy).toHaveBeenCalledTimes(1);
expect(popupSpy).toHaveBeenCalledWith({
name: 'My Provider Login',
origin: 'http://my-host',
url: 'http://my-host/api/auth/my-provider/start?scope=&origin=http%3A%2F%2Flocalhost&flow=popup&env=production',
width: 450,
height: 730,
});
});
it('should show popup fullscreen', async () => {
const popupSpy = jest
.spyOn(loginPopup, 'showLoginPopup')
.mockResolvedValue('my-session');
jest.spyOn(window.screen, 'width', 'get').mockReturnValue(1000);
jest.spyOn(window.screen, 'height', 'get').mockReturnValue(1000);
const connector = new DefaultAuthConnector({
...defaultOptions,
oauthRequestApi: new MockOAuthApi(),
sessionTransform: str => str,
popupOptions: {
size: {
fullscreen: true,
},
},
});
const sessionPromise = connector.createSession({
scopes: new Set(),
instantPopup: true,
});
await expect(sessionPromise).resolves.toBe('my-session');
expect(popupSpy).toHaveBeenCalledWith({
height: 1000,
name: 'My Provider Login',
origin: 'http://my-host',
url: 'http://my-host/api/auth/my-provider/start?scope=&origin=http%3A%2F%2Flocalhost&flow=popup&env=production',
width: 1000,
});
});
it('should show popup with special width and height', async () => {
const popupSpy = jest
.spyOn(loginPopup, 'showLoginPopup')
.mockResolvedValue('my-session');
const connector = new DefaultAuthConnector({
...defaultOptions,
oauthRequestApi: new MockOAuthApi(),
sessionTransform: str => str,
popupOptions: {
size: {
width: 500,
height: 1000,
},
},
});
const sessionPromise = connector.createSession({
scopes: new Set(),
instantPopup: true,
});
await expect(sessionPromise).resolves.toBe('my-session');
expect(popupSpy).toHaveBeenCalledWith({
name: 'My Provider Login',
origin: 'http://my-host',
url: 'http://my-host/api/auth/my-provider/start?scope=&origin=http%3A%2F%2Flocalhost&flow=popup&env=production',
width: 500,
height: 1000,
});
});
it('should use join func to join scopes', async () => {
@@ -21,7 +21,7 @@ import {
OAuthRequester,
} from '@backstage/core-plugin-api';
import { showLoginPopup } from '../loginPopup';
import { AuthConnector, CreateSessionOptions } from './types';
import { AuthConnector, CreateSessionOptions, PopupOptions } from './types';
let warned = false;
@@ -55,6 +55,10 @@ type Options<AuthSession> = {
* ConfigApi instance used to configure authentication flow of pop-up or redirect.
*/
configApi?: ConfigApi;
/**
* Options used to configure auth popup
*/
popupOptions?: PopupOptions;
};
function defaultJoinScopes(scopes: Set<string>) {
@@ -76,6 +80,7 @@ export class DefaultAuthConnector<AuthSession>
private readonly authRequester: OAuthRequester<AuthSession>;
private readonly sessionTransform: (response: any) => Promise<AuthSession>;
private readonly enableExperimentalRedirectFlow: boolean;
private readonly popupOptions: PopupOptions | undefined;
constructor(options: Options<AuthSession>) {
const {
configApi,
@@ -85,6 +90,7 @@ export class DefaultAuthConnector<AuthSession>
joinScopes = defaultJoinScopes,
oauthRequestApi,
sessionTransform = id => id,
popupOptions,
} = options;
if (!warned && !configApi) {
@@ -114,6 +120,7 @@ export class DefaultAuthConnector<AuthSession>
this.provider = provider;
this.joinScopesFunc = joinScopes;
this.sessionTransform = sessionTransform;
this.popupOptions = popupOptions;
}
async createSession(options: CreateSessionOptions): Promise<AuthSession> {
@@ -188,12 +195,20 @@ export class DefaultAuthConnector<AuthSession>
flow: 'popup',
});
const width = this.popupOptions?.size?.fullscreen
? window.screen.width
: this.popupOptions?.size?.width || 450;
const height = this.popupOptions?.size?.fullscreen
? window.screen.height
: this.popupOptions?.size?.height || 730;
const payload = await showLoginPopup({
url: popupUrl,
name: `${this.provider.title} Login`,
origin: new URL(popupUrl).origin,
width: 450,
height: 730,
width,
height,
});
return await this.sessionTransform(payload);
@@ -28,3 +28,13 @@ export type AuthConnector<AuthSession> = {
refreshSession(scopes?: Set<string>): Promise<AuthSession>;
removeSession(): Promise<void>;
};
/**
* Options for login popup
* @public
*/
export type PopupOptions = {
size?:
| { width: number; height: number; fullscreen?: never }
| { width?: never; height?: never; fullscreen: boolean };
};