A project member can be a GUEST. In a private project a guest only sees the tickets they take part in (opened, assigned or followed): every other ticket answers 404, also in my work, realtime changes, blockers and linked tickets, and project-wide views (activity, statistics, dashboard, releases, sprints, epics, trash) answer 403. Guests open tickets without assigning or planning them, and comment, attach, follow and vote on their own; they change nothing else. In a public project they see what anyone does. The web gives them only Tablero, Lista and Miembros and loads none of the project-wide data. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
36 lines
1.3 KiB
TypeScript
36 lines
1.3 KiB
TypeScript
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
|
|
import {
|
|
BusinessRuleError,
|
|
ForbiddenError,
|
|
} from '@task-stream/api/shared/domain';
|
|
import { CommandResult, ack } from './command-result';
|
|
import { VoteIssueCommand } from './vote-issue.command';
|
|
import { WriteAccess } from './write-access';
|
|
|
|
/**
|
|
* Anyone signed in votes on a public project's tickets (that is the point:
|
|
* the people it is for say what they want); on a private one, its members.
|
|
*/
|
|
@CommandHandler(VoteIssueCommand)
|
|
export class VoteIssueCommandHandler
|
|
implements ICommandHandler<VoteIssueCommand>
|
|
{
|
|
constructor(private readonly access: WriteAccess) {}
|
|
|
|
async execute(command: VoteIssueCommand): Promise<CommandResult> {
|
|
const issue = await this.access.issue(command.issueId);
|
|
const project = await this.access.project(issue.projectId);
|
|
if (!project.isPublic && !project.isMember(command.actorId))
|
|
throw new ForbiddenError(
|
|
`You are not a member of project ${project.key}`,
|
|
);
|
|
project.assertNotArchived();
|
|
this.access.assertSees(project, issue, command.actorId);
|
|
if (issue.trashedAt)
|
|
throw new BusinessRuleError(`${issue.key} is in the trash`);
|
|
issue.vote(command.actorId, command.on);
|
|
await issue.commitAndWait();
|
|
return ack(issue);
|
|
}
|
|
}
|