mirror of
https://github.com/logto-io/logto.git
synced 2025-03-17 22:31:28 -05:00
feat(core): add customJwt paywall guard to core API (#5708)
add customJwt paywall guard to core API
This commit is contained in:
parent
49b60af093
commit
43430afddb
54 changed files with 332 additions and 38 deletions
|
@ -28,7 +28,7 @@
|
|||
"@fontsource/roboto-mono": "^5.0.0",
|
||||
"@jest/types": "^29.5.0",
|
||||
"@logto/app-insights": "workspace:^1.4.0",
|
||||
"@logto/cloud": "0.2.5-ab8a489",
|
||||
"@logto/cloud": "0.2.5-94f7bcc",
|
||||
"@logto/connector-kit": "workspace:^3.0.0",
|
||||
"@logto/core-kit": "workspace:^2.4.0",
|
||||
"@logto/language-kit": "workspace:^1.1.0",
|
||||
|
|
|
@ -27,6 +27,7 @@ export const quotaItemPhrasesMap: Record<
|
|||
organizationsEnabled: 'organizations_enabled.name',
|
||||
ssoEnabled: 'sso_enabled.name',
|
||||
tenantMembersLimit: 'tenant_members_limit.name',
|
||||
customJwtEnabled: 'custom_jwt_enabled.name',
|
||||
};
|
||||
|
||||
export const quotaItemUnlimitedPhrasesMap: Record<
|
||||
|
@ -54,6 +55,7 @@ export const quotaItemUnlimitedPhrasesMap: Record<
|
|||
organizationsEnabled: 'organizations_enabled.unlimited',
|
||||
ssoEnabled: 'sso_enabled.unlimited',
|
||||
tenantMembersLimit: 'tenant_members_limit.unlimited',
|
||||
customJwtEnabled: 'custom_jwt_enabled.unlimited',
|
||||
};
|
||||
|
||||
export const quotaItemLimitedPhrasesMap: Record<
|
||||
|
@ -81,6 +83,7 @@ export const quotaItemLimitedPhrasesMap: Record<
|
|||
organizationsEnabled: 'organizations_enabled.limited',
|
||||
ssoEnabled: 'sso_enabled.limited',
|
||||
tenantMembersLimit: 'tenant_members_limit.limited',
|
||||
customJwtEnabled: 'custom_jwt_enabled.limited',
|
||||
};
|
||||
|
||||
export const quotaItemNotEligiblePhrasesMap: Record<
|
||||
|
@ -108,4 +111,5 @@ export const quotaItemNotEligiblePhrasesMap: Record<
|
|||
organizationsEnabled: 'organizations_enabled.not_eligible',
|
||||
ssoEnabled: 'sso_enabled.not_eligible',
|
||||
tenantMembersLimit: 'tenant_members_limit.not_eligible',
|
||||
customJwtEnabled: 'custom_jwt_enabled.not_eligible',
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { TenantTag, ReservedPlanId, defaultManagementApi } from '@logto/schemas';
|
||||
import { ReservedPlanId, TenantTag, defaultManagementApi } from '@logto/schemas';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
import { type TenantResponse } from '@/cloud/types/router';
|
||||
|
@ -67,6 +67,7 @@ export const defaultSubscriptionPlan: SubscriptionPlan = {
|
|||
ticketSupportResponseTime: 48,
|
||||
thirdPartyApplicationsLimit: null,
|
||||
tenantMembersLimit: null,
|
||||
customJwtEnabled: true,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import type { Nullable } from '@silverhand/essentials';
|
||||
import { noop } from '@silverhand/essentials';
|
||||
import { useState, useRef, useMemo, createContext, useCallback, useEffect } from 'react';
|
||||
import { createContext, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import ConfirmModal from '@/ds-components/ConfirmModal';
|
||||
import type { ConfirmModalProps } from '@/ds-components/ConfirmModal';
|
||||
import ConfirmModal from '@/ds-components/ConfirmModal';
|
||||
|
||||
type ModalContentRenderProps = {
|
||||
confirm: (data?: unknown) => void;
|
||||
|
@ -108,13 +108,7 @@ function AppConfirmModalProvider({ children }: Props) {
|
|||
{children}
|
||||
<ConfirmModal
|
||||
{...restProps}
|
||||
onConfirm={
|
||||
type === 'confirm'
|
||||
? () => {
|
||||
handleConfirm();
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
onConfirm={type === 'confirm' ? handleConfirm : undefined}
|
||||
onCancel={() => {
|
||||
handleCancel();
|
||||
}}
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
import { type LogtoJwtTokenKeyType } from '@logto/schemas';
|
||||
import { useCallback, useContext } from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
|
||||
import ContactUsPhraseLink from '@/components/ContactUsPhraseLink';
|
||||
import { SubscriptionDataContext } from '@/contexts/SubscriptionDataProvider';
|
||||
import Button from '@/ds-components/Button';
|
||||
import { useConfirmModal } from '@/hooks/use-confirm-modal';
|
||||
import useTenantPathname from '@/hooks/use-tenant-pathname';
|
||||
import { getPagePath } from '@/pages/CustomizeJwt/utils/path';
|
||||
|
||||
|
@ -11,14 +16,47 @@ type Props = {
|
|||
function CreateButton({ tokenType }: Props) {
|
||||
const link = getPagePath(tokenType, 'create');
|
||||
const { navigate } = useTenantPathname();
|
||||
const { show } = useConfirmModal();
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
|
||||
const { currentPlan } = useContext(SubscriptionDataContext);
|
||||
const {
|
||||
quota: { customJwtEnabled },
|
||||
} = currentPlan;
|
||||
|
||||
const onCreateButtonClick = useCallback(async () => {
|
||||
if (customJwtEnabled) {
|
||||
navigate(link);
|
||||
return;
|
||||
}
|
||||
|
||||
const [confirm] = await show({
|
||||
title: 'upsell.paywall.custom_jwt.title',
|
||||
ModalContent: () => (
|
||||
<Trans
|
||||
components={{
|
||||
a: <ContactUsPhraseLink />,
|
||||
}}
|
||||
>
|
||||
{t('upsell.paywall.custom_jwt.description')}
|
||||
</Trans>
|
||||
),
|
||||
confirmButtonText: 'upsell.upgrade_plan',
|
||||
confirmButtonType: 'primary',
|
||||
isCancelButtonVisible: false,
|
||||
});
|
||||
|
||||
if (confirm) {
|
||||
// Navigate to subscription page by default
|
||||
navigate('/tenant-settings/subscription');
|
||||
}
|
||||
}, [customJwtEnabled, link, navigate, show, t]);
|
||||
|
||||
return (
|
||||
<Button
|
||||
type="primary"
|
||||
title="jwt_claims.custom_jwt_create_button"
|
||||
onClick={() => {
|
||||
navigate(link);
|
||||
}}
|
||||
onClick={onCreateButtonClick}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@
|
|||
"zod": "^3.22.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@logto/cloud": "0.2.5-749cae5",
|
||||
"@logto/cloud": "0.2.5-94f7bcc",
|
||||
"@silverhand/eslint-config": "5.0.0",
|
||||
"@silverhand/ts-config": "5.0.0",
|
||||
"@types/debug": "^4.1.7",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { ConnectorType, DemoConnector } from '@logto/connector-kit';
|
||||
import { RoleType, ReservedPlanId } from '@logto/schemas';
|
||||
import { ReservedPlanId, RoleType } from '@logto/schemas';
|
||||
|
||||
import { EnvSet } from '#src/env-set/index.js';
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
|
@ -72,6 +72,7 @@ export const createQuotaLibrary = (
|
|||
ssoEnabled: notNumber,
|
||||
omniSignInEnabled: notNumber, // No limit for now
|
||||
builtInEmailConnectorEnabled: notNumber, // No limit for now
|
||||
customJwtEnabled: notNumber, // No limit for now
|
||||
};
|
||||
|
||||
const getTenantUsage = async (key: keyof FeatureQuota, queryKey?: string): Promise<number> => {
|
||||
|
|
|
@ -14,6 +14,7 @@ import { ZodError, z } from 'zod';
|
|||
import { EnvSet } from '#src/env-set/index.js';
|
||||
import RequestError, { formatZodError } from '#src/errors/RequestError/index.js';
|
||||
import koaGuard, { parse } from '#src/middleware/koa-guard.js';
|
||||
import koaQuotaGuard from '#src/middleware/koa-quota-guard.js';
|
||||
|
||||
import type { AuthedRouter, RouterInitArgs } from '../types.js';
|
||||
|
||||
|
@ -31,7 +32,10 @@ const getJwtTokenKeyAndBody = (tokenPath: LogtoJwtTokenKeyType, body: unknown) =
|
|||
};
|
||||
|
||||
export default function logtoConfigJwtCustomizerRoutes<T extends AuthedRouter>(
|
||||
...[router, { id: tenantId, queries, logtoConfigs, cloudConnection }]: RouterInitArgs<T>
|
||||
...[
|
||||
router,
|
||||
{ id: tenantId, queries, logtoConfigs, cloudConnection, libraries },
|
||||
]: RouterInitArgs<T>
|
||||
) {
|
||||
const { getRowsByKeys, deleteJwtCustomizer } = queries.logtoConfigs;
|
||||
const {
|
||||
|
@ -60,6 +64,7 @@ export default function logtoConfigJwtCustomizerRoutes<T extends AuthedRouter>(
|
|||
response: accessTokenJwtCustomizerGuard.or(clientCredentialsJwtCustomizerGuard),
|
||||
status: [200, 201, 400, 403],
|
||||
}),
|
||||
koaQuotaGuard({ key: 'customJwtEnabled', quota: libraries.quota }),
|
||||
async (ctx, next) => {
|
||||
const { isCloud, isIntegrationTest } = EnvSet.values;
|
||||
if (tenantId === adminTenantId && isCloud && !isIntegrationTest) {
|
||||
|
@ -109,6 +114,7 @@ export default function logtoConfigJwtCustomizerRoutes<T extends AuthedRouter>(
|
|||
response: accessTokenJwtCustomizerGuard.or(clientCredentialsJwtCustomizerGuard),
|
||||
status: [200, 400, 404],
|
||||
}),
|
||||
koaQuotaGuard({ key: 'customJwtEnabled', quota: libraries.quota }),
|
||||
async (ctx, next) => {
|
||||
const { isIntegrationTest } = EnvSet.values;
|
||||
|
||||
|
@ -211,6 +217,7 @@ export default function logtoConfigJwtCustomizerRoutes<T extends AuthedRouter>(
|
|||
response: jsonObjectGuard,
|
||||
status: [200, 400, 403, 422],
|
||||
}),
|
||||
koaQuotaGuard({ key: 'customJwtEnabled', quota: libraries.quota }),
|
||||
async (ctx, next) => {
|
||||
const { body } = ctx.guard;
|
||||
|
||||
|
|
|
@ -163,6 +163,16 @@ const quota_item = {
|
|||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your tenant members',
|
||||
},
|
||||
custom_jwt_enabled: {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
limited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
unlimited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your JWT claims customizer',
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(quota_item);
|
||||
|
|
|
@ -15,7 +15,7 @@ const tabs = {
|
|||
tenant_settings: 'Einstellungen',
|
||||
mfa: 'Multi-Faktor-Authentifizierung',
|
||||
/** UNTRANSLATED */
|
||||
customize_jwt: 'JWT Claims',
|
||||
customize_jwt: 'Custom JWT',
|
||||
signing_keys: 'Signierschlüssel',
|
||||
organization_template: 'Organisationstemplate',
|
||||
};
|
||||
|
|
|
@ -64,6 +64,13 @@ const paywall = {
|
|||
/** UNTRANSLATED */
|
||||
tenant_members_dev_plan:
|
||||
"You've reached your {{limit}}-member limit. Release a member or revoke a pending invitation to add someone new. Need more seats? Feel free to contact us.",
|
||||
custom_jwt: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Add custom claims',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Upgrade to a paid plan for custom JWT functionality and premium benefits. Don't hesitate to <a>contact us</a> if you have any questions.",
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(paywall);
|
||||
|
|
|
@ -153,6 +153,12 @@ const quota_item = {
|
|||
unlimited: 'Unlimited tenant members',
|
||||
not_eligible: 'Remove your tenant members',
|
||||
},
|
||||
custom_jwt_enabled: {
|
||||
name: 'Custom JWT',
|
||||
limited: 'Custom JWT',
|
||||
unlimited: 'Custom JWT',
|
||||
not_eligible: 'Remove your JWT claims customizer',
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(quota_item);
|
||||
|
|
|
@ -14,7 +14,7 @@ const tabs = {
|
|||
docs: 'Docs',
|
||||
tenant_settings: 'Settings',
|
||||
mfa: 'Multi-factor auth',
|
||||
customize_jwt: 'JWT Claims',
|
||||
customize_jwt: 'Custom JWT',
|
||||
signing_keys: 'Signing keys',
|
||||
organization_template: 'Organization template',
|
||||
};
|
||||
|
|
|
@ -60,6 +60,11 @@ const paywall = {
|
|||
'Unlock collaboration feature by upgrading to a paid plan. For any assistance, feel free to <a>contact us</a>.',
|
||||
tenant_members_dev_plan:
|
||||
"You've reached your {{limit}}-member limit. Release a member or revoke a pending invitation to add someone new. Need more seats? Feel free to contact us.",
|
||||
custom_jwt: {
|
||||
title: 'Add custom claims',
|
||||
description:
|
||||
"Upgrade to a paid plan for custom JWT functionality and premium benefits. Don't hesitate to <a>contact us</a> if you have any questions.",
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(paywall);
|
||||
|
|
|
@ -163,6 +163,16 @@ const quota_item = {
|
|||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your tenant members',
|
||||
},
|
||||
custom_jwt_enabled: {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
limited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
unlimited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your JWT claims customizer',
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(quota_item);
|
||||
|
|
|
@ -15,7 +15,7 @@ const tabs = {
|
|||
tenant_settings: 'Configuraciones del inquilino',
|
||||
mfa: 'Autenticación multifactor',
|
||||
/** UNTRANSLATED */
|
||||
customize_jwt: 'JWT Claims',
|
||||
customize_jwt: 'Custom JWT',
|
||||
signing_keys: 'Claves de firma',
|
||||
organization_template: 'Plantilla de organización',
|
||||
};
|
||||
|
|
|
@ -64,6 +64,13 @@ const paywall = {
|
|||
/** UNTRANSLATED */
|
||||
tenant_members_dev_plan:
|
||||
"You've reached your {{limit}}-member limit. Release a member or revoke a pending invitation to add someone new. Need more seats? Feel free to contact us.",
|
||||
custom_jwt: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Add custom claims',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Upgrade to a paid plan for custom JWT functionality and premium benefits. Don't hesitate to <a>contact us</a> if you have any questions.",
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(paywall);
|
||||
|
|
|
@ -163,6 +163,16 @@ const quota_item = {
|
|||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your tenant members',
|
||||
},
|
||||
custom_jwt_enabled: {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
limited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
unlimited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your JWT claims customizer',
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(quota_item);
|
||||
|
|
|
@ -15,7 +15,7 @@ const tabs = {
|
|||
tenant_settings: 'Paramètres du locataire',
|
||||
mfa: 'Authentification multi-facteur',
|
||||
/** UNTRANSLATED */
|
||||
customize_jwt: 'JWT Claims',
|
||||
customize_jwt: 'Custom JWT',
|
||||
signing_keys: 'Clés de signature',
|
||||
organization_template: "Modèle d'organisation",
|
||||
};
|
||||
|
|
|
@ -64,6 +64,13 @@ const paywall = {
|
|||
/** UNTRANSLATED */
|
||||
tenant_members_dev_plan:
|
||||
"You've reached your {{limit}}-member limit. Release a member or revoke a pending invitation to add someone new. Need more seats? Feel free to contact us.",
|
||||
custom_jwt: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Add custom claims',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Upgrade to a paid plan for custom JWT functionality and premium benefits. Don't hesitate to <a>contact us</a> if you have any questions.",
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(paywall);
|
||||
|
|
|
@ -163,6 +163,16 @@ const quota_item = {
|
|||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your tenant members',
|
||||
},
|
||||
custom_jwt_enabled: {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
limited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
unlimited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your JWT claims customizer',
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(quota_item);
|
||||
|
|
|
@ -15,7 +15,7 @@ const tabs = {
|
|||
tenant_settings: 'Impostazioni',
|
||||
mfa: 'Autenticazione multi-fattore',
|
||||
/** UNTRANSLATED */
|
||||
customize_jwt: 'JWT Claims',
|
||||
customize_jwt: 'Custom JWT',
|
||||
signing_keys: 'Chiavi di firma',
|
||||
organization_template: 'Modello di organizzazione',
|
||||
};
|
||||
|
|
|
@ -64,6 +64,13 @@ const paywall = {
|
|||
/** UNTRANSLATED */
|
||||
tenant_members_dev_plan:
|
||||
"You've reached your {{limit}}-member limit. Release a member or revoke a pending invitation to add someone new. Need more seats? Feel free to contact us.",
|
||||
custom_jwt: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Add custom claims',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Upgrade to a paid plan for custom JWT functionality and premium benefits. Don't hesitate to <a>contact us</a> if you have any questions.",
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(paywall);
|
||||
|
|
|
@ -163,6 +163,16 @@ const quota_item = {
|
|||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your tenant members',
|
||||
},
|
||||
custom_jwt_enabled: {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
limited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
unlimited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your JWT claims customizer',
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(quota_item);
|
||||
|
|
|
@ -15,7 +15,7 @@ const tabs = {
|
|||
tenant_settings: '設定',
|
||||
mfa: 'Multi-factor auth',
|
||||
/** UNTRANSLATED */
|
||||
customize_jwt: 'JWT Claims',
|
||||
customize_jwt: 'Custom JWT',
|
||||
signing_keys: '署名キー',
|
||||
organization_template: '組織テンプレート',
|
||||
};
|
||||
|
|
|
@ -64,6 +64,13 @@ const paywall = {
|
|||
/** UNTRANSLATED */
|
||||
tenant_members_dev_plan:
|
||||
"You've reached your {{limit}}-member limit. Release a member or revoke a pending invitation to add someone new. Need more seats? Feel free to contact us.",
|
||||
custom_jwt: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Add custom claims',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Upgrade to a paid plan for custom JWT functionality and premium benefits. Don't hesitate to <a>contact us</a> if you have any questions.",
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(paywall);
|
||||
|
|
|
@ -163,6 +163,16 @@ const quota_item = {
|
|||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your tenant members',
|
||||
},
|
||||
custom_jwt_enabled: {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
limited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
unlimited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your JWT claims customizer',
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(quota_item);
|
||||
|
|
|
@ -15,7 +15,7 @@ const tabs = {
|
|||
tenant_settings: '테넌트 설정',
|
||||
mfa: '다중 요소 인증',
|
||||
/** UNTRANSLATED */
|
||||
customize_jwt: 'JWT Claims',
|
||||
customize_jwt: 'Custom JWT',
|
||||
signing_keys: '서명 키',
|
||||
organization_template: '조직 템플릿',
|
||||
};
|
||||
|
|
|
@ -64,6 +64,13 @@ const paywall = {
|
|||
/** UNTRANSLATED */
|
||||
tenant_members_dev_plan:
|
||||
"You've reached your {{limit}}-member limit. Release a member or revoke a pending invitation to add someone new. Need more seats? Feel free to contact us.",
|
||||
custom_jwt: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Add custom claims',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Upgrade to a paid plan for custom JWT functionality and premium benefits. Don't hesitate to <a>contact us</a> if you have any questions.",
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(paywall);
|
||||
|
|
|
@ -163,6 +163,16 @@ const quota_item = {
|
|||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your tenant members',
|
||||
},
|
||||
custom_jwt_enabled: {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
limited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
unlimited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your JWT claims customizer',
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(quota_item);
|
||||
|
|
|
@ -15,7 +15,7 @@ const tabs = {
|
|||
tenant_settings: 'Ustawienia',
|
||||
mfa: 'Multi-factor auth',
|
||||
/** UNTRANSLATED */
|
||||
customize_jwt: 'JWT Claims',
|
||||
customize_jwt: 'Custom JWT',
|
||||
signing_keys: 'Klucze do podpisu',
|
||||
organization_template: 'Szablon organizacji',
|
||||
};
|
||||
|
|
|
@ -64,6 +64,13 @@ const paywall = {
|
|||
/** UNTRANSLATED */
|
||||
tenant_members_dev_plan:
|
||||
"You've reached your {{limit}}-member limit. Release a member or revoke a pending invitation to add someone new. Need more seats? Feel free to contact us.",
|
||||
custom_jwt: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Add custom claims',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Upgrade to a paid plan for custom JWT functionality and premium benefits. Don't hesitate to <a>contact us</a> if you have any questions.",
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(paywall);
|
||||
|
|
|
@ -163,6 +163,16 @@ const quota_item = {
|
|||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your tenant members',
|
||||
},
|
||||
custom_jwt_enabled: {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
limited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
unlimited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your JWT claims customizer',
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(quota_item);
|
||||
|
|
|
@ -15,7 +15,7 @@ const tabs = {
|
|||
tenant_settings: 'Configurações',
|
||||
mfa: 'Autenticação de multi-fator',
|
||||
/** UNTRANSLATED */
|
||||
customize_jwt: 'JWT Claims',
|
||||
customize_jwt: 'Custom JWT',
|
||||
signing_keys: 'Chaves de assinatura',
|
||||
organization_template: 'Modelo de organização',
|
||||
};
|
||||
|
|
|
@ -64,6 +64,13 @@ const paywall = {
|
|||
/** UNTRANSLATED */
|
||||
tenant_members_dev_plan:
|
||||
"You've reached your {{limit}}-member limit. Release a member or revoke a pending invitation to add someone new. Need more seats? Feel free to contact us.",
|
||||
custom_jwt: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Add custom claims',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Upgrade to a paid plan for custom JWT functionality and premium benefits. Don't hesitate to <a>contact us</a> if you have any questions.",
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(paywall);
|
||||
|
|
|
@ -163,6 +163,16 @@ const quota_item = {
|
|||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your tenant members',
|
||||
},
|
||||
custom_jwt_enabled: {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
limited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
unlimited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your JWT claims customizer',
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(quota_item);
|
||||
|
|
|
@ -15,7 +15,7 @@ const tabs = {
|
|||
tenant_settings: 'Definições do inquilino',
|
||||
mfa: 'Autenticação multi-fator',
|
||||
/** UNTRANSLATED */
|
||||
customize_jwt: 'JWT Claims',
|
||||
customize_jwt: 'Custom JWT',
|
||||
signing_keys: 'Chaves de assinatura',
|
||||
organization_template: 'Modelo de organização',
|
||||
};
|
||||
|
|
|
@ -64,6 +64,13 @@ const paywall = {
|
|||
/** UNTRANSLATED */
|
||||
tenant_members_dev_plan:
|
||||
"You've reached your {{limit}}-member limit. Release a member or revoke a pending invitation to add someone new. Need more seats? Feel free to contact us.",
|
||||
custom_jwt: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Add custom claims',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Upgrade to a paid plan for custom JWT functionality and premium benefits. Don't hesitate to <a>contact us</a> if you have any questions.",
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(paywall);
|
||||
|
|
|
@ -163,6 +163,16 @@ const quota_item = {
|
|||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your tenant members',
|
||||
},
|
||||
custom_jwt_enabled: {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
limited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
unlimited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your JWT claims customizer',
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(quota_item);
|
||||
|
|
|
@ -15,7 +15,7 @@ const tabs = {
|
|||
tenant_settings: 'Настройки',
|
||||
mfa: 'Multi-factor auth',
|
||||
/** UNTRANSLATED */
|
||||
customize_jwt: 'JWT Claims',
|
||||
customize_jwt: 'Custom JWT',
|
||||
signing_keys: 'Ключи подписи',
|
||||
organization_template: 'Шаблон организации',
|
||||
};
|
||||
|
|
|
@ -64,6 +64,13 @@ const paywall = {
|
|||
/** UNTRANSLATED */
|
||||
tenant_members_dev_plan:
|
||||
"You've reached your {{limit}}-member limit. Release a member or revoke a pending invitation to add someone new. Need more seats? Feel free to contact us.",
|
||||
custom_jwt: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Add custom claims',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Upgrade to a paid plan for custom JWT functionality and premium benefits. Don't hesitate to <a>contact us</a> if you have any questions.",
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(paywall);
|
||||
|
|
|
@ -163,6 +163,16 @@ const quota_item = {
|
|||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your tenant members',
|
||||
},
|
||||
custom_jwt_enabled: {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
limited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
unlimited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your JWT claims customizer',
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(quota_item);
|
||||
|
|
|
@ -15,7 +15,7 @@ const tabs = {
|
|||
tenant_settings: 'Ayarlar',
|
||||
mfa: 'Çoklu faktörlü kimlik doğrulama',
|
||||
/** UNTRANSLATED */
|
||||
customize_jwt: 'JWT Claims',
|
||||
customize_jwt: 'Custom JWT',
|
||||
signing_keys: 'İmza anahtarları',
|
||||
organization_template: 'Kuruluş şablonu',
|
||||
};
|
||||
|
|
|
@ -64,6 +64,13 @@ const paywall = {
|
|||
/** UNTRANSLATED */
|
||||
tenant_members_dev_plan:
|
||||
"You've reached your {{limit}}-member limit. Release a member or revoke a pending invitation to add someone new. Need more seats? Feel free to contact us.",
|
||||
custom_jwt: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Add custom claims',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Upgrade to a paid plan for custom JWT functionality and premium benefits. Don't hesitate to <a>contact us</a> if you have any questions.",
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(paywall);
|
||||
|
|
|
@ -163,6 +163,16 @@ const quota_item = {
|
|||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your tenant members',
|
||||
},
|
||||
custom_jwt_enabled: {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
limited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
unlimited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your JWT claims customizer',
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(quota_item);
|
||||
|
|
|
@ -15,7 +15,7 @@ const tabs = {
|
|||
tenant_settings: '租户设置',
|
||||
mfa: '多因素认证',
|
||||
/** UNTRANSLATED */
|
||||
customize_jwt: 'JWT Claims',
|
||||
customize_jwt: 'Custom JWT',
|
||||
signing_keys: '签名密钥',
|
||||
organization_template: '组织模板',
|
||||
};
|
||||
|
|
|
@ -63,6 +63,13 @@ const paywall = {
|
|||
/** UNTRANSLATED */
|
||||
tenant_members_dev_plan:
|
||||
"You've reached your {{limit}}-member limit. Release a member or revoke a pending invitation to add someone new. Need more seats? Feel free to contact us.",
|
||||
custom_jwt: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Add custom claims',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Upgrade to a paid plan for custom JWT functionality and premium benefits. Don't hesitate to <a>contact us</a> if you have any questions.",
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(paywall);
|
||||
|
|
|
@ -163,6 +163,16 @@ const quota_item = {
|
|||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your tenant members',
|
||||
},
|
||||
custom_jwt_enabled: {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
limited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
unlimited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your JWT claims customizer',
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(quota_item);
|
||||
|
|
|
@ -15,7 +15,7 @@ const tabs = {
|
|||
tenant_settings: '租戶設置',
|
||||
mfa: '多重認證',
|
||||
/** UNTRANSLATED */
|
||||
customize_jwt: 'JWT Claims',
|
||||
customize_jwt: 'Custom JWT',
|
||||
signing_keys: '簽署密鑰',
|
||||
organization_template: '組織模板',
|
||||
};
|
||||
|
|
|
@ -63,6 +63,13 @@ const paywall = {
|
|||
/** UNTRANSLATED */
|
||||
tenant_members_dev_plan:
|
||||
"You've reached your {{limit}}-member limit. Release a member or revoke a pending invitation to add someone new. Need more seats? Feel free to contact us.",
|
||||
custom_jwt: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Add custom claims',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Upgrade to a paid plan for custom JWT functionality and premium benefits. Don't hesitate to <a>contact us</a> if you have any questions.",
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(paywall);
|
||||
|
|
|
@ -163,6 +163,16 @@ const quota_item = {
|
|||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your tenant members',
|
||||
},
|
||||
custom_jwt_enabled: {
|
||||
/** UNTRANSLATED */
|
||||
name: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
limited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
unlimited: 'Custom JWT',
|
||||
/** UNTRANSLATED */
|
||||
not_eligible: 'Remove your JWT claims customizer',
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(quota_item);
|
||||
|
|
|
@ -15,7 +15,7 @@ const tabs = {
|
|||
tenant_settings: '租戶設定',
|
||||
mfa: '多重認證',
|
||||
/** UNTRANSLATED */
|
||||
customize_jwt: 'JWT Claims',
|
||||
customize_jwt: 'Custom JWT',
|
||||
signing_keys: '簽署密鑰',
|
||||
organization_template: '組織模板',
|
||||
};
|
||||
|
|
|
@ -63,6 +63,13 @@ const paywall = {
|
|||
/** UNTRANSLATED */
|
||||
tenant_members_dev_plan:
|
||||
"You've reached your {{limit}}-member limit. Release a member or revoke a pending invitation to add someone new. Need more seats? Feel free to contact us.",
|
||||
custom_jwt: {
|
||||
/** UNTRANSLATED */
|
||||
title: 'Add custom claims',
|
||||
/** UNTRANSLATED */
|
||||
description:
|
||||
"Upgrade to a paid plan for custom JWT functionality and premium benefits. Don't hesitate to <a>contact us</a> if you have any questions.",
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(paywall);
|
||||
|
|
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
|
@ -2715,8 +2715,8 @@ importers:
|
|||
specifier: workspace:^1.4.0
|
||||
version: link:../app-insights
|
||||
'@logto/cloud':
|
||||
specifier: 0.2.5-ab8a489
|
||||
version: 0.2.5-ab8a489(zod@3.22.4)
|
||||
specifier: 0.2.5-94f7bcc
|
||||
version: 0.2.5-94f7bcc(zod@3.22.4)
|
||||
'@logto/connector-kit':
|
||||
specifier: workspace:^3.0.0
|
||||
version: link:../toolkit/connector-kit
|
||||
|
@ -3205,8 +3205,8 @@ importers:
|
|||
version: 3.22.4
|
||||
devDependencies:
|
||||
'@logto/cloud':
|
||||
specifier: 0.2.5-749cae5
|
||||
version: 0.2.5-749cae5(zod@3.22.4)
|
||||
specifier: 0.2.5-94f7bcc
|
||||
version: 0.2.5-94f7bcc(zod@3.22.4)
|
||||
'@silverhand/eslint-config':
|
||||
specifier: 5.0.0
|
||||
version: 5.0.0(eslint@8.44.0)(prettier@3.0.0)(typescript@5.3.3)
|
||||
|
@ -7647,8 +7647,8 @@ packages:
|
|||
jose: 5.2.2
|
||||
dev: true
|
||||
|
||||
/@logto/cloud@0.2.5-749cae5(zod@3.22.4):
|
||||
resolution: {integrity: sha512-QzebHRSBShQwOsKAvYlVd7QF43RlrHOt/nmwrlRNW4F9U0DUEFaeLZujYS56oxjQ49GRdsOPKSQCE97wRB7NNQ==}
|
||||
/@logto/cloud@0.2.5-94f7bcc(zod@3.22.4):
|
||||
resolution: {integrity: sha512-1nY3o1/gXgEIqgvjel2no0X3rR+BGnfozB7Vev+FY2qTkDyQIWRtHAnx+kkv4iEIIFcZW86LRNlvfjDUqR2yIg==}
|
||||
engines: {node: ^20.9.0}
|
||||
dependencies:
|
||||
'@silverhand/essentials': 2.9.0
|
||||
|
|
Loading…
Add table
Reference in a new issue