diff --git a/packages/console/src/consts/env.ts b/packages/console/src/consts/env.ts
index b49e6b6f7db3..888eb2d738f4 100644
--- a/packages/console/src/consts/env.ts
+++ b/packages/console/src/consts/env.ts
@@ -4,6 +4,5 @@ const isProduction = process.env.NODE_ENV === 'production';
export const isCloud = yes(process.env.IS_CLOUD);
export const adminEndpoint = process.env.ADMIN_ENDPOINT;
-// eslint-disable-next-line import/no-unused-modules
export const isDevFeaturesEnabled =
!isProduction || yes(process.env.DEV_FEATURES_ENABLED) || yes(process.env.INTEGRATION_TEST);
diff --git a/packages/console/src/pages/RoleDetails/index.tsx b/packages/console/src/pages/RoleDetails/index.tsx
index 4cba0d18673e..c28f5dc17929 100644
--- a/packages/console/src/pages/RoleDetails/index.tsx
+++ b/packages/console/src/pages/RoleDetails/index.tsx
@@ -3,7 +3,7 @@ import { Theme, RoleType } from '@logto/schemas';
import classNames from 'classnames';
import { useEffect, useState } from 'react';
import { toast } from 'react-hot-toast';
-import { useTranslation } from 'react-i18next';
+import { Trans, useTranslation } from 'react-i18next';
import { Outlet, useLocation, useParams } from 'react-router-dom';
import useSWR, { useSWRConfig } from 'swr';
@@ -14,11 +14,15 @@ import UserRoleIconDark from '@/assets/icons/user-role-dark.svg';
import UserRoleIcon from '@/assets/icons/user-role.svg';
import DetailsPage from '@/components/DetailsPage';
import DetailsPageHeader from '@/components/DetailsPage/DetailsPageHeader';
+import { isDevFeaturesEnabled } from '@/consts/env';
import { RoleDetailsTabs } from '@/consts/page-tabs';
import ConfirmModal from '@/ds-components/ConfirmModal';
+import InlineNotification from '@/ds-components/InlineNotification';
import TabNav, { TabNavItem } from '@/ds-components/TabNav';
+import TextLink from '@/ds-components/TextLink';
import type { RequestError } from '@/hooks/use-api';
import useApi from '@/hooks/use-api';
+import useConfigs from '@/hooks/use-configs';
import useTenantPathname from '@/hooks/use-tenant-pathname';
import useTheme from '@/hooks/use-theme';
@@ -47,6 +51,12 @@ function RoleDetails() {
const { mutate: mutateGlobal } = useSWRConfig();
const isLoading = !data && !error;
+ const { configs, updateConfigs } = useConfigs();
+ // Default to true to avoid page flickering
+ const isM2mRoleNotificationAcknowledged = configs
+ ? Boolean(configs.m2mRoleNotificationAcknowledged)
+ : true;
+
const [isDeletionAlertOpen, setIsDeletionAlertOpen] = useState(false);
useEffect(() => {
@@ -83,6 +93,25 @@ function RoleDetails() {
className={classNames(isPageHasTable && styles.withTable)}
onRetry={mutate}
>
+ {/* Todo @xiaoyijun remove dev feature flag */}
+ {isDevFeaturesEnabled && !isM2mRoleNotificationAcknowledged && (
+ {
+ void updateConfigs({
+ m2mRoleNotificationAcknowledged: true,
+ });
+ }}
+ >
+ ,
+ }}
+ >
+ {t('role_details.m2m_role_notification')}
+
+
+ )}
{data && (
<>
Erstellen Sie zuerst eine Maschinen-zu-Maschinen-App, wenn Sie noch keine erstellt haben.',
permission: {
assign_button: 'Berechtigungen zuweisen',
assign_title: 'Berechtigungen zuweisen',
diff --git a/packages/phrases/src/locales/en/translation/admin-console/role-details.ts b/packages/phrases/src/locales/en/translation/admin-console/role-details.ts
index 022f552e294b..08fbd3eacf72 100644
--- a/packages/phrases/src/locales/en/translation/admin-console/role-details.ts
+++ b/packages/phrases/src/locales/en/translation/admin-console/role-details.ts
@@ -18,6 +18,8 @@ const role_details = {
'Set this role as a default role for new users. Multiple default roles can be set. This will also affect the default roles for users created via Management API.',
type_m2m_role_tag: 'Machine-to-machine app role',
type_user_role_tag: 'User role',
+ m2m_role_notification:
+ 'Assign this machine-to-machine role to a machine-to-machine app to grant access to the relative API resources. Create a machine-to-machine app first if you haven’t already.',
permission: {
assign_button: 'Assign permissions',
assign_title: 'Assign permissions',
diff --git a/packages/phrases/src/locales/es/translation/admin-console/role-details.ts b/packages/phrases/src/locales/es/translation/admin-console/role-details.ts
index 397ad2c8b587..65f812d316f3 100644
--- a/packages/phrases/src/locales/es/translation/admin-console/role-details.ts
+++ b/packages/phrases/src/locales/es/translation/admin-console/role-details.ts
@@ -15,6 +15,8 @@ const role_details = {
field_description: 'Descripción',
type_m2m_role_tag: 'Rol de aplicación de máquina a máquina',
type_user_role_tag: 'Rol de usuario',
+ m2m_role_notification:
+ 'Asigne este rol de máquina a máquina a una aplicación de máquina a máquina para otorgar acceso a los recursos de API relativos. Cree primero una aplicación de máquina a máquina si aún no lo ha hecho.',
permission: {
assign_button: 'Asignar permisos',
assign_title: 'Asignar permisos',
diff --git a/packages/phrases/src/locales/fr/translation/admin-console/role-details.ts b/packages/phrases/src/locales/fr/translation/admin-console/role-details.ts
index 653c877c42fc..86080d08ff39 100644
--- a/packages/phrases/src/locales/fr/translation/admin-console/role-details.ts
+++ b/packages/phrases/src/locales/fr/translation/admin-console/role-details.ts
@@ -15,6 +15,8 @@ const role_details = {
field_description: 'Description',
type_m2m_role_tag: "Rôle de l'application machine-à-machine",
type_user_role_tag: "Rôle d'utilisateur",
+ m2m_role_notification:
+ "Attribuez ce rôle machine à machine à une application machine à machine pour accorder l'accès aux ressources d'API relatives. Créez d'abord une application machine à machine si ce n'est pas déjà fait.",
permission: {
assign_button: 'Attribuer des autorisations',
assign_title: 'Attribuer des autorisations',
diff --git a/packages/phrases/src/locales/it/translation/admin-console/role-details.ts b/packages/phrases/src/locales/it/translation/admin-console/role-details.ts
index 1a58df95e5eb..a00796998062 100644
--- a/packages/phrases/src/locales/it/translation/admin-console/role-details.ts
+++ b/packages/phrases/src/locales/it/translation/admin-console/role-details.ts
@@ -15,6 +15,8 @@ const role_details = {
field_description: 'Descrizione',
type_m2m_role_tag: 'Ruolo app macchina-to-macchina',
type_user_role_tag: 'Ruolo utente',
+ m2m_role_notification:
+ "Assegna questo ruolo di macchina a macchina a un'applicazione di macchina a macchina per concedere l'accesso alle risorse API relative. Crea prima un'applicazione di macchina a macchina se non l'hai ancora fatto.",
permission: {
assign_button: 'Assegna permessi',
assign_title: 'Assegna permessi',
diff --git a/packages/phrases/src/locales/ja/translation/admin-console/role-details.ts b/packages/phrases/src/locales/ja/translation/admin-console/role-details.ts
index 32b76f8bf5cf..fc1102ecc574 100644
--- a/packages/phrases/src/locales/ja/translation/admin-console/role-details.ts
+++ b/packages/phrases/src/locales/ja/translation/admin-console/role-details.ts
@@ -15,6 +15,8 @@ const role_details = {
field_description: '説明',
type_m2m_role_tag: '機械対機械のアプリのロール',
type_user_role_tag: 'ユーザーロール',
+ m2m_role_notification:
+ 'この機械間ロールを機械間アプリに割り当てて、関連するAPIリソースへのアクセスを許可します。まだ作成していない場合は、まず機械間アプリを作成してください。',
permission: {
assign_button: '許可を割り当てる',
assign_title: '許可の割り当て',
diff --git a/packages/phrases/src/locales/ko/translation/admin-console/role-details.ts b/packages/phrases/src/locales/ko/translation/admin-console/role-details.ts
index 804a638724ad..7004b0dc8183 100644
--- a/packages/phrases/src/locales/ko/translation/admin-console/role-details.ts
+++ b/packages/phrases/src/locales/ko/translation/admin-console/role-details.ts
@@ -15,6 +15,8 @@ const role_details = {
field_description: '설명',
type_m2m_role_tag: '기계 대 기계 앱 역할',
type_user_role_tag: '사용자 역할',
+ m2m_role_notification:
+ '이 머신 투 머신 역할을 머신 투 머신 앱에 할당하여 관련 API 리소스에 액세스할 수 있습니다. 아직 만들지 않은 경우에는 먼저 머신 투 머신 앱을 만드십시오.',
permission: {
assign_button: '권한 할당',
assign_title: '권한 할당',
diff --git a/packages/phrases/src/locales/pl-pl/translation/admin-console/role-details.ts b/packages/phrases/src/locales/pl-pl/translation/admin-console/role-details.ts
index 0ecf42a3f840..86ad7b271e31 100644
--- a/packages/phrases/src/locales/pl-pl/translation/admin-console/role-details.ts
+++ b/packages/phrases/src/locales/pl-pl/translation/admin-console/role-details.ts
@@ -15,6 +15,8 @@ const role_details = {
field_description: 'Opis',
type_m2m_role_tag: 'Rola aplikacji maszynowych',
type_user_role_tag: 'Rola użytkownika',
+ m2m_role_notification:
+ 'Przypisz tę rolę maszyny do maszyny do aplikacji maszyny do maszyny, aby umożliwić dostęp do odpowiednich zasobów API. Najpierw utwórz aplikację maszyny do maszyny, jeśli jeszcze tego nie zrobiłeś.',
permission: {
assign_button: 'Przypisz uprawnienia',
assign_title: 'Przypisz uprawnienia',
diff --git a/packages/phrases/src/locales/pt-br/translation/admin-console/role-details.ts b/packages/phrases/src/locales/pt-br/translation/admin-console/role-details.ts
index 71faa7ce9778..8e106a49b6f5 100644
--- a/packages/phrases/src/locales/pt-br/translation/admin-console/role-details.ts
+++ b/packages/phrases/src/locales/pt-br/translation/admin-console/role-details.ts
@@ -15,6 +15,8 @@ const role_details = {
field_description: 'Descrição',
type_m2m_role_tag: 'Função de aplicativo máquina-a-máquina',
type_user_role_tag: 'Função de usuário',
+ m2m_role_notification:
+ 'Atribua essa função de máquina para máquina a um aplicativo de máquina para máquina para conceder acesso aos recursos de API relativos. Crie primeiro um aplicativo de máquina para máquina se ainda não o fez.',
permission: {
assign_button: 'Atribuir permissões',
assign_title: 'Atribuir permissões',
diff --git a/packages/phrases/src/locales/pt-pt/translation/admin-console/role-details.ts b/packages/phrases/src/locales/pt-pt/translation/admin-console/role-details.ts
index 778216214947..7167e19ac25f 100644
--- a/packages/phrases/src/locales/pt-pt/translation/admin-console/role-details.ts
+++ b/packages/phrases/src/locales/pt-pt/translation/admin-console/role-details.ts
@@ -15,6 +15,8 @@ const role_details = {
field_description: 'Descrição',
type_m2m_role_tag: 'Função de aplicação de máquina para máquina',
type_user_role_tag: 'Função de utilizador',
+ m2m_role_notification:
+ 'Atribua esta função de máquina para máquina a uma aplicação de máquina para máquina para conceder acesso aos recursos de API relativos. Crie primeiro uma aplicação de máquina para máquina se ainda não o fez.',
permission: {
assign_button: 'Atribuir Permissões',
assign_title: 'Atribuir permissões',
diff --git a/packages/phrases/src/locales/ru/translation/admin-console/role-details.ts b/packages/phrases/src/locales/ru/translation/admin-console/role-details.ts
index f300c1ecf03e..14a00bc10f73 100644
--- a/packages/phrases/src/locales/ru/translation/admin-console/role-details.ts
+++ b/packages/phrases/src/locales/ru/translation/admin-console/role-details.ts
@@ -15,6 +15,8 @@ const role_details = {
field_description: 'Описание',
type_m2m_role_tag: 'Роль машинного приложения',
type_user_role_tag: 'Роль пользователя',
+ m2m_role_notification:
+ 'Назначьте эту роль машина-машина приложению машина-машина, чтобы предоставить доступ к соответствующим ресурсам API. Сначала создайте приложение машина-машина, если еще этого не сделали.',
permission: {
assign_button: 'Назначить Разрешения',
assign_title: 'Назначить разрешения',
diff --git a/packages/phrases/src/locales/tr-tr/translation/admin-console/role-details.ts b/packages/phrases/src/locales/tr-tr/translation/admin-console/role-details.ts
index 502a4482719b..4e937685cb49 100644
--- a/packages/phrases/src/locales/tr-tr/translation/admin-console/role-details.ts
+++ b/packages/phrases/src/locales/tr-tr/translation/admin-console/role-details.ts
@@ -15,6 +15,8 @@ const role_details = {
field_description: 'Açıklama',
type_m2m_role_tag: 'Makine-makine uygulama rolü',
type_user_role_tag: 'Kullanıcı rolü',
+ m2m_role_notification:
+ 'Bu makineye makine rolünü ilgili API kaynaklarına erişim sağlamak için bir makineye makine uygulamasına atayın. Henüz yapmadıysanız önce bir makineye makine uygulaması oluşturun.',
permission: {
assign_button: 'İzinleri Ata',
assign_title: 'İzinleri Ata',
diff --git a/packages/phrases/src/locales/zh-cn/translation/admin-console/role-details.ts b/packages/phrases/src/locales/zh-cn/translation/admin-console/role-details.ts
index 139b99645c39..1c33d9a4157d 100644
--- a/packages/phrases/src/locales/zh-cn/translation/admin-console/role-details.ts
+++ b/packages/phrases/src/locales/zh-cn/translation/admin-console/role-details.ts
@@ -15,6 +15,8 @@ const role_details = {
field_description: '描述',
type_m2m_role_tag: '机器对机器应用角色',
type_user_role_tag: '用户角色',
+ m2m_role_notification:
+ '将此机器到机器角色分配给机器到机器应用程序,以授予对相关API资源的访问权限。如果尚未创建,请首先创建机器到机器应用程序。',
permission: {
assign_button: '分配权限',
assign_title: '分配权限',
diff --git a/packages/phrases/src/locales/zh-hk/translation/admin-console/role-details.ts b/packages/phrases/src/locales/zh-hk/translation/admin-console/role-details.ts
index 77a5447712a9..e345c4269a5f 100644
--- a/packages/phrases/src/locales/zh-hk/translation/admin-console/role-details.ts
+++ b/packages/phrases/src/locales/zh-hk/translation/admin-console/role-details.ts
@@ -15,6 +15,8 @@ const role_details = {
field_description: '描述',
type_m2m_role_tag: '機器對機器應用角色',
type_user_role_tag: '用戶角色',
+ m2m_role_notification:
+ '將此機器對機器角色分配給機器對機器應用程式,以授予相關API資源的存取權限。如果尚未建立,請先建立機器對機器應用程式。',
permission: {
assign_button: '分配權限',
assign_title: '分配權限',
diff --git a/packages/phrases/src/locales/zh-tw/translation/admin-console/role-details.ts b/packages/phrases/src/locales/zh-tw/translation/admin-console/role-details.ts
index 45d260767c6f..5b6afbc21490 100644
--- a/packages/phrases/src/locales/zh-tw/translation/admin-console/role-details.ts
+++ b/packages/phrases/src/locales/zh-tw/translation/admin-console/role-details.ts
@@ -15,6 +15,8 @@ const role_details = {
field_description: '描述',
type_m2m_role_tag: '機器對機器應用角色',
type_user_role_tag: '用戶角色',
+ m2m_role_notification:
+ '將此機器對機器角色分配給機器對機器應用程式,以授予相關API資源的存取權限。如果尚未建立,請先建立機器對機器應用程式。',
permission: {
assign_button: '分配權限',
assign_title: '分配權限',
diff --git a/packages/schemas/src/types/logto-config/index.ts b/packages/schemas/src/types/logto-config/index.ts
index aa92f0a01aea..51f5bf091b17 100644
--- a/packages/schemas/src/types/logto-config/index.ts
+++ b/packages/schemas/src/types/logto-config/index.ts
@@ -108,6 +108,7 @@ export const adminConsoleDataGuard = z.object({
tenantMember: z.boolean().optional(),
})
.optional(),
+ m2mRoleNotificationAcknowledged: z.boolean().optional(),
});
export type AdminConsoleData = z.infer;