82f6597dc3
Created by Github action <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/21923?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> Co-authored-by: github-actions <github-actions@twenty.com>
205 lines
9.7 KiB
Plaintext
205 lines
9.7 KiB
Plaintext
---
|
|
title: 역할 및 권한
|
|
description: 앱의 로직 함수와 프런트 컴포넌트가 어떤 객체와 필드를 읽고 쓸 수 있는지 선언합니다.
|
|
icon: shield-halved
|
|
---
|
|
|
|
\*\*역할(role)\*\*은 권한 집합입니다. 즉, 앱이 어떤 객체를 읽거나 쓸 수 있는지, 어떤 필드를 볼 수 있는지, 그리고 어떤 플랫폼 수준 기능을 사용할 수 있는지를 정의합니다. 모든 앱의 로직 함수와 프런트 컴포넌트는 `defineApplicationRole()`로 표시된 역할의 권한을 상속받습니다(아래 [기본 함수 역할](#the-default-function-role)을 참조하세요).
|
|
|
|
```ts src/roles/restricted-company-role.ts
|
|
import {
|
|
defineRole,
|
|
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
|
|
SystemPermissionFlag,
|
|
} from 'twenty-sdk/define';
|
|
|
|
export default defineRole({
|
|
universalIdentifier: '2c80f640-2083-4803-bb49-003e38279de6',
|
|
label: 'My new role',
|
|
description: 'A role that can be used in your workspace',
|
|
canReadAllObjectRecords: false,
|
|
canUpdateAllObjectRecords: false,
|
|
canSoftDeleteAllObjectRecords: false,
|
|
canDestroyAllObjectRecords: false,
|
|
canUpdateAllSettings: false,
|
|
canBeAssignedToAgents: false,
|
|
canBeAssignedToUsers: false,
|
|
canBeAssignedToApiKeys: false,
|
|
objectPermissions: [
|
|
{
|
|
objectUniversalIdentifier:
|
|
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.company.universalIdentifier,
|
|
canReadObjectRecords: true,
|
|
canUpdateObjectRecords: true,
|
|
canSoftDeleteObjectRecords: false,
|
|
canDestroyObjectRecords: false,
|
|
},
|
|
],
|
|
fieldPermissions: [
|
|
{
|
|
objectUniversalIdentifier:
|
|
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.company.universalIdentifier,
|
|
fieldUniversalIdentifier:
|
|
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.company.fields.name
|
|
.universalIdentifier,
|
|
canReadFieldValue: false,
|
|
canUpdateFieldValue: false,
|
|
},
|
|
],
|
|
permissionFlagUniversalIdentifiers: [SystemPermissionFlag.APPLICATIONS],
|
|
});
|
|
```
|
|
|
|
## 행 수준 보안
|
|
|
|
오브젝트 및 필드 권한은 역할이 *어떤 오브젝트와 필드* 를 다룰 수 있는지를 결정합니다. **행 수준
|
|
권한 프레디킷** 은 더 나아가 역할이 *어떤 레코드* 를 보고 작업할 수 있는지를 결정합니다. 예를 들어, 각 외부 사용자가 자신의 레코드만 볼 수 있는 셀프 서비스 역할 같은 경우입니다.
|
|
|
|
역할에 `rowLevelPermissionPredicates` 로 프레디킷을 선언합니다. 매니페스트의 나머지와 마찬가지로,
|
|
각 프레디킷은 자체 `universalIdentifier` 를 가지고, 오브젝트와 필드를 각각의
|
|
`universalIdentifier`, `operand`, 그리고 (선택적으로) 쿼리 시점에 값이 주입되는 workspaceMember 필드를 통해 참조합니다. 이렇게 하면 "레코드의 owner relation **is** 현재 workspace member이다"를 표현할 수 있습니다:
|
|
|
|
```ts src/roles/partner-role.ts
|
|
import {
|
|
defineRole,
|
|
RowLevelPermissionPredicateOperand,
|
|
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
|
|
} from 'twenty-sdk/define';
|
|
|
|
import { ACCOUNT_OWNER_FIELD_UNIVERSAL_IDENTIFIER } from '../fields/account-owner.field';
|
|
|
|
export default defineRole({
|
|
universalIdentifier: 'c3c1dc2e-1a08-4de5-abb7-2139b3d99343',
|
|
label: 'Partner',
|
|
description: 'External partner — sees only its own records',
|
|
canBeAssignedToUsers: true,
|
|
objectPermissions: [
|
|
{
|
|
objectUniversalIdentifier:
|
|
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.company.universalIdentifier,
|
|
canReadObjectRecords: true,
|
|
canUpdateObjectRecords: true,
|
|
},
|
|
],
|
|
rowLevelPermissionPredicates: [
|
|
{
|
|
universalIdentifier: 'd0f0c1a2-3b4c-4d5e-8f60-111111111111',
|
|
objectUniversalIdentifier:
|
|
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.company.universalIdentifier,
|
|
fieldUniversalIdentifier: ACCOUNT_OWNER_FIELD_UNIVERSAL_IDENTIFIER,
|
|
operand: RowLevelPermissionPredicateOperand.IS,
|
|
workspaceMemberFieldUniversalIdentifier:
|
|
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.workspaceMember.fields.id
|
|
.universalIdentifier,
|
|
},
|
|
],
|
|
});
|
|
```
|
|
|
|
프레디킷은 매니페스트에 함께 포함되어 배포되므로, 모든 설치와 업그레이드 시 역할과 함께 생성·업데이트·제거됩니다. 동기화를 유지하기 위한 별도의 설치 후 단계는 필요하지 않습니다.
|
|
|
|
### 프레디킷을 그룹과 결합하기
|
|
|
|
기본적으로 역할의 프레디킷은 `AND`로 결합됩니다. 일부를 `OR`로 결합하거나(또는 논리를 중첩하려면) `rowLevelPermissionPredicateGroups` 항목을 선언하고 각 프레디킷이 `predicateGroupUniversalIdentifier`를 통해 해당 그룹을 가리키도록 설정합니다. 이 역할은 파트너가 자신이 **소유한** 또는 **담당자**인 기회(Opportunity)를 볼 수 있도록 허용합니다:
|
|
|
|
```ts src/roles/partner-opportunities-role.ts
|
|
import {
|
|
defineRole,
|
|
RowLevelPermissionPredicateGroupLogicalOperator,
|
|
RowLevelPermissionPredicateOperand,
|
|
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
|
|
} from 'twenty-sdk/define';
|
|
|
|
const OPPORTUNITY = STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.opportunity;
|
|
const CURRENT_MEMBER =
|
|
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.workspaceMember.fields.id
|
|
.universalIdentifier;
|
|
|
|
export default defineRole({
|
|
universalIdentifier: 'b2a1c0d9-8e7f-4a6b-9c5d-222222222222',
|
|
label: 'Partner (opportunities)',
|
|
canBeAssignedToUsers: true,
|
|
objectPermissions: [
|
|
{
|
|
objectUniversalIdentifier: OPPORTUNITY.universalIdentifier,
|
|
canReadObjectRecords: true,
|
|
},
|
|
],
|
|
rowLevelPermissionPredicateGroups: [
|
|
{
|
|
universalIdentifier: 'c3b2a1d0-9f8e-4b7a-8d6c-333333333333',
|
|
objectUniversalIdentifier: OPPORTUNITY.universalIdentifier,
|
|
logicalOperator: RowLevelPermissionPredicateGroupLogicalOperator.OR,
|
|
},
|
|
],
|
|
rowLevelPermissionPredicates: [
|
|
{
|
|
universalIdentifier: 'd4c3b2a1-0e9f-4c8b-9e7d-444444444444',
|
|
objectUniversalIdentifier: OPPORTUNITY.universalIdentifier,
|
|
fieldUniversalIdentifier: OPPORTUNITY.fields.owner.universalIdentifier,
|
|
operand: RowLevelPermissionPredicateOperand.IS,
|
|
workspaceMemberFieldUniversalIdentifier: CURRENT_MEMBER,
|
|
predicateGroupUniversalIdentifier: 'c3b2a1d0-9f8e-4b7a-8d6c-333333333333',
|
|
},
|
|
{
|
|
universalIdentifier: 'e5d4c3b2-1f0e-4d9c-8f8e-555555555555',
|
|
objectUniversalIdentifier: OPPORTUNITY.universalIdentifier,
|
|
fieldUniversalIdentifier:
|
|
OPPORTUNITY.fields.pointOfContact.universalIdentifier,
|
|
operand: RowLevelPermissionPredicateOperand.IS,
|
|
workspaceMemberFieldUniversalIdentifier: CURRENT_MEMBER,
|
|
predicateGroupUniversalIdentifier: 'c3b2a1d0-9f8e-4b7a-8d6c-333333333333',
|
|
},
|
|
],
|
|
});
|
|
```
|
|
|
|
노트:
|
|
|
|
* 모든 프레디킷과 그룹에 안정적인 `universalIdentifier`(임의의 uuid)를 부여하세요. 이는 업그레이드 전반에 걸쳐 엔티티의 키로 사용되며, 프레디킷은 이를 통해 그룹을 참조합니다.
|
|
* 프레디킷은 앱에서 소유한 오브젝트와 필드뿐만 아니라 Twenty의 표준 오브젝트가 소유한 오브젝트와 필드를 참조할 수 있습니다.
|
|
* 행 수준 보안은 이를 포함한 플랜의 워크스페이스에 대해 적용됩니다. 다른 플랜에서도 프레디킷은 계속 동기화되지만, 적용되지는 않습니다.
|
|
|
|
## 기본 함수 역할
|
|
|
|
새 앱을 스캐폴딩하면, CLI가 `defineApplicationRole()`로 선언된 기본 역할 파일을 생성합니다:
|
|
|
|
```ts src/roles/default-role.ts
|
|
import { defineApplicationRole } from 'twenty-sdk/define';
|
|
|
|
export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER =
|
|
'b648f87b-1d26-4961-b974-0908fd991061';
|
|
|
|
export default defineApplicationRole({
|
|
universalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER,
|
|
label: 'Default function role',
|
|
description: 'Default role for function Twenty client',
|
|
canReadAllObjectRecords: true,
|
|
canUpdateAllObjectRecords: false,
|
|
canSoftDeleteAllObjectRecords: false,
|
|
canDestroyAllObjectRecords: false,
|
|
canUpdateAllSettings: false,
|
|
canBeAssignedToAgents: false,
|
|
canBeAssignedToUsers: false,
|
|
canBeAssignedToApiKeys: false,
|
|
objectPermissions: [],
|
|
fieldPermissions: [],
|
|
permissionFlagUniversalIdentifiers: [],
|
|
});
|
|
```
|
|
|
|
`defineApplicationRole()`는 설치 시 애플리케이션의 기본 역할로 사용할 역할을 표시하는, `defineRole()`에 대한 간단한 래퍼입니다. 검증 방식은 `defineRole`과 동일하지만, 빌드 파이프라인이 애플리케이션 매니페스트의 `defaultRoleUniversalIdentifier`에 해당 역할의 `universalIdentifier`를 자동으로 연결하므로, [`defineApplication`](/l/ko/developers/extend/apps/config/application)에서 직접 참조할 필요가 없습니다.
|
|
|
|
노트:
|
|
|
|
* 앱당 정확히 **하나의** `defineApplicationRole(...)`만 허용되며, 둘 이상 발견되면 매니페스트 빌드가 실패합니다.
|
|
* 앱에서 제공하는 **추가** 역할에는 `defineApplicationRole()`가 아니라 `defineRole()`을 사용하세요.
|
|
* 호환성을 위해 `defineApplication()`에서 `defaultRoleUniversalIdentifier`를 명시적으로 설정하는 방식도 여전히 지원되지만, 이제는 `defineApplicationRole()` 방식이 권장되며 이전 방식은 더 이상 권장되지 않습니다.
|
|
|
|
## 모범 사례
|
|
|
|
* 스캐폴딩된 역할에서 시작한 다음 점진적으로 권한을 제한하세요. 기본 설정은 광범위한 읽기 액세스를 부여하는데, 이는 프로덕션 환경에서 원하는 경우가 거의 없습니다.
|
|
* `objectPermissions`와 `fieldPermissions`를 함수에 실제로 필요한 정확한 객체와 필드로 교체하세요.
|
|
* `permissionFlagUniversalIdentifiers`는 플랫폼 수준 기능에 대한 액세스를 제어합니다. 최소한으로 유지하세요.
|
|
* 동작 예제를 참조하세요: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts).
|