feat(activities): let a group show and limit its members

Empty membership stays open to the whole workspace; picking people restricts who can see that activity group.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-28 20:24:40 +03:30
co-authored by Cursor
parent 2cc2d358e4
commit 63a1803adc
8 changed files with 272 additions and 22 deletions
@@ -277,6 +277,7 @@ export class ActivitiesService {
const boardCtx = await this.stages.boardContext(organizationId);
if (facets?.boardId) {
const boardId = await this.stages.resolveBoardId(organizationId, facets.boardId);
await this.stages.assertCanAccessBoard(organizationId, boardId, actor);
(where.AND as Prisma.ActivityWhereInput[]).push(
this.stages.boardWhere(boardId, boardCtx.defaultBoardId),
);
@@ -320,6 +321,7 @@ export class ActivitiesService {
facets?: ListFacets,
): Promise<ActivityStageCountsDto> {
const boardId = await this.stages.resolveBoardId(organizationId, facets?.boardId);
await this.stages.assertCanAccessBoard(organizationId, boardId, actor);
const defaultBoard = await this.stages.ensureDefaultBoard(organizationId);
const rows = await this.stages.rows(organizationId, boardId);
const defaults = this.stages.defaultsOf(rows);
@@ -451,6 +453,7 @@ export class ActivitiesService {
: requestedBoardId
? await this.stages.resolveBoardId(organizationId, requestedBoardId)
: null;
if (boardId) await this.stages.assertCanAccessBoard(organizationId, boardId, linkActor);
const resolved = await this.types.resolve(organizationId, {
typeDefId: dto.typeDefId,
type: dto.type,
@@ -571,6 +574,7 @@ export class ActivitiesService {
select: { boardId: true },
});
const defaultBoard = await this.stages.ensureDefaultBoard(organizationId);
await this.stages.assertCanAccessBoard(organizationId, nextBoardId, actor);
if (nextBoardId !== (current?.boardId ?? defaultBoard.id)) {
// ستون قبلی مال گروه دیگر است؛ فعالیت به ستون اولِ هم‌وضعیت گروه جدید می‌رود
data.boardId = nextBoardId;