Skip to content

Commit

Permalink
review feedback improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
martin-trajanovski committed Dec 17, 2024
1 parent a83609d commit c0b6f0f
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 175 deletions.
168 changes: 168 additions & 0 deletions src/datasets/datasets-access.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import { Inject, Injectable, Scope } from "@nestjs/common";
import { REQUEST } from "@nestjs/core";
import { Request } from "express";
import { PipelineStage } from "mongoose";
import { JWTUser } from "src/auth/interfaces/jwt-user.interface";
import { Action } from "src/casl/action.enum";
import { DatasetLookupKeysEnum } from "./types/dataset-lookup";
import { CaslAbilityFactory } from "src/casl/casl-ability.factory";
import { ProposalClass } from "src/proposals/schemas/proposal.schema";
import { Instrument } from "src/instruments/schemas/instrument.schema";
import { OrigDatablock } from "src/origdatablocks/schemas/origdatablock.schema";

@Injectable({ scope: Scope.REQUEST })
export class DatasetsAccessService {
constructor(
private caslAbilityFactory: CaslAbilityFactory,
@Inject(REQUEST) private request: Request,
) {}

getRelationViewAccess(field: DatasetLookupKeysEnum, user: JWTUser) {
switch (field) {
case DatasetLookupKeysEnum.proposals: {
const ability = this.caslAbilityFactory.proposalsInstanceAccess(user);
const canViewAny = ability.can(Action.ProposalsReadAny, ProposalClass);
const canViewAccess = ability.can(
Action.ProposalsReadManyAccess,
ProposalClass,
);
const canViewOwner = ability.can(
Action.ProposalsReadManyOwner,
ProposalClass,
);
const canViewPublic = ability.can(
Action.ProposalsReadManyPublic,
ProposalClass,
);

return { canViewAny, canViewOwner, canViewAccess, canViewPublic };
}
case DatasetLookupKeysEnum.origdatablocks: {
const ability =
this.caslAbilityFactory.origDatablockInstanceAccess(user);
const canViewAny = ability.can(
Action.OrigdatablockReadAny,
OrigDatablock,
);
const canViewAccess = ability.can(
Action.OrigdatablockReadManyAccess,
ProposalClass,
);
const canViewOwner = ability.can(
Action.OrigdatablockReadManyOwner,
ProposalClass,
);
const canViewPublic = ability.can(
Action.OrigdatablockReadManyPublic,
ProposalClass,
);

return { canViewAny, canViewOwner, canViewAccess, canViewPublic };
}
case DatasetLookupKeysEnum.datablocks: {
const ability = this.caslAbilityFactory.datasetInstanceAccess(user);
const canViewAny = ability.can(
Action.DatasetDatablockReadAny,
OrigDatablock,
);
const canViewAccess = ability.can(
Action.DatasetDatablockReadAccess,
ProposalClass,
);
const canViewOwner = ability.can(
Action.DatasetDatablockReadOwner,
ProposalClass,
);
const canViewPublic = ability.can(
Action.DatasetDatablockReadPublic,
ProposalClass,
);

return { canViewAny, canViewOwner, canViewAccess, canViewPublic };
}
case DatasetLookupKeysEnum.samples: {
const ability = this.caslAbilityFactory.samplesInstanceAccess(user);
const canViewAny = ability.can(Action.SampleReadAny, OrigDatablock);
const canViewAccess = ability.can(
Action.SampleReadManyAccess,
ProposalClass,
);
const canViewOwner = ability.can(
Action.SampleReadManyOwner,
ProposalClass,
);
const canViewPublic = ability.can(
Action.SampleReadManyPublic,
ProposalClass,
);

return { canViewAny, canViewOwner, canViewAccess, canViewPublic };
}
case DatasetLookupKeysEnum.instruments: {
// TODO: Fix this if the instrument access change
const ability = this.caslAbilityFactory.instrumentEndpointAccess(user);
const canViewAny = ability.can(Action.InstrumentRead, Instrument);

return {
canViewAny,
canViewOwner: false,
canViewAccess: false,
canViewPublic: true,
};
}
default:
return {
canViewAny: false,
canViewOwner: false,
canViewAccess: false,
canViewPublic: true,
};
}
}

addRelationFieldAccess(fieldValue: PipelineStage.Lookup) {
const currentUser = this.request.user as JWTUser;

const access = this.getRelationViewAccess(
fieldValue.$lookup.as as DatasetLookupKeysEnum,
currentUser,
);

if (access) {
const { canViewAny, canViewAccess, canViewOwner, canViewPublic } = access;

if (!canViewAny) {
if (canViewAccess) {
fieldValue.$lookup.pipeline = [
{
$match: {
$or: [
{ ownerGroup: { $in: currentUser.currentGroups } },
{ accessGroups: { $in: currentUser.currentGroups } },
{ sharedWith: { $in: [currentUser.email] } },
{ isPublished: true },
],
},
},
];
} else if (canViewOwner) {
fieldValue.$lookup.pipeline = [
{
$match: {
ownerGroup: { $in: currentUser.currentGroups },
},
},
];
} else if (canViewPublic) {
fieldValue.$lookup.pipeline = [
{
$match: {
isPublished: true,
},
},
];
}
}
}
}
}
3 changes: 2 additions & 1 deletion src/datasets/datasets.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { PoliciesService } from "src/policies/policies.service";
import { PoliciesModule } from "src/policies/policies.module";
import { ElasticSearchModule } from "src/elastic-search/elastic-search.module";
import { DatasetsV4Controller } from "./datasets.v4.controller";
import { DatasetsAccessService } from "./datasets-access.service";

@Module({
imports: [
Expand Down Expand Up @@ -64,6 +65,6 @@ import { DatasetsV4Controller } from "./datasets.v4.controller";
],
exports: [DatasetsService],
controllers: [DatasetsController, DatasetsV4Controller],
providers: [DatasetsService, CaslAbilityFactory],
providers: [DatasetsService, CaslAbilityFactory, DatasetsAccessService],
})
export class DatasetsModule {}
2 changes: 2 additions & 0 deletions src/datasets/datasets.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ElasticSearchService } from "src/elastic-search/elastic-search.service"
import { DatasetsService } from "./datasets.service";
import { DatasetClass } from "./schemas/dataset.schema";
import { CaslAbilityFactory } from "src/casl/casl-ability.factory";
import { DatasetsAccessService } from "./datasets-access.service";

class InitialDatasetsServiceMock {}

Expand Down Expand Up @@ -102,6 +103,7 @@ describe("DatasetsService", () => {
},
},
DatasetsService,
DatasetsAccessService,
{
provide: InitialDatasetsService,
useClass: InitialDatasetsServiceMock,
Expand Down
Loading

0 comments on commit c0b6f0f

Please sign in to comment.