Skip to content

Commit

Permalink
merge release-jobs
Browse files Browse the repository at this point in the history
  • Loading branch information
despadam committed Jul 31, 2024
2 parents 81dae5e + 4e67d3a commit fb59df0
Show file tree
Hide file tree
Showing 38 changed files with 4,559 additions and 1,160 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
pull_request:
branches:
- master
- release-*

jobs:
install-and-cache:
Expand Down Expand Up @@ -152,6 +153,9 @@ jobs:
CREATE_DATASET_WITH_PID_GROUPS: "group2"
CREATE_DATASET_PRIVILEGED_GROUPS: "datasetIngestor,group3"
ACCESS_GROUPS_STATIC_VALUES: "ess"
CREATE_JOB_GROUPS: group1,group2
UPDATE_JOB_GROUPS: group1
DELETE_JOB_GROUPS: "archivemanager"
PROPOSAL_GROUPS: "proposalingestor"
SAMPLE_PRIVILEGED_GROUPS: "sampleingestor"
SAMPLE_GROUPS: "group1"
Expand All @@ -168,6 +172,7 @@ jobs:
STACK_VERSION: 8.8.2
CLUSTER_NAME: es-cluster
MEM_LIMIT: 4G
JOB_CONFIGURATION_FILE: test/config/jobconfig.json

# Start mongo container and app before running api tests
run: |
Expand Down
72 changes: 53 additions & 19 deletions src/casl/casl-ability.factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ import { UserSettings } from "src/users/schemas/user-settings.schema";
import { User } from "src/users/schemas/user.schema";
import { AuthOp } from "./authop.enum";
import configuration from "src/config/configuration";
import { CreateJobAuth, StatusUpdateJobAuth } from "src/jobs/types/jobs-auth.enum";
import {
CreateJobAuth,
StatusUpdateJobAuth,
} from "src/jobs/types/jobs-auth.enum";

type Subjects =
| string
Expand Down Expand Up @@ -818,36 +821,53 @@ export class CaslAbilityFactory {
["configuration.create.auth" as string]: CreateJobAuth.DatasetPublic,
datasetsValidation: true,
});
can(AuthOp.JobStatusUpdateConfiguration, JobClass, {
["configuration.statusUpdate.auth" as string]: StatusUpdateJobAuth.All,
ownerGroup: undefined,
});
} else {
/**
* authenticated users
*/

// check if this user is part of the admin group
if (
user.currentGroups.some((g) => configuration().adminGroups.includes(g))
) {
/**
* authenticated users belonging to any of the group listed in ADMIN_GROUPS
*/

// -------------------------------------
// endpoint authorization
can(AuthOp.JobRead, JobClass);
can(AuthOp.JobCreate, JobClass);
can(AuthOp.JobStatusUpdate, JobClass);
cannot(AuthOp.JobDelete, JobClass);

// -------------------------------------
// data instance authorization
can(AuthOp.JobReadAny, JobClass);
can(AuthOp.JobCreateAny, JobClass);
can(AuthOp.JobStatusUpdateAny, JobClass);
} else if (
user.currentGroups.some((g) =>
configuration().deleteJobGroups.includes(g),
)
) {
/**
* authenticated users belonging to any of the group listed in DELETE_JOB_GROUPS
*/
// -------------------------------------
// endpoint authorization
can(AuthOp.JobDelete, JobClass);

// -------------------------------------
// data instance authorization
can(AuthOp.JobDeleteAny, JobClass);
} else {
const jobUserAuthorizationValues = [
...user.currentGroups.map((g) => "@" + g),
user.username,
];

if (
user.currentGroups.some((g) =>
configuration().createJobGroups.includes(g),
Expand Down Expand Up @@ -880,7 +900,7 @@ export class CaslAbilityFactory {
];
const jobCreateInstanceAuthorizationValues = [
...Object.values(CreateJobAuth).filter(
(v) => ~String(v).includes("#dataset"),
(v) => !String(v).includes("#dataset"),
),
...jobUserAuthorizationValues,
];
Expand All @@ -889,13 +909,17 @@ export class CaslAbilityFactory {
String(v).includes("#dataset"),
),
];

// -------------------------------------
// endpoint authorization
can(AuthOp.JobRead, JobClass);

if (
configuration().jobConfiguration.some(
(j) => j.create.auth! in jobCreateEndPointAuthorizationValues,
(j) =>
j.create.auth &&
jobCreateEndPointAuthorizationValues.includes(
j.create.auth as string,
),
)
) {
can(AuthOp.JobCreate, JobClass);
Expand All @@ -907,6 +931,7 @@ export class CaslAbilityFactory {
ownerGroup: { $in: user.currentGroups },
ownerUser: user.username,
});

can(AuthOp.JobCreateConfiguration, JobClass, {
["configuration.create.auth" as string]: {
$in: jobCreateInstanceAuthorizationValues,
Expand All @@ -919,6 +944,16 @@ export class CaslAbilityFactory {
datasetsValidation: true,
});
}
const jobUpdateEndPointAuthorizationValues = [
...Object.values(StatusUpdateJobAuth),
...jobUserAuthorizationValues,
];
const jobUpdateInstanceAuthorizationValues = [
...Object.values(StatusUpdateJobAuth).filter(
(v) => !String(v).includes("#job"),
),
...jobUserAuthorizationValues,
];

if (
user.currentGroups.some((g) =>
Expand All @@ -931,29 +966,27 @@ export class CaslAbilityFactory {

// -------------------------------------
// data instance authorization
can(AuthOp.JobStatusUpdateConfiguration, JobClass, {
["configuration.statusUpdate.auth" as string]: {
$in: jobUpdateInstanceAuthorizationValues,
},
});
can(AuthOp.JobStatusUpdateOwner, JobClass, {
ownerUser: user.username,
});
can(AuthOp.JobStatusUpdateOwner, JobClass, {
ownerGroup: { $in: user.currentGroups },
});
} else {
const jobUpdateEndPointAuthorizationValues = [
...Object.values(StatusUpdateJobAuth),
...jobUserAuthorizationValues,
];
const jobUpdateInstanceAuthorizationValues = [
...Object.values(StatusUpdateJobAuth).filter(
(v) => ~String(v).includes("#job"),
),
...jobUserAuthorizationValues,
];

// -------------------------------------
// endpoint authorization
if (
configuration().jobConfiguration.some(
(j) => j.statusUpdate.auth! in jobUpdateEndPointAuthorizationValues,
(j) =>
j.statusUpdate.auth &&
jobUpdateEndPointAuthorizationValues.includes(
j.statusUpdate.auth as string,
),
)
) {
can(AuthOp.JobStatusUpdate, JobClass);
Expand All @@ -975,6 +1008,7 @@ export class CaslAbilityFactory {
ownerGroup: { $in: user.currentGroups },
});
}
cannot(AuthOp.JobDelete, JobClass);
}
}

Expand Down
6 changes: 4 additions & 2 deletions src/config/configuration.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Logger } from "@nestjs/common";
import {
loadJobConfig,
registerCreateAction,
Expand Down Expand Up @@ -31,6 +30,7 @@ const configuration = () => {

const createJobGroups = process.env.CREATE_JOB_GROUPS || ("" as string);
const statusUpdateJobGroups = process.env.UPDATE_JOB_GROUPS || ("" as string);
const deleteJobGroups = process.env.DELETE_JOB_GROUPS || ("" as string);

const proposalGroups = process.env.PROPOSAL_GROUPS || ("" as string);
const sampleGroups = process.env.SAMPLE_GROUPS || ("#all" as string);
Expand All @@ -44,7 +44,8 @@ const configuration = () => {
process.env.OIDC_USERINFO_MAPPING_FIELD_USERNAME || ("" as string);

const jobConfigurationFile =
process.env.JOB_CONFIGURATION_FILE || ("src/jobs/config/jobConfig.example.json" as string);
process.env.JOB_CONFIGURATION_FILE ||
("src/jobs/config/jobConfig.example.json" as string);

const defaultLogger = {
type: "DefaultLogger",
Expand Down Expand Up @@ -109,6 +110,7 @@ const configuration = () => {
datasetCreationValidationRegex: datasetCreationValidationRegex,
createJobGroups: createJobGroups,
statusUpdateJobGroups: statusUpdateJobGroups,
deleteJobGroups: deleteJobGroups,
logoutURL: process.env.LOGOUT_URL ?? "", // Example: http://localhost:3000/
accessGroupsGraphQlConfig: {
enabled: boolean(process.env?.ACCESS_GROUPS_GRAPHQL_ENABLED || false),
Expand Down
9 changes: 5 additions & 4 deletions src/elastic-search/elastic-search.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ export class ElasticSearchService implements OnModuleInit {

const totalCount = body.hits.hits.length || 0;

const data = body.hits.hits.map((item) => item._id);
const data = body.hits.hits.map((item) => item._id || "");
return {
totalCount,
data,
Expand Down Expand Up @@ -361,13 +361,14 @@ export class ElasticSearchService implements OnModuleInit {
}
async updateInsertDocument(data: DatasetDocument) {
//NOTE: Replace all keys with lower case, also replace spaces and dot with underscore
delete data._id;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { _id: unused, ...restData } = data; // type-safe delete _id
const transformedScientificMetadata = transformKeysInObject(
data.scientificMetadata as Record<string, unknown>,
restData.scientificMetadata as Record<string, unknown>,
);

const transformedData = {
...data,
...restData,
scientificMetadata: transformedScientificMetadata,
};
try {
Expand Down
14 changes: 12 additions & 2 deletions src/jobs/actions/emailaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ import { JobClass } from "../schemas/job.schema";
import { createTransport, Transporter } from "nodemailer";
import { compile, TemplateDelegate } from "handlebars";

type MailOptions = {
to: string;
from: string;
subject: string;
text?: string;
};

/**
* Send an email following a job
*/
Expand All @@ -25,7 +32,7 @@ export class EmailJobAction<T> implements JobAction<T> {
return EmailJobAction.actionType;
}

constructor(data: Record<string, any>) {
constructor(data: Record<string, unknown>) {
Logger.log(
"Initializing EmailJobAction. Params: " + JSON.stringify(data),
"EmailJobAction",
Expand All @@ -40,6 +47,9 @@ export class EmailJobAction<T> implements JobAction<T> {
if (!data["from"]) {
throw new NotFoundException("Param 'from' is undefined");
}
if (typeof data["from"] !== "string") {
throw new TypeError("from should be a string");
}
if (!data["subject"]) {
throw new NotFoundException("Param 'subject' is undefined");
}
Expand Down Expand Up @@ -69,7 +79,7 @@ export class EmailJobAction<T> implements JobAction<T> {
);

// Fill templates
const mail: any = {
const mail: MailOptions = {
to: this.toTemplate(job),
from: this.from,
subject: this.subjectTemplate(job),
Expand Down
2 changes: 1 addition & 1 deletion src/jobs/actions/logaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class LogJobAction<T> implements JobAction<T> {
Logger.log("Performing job: " + JSON.stringify(job), "LogJobAction");
}

constructor(data: Record<string, any>) {
constructor(data: Record<string, unknown>) {
Logger.log(
"Initializing LogJobAction. Params: " + JSON.stringify(data),
"LogJobAction",
Expand Down
Loading

0 comments on commit fb59df0

Please sign in to comment.