0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

fix(experience): correct first screen fallbacks (#6472)

This commit is contained in:
Xiao Yijun 2024-08-20 14:04:29 +08:00 committed by GitHub
parent 608d2efdb5
commit d4674833c8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 54 additions and 4 deletions

View file

@ -1,9 +1,10 @@
import { AgreeToTermsPolicy, experience } from '@logto/schemas';
import { AgreeToTermsPolicy, experience, SignInMode } from '@logto/schemas';
import { useTranslation } from 'react-i18next';
import { Navigate } from 'react-router-dom';
import FocusedAuthPageLayout from '@/Layout/FocusedAuthPageLayout';
import IdentifierRegisterForm from '@/components/IdentifierRegisterForm';
import { useSieMethods } from '@/hooks/use-sie';
import { identifierInputDescriptionMap } from '@/utils/form';
import useIdentifierSignUpMethods from './use-identifier-sign-up-methods';
@ -11,11 +12,14 @@ import useIdentifierSignUpMethods from './use-identifier-sign-up-methods';
const IdentifierRegister = () => {
const { t } = useTranslation();
const signUpMethods = useIdentifierSignUpMethods();
const { signInMode } = useSieMethods();
/**
* Fallback to sign-in page if no sign up methods are available (not allowed to create an account).
* Fallback to sign-in page in the following cases:
* - Sign-in mode is set to `SignIn` (user registration is not enabled in the sign-in experience configuration)
* - No sign up methods are available
*/
if (signUpMethods.length === 0) {
if (signInMode === SignInMode.SignIn || signUpMethods.length === 0) {
return <Navigate to={`/${experience.routes.signIn}`} />;
}

View file

@ -1,14 +1,22 @@
import { AgreeToTermsPolicy, experience } from '@logto/schemas';
import { useTranslation } from 'react-i18next';
import { Navigate } from 'react-router-dom';
import FocusedAuthPageLayout from '@/Layout/FocusedAuthPageLayout';
import SingleSignOnForm from '@/components/SingleSignOnForm';
import { useSieMethods } from '@/hooks/use-sie';
import useTerms from '@/hooks/use-terms';
const SingleSignOnLanding = () => {
const { t } = useTranslation();
const { singleSignOnEnabled } = useSieMethods();
const { agreeToTermsPolicy } = useTerms();
// Fallback to sign-in page if SSO is not enabled
if (!singleSignOnEnabled) {
return <Navigate to={`/${experience.routes.signIn}`} />;
}
return (
<FocusedAuthPageLayout
pageMeta={{ titleKey: 'action.single_sign_on' }}

View file

@ -41,6 +41,11 @@ export const patchSsoConnectorById = async (id: string, data: Partial<SsoConnect
})
.json<SsoConnectorWithProviderConfig>();
export const clearSsoConnectors = async () => {
const connectors = await getSsoConnectors();
await Promise.all(connectors.map(async (connector) => deleteSsoConnectorById(connector.id)));
};
export class SsoConnectorApi {
readonly connectorInstances = new Map<string, SsoConnector>();

View file

@ -1,7 +1,8 @@
import { ConnectorType } from '@logto/connector-kit';
import { SignInIdentifier } from '@logto/schemas';
import { SignInIdentifier, SignInMode } from '@logto/schemas';
import { updateSignInExperience } from '#src/api/sign-in-experience.js';
import { clearSsoConnectors } from '#src/api/sso-connector.js';
import { demoAppUrl } from '#src/constants.js';
import {
clearConnectorsByTypes,
@ -16,8 +17,12 @@ const { describe, it } = devFeatureTest;
describe('first screen', () => {
beforeAll(async () => {
await clearConnectorsByTypes([ConnectorType.Social, ConnectorType.Email, ConnectorType.Sms]);
await clearSsoConnectors();
await setEmailConnector();
await setSmsConnector();
await updateSignInExperience({
signInMode: SignInMode.SignInAndRegister,
});
});
describe('sign-in page', () => {
@ -44,6 +49,9 @@ describe('first screen', () => {
describe('single sign-on page', () => {
it('should be landed on single sign-on page directly', async () => {
await updateSignInExperience({
singleSignOnEnabled: true,
});
const experience = new ExpectExperience(await browser.newPage());
const url = new URL(demoAppUrl);
url.searchParams.set('first_screen', 'single_sign_on');
@ -51,6 +59,19 @@ describe('first screen', () => {
experience.toBeAt('single-sign-on');
await experience.page.close();
});
it('should fallback to sign-in page if SSO is not enabled', async () => {
// Turn off SSO
await updateSignInExperience({
singleSignOnEnabled: false,
});
const experience = new ExpectExperience(await browser.newPage());
const url = new URL(demoAppUrl);
url.searchParams.set('first_screen', 'single_sign_on');
await experience.page.goto(url.href, { waitUntil: 'networkidle0' });
experience.toBeAt('sign-in');
await experience.page.close();
});
});
describe('identifier sign-in page', () => {
@ -84,6 +105,7 @@ describe('first screen', () => {
},
],
},
signInMode: SignInMode.SignIn,
});
// eslint-disable-next-line @silverhand/fp/no-mutation
@ -161,6 +183,7 @@ describe('first screen', () => {
password: false,
verify: true,
},
signInMode: SignInMode.SignInAndRegister,
});
// eslint-disable-next-line @silverhand/fp/no-mutation
@ -197,5 +220,15 @@ describe('first screen', () => {
await experience.page.goto(url.href, { waitUntil: 'networkidle0' });
experience.toBeAt('sign-in');
});
it('should fallback to sign-in page if sign-in mode is `SignIn` only', async () => {
await updateSignInExperience({
signUp: { identifiers: [SignInIdentifier.Email], password: false, verify: true },
signInMode: SignInMode.SignIn,
});
await experience.page.goto(url.href, { waitUntil: 'networkidle0' });
experience.toBeAt('sign-in');
});
});
});