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:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-app-api': minor
|
||||
---
|
||||
|
||||
add login in popup options to config popup width and height
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 };
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user