mirror of
https://github.com/logto-io/logto.git
synced 2025-02-17 22:04:19 -05:00
refactor(core,ui): fix cache issue when sign in to live preview (#3495)
This commit is contained in:
parent
c17fb35298
commit
5a2f3c3461
8 changed files with 65 additions and 18 deletions
|
@ -9,7 +9,6 @@ import i18next from 'i18next';
|
|||
import Provider, { errors, ResourceServer } from 'oidc-provider';
|
||||
import snakecaseKeys from 'snakecase-keys';
|
||||
|
||||
import { wellKnownCache } from '#src/caches/well-known.js';
|
||||
import type { EnvSet } from '#src/env-set/index.js';
|
||||
import { addOidcEventListeners } from '#src/event-listeners/index.js';
|
||||
import koaAuditLog from '#src/middleware/koa-audit-log.js';
|
||||
|
@ -151,16 +150,11 @@ export default function initOidc(
|
|||
|
||||
const appendParameters = (path: string) => {
|
||||
// `notification` is for showing a text banner on the homepage
|
||||
return isDemoApp ? path + `?notification=demo_app.notification` : path;
|
||||
return isDemoApp ? path + `?notification=demo_app.notification&no_cache` : path;
|
||||
};
|
||||
|
||||
switch (interaction.prompt.name) {
|
||||
case 'login': {
|
||||
// Always fetch the latest sign-in experience config for demo app (live preview)
|
||||
if (isDemoApp) {
|
||||
wellKnownCache.invalidate(tenantId, ['sie', 'sie-full']);
|
||||
}
|
||||
|
||||
const isSignUp =
|
||||
ctx.oidc.params?.[OIDCExtraParametersKey.InteractionMode] === InteractionMode.signUp;
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ export default function koaInteractionSie<StateT, ContextT, ResponseT>(
|
|||
tenantId: string
|
||||
): MiddlewareType<StateT, WithInteractionSieContext<ContextT>, ResponseT> {
|
||||
return async (ctx, next) => {
|
||||
if (noCache(ctx.headers)) {
|
||||
if (noCache(ctx.request)) {
|
||||
wellKnownCache.invalidate(tenantId, ['sie']);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,8 +39,9 @@ export default function wellKnownRoutes<T extends AnonymousRouter>(
|
|||
'/.well-known/sign-in-exp',
|
||||
koaGuard({ response: guardFullSignInExperience, status: 200 }),
|
||||
async (ctx, next) => {
|
||||
if (noCache(ctx.headers)) {
|
||||
if (noCache(ctx.request)) {
|
||||
wellKnownCache.invalidate(tenantId, ['sie', 'sie-full']);
|
||||
console.log('invalidated');
|
||||
}
|
||||
|
||||
ctx.body = await getFullSignInExperience();
|
||||
|
@ -59,7 +60,7 @@ export default function wellKnownRoutes<T extends AnonymousRouter>(
|
|||
status: 200,
|
||||
}),
|
||||
async (ctx, next) => {
|
||||
if (noCache(ctx.headers)) {
|
||||
if (noCache(ctx.request)) {
|
||||
wellKnownCache.invalidate(tenantId, ['sie', 'phrases-lng-tags', 'phrases']);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import type { IncomingHttpHeaders } from 'http';
|
||||
import type { Request } from 'koa';
|
||||
|
||||
export const noCache = (headers: IncomingHttpHeaders): boolean =>
|
||||
headers['cache-control']?.split(',').some((value) => value.trim().toLowerCase() === 'no-cache') ??
|
||||
false;
|
||||
export const noCache = (request: Request): boolean =>
|
||||
Boolean(
|
||||
request.headers['cache-control']
|
||||
?.split(',')
|
||||
.some((value) => ['no-cache', 'no-store'].includes(value.trim().toLowerCase()))
|
||||
) || request.URL.searchParams.get('no_cache') !== null;
|
||||
|
|
|
@ -23,10 +23,13 @@ import SocialLinkAccount from './pages/SocialLinkAccount';
|
|||
import SocialSignIn from './pages/SocialSignInCallback';
|
||||
import Springboard from './pages/Springboard';
|
||||
import VerificationCode from './pages/VerificationCode';
|
||||
import { handleSearchParametersData } from './utils/search-parameters';
|
||||
import { getSignInExperienceSettings, setFavIcon } from './utils/sign-in-experience';
|
||||
|
||||
import './scss/normalized.scss';
|
||||
|
||||
handleSearchParametersData();
|
||||
|
||||
const App = () => {
|
||||
const { context, Provider } = usePageContext();
|
||||
const { experienceSettings, setLoading, setExperienceSettings } = context;
|
||||
|
|
|
@ -3,13 +3,29 @@
|
|||
* The API will be deprecated in the future once SSR is implemented.
|
||||
*/
|
||||
|
||||
import { conditionalString } from '@silverhand/essentials';
|
||||
import type { Nullable, Optional } from '@silverhand/essentials';
|
||||
import { conditional } from '@silverhand/essentials';
|
||||
import ky from 'ky';
|
||||
|
||||
import type { SignInExperienceResponse } from '@/types';
|
||||
import { searchKeys } from '@/utils/search-parameters';
|
||||
|
||||
const buildSearchParameters = (record: Record<string, Nullable<Optional<string>>>) => {
|
||||
const entries = Object.entries(record).filter((entry): entry is [string, string] =>
|
||||
Boolean(entry[0] && entry[1])
|
||||
);
|
||||
|
||||
return conditional(entries.length > 0 && entries);
|
||||
};
|
||||
|
||||
export const getSignInExperience = async <T extends SignInExperienceResponse>(): Promise<T> => {
|
||||
return ky.get('/api/.well-known/sign-in-exp').json<T>();
|
||||
return ky
|
||||
.get('/api/.well-known/sign-in-exp', {
|
||||
searchParams: buildSearchParameters({
|
||||
[searchKeys.noCache]: sessionStorage.getItem(searchKeys.noCache),
|
||||
}),
|
||||
})
|
||||
.json<T>();
|
||||
};
|
||||
|
||||
export const getPhrases = async ({
|
||||
|
@ -31,4 +47,9 @@ export const getPhrases = async ({
|
|||
],
|
||||
},
|
||||
})
|
||||
.get(`/api/.well-known/phrases${conditionalString(language && `?lng=${language}`)}`);
|
||||
.get('/api/.well-known/phrases', {
|
||||
searchParams: buildSearchParameters({
|
||||
[searchKeys.noCache]: sessionStorage.getItem(searchKeys.noCache),
|
||||
lng: language,
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -5,6 +5,7 @@ import { Trans, useTranslation } from 'react-i18next';
|
|||
|
||||
import { AppNotification as Notification } from '@/components/Notification';
|
||||
import usePlatform from '@/hooks/use-platform';
|
||||
import { searchKeys } from '@/utils/search-parameters';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
|
@ -26,7 +27,7 @@ const AppNotification = () => {
|
|||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setNotification(new URLSearchParams(window.location.search).get('notification'));
|
||||
setNotification(sessionStorage.getItem(searchKeys.notification));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
24
packages/ui/src/utils/search-parameters.ts
Normal file
24
packages/ui/src/utils/search-parameters.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
export const searchKeys = Object.freeze({
|
||||
notification: 'notification',
|
||||
noCache: 'no_cache',
|
||||
});
|
||||
|
||||
export const handleSearchParametersData = () => {
|
||||
const { search } = window.location;
|
||||
|
||||
if (!search) {
|
||||
return;
|
||||
}
|
||||
|
||||
const parameters = new URLSearchParams(search);
|
||||
|
||||
const notification = parameters.get(searchKeys.notification);
|
||||
|
||||
if (notification) {
|
||||
sessionStorage.setItem(searchKeys.notification, notification);
|
||||
}
|
||||
|
||||
if (parameters.get(searchKeys.noCache) !== null) {
|
||||
sessionStorage.setItem(searchKeys.noCache, 'true');
|
||||
}
|
||||
};
|
Loading…
Add table
Reference in a new issue