feat(acl): deep data access by section for roles and users
Role default + user override with OR rules; covers customers, leads, sales, activities, notes, routines, projects, and tickets.
This commit is contained in:
@@ -4,6 +4,10 @@ import { PassportStrategy } from '@nestjs/passport';
|
||||
import { ExtractJwt, Strategy } from 'passport-jwt';
|
||||
import type { DataVisibility } from '@mento/shared';
|
||||
import { BillingService } from '../billing/billing.service';
|
||||
import {
|
||||
resolveAllSectionAccess,
|
||||
sectionNeedsTeamPeers,
|
||||
} from '../common/data-access';
|
||||
import {
|
||||
type Actor,
|
||||
normalizeDataVisibility,
|
||||
@@ -86,8 +90,10 @@ export class JwtStrategy extends PassportStrategy(Strategy) {
|
||||
role: true,
|
||||
dataVisibility: true,
|
||||
dataVisibilityScopes: true,
|
||||
dataAccessOverride: true,
|
||||
priorArchiveEnabled: true,
|
||||
priorArchiveLens: true,
|
||||
orgRole: { select: { dataAccessPolicy: true } },
|
||||
organization: { select: { enabledModules: true, priorArchiveEnabledAt: true } },
|
||||
},
|
||||
});
|
||||
@@ -118,6 +124,27 @@ export class JwtStrategy extends PassportStrategy(Strategy) {
|
||||
}
|
||||
}
|
||||
|
||||
const deepAccess = resolveAllSectionAccess({
|
||||
role: membership.role,
|
||||
rolePolicy: membership.orgRole?.dataAccessPolicy,
|
||||
override: membership.dataAccessOverride,
|
||||
legacyVisibility: dataVisibility,
|
||||
legacyScopes: scopeLevels,
|
||||
});
|
||||
const needsTeamPeers =
|
||||
!elevatedRole &&
|
||||
(sectionNeedsTeamPeers(deepAccess.customers) ||
|
||||
sectionNeedsTeamPeers(deepAccess.leads) ||
|
||||
sectionNeedsTeamPeers(deepAccess.sales) ||
|
||||
sectionNeedsTeamPeers(deepAccess.activities) ||
|
||||
sectionNeedsTeamPeers(deepAccess.notes) ||
|
||||
sectionNeedsTeamPeers(deepAccess.routines) ||
|
||||
sectionNeedsTeamPeers(deepAccess.projects) ||
|
||||
sectionNeedsTeamPeers(deepAccess.tickets));
|
||||
if (needsTeamPeers) {
|
||||
teamIds ??= await this.teamPeerIds(membership.organizationId, user.id);
|
||||
}
|
||||
|
||||
const modules = this.billing.normalizeModules(membership.organization.enabledModules);
|
||||
const priorGranted =
|
||||
modules.includes('prior_data_archive') && membership.priorArchiveEnabled;
|
||||
@@ -130,6 +157,15 @@ export class JwtStrategy extends PassportStrategy(Strategy) {
|
||||
dataVisibility,
|
||||
visibleUserIds,
|
||||
scopes,
|
||||
customersAccess: deepAccess.customers,
|
||||
leadsAccess: deepAccess.leads,
|
||||
salesAccess: deepAccess.sales,
|
||||
activitiesAccess: deepAccess.activities,
|
||||
notesAccess: deepAccess.notes,
|
||||
routinesAccess: deepAccess.routines,
|
||||
projectsAccess: deepAccess.projects,
|
||||
ticketsAccess: deepAccess.tickets,
|
||||
teamPeerIds: teamIds ?? (elevatedRole ? null : [user.id]),
|
||||
priorLens: priorGranted ? priorLens : 'off',
|
||||
priorCutoff:
|
||||
priorGranted && membership.organization.priorArchiveEnabledAt
|
||||
|
||||
Reference in New Issue
Block a user