Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project member changeset aware #2504

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Type } from 'class-transformer';
import { ValidateNested } from 'class-validator';
import { ID, IdField } from '../../../../common';
import { Role } from '../../../authorization';
import { ChangesetIdField } from '../../../changeset';
import { ProjectMember } from './project-member.dto';

@InputType()
Expand All @@ -23,6 +24,9 @@ export class CreateProjectMember {

@InputType()
export abstract class CreateProjectMemberInput {
@ChangesetIdField()
readonly changeset?: ID;

@Field()
@Type(() => CreateProjectMember)
@ValidateNested()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Type } from 'class-transformer';
import { ValidateNested } from 'class-validator';
import { ID, IdField } from '../../../../common';
import { Role } from '../../../authorization';
import { ChangesetIdField } from '../../../changeset';
import { ProjectMember } from './project-member.dto';

@InputType()
Expand All @@ -16,6 +17,9 @@ export abstract class UpdateProjectMember {

@InputType()
export abstract class UpdateProjectMemberInput {
@ChangesetIdField()
readonly changeset?: ID;

@Field()
@Type(() => UpdateProjectMemberInput)
@ValidateNested()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
import { Node, node, Query, relation } from 'cypher-query-builder';
import { DateTime } from 'luxon';
import { CreateProjectMember, ProjectMember, ProjectMemberListInput } from '.';
import { ID, Session, UnsecuredDto } from '../../../common';
import { ID, ObjectView, Session, UnsecuredDto } from '../../../common';
import { DatabaseService, DtoRepository } from '../../../core';
import {
ACTIVE,
Expand All @@ -12,13 +12,14 @@ import {
property,
requestingUser,
sorting,
whereNotDeletedInChangeset,
} from '../../../core/database/query';
import { UserRepository } from '../../user/user.repository';

@Injectable()
export class ProjectMemberRepository extends DtoRepository<
typeof ProjectMember,
[session: Session]
[session: Session, view?: ObjectView]
>(ProjectMember) {
constructor(private readonly users: UserRepository, db: DatabaseService) {
super(db);
Expand All @@ -45,7 +46,8 @@ export class ProjectMemberRepository extends DtoRepository<
{ userId, projectId, ...input }: CreateProjectMember,
id: ID,
session: Session,
createdAt: DateTime
createdAt: DateTime,
changeset?: ID
) {
const createProjectMember = this.db
.query()
Expand Down Expand Up @@ -84,6 +86,20 @@ export class ProjectMemberRepository extends DtoRepository<
}),
node('user'),
])
.apply((q) =>
changeset
? q
.match([node('changeset', 'Changeset', { id: changeset })])
.create([
node('changeset'),
relation('out', '', 'changeset', {
active: true,
createdAt: DateTime.local(),
}),
node('projectMember'),
])
: q
)
.return<{ id: ID }>('projectMember.id as id')
.first();
}
Expand All @@ -110,7 +126,11 @@ export class ProjectMemberRepository extends DtoRepository<
);
}

async list({ filter, ...input }: ProjectMemberListInput, session: Session) {
async list(
{ filter, ...input }: ProjectMemberListInput,
session: Session,
changeset?: ID
) {
const result = await this.db
.query()
.match([
Expand All @@ -124,6 +144,7 @@ export class ProjectMemberRepository extends DtoRepository<
: []),
node('node', 'ProjectMember'),
])
.apply(whereNotDeletedInChangeset(changeset))
.apply((q) =>
filter.roles
? q
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import {
ListArg,
LoggedInSession,
Session,
viewOfChangeset,
} from '../../../common';
import { Loader, LoaderOf } from '../../../core';
import { ChangesetIds } from '../../changeset/dto';
import { ProjectMemberLoader, ProjectMemberService } from '../project-member';
import {
CreateProjectMemberInput,
Expand All @@ -29,9 +31,9 @@ export class ProjectMemberResolver {
})
async createProjectMember(
@LoggedInSession() session: Session,
@Args('input') { projectMember: input }: CreateProjectMemberInput
@Args('input') { projectMember: input, changeset }: CreateProjectMemberInput
): Promise<CreateProjectMemberOutput> {
const projectMember = await this.service.create(input, session);
const projectMember = await this.service.create(input, session, changeset);
return { projectMember };
}

Expand Down Expand Up @@ -63,9 +65,13 @@ export class ProjectMemberResolver {
})
async updateProjectMember(
@LoggedInSession() session: Session,
@Args('input') { projectMember: input }: UpdateProjectMemberInput
@Args('input') { projectMember: input, changeset }: UpdateProjectMemberInput
): Promise<UpdateProjectMemberOutput> {
const projectMember = await this.service.update(input, session);
const projectMember = await this.service.update(
input,
session,
viewOfChangeset(changeset)
);
return { projectMember };
}

Expand All @@ -74,9 +80,9 @@ export class ProjectMemberResolver {
})
async deleteProjectMember(
@LoggedInSession() session: Session,
@IdArg() id: ID
@Args() { id, changeset }: ChangesetIds
): Promise<DeleteProjectMemberOutput> {
await this.service.delete(id, session);
await this.service.delete(id, session, changeset);
return { success: true };
}
}
27 changes: 16 additions & 11 deletions src/components/project/project-member/project-member.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
Session,
UnauthorizedException,
UnsecuredDto,
viewOfChangeset,
} from '../../../common';
import {
ConfigService,
Expand Down Expand Up @@ -86,7 +87,8 @@ export class ProjectMemberService {

async create(
{ userId, projectId, ...input }: CreateProjectMember,
session: Session
session: Session,
changeset?: ID
): Promise<ProjectMember> {
await this.authorizationService.checkPower(
Powers.CreateProjectMember,
Expand All @@ -106,13 +108,14 @@ export class ProjectMemberService {
{ userId, projectId, ...input },
id,
session,
createdAt
createdAt,
changeset
);
if (!memberQuery) {
throw new ServerException('Failed to create project member');
}

return await this.readOne(id, session);
return await this.readOne(id, session, viewOfChangeset(changeset));
} catch (exception) {
throw new ServerException('Could not create project member', exception);
}
Expand All @@ -122,7 +125,7 @@ export class ProjectMemberService {
async readOne(
id: ID,
session: Session,
_view?: ObjectView
view?: ObjectView
): Promise<ProjectMember> {
this.logger.debug(`read one`, {
id,
Expand All @@ -135,7 +138,7 @@ export class ProjectMemberService {
);
}

const dto = await this.repo.readOne(id, session);
const dto = await this.repo.readOne(id, session, view);
return await this.secure(dto, session);
}

Expand Down Expand Up @@ -173,7 +176,8 @@ export class ProjectMemberService {

async update(
input: UpdateProjectMember,
session: Session
session: Session,
view?: ObjectView
): Promise<ProjectMember> {
const object = await this.readOne(input.id, session);

Expand All @@ -193,7 +197,7 @@ export class ProjectMemberService {
object,
changes
);
await this.repo.updateProperties(object, changes);
await this.repo.updateProperties(object, changes, view?.changeset);
return await this.readOne(input.id, session);
}

Expand All @@ -216,7 +220,7 @@ export class ProjectMemberService {
}
}

async delete(id: ID, session: Session): Promise<void> {
async delete(id: ID, session: Session, changeset?: ID): Promise<void> {
const object = await this.readOne(id, session);

if (!object) {
Expand All @@ -227,7 +231,7 @@ export class ProjectMemberService {
}

try {
await this.repo.deleteNode(object);
await this.repo.deleteNode(object, changeset);
} catch (exception) {
this.logger.warning('Failed to delete project member', {
exception,
Expand All @@ -239,12 +243,13 @@ export class ProjectMemberService {

async list(
input: ProjectMemberListInput,
session: Session
session: Session,
changeset?: ID
): Promise<ProjectMemberListOutput> {
// Since there is no case at the present where there is global versus scoped canList,
// not doing the whole limitedScope map thing for now.
if (await this.authorizationService.canList(ProjectMember, session)) {
const results = await this.repo.list(input, session);
const results = await this.repo.list(input, session, changeset);
return await mapListResults(results, (dto) => this.secure(dto, session));
} else {
return SecuredList.Redacted;
Expand Down