first commit
This commit is contained in:
77
libs/api/tracker/application/src/lib/changes.service.ts
Normal file
77
libs/api/tracker/application/src/lib/changes.service.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { QueryBus } from '@nestjs/cqrs';
|
||||
import { NotFoundError } from '@task-stream/api/shared/domain';
|
||||
import { ActivityReadModel } from '@task-stream/api/tracker/domain';
|
||||
import {
|
||||
ChangeFeed,
|
||||
CommentChange,
|
||||
IssueChange,
|
||||
ProjectChange,
|
||||
ReleaseChange,
|
||||
} from './ports/change-feed';
|
||||
import { CanViewProjectQuery } from './queries/can-view-project.query';
|
||||
import { GetIssueQuery } from './queries/get-issue.query';
|
||||
|
||||
/** Realtime subscriptions, authorised at subscribe time. */
|
||||
@Injectable()
|
||||
export class ChangesService {
|
||||
constructor(
|
||||
private readonly queryBus: QueryBus,
|
||||
private readonly changeFeed: ChangeFeed,
|
||||
) {}
|
||||
|
||||
async watchIssues(
|
||||
viewerId: string,
|
||||
projectId: string,
|
||||
): Promise<AsyncIterableIterator<IssueChange>> {
|
||||
await this.assertCanView(viewerId, projectId);
|
||||
return this.changeFeed.issues(projectId);
|
||||
}
|
||||
|
||||
async watchComments(
|
||||
viewerId: string,
|
||||
issueId: string,
|
||||
): Promise<AsyncIterableIterator<CommentChange>> {
|
||||
await this.queryBus.execute(new GetIssueQuery(viewerId, issueId)); // access check
|
||||
return this.changeFeed.comments(issueId);
|
||||
}
|
||||
|
||||
async watchActivity(
|
||||
viewerId: string,
|
||||
projectId: string,
|
||||
): Promise<AsyncIterableIterator<ActivityReadModel>> {
|
||||
await this.assertCanView(viewerId, projectId);
|
||||
return this.changeFeed.activity(projectId);
|
||||
}
|
||||
|
||||
async watchReleases(
|
||||
viewerId: string,
|
||||
projectId: string,
|
||||
): Promise<AsyncIterableIterator<ReleaseChange>> {
|
||||
await this.assertCanView(viewerId, projectId);
|
||||
return this.changeFeed.releases(projectId);
|
||||
}
|
||||
|
||||
async watchProject(
|
||||
viewerId: string,
|
||||
projectId: string,
|
||||
): Promise<AsyncIterableIterator<ProjectChange>> {
|
||||
await this.assertCanView(viewerId, projectId);
|
||||
return this.changeFeed.project(projectId);
|
||||
}
|
||||
|
||||
/** Projects the viewer is added to or removed from. */
|
||||
watchMyProjects(viewerId: string): AsyncIterableIterator<ProjectChange> {
|
||||
return this.changeFeed.userProjects(viewerId);
|
||||
}
|
||||
|
||||
private async assertCanView(
|
||||
viewerId: string,
|
||||
projectId: string,
|
||||
): Promise<void> {
|
||||
const allowed = await this.queryBus.execute(
|
||||
new CanViewProjectQuery(viewerId, projectId),
|
||||
);
|
||||
if (!allowed) throw new NotFoundError('Project', projectId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user