0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-01-27 21:39:16 -05:00

refactor: use URL class

This commit is contained in:
Gao Sun 2023-03-07 12:38:26 +08:00
parent 04cc1fe69a
commit 3287c2c232
No known key found for this signature in database
GPG key ID: 13EBE123E4773688
12 changed files with 33 additions and 38 deletions

View file

@ -1,5 +1,6 @@
import { adminConsoleApplicationId, adminTenantId, defaultTenantId } from '@logto/schemas';
import { appendPath, GlobalValues } from '@logto/shared';
import { GlobalValues } from '@logto/shared';
import { appendPath } from '@silverhand/essentials';
import type { CommonQueryMethods } from 'slonik';
import { sql } from 'slonik';

View file

@ -53,7 +53,7 @@ const Content = () => {
return (
<LogtoProvider
config={{
endpoint: adminTenantEndpoint,
endpoint: adminTenantEndpoint.href,
appId: adminConsoleApplicationId,
resources,
scopes,

View file

@ -6,8 +6,9 @@ import { isCloud } from './cloud';
const isProduction = process.env.NODE_ENV === 'production';
export const adminTenantEndpoint =
process.env.ADMIN_ENDPOINT ?? (isProduction ? window.location.origin : 'http://localhost:3002');
export const adminTenantEndpoint = new URL(
process.env.ADMIN_ENDPOINT ?? (isProduction ? window.location.origin : 'http://localhost:3002')
);
export const getUserTenantId = () => {
if (isCloud) {

View file

@ -24,7 +24,7 @@ export class RequestError extends Error {
}
type StaticApiProps = {
prefixUrl: string;
prefixUrl?: URL;
hideErrorToast?: boolean;
resourceIndicator?: string;
};
@ -113,7 +113,7 @@ export const useStaticApi = ({
const useApi = (props: Omit<StaticApiProps, 'prefixUrl'> = {}) => {
const { userEndpoint } = useContext(AppEndpointsContext);
return useStaticApi({ ...props, prefixUrl: userEndpoint?.toString() ?? '' });
return useStaticApi({ ...props, prefixUrl: userEndpoint });
};
export default useApi;

View file

@ -2,7 +2,7 @@ import { buildIdGenerator } from '@logto/core-kit';
import type { ConnectorResponse, User } from '@logto/schemas';
import { AppearanceMode } from '@logto/schemas';
import type { Optional } from '@silverhand/essentials';
import { conditional } from '@silverhand/essentials';
import { appendPath, conditional } from '@silverhand/essentials';
import { useCallback, useMemo } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
@ -43,7 +43,7 @@ const LinkAccountSection = ({ user, connectors, onUpdate }: Props) => {
async (connectorId: string) => {
const adminTenantEndpointUrl = new URL(adminTenantEndpoint);
const state = buildIdGenerator(8)();
const redirectUri = new URL(`/callback/${connectorId}`, adminTenantEndpointUrl).toString();
const redirectUri = new URL(`/callback/${connectorId}`, adminTenantEndpointUrl).href;
const { redirectTo } = await api
.post('me/social/authorization-uri', { json: { connectorId, state, redirectUri } })
.json<{ redirectTo: string }>();
@ -60,8 +60,6 @@ const LinkAccountSection = ({ user, connectors, onUpdate }: Props) => {
return [];
}
const adminTenantEndpointUrl = new URL(adminTenantEndpoint);
return connectors.map(({ id, name, logo, logoDark, target }) => {
const logoSrc = theme === AppearanceMode.DarkMode && logoDark ? logoDark : logo;
const relatedUserDetails = user.identities[target]?.details;
@ -113,7 +111,7 @@ const LinkAccountSection = ({ user, connectors, onUpdate }: Props) => {
});
const newWindow = popupWindow(
new URL(`/springboard?${queries.toString()}`, adminTenantEndpointUrl).toString(),
appendPath(adminTenantEndpoint, `/springboard?${queries.toString()}`).href,
'Link social account with Logto',
600,
640

View file

@ -1,5 +1,6 @@
import { GlobalValues, appendPath } from '@logto/shared';
import { GlobalValues } from '@logto/shared';
import type { Optional } from '@silverhand/essentials';
import { appendPath } from '@silverhand/essentials';
import type { PostgreSql } from '@withtyped/postgres';
import type { QueryClient } from '@withtyped/server';
import type { DatabasePool } from 'slonik';
@ -94,7 +95,7 @@ export class EnvSet {
const oidcConfigs = await getOidcConfigs();
const endpoint = getTenantEndpoint(this.tenantId, EnvSet.values);
this.#oidc = await loadOidcValues(appendPath(endpoint, '/oidc').toString(), oidcConfigs);
this.#oidc = await loadOidcValues(appendPath(endpoint, '/oidc').href, oidcConfigs);
}
}

View file

@ -7,7 +7,8 @@ import {
LogtoOidcConfigKey,
LogtoConfigs,
} from '@logto/schemas';
import { convertToIdentifiers, appendPath } from '@logto/shared';
import { convertToIdentifiers } from '@logto/shared';
import { appendPath } from '@silverhand/essentials';
import type { JWK } from 'jose';
import { sql } from 'slonik';
@ -49,7 +50,7 @@ export const getAdminTenantTokenValidationSet = async (): Promise<{
appendPath(
isMultiTenancy ? getTenantEndpoint(adminTenantId, EnvSet.values) : adminUrlSet.endpoint,
'/oidc'
).toString(),
).href,
],
};
};

View file

@ -1,4 +1,4 @@
import { appendPath } from '@logto/shared';
import { appendPath } from '@silverhand/essentials';
import type { MiddlewareType } from 'koa';
import type { IRouterParamContext } from 'koa-router';
import type Provider from 'oidc-provider';
@ -31,7 +31,7 @@ export default function koaSpaSessionGuard<
try {
await provider.interactionDetails(ctx.req, ctx.res);
} catch {
ctx.redirect(appendPath(endpoint, sessionNotFoundPath).toString());
ctx.redirect(appendPath(endpoint, sessionNotFoundPath).href);
return;
}

View file

@ -1,6 +1,7 @@
import type { CreateApplication } from '@logto/schemas';
import { ApplicationType, adminConsoleApplicationId, demoAppApplicationId } from '@logto/schemas';
import { tryThat, appendPath } from '@logto/shared';
import { tryThat } from '@logto/shared';
import { appendPath } from '@silverhand/essentials';
import { addSeconds } from 'date-fns';
import type { AdapterFactory, AllClientMetadata } from 'oidc-provider';
import { errors } from 'oidc-provider';
@ -23,31 +24,31 @@ const transpileMetadata = (clientId: string, data: AllClientMetadata): AllClient
const { adminUrlSet, cloudUrlSet } = EnvSet.values;
const urls = [
...adminUrlSet.deduplicated().map((url) => appendPath(url, '/console').toString()),
...cloudUrlSet.deduplicated().map(String),
...adminUrlSet.deduplicated().map((url) => appendPath(url, '/console')),
...cloudUrlSet.deduplicated(),
];
return {
...data,
redirect_uris: [
...(data.redirect_uris ?? []),
...urls.map((url) => appendPath(url, '/callback').toString()),
...urls.map((url) => appendPath(url, '/callback').href),
],
post_logout_redirect_uris: [...(data.post_logout_redirect_uris ?? []), ...urls],
post_logout_redirect_uris: [...(data.post_logout_redirect_uris ?? []), ...urls.map(String)],
};
};
const buildDemoAppClientMetadata = (envSet: EnvSet): AllClientMetadata => {
const urls = getTenantUrls(envSet.tenantId, EnvSet.values).map((url) =>
appendPath(url, '/demo-app').toString()
const urlStrings = getTenantUrls(envSet.tenantId, EnvSet.values).map(
(url) => appendPath(url, '/demo-app').href
);
return {
...getConstantClientMetadata(envSet, ApplicationType.SPA),
client_id: demoAppApplicationId,
client_name: 'Demo App',
redirect_uris: urls,
post_logout_redirect_uris: urls,
redirect_uris: urlStrings,
post_logout_redirect_uris: urlStrings,
};
};

View file

@ -1,11 +1,8 @@
import path from 'path';
import { appendPath } from '@silverhand/essentials';
import { logtoCloudUrl as logtoCloudUrlString, logtoConsoleUrl } from '#src/constants.js';
import { generatePassword } from '#src/utils.js';
const appendPathname = (pathname: string, baseUrl: URL) =>
new URL(path.join(baseUrl.pathname, pathname), baseUrl);
/**
* NOTE: This test suite assumes test cases will run sequentially (which is Jest default).
* Parallel execution will lead to errors.
@ -22,8 +19,8 @@ describe('smoke testing for cloud', () => {
await page.goto(logtoCloudUrl.href);
await page.waitForNavigation({ waitUntil: 'networkidle0' });
await expect(page).toMatchElement('#app');
expect(page.url()).toBe(appendPathname('/register', adminTenantUrl).href);
await expect(page.waitForSelector('#app')).resolves.not.toBeNull();
expect(page.url()).toBe(appendPath(adminTenantUrl, '/register').href);
});
it('can register the first admin account', async () => {
@ -33,7 +30,7 @@ describe('smoke testing for cloud', () => {
await expect(page).toClick('button[name=submit]');
await page.waitForNavigation({ waitUntil: 'networkidle0' });
expect(page.url()).toBe(appendPathname('/register/password', adminTenantUrl).href);
expect(page.url()).toBe(appendPath(adminTenantUrl, '/register/password').href);
await expect(page).toFillForm('form', {
newPassword: consolePassword,

View file

@ -1,4 +1,3 @@
export * from './function.js';
export * from './object.js';
export { default as findPackage } from './find-package.js';
export * from './url.js';

View file

@ -1,4 +0,0 @@
import path from 'path';
export const appendPath = (url: URL | string, ...pathnames: string[]): URL =>
new URL(path.join(new URL(url).pathname, ...pathnames), url);