Files
CRM_Montzar/apps/api/test/record-scope.test.ts
MahdiandCursor 9812e4e5ba fix(crm): honor open data scopes and role assignees
Unset sections on a saved role policy were still filtered as own-only, so full lead access showed nothing. Activities can now be assigned by org role, and the Tahesab sales report reads as a result instead of a tag wall.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-27 18:07:42 +03:30

125 lines
4.6 KiB
TypeScript

import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { leadsDeepWhere, resolveSectionAccess } from '../src/common/data-access';
import {
noteAccessWhere,
normalizeDataVisibility,
ownerWhere,
parseVisibilityScopes,
resolveOwnerId,
scopedOwnerIds,
seesAllRecords,
} from '../src/common/record-scope';
const sales = { userId: 'u1', role: 'sales' };
describe('سطح دسترسی به پرونده‌ها', () => {
it('مدیر و مالک همه را می‌بینند', () => {
assert.ok(seesAllRecords({ role: 'owner' }));
assert.ok(seesAllRecords({ role: 'admin' }));
assert.deepEqual(ownerWhere({ userId: 'a', role: 'admin' }), {});
});
it('کارشناس فروش فقط پرونده‌های خودش را می‌بیند', () => {
assert.ok(!seesAllRecords(sales));
assert.deepEqual(scopedOwnerIds(sales), ['u1']);
assert.deepEqual(ownerWhere(sales), { ownerId: 'u1' });
});
it('دید تیمی', () => {
const actor = { ...sales, dataVisibility: 'team' as const, visibleUserIds: ['u1', 'u2', 'u2'] };
assert.deepEqual(ownerWhere(actor), { ownerId: { in: ['u1', 'u2'] } });
});
it('دید سازمانی یا visibleUserIds=null یعنی همه', () => {
assert.deepEqual(ownerWhere({ ...sales, dataVisibility: 'org' as const }), {});
assert.deepEqual(ownerWhere({ ...sales, visibleUserIds: null }), {});
});
it('سطح دید تفکیکی هر بخش بر پیش‌فرض اولویت دارد', () => {
const actor = {
...sales,
dataVisibility: 'org' as const,
scopes: { finance: { dataVisibility: 'own' as const, visibleUserIds: ['u1'] } },
};
assert.deepEqual(ownerWhere(actor, 'contacts'), {});
assert.deepEqual(ownerWhere(actor, 'finance'), { ownerId: 'u1' });
});
it('یادداشت شخصی فقط برای نویسنده', () => {
const where = noteAccessWhere({ userId: 'a', role: 'admin' });
assert.deepEqual(where, {
OR: [
{ visibility: { not: 'personal' } },
{ visibility: 'personal', authorId: 'a' },
],
});
});
it('فقط مدیر می‌تواند مالک را عوض کند', () => {
assert.equal(resolveOwnerId(sales, 'u9'), 'u1');
assert.equal(resolveOwnerId({ userId: 'a', role: 'admin' }, ' u9 '), 'u9');
assert.equal(resolveOwnerId({ userId: 'a', role: 'admin' }, ''), 'a');
});
it('پارس تنظیمات دید', () => {
assert.deepEqual(parseVisibilityScopes({ contacts: 'team', finance: 'bad' }), { contacts: 'team' });
assert.deepEqual(parseVisibilityScopes(null), {});
assert.equal(normalizeDataVisibility('weird'), 'own');
});
});
describe('عمق داده وقتی نقش فقط بعضی بخش‌ها را ذخیره کرده', () => {
const legacyOwn = {
role: 'sales',
legacyVisibility: 'own' as const,
legacyScopes: {},
};
it('بخش ننوشتهٔ نقشِ تنظیم‌شده بدون محدودیت است، نه فقط مسئول خودش', () => {
const leads = resolveSectionAccess('leads', {
...legacyOwn,
rolePolicy: { customers: { mode: 'rules', rules: [] } },
override: {},
});
assert.equal(leads.source, 'role');
assert.deepEqual(leads.section, { mode: 'all', rules: [] });
assert.deepEqual(
leadsDeepWhere({ userId: 'u1', role: 'sales', leadsAccess: leads.section, teamPeerIds: null }),
{},
);
});
it('نقش بدون سیاست جدید همچنان دید قدیمی را نگه می‌دارد', () => {
const leads = resolveSectionAccess('leads', {
...legacyOwn,
rolePolicy: {},
override: {},
});
assert.deepEqual(leads.section, { mode: 'rules', rules: [{ owners: ['self'] }] });
assert.deepEqual(
leadsDeepWhere({ userId: 'u1', role: 'sales', leadsAccess: leads.section, teamPeerIds: null }),
{ assigneeId: 'u1' },
);
});
it('override کاربر بر بخش باز نقش اولویت دارد', () => {
const leads = resolveSectionAccess('leads', {
...legacyOwn,
rolePolicy: { customers: { mode: 'all', rules: [] } },
override: { leads: { mode: 'rules', rules: [{ owners: ['self'] }] } },
});
assert.equal(leads.source, 'override');
assert.deepEqual(leads.section, { mode: 'rules', rules: [{ owners: ['self'] }] });
});
it('سفارشی کردن فقط مشتریان، لید را از دید قدیمی جدا نمی‌کند', () => {
const leads = resolveSectionAccess('leads', {
...legacyOwn,
rolePolicy: {},
override: { customers: { mode: 'all', rules: [] } },
});
assert.deepEqual(leads.section, { mode: 'rules', rules: [{ owners: ['self'] }] });
});
});