mirror of
https://github.com/logto-io/logto.git
synced 2025-01-06 20:40:08 -05:00
feat(ui): add native sdk guard logic (#1096)
add native sdk guard logic
This commit is contained in:
parent
142f3f7b77
commit
147775a8f4
2 changed files with 74 additions and 25 deletions
|
@ -1,4 +1,5 @@
|
|||
import { ConnectorData, SearchParameters } from '@/types';
|
||||
import { getLogtoNativeSdk, isNativeWebview } from '@/utils/native-sdk';
|
||||
|
||||
import {
|
||||
filterSocialConnectors,
|
||||
|
@ -15,9 +16,18 @@ const mockConnectors = [
|
|||
{ platform: 'Native', target: 'Alipay' },
|
||||
] as ConnectorData[];
|
||||
|
||||
jest.mock('@/utils/native-sdk', () => ({
|
||||
isNativeWebview: jest.fn(),
|
||||
getLogtoNativeSdk: jest.fn(),
|
||||
}));
|
||||
|
||||
const getLogtoNativeSdkMock = getLogtoNativeSdk as jest.Mock;
|
||||
const isNativeWebviewMock = isNativeWebview as jest.Mock;
|
||||
|
||||
describe('filterSocialConnectors', () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('undefined input should return empty list', () => {
|
||||
|
@ -25,6 +35,7 @@ describe('filterSocialConnectors', () => {
|
|||
});
|
||||
|
||||
it('filter Web Connectors', () => {
|
||||
isNativeWebviewMock.mockImplementation(() => false);
|
||||
expect(filterSocialConnectors(mockConnectors)).toEqual([
|
||||
{ platform: 'Web', target: 'facebook' },
|
||||
{ platform: 'Web', target: 'google' },
|
||||
|
@ -32,17 +43,28 @@ describe('filterSocialConnectors', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
it('filter Native Connectors', () => {
|
||||
/* eslint-disable @silverhand/fp/no-mutation */
|
||||
// @ts-expect-error mock global object
|
||||
globalThis.logtoNativeSdk = {
|
||||
platform: 'ios',
|
||||
it('Native Platform should return empty if not getPostMessage method is injected', () => {
|
||||
isNativeWebviewMock.mockImplementation(() => true);
|
||||
getLogtoNativeSdkMock.mockImplementation(() => ({
|
||||
supportedConnector: {
|
||||
universal: true,
|
||||
nativeTargets: ['Web', 'WeChat'],
|
||||
nativeTargets: ['WeChat', 'Alipay'],
|
||||
},
|
||||
};
|
||||
/* eslint-enable @silverhand/fp/no-mutation */
|
||||
}));
|
||||
|
||||
expect(filterSocialConnectors(mockConnectors)).toEqual([]);
|
||||
});
|
||||
|
||||
it('filter Native & Universal Connectors', () => {
|
||||
isNativeWebviewMock.mockImplementation(() => true);
|
||||
getLogtoNativeSdkMock.mockImplementation(() => ({
|
||||
supportedConnector: {
|
||||
universal: true,
|
||||
nativeTargets: ['WeChat'],
|
||||
},
|
||||
getPostMessage: jest.fn(),
|
||||
callbackLink: 'logto://callback',
|
||||
}));
|
||||
|
||||
expect(filterSocialConnectors(mockConnectors)).toEqual([
|
||||
{ platform: 'Universal', target: 'facebook' },
|
||||
|
@ -50,17 +72,31 @@ describe('filterSocialConnectors', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
it('filter Native & Universal Connectors', () => {
|
||||
/* eslint-disable @silverhand/fp/no-mutation */
|
||||
// @ts-expect-error mock global object
|
||||
globalThis.logtoNativeSdk = {
|
||||
it('filter Native & Universal Connectors with out callbackLink should only return native connectors', () => {
|
||||
isNativeWebviewMock.mockImplementation(() => true);
|
||||
getLogtoNativeSdkMock.mockImplementation(() => ({
|
||||
supportedConnector: {
|
||||
universal: true,
|
||||
nativeTargets: ['WeChat'],
|
||||
},
|
||||
getPostMessage: jest.fn(),
|
||||
}));
|
||||
|
||||
expect(filterSocialConnectors(mockConnectors)).toEqual([
|
||||
{ platform: 'Native', target: 'WeChat' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('filter Native Connectors', () => {
|
||||
isNativeWebviewMock.mockImplementation(() => true);
|
||||
getLogtoNativeSdkMock.mockImplementation(() => ({
|
||||
platform: 'ios',
|
||||
supportedConnector: {
|
||||
universal: false,
|
||||
nativeTargets: ['Web', 'WeChat'],
|
||||
nativeTargets: ['WeChat'],
|
||||
},
|
||||
};
|
||||
/* eslint-enable @silverhand/fp/no-mutation */
|
||||
getPostMessage: jest.fn(),
|
||||
}));
|
||||
|
||||
expect(filterSocialConnectors(mockConnectors)).toEqual([
|
||||
{ platform: 'Native', target: 'WeChat' },
|
||||
|
@ -71,6 +107,7 @@ describe('filterSocialConnectors', () => {
|
|||
describe('filterPreviewSocialConnectors', () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('undefined input should return empty list', () => {
|
||||
|
@ -97,13 +134,10 @@ describe('filterPreviewSocialConnectors', () => {
|
|||
|
||||
describe('buildSocialLandingUri', () => {
|
||||
it('buildSocialLandingUri', () => {
|
||||
/* eslint-disable @silverhand/fp/no-mutation */
|
||||
// @ts-expect-error mock global object
|
||||
globalThis.logtoNativeSdk = {
|
||||
getLogtoNativeSdkMock.mockImplementation(() => ({
|
||||
platform: 'ios',
|
||||
callbackLink: 'logto://callback',
|
||||
};
|
||||
/* eslint-enable @silverhand/fp/no-mutation */
|
||||
}));
|
||||
|
||||
const redirectUri = 'https://www.example.com/callback';
|
||||
const socialLandingPath = '/social/landing';
|
||||
|
|
|
@ -88,10 +88,16 @@ export const filterSocialConnectors = (socialConnectors?: ConnectorData[]) => {
|
|||
/**
|
||||
* Native Webview Environment
|
||||
* Accepts both native and universal platform connectors.
|
||||
* Insert universal connectors only if there is no native platform connector provided with the same target.
|
||||
* Native platform has higher priority.
|
||||
**/
|
||||
|
||||
const { supportedConnector, getPostMessage, callbackLink } = getLogtoNativeSdk() ?? {};
|
||||
|
||||
if (!getPostMessage) {
|
||||
// Invalid Native SDK bridge injections, not able to sign in with any social connectors.
|
||||
return [];
|
||||
}
|
||||
|
||||
for (const connector of socialConnectors) {
|
||||
const { platform, target } = connector;
|
||||
|
||||
|
@ -99,19 +105,28 @@ export const filterSocialConnectors = (socialConnectors?: ConnectorData[]) => {
|
|||
continue;
|
||||
}
|
||||
|
||||
const { supportedConnector } = getLogtoNativeSdk() ?? {};
|
||||
|
||||
// No native supportedConnector settings found
|
||||
// Native SupportedConnector Settings is required
|
||||
if (!supportedConnector) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Native supported nativeTargets flag is required
|
||||
if (platform === 'Native' && supportedConnector.nativeTargets.includes(target)) {
|
||||
connectorMap.set(target, connector);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (platform === 'Universal' && supportedConnector.universal && !connectorMap.get(target)) {
|
||||
/**
|
||||
* Native supportedConnector.universal flag is required
|
||||
* Native callback link settings is required
|
||||
* Only if there is no native platform connector provided with the same target.
|
||||
**/
|
||||
if (
|
||||
platform === 'Universal' &&
|
||||
supportedConnector.universal &&
|
||||
callbackLink &&
|
||||
!connectorMap.get(target)
|
||||
) {
|
||||
connectorMap.set(target, connector);
|
||||
continue;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue