--- title: Ruoli e permessi description: Dichiara quali oggetti e campi le funzioni di logica e i componenti front-end della tua app possono leggere e scrivere. icon: shield-halved --- Un **ruolo** è un insieme di permessi: quali oggetti un’app può leggere o scrivere, quali campi può vedere e quali funzionalità a livello di piattaforma può usare. Tutte le funzioni di logica e i componenti front-end di ogni app ereditano i permessi del ruolo contrassegnato con `defineApplicationRole()` (vedi [The default function role](#the-default-function-role) di seguito). ```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], }); ``` ## Sicurezza a livello di riga Le autorizzazioni sugli oggetti e sui campi determinano *quali oggetti e campi* un ruolo può gestire. **I predicati di autorizzazione a livello di riga** vanno oltre e determinano *quali record* un ruolo può vedere e su cui può agire — per esempio, un ruolo self-service in cui ogni utente esterno vede solo i propri record. Dichiara i predicati con `rowLevelPermissionPredicates` sul ruolo. Come il resto del manifest, ogni predicato ha il proprio `universalIdentifier` e fa riferimento a un oggetto e a un campo tramite il loro `universalIdentifier`, un `operand` e (facoltativamente) un campo workspaceMember il cui valore viene iniettato al momento della query — così puoi esprimere "la relazione di proprietario del record **è** l'attuale membro dello spazio di lavoro": ```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, }, ], }); ``` Poiché i predicati vengono distribuiti nel manifest, vengono creati, aggiornati e rimossi insieme al ruolo a ogni installazione e aggiornamento — non è necessario alcun passaggio post-installazione separato per mantenerli sincronizzati. ### Combinare i predicati con i gruppi Per impostazione predefinita, i predicati di un ruolo sono combinati con `AND`. Per combinarne alcuni con `OR` (o per annidare la logica), dichiara una voce `rowLevelPermissionPredicateGroups` e collega ogni predicato ad essa tramite `predicateGroupUniversalIdentifier`. Questo ruolo consente a un partner di vedere un'Opportunità di cui **è proprietario** o per cui è il **punto di contatto**: ```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', }, ], }); ``` Note: * Assegna a ogni predicato e gruppo un `universalIdentifier` stabile (qualsiasi uuid) — identifica l'entità attraverso gli aggiornamenti e i predicati fanno riferimento ai gruppi tramite esso. * I predicati possono fare riferimento a oggetti e campi di proprietà della tua app o degli oggetti standard di Twenty. * La sicurezza a livello di riga è applicata per gli spazi di lavoro sui piani che la includono; i predicati vengono comunque sincronizzati sugli altri piani, semplicemente non vengono applicati. ## Ruolo funzione predefinito Quando esegui lo scaffolding di una nuova app, la CLI crea un file di ruolo predefinito dichiarato con `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()` è un leggero wrapper attorno a `defineRole()` che contrassegna il ruolo usato come predefinito per la tua applicazione al momento dell’installazione. La convalida è identica a `defineRole`, ma la pipeline di build collega automaticamente il suo `universalIdentifier` al `defaultRoleUniversalIdentifier` del manifest dell’applicazione — quindi non è necessario farvi riferimento in [`defineApplication`](/l/it/developers/extend/apps/config/application). Note: * È consentita esattamente **una** chiamata a `defineApplicationRole(...)` per app — la build del manifest avrà esito negativo se ne trova più di una. * Usa `defineRole()` (non `defineApplicationRole()`) per qualsiasi ruolo **aggiuntivo** fornito dalla tua app. * L’impostazione esplicita di `defaultRoleUniversalIdentifier` in `defineApplication()` è ancora supportata per retrocompatibilità, ma è deprecata a favore di `defineApplicationRole()`. ## Migliori Pratiche * Parti dal ruolo generato dallo scaffold, poi restringilo progressivamente: il ruolo predefinito concede un ampio accesso in lettura, che raramente è ciò che vuoi in produzione. * Sostituisci `objectPermissions` e `fieldPermissions` con gli oggetti e i campi di cui le tue funzioni hanno realmente bisogno. * `permissionFlagUniversalIdentifiers` controllano l'accesso alle funzionalità a livello di piattaforma. Mantienili al minimo. * Vedi un esempio funzionante: [`hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts).