mirror of
https://github.com/logto-io/logto.git
synced 2025-03-31 22:51:25 -05:00
feat(console): assign permissions for org roles (#5664)
This commit is contained in:
parent
c1c91b6ab8
commit
07ed139d6a
23 changed files with 416 additions and 14 deletions
|
@ -0,0 +1,125 @@
|
|||
import { type AdminConsoleKey } from '@logto/phrases';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import ConfirmModal from '@/ds-components/ConfirmModal';
|
||||
import DataTransferBox from '@/ds-components/DataTransferBox';
|
||||
import TabNav, { TabNavItem } from '@/ds-components/TabNav';
|
||||
import TabWrapper from '@/ds-components/TabWrapper';
|
||||
|
||||
import { PermissionType } from './types';
|
||||
import useOrganizationRolePermissionsAssignment from './use-organization-role-permissions-assignment';
|
||||
|
||||
const permissionTabs = {
|
||||
[PermissionType.Organization]: {
|
||||
title: 'organization_role_details.permissions.organization_permissions',
|
||||
key: PermissionType.Organization,
|
||||
},
|
||||
[PermissionType.Api]: {
|
||||
title: 'organization_role_details.permissions.api_permissions',
|
||||
key: PermissionType.Api,
|
||||
},
|
||||
} satisfies {
|
||||
[key in PermissionType]: {
|
||||
title: AdminConsoleKey;
|
||||
key: key;
|
||||
};
|
||||
};
|
||||
|
||||
type Props = {
|
||||
organizationRoleId: string;
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
function OrganizationRolePermissionsAssignmentModal({
|
||||
organizationRoleId,
|
||||
isOpen,
|
||||
onClose,
|
||||
}: Props) {
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
|
||||
const {
|
||||
activeTab,
|
||||
setActiveTab,
|
||||
onSubmit,
|
||||
organizationScopesAssignment,
|
||||
resourceScopesAssignment,
|
||||
clearSelectedData,
|
||||
isLoading,
|
||||
} = useOrganizationRolePermissionsAssignment(organizationRoleId);
|
||||
|
||||
const onCloseHandler = useCallback(() => {
|
||||
onClose();
|
||||
clearSelectedData();
|
||||
setActiveTab(PermissionType.Organization);
|
||||
}, [clearSelectedData, onClose, setActiveTab]);
|
||||
|
||||
const onSubmitHandler = useCallback(async () => {
|
||||
await onSubmit();
|
||||
onCloseHandler();
|
||||
}, [onCloseHandler, onSubmit]);
|
||||
|
||||
const tabs = useMemo(
|
||||
() =>
|
||||
Object.values(permissionTabs).map(({ title, key }) => {
|
||||
const selectedDataCount =
|
||||
key === PermissionType.Organization
|
||||
? organizationScopesAssignment.selectedData.length
|
||||
: resourceScopesAssignment.selectedData.length;
|
||||
|
||||
return (
|
||||
<TabNavItem
|
||||
key={key}
|
||||
isActive={key === activeTab}
|
||||
onClick={() => {
|
||||
setActiveTab(key);
|
||||
}}
|
||||
>
|
||||
{`${t(title)}${selectedDataCount ? ` (${selectedDataCount})` : ''}`}
|
||||
</TabNavItem>
|
||||
);
|
||||
}),
|
||||
[
|
||||
activeTab,
|
||||
organizationScopesAssignment.selectedData.length,
|
||||
resourceScopesAssignment.selectedData.length,
|
||||
setActiveTab,
|
||||
t,
|
||||
]
|
||||
);
|
||||
|
||||
return (
|
||||
<ConfirmModal
|
||||
isOpen={isOpen}
|
||||
isLoading={isLoading}
|
||||
title="organization_role_details.permissions.assign_permissions"
|
||||
subtitle="organization_role_details.permissions.assign_description"
|
||||
confirmButtonType="primary"
|
||||
confirmButtonText="general.save"
|
||||
cancelButtonText="general.discard"
|
||||
size="large"
|
||||
onCancel={onCloseHandler}
|
||||
onConfirm={onSubmitHandler}
|
||||
>
|
||||
<TabNav>{tabs}</TabNav>
|
||||
<TabWrapper
|
||||
key={PermissionType.Organization}
|
||||
isActive={PermissionType.Organization === activeTab}
|
||||
>
|
||||
<DataTransferBox
|
||||
title="organization_role_details.permissions.assign_organization_permissions"
|
||||
{...organizationScopesAssignment}
|
||||
/>
|
||||
</TabWrapper>
|
||||
<TabWrapper key={PermissionType.Api} isActive={PermissionType.Api === activeTab}>
|
||||
<DataTransferBox
|
||||
title="organization_role_details.permissions.assign_api_permissions"
|
||||
{...resourceScopesAssignment}
|
||||
/>
|
||||
</TabWrapper>
|
||||
</ConfirmModal>
|
||||
);
|
||||
}
|
||||
|
||||
export default OrganizationRolePermissionsAssignmentModal;
|
|
@ -0,0 +1,4 @@
|
|||
export enum PermissionType {
|
||||
Organization = 'Organization',
|
||||
Api = 'Api',
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
import { cond } from '@silverhand/essentials';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
|
||||
import useApi from '@/hooks/use-api';
|
||||
import useOrganizationRoleScopes from '@/pages/OrganizationRoleDetails/Permissions/use-organization-role-scopes';
|
||||
|
||||
import { PermissionType } from './types';
|
||||
import useOrganizationScopesAssignment from './use-organization-scopes-assignment';
|
||||
import useResourceScopesAssignment from './use-resource-scopes-assignment';
|
||||
|
||||
function useOrganizationRolePermissionsAssignment(organizationRoleId: string) {
|
||||
const organizationRolePath = `api/organization-roles/${organizationRoleId}`;
|
||||
const [activeTab, setActiveTab] = useState<PermissionType>(PermissionType.Organization);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const api = useApi();
|
||||
|
||||
const { organizationScopes, resourceScopes, mutate } =
|
||||
useOrganizationRoleScopes(organizationRoleId);
|
||||
|
||||
const organizationScopesAssignment = useOrganizationScopesAssignment(organizationScopes);
|
||||
const resourceScopesAssignment = useResourceScopesAssignment(resourceScopes);
|
||||
|
||||
const clearSelectedData = useCallback(() => {
|
||||
organizationScopesAssignment.setSelectedData([]);
|
||||
resourceScopesAssignment.setSelectedData([]);
|
||||
}, [organizationScopesAssignment, resourceScopesAssignment]);
|
||||
|
||||
const onSubmit = useCallback(async () => {
|
||||
setIsLoading(true);
|
||||
const newOrganizationScopes = organizationScopesAssignment.selectedData.map(({ id }) => id);
|
||||
const newResourceScopes = resourceScopesAssignment.selectedData.map(({ id }) => id);
|
||||
|
||||
await Promise.all(
|
||||
[
|
||||
cond(
|
||||
newOrganizationScopes.length > 0 &&
|
||||
api.post(`${organizationRolePath}/scopes`, {
|
||||
json: { organizationScopeIds: newOrganizationScopes },
|
||||
})
|
||||
),
|
||||
cond(
|
||||
newResourceScopes.length > 0 &&
|
||||
api.post(`${organizationRolePath}/resource-scopes`, {
|
||||
json: { scopeIds: newResourceScopes },
|
||||
})
|
||||
),
|
||||
].filter(Boolean)
|
||||
).finally(() => {
|
||||
setIsLoading(false);
|
||||
});
|
||||
|
||||
mutate();
|
||||
}, [
|
||||
api,
|
||||
mutate,
|
||||
organizationRolePath,
|
||||
organizationScopesAssignment.selectedData,
|
||||
resourceScopesAssignment.selectedData,
|
||||
]);
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
activeTab,
|
||||
setActiveTab,
|
||||
isLoading,
|
||||
organizationScopesAssignment,
|
||||
resourceScopesAssignment,
|
||||
clearSelectedData,
|
||||
onSubmit,
|
||||
}),
|
||||
[
|
||||
activeTab,
|
||||
clearSelectedData,
|
||||
isLoading,
|
||||
onSubmit,
|
||||
organizationScopesAssignment,
|
||||
resourceScopesAssignment,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
export default useOrganizationRolePermissionsAssignment;
|
|
@ -0,0 +1,28 @@
|
|||
import { type OrganizationScope } from '@logto/schemas';
|
||||
import { useMemo, useState } from 'react';
|
||||
import useSWR from 'swr';
|
||||
|
||||
function useOrganizationScopesAssignment(assignedScopes: OrganizationScope[] = []) {
|
||||
const [selectedData, setSelectedData] = useState<OrganizationScope[]>([]);
|
||||
|
||||
const { data: organizationScopes } = useSWR<OrganizationScope[]>('api/organization-scopes');
|
||||
|
||||
const availableDataList = useMemo(
|
||||
() =>
|
||||
(organizationScopes ?? []).filter(
|
||||
({ id }) => !assignedScopes.some((scope) => scope.id === id)
|
||||
),
|
||||
[organizationScopes, assignedScopes]
|
||||
);
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
selectedData,
|
||||
setSelectedData,
|
||||
availableDataList,
|
||||
}),
|
||||
[selectedData, setSelectedData, availableDataList]
|
||||
);
|
||||
}
|
||||
|
||||
export default useOrganizationScopesAssignment;
|
|
@ -0,0 +1,42 @@
|
|||
import { isManagementApi, type Scope, type ResourceResponse } from '@logto/schemas';
|
||||
import { useMemo, useState } from 'react';
|
||||
import useSWR from 'swr';
|
||||
|
||||
import { type DataGroup } from '@/ds-components/DataTransferBox/type';
|
||||
|
||||
function useResourceScopesAssignment(assignedScopes?: Scope[]) {
|
||||
const [selectedData, setSelectedData] = useState<Scope[]>([]);
|
||||
|
||||
const { data: allResources } = useSWR<ResourceResponse[]>('api/resources?includeScopes=true');
|
||||
|
||||
const availableDataGroups: Array<DataGroup<Scope>> = useMemo(() => {
|
||||
if (!allResources) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const resourcesWithScopes = allResources
|
||||
// Filter out the management APIs
|
||||
.filter((resource) => !isManagementApi(resource.indicator))
|
||||
.map(({ name, scopes, id: resourceId }) => ({
|
||||
groupId: resourceId,
|
||||
groupName: name,
|
||||
dataList: scopes
|
||||
// Filter out the scopes that have been assigned
|
||||
.filter(({ id: scopeId }) => !assignedScopes?.some((scope) => scope.id === scopeId)),
|
||||
}));
|
||||
|
||||
// Filter out the resources that have no scopes
|
||||
return resourcesWithScopes.filter(({ dataList }) => dataList.length > 0);
|
||||
}, [allResources, assignedScopes]);
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
selectedData,
|
||||
setSelectedData,
|
||||
availableDataGroups,
|
||||
}),
|
||||
[availableDataGroups, selectedData]
|
||||
);
|
||||
}
|
||||
|
||||
export default useResourceScopesAssignment;
|
|
@ -8,6 +8,7 @@ import ActionsButton from '@/components/ActionsButton';
|
|||
import Breakable from '@/components/Breakable';
|
||||
import EditScopeModal, { type EditScopeData } from '@/components/EditScopeModal';
|
||||
import EmptyDataPlaceholder from '@/components/EmptyDataPlaceholder';
|
||||
import OrganizationRolePermissionsAssignmentModal from '@/components/OrganizationRolePermissionsAssignmentModal';
|
||||
import Button from '@/ds-components/Button';
|
||||
import DynamicT from '@/ds-components/DynamicT';
|
||||
import Search from '@/ds-components/Search';
|
||||
|
@ -77,6 +78,8 @@ function Permissions({ organizationRoleId }: Props) {
|
|||
mutate();
|
||||
};
|
||||
|
||||
const [isAssignScopesModalOpen, setIsAssignScopesModalOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Table
|
||||
|
@ -161,7 +164,7 @@ function Permissions({ organizationRoleId }: Props) {
|
|||
type="primary"
|
||||
icon={<Plus />}
|
||||
onClick={() => {
|
||||
// Todo @xiaoyijun Assign permissions to org role
|
||||
setIsAssignScopesModalOpen(true);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
@ -199,6 +202,13 @@ function Permissions({ organizationRoleId }: Props) {
|
|||
}}
|
||||
/>
|
||||
)}
|
||||
<OrganizationRolePermissionsAssignmentModal
|
||||
organizationRoleId={organizationRoleId}
|
||||
isOpen={isAssignScopesModalOpen}
|
||||
onClose={() => {
|
||||
setIsAssignScopesModalOpen(false);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { type OrganizationRole } from '@logto/schemas';
|
||||
import { useCallback } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
@ -15,18 +16,29 @@ import { trySubmitSafe } from '@/utils/form';
|
|||
type FormData = Pick<OrganizationRole, 'name' | 'description'>;
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
onClose: (createdOrganizationRole?: OrganizationRole) => void;
|
||||
};
|
||||
|
||||
function CreateOrganizationRoleModal({ onClose }: Props) {
|
||||
function CreateOrganizationRoleModal({ isOpen, onClose }: Props) {
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
|
||||
const {
|
||||
register,
|
||||
formState: { errors, isSubmitting },
|
||||
handleSubmit,
|
||||
reset,
|
||||
} = useForm<FormData>();
|
||||
|
||||
const onCloseHandler = useCallback(
|
||||
(createdData?: OrganizationRole) => {
|
||||
// Reset form when modal is closed
|
||||
reset();
|
||||
onClose(createdData);
|
||||
},
|
||||
[onClose, reset]
|
||||
);
|
||||
|
||||
const api = useApi();
|
||||
|
||||
const submit = handleSubmit(
|
||||
|
@ -37,17 +49,17 @@ function CreateOrganizationRoleModal({ onClose }: Props) {
|
|||
toast.success(
|
||||
t('organization_template.roles.create_modal.created', { name: createdData.name })
|
||||
);
|
||||
onClose(createdData);
|
||||
onCloseHandler(createdData);
|
||||
})
|
||||
);
|
||||
|
||||
return (
|
||||
<ReactModal
|
||||
isOpen
|
||||
isOpen={isOpen}
|
||||
className={modalStyles.content}
|
||||
overlayClassName={modalStyles.overlay}
|
||||
onRequestClose={() => {
|
||||
onClose();
|
||||
onCloseHandler();
|
||||
}}
|
||||
>
|
||||
<ModalLayout
|
||||
|
@ -60,7 +72,7 @@ function CreateOrganizationRoleModal({ onClose }: Props) {
|
|||
onClick={submit}
|
||||
/>
|
||||
}
|
||||
onClose={onClose}
|
||||
onClose={onCloseHandler}
|
||||
>
|
||||
<FormField isRequired title="organization_template.roles.create_modal.name_field">
|
||||
<TextInput
|
||||
|
|
|
@ -11,6 +11,7 @@ import RolesEmpty from '@/assets/images/roles-empty.svg';
|
|||
import Breakable from '@/components/Breakable';
|
||||
import EmptyDataPlaceholder from '@/components/EmptyDataPlaceholder';
|
||||
import ItemPreview from '@/components/ItemPreview';
|
||||
import OrganizationRolePermissionsAssignmentModal from '@/components/OrganizationRolePermissionsAssignmentModal';
|
||||
import ThemedIcon from '@/components/ThemedIcon';
|
||||
import { defaultPageSize, organizationRoleLink } from '@/consts';
|
||||
import Button from '@/ds-components/Button';
|
||||
|
@ -51,6 +52,7 @@ function OrganizationRoles() {
|
|||
const [orgRoles, totalCount] = data ?? [];
|
||||
|
||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||
const [createdRole, setCreatedRole] = useState<OrganizationRoleWithScopes>();
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -152,14 +154,24 @@ function OrganizationRoles() {
|
|||
errorMessage={error?.body?.message ?? error?.message}
|
||||
onRetry={async () => mutate(undefined, true)}
|
||||
/>
|
||||
{isCreateModalOpen && (
|
||||
<CreateOrganizationRoleModal
|
||||
onClose={(createdRole) => {
|
||||
setIsCreateModalOpen(false);
|
||||
if (createdRole) {
|
||||
void mutate();
|
||||
navigate(createdRole.id);
|
||||
}
|
||||
<CreateOrganizationRoleModal
|
||||
isOpen={isCreateModalOpen}
|
||||
onClose={(createdRole) => {
|
||||
setIsCreateModalOpen(false);
|
||||
if (createdRole) {
|
||||
void mutate();
|
||||
setCreatedRole({ ...createdRole, scopes: [], resourceScopes: [] });
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{createdRole && (
|
||||
<OrganizationRolePermissionsAssignmentModal
|
||||
isOpen
|
||||
organizationRoleId={createdRole.id}
|
||||
onClose={() => {
|
||||
setCreatedRole(undefined);
|
||||
navigate(createdRole.id);
|
||||
void mutate();
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -19,6 +19,12 @@ const organization_role_details = {
|
|||
remove_confirmation:
|
||||
'Wenn diese Berechtigung entfernt wird, verliert der Benutzer mit dieser Organisationsrolle den Zugriff, der durch diese Berechtigung gewährt wurde.',
|
||||
removed: 'Die Berechtigung {{name}} wurde erfolgreich aus dieser Organisationsrolle entfernt',
|
||||
assign_description:
|
||||
'Weisen Sie Berechtigungen den Rollen innerhalb dieser Organisation zu. Diese können sowohl Organisationsberechtigungen als auch API-Berechtigungen umfassen.',
|
||||
organization_permissions: 'Organisationsberechtigungen',
|
||||
api_permissions: 'API-Berechtigungen',
|
||||
assign_organization_permissions: 'Organisationsberechtigungen zuweisen',
|
||||
assign_api_permissions: 'API-Berechtigungen zuweisen',
|
||||
},
|
||||
general: {
|
||||
tab: 'Allgemein',
|
||||
|
|
|
@ -19,6 +19,12 @@ const organization_role_details = {
|
|||
remove_confirmation:
|
||||
'If this permission is removed, the user with this organization role will lose the access granted by this permission.',
|
||||
removed: 'The permission {{name}} was successfully removed from this organization role',
|
||||
assign_description:
|
||||
'Assign permissions to the roles within this organization. These can include both organization permissions and API permissions.',
|
||||
organization_permissions: 'Organization permissions',
|
||||
api_permissions: 'API permissions',
|
||||
assign_organization_permissions: 'Assign organization permissions',
|
||||
assign_api_permissions: 'Assign API permissions',
|
||||
},
|
||||
general: {
|
||||
tab: 'General',
|
||||
|
|
|
@ -19,6 +19,12 @@ const organization_role_details = {
|
|||
remove_confirmation:
|
||||
'Si este permiso se elimina, el usuario con este rol de organización perderá el acceso otorgado por este permiso.',
|
||||
removed: 'El permiso {{name}} se eliminó correctamente de este rol de organización',
|
||||
assign_description:
|
||||
'Asigne permisos a los roles dentro de esta organización. Estos pueden incluir tanto permisos de organización como permisos de API.',
|
||||
organization_permissions: 'Permisos de organización',
|
||||
api_permissions: 'Permisos de API',
|
||||
assign_organization_permissions: 'Asignar permisos de organización',
|
||||
assign_api_permissions: 'Asignar permisos de API',
|
||||
},
|
||||
general: {
|
||||
tab: 'General',
|
||||
|
|
|
@ -19,6 +19,12 @@ const organization_role_details = {
|
|||
remove_confirmation:
|
||||
"Si cette permission est supprimée, l'utilisateur avec ce rôle d'organisation perdra l'accès accordé par cette permission.",
|
||||
removed: "La permission {{name}} a été supprimée avec succès de ce rôle d'organisation",
|
||||
assign_description:
|
||||
"Attribuez des autorisations aux rôles au sein de cette organisation. Celles-ci peuvent inclure à la fois des autorisations d'organisation et des autorisations d'API.",
|
||||
organization_permissions: "Autorisations de l'organisation",
|
||||
api_permissions: "Autorisations de l'API",
|
||||
assign_organization_permissions: 'Attribuer des permissions d’organisation',
|
||||
assign_api_permissions: 'Attribuer des permissions d’API',
|
||||
},
|
||||
general: {
|
||||
tab: 'Général',
|
||||
|
|
|
@ -19,6 +19,12 @@ const organization_role_details = {
|
|||
remove_confirmation:
|
||||
"Se questo permesso viene rimosso, l'utente con questo ruolo organizzativo perderà l'accesso concessogli da questo permesso.",
|
||||
removed: 'Il permesso {{name}} è stato rimosso con successo da questo ruolo organizzativo',
|
||||
assign_description:
|
||||
"Assegna le autorizzazioni ai ruoli all'interno di questa organizzazione. Queste possono includere sia autorizzazioni dell'organizzazione che autorizzazioni API.",
|
||||
organization_permissions: "Autorizzazioni dell'organizzazione",
|
||||
api_permissions: 'Autorizzazioni API',
|
||||
assign_organization_permissions: 'Assegna permessi di organizzazione',
|
||||
assign_api_permissions: 'Assegna permessi API',
|
||||
},
|
||||
general: {
|
||||
tab: 'Generale',
|
||||
|
|
|
@ -19,6 +19,12 @@ const organization_role_details = {
|
|||
remove_confirmation:
|
||||
'この権限を削除すると、この組織の役割を持つユーザーはこの権限によって付与されたアクセスを失います。',
|
||||
removed: 'この組織の役割から権限 {{name}} が正常に削除されました',
|
||||
assign_description:
|
||||
'この組織内のロールに権限を割り当てます。これには組織の権限とAPIの権限の両方が含まれる場合があります。',
|
||||
organization_permissions: '組織の権限',
|
||||
api_permissions: 'APIの権限',
|
||||
assign_organization_permissions: '組織の権限を割り当てる',
|
||||
assign_api_permissions: 'APIの権限を割り当てる',
|
||||
},
|
||||
general: {
|
||||
tab: '一般',
|
||||
|
|
|
@ -19,6 +19,12 @@ const organization_role_details = {
|
|||
remove_confirmation:
|
||||
'이 권한을 제거하면이 조직 역할을하는 사용자는이 권한으로 부여된 액세스를 잃게됩니다.',
|
||||
removed: '권한 {{name}}이(가)이 조직 역할에서 성공적으로 제거되었습니다',
|
||||
assign_description:
|
||||
'이 조직 내의 역할에 권한을 할당합니다. 이는 조직 권한과 API 권한을 모두 포함할 수 있습니다.',
|
||||
organization_permissions: '조직 권한',
|
||||
api_permissions: 'API 권한',
|
||||
assign_organization_permissions: '조직 권한 할당',
|
||||
assign_api_permissions: 'API 권한 할당',
|
||||
},
|
||||
general: {
|
||||
tab: '일반',
|
||||
|
|
|
@ -19,6 +19,12 @@ const organization_role_details = {
|
|||
remove_confirmation:
|
||||
'Jeśli to uprawnienie zostanie usunięte, użytkownik z tą rolą organizacyjną utraci dostęp udzielony przez to uprawnienie.',
|
||||
removed: 'Uprawnienie {{name}} zostało pomyślnie usunięte z tej roli organizacyjnej',
|
||||
assign_description:
|
||||
'Przypisz uprawnienia do ról w tej organizacji. Mogą one obejmować zarówno uprawnienia organizacyjne, jak i uprawnienia interfejsu API.',
|
||||
organization_permissions: 'Uprawnienia organizacyjne',
|
||||
api_permissions: 'Uprawnienia interfejsu API',
|
||||
assign_organization_permissions: 'Przydziel uprawnienia organizacyjne',
|
||||
assign_api_permissions: 'Przydziel uprawnienia API',
|
||||
},
|
||||
general: {
|
||||
tab: 'Ogólne',
|
||||
|
|
|
@ -19,6 +19,12 @@ const organization_role_details = {
|
|||
remove_confirmation:
|
||||
'Se esta permissão for removida, o usuário com essa função organizacional perderá o acesso concedido por esta permissão.',
|
||||
removed: 'A permissão {{name}} foi removida com sucesso desta função organizacional',
|
||||
assign_description:
|
||||
'Atribua permissões aos papéis dentro desta organização. Estas podem incluir tanto permissões de organização quanto permissões de API.',
|
||||
organization_permissions: 'Permissões de organização',
|
||||
api_permissions: 'Permissões de API',
|
||||
assign_organization_permissions: 'Atribuir permissões de organização',
|
||||
assign_api_permissions: 'Atribuir permissões de API',
|
||||
},
|
||||
general: {
|
||||
tab: 'Geral',
|
||||
|
|
|
@ -19,6 +19,12 @@ const organization_role_details = {
|
|||
remove_confirmation:
|
||||
'Se esta permissão for removida, o utilizador com esta função organizacional perderá o acesso concedido por esta permissão.',
|
||||
removed: 'A permissão {{name}} foi removida com sucesso desta função organizacional',
|
||||
assign_description:
|
||||
'Atribuir permissões aos cargos dentro desta organização. Estas podem incluir permissões de organização e permissões de API.',
|
||||
organization_permissions: 'Permissões de organização',
|
||||
api_permissions: 'Permissões de API',
|
||||
assign_organization_permissions: 'Atribuir permissões de organização',
|
||||
assign_api_permissions: 'Atribuir permissões de API',
|
||||
},
|
||||
general: {
|
||||
tab: 'Geral',
|
||||
|
|
|
@ -19,6 +19,12 @@ const organization_role_details = {
|
|||
remove_confirmation:
|
||||
'Если это разрешение будет удалено, пользователь с этой организационной ролью потеряет доступ, предоставленный этим разрешением.',
|
||||
removed: 'Разрешение {{name}} успешно удалено из этой организационной роли',
|
||||
assign_description:
|
||||
'Назначьте разрешения ролям в этой организации. Они могут включать как организационные разрешения, так и разрешения API.',
|
||||
organization_permissions: 'Организационные разрешения',
|
||||
api_permissions: 'Разрешения API',
|
||||
assign_organization_permissions: 'Назначить разрешения организации',
|
||||
assign_api_permissions: 'Назначить разрешения API',
|
||||
},
|
||||
general: {
|
||||
tab: 'Общее',
|
||||
|
|
|
@ -19,6 +19,12 @@ const organization_role_details = {
|
|||
remove_confirmation:
|
||||
'Bu izin kaldırılırsa, bu organizasyon rolüne sahip kullanıcı bu izin tarafından verilen erişimi kaybeder.',
|
||||
removed: '{{name}} izni bu organizasyon rolünden başarıyla kaldırıldı',
|
||||
assign_description:
|
||||
'Bu organizasyon içindeki roller için izinleri atayın. Bunlar hem organizasyon izinlerini hem de API izinlerini içerebilir.',
|
||||
organization_permissions: 'Organizasyon izinleri',
|
||||
api_permissions: 'API izinleri',
|
||||
assign_organization_permissions: 'Kuruluş izinleri ata',
|
||||
assign_api_permissions: 'API izinleri ata',
|
||||
},
|
||||
general: {
|
||||
tab: 'Genel',
|
||||
|
|
|
@ -18,6 +18,11 @@ const organization_role_details = {
|
|||
remove_permission: '移除权限',
|
||||
remove_confirmation: '如果移除此权限,拥有此组织角色的用户将失去此权限授予的访问权限。',
|
||||
removed: '权限 {{name}} 已成功从此组织角色中移除',
|
||||
assign_description: '为此组织中的角色分配权限。这些权限可以包括组织权限和 API 权限。',
|
||||
organization_permissions: '组织权限',
|
||||
api_permissions: 'API 权限',
|
||||
assign_organization_permissions: '分配组织权限',
|
||||
assign_api_permissions: '分配API权限',
|
||||
},
|
||||
general: {
|
||||
tab: '常规',
|
||||
|
|
|
@ -18,6 +18,11 @@ const organization_role_details = {
|
|||
remove_permission: '移除權限',
|
||||
remove_confirmation: '如果移除此權限,擁有此組織角色的使用者將失去此權限所授予的存取權。',
|
||||
removed: '權限 {{name}} 已成功從此組織角色中移除',
|
||||
assign_description: '為此組織中的角色分配權限。這些可以包括組織權限和 API 權限。',
|
||||
organization_permissions: '組織權限',
|
||||
api_permissions: 'API 權限',
|
||||
assign_organization_permissions: '分配組織權限',
|
||||
assign_api_permissions: '分配API權限',
|
||||
},
|
||||
general: {
|
||||
tab: '一般',
|
||||
|
|
|
@ -18,6 +18,11 @@ const organization_role_details = {
|
|||
remove_permission: '移除權限',
|
||||
remove_confirmation: '如果移除此權限,擁有此組織角色的使用者將失去此權限所授予的存取權。',
|
||||
removed: '權限 {{name}} 已成功從此組織角色中移除',
|
||||
assign_description: '為此組織中的角色分配權限。這些可以包括組織權限和 API 權限。',
|
||||
organization_permissions: '組織權限',
|
||||
api_permissions: 'API 權限',
|
||||
assign_organization_permissions: '分配組織權限',
|
||||
assign_api_permissions: '分配API許可權',
|
||||
},
|
||||
general: {
|
||||
tab: '一般',
|
||||
|
|
Loading…
Add table
Reference in a new issue