feat(roles): let each section decide who may assign work to others
Section access now only creates a record for yourself. Assigning it to a colleague requires a separate permission on that section. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -20,10 +20,10 @@ import {
|
||||
import { customersCompanyWhere } from '../common/data-access';
|
||||
import {
|
||||
type Actor,
|
||||
canReassignOwner,
|
||||
elevated,
|
||||
resolveOwnerId,
|
||||
} from '../common/record-scope';
|
||||
import { actorCanAssignToOthers, assertAssigneeSet } from '../common/assign-access';
|
||||
import { normalizeTags } from '../common/tags';
|
||||
import { normalizePersonImportSource } from './person-source';
|
||||
import { buildSearchWhere, ci, splitCsv } from '../common/search';
|
||||
@@ -201,7 +201,11 @@ export class CompaniesService {
|
||||
notes: emptyToNull(dto.notes),
|
||||
registeredAt: parseDateOrNull(dto.registeredAt),
|
||||
tags: normalizeTags(dto.tags),
|
||||
ownerId: resolveOwnerId(actor, dto.ownerId),
|
||||
ownerId: resolveOwnerId(
|
||||
actor,
|
||||
dto.ownerId,
|
||||
await actorCanAssignToOthers(this.prisma, actor, 'customers'),
|
||||
),
|
||||
customFields: toJsonCustomFields(dto.customFields),
|
||||
};
|
||||
await this.assertNoDuplicate(actor.organizationId, data);
|
||||
@@ -266,8 +270,14 @@ export class CompaniesService {
|
||||
if ('customFields' in dto) {
|
||||
data.customFields = toJsonCustomFields(dto.customFields);
|
||||
}
|
||||
if (dto.ownerId !== undefined && canReassignOwner(actor.role)) {
|
||||
data.ownerId = resolveOwnerId(actor, dto.ownerId);
|
||||
if (dto.ownerId !== undefined) {
|
||||
const current = await this.prisma.company.findFirst({
|
||||
where: { id, organizationId: actor.organizationId },
|
||||
select: { ownerId: true },
|
||||
});
|
||||
const nextOwner = emptyToNull(dto.ownerId ?? null);
|
||||
await assertAssigneeSet(this.prisma, actor, 'customers', [nextOwner], [current?.ownerId]);
|
||||
data.ownerId = nextOwner ?? actor.userId;
|
||||
}
|
||||
|
||||
await this.assertNoDuplicate(actor.organizationId, data, id);
|
||||
|
||||
@@ -38,9 +38,9 @@ import {
|
||||
import { customersPersonWhere } from '../common/data-access';
|
||||
import {
|
||||
type Actor,
|
||||
canReassignOwner,
|
||||
resolveOwnerId,
|
||||
} from '../common/record-scope';
|
||||
import { actorCanAssignToOthers, assertAssigneeSet } from '../common/assign-access';
|
||||
import { LoyaltyService } from '../loyalty/loyalty.service';
|
||||
import { AutomationsService } from '../automations/automations.service';
|
||||
import { MessageAutomationsService } from '../message-automations/message-automations.service';
|
||||
@@ -453,7 +453,11 @@ export class PeopleService implements OnModuleInit {
|
||||
mood: dto.mood ?? 'newcomer',
|
||||
tags: normalizeTags(dto.tags),
|
||||
companyId,
|
||||
ownerId: resolveOwnerId(actor, dto.ownerId),
|
||||
ownerId: resolveOwnerId(
|
||||
actor,
|
||||
dto.ownerId,
|
||||
await actorCanAssignToOthers(this.prisma, actor, 'customers'),
|
||||
),
|
||||
customFields: toJsonCustomFields(dto.customFields),
|
||||
...(registeredAt && !Number.isNaN(registeredAt.getTime())
|
||||
? { createdAt: registeredAt }
|
||||
@@ -574,8 +578,14 @@ export class PeopleService implements OnModuleInit {
|
||||
}
|
||||
data.companyId = nextCompanyId;
|
||||
}
|
||||
if (dto.ownerId !== undefined && canReassignOwner(actor.role)) {
|
||||
data.ownerId = resolveOwnerId(actor, dto.ownerId);
|
||||
if (dto.ownerId !== undefined) {
|
||||
const current = await this.prisma.person.findFirst({
|
||||
where: { id, organizationId: actor.organizationId },
|
||||
select: { ownerId: true },
|
||||
});
|
||||
const nextOwner = emptyToNull(dto.ownerId ?? null);
|
||||
await assertAssigneeSet(this.prisma, actor, 'customers', [nextOwner], [current?.ownerId]);
|
||||
data.ownerId = nextOwner ?? actor.userId;
|
||||
}
|
||||
|
||||
await this.assertNoDuplicate(actor.organizationId, data, id);
|
||||
|
||||
Reference in New Issue
Block a user