Salt la conținutul principal
Un rol este un set de permisiuni: ce obiecte poate citi sau scrie o aplicație, ce câmpuri poate vedea și ce capabilități la nivel de platformă poate folosi. Funcțiile de logică și componentele front-end ale fiecărei aplicații moștenesc permisiunile rolului marcat cu defineApplicationRole() (consultați Rolul implicit pentru funcții mai jos).
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],
});

Securitate la nivel de rând

Permisiunile pentru obiecte și câmpuri decid ce obiecte și câmpuri poate accesa un rol. Predicate de permisiuni la nivel de rând merg mai departe și decid ce înregistrări poate vedea și asupra cărora poate acționa un rol — de exemplu, un rol de tip autoservire în care fiecare utilizator extern își vede doar propriile înregistrări. Declară predicate cu rowLevelPermissionPredicates în rol. La fel ca restul manifestului, fiecare predicat are propriul universalIdentifier și face referire la un obiect și un câmp prin universalIdentifier, un operand și (opțional) un câmp workspaceMember a cărui valoare este injectată în momentul interogării — astfel încât poți exprima „relația de proprietar a înregistrării este membrul curent al spațiului de lucru”:
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,
    },
  ],
});
Deoarece predicatele sunt livrate în manifest, ele sunt create, actualizate și eliminate împreună cu rolul la fiecare instalare și actualizare — nu există un pas separat post-instalare pentru a le menține sincronizate.

Combinarea predicatelor cu grupuri

În mod implicit, predicatele unui rol sunt combinate cu AND. Pentru a combina unele dintre ele cu OR (sau pentru a imbrica logica), declară o intrare rowLevelPermissionPredicateGroups și asociază fiecare predicat la aceasta prin predicateGroupUniversalIdentifier. Acest rol permite unui partener să vadă o oportunitate pe care fie o deține, fie pentru care este punctul de contact:
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',
    },
  ],
});
Notițe:
  • Oferă fiecărui predicat și fiecărui grup un universalIdentifier stabil (orice uuid) — acesta este cheia entității de-a lungul actualizărilor, iar predicatele fac referire la grupuri prin el.
  • Predicatele pot face referire la obiecte și câmpuri deținute de aplicația ta sau de obiectele standard ale Twenty.
  • Securitatea la nivel de rând este aplicată pentru spațiile de lucru din planurile care o includ; predicatele se sincronizează în continuare pe alte planuri, doar că nu sunt aplicate.

Rolul implicit pentru funcții

Când generați o aplicație nouă, CLI creează un fișier de rol implicit declarat cu defineApplicationRole():
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() este un wrapper subțire în jurul defineRole() care marchează rolul utilizat ca implicit pentru aplicația dvs. în momentul instalării. Validarea este identică cu defineRole, dar pipeline-ul de build conectează automat universalIdentifier în defaultRoleUniversalIdentifier din manifestul aplicației — astfel încât nu trebuie să îl referiți manual din defineApplication. Notițe:
  • Exact un defineApplicationRole(...) este permis per aplicație — build-ul manifestului va eșua dacă găsește mai mult de unul.
  • Utilizați defineRole() (nu defineApplicationRole()) pentru orice roluri suplimentare cu care este livrată aplicația.
  • Setarea explicită a defaultRoleUniversalIdentifier în defineApplication() este în continuare acceptată pentru compatibilitate retroactivă, dar este considerată învechită în favoarea defineApplicationRole().

Cele mai bune practici

  • Porniți de la rolul generat de scaffolding, apoi restrângeți-l progresiv — rolul implicit acordă acces larg la citire, ceea ce rareori este de dorit în producție.
  • Înlocuiți objectPermissions și fieldPermissions cu obiectele și câmpurile de care au nevoie efectiv funcțiile dvs.
  • permissionFlagUniversalIdentifiers controlează accesul la capabilități la nivelul platformei. Mențineți-le la minimum.
  • Vedeți un exemplu funcțional: hello-world/src/roles/function-role.ts.