From 4e67d3a64954709fe4746c19429e5bbeed6b1ecf Mon Sep 17 00:00:00 2001 From: Sofya Laskina <44316816+sofyalaski@users.noreply.github.com> Date: Mon, 29 Jul 2024 16:31:25 +0200 Subject: [PATCH] Jobs tests (#1286) * first tests * feat: reset dataset before every api test (#1131) * reset dataset before every api test * Clear collections before each api test * Fixes after jobs testing: 1. Use CreateJobAuth enum instead of AuthOp to define jobDatasetAuthorization 2. Shift a block if groupOwner is present down after the admin check was passed (admin create a job for anonym) 3. Check if current authorization is in jobDatasetAuthorization in instanceAuthorizationJobCreate (types mismatching) 4. Add a check if unauthorized user creates a job for someone else * Fixes after jobs testing: if anonymous user creates a job, initialize a jwt instance for him/her * Fixes after testing: string array includes string enum * dataset(s)Validation redundancy after a merged PR * test Jobs authorization wip * fix filtering syntax * fixes after Job testing: 1. comment out jobConfig matchin, as now in interceptor 2. fix filtering object hierarchy in #dataset kind of jobConfig's 3. not defining jobInstance ownerUser/Group as empty string 4. add jobInstance.jobParams initialization 5. add a check if datasets passed in the ID list exist * minor changes * fix findOne filtering syntax * add Jobs tests * remove redundancy * fix numbering * extend UPDATE_JOB_GROUP user's right to match docs * remove unneccessary arguments * make function return value of findOne an instance of JobClass * add statusUpdate tests * add jobParams to the job instance * Patch tests * Fixes after tests: * Anonymous user can patch status update to a job in #all config. Added instance authorization * Implement JobDelete authorization * add deleteJobGroups from env to configuration * add username for anonymous user when creating/updating status of the job * statusUpdate instead of update * Fixes after testing: * similarly to Datasets, mongoose returns an Object and not JobClass instances. To pass this into CASL we first need to make those class instances. generateJobInstanceForPermissions implements a copy of object as correct class instance only with properties required in casl. * functionality of instanceAuthorizationJobStatusUpdate is now implemented in the patch endpoint function. This is done to avoid redefining a found job as a instance of JobClass with all properties * For both GET endpoints only the endpoint authorisation was implemented for user in the functions of the controller. To add the instance authorization too, first create JobClass instance of the found job Objects and pass them to respective casl expressions. * adds implementation of delete endpoints. The rules are defined in the CheckPolicies decorator. * Finalized tests for authorization * add delete_job_groups definition * fix unit tests after test jobconfig.json changes * empty collections before testing * changes requested in PR * eremove version duplicate * change getJobMatchingConfiguration function to explicitly use job type, st it can be used for all cases where we need to extract the configuration, without having to pass the full dto * run full testing workflow on pushing to release branches * add env variable for jobs config path for github workflow * Fix lint errors - Run lint:fix - Ignore no-explicit-any rule for jobParams (which are not type checked) - remove 'read' jobOperation (not implemented) * Fix lint following merge * Update test/config/pretest.js to use "dotenv" Co-authored-by: Jay <a331998513@gmail.com> * Fix pretest.js after merging suggestions * Fix pretest.js * Fix jobconfig no-explicit-any issues - Revert previous changes to ignore no-explicit-any - Use `unknown` for jobParam inputs plus stronger runtime checks - Fix compilation error in elastic-search service relating to deleting non-optional variables. - Remove rabbitmqaction validation. RabbitMQ should ignore the DTO body, and validate the config itself in the constructor. * Fix jobconfig no-explicit-any issue (missed logaction) * changes in tests: 0060 now checks if a job was passed without a required parameter JobParams 0065 (new) checks if a job was passed with an empty object for jobParams 1950 now tries to delete a job that doesn't exist and fails 1960 was called 1950 before counts on GET are changed (because 0060 before was passing) * address comments in the PR: * now makes one request to the db to find datasets and extracts their pids. * loggs the names of all dataset pids that are not in the db in case of an error * job endpoint implements the check that the jobParams were passed and are not empty, otherwise it will throw a bad request with respective message * job endpoint loggs the id of job to be deleted and implements a check if job exist in db, otherwise throws an error. --------- Co-authored-by: Jay Quan <a331998513@gmail.com> Co-authored-by: Spencer Bliven <spencer.bliven@gmail.com> Co-authored-by: Despina Adamopoulou <16343312+despadam@users.noreply.github.com> --- .github/workflows/test.yml | 5 + src/casl/casl-ability.factory.ts | 72 +- src/common/handlebars-helpers.ts | 1 + src/config/configuration.ts | 6 +- src/elastic-search/elastic-search.service.ts | 9 +- src/jobs/actions/emailaction.ts | 14 +- src/jobs/actions/logaction.ts | 2 +- src/jobs/actions/rabbitmqaction.ts | 108 +- src/jobs/actions/urlaction.ts | 11 +- src/jobs/config/jobconfig.spec.ts | 4 +- src/jobs/config/jobconfig.ts | 96 +- src/jobs/jobs.controller.spec.ts | 9 +- src/jobs/jobs.controller.ts | 298 +- src/jobs/jobs.service.ts | 25 +- src/users/users.service.ts | 2 +- test/DatasetAuthorization.js | 3 + test/DatasetFilter.js | 3 + test/DatasetLifecycle.js | 3 + test/DerivedDataset.js | 3 + test/DerivedDatasetDatablock.js | 3 + test/DerivedDatasetOrigDatablock.js | 4 + test/ElasticSearch.js | 3 + test/Instrument.js | 3 + test/InstrumentsFilter.js | 6 +- test/Jobs.js | 4078 +++++++++++++++--- test/OrigDatablockForRawDataset.js | 22 +- test/Policy.js | 3 + test/Proposal.js | 3 + test/ProposalAuthorization.js | 10 +- test/PublishedData.js | 4 + test/RandomizedDatasetPermissions.js | 6 +- test/RawDataset.js | 4 + test/RawDatasetDatablock.js | 3 + test/RawDatasetOrigDatablock.js | 4 + test/Sample.js | 1 + test/SampleAuthorization.js | 741 ++-- test/TestData.js | 40 +- test/config/jobconfig.json | 108 +- test/config/pretest.js | 9 +- 39 files changed, 4562 insertions(+), 1167 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2a977c611..5b7067e54 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,6 +6,7 @@ on: pull_request: branches: - master + - release-* jobs: install-and-cache: @@ -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" @@ -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: | diff --git a/src/casl/casl-ability.factory.ts b/src/casl/casl-ability.factory.ts index 6fcc1a93e..c0aa2de27 100644 --- a/src/casl/casl-ability.factory.ts +++ b/src/casl/casl-ability.factory.ts @@ -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 @@ -818,11 +821,14 @@ 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)) @@ -830,24 +836,38 @@ export class CaslAbilityFactory { /** * 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), @@ -880,7 +900,7 @@ export class CaslAbilityFactory { ]; const jobCreateInstanceAuthorizationValues = [ ...Object.values(CreateJobAuth).filter( - (v) => ~String(v).includes("#dataset"), + (v) => !String(v).includes("#dataset"), ), ...jobUserAuthorizationValues, ]; @@ -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); @@ -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, @@ -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) => @@ -931,6 +966,11 @@ export class CaslAbilityFactory { // ------------------------------------- // data instance authorization + can(AuthOp.JobStatusUpdateConfiguration, JobClass, { + ["configuration.statusUpdate.auth" as string]: { + $in: jobUpdateInstanceAuthorizationValues, + }, + }); can(AuthOp.JobStatusUpdateOwner, JobClass, { ownerUser: user.username, }); @@ -938,22 +978,15 @@ export class CaslAbilityFactory { 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); @@ -975,6 +1008,7 @@ export class CaslAbilityFactory { ownerGroup: { $in: user.currentGroups }, }); } + cannot(AuthOp.JobDelete, JobClass); } } diff --git a/src/common/handlebars-helpers.ts b/src/common/handlebars-helpers.ts index 578a3c5be..b66e23235 100644 --- a/src/common/handlebars-helpers.ts +++ b/src/common/handlebars-helpers.ts @@ -40,6 +40,7 @@ export const formatCamelCase = (camelCase: string): string => { return words; }; +// eslint-disable-next-line @typescript-eslint/no-explicit-any export const jsonify = (context: any): string => { return JSON.stringify(context, null, 3); }; diff --git a/src/config/configuration.ts b/src/config/configuration.ts index bf1352fcc..3fd5452c9 100644 --- a/src/config/configuration.ts +++ b/src/config/configuration.ts @@ -1,4 +1,3 @@ -import { Logger } from "@nestjs/common"; import { loadJobConfig, registerCreateAction, @@ -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); @@ -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", @@ -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), diff --git a/src/elastic-search/elastic-search.service.ts b/src/elastic-search/elastic-search.service.ts index 59d9b4244..d3dbf1321 100644 --- a/src/elastic-search/elastic-search.service.ts +++ b/src/elastic-search/elastic-search.service.ts @@ -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, @@ -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 { diff --git a/src/jobs/actions/emailaction.ts b/src/jobs/actions/emailaction.ts index 54d67a186..4c41587ee 100644 --- a/src/jobs/actions/emailaction.ts +++ b/src/jobs/actions/emailaction.ts @@ -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 */ @@ -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", @@ -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"); } @@ -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), diff --git a/src/jobs/actions/logaction.ts b/src/jobs/actions/logaction.ts index b904f84ef..416f9e304 100644 --- a/src/jobs/actions/logaction.ts +++ b/src/jobs/actions/logaction.ts @@ -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", diff --git a/src/jobs/actions/rabbitmqaction.ts b/src/jobs/actions/rabbitmqaction.ts index 9e945e3bc..cc5703fd7 100644 --- a/src/jobs/actions/rabbitmqaction.ts +++ b/src/jobs/actions/rabbitmqaction.ts @@ -3,7 +3,6 @@ import amqp, { Connection } from "amqplib/callback_api"; import { JobAction } from "../config/jobconfig"; import { JobClass } from "../schemas/job.schema"; - /** * Publish a message in a RabbitMQ queue */ @@ -12,23 +11,42 @@ export class RabbitMQJobAction<T> implements JobAction<T> { private connection; private binding; - constructor(data: Record<string, any>) { + constructor(data: Record<string, unknown>) { Logger.log( "Initializing RabbitMQJobAction. Params: " + JSON.stringify(data), "RabbitMQJobAction", ); + // Validate that all necessary params are present + const requiredConnectionParams = [ + "hostname", + "port", + "username", + "password", + ]; + for (const param of requiredConnectionParams) { + if (!data[param]) { + throw new NotFoundException(`Missing connection parameter: ${param}`); + } + } + + const requiredBindingParams = ["exchange", "queue", "key"]; + for (const param of requiredBindingParams) { + if (!data[param]) { + throw new NotFoundException(`Missing binding parameter: ${param}`); + } + } this.connection = { protocol: "amqp", - hostname: data.hostname, - port: data.port, - username: data.username, - password: data.password, + hostname: data.hostname as string, + port: data.port as number, + username: data.username as string, + password: data.password as string, }; this.binding = { - exchange: data.exchange, - queue: data.queue, - key: data.key + exchange: data.exchange as string, + queue: data.queue as string, + key: data.key as string, }; } @@ -36,22 +54,8 @@ export class RabbitMQJobAction<T> implements JobAction<T> { return RabbitMQJobAction.actionType; } - async validate(dto: T) { - Logger.log( - "Validating RabbitMQJobAction: " + JSON.stringify(dto), - "RabbitMQJobAction", - ); - - const connectionDetailsMissing = [undefined, ""].some(el => Object.values(this.connection).includes(el)); - if (connectionDetailsMissing) { - throw new NotFoundException("RabbitMQ configuration is missing connection details."); - } - - const bindingDetailsMissing = [undefined, ""].some(el => Object.values(this.binding).includes(el)); - if (bindingDetailsMissing) { - throw new NotFoundException("RabbitMQ binding is missing exchange/queue/key details."); - } - } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async validate(dto: T) {} async performJob(job: JobClass) { Logger.log( @@ -59,33 +63,47 @@ export class RabbitMQJobAction<T> implements JobAction<T> { "RabbitMQJobAction", ); - amqp.connect(this.connection, (connectionError: Error, connection: Connection) => { - if (connectionError) { - Logger.error( - "Connection error in RabbitMQJobAction: " + JSON.stringify(connectionError.message), - "RabbitMQJobAction", - ); - return; - } - - connection.createChannel((channelError: Error, channel) => { - if (channelError) { + amqp.connect( + this.connection, + (connectionError: Error, connection: Connection) => { + if (connectionError) { Logger.error( - "Channel error in RabbitMQJobAction: " + JSON.stringify(channelError.message), + "Connection error in RabbitMQJobAction: " + + JSON.stringify(connectionError.message), "RabbitMQJobAction", ); return; } - channel.assertQueue(this.binding.queue, { durable: true }); - channel.assertExchange(this.binding.exchange, "topic", { durable: true }); - channel.bindQueue(this.binding.queue, this.binding.exchange, this.binding.key); - channel.sendToQueue(this.binding.queue, Buffer.from(JSON.stringify(job))); + connection.createChannel((channelError: Error, channel) => { + if (channelError) { + Logger.error( + "Channel error in RabbitMQJobAction: " + + JSON.stringify(channelError.message), + "RabbitMQJobAction", + ); + return; + } - channel.close(() => { - connection.close(); + channel.assertQueue(this.binding.queue, { durable: true }); + channel.assertExchange(this.binding.exchange, "topic", { + durable: true, + }); + channel.bindQueue( + this.binding.queue, + this.binding.exchange, + this.binding.key, + ); + channel.sendToQueue( + this.binding.queue, + Buffer.from(JSON.stringify(job)), + ); + + channel.close(() => { + connection.close(); + }); }); - }); - }); + }, + ); } } diff --git a/src/jobs/actions/urlaction.ts b/src/jobs/actions/urlaction.ts index 0ffe9f68c..ac4266fb8 100644 --- a/src/jobs/actions/urlaction.ts +++ b/src/jobs/actions/urlaction.ts @@ -1,9 +1,4 @@ -import { - Logger, - NotFoundException, - BadRequestException, - HttpException, -} from "@nestjs/common"; +import { Logger, NotFoundException, HttpException } from "@nestjs/common"; import { JobAction } from "../config/jobconfig"; import { JobClass } from "../schemas/job.schema"; import * as Handlebars from "handlebars"; @@ -32,12 +27,13 @@ export class URLAction<T> implements JobAction<T> { private urlTemplate: Handlebars.TemplateDelegate<JobClass>; private method = "GET"; private headers: Record<string, string> = {}; - private body: Record<string, any> | null = null; + private body: Record<string, unknown> | null = null; getActionType(): string { return URLAction.actionType; } + // eslint-disable-next-line @typescript-eslint/no-unused-vars async validate(dto: T) {} async performJob(job: JobClass) { @@ -75,6 +71,7 @@ export class URLAction<T> implements JobAction<T> { * * @throws {NotFoundException} If the 'url' parameter is not provided in the data object */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any constructor(data: Record<string, any>) { if (!data["url"]) { throw new NotFoundException("Param 'url' is undefined in url action"); diff --git a/src/jobs/config/jobconfig.spec.ts b/src/jobs/config/jobconfig.spec.ts index 819c85182..7f7db98b4 100644 --- a/src/jobs/config/jobconfig.spec.ts +++ b/src/jobs/config/jobconfig.spec.ts @@ -14,8 +14,8 @@ describe("Job configuration", () => { const path = "test/config/jobconfig.json"; const config = await loadJobConfig(path); expect(config).toBeDefined(); - expect(config.length).toBe(1); - expect(config[0].jobType).toBe("archive"); + expect(config.length).toBe(7); + expect(config[0].jobType).toBe("all_access"); expect(config[0].create).toBeDefined(); const create = config[0].create; expect(create.actions.length).toBe(1); diff --git a/src/jobs/config/jobconfig.ts b/src/jobs/config/jobconfig.ts index 6621ceabf..06658ef53 100644 --- a/src/jobs/config/jobconfig.ts +++ b/src/jobs/config/jobconfig.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ /** * Job configuration * @@ -24,7 +23,6 @@ import { CreateJobAuth, JobsAuth } from "../types/jobs-auth.enum"; import Ajv from "ajv"; import { JobConfigSchema } from "./jobConfig.schema"; - /** * Encapsulates all responses to a particular job type (eg "archive") */ @@ -32,20 +30,17 @@ export class JobConfig { jobType: string; configVersion: string; create: JobOperation<CreateJobDto>; - // read: JobOperation<ReadJobDto>; statusUpdate: JobOperation<StatusUpdateJobDto>; constructor( jobType: string, configVersion: string, create: JobOperation<CreateJobDto>, - read = undefined, statusUpdate: JobOperation<StatusUpdateJobDto>, ) { this.jobType = jobType; this.configVersion = configVersion; this.create = create; - // this.read = read; this.statusUpdate = statusUpdate; } @@ -55,24 +50,36 @@ export class JobConfig { * @returns */ static parse( - jobData: Record<string, any>, - configVersion: string + jobData: Record<string, unknown>, + configVersion: string, ): JobConfig { - const type = jobData[JobsConfigSchema.JobType]; + if ( + !(JobsConfigSchema.JobType in jobData) || + typeof jobData[JobsConfigSchema.JobType] !== "string" + ) { + throw new Error(`Invalid job type`); + } + const type = jobData[JobsConfigSchema.JobType] as string; + if (!(AuthOp.Create in jobData)) { + throw new Error(`No ${AuthOp.Create} configured for job type "${type}"`); + } + if (!(AuthOp.StatusUpdate in jobData)) { + throw new Error( + `No ${AuthOp.StatusUpdate} configured for job type "${type}"`, + ); + } const create = JobOperation.parse<CreateJobDto>( createActions, - jobData[AuthOp.Create], + jobData[AuthOp.Create] as Record<string, unknown>, ); - const read = undefined; const statusUpdate = JobOperation.parse<StatusUpdateJobDto>( statusUpdateActions, - jobData[AuthOp.StatusUpdate], + jobData[AuthOp.StatusUpdate] as Record<string, unknown>, ); - return new JobConfig(type, configVersion, create, read, statusUpdate); + return new JobConfig(type, configVersion, create, statusUpdate); } } - /** * Encapsulates all information for a particular job operation (eg "create", "statusUpdate") */ @@ -87,23 +94,36 @@ export class JobOperation<DtoType> { static parse<DtoType>( actionList: Record<string, JobActionClass<DtoType>>, - data: Record<string, any>, + data: Record<string, unknown>, ): JobOperation<DtoType> { // if Auth is not defined, default to #authenticated - const auth = data[JobsConfigSchema.Auth] - ? data[JobsConfigSchema.Auth] - : CreateJobAuth.Authenticated; - const actionsData: any[] = data[JobsConfigSchema.Actions] - ? data[JobsConfigSchema.Actions] - : []; - const actions = actionsData.map((json) => - parseAction<DtoType>(actionList, json), - ); + let auth: JobsAuth = CreateJobAuth.Authenticated; + if (data[JobsConfigSchema.Auth]) { + // don't bother to validate auth value + if (typeof data[JobsConfigSchema.Auth] !== "string") { + throw new Error( + `Invalid auth value "${data[JobsConfigSchema.Auth]}" for job type`, + ); + } + auth = data[JobsConfigSchema.Auth] as JobsAuth; + } + let actionsData: unknown[] = []; + if (JobsConfigSchema.Actions in data) { + if (!Array.isArray(data[JobsConfigSchema.Actions])) { + throw new Error(`Expected array for ${JobsConfigSchema.Actions} value`); + } + actionsData = data[JobsConfigSchema.Actions]; + } + const actions = actionsData.map((json) => { + if (typeof json !== "object") { + throw new Error(`Expected object for job config action`); + } + return parseAction<DtoType>(actionList, json as Record<string, unknown>); + }); return new JobOperation<DtoType>(actions, auth); } } - /** * Given a JSON object configuring a JobConfigAction. * @@ -114,11 +134,13 @@ export class JobOperation<DtoType> { */ function parseAction<DtoType>( actionList: Record<string, JobActionClass<DtoType>>, - data: Record<string, any>, + data: Record<string, unknown>, ): JobAction<DtoType> { if (!(JobsConfigSchema.ActionType in data)) throw SyntaxError(`No action.actionType in ${JSON.stringify(data)}`); - + if (typeof data[JobsConfigSchema.ActionType] !== "string") { + throw SyntaxError(`Expected string for ${JobsConfigSchema.ActionType}`); + } const type = data[JobsConfigSchema.ActionType]; if (!(type in actionList)) { throw SyntaxError(`No handler found for actions of type ${type}`); @@ -128,7 +150,6 @@ function parseAction<DtoType>( return new actionClass(data); } - /** * Superclass for all responses to Job changes */ @@ -150,7 +171,6 @@ export interface JobAction<DtoType> { getActionType(): string; } - /** * Describes the constructor and static members for JobAction implementations */ @@ -159,28 +179,27 @@ export interface JobActionClass<DtoType> { * Action type, eg "url". Matched during parsing of the action */ readonly actionType: string; - new (json: Record<string, any>): JobAction<DtoType>; + new (json: Record<string, unknown>): JobAction<DtoType>; } export type JobCreateAction = JobAction<CreateJobDto>; // export type JobReadAction = JobAction<ReadJobDto>; export type JobStatusUpdateAction = JobAction<StatusUpdateJobDto>; - /** * Action registration */ const createActions: Record<string, JobActionClass<CreateJobDto>> = {}; -// const readActions: Record<string, JobActionClass<ReadJobDto>> = {}; -const statusUpdateActions: Record<string, JobActionClass<StatusUpdateJobDto>> = {}; +const statusUpdateActions: Record< + string, + JobActionClass<StatusUpdateJobDto> +> = {}; /** * Registers an action to handle jobs of a particular type * @param action */ -export function registerCreateAction( - action: JobActionClass<CreateJobDto> -) { +export function registerCreateAction(action: JobActionClass<CreateJobDto>) { createActions[action.actionType] = action; } @@ -202,7 +221,6 @@ export function getRegisteredStatusUpdateActions(): string[] { return Object.keys(statusUpdateActions); } - /** * Parsing */ @@ -220,7 +238,7 @@ export function loadJobConfig(filePath: string): JobConfig[] { } const json = fs.readFileSync(filePath, "utf8"); - let data = JSON.parse(json); + const data = JSON.parse(json); // Validate schema const ajv = new Ajv(); @@ -232,6 +250,8 @@ export function loadJobConfig(filePath: string): JobConfig[] { console.log("Invalid Schema", JSON.stringify(validate.errors, null, 2)); } - jobConfig = data.jobs.map((jobData: Record<string, any>) => JobConfig.parse(jobData, data.configVersion)); + jobConfig = data.jobs.map((jobData: Record<string, unknown>) => + JobConfig.parse(jobData, data.configVersion), + ); return jobConfig as JobConfig[]; } diff --git a/src/jobs/jobs.controller.spec.ts b/src/jobs/jobs.controller.spec.ts index cc293eecd..73d0358e3 100644 --- a/src/jobs/jobs.controller.spec.ts +++ b/src/jobs/jobs.controller.spec.ts @@ -1,14 +1,17 @@ import { EventEmitter2 } from "@nestjs/event-emitter"; import { Test, TestingModule } from "@nestjs/testing"; -import { CaslAbilityFactory } from "src/casl/casl-ability.factory"; +import { CaslModule } from "src/casl/casl.module"; +//import { CaslAbilityFactory } from "src/casl/casl-ability.factory"; import { DatasetsService } from "src/datasets/datasets.service"; import { OrigDatablocksService } from "src/origdatablocks/origdatablocks.service"; import { JobsController } from "./jobs.controller"; import { JobsService } from "./jobs.service"; +import { UsersService } from "src/users/users.service"; class JobsServiceMock {} class DatasetsServiceMock {} class OrigDatablocksServiceMock {} +class UsersServiceMock {} describe("JobsController", () => { let controller: JobsController; @@ -16,11 +19,13 @@ describe("JobsController", () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [JobsController], + imports: [CaslModule], providers: [ - CaslAbilityFactory, + //CaslAbilityFactory, { provide: JobsService, useClass: JobsServiceMock }, { provide: DatasetsService, useClass: DatasetsServiceMock }, { provide: OrigDatablocksService, useClass: OrigDatablocksServiceMock }, + { provide: UsersService, useClass: UsersServiceMock }, { provide: EventEmitter2, useClass: EventEmitter2 }, ], }).compile(); diff --git a/src/jobs/jobs.controller.ts b/src/jobs/jobs.controller.ts index 3257d774a..062231c6f 100644 --- a/src/jobs/jobs.controller.ts +++ b/src/jobs/jobs.controller.ts @@ -23,6 +23,7 @@ import { PoliciesGuard } from "src/casl/guards/policies.guard"; import { CheckPolicies } from "src/casl/decorators/check-policies.decorator"; import { AppAbility, CaslAbilityFactory } from "src/casl/casl-ability.factory"; import { AuthOp } from "src/casl/authop.enum"; +import { CreateJobAuth } from "src/jobs/types/jobs-auth.enum"; import { JobClass, JobDocument } from "./schemas/job.schema"; import { ApiBearerAuth, @@ -62,7 +63,7 @@ export class JobsController { private readonly usersService: UsersService, private eventEmitter: EventEmitter2, ) { - this.jobDatasetAuthorization = Object.values(AuthOp).filter((v) => + this.jobDatasetAuthorization = Object.values(CreateJobAuth).filter((v) => v.includes("#dataset"), ); } @@ -275,7 +276,6 @@ export class JobsController { return true; }; - /** * Check that the user is authenticated */ @@ -293,17 +293,7 @@ export class JobsController { /** * Check that the dataset ids list is valid */ - checkDatasetIds = (jobParams: Record<string, unknown> | undefined) => { - if (!jobParams) { - throw new HttpException( - { - status: HttpStatus.BAD_REQUEST, - message: "Dataset ids list was not provided in jobParams", - }, - HttpStatus.BAD_REQUEST, - ); - } - + async checkDatasetIds(jobParams: Record<string, unknown>): Promise<string[]> { const field = JobsConfigSchema.DatasetIds; const datasetIds = ( typeof jobParams[field] === "string" @@ -320,31 +310,78 @@ export class JobsController { HttpStatus.BAD_REQUEST, ); } + interface condition { + where: { + pid: { $in: string[] }; + }; + } + if (datasetIds.length == 0) { + throw new HttpException( + { + status: HttpStatus.BAD_REQUEST, + message: "List of passed dataset IDs is empty.", + }, + HttpStatus.BAD_REQUEST, + ); + } + + const filter: condition = { + where: { + pid: { $in: datasetIds }, + }, + }; + const findDatasetsById = await this.datasetsService.findAll(filter); + const findIds = findDatasetsById.map(({ pid }) => pid); + const nonExistIds = datasetIds.filter((x) => !findIds.includes(x)); + if (nonExistIds.length != 0) { + throw new HttpException( + { + status: HttpStatus.BAD_REQUEST, + message: ` Datasets with pid ${nonExistIds} don't exist.`, + }, + HttpStatus.BAD_REQUEST, + ); + } return datasetIds; - }; + } + + /** + * Create instance of JobClass to check permissions + */ + async generateJobInstanceForPermissions(job: JobClass): Promise<JobClass> { + const jobInstance = new JobClass(); + jobInstance._id = job._id; + jobInstance.id = job.id; + jobInstance.type = job.type; + //jobInstance.configuration = configuration().statusUpdateJobGroups; + jobInstance.ownerGroup = job.ownerGroup; + jobInstance.ownerUser = job.ownerUser; + + return jobInstance; + } /** * Check job type matching configuration */ - getJobMatchingConfiguration = (createJobDto: CreateJobDtoWithConfig) => { + getJobMatchingConfiguration = (createJobDtoType: string) => { const jobConfigs = configuration().jobConfiguration; const matchingConfig = jobConfigs.filter( - (j) => j.jobType == createJobDto.type, + (j) => j.jobType == createJobDtoType, ); if (matchingConfig.length != 1) { if (matchingConfig.length > 1) { Logger.error( - "More than one job configurations matching type " + createJobDto.type, + "More than one job configurations matching type " + createJobDtoType, ); } else { - Logger.error("No job configuration matching type " + createJobDto.type); + Logger.error("No job configuration matching type " + createJobDtoType); } // return error that job type does not exists throw new HttpException( { status: HttpStatus.BAD_REQUEST, - message: "Invalid job type: " + createJobDto.type, + message: "Invalid job type: " + createJobDtoType, }, HttpStatus.BAD_REQUEST, ); @@ -362,32 +399,27 @@ export class JobsController { // NOTE: We need JobClass instance because casl module works only on that. // If other fields are needed can be added later. const jobInstance = new JobClass(); - const jobConfiguration = this.getJobMatchingConfiguration(jobCreateDto); + const jobConfiguration = this.getJobMatchingConfiguration( + jobCreateDto.type, + ); jobInstance._id = ""; - jobInstance.ownerUser = ""; - jobInstance.ownerGroup = ""; jobInstance.accessGroups = []; jobInstance.type = jobCreateDto.type; jobInstance.contactEmail = jobCreateDto.contactEmail; + jobInstance.jobParams = jobCreateDto.jobParams; jobInstance.datasetsValidation = false; jobInstance.configuration = jobConfiguration; jobInstance.statusCode = "Initializing"; jobInstance.statusMessage = "Building and validating job, verifying authorization"; + // if datasetIds property in jobParams is passed, check if such IDs exist in data base + let datasetIds: string[] = []; + if (JobsConfigSchema.DatasetIds in jobCreateDto.jobParams) { + datasetIds = await this.checkDatasetIds(jobCreateDto.jobParams); + } if (user) { - // check if we have ownerGroup - if (!jobCreateDto.ownerGroup) { - throw new HttpException( - { - status: HttpStatus.BAD_REQUEST, - message: `Invalid new job. Owner group should be specified`, - }, - HttpStatus.BAD_REQUEST, - ); - } - // the request comes from a user who is logged in. if ( user.currentGroups.some((g) => configuration().adminGroups.includes(g)) @@ -399,11 +431,20 @@ export class JobsController { jobCreateDto.ownerUser, ); } - jobInstance.ownerUser = jobUser?.username as string; jobInstance.contactEmail = jobUser?.email as string; jobInstance.ownerGroup = jobCreateDto.ownerGroup; } else { + // check if we have ownerGroup + if (!jobCreateDto.ownerGroup) { + throw new HttpException( + { + status: HttpStatus.BAD_REQUEST, + message: `Invalid new job. Owner group should be specified.`, + }, + HttpStatus.BAD_REQUEST, + ); + } // check that job user matches the user placing the request, if job user is specified if (jobCreateDto.ownerUser && jobCreateDto.ownerUser != user.username) { throw new HttpException( @@ -421,7 +462,7 @@ export class JobsController { throw new HttpException( { status: HttpStatus.BAD_REQUEST, - message: `Invalid new job. User needs to belong to job owner group`, + message: `Invalid new job. User needs to belong to job owner group.`, }, HttpStatus.BAD_REQUEST, ); @@ -432,26 +473,51 @@ export class JobsController { if ( jobConfiguration.create.auth && - jobConfiguration.create.auth in this.jobDatasetAuthorization + Object.values(this.jobDatasetAuthorization).includes( + jobConfiguration.create.auth, + ) ) { + // check that jobParams are passed for #dataset jobs + if (!jobCreateDto.jobParams) { + throw new HttpException( + { + status: HttpStatus.BAD_REQUEST, + message: "Dataset ids list was not provided in jobParams", + }, + HttpStatus.BAD_REQUEST, + ); + } // verify that the user meet the requested permissions on the datasets listed - const datasetIds = this.checkDatasetIds(jobCreateDto.jobParams); + // const datasetIds = await this.checkDatasetIds(jobCreateDto.jobParams); // build the condition - const datasetsWhere: Record<string, unknown> = { + interface datasetsWhere { + where: { + pid: { $in: string[] }; + isPublished?: boolean; + ownerGroup?: { $in: string[] }; + $or?: [ + { ownerGroup: { $in: string[] } }, + { accessGroups: { $in: string[] } }, + { isPublished: true }, + ]; + }; + } + + const datasetsWhere: datasetsWhere = { where: { pid: { $in: datasetIds }, }, }; if (jobConfiguration.create.auth === "#datasetPublic") { - datasetsWhere["isPublished"] = true; + datasetsWhere["where"]["isPublished"] = true; } else if (jobConfiguration.create.auth === "#datasetAccess") { - datasetsWhere["$or"] = [ + datasetsWhere["where"]["$or"] = [ { ownerGroup: { $in: user.currentGroups } }, { accessGroups: { $in: user.currentGroups } }, { isPublished: true }, ]; } else if (jobConfiguration.create.auth === "#datasetOwner") { - datasetsWhere["ownerGroup"] = { $in: user.currentGroups }; + datasetsWhere["where"]["ownerGroup"] = { $in: user.currentGroups }; } const numberOfDatasetsWithAccess = await this.datasetsService.count(datasetsWhere); @@ -459,6 +525,15 @@ export class JobsController { datasetIds.length - numberOfDatasetsWithAccess.count; jobInstance.datasetsValidation = datasetsNoAccess == 0; } + if (!user && jobCreateDto.ownerGroup) { + throw new HttpException( + { + status: HttpStatus.BAD_REQUEST, + message: `Invalid new job. Unauthenticated user cannot initiate a job owned by another user.`, + }, + HttpStatus.BAD_REQUEST, + ); + } // instantiate the casl matrix for the user const ability = this.caslAbilityFactory.createForUser(user); @@ -469,7 +544,7 @@ export class JobsController { ability.can(AuthOp.JobCreateConfiguration, jobInstance); if (!canCreate) { - throw new ForbiddenException("Unauthorized to create this dataset"); + throw new ForbiddenException("Unauthorized to create this dataset."); } return jobInstance; @@ -478,7 +553,10 @@ export class JobsController { /** * Send off to external service */ - async performJobAction(jobInstance: JobClass, action: JobAction<CreateJobDto> | JobAction<StatusUpdateJobDto>): Promise<void> { + async performJobAction( + jobInstance: JobClass, + action: JobAction<CreateJobDto> | JobAction<StatusUpdateJobDto>, + ): Promise<void> { await action.performJob(jobInstance).catch((err: Error) => { if (err instanceof HttpException) { throw err; @@ -496,7 +574,7 @@ export class JobsController { } async performJobCreateAction(jobInstance: JobClass): Promise<void> { - const jobConfig = this.getJobMatchingConfiguration(jobInstance); + const jobConfig = this.getJobMatchingConfiguration(jobInstance.type); for (const action of jobConfig.create.actions) { await this.performJobAction(jobInstance, action); } @@ -504,7 +582,7 @@ export class JobsController { } async performJobStatusUpdateAction(jobInstance: JobClass): Promise<void> { - const jobConfig = this.getJobMatchingConfiguration(jobInstance); + const jobConfig = this.getJobMatchingConfiguration(jobInstance.type); await Promise.all( jobConfig.statusUpdate.actions.map((action) => { @@ -533,7 +611,6 @@ export class JobsController { return; } - /** * Create job */ @@ -562,6 +639,19 @@ export class JobsController { @Body() createJobDtoWithConfig: CreateJobDtoWithConfig, ): Promise<JobClass | null> { Logger.log("Creating job!"); + // throw an error if no jobParams are passed + if ( + !createJobDtoWithConfig.jobParams || + Object.keys(createJobDtoWithConfig.jobParams).length == 0 + ) { + throw new HttpException( + { + status: HttpStatus.BAD_REQUEST, + message: "Job parameters need to be defined.", + }, + HttpStatus.BAD_REQUEST, + ); + } // Validate that request matches the current configuration // Check job authorization const jobInstance = await this.instanceAuthorizationJobCreate( @@ -569,37 +659,12 @@ export class JobsController { request.user as JWTUser, ); // Create actual job in database - const createdJobInstance = await this.jobsService.create( - jobInstance, - ); - + const createdJobInstance = await this.jobsService.create(jobInstance); // Perform the action that is specified in the create portion of the job configuration await this.performJobCreateAction(createdJobInstance); return createdJobInstance; } - /** - * Checking if user is allowed to create job according to auth field of job configuration - */ - async instanceAuthorizationJobStatusUpdate( - user: JWTUser, - jobInstance: JobClass, - ): Promise<JobClass> { - // instantiate the casl matrix for the user - const ability = this.caslAbilityFactory.createForUser(user); - // check if he/she can create this dataset - const canCreate = - ability.can(AuthOp.JobStatusUpdateAny, JobClass) || - ability.can(AuthOp.JobStatusUpdateOwner, jobInstance) || - ability.can(AuthOp.JobStatusUpdateConfiguration, jobInstance); - - if (!canCreate) { - throw new ForbiddenException("Unauthorized to update this dataset"); - } - - return jobInstance; - } - /** * Update job status */ @@ -639,13 +704,29 @@ export class JobsController { HttpStatus.BAD_REQUEST, ); } - // Check job authorization - await this.instanceAuthorizationJobStatusUpdate( + const currentJobInstance = + await this.generateJobInstanceForPermissions(currentJob); + currentJobInstance.configuration = this.getJobMatchingConfiguration( + currentJobInstance.type, + ); + + const ability = this.caslAbilityFactory.createForUser( request.user as JWTUser, - currentJob, ); + // check if he/she can create this dataset + const canUpdateStatus = + ability.can(AuthOp.JobStatusUpdateAny, JobClass) || + ability.can(AuthOp.JobStatusUpdateOwner, currentJobInstance) || + ability.can(AuthOp.JobStatusUpdateConfiguration, currentJobInstance); + if (!canUpdateStatus) { + throw new ForbiddenException("Unauthorized to update this dataset"); + } + // Update job in database - const updatedJob = await this.jobsService.statusUpdate(id, statusUpdateJobDto); + const updatedJob = await this.jobsService.statusUpdate( + id, + statusUpdateJobDto, + ); // Perform the action that is specified in the update portion of the job configuration if (updatedJob !== null) { await this.performJobStatusUpdateAction(updatedJob); @@ -681,7 +762,28 @@ export class JobsController { @Req() request: Request, @Param("id") id: string, ): Promise<JobClass | null> { - return this.jobsService.findOne({ _id: id }); + const currentJob = await this.jobsService.findOne({ _id: id }); + if (currentJob === null) { + throw new HttpException( + { + status: HttpStatus.BAD_REQUEST, + message: "Invalid job id.", + }, + HttpStatus.BAD_REQUEST, + ); + } + const currentJobInstance = + await this.generateJobInstanceForPermissions(currentJob); + const ability = this.caslAbilityFactory.createForUser( + request.user as JWTUser, + ); + const canCreate = + ability.can(AuthOp.JobReadAny, JobClass) || + ability.can(AuthOp.JobReadAccess, currentJobInstance); + if (!canCreate) { + throw new ForbiddenException("Unauthorized to update this dataset"); + } + return currentJob; } /** @@ -711,7 +813,7 @@ export class JobsController { async findAll( @Req() request: Request, @Query("filter") filter?: string, - ): Promise<JobClass[] | null> { + ): Promise<JobClass[]> { try { filter = filter ?? "{}"; JSON.parse(filter as string); @@ -724,9 +826,27 @@ export class JobsController { if (!this.isFilterValid(Object.keys(parsedFilter))) { throw { message: "Invalid filter syntax." }; } - return this.jobsService.findAll(parsedFilter); - } - catch (e) { + // for each job run a casl JobReadOwner on a jobInstance + const datasetsFound = await this.jobsService.findAll(parsedFilter); + const datasetsAccessible: JobClass[] = []; + const ability = this.caslAbilityFactory.createForUser( + request.user as JWTUser, + ); + + for (const i in datasetsFound) { + // check if he/she can create this dataset + const jobInstance = await this.generateJobInstanceForPermissions( + datasetsFound[i], + ); + const canCreate = + ability.can(AuthOp.JobReadAny, JobClass) || + ability.can(AuthOp.JobReadAccess, jobInstance); + if (canCreate) { + datasetsAccessible.push(datasetsFound[i]); + } + } + return datasetsAccessible; + } catch (e) { throw new HttpException( { status: HttpStatus.BAD_REQUEST, @@ -742,7 +862,9 @@ export class JobsController { */ @UseGuards(PoliciesGuard) @CheckPolicies( - (ability: AppAbility) => ability.can(AuthOp.Delete, JobClass), // TBD + (ability: AppAbility) => + ability.can(AuthOp.JobDelete, JobClass) && + ability.can(AuthOp.JobDeleteAny, JobClass), ) @Delete(":id") @ApiOperation({ @@ -758,6 +880,18 @@ export class JobsController { @Req() request: Request, @Param("id") id: string, ): Promise<unknown> { + const foundJob = await this.jobsService.findOne({ _id: id }); + if (foundJob === null) { + throw new HttpException( + { + status: HttpStatus.BAD_REQUEST, + message: `Job id ${id} doesn't exist.`, + }, + HttpStatus.BAD_REQUEST, + ); + } + + Logger.log(`Deleting job with id ${id}!`); return this.jobsService.remove({ _id: id }); } } diff --git a/src/jobs/jobs.service.ts b/src/jobs/jobs.service.ts index c9cfa5e2b..f380bf08e 100644 --- a/src/jobs/jobs.service.ts +++ b/src/jobs/jobs.service.ts @@ -30,10 +30,16 @@ export class JobsService { @Inject(REQUEST) private request: Request, ) {} - async create( - createJobDto: CreateJobDto, - ): Promise<JobDocument> { - const username = (this.request.user as JWTUser).username; + getUsername(): string { + if (this.request.user as JWTUser) { + return (this.request.user as JWTUser).username; + } else { + return "anonymous"; + } + } + + async create(createJobDto: CreateJobDto): Promise<JobDocument> { + const username = this.getUsername(); const createdJob = new this.jobModel( addStatusFields( addCreatedByFields(createJobDto, username), @@ -45,9 +51,9 @@ export class JobsService { } async findAll( - filter: IFilters<JobDocument, FilterQuery<JobDocument>> + filter: IFilters<JobDocument, FilterQuery<JobDocument>>, ): Promise<JobClass[]> { - var whereFilters: FilterQuery<JobDocument> = filter.where ?? {}; + const whereFilters: FilterQuery<JobDocument> = filter.where ?? {}; const { limit, skip, sort } = parseLimitFilters(filter.limits); return this.jobModel @@ -94,13 +100,16 @@ export class JobsService { if (!existingJob) { throw new NotFoundException(`Job #${id} not found`); } - const username = (this.request.user as JWTUser).username; + const username = this.getUsername(); const updatedJob = await this.jobModel .findOneAndUpdate( { id: id }, addStatusFields( - addUpdatedByField(statusUpdateJobDto as UpdateQuery<JobDocument>, username), + addUpdatedByField( + statusUpdateJobDto as UpdateQuery<JobDocument>, + username, + ), statusUpdateJobDto.statusCode, statusUpdateJobDto.statusMessage!, ), diff --git a/src/users/users.service.ts b/src/users/users.service.ts index 2f96d25ae..6675324fc 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -238,7 +238,7 @@ export class UsersService implements OnModuleInit { async findByUsername2JWTUser(username: string): Promise<JWTUser | null> { const userIdentity = await this.userIdentityModel - .findOne({ username: username }) + .findOne({ "profile.username": username }) .exec(); if (userIdentity) { const userProfile = userIdentity.profile; diff --git a/test/DatasetAuthorization.js b/test/DatasetAuthorization.js index b2ab8c39d..bcecc2b03 100644 --- a/test/DatasetAuthorization.js +++ b/test/DatasetAuthorization.js @@ -42,6 +42,9 @@ const dataset3 = { }; describe("0300: DatasetAuthorization: Test access to dataset", () => { + before(() => { + db.collection("Dataset").deleteMany({}); + }); beforeEach((done) => { utils.getToken( appUrl, diff --git a/test/DatasetFilter.js b/test/DatasetFilter.js index 05d64550e..37b71bf79 100644 --- a/test/DatasetFilter.js +++ b/test/DatasetFilter.js @@ -89,6 +89,9 @@ const RawCorrect4 = { }; describe("0400: DatasetFilter: Test retrieving datasets using filtering capabilities", () => { + before(() => { + db.collection("Dataset").deleteMany({}); + }); beforeEach((done) => { utils.getToken( appUrl, diff --git a/test/DatasetLifecycle.js b/test/DatasetLifecycle.js index 8c9b4749c..2f3fed3bc 100644 --- a/test/DatasetLifecycle.js +++ b/test/DatasetLifecycle.js @@ -13,6 +13,9 @@ var policyIds = null; const raw2 = { ...TestData.RawCorrect }; describe("0500: DatasetLifecycle: Test facet and filter queries", () => { + before(() => { + db.collection("Dataset").deleteMany({}); + }); beforeEach((done) => { utils.getToken( appUrl, diff --git a/test/DerivedDataset.js b/test/DerivedDataset.js index efce61e31..61b960799 100644 --- a/test/DerivedDataset.js +++ b/test/DerivedDataset.js @@ -14,6 +14,9 @@ var minPid = null; var explicitPid = null; describe("0700: DerivedDataset: Derived Datasets", () => { + before(() => { + db.collection("Dataset").deleteMany({}); + }); beforeEach((done) => { utils.getToken( appUrl, diff --git a/test/DerivedDatasetDatablock.js b/test/DerivedDatasetDatablock.js index 1621e03a9..ca62c7fc8 100644 --- a/test/DerivedDatasetDatablock.js +++ b/test/DerivedDatasetDatablock.js @@ -12,6 +12,9 @@ describe("0750: DerivedDatasetDatablock: Test Datablocks and their relation to d let datablockId2 = null; beforeEach((done) => { + before(() => { + db.collection("Dataset").deleteMany({}); + }); utils.getToken( appUrl, { diff --git a/test/DerivedDatasetOrigDatablock.js b/test/DerivedDatasetOrigDatablock.js index c9f96ea2e..a8566b816 100644 --- a/test/DerivedDatasetOrigDatablock.js +++ b/test/DerivedDatasetOrigDatablock.js @@ -12,6 +12,10 @@ describe("0800: DerivedDatasetOrigDatablock: Test OrigDatablocks and their relat let origDatablockId2 = null; beforeEach((done) => { + before(() => { + db.collection("Dataset").deleteMany({}); + db.collection("OrigDatablock").deleteMany({}); + }); utils.getToken( appUrl, { diff --git a/test/ElasticSearch.js b/test/ElasticSearch.js index c65141758..a34551ab1 100644 --- a/test/ElasticSearch.js +++ b/test/ElasticSearch.js @@ -44,6 +44,9 @@ const scientificMetadata = ({ (isESenabled ? describe : describe.skip)( "ElastiSearch: CRUD, filtering and search test case", () => { + before(() => { + db.collection("Dataset").deleteMany({}); + }); beforeEach((done) => { utils.getToken( appUrl, diff --git a/test/Instrument.js b/test/Instrument.js index bb630e10c..613f5f621 100644 --- a/test/Instrument.js +++ b/test/Instrument.js @@ -17,6 +17,9 @@ let accessTokenAdminIngestor = null, const newName = "ESS3-1"; describe("0900: Instrument: instrument management, creation, update, deletion and search", () => { + before(() => { + db.collection("Instrument").deleteMany({}); + }); beforeEach((done) => { utils.getToken( appUrl, diff --git a/test/InstrumentsFilter.js b/test/InstrumentsFilter.js index 973e6e879..a3958f90d 100644 --- a/test/InstrumentsFilter.js +++ b/test/InstrumentsFilter.js @@ -42,6 +42,9 @@ const InstrumentCorrect4 = { }; describe("1000: InstrumentFilter: Test retrieving instruments using filtering capabilities", () => { + before(() => { + db.collection("Instrument").deleteMany({}); + }); beforeEach((done) => { utils.getToken( appUrl, @@ -79,7 +82,8 @@ describe("1000: InstrumentFilter: Test retrieving instruments using filtering ca appUrl, { username: "archiveManager", - password: TestData.Accounts["archiveManager"]["password"], + password: + TestData.Accounts["archiveManager"]["password"], }, (tokenVal) => { accessTokenArchiveManager = tokenVal; diff --git a/test/Jobs.js b/test/Jobs.js index 9d7ec1f60..e9d48638a 100644 --- a/test/Jobs.js +++ b/test/Jobs.js @@ -1,33 +1,151 @@ /* eslint-disable @typescript-eslint/no-var-requires */ "use strict"; +const { and } = require("ajv/dist/compile/codegen"); var utils = require("./LoginUtils"); const { TestData } = require("./TestData"); -var accessTokenAdminIngestor = null; -var accessTokenArchiveManager = null; +let accessTokenAdminIngestor = null, + accessTokenUser1 = null, + accessTokenUser3 = null, + accessTokenUser51 = null, + accessTokenUser52 = null, + accessTokenAdmin = null, + accessTokenArchiveManager = null; -var pid1 = null; -var pid2 = null; -var datasetLiveCycle1 = {}; -var datasetLiveCycle2 = {}; -var archiveJob = null; -var retrieveJob = null; -var publicJob = null; -var archiveJobId = null; -var retrieveJobId = null; -var publicJobIds = []; -var origDatablockId = null; -describe.skip("1100: Jobs: Test New Job Model", () => { - before((done) => { - archiveJob = { ...TestData.ArchiveJob }; - retrieveJob = { ...TestData.RetrieveJob }; - publicJob = { ...TestData.PublicJob }; - done(); +let datasetPid1 = null, + datasetPid2 = null, + datasetPid3 = null, + jobId1 = null, + encodedJobId1 = null, + jobId2 = null, + encodedJobId2 = null, + jobId3 = null, + encodedJobId3 = null, + jobId4 = null, + encodedJobId4 = null, + jobId5 = null, + encodedJobId5 = null, + jobId6 = null, + encodedJobId6 = null, + + jobIdGroup1 = null, + encodedJobIdGroup1 = null, + jobIdGroup2 = null, + encodedJobIdGroup2 = null, + jobIdGroup3 = null, + encodedJobIdGroup3 = null, + jobIdGroup4 = null, + encodedJobIdGroup4 = null, + jobIdGroup5 = null, + encodedJobIdGroup5 = null, + jobIdGroup6 = null, + encodedJobIdGroup6 = null, + + jobIdUser1 = null, + encodedJobIdUser1 = null, + jobIdUser2 = null, + encodedJobIdUser2 = null, + jobIdUser3 = null, + encodedJobIdUser3 = null, + jobIdUser4 = null, + encodedJobIdUser4 = null, + jobIdUser5 = null, + encodedJobIdUser5 = null, + jobIdUser6 = null, + encodedJobIdUser6 = null, + + jobIdUserSpec1 = null, + encodedJobIdUserSpec1 = null, + jobIdUserSpec2 = null, + encodedJobIdUserSpec2 = null, + jobIdUserSpec3 = null, + encodedJobIdUserSpec3 = null, + jobIdUserSpec4 = null, + encodedJobIdUserSpec4 = null, + jobIdUserSpec5 = null, + encodedJobIdUserSpec5 = null, + jobIdUserSpec6 = null, + encodedJobIdUserSpec6 = null, + jobIdUserSpec7 = null, + encodedJobIdUserSpec7 = null, + + jobIdGroupSpec1 = null, + encodedJobIdGroupSpec1 = null, + jobIdGroupSpec2 = null, + encodedJobIdGroupSpec2 = null, + jobIdGroupSpec3 = null, + encodedJobIdGroupSpec3 = null, + jobIdGroupSpec4 = null, + encodedJobIdGroupSpec4 = null, + jobIdGroupSpec5 = null, + encodedJobIdGroupSpec5 = null, + jobIdGroupSpec6 = null, + encodedJobIdGroupSpec6 = null, + jobIdGroupSpec7 = null, + encodedJobIdGroupSpec7 = null, + jobIdGroupSpec8 = null, + encodedJobIdGroupSpec8 = null; + + +const dataset1 = { + ...TestData.RawCorrect, + isPublished: true, + ownerGroup: "group1", + accessGroups: ["group5"], +}; + +const dataset2 = { + ...TestData.RawCorrect, + isPublished: false, + ownerGroup: "group2", + accessGroups: [], +}; + +const dataset3 = { + ...TestData.RawCorrect, + isPublished: false, + ownerGroup: "group5", + accessGroups: ["group1"], +}; +const jobAll = { + ...TestData.Job, + type: "all_access", +}; +const jobDatasetPublic = { + ...TestData.Job, + type: "public_access", +} +const jobAuthenticated = { + ...TestData.Job, + type: "authenticated_access" +}; +const jobDatasetAccess = { + ...TestData.Job, + type: "dataset_access" +}; +const jobDatasetOwner = { + ...TestData.Job, + type: "owner_access" +}; +const jobUser51 = { + ...TestData.Job, + type: "user_access" +}; +const jobGroup5 = { + ...TestData.Job, + type: "group_access" +}; + +describe("1100: Jobs: Test New Job Model", () => { + before(() => { + db.collection("Dataset").deleteMany({}); + db.collection("Job").deleteMany({}); }); + beforeEach((done) => { utils.getToken( appUrl, @@ -40,755 +158,3715 @@ describe.skip("1100: Jobs: Test New Job Model", () => { utils.getToken( appUrl, { - username: "archiveManager", - password: TestData.Accounts["archiveManager"]["password"], + username: "user1", + password: TestData.Accounts["user1"]["password"], }, (tokenVal) => { - accessTokenArchiveManager = tokenVal; - done(); + accessTokenUser1 = tokenVal; + utils.getToken( + appUrl, + { + username: "user3", + password: TestData.Accounts["user3"]["password"], + }, + (tokenVal) => { + accessTokenUser3 = tokenVal; + utils.getToken( + appUrl, + { + username: "user5.1", + password: TestData.Accounts["user5.1"]["password"], + }, + (tokenVal) => { + accessTokenUser51 = tokenVal; + utils.getToken( + appUrl, + { + username: "user5.2", + password: + TestData.Accounts["user5.2"]["password"], + }, + (tokenVal) => { + accessTokenUser52 = tokenVal; + utils.getToken( + appUrl, + { + username: "admin", + password: TestData.Accounts["admin"]["password"], + }, + (tokenVal) => { + accessTokenAdmin = tokenVal; + utils.getToken( + appUrl, + { + username:"archiveManager", + password: TestData.Accounts["archiveManager"]["password"], + }, + (tokenVal) => { + accessTokenArchiveManager = tokenVal; + done(); + } + ) + }, + ); + }, + ); + }, + ); + }, + ); }, ); }, ); }); - it("0010: adds a new raw dataset", async () => { + after(() => { //because we're not deleting all the jobs and don't delete datasets + db.collection("Dataset").deleteMany({}); + db.collection("Job").deleteMany({}); + }); + + it("0010: adds dataset 1 as Admin Ingestor", async () => { return request(appUrl) .post("/api/v3/Datasets") - .send(TestData.RawCorrect) + .send(dataset1) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .expect(TestData.EntryCreatedStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.body.should.have.property("owner").and.be.string; + res.body.should.have.property("ownerGroup").and.equal("group1"); res.body.should.have.property("type").and.equal("raw"); + res.body.should.have.property("isPublished").and.equal(true); res.body.should.have.property("pid").and.be.string; - // store link to this dataset in datablocks - var pidtest = res.body["pid"]; - archiveJob.datasetList[0].pid = pidtest; - retrieveJob.datasetList[0].pid = pidtest; - publicJob.datasetList[0].pid = pidtest; - pid1 = encodeURIComponent(res.body["pid"]); + datasetPid1 = res.body["pid"]; }); }); - it("0020: adds another new raw dataset", async () => { + it("0020: adds dataset 2 as Admin Ingestor", async () => { return request(appUrl) .post("/api/v3/Datasets") - .send(TestData.RawCorrect) + .send(dataset2) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .expect(TestData.EntryCreatedStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.body.should.have.property("owner").and.be.string; + res.body.should.have.property("ownerGroup").and.equal("group2"); res.body.should.have.property("type").and.equal("raw"); + res.body.should.have.property("isPublished").and.equal(false); res.body.should.have.property("pid").and.be.string; - // store link to this dataset in datablocks - var pidtest = res.body["pid"]; - archiveJob.datasetList[1].pid = pidtest; - retrieveJob.datasetList[1].pid = pidtest; - publicJob.datasetList[1].pid = pidtest; - pid2 = encodeURIComponent(res.body["pid"]); + datasetPid2 = res.body["pid"]; }); }); - it("0030: Adds a new archive job request without authentication, which should fail", async () => { + it("0030: adds dataset 3 as Admin Ingestor", async () => { return request(appUrl) - .post("/api/v3/Jobs") - .send(archiveJob) + .post("/api/v3/Datasets") + .send(dataset3) .set("Accept", "application/json") - .expect(TestData.UnauthorizedStatusCode) + .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) + .expect(TestData.EntryCreatedStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.should.have.property("error"); + res.body.should.have.property("ownerGroup").and.equal("group5"); + res.body.should.have.property("type").and.equal("raw"); + res.body.should.have.property("isPublished").and.equal(false); + res.body.should.have.property("pid").and.be.string; + datasetPid3 = res.body["pid"]; }); }); + + it("0040: Add a new job as a user from ADMIN_GROUPS for himself/herself in '#all' configuration with no datasets in job parameters, which should fail", async () => { + const newDataset = { + ...jobAll, + ownerUser: "admin", + ownerGroup: "admin", + jobParams: { + ...jobAll.jobParams, + datasetIds: [], + }, + }; - it("0040: Adds a new archive job request", async () => { return request(appUrl) .post("/api/v3/Jobs") - .send(archiveJob) + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.EntryCreatedStatusCode) + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.BadRequestStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.body.should.have.property("type").and.be.string; - archiveJobId = res.body["id"]; + res.body.should.not.have.property("id") + res.body.should.have.property("message").and.be.equal("List of passed dataset IDs is empty."); }); }); - it("0050: Adds a new archive job request contains empty datasetList, which should fail", async () => { - const empty = { ...TestData.ArchiveJob }; - empty.datasetList = []; + it("0050: Add a new job as a user from ADMIN_GROUPS for himself/herself in '#all' configuration with not existing dataset IDs, which should fail", async () => { + const newDataset = { + ...jobAll, + ownerUser: "admin", + ownerGroup: "admin", + jobParams: { + ...jobAll.jobParams, + datasetIds: ["fakeID", "fakeID2"], + }, + }; + return request(appUrl) .post("/api/v3/Jobs") - .send(empty) + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) .expect(TestData.BadRequestStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.should.have.property("error"); + res.body.should.not.have.property("id") }); }); - it("0060: Adds a new archive job request on non exist dataset which should fail", async () => { - let nonExistDataset = { - ...TestData.ArchiveJob, - datasetList: [ - { - pid: "dummy", - files: [], - }, - ], + it("0060: Add a new job as a user from ADMIN_GROUPS for himself/herself in '#datasetPublic' configuration with no jobParams parameter, which should fail", async () => { + const newDataset = { + type: "all_access", + ownerUser: "admin", + ownerGroup: "admin", }; return request(appUrl) .post("/api/v3/Jobs") - .send(nonExistDataset) + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) .expect(TestData.BadRequestStatusCode) .expect("Content-Type", /json/) - .then((res, err) => { - if (err) { - return done(err); - } - res.body.should.have.property("message"); + .then((res) => { + res.body.should.not.have.property("id"); + res.body.should.have.property("message").and.be.equal("Job parameters need to be defined."); }); }); - it("0070: Check if dataset 1 was updated by job request", async () => { + it("0065: Add a new job as a user from ADMIN_GROUPS for himself/herself in '#datasetPublic' configuration with empty jobParams parameter, which should fail", async () => { + const newDataset = { + type: "all_access", + ownerUser: "admin", + ownerGroup: "admin", + }; + return request(appUrl) - .get("/api/v3/Datasets/" + pid1) + .post("/api/v3/Jobs") + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.SuccessfulGetStatusCode) + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.BadRequestStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.body.should.have.nested - .property("datasetlifecycle.archivable") - .and.equal(false); - res.body.should.have.nested - .property("datasetlifecycle.retrievable") - .and.equal(false); - res.body.should.have.nested - .property("datasetlifecycle.archiveStatusMessage") - .and.equal("scheduledForArchiving"); - res.body.should.have.nested - .property("datasetlifecycle.publishable") - .and.equal(false); - - datasetLiveCycle1 = res.body.datasetlifecycle; + res.body.should.not.have.property("id"); + res.body.should.have.property("message").and.be.equal("Job parameters need to be defined."); }); }); - it("0080: Check if dataset 2 was updated by job request", async () => { + + it("0070: Add a new job as a user from ADMIN_GROUPS for himself/herself in '#all' configuration", async () => { + const newDataset = { + ...jobAll, + ownerUser: "admin", + ownerGroup: "admin", + jobParams: { + ...jobAll.jobParams, + datasetIds: [datasetPid1], + }, + }; + return request(appUrl) - .get("/api/v3/Datasets/" + pid2) + .post("/api/v3/Jobs") + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.SuccessfulGetStatusCode) + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.body.should.have.nested - .property("datasetlifecycle.archivable") - .and.equal(false); - res.body.should.have.nested - .property("datasetlifecycle.retrievable") - .and.equal(false); - res.body.should.have.nested - .property("datasetlifecycle.archiveStatusMessage") - .and.equal("scheduledForArchiving"); - res.body.should.have.nested - .property("datasetlifecycle.publishable") - .and.equal(false); - datasetLiveCycle2 = res.body.datasetlifecycle; + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("admin"); + res.body.should.have.property("ownerUser").and.be.equal("admin"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobId1 = res.body["id"]; + encodedJobId1 = encodeURIComponent(jobId1); }); }); - it("0090: Create retrieve job request on same dataset, which should fail as well because not yet retrievable", async () => { + it("0080: Add a new job as a user from ADMIN_GROUPS for another user in '#all' configuration", async () => { + const newDataset = { + ...jobAll, + ownerUser: "user1", + ownerGroup: "group1", + jobParams: { + ...jobAll.jobParams, + datasetIds: [datasetPid1], + }, + }; + return request(appUrl) .post("/api/v3/Jobs") - .send(TestData.RetrieveJob) + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.ConflictStatusCode) + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) .expect("Content-Type", /json/) - .then((res, err) => { - if (err) { - return done(err); - } - res.body.should.have.property("error"); + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.have.property("ownerUser").and.be.equal("user1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobId2 = res.body["id"]; + encodedJobId2 = encodeURIComponent(jobId2); }); }); - it("0100: Send an update status to dataset 1, simulating the archive system response", async () => { + it("0090: Add a new job as a user from ADMIN_GROUPS for undefined user from another group user in '#all' configuration", async () => { + const newDataset = { + ...jobAll, + ownerGroup: "group1", + jobParams: { + ...jobAll.jobParams, + datasetIds: [datasetPid1], + }, + }; + return request(appUrl) - .patch("/api/v3/Datasets/" + pid1) - .send({ - datasetlifecycle: { - ...datasetLiveCycle1, - retrievable: true, - archiveStatusMessage: "datasetOnArchiveDisk", - }, - }) + .post("/api/v3/Jobs") + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.SuccessfulPatchStatusCode) + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.body.should.have.nested - .property("datasetlifecycle.retrievable") - .and.equal(true); - res.body.should.have.nested - .property("datasetlifecycle.publishable") - .and.equal(false); + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobId3 = res.body["id"]; + encodedJobId3 = encodeURIComponent(jobId3); }); }); - it("0110: Send an update status to dataset 2, simulating the archive system response", async () => { + + it("0100: Add a new job as a user from ADMIN_GROUPS for anonymous user in '#all' configuration", async () => { + const newDataset = { + ...jobAll, + jobParams: { + ...jobAll.jobParams, + datasetIds: [datasetPid1], + }, + }; + return request(appUrl) - .patch("/api/v3/Datasets/" + pid2) - .send({ - datasetlifecycle: { - ...datasetLiveCycle2, - retrievable: true, - archiveStatusMessage: "datasetOnArchiveDisk", - }, - }) + .post("/api/v3/Jobs") + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.SuccessfulPatchStatusCode) + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.body.should.have.nested - .property("datasetlifecycle.retrievable") - .and.equal(true); - res.body.should.have.nested - .property("datasetlifecycle.publishable") - .and.equal(false); + res.body.should.have.property("type").and.be.string; + res.body.should.not.have.property("ownerGroup"); + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobId6 = res.body["id"]; + encodedJobId6 = encodeURIComponent(jobId6); }); }); - // change policy to suppress emails - it("0120: Disable notification by email", async () => { + it("0110: Add a new job as a user from CREATE_JOB_GROUPS for himself/herself in '#all' configuration", async () => { + const newDataset = { + ...jobAll, + ownerUser: "user1", + ownerGroup: "group1", + jobParams: { + ...jobAll.jobParams, + datasetIds: [datasetPid1], + }, + }; + return request(appUrl) - .post("/api/v3/Policies/updateWhere") - .send({ - ownerGroupList: TestData.RawCorrect.ownerGroup, - data: { - archiveEmailNotification: false, - retrieveEmailNotification: false, - }, - }) + .post("/api/v3/Jobs") + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .set("Content-Type", "application/x-www-form-urlencoded") - .expect(TestData.SuccessfulPostStatusCode) + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) .then((res) => { - console.log("Result policy update:", res.body); - //res.body.not.equal({}); + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.have.property("ownerUser").and.be.equal("user1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); }); }); - it("0130: Adds a new archive job request for same data which should fail", async () => { + it("0120: Add a new job as a user from CREATE_JOB_GROUPS for his/her group in '#all' configuration", async () => { + const newDataset = { + ...jobAll, + ownerGroup: "group1", + jobParams: { + ...jobAll.jobParams, + datasetIds: [datasetPid1], + }, + }; + return request(appUrl) .post("/api/v3/Jobs") - .send(TestData.ArchiveJob) + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.ConflictStatusCode) + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.EntryCreatedStatusCode) .expect("Content-Type", /json/) - .then((res, err) => { - if (err) { - return done(err); - } - res.body.should.have.property("error"); + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.have.property("ownerUser").and.be.equal("user1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); }); }); - it("0140: Send an update status to the archive job request, signal successful archiving", async () => { - return request(appUrl) - .patch("/api/v3/Jobs/" + archiveJobId) - .send({ - jobStatusMessage: "finishedSuccessful", - jobResultObject: { - status: "okay", - message: "Archive job was finished successfully", - }, - }) - .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) - .expect(TestData.SuccessfulPatchStatusCode) - .expect("Content-Type", /json/); - }); + it("0130: Add a new job as a user from CREATE_JOB_GROUPS for another user in '#all' configuration, which should fail as bad request", async () => { + const newDataset = { + ...jobAll, + ownerUser: "user5.1", + ownerGroup: "group5", + jobParams: { + ...jobAll.jobParams, + datasetIds: [datasetPid1], + }, + }; - it("0150: Adds a new retrieve job request on same dataset, which should succeed now", async () => { return request(appUrl) .post("/api/v3/Jobs") - .send(TestData.RetrieveJob) + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.EntryCreatedStatusCode) + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.BadRequestStatusCode) .expect("Content-Type", /json/) - .then((res, err) => { - if (err) { - return done(err); - } - res.body.should.have.property("id"); - retrieveJobId = res.body["id"]; + .then((res) => { + res.body.should.not.have.property("id"); + res.body.should.have.property("message").and.be.equal("Invalid new job. User owning the job should match user logged in."); }); }); - it("0160: Read contents of dataset 1 after retrieve job and make sure that still retrievable", async () => { + it("0140: Add a new job as a user from CREATE_JOB_GROUPS for another group in '#all' configuration, which should fail as bad request", async () => { + const newDataset = { + ...jobAll, + ownerGroup: "group5", + jobParams: { + ...jobAll.jobParams, + datasetIds: [datasetPid1], + }, + }; + return request(appUrl) - .get("/api/v3/Datasets/" + pid1) + .post("/api/v3/Jobs") + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.SuccessfulGetStatusCode) + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.BadRequestStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.body.should.have.nested - .property("datasetlifecycle.retrievable") - .and.equal(true); + res.body.should.not.have.property("id"); + res.body.should.have.property("message").and.be.equal("Invalid new job. User needs to belong to job owner group."); }); }); - it("0170: Send an update status to the dataset", async () => { + it("0150: Add a new job as a user from CREATE_JOB_GROUPS for anonymous user in '#all' configuration, which should fail as bad request", async () => { + const newDataset = { + ...jobAll, + jobParams: { + ...jobAll.jobParams, + datasetIds: [datasetPid1], + }, + }; + return request(appUrl) - .patch("/api/v3/Datasets/" + pid1) - .send({ - datasetlifecycle: { - ...datasetLiveCycle1, - retrieveReturnMessage: { - text: "Some dummy retrieve message", - }, - }, - }) + .post("/api/v3/Jobs") + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.SuccessfulPatchStatusCode) + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.BadRequestStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.body.should.have.nested.property( - "datasetlifecycle.retrieveReturnMessage", - ); + res.body.should.not.have.property("id"); + res.body.should.have.property("message").and.be.equal("Invalid new job. Owner group should be specified."); }); }); - it("0180: Send an update status to the dataset, simulating the archive system response of finished job with partial failure", async () => { + it("0160: Add a new job as a normal user for himself/herself in '#all' configuration", async () => { + const newDataset = { + ...jobAll, + ownerUser: "user5.1", + ownerGroup: "group5", + jobParams: { + ...jobAll.jobParams, + datasetIds: [datasetPid2], + }, + }; + return request(appUrl) - .patch("/api/v3/Datasets/" + pid1) - .send({ - datasetlifecycle: { - ...datasetLiveCycle1, - retrievable: true, - archiveStatusMessage: "datasetOnArchiveDisk", - }, - }) + .post("/api/v3/Jobs") + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.SuccessfulPatchStatusCode) + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.EntryCreatedStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.body.should.have.nested - .property("datasetlifecycle.retrievable") - .and.equal(true); - res.body.should.have.nested - .property("datasetlifecycle.publishable") - .and.equal(false); + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group5"); + res.body.should.have.property("ownerUser").and.be.equal("user5.1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobId4 = res.body["id"]; + encodedJobId4 = encodeURIComponent(jobId4); }); }); - it("0190: Send an update status message to the Job", async () => { + it("0170:Add a new job as a normal user for his/her group in '#all' configuration", async () => { + const newDataset = { + ...jobAll, + ownerGroup: "group5", + jobParams: { + ...jobAll.jobParams, + datasetIds: [datasetPid1], + }, + }; + return request(appUrl) - .patch("/api/v3/Jobs/" + retrieveJobId) - .send({ - jobStatusMessage: "finishedUnsuccessful", - jobResultObject: { - status: "bad", - message: "System A failed", - }, - }) + .post("/api/v3/Jobs") + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.SuccessfulPatchStatusCode) + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.EntryCreatedStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.body.should.have.property("jobResultObject"); + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group5"); + res.body.should.have.property("ownerUser").and.be.equal("user5.1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobId5 = res.body["id"]; + encodedJobId5 = encodeURIComponent(jobId5); }); }); - it("0200: Send an update status to the datasets, simulating the archive system response of successful job", async () => { - await request(appUrl) - .patch("/api/v3/Datasets/" + pid1) - .send({ - datasetlifecycle: { - ...datasetLiveCycle1, - retrievable: true, - archiveStatusMessage: "datasetOnArchiveDisk", - }, - }) + it("0180: Add a new job as a normal user for another user in '#all' configuration, which should fail as bad request", async () => { + const newDataset = { + ...jobAll, + ownerUser: "user1", + ownerGroup: "group1", + jobParams: { + ...jobAll.jobParams, + datasetIds: [datasetPid1], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.SuccessfulPatchStatusCode) + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.BadRequestStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.body.should.have.nested - .property("datasetlifecycle.retrievable") - .and.equal(true); + res.body.should.not.have.property("id"); + res.body.should.have.property("message").and.be.equal("Invalid new job. User owning the job should match user logged in."); }); + }); + + it("0190: Add a new job as a normal user for another group in '#all' configuration, which should fail as bad request", async () => { + const newDataset = { + ...jobAll, + ownerGroup: "group1", + jobParams: { + ...jobAll.jobParams, + datasetIds: [datasetPid1], + }, + }; return request(appUrl) - .patch("/api/v3/Datasets/" + pid2) - .send({ - datasetlifecycle: { - ...datasetLiveCycle2, - retrievable: true, - archiveStatusMessage: "datasetOnArchiveDisk", - }, - }) + .post("/api/v3/Jobs") + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.SuccessfulPatchStatusCode) + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.BadRequestStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.body.should.have.nested - .property("datasetlifecycle.retrievable") - .and.equal(true); + res.body.should.not.have.property("id"); + res.body.should.have.property("message").and.be.equal("Invalid new job. User needs to belong to job owner group."); }); }); - it("0210: Send an update status message to the Job", async () => { + it("0200: Add a new job as a normal user for anonymous user in '#all' configuration, which should fail as bad request", async () => { + const newDataset = { + ...jobAll, + jobParams: { + ...jobAll.jobParams, + datasetIds: [datasetPid1], + }, + }; + return request(appUrl) - .patch("/api/v3/Jobs/" + retrieveJobId) - .send({ - jobStatusMessage: "finishedSuccessful", - jobResultObject: { - status: "okay", - message: "Job archiving worked", - }, - }) + .post("/api/v3/Jobs") + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.SuccessfulPatchStatusCode) + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.BadRequestStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.body.should.have.property("jobStatusMessage").and.be.string; - }); - }); - - // NOTE: Missing endpoint!!! /api/v3/Jobs/update?where. Do we need one??? - // it("Bulk update Job status prepare to trigger sending email mechanism", async () => { - // const filter = { - // id: { - // inq: [archiveJobId, retrieveJobId], - // }, - // }; - // return request(appUrl) - // .post("/api/v3/Jobs/update?where=" + JSON.stringify(filter)) - // .send({ - // jobStatusMessage: "test", - // }) - // .set("Accept", "application/json") - // .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) - // .expect(200) - // .expect("Content-Type", /json/) - // .then((res) => { - // res.body.should.have.property("count").and.equal(2); - // return; - // }); - // }); - - // NOTE: Missing endpoint!!! /api/v3/Jobs/update?where. Do we need one??? - // it("Bulk update Job status, should send out email", async () => { - // var filter = { - // id: { - // inq: [archiveJobId, retrieveJobId], - // }, - // }; - // return request(appUrl) - // .post("/api/v3/Jobs/update?where=" + JSON.stringify(filter)) - // .send({ - // jobStatusMessage: "finishedSuccessful", - // }) - // .set("Accept", "application/json") - // .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) - // .expect(200) - // .expect("Content-Type", /json/) - // .then((res) => { - // res.body.should.have.property("count").and.equal(2); - // //setTimeout(done, 3000); - // return; - // }); - // }); - - it("0220: adds a new origDatablock", async () => { - return request(appUrl) - .post(`/api/v3/datasets/${pid1}/OrigDatablocks`) - .send(TestData.OrigDataBlockCorrect1) + res.body.should.not.have.property("id"); + res.body.should.have.property("message").and.be.equal("Invalid new job. Owner group should be specified."); + }); + }); + + it("0210: Adds a new job as unauthenticated user in '#all' configuration", async () => { + const newDataset = { + ...jobAll, + jobParams: { + ...jobAll.jobParams, + datasetIds: [datasetPid1], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .expect(TestData.EntryCreatedStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.body.should.have - .property("size") - .and.equal(TestData.OrigDataBlockCorrect1.size); - res.body.should.have.property("id").and.be.string; - origDatablockId = res.body["id"]; + res.body.should.have.property("type").and.be.string; + res.body.should.not.have.property("ownerUser"); + res.body.should.not.have.property("ownerGroup"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); }); }); - it("0230: Adds a new public job request on private datasets, which should fails", async () => { + it("0220: Adds a new job as unauthenticated user for another user in '#all' configuration, which should fail as bad request", async () => { + const newDataset = { + ...jobAll, + ownerGroup: "group1", + jobParams: { + ...jobAll.jobParams, + datasetIds: [datasetPid1], + }, + }; + return request(appUrl) .post("/api/v3/Jobs") - .send(publicJob) + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.ConflictStatusCode) + .expect(TestData.BadRequestStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.body.should.have.property("error"); + res.body.should.not.have.property("id"); + res.body.should.have.property("message").and.be.equal("Invalid new job. Unauthenticated user cannot initiate a job owned by another user."); }); }); + + it("0230: Add a new job as a user from ADMIN_GROUPS for himself/herself in '#datasetPublic' configuration with all published datasets", async () => { + const newDataset = { + ...jobDatasetPublic, + ownerUser: "admin", + ownerGroup: "admin", + jobParams: { + ...jobDatasetPublic.jobParams, + datasetIds: [datasetPid1], + }, + }; - it("0240: Set to true for one of the dataset", async () => { return request(appUrl) - .patch("/api/v3/Datasets/" + pid1) - .send({ - isPublished: true, - }) + .post("/api/v3/Jobs") + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.SuccessfulPatchStatusCode) + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.body.should.have.nested.property("isPublished").and.equal(true); + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("admin"); + res.body.should.have.property("ownerUser").and.be.equal("admin"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); }); }); - it("0250: Adds a new public job request on one public and one private dataset, which should fails", async () => { + it("0240: Add a new job as a user from ADMIN_GROUPS for himself/herself in '#datasetPublic' configuration with one unpublished dataset", async () => { + const newDataset = { + ...jobDatasetPublic, + ownerUser: "admin", + ownerGroup: "admin", + jobParams: { + ...jobDatasetPublic.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + return request(appUrl) .post("/api/v3/Jobs") - .send(publicJob) + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.ConflictStatusCode) + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.body.should.have.property("error"); + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("admin"); + res.body.should.have.property("ownerUser").and.be.equal("admin"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); }); }); - it("0260: Update isPublished to true on second dataset", async () => { + it("0250: Add a new job as a user from ADMIN_GROUPS for another user in '#datasetPublic' configuration with one unpublished dataset", async () => { + const newDataset = { + ...jobDatasetPublic, + ownerUser: "user1", + ownerGroup: "group1", + jobParams: { + ...jobDatasetPublic.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + return request(appUrl) - .patch("/api/v3/Datasets/" + pid2) - .send({ - isPublished: true, - }) + .post("/api/v3/Jobs") + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.SuccessfulPatchStatusCode) + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) .expect("Content-Type", /json/) .then((res) => { - res.body.should.have.nested.property("isPublished").and.equal(true); + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.have.property("ownerUser").and.be.equal("user1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); }); }); - it("0270: Adds a new public job request without authentication", async () => { + it("0260: Add a new job as a user from ADMIN_GROUPS for another group in '#datasetPublic' configuration with one unpublished dataset", async () => { + const newDataset = { + ...jobDatasetPublic, + ownerGroup: "group1", + jobParams: { + ...jobDatasetPublic.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + return request(appUrl) .post("/api/v3/Jobs") - .send(publicJob) + .send(newDataset) .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) .expect(TestData.EntryCreatedStatusCode) .expect("Content-Type", /json/) .then((res) => { res.body.should.have.property("type").and.be.string; - publicJobIds.push(res.body["id"]); + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); }); }); - it("0280: Adds a new public job request with authentication", async () => { + it("0270: Add a new job as a user from ADMIN_GROUPS for anonymous user in '#datasetPublic' configuration with one unpublished dataset", async () => { + const newDataset = { + ...jobDatasetPublic, + jobParams: { + ...jobDatasetPublic.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + return request(appUrl) .post("/api/v3/Jobs") - .send(publicJob) + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) .expect(TestData.EntryCreatedStatusCode) .expect("Content-Type", /json/) .then((res) => { res.body.should.have.property("type").and.be.string; - publicJobIds.push(res.body["id"]); - }); - }); - - it("0290: Send an update status to the public job request, signal finished job with partial failure", async () => { - return request(appUrl) - .patch("/api/v3/Jobs/" + publicJobIds[0]) - .send({ - jobStatusMessage: "finishedUnsuccessful", - jobResultObject: { - good: [ - { - pid: decodeURIComponent(pid1), - downloadLink: "Globus link", - }, - ], - bad: [ - { - pid: decodeURIComponent(pid2), - downloadLink: "Globus link", - availableFiles: [ - { - file: "N1039-1.tif", - reason: "ok", - }, - { - file: "N1039-2.tif", - reason: "ok", - }, - ], - unavailableFiles: [ - { - file: "N1039-3.tif", - reason: "no space in destination", - }, - ], - }, - ], - }, - }) - .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) - .expect(TestData.SuccessfulPatchStatusCode) - .expect("Content-Type", /json/); + res.body.should.not.have.property("ownerGroup"); + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + }); }); - it("0300: Adds a new public job request to download some selected files", async () => { - publicJob.datasetList[0].files = ["N1039-1.tif", "N1039-2.tif"]; + it("0280: Add a new job as a user from CREATE_JOB_GROUPS for himself/herself in '#datasetPublic' configuration with all published datasets", async () => { + const newDataset = { + ...jobDatasetPublic, + ownerUser: "user1", + ownerGroup: "group1", + jobParams: { + ...jobDatasetPublic.jobParams, + datasetIds: [datasetPid1], + }, + }; + return request(appUrl) .post("/api/v3/Jobs") - .send(publicJob) + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) + .set({ Authorization: `Bearer ${accessTokenUser1}` }) .expect(TestData.EntryCreatedStatusCode) .expect("Content-Type", /json/) .then((res) => { - //reset - publicJob.datasetList[0].files = []; - res.body.should.have.property("type").and.be.string; - publicJobIds.push(res.body["id"]); + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.have.property("ownerUser").and.be.equal("user1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); }); }); + + it("0290: Add a new job as a user from CREATE_JOB_GROUPS for himself/herself in '#datasetPublic' configuration with one unpublished dataset", async () => { + const newDataset = { + ...jobDatasetPublic, + ownerUser: "user1", + ownerGroup: "group1", + jobParams: { + ...jobDatasetPublic.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; - it("0310: Send an update status to the public job request, signal successful job", async () => { return request(appUrl) - .patch("/api/v3/Jobs/" + publicJobIds[1]) - .send({ - jobStatusMessage: "finishedSuccessful", - jobResultObject: { - good: [ - { - pid: pid1, - downloadLink: "Globus link 1", - }, - { - pid: pid2, - downloadLink: "Globus link 2", - }, - ], - bad: [], - }, - }) + .post("/api/v3/Jobs") + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) - .expect(TestData.SuccessfulPatchStatusCode) - .expect("Content-Type", /json/); + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.have.property("ownerUser").and.be.equal("user1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + }); }); - // NOTE: We don't have put endpoint on the jobs here, only patch. - // Patch without id is returning 404 nor found. Maybe this will be valid one if we need and add put endpoint later? - // it("Add new job using put, which should fails. Ensure that adding new job without authentication using put is not possible ", async () => { - // return request(appUrl) - // .put("/api/v3/Jobs/") - // .send(testPublicJob) - // .set("Accept", "application/json") - // .expect(401) - // .expect("Content-Type", /json/); - // }); + it("0300: Add a new job as a normal user himself/herself in '#datasetPublic' configuration with all published datasets", async () => { + const newDataset = { + ...jobDatasetPublic, + ownerUser: "user5.1", + ownerGroup: "group5", + jobParams: { + ...jobDatasetPublic.jobParams, + datasetIds: [datasetPid1,], + }, + }; - it("0320: Adds a new public job request with to download some selected files that dont exist, which should fail", async () => { - publicJob.datasetList[0].files = ["N1039-1.tif", "N1039-101.tif"]; return request(appUrl) .post("/api/v3/Jobs") - .send(publicJob) + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) - .expect(TestData.BadRequestStatusCode) + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.EntryCreatedStatusCode) .expect("Content-Type", /json/) .then((res) => { - //reset - publicJob.datasetList[0].files = []; - - res.should.have.property("error").and.be.string; + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group5"); + res.body.should.have.property("ownerUser").and.be.equal("user5.1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); }); }); + + it("0310: Add a new job as a normal user himself/herself in '#datasetPublic' configuration with one unpublished dataset, which should fail ad forbidden", async () => { + const newDataset = { + ...jobDatasetPublic, + ownerUser: "user5.1", + ownerGroup: "group5", + jobParams: { + ...jobDatasetPublic.jobParams, + datasetIds: [datasetPid1, datasetPid2, datasetPid3], + }, + }; - it("0330: should delete the archive Job", async () => { return request(appUrl) - .delete("/api/v3/Jobs/" + archiveJobId) + .post("/api/v3/Jobs") + .send(newDataset) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) - .expect(TestData.SuccessfulDeleteStatusCode) - .expect("Content-Type", /json/); + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("id"); + res.body.should.have.property("message").and.be.equal("Unauthorized to create this dataset."); + }); }); - it("0340: should delete the retrieve Job", async () => { + it("0320: Add a new job as anonymous user in '#datasetPublic' configuration with all published datasets", async () => { + const newDataset = { + ...jobDatasetPublic, + jobParams: { + ...jobDatasetPublic.jobParams, + datasetIds: [datasetPid1], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.not.have.property("ownerUser"); + res.body.should.not.have.property("ownerGroup"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + }); + }); + + it("0330: Add a new job as anonymous user in '#datasetPublic' configuration with one unpublished dataset, which should fail as forbidden", async () => { + const newDataset = { + ...jobDatasetPublic, + jobParams: { + ...jobDatasetPublic.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("id"); + res.body.should.have.property("message").and.be.equal("Unauthorized to create this dataset."); + }); + }); + + it("0340: Add a new job as a user from ADMIN_GROUPS for himself/herself in '#authenticated' configuration", async () => { + const newDataset = { + ...jobAuthenticated, + ownerUser: "admin", + ownerGroup: "admin", + jobParams: { + ...jobAuthenticated.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("admin"); + res.body.should.have.property("ownerUser").and.be.equal("admin"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + }); + }); + + it("0350: Add a new job as a user from ADMIN_GROUPS for another user in '#authenticated' configuration", async () => { + const newDataset = { + ...jobAuthenticated, + ownerUser: "user1", + ownerGroup: "group1", + jobParams: { + ...jobAuthenticated.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.have.property("ownerUser").and.be.equal("user1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + }); + }); + it("0360: Add a new job as a user from ADMIN_GROUPS for another group in '#authenticated' configuration", async () => { + const newDataset = { + ...jobAuthenticated, + ownerGroup: "group1", + jobParams: { + ...jobAuthenticated.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + }); + }); + + it("0370: Add a new job as a user from ADMIN_GROUPS for anonymous user in '#authenticated' configuration", async () => { + const newDataset = { + ...jobAuthenticated, + jobParams: { + ...jobAuthenticated.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.not.have.property("ownerGroup"); + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + }); + }); + + it("0380: Add a new job as a user from CREATE_JOB_GROUPS for himself/herself in '#authenticated' configuration", async () => { + const newDataset = { + ...jobAuthenticated, + ownerUser: "user1", + ownerGroup: "group1", + jobParams: { + ...jobAuthenticated.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.have.property("ownerUser").and.be.equal("user1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + }); + }); + + it("0390: Add a new job as a normal user for himself/herself in '#authenticated' configuration", async () => { + const newDataset = { + ...jobAuthenticated, + ownerUser: "user5.1", + ownerGroup: "group5", + jobParams: { + ...jobAuthenticated.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group5"); + res.body.should.have.property("ownerUser").and.be.equal("user5.1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + }); + }); + + it("0400: Add a new job as unauthenticated user in '#authenticated' configuration, which should fail as forbidden", async () => { + const newDataset = { + ...jobAuthenticated, + jobParams: { + ...jobAuthenticated.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("id"); + res.body.should.have.property("message").and.be.equal("Unauthorized to create this dataset."); + }); + }); + + it("0410: Add a new job as a user from ADMIN_GROUPS for himself/herself in '#datasetAccess' configuration", async () => { + const newDataset = { + ...jobDatasetAccess, + ownerUser: "admin", + ownerGroup: "admin", + jobParams: { + ...jobDatasetAccess.jobParams, + datasetIds: [datasetPid1, datasetPid3], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("admin"); + res.body.should.have.property("ownerUser").and.be.equal("admin"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdGroup1 = res.body["id"]; + encodedJobIdGroup1 = encodeURIComponent(jobIdGroup1); + }); + }); + + it("0420: Add a new job as a user from ADMIN_GROUPS for another user in '#datasetAccess' configuration", async () => { + const newDataset = { + ...jobDatasetAccess, + ownerUser: "user1", + ownerGroup: "group1", + jobParams: { + ...jobDatasetAccess.jobParams, + datasetIds: [datasetPid1, datasetPid2, datasetPid3], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.have.property("ownerUser").and.be.equal("user1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdGroup2 = res.body["id"]; + encodedJobIdGroup2 = encodeURIComponent(jobIdGroup2); + }); + }); + + it("0430: Add a new job as a user from ADMIN_GROUPS for another group in '#datasetAccess' configuration", async () => { + const newDataset = { + ...jobDatasetAccess, + ownerGroup: "group1", + jobParams: { + ...jobDatasetAccess.jobParams, + datasetIds: [datasetPid1, datasetPid2, datasetPid3], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdGroup3 = res.body["id"]; + encodedJobIdGroup3 = encodeURIComponent(jobIdGroup3); + }); + }); + + it("0435: Add a new job as a user from ADMIN_GROUPS for another group in '#datasetAccess' configuration", async () => { + const newDataset = { + ...jobDatasetAccess, + ownerGroup: "group5", + jobParams: { + ...jobDatasetAccess.jobParams, + datasetIds: [datasetPid1, datasetPid2, datasetPid3], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group5"); + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdGroup5 = res.body["id"]; + encodedJobIdGroup5 = encodeURIComponent(jobIdGroup5); + }); + }); + + it("0440: Add a new job as a user from ADMIN_GROUPS for anonymous user in '#datasetAccess' configuration", async () => { + const newDataset = { + ...jobDatasetAccess, + jobParams: { + ...jobDatasetAccess.jobParams, + datasetIds: [datasetPid1, datasetPid3], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.not.have.property("ownerGroup"); + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdGroup6 = res.body["id"]; + encodedJobIdGroup6 = encodeURIComponent(jobIdGroup6); + }); + }); + + it("0450: Add a new job as a user from CREATE_JOB_GROUPS for himself/herself in '#datasetAccess' configuration with access to datasets", async () => { + const newDataset = { + ...jobDatasetAccess, + ownerUser: "user1", + ownerGroup: "group1", + jobParams: { + ...jobDatasetAccess.jobParams, + datasetIds: [datasetPid1, datasetPid3], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.have.property("ownerUser").and.be.equal("user1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + }); + }); + + it("0460: Add a new job as a user from CREATE_JOB_GROUPS for himself/herself in '#datasetAccess' configuration with no access to datasets", async () => { + const newDataset = { + ...jobDatasetAccess, + ownerUser: "user1", + ownerGroup: "group1", + jobParams: { + ...jobDatasetAccess.jobParams, + datasetIds: [datasetPid1, datasetPid2, datasetPid3], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.have.property("ownerUser").and.be.equal("user1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + }); + }); + + it("0470: Adds a new job as user1 for user5.1 ownerUser and group5 ownerGroup for #datasetAccess, which should fail", async () => { + const newDataset = { + ...jobDatasetAccess, + ownerUser: "user5.1", + ownerGroup: "group5", + jobParams: { + ...jobDatasetAccess.jobParams, + datasetIds: [datasetPid1, datasetPid2, datasetPid3], + }, + }; + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.BadRequestStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("id"); + res.body.should.have.property("message").and.be.equal("Invalid new job. User owning the job should match user logged in."); + }); + }); + + it("0480: Add a new job as a normal user for himself/herself in '#datasetAccess' configuration with access to datasets", async () => { + const newDataset = { + ...jobDatasetAccess, + ownerUser: "user5.1", + ownerGroup: "group5", + jobParams: { + ...jobDatasetAccess.jobParams, + datasetIds: [datasetPid1, datasetPid3], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group5"); + res.body.should.have.property("ownerUser").and.be.equal("user5.1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdGroup4 = res.body["id"]; + encodedJobIdGroup4 = encodeURIComponent(jobIdGroup4); + }); + }); + + it("0490: Add a new job as a normal user for himself/herself in '#datasetAccess' configuration with no access to datasets, which should fail as forbidden", async () => { + const newDataset = { + ...jobDatasetAccess, + ownerUser: "user5.1", + ownerGroup: "group5", + jobParams: { + ...jobDatasetAccess.jobParams, + datasetIds: [datasetPid1, datasetPid2, datasetPid3], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("id"); + res.body.should.have.property("message").and.be.equal("Unauthorized to create this dataset."); + }); + }); + + it("0500: Add a new job as a user from ADMIN_GROUPS for himself/herself in '#datasetOwner' configuration", async () => { + const newDataset = { + ...jobDatasetOwner, + ownerUser: "admin", + ownerGroup: "admin", + jobParams: { + ...jobDatasetOwner.jobParams, + datasetIds: [datasetPid1], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("admin"); + res.body.should.have.property("ownerUser").and.be.equal("admin"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdUser1 = res.body["id"]; + encodedJobIdUser1 = encodeURIComponent(jobIdUser1); + }); + }); + + it("0510: Add a new job as a user from ADMIN_GROUPS for himself/herself in '#datasetOwner' configuration", async () => { + const newDataset = { + ...jobDatasetOwner, + ownerUser: "admin", + ownerGroup: "admin", + jobParams: { + ...jobDatasetOwner.jobParams, + datasetIds: [datasetPid1, datasetPid2, datasetPid3], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("admin"); + res.body.should.have.property("ownerUser").and.be.equal("admin"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + }); + }); + + it("0520: Add a new job as a user from ADMIN_GROUPS for another user in '#datasetOwner' configuration", async () => { + const newDataset = { + ...jobDatasetOwner, + ownerUser: "user1", + ownerGroup: "group1", + jobParams: { + ...jobDatasetOwner.jobParams, + datasetIds: [datasetPid1, datasetPid2, datasetPid3], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.have.property("ownerUser").and.be.equal("user1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdUser2 = res.body["id"]; + encodedJobIdUser2 = encodeURIComponent(jobIdUser2); + }); + }); + + it("0530: Add a new job as a user from ADMIN_GROUPS for another group in '#datasetOwner' configuration", async () => { + const newDataset = { + ...jobDatasetOwner, + ownerGroup: "group1", + jobParams: { + ...jobDatasetOwner.jobParams, + datasetIds: [datasetPid1, datasetPid2, datasetPid3], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdUser3 = res.body["id"]; + encodedJobIdUser3 = encodeURIComponent(jobIdUser3); + }); + }); + + it("0535: Add a new job as a user from ADMIN_GROUPS for another group in '#datasetOwner' configuration", async () => { + const newDataset = { + ...jobDatasetOwner, + ownerGroup: "group5", + jobParams: { + ...jobDatasetOwner.jobParams, + datasetIds: [datasetPid1, datasetPid2, datasetPid3], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group5"); + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdUser5 = res.body["id"]; + encodedJobIdUser5 = encodeURIComponent(jobIdUser5); + }); + }); + + it("0540: Add a new job as a user from ADMIN_GROUPS for anonymous user in '#datasetOwner' configuration", async () => { + const newDataset = { + ...jobDatasetOwner, + jobParams: { + ...jobDatasetOwner.jobParams, + datasetIds: [datasetPid1, datasetPid2, datasetPid3], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.not.have.property("ownerGroup"); + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdUser6 = res.body["id"]; + encodedJobIdUser6 = encodeURIComponent(jobIdUser6); + }); + }); + + it("0550: Add a new job as a user from CREATE_JOB_GROUPS for himself/herself in '#datasetOwner' configuration with datasets owned by his/her group", async () => { + const newDataset = { + ...jobDatasetOwner, + ownerUser: "user1", + ownerGroup: "group1", + jobParams: { + ...jobDatasetOwner.jobParams, + datasetIds: [datasetPid1], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.have.property("ownerUser").and.be.equal("user1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + }); + }); + + it("0560: Add a new job as a user from CREATE_JOB_GROUPS for himself/herself in '#datasetOwner' configuration with datasets owned by his/her group", async () => { + const newDataset = { + ...jobDatasetOwner, + ownerUser: "user1", + ownerGroup: "group1", + jobParams: { + ...jobDatasetOwner.jobParams, + datasetIds: [datasetPid1, datasetPid3], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.have.property("ownerUser").and.be.equal("user1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + }); + }); + + it("0570: Add a new job as a normal user for himself/herself in '#datasetOwner' configuration with datasets owned by his/her group", async () => { + const newDataset = { + ...jobDatasetOwner, + ownerUser: "user5.1", + ownerGroup: "group5", + jobParams: { + ...jobDatasetOwner.jobParams, + datasetIds: [datasetPid3], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group5"); + res.body.should.have.property("ownerUser").and.be.equal("user5.1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdUser4 = res.body["id"]; + encodedJobIdUser4 = encodeURIComponent(jobIdUser4); + }); + }); + + it("0580: Add a new job as a normal user for himself/herself in '#datasetOwner' configuration with datasets not owned by his/her group, which should fail as forbidden", async () => { + const newDataset = { + ...jobDatasetOwner, + ownerUser: "user5.1", + ownerGroup: "group5", + jobParams: { + ...jobDatasetOwner.jobParams, + datasetIds: [datasetPid1], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("id"); + res.body.should.have.property("message").and.be.equal("Unauthorized to create this dataset."); + }); + }); + + it("0590: Add a new job as a user from ADMIN_GROUPS for himself/herself in '#USER5.1' configuration", async () => { + const newDataset = { + ...jobUser51, + ownerUser: "admin", + ownerGroup: "admin", + jobParams: { + ...jobUser51.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("admin"); + res.body.should.have.property("ownerUser").and.be.equal("admin"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdUserSpec1 = res.body["id"]; + encodedJobIdUserSpec1 = encodeURIComponent(jobIdUserSpec1); + }); + }); + + it("0600: Add a new job as a user from ADMIN_GROUPS for another user in '#USER5.1' configuration", async () => { + const newDataset = { + ...jobUser51, + ownerUser: "user1", + ownerGroup: "group1", + jobParams: { + ...jobUser51.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.have.property("ownerUser").and.be.equal("user1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdUserSpec2 = res.body["id"]; + encodedJobIdUserSpec2 = encodeURIComponent(jobIdUserSpec2); + }); + }); + + it("0610: Add a new job as a user from ADMIN_GROUPS for another group in '#USER5.1' configuration", async () => { + const newDataset = { + ...jobUser51, + ownerGroup: "group1", + jobParams: { + ...jobUser51.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdUserSpec3 = res.body["id"]; + encodedJobIdUserSpec3 = encodeURIComponent(jobIdUserSpec3); + }); + }); + + it("0615: Add a new job as a user from ADMIN_GROUPS for another group in '#USER5.1' configuration", async () => { + const newDataset = { + ...jobUser51, + ownerGroup: "group5", + jobParams: { + ...jobUser51.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group5"); + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdUserSpec5 = res.body["id"]; + encodedJobIdUserSpec5 = encodeURIComponent(jobIdUserSpec5); + }); + }); + + it("0616: Add a new job as a user from ADMIN_GROUPS for another user in '#USER5.1' configuration", async () => { + const newDataset = { + ...jobUser51, + ownerUser: "user5.2", + ownerGroup: "group5", + jobParams: { + ...jobUser51.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group5"); + res.body.should.have.property("ownerUser").and.be.equal("user5.2"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdUserSpec7 = res.body["id"]; + encodedJobIdUserSpec7 = encodeURIComponent(jobIdUserSpec7); + }); + }); + + + it("0620: Add a new job as a user from ADMIN_GROUPS for anonymous user in '#USER5.1' configuration", async () => { + const newDataset = { + ...jobUser51, + jobParams: { + ...jobUser51.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.not.have.property("ownerGroup"); + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdUserSpec6 = res.body["id"]; + encodedJobIdUserSpec6 = encodeURIComponent(jobIdUserSpec6); + }); + }); + + it("0630: Add a new job as a user from CREATE_JOB_GROUPS for himself/herself user in '#USER5.1' configuration", async () => { + const newDataset = { + ...jobUser51, + ownerUser: "user1", + ownerGroup: "group1", + jobParams: { + ...jobUser51.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.have.property("ownerUser").and.be.equal("user1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + }); + }); + + it("0640: Add a new job as a user from CREATE_JOB_GROUPS for user5.1 in '#USER5.1' configuration, which should fail as bad request", async () => { + const newDataset = { + ...jobUser51, + ownerUser: "user5.1", + ownerGroup: "group5", + jobParams: { + ...jobUser51.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.BadRequestStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("id"); + res.body.should.have.property("message").and.be.equal("Invalid new job. User owning the job should match user logged in."); + }); + }); + + it("0650: Adds a new job as user5.1 himself/herself in '#USER5.1' configuration", async () => { + const newDataset = { + ...jobUser51, + ownerUser: "user5.1", + ownerGroup: "group5", + jobParams: { + ...jobUser51.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group5"); + res.body.should.have.property("ownerUser").and.be.equal("user5.1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdUserSpec4 = res.body["id"]; + encodedJobIdUserSpec4 = encodeURIComponent(jobIdUserSpec4); + }); + }); + + it("0660: Adds a new job as user5.1 for no ownerUser and group5 ownerGroup in #USER5.1 configuration", async () => { + const newDataset = { + ...jobUser51, + ownerGroup: "group5", + jobParams: { + ...jobUser51.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group5"); + res.body.should.have.property("ownerUser").and.be.equal("user5.1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + }); + }); + + it("0670: Adds a new job as user5.2 for himself/herself in #USER5.1, which should fail as forbidden", async () => { + const newDataset = { + ...jobUser51, + ownerUser: "user5.2", + ownerGroup: "group5", + jobParams: { + ...jobUser51.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser52}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("id"); + res.body.should.have.property("message").and.be.equal("Unauthorized to create this dataset."); + }); + }); + + it("0680: Add a new job as a user from ADMIN_GROUPS for himself/herself in '#@group5' configuration", async () => { + const newDataset = { + ...jobGroup5, + ownerUser: "admin", + ownerGroup: "admin", + jobParams: { + ...jobGroup5.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("admin"); + res.body.should.have.property("ownerUser").and.be.equal("admin"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdGroupSpec1 = res.body["id"]; + encodedJobIdGroupSpec1 = encodeURIComponent(jobIdGroupSpec1); + }); + }); + + it("0690: Add a new job as a user from ADMIN_GROUPS for another user in '#@group5' configuration", async () => { + const newDataset = { + ...jobGroup5, + ownerUser: "user1", + ownerGroup: "group1", + jobParams: { + ...jobGroup5.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.have.property("ownerUser").and.be.equal("user1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdGroupSpec2 = res.body["id"]; + encodedJobIdGroupSpec2 = encodeURIComponent(jobIdGroupSpec2); + }); + }); + + it("0700: Add a new job as a user from ADMIN_GROUPS for another group in '#@group5' configuration", async () => { + const newDataset = { + ...jobGroup5, + ownerGroup: "group1", + jobParams: { + ...jobGroup5.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdGroupSpec3 = res.body["id"]; + encodedJobIdGroupSpec3 = encodeURIComponent(jobIdGroupSpec3); + }); + }); + + it("0705: Add a new job as a user from ADMIN_GROUPS for another group in '#@group5' configuration", async () => { + const newDataset = { + ...jobGroup5, + ownerGroup: "group5", + jobParams: { + ...jobGroup5.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group5"); + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdGroupSpec5 = res.body["id"]; + encodedJobIdGroupSpec5 = encodeURIComponent(jobIdGroupSpec5); + }); + }); + + it("0706: Add a new job as a user from ADMIN_GROUPS for another user in '@group5' configuration", async () => { + const newDataset = { + ...jobGroup5, + ownerUser: "user3", + ownerGroup: "group3", + jobParams: { + ...jobGroup5.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group3"); + res.body.should.have.property("ownerUser").and.be.equal("user3"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdGroupSpec8 = res.body["id"]; + encodedJobIdGroupSpec8 = encodeURIComponent(jobIdGroupSpec8); + }); + }); + + it("0710: Add a new job as a user from ADMIN_GROUPS for anonymous user in '#@group5' configuration", async () => { + const newDataset = { + ...jobGroup5, + jobParams: { + ...jobGroup5.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.not.have.property("ownerGroup"); + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdGroupSpec6 = res.body["id"]; + encodedJobIdGroupSpec6 = encodeURIComponent(jobIdGroupSpec6); + }); + }); + + it("0720: Add a new job as a user from CREATE_JOB_GROUPS for another group in '#@group5' configuration", async () => { + const newDataset = { + ...jobGroup5, + ownerUser: "user1", + ownerGroup: "group1", + jobParams: { + ...jobGroup5.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + res.body.should.have.property("ownerUser").and.be.equal("user1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + }); + }); + + it("0730: Add a new job as a user from CREATE_JOB_GROUPS for user 5.1 in '#@group5' configuration, which should fail as bad request", async () => { + const newDataset = { + ...jobGroup5, + ownerUser: "user5.1", + ownerGroup: "group5", + jobParams: { + ...jobGroup5.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.BadRequestStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("id"); + res.body.should.have.property("message").and.be.equal("Invalid new job. User owning the job should match user logged in."); + }); + }); + + it("0740: Add a new job as a user 5.1 for himself/herself in '#@group5' configuration", async () => { + const newDataset = { + ...jobGroup5, + ownerUser: "user5.1", + ownerGroup: "group5", + jobParams: { + ...jobGroup5.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group5"); + res.body.should.have.property("ownerUser").and.be.equal("user5.1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdGroupSpec4 = res.body["id"]; + encodedJobIdGroupSpec4 = encodeURIComponent(jobIdGroupSpec4); + }); + }); + + it("0750: Add a new job as a user 5.1 for another user in his/her group in '#@group5' configuration", async () => { + const newDataset = { + ...jobGroup5, + ownerGroup: "group5", + jobParams: { + ...jobGroup5.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group5"); + res.body.should.have.property("ownerUser").and.be.equal("user5.1"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + }); + }); + + it("0760: Add a new job as a user 5.2 for himself/herself in '#@group5' configuration", async () => { + const newDataset = { + ...jobGroup5, + ownerUser: "user5.2", + ownerGroup: "group5", + jobParams: { + ...jobGroup5.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser52}` }) + .expect(TestData.EntryCreatedStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("type").and.be.string; + res.body.should.have.property("ownerGroup").and.be.equal("group5"); + res.body.should.have.property("ownerUser").and.be.equal("user5.2"); + res.body.should.have.property("statusMessage").to.be.equal("jobCreated"); + jobIdGroupSpec7 = res.body["id"]; + encodedJobIdGroupSpec7 = encodeURIComponent(jobIdGroupSpec7); + }); + }); + + it("0770: Adds a new job as user3 for himself/herself in #@group5 configuration, which should fail as forbidden", async () => { + const newDataset = { + ...jobGroup5, + ownerUser: "user3", + ownerGroup: "group3", + jobParams: { + ...jobGroup5.jobParams, + datasetIds: [datasetPid1, datasetPid2], + }, + }; + + return request(appUrl) + .post("/api/v3/Jobs") + .send(newDataset) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser3}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("id"); + res.body.should.have.property("message").and.be.equal("Unauthorized to create this dataset."); + }); + }); + + it("0780: Adds a status update to a job as a user from ADMIN_GROUPS for his/her job in '#all' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobId1}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("0790: Adds a Status update to a job as a user from ADMIN_GROUPS for another user's job in '#all' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobId2}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("0800: Adds a Status update to a job as a user from ADMIN_GROUPS for another group's job in '#all' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobId3}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("0810: Adds a Status update to a job as a user from ADMIN_GROUPS for anonymous user's job in '#all' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobId6}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("0820: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for his/her job in '#all' configuration", async () => { + + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobId2}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("0830: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for another user's job in '#all' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobId4}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("0840: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for his/her group in '#all' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobId3}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("0850: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for another user's group in '#all' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobId5}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("0860: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for anonymous user's group in '#all' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobId6}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("0870: Adds a Status update to a job as a normal user for his/her job in '#all' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobId4}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("0880: Adds a Status update to a job as a normal user for another user's job in '#all' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobId2}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("0890: Adds a Status update to a job as a normal user for his/her group in '#all' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobId5}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("0900: Adds a Status update to a job as a normal user for another user's group in '#all' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobId3}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("0910: Adds a Status update to a job as a normal user for anonymous user's group in '#all' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobId6}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("0920: Adds a Status update to a job as unauthhenticated user for anonymous job in '#all' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobId6}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("0930: Adds a Status update to a job as unauthhenticated user for anouther group's job in '#all' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobId3}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("0940: Adds a Status update to a job as unauthhenticated user for another user's job in '#all' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobId2}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("0950: Adds a status update to a job as a user from ADMIN_GROUPS for his/her job in '#jobOwnerUser' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUser1}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("0960: Adds a Status update to a job as a user from ADMIN_GROUPS for another group's job in '#jobOwnerUser' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUser2}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("0970: Adds a Status update to a job as a user from ADMIN_GROUPS for anonymous user's job in '#jobOwnerUser' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUser3}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("0980: Adds a Status update to a job as a user from ADMIN_GROUPS for anonymous user's job in '#jobOwnerUser' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUser6}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("0990: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for his/her job in '#jobOwnerUser' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUser2}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1000: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for another user's job in '#jobOwnerUser' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUser4}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1010: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for his/her group in '#jobOwnerUser' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUser3}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1020: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for another user's group in '#jobOwnerUser' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUser5}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1030: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for anonymous user's group in '#jobOwnerUser' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUser6}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1040: Adds a Status update to a job as a normal user for his/her job in '#jobOwnerUser' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUser4}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1050: Adds a Status update to a job as a normal user for another user's job in '#jobOwnerUser' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUser2}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1060: Adds a Status update to a job as a normal user for his/her group in '#jobOwnerUser' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUser5}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1070: Adds a Status update to a job as a normal user for another user's group in '#jobOwnerUser' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUser3}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1080: Adds a Status update to a job as a normal user for anonymous user's group in '#jobOwnerUser' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUser6}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1090: Adds a Status update to a job as unauthhenticated user for anonymous user's group in '#jobOwnerUser' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUser6}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1100: Adds a status update to a job as a user from ADMIN_GROUPS for his/her job in '#jobOwnerGroup' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroup1}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1110: Adds a Status update to a job as a user from ADMIN_GROUPS for another group's job in '#jobOwnerGroup' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroup2}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1120: Adds a Status update to a job as a user from ADMIN_GROUPS for anonymous user's job in '#jobOwnerGroup' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroup3}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1130: Adds a Status update to a job as a user from ADMIN_GROUPS for anonymous user's job in '#jobOwnerGroup' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroup6}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + + it("1140: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for his/her job in '#jobOwnerGroup' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroup2}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + it("1150: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for another user's job in '#jobOwnerGroup' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroup4}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + it("1160: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for his/her group in '#jobOwnerGroup' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroup3}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + it("1170: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for another user's group in '#jobOwnerGroup' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroup5}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1180: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for anonymous user's group in '#jobOwnerGroup' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroup6}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1190: Adds a Status update to a job as a normal user for his/her job in '#jobOwnerGroup' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroup4}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1200: Adds a Status update to a job as a normal user for another user's job in '#jobOwnerGroup' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroup2}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1210: Adds a Status update to a job as a normal user for his/her group in '#jobOwnerGroup' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroup5}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1220: Adds a Status update to a job as a normal user for another user's group in '#jobOwnerGroup' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroup3}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1230: Adds a Status update to a job as a normal user for anonymous user's group in '#jobOwnerGroup' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroup6}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1240: Adds a Status update to a job as unauthhenticated user for anonymous user's group in '#jobOwnerGroup' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroup6}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1250: Adds a Status update to a job as a user from ADMIN_GROUPS for his/her job in 'USER5.1' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUserSpec1}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1260: Adds a Status update to a job as a user from ADMIN_GROUPS for another group's job in 'USER5.1' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUserSpec2}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1270: Adds a Status update to a job as a user from ADMIN_GROUPS for anonymous user's job in 'USER5.1' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUserSpec3}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1280: Adds a Status update to a job as a user from ADMIN_GROUPS for anonymous user's job in 'USER5.1' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUserSpec6}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1290: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for his/her job in 'USER5.1' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUserSpec2}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1300: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for another user's job in 'USER5.1' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUserSpec4}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1310: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for his/her group in 'USER5.1' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUserSpec3}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1320: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for another user's group in 'USER5.1' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUserSpec5}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1330: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for anonymous user's group in 'USER5.1' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUserSpec6}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1340: Adds a Status update to a job as user5.1 for his/her job in 'USER5.1' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUserSpec4}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1350: Adds a Status update to a job as user5.1 for another user's job in 'USER5.1' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUserSpec2}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1360: Adds a Status update to a job as user5.1 for his/her group in 'USER5.1' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUserSpec5}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1370: Adds a Status update to a job as user5.1 for another user's group in 'USER5.1' configuration", async () => { return request(appUrl) - .delete("/api/v3/Jobs/" + retrieveJobId) - .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) - .expect(TestData.SuccessfulDeleteStatusCode); + .patch(`/api/v3/Jobs/${encodedJobIdUserSpec4}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); }); - publicJobIds.forEach((jobId) => { - it("0350: should delete the public Job" + jobId, async () => { - return request(appUrl) - .delete("/api/v3/Jobs/" + jobId) + it("1380: Adds a Status update to a job as user5.1 for anonymous user's group in 'USER5.1' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUserSpec6}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) - .expect(TestData.SuccessfulDeleteStatusCode) + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1390: Adds a Status update to a job as user5.2 for his/her job in 'USER5.1' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUserSpec7}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser52}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1400: Adds a Status update to a job as user5.2 for user's 5.1 in same group job in 'USER5.1' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUserSpec4}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser52}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1410: Adds a Status update to a job as user5.2 for another user in his/her group job in 'USER5.1' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdUserSpec5}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser52}` }) + .expect(TestData.AccessForbiddenStatusCode) .expect("Content-Type", /json/); - }); }); - it("0360: should delete the originDataBlock", async () => { + it("1420: Adds a status update to a job as a user from ADMIN_GROUPS for his/her job in '@group5' configuration", async () => { return request(appUrl) - .delete(`/api/v3/datasets/${pid1}/OrigDatablocks/` + origDatablockId) + .patch(`/api/v3/Jobs/${encodedJobIdGroupSpec1}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1430: Adds a Status update to a job as a user from ADMIN_GROUPS for another group's job in '@group5' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroupSpec2}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) - .expect(TestData.SuccessfulDeleteStatusCode); + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1440: Adds a Status update to a job as a user from ADMIN_GROUPS for anonymous user's job in '@group5' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroupSpec3}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1450: Adds a Status update to a job as a user from ADMIN_GROUPS for anonymous user's job in '@group5' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroupSpec6}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1460: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for his/her job in '@group5' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroupSpec2}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1470: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for another user's job in '@group5' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroupSpec4}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1480: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for his/her group in '@group5' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroupSpec3}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1490: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for another user's group in '@group5' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroupSpec5}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1500: Adds a Status update to a job as a user from UPDATE_JOB_GROUPS for anonymous user's group in '@group5' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroupSpec6}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1510: Adds a Status update to a job as user5.1 for his/her job in '@group5' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroupSpec4}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1520: Adds a Status update to a job as user5.1 for another user's job in '@group5' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroupSpec2}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1530: Adds a Status update to a job as user5.1 for his/her group in '@group5' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroupSpec5}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1540: Adds a Status update to a job as user5.1 for another user's group in '@group5' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroupSpec4}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1550: Adds a Status update to a job as user5.1 for anonymous user's group in '@group5' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroupSpec6}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1560: Adds a Status update to a job as user5.2 for his/her job in '@group5' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroupSpec7}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser52}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + + it("1570: Adds a Status update to a job as user5.2 for user's 5.1 in same group job in '@group5' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroupSpec4}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser52}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1580: Adds a Status update to a job as user5.2 for another user in his/her group job in '@group5' configuration", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroupSpec5}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser52}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/); + }); + + it("1590: Adds a Status update to a job as user3 for his/her job in '@group5' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroupSpec8}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser3}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1600: Adds a Status update to a job as user3 for user's 5.1 job in '@group5' configuration, which should fail as forbidden", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/${encodedJobIdGroupSpec4}`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser3}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1610: Adds a status update to a job as a user from ADMIN_GROUPS for his/her job in '#all' configuration with non-existing jobId, which should fail as bad request", async () => { + return request(appUrl) + .patch(`/api/v3/Jobs/badJobId`) + .send({ + statusCode: "update status of a job", + statusMessage: "job finished/blocked/etc", + }) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.BadRequestStatusCode) + .expect("Content-Type", /json/); + }); + + it("1620: Access jobs as a user from ADMIN_GROUPS ", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/`) + .send({}) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulGetStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(60); + }); + }); + + it("1630: Access jobs as a user from ADMIN_GROUPS that were created by admin", async () => { + const query = { where:{ createdBy: "admin" }}; + return request(appUrl) + .get(`/api/v3/Jobs/`) + .send({}) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulGetStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(36); + }); + }); + + it("1640: Access jobs as a user from ADMIN_GROUPS that were created by User1", async () => { + const query = { where:{ createdBy: "user1" }}; + return request(appUrl) + .get(`/api/v3/Jobs/`) + .send({}) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulGetStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(11); + }); + }); + + it("1650: Access jobs as a user from ADMIN_GROUPS that were created by User5.1", async () => { + const query = { where:{ createdBy: "user5.1" }}; + return request(appUrl) + .get(`/api/v3/Jobs/`) + .send({}) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulGetStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(10); + }); + }); + + it("1660: Access jobs as a user from ADMIN_GROUPS that were created by User5.2", async () => { + const query = { where:{ createdBy: "user5.2" }}; + return request(appUrl) + .get(`/api/v3/Jobs/`) + .send({}) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulGetStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(1); + }); + }); + + it("1670: Access jobs as a user from ADMIN_GROUPS that were created by anonymous user", async () => { + const query = { where:{ createdBy: "anonymous" }}; + return request(appUrl) + .get(`/api/v3/Jobs/`) + .send({}) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulGetStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(2); + }); + }); + + it("1680: Access jobs as a user from CREATE_JOB_GROUPS ", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/`) + .send({}) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.SuccessfulGetStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(25); + }); + }); + + it("1690: Access jobs as a user from CREATE_JOB_GROUPS that were created by admin", async () => { + const query = { where:{ createdBy: "admin" }}; + return request(appUrl) + .get(`/api/v3/Jobs/`) + .send({}) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.SuccessfulGetStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(14); + }); + }); + + it("1700: Access jobs as a user from CREATE_JOB_GROUPS that were created by User1", async () => { + const query = { where:{ createdBy: "user1" }}; + return request(appUrl) + .get(`/api/v3/Jobs/`) + .send({}) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.SuccessfulGetStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(11); + }); + }); + + it("1710: Access jobs as a normal user", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/`) + .send({}) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulGetStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(10); + }); + }); + + it("1720: Access jobs as a normal user (user5.1) that were created by admin", async () => { + const query = { where:{ createdBy: "admin" }}; + return request(appUrl) + .get(`/api/v3/Jobs/`) + .send({}) + .query("filter=" + encodeURIComponent(JSON.stringify(query))) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulGetStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(0); + }); + }); + + it("1730: Access jobs as another normal user (user5.2)", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/`) + .send({}) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser52}` }) + .expect(TestData.SuccessfulGetStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(2); + }); + }); + + it("1740: Access jobs as unauthenticated user, which should be forbidden", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/`) + .send({}) + .set("Accept", "application/json") + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1750: Get admin's job as user from ADMIN_GROUP", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/${encodedJobIdUser1}`) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("ownerUser").and.be.equal("admin"); + }); + }); + + it("1760: Get user1's job as user from ADMIN_GROUP", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/${encodedJobIdUser2}`) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("ownerUser").and.be.equal("user1"); + }); + }); + + it("1770: Get group1's job as user from ADMIN_GROUP", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/${encodedJobIdUser3}`) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + }); + }); + + it("1780: Get admin's job as user from ADMIN_GROUP", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/${encodedJobIdUser6}`) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("ownerUser"); + }); + }); + + it("1790: Get admin's job as user from CREATE_JOB_GROUP, which should be forbidden", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/${encodedJobIdUser1}`) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("ownerUser"); + }); + }); + + it("1800: Get his/her own job as user from CREATE_JOB_GROUP", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/${encodedJobIdUser2}`) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("ownerUser").and.be.equal("user1"); + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + }); + }); + + it("1810: Get a job from his/her own group as user from CREATE_JOB_GROUP", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/${encodedJobIdUser3}`) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("ownerUser"); + res.body.should.have.property("ownerGroup").and.be.equal("group1"); + }); + }); + + it("1820: Get other user's job as user from CREATE_JOB_GROUP, which should be forbidden", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/${encodedJobIdUser4}`) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("ownerUser"); + }); + }); + + it("1830: Get anonymous user's job as user from CREATE_JOB_GROUP, which should be forbidden", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/${encodedJobIdUser6}`) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("ownerUser"); + }); + }); + + it("1840: Get admin's job as normal, which should be forbidden", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/${encodedJobIdUser1}`) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("ownerUser"); + }); + }); + + it("1850: Get other user's job as normal user, which should be forbidden", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/${encodedJobIdUser2}`) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("ownerUser"); + }); + }); + + it("1860: Get his/her own job as normal user", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/${encodedJobIdUser4}`) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.SuccessfulPatchStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.have.property("ownerUser").and.be.equal('user5.1'); + res.body.should.have.property("ownerGroup").and.be.equal("group5"); + }); + }); + + it("1870: Get job od another user in his/her group as normal user, which should be forbidden", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/${encodedJobIdUserSpec7}`) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("ownerUser"); + }); + }); + + it("1880: Get job from his/her own group as normal user, which should be forbidden", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/${encodedJobIdUser5}`) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("ownerUser"); + }); + }); + + it("1890: Get anonymous user's job as normal user, which should be forbidden", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/${encodedJobIdUser6}`) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("ownerUser"); + }); + }); + + it("1900: Get anonymous user's job as anonymous user, which should be forbidden", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/${encodedJobIdUser6}`) + .set("Accept", "application/json") + .expect(TestData.AccessForbiddenStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.not.have.property("ownerUser"); + }); }); - it("0370: should delete the dataset #1", async () => { + it("1910: Delete job 1 as Archive Manager", async () => { return request(appUrl) - .delete("/api/v3/Datasets/" + pid1) + .delete("/api/v3/jobs/" + encodedJobIdUser1) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) .expect(TestData.SuccessfulDeleteStatusCode) .expect("Content-Type", /json/); }); - it("0390: should delete the dataset #2", async () => { + it("1920: Delete job 1 as Admin, which should fail", async () => { + return request(appUrl) + .delete("/api/v3/jobs/" + encodedJobIdUser1) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.DeleteForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1930: Delete job 1 as CREATE_JOB_GROUPS user, which should fail", async () => { return request(appUrl) - .delete("/api/v3/Datasets/" + pid2) + .delete("/api/v3/jobs/" + encodedJobIdUser1) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .expect(TestData.DeleteForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1940: Delete job 1 as normal user, which should fail", async () => { + return request(appUrl) + .delete("/api/v3/jobs/" + encodedJobIdUser1) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenUser51}` }) + .expect(TestData.DeleteForbiddenStatusCode) + .expect("Content-Type", /json/); + }); + + it("1950: Delete job not existing in database as Archive Manager, which should fail", async () => { + return request(appUrl) + .delete("/api/v3/jobs/" + 'fakeJobId') .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) - .expect(TestData.SuccessfulDeleteStatusCode) + .expect(TestData.BadRequestStatusCode) .expect("Content-Type", /json/); }); + + it("1960: Access jobs as a user from ADMIN_GROUPS, which should be one less that before prooving that delete works.", async () => { + return request(appUrl) + .get(`/api/v3/Jobs/`) + .send({}) + .set("Accept", "application/json") + .set({ Authorization: `Bearer ${accessTokenAdmin}` }) + .expect(TestData.SuccessfulGetStatusCode) + .expect("Content-Type", /json/) + .then((res) => { + res.body.should.be.an("array").to.have.lengthOf(59); + }); + }); + }); diff --git a/test/OrigDatablockForRawDataset.js b/test/OrigDatablockForRawDataset.js index e835631fc..e7d226d62 100644 --- a/test/OrigDatablockForRawDataset.js +++ b/test/OrigDatablockForRawDataset.js @@ -19,6 +19,10 @@ var accessTokenAdminIngestor = null, origDatablockWithValidChkAlg = null; describe("1200: OrigDatablockForRawDataset: Test OrigDatablocks and their relation to raw Datasets using origdatablocks endpoint", () => { + before(() => { + db.collection("Dataset").deleteMany({}); + db.collection("OrigDatablock").deleteMany({}); + }); beforeEach((done) => { utils.getToken( appUrl, @@ -147,7 +151,7 @@ describe("1200: OrigDatablockForRawDataset: Test OrigDatablocks and their relati it("0050: adds a new origDatablock with wrong account which should fail", async () => { origDatablockData1.datasetId = datasetPid1; return request(appUrl) - .post(`/api/v3/OrigDatablocks`) + .post(`/api/v3/origDatablocks`) .send(origDatablockData1) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) @@ -158,7 +162,7 @@ describe("1200: OrigDatablockForRawDataset: Test OrigDatablocks and their relati it("0060: adds a new origDatablock with correct account (origdatablock 1)", async () => { origDatablockData1.datasetId = datasetPid1; return request(appUrl) - .post(`/api/v3/OrigDatablocks`) + .post(`/api/v3/origDatablocks`) .send(origDatablockData1) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) @@ -176,7 +180,7 @@ describe("1200: OrigDatablockForRawDataset: Test OrigDatablocks and their relati it("0070: adds a second origDatablock (origdatablock 2)", async () => { origDatablockData2.datasetId = datasetPid1; return request(appUrl) - .post(`/api/v3/OrigDatablocks`) + .post(`/api/v3/origDatablocks`) .send(origDatablockData2) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) @@ -193,7 +197,7 @@ describe("1200: OrigDatablockForRawDataset: Test OrigDatablocks and their relati it("0080: add a new origDatablock with empty chkAlg should fail", async () => { return request(appUrl) - .post(`/api/v3/OrigDatablocks`) + .post(`/api/v3/origDatablocks`) .send(origDatablockWithEmptyChkAlg) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) @@ -207,7 +211,7 @@ describe("1200: OrigDatablockForRawDataset: Test OrigDatablocks and their relati it("0090: add a new origDatablock with valid chkAlg should success (origdatablock 3)", async () => { origDatablockData3.datasetId = datasetPid2; return request(appUrl) - .post(`/api/v3/OrigDatablocks`) + .post(`/api/v3/origDatablocks`) .send(origDatablockData3) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) @@ -229,7 +233,7 @@ describe("1200: OrigDatablockForRawDataset: Test OrigDatablocks and their relati const filter = { where: { datasetId: datasetPid1 } }; return request(appUrl) - .get(`/api/v3/OrigDatablocks`) + .get(`/api/v3/origDatablocks`) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .query({ filter: JSON.stringify(filter) }) @@ -246,7 +250,7 @@ describe("1200: OrigDatablockForRawDataset: Test OrigDatablocks and their relati const filter = { where: { datasetId: datasetPid2 } }; return request(appUrl) - .get(`/api/v3/OrigDatablocks`) + .get(`/api/v3/origDatablocks`) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .query({ filter: JSON.stringify(filter) }) @@ -727,7 +731,7 @@ describe("1200: OrigDatablockForRawDataset: Test OrigDatablocks and their relati const filter = { where: { datasetId: datasetPid1 } }; return request(appUrl) - .get(`/api/v3/OrigDatablocks`) + .get(`/api/v3/origDatablocks`) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .query({ filter: JSON.stringify(filter) }) @@ -742,7 +746,7 @@ describe("1200: OrigDatablockForRawDataset: Test OrigDatablocks and their relati const filter = { where: { datasetId: datasetPid2 } }; return request(appUrl) - .get(`/api/v3/OrigDatablocks`) + .get(`/api/v3/origDatablocks`) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .query({ filter: JSON.stringify(filter) }) diff --git a/test/Policy.js b/test/Policy.js index 5aebadc68..e6b3b9fa4 100644 --- a/test/Policy.js +++ b/test/Policy.js @@ -22,6 +22,9 @@ var testdataset = { }; describe("1300: Policy: Simple Policy tests", () => { + before(() => { + db.collection("Policy").deleteMany({}); + }); beforeEach((done) => { utils.getToken( appUrl, diff --git a/test/Proposal.js b/test/Proposal.js index 65d27a832..411aa220f 100644 --- a/test/Proposal.js +++ b/test/Proposal.js @@ -12,6 +12,9 @@ let accessTokenProposalIngestor = null, attachmentId = null; describe("1500: Proposal: Simple Proposal", () => { + before(() => { + db.collection("Proposal").deleteMany({}); + }); beforeEach((done) => { utils.getToken( appUrl, diff --git a/test/ProposalAuthorization.js b/test/ProposalAuthorization.js index 16637b70f..4e4a9a200 100644 --- a/test/ProposalAuthorization.js +++ b/test/ProposalAuthorization.js @@ -5,7 +5,7 @@ const utils = require("./LoginUtils"); const { TestData } = require("./TestData"); const sandbox = require("sinon").createSandbox(); -let accessTokenProposalIngestor= null, +let accessTokenProposalIngestor = null, accessTokenArchiveManager = null, accessTokenAdminIngestor = null, accessTokenUser1 = null, @@ -40,6 +40,9 @@ const proposal3 = { }; describe("1400: ProposalAuthorization: Test access to proposal", () => { + before(() => { + db.collection("Proposal").deleteMany({}); + }); beforeEach((done) => { utils.getToken( appUrl, @@ -48,7 +51,7 @@ describe("1400: ProposalAuthorization: Test access to proposal", () => { password: TestData.Accounts["adminIngestor"]["password"], }, (tokenVal) => { - accessTokenAdminIngestor= tokenVal; + accessTokenAdminIngestor = tokenVal; utils.getToken( appUrl, @@ -78,7 +81,8 @@ describe("1400: ProposalAuthorization: Test access to proposal", () => { appUrl, { username: "archiveManager", - password: TestData.Accounts["archiveManager"]["password"], + password: + TestData.Accounts["archiveManager"]["password"], }, (tokenVal) => { accessTokenArchiveManager = tokenVal; diff --git a/test/PublishedData.js b/test/PublishedData.js index c6a110356..69531a188 100644 --- a/test/PublishedData.js +++ b/test/PublishedData.js @@ -34,6 +34,10 @@ const nonpublictestdataset = { }; describe("1600: PublishedData: Test of access to published data", () => { + before(() => { + db.collection("Dataset").deleteMany({}); + db.collection("PublishedData").deleteMany({}); + }); beforeEach((done) => { utils.getToken( appUrl, diff --git a/test/RandomizedDatasetPermissions.js b/test/RandomizedDatasetPermissions.js index 6d22c26ad..9a31f8eb2 100644 --- a/test/RandomizedDatasetPermissions.js +++ b/test/RandomizedDatasetPermissions.js @@ -185,6 +185,9 @@ async function removeAllDatasets() { } describe("1700: Randomized Datasets: permission test with bigger amount of data", async () => { + before(() => { + db.collection("Dataset").deleteMany({}); + }); beforeEach((done) => { utils.getToken( appUrl, @@ -222,7 +225,8 @@ describe("1700: Randomized Datasets: permission test with bigger amount of data" appUrl, { username: "archiveManager", - password: TestData.Accounts["archiveManager"]["password"], + password: + TestData.Accounts["archiveManager"]["password"], }, (tokenVal) => { accessTokenArchiveManager = tokenVal; diff --git a/test/RawDataset.js b/test/RawDataset.js index a4f4cff35..89a04f3dd 100644 --- a/test/RawDataset.js +++ b/test/RawDataset.js @@ -14,6 +14,10 @@ var accessTokenArchiveManager = null; var proposalId = null; describe("1900: RawDataset: Raw Datasets", () => { + before(() => { + db.collection("Dataset").deleteMany({}); + db.collection("Proposals").deleteMany({}); + }); beforeEach((done) => { utils.getToken( appUrl, diff --git a/test/RawDatasetDatablock.js b/test/RawDatasetDatablock.js index b6081a568..fae50686b 100644 --- a/test/RawDatasetDatablock.js +++ b/test/RawDatasetDatablock.js @@ -11,6 +11,9 @@ describe("1800: RawDatasetDatablock: Test Datablocks and their relation to raw D var datablockId2 = null; beforeEach((done) => { + before(() => { + db.collection("Dataset").deleteMany({}); + }); utils.getToken( appUrl, { diff --git a/test/RawDatasetOrigDatablock.js b/test/RawDatasetOrigDatablock.js index 1f7587f1c..fc46197a1 100644 --- a/test/RawDatasetOrigDatablock.js +++ b/test/RawDatasetOrigDatablock.js @@ -15,6 +15,10 @@ describe("2000: RawDatasetOrigDatablock: Test OrigDatablocks and their relation origDatablockWithValidChkAlg = null; beforeEach((done) => { + before(() => { + db.collection("Dataset").deleteMany({}); + db.collection("OrigDatablock").deleteMany({}); + }); utils.getToken( appUrl, { diff --git a/test/Sample.js b/test/Sample.js index 915871cd5..3baccdb69 100644 --- a/test/Sample.js +++ b/test/Sample.js @@ -13,6 +13,7 @@ let accessTokenAdminIngestor = null, describe("2200: Sample: Simple Sample", () => { before(() => { db.collection("Sample").deleteMany({}); + db.collection("Dataset").deleteMany({}); }); beforeEach((done) => { utils.getToken( diff --git a/test/SampleAuthorization.js b/test/SampleAuthorization.js index 3f02fa75b..a8fcfcb25 100644 --- a/test/SampleAuthorization.js +++ b/test/SampleAuthorization.js @@ -36,6 +36,9 @@ let accessTokenAdminIngestor = null, attachmentId10 = null; describe("2250: Sample Authorization", () => { + before(() => { + db.collection("Sample").deleteMany({}); + }); beforeEach((done) => { utils.getToken( appUrl, @@ -73,7 +76,8 @@ describe("2250: Sample Authorization", () => { appUrl, { username: "archiveManager", - password: TestData.Accounts["archiveManager"]["password"], + password: + TestData.Accounts["archiveManager"]["password"], }, (tokenVal) => { accessTokenArchiveManager = tokenVal; @@ -89,7 +93,8 @@ describe("2250: Sample Authorization", () => { appUrl, { username: "user4", - password: TestData.Accounts["user4"]["password"], + password: + TestData.Accounts["user4"]["password"], }, (tokenVal) => { accessTokenUser4 = tokenVal; @@ -97,7 +102,8 @@ describe("2250: Sample Authorization", () => { appUrl, { username: "user5.1", - password: TestData.Accounts["user5.1"]["password"], + password: + TestData.Accounts["user5.1"]["password"], }, (tokenVal) => { accessTokenUser5 = tokenVal; @@ -126,7 +132,7 @@ describe("2250: Sample Authorization", () => { }; sample.description = "Sample 1"; sample.ownerGroup = "adminingestor"; - sample.accessGroups=["group5"]; + sample.accessGroups = ["group5"]; return request(appUrl) .post("/api/v3/Samples") @@ -151,7 +157,7 @@ describe("2250: Sample Authorization", () => { }; sample.description = "Sample 2"; sample.ownerGroup = "sampleingestor"; - sample.accessGroups=["group3"]; + sample.accessGroups = ["group3"]; return request(appUrl) .post("/api/v3/Samples") @@ -176,7 +182,7 @@ describe("2250: Sample Authorization", () => { }; sample.description = "Sample 3"; sample.ownerGroup = "group1"; - sample.accessGroups=["group3"]; + sample.accessGroups = ["group3"]; return request(appUrl) .post("/api/v3/Samples") @@ -199,9 +205,9 @@ describe("2250: Sample Authorization", () => { let sample = { ...TestData.SampleCorrect, }; - sample.description = "Sample 4" + sample.description = "Sample 4"; sample.ownerGroup = "group2"; - sample.accessGroups=["group4"]; + sample.accessGroups = ["group4"]; return request(appUrl) .post("/api/v3/Samples") @@ -226,8 +232,8 @@ describe("2250: Sample Authorization", () => { }; sample.description = "Sample 10 Public"; sample.ownerGroup = "nogroup"; - sample.accessGroups=[]; - sample.isPublished=true; + sample.accessGroups = []; + sample.isPublished = true; return request(appUrl) .post("/api/v3/Samples") @@ -252,7 +258,7 @@ describe("2250: Sample Authorization", () => { }; sample.description = "Sample 5"; sample.ownerGroup = "adminingestor"; - sample.accessGroups=["group5","group2"]; + sample.accessGroups = ["group5", "group2"]; return request(appUrl) .post("/api/v3/Samples") @@ -277,7 +283,7 @@ describe("2250: Sample Authorization", () => { }; sample.description = "Sample 6"; sample.ownerGroup = "sampleingestor"; - sample.accessGroups=["group1","group4"]; + sample.accessGroups = ["group1", "group4"]; return request(appUrl) .post("/api/v3/Samples") @@ -302,7 +308,7 @@ describe("2250: Sample Authorization", () => { }; sample.description = "Sample 7"; sample.ownerGroup = "group1"; - sample.accessGroups=["group2","group3"]; + sample.accessGroups = ["group2", "group3"]; return request(appUrl) .post("/api/v3/Samples") @@ -327,7 +333,7 @@ describe("2250: Sample Authorization", () => { }; sample.description = "Sample 8"; sample.ownerGroup = "group2"; - sample.accessGroups=[]; + sample.accessGroups = []; return request(appUrl) .post("/api/v3/Samples") @@ -380,7 +386,7 @@ describe("2250: Sample Authorization", () => { }; sample.description = "Sample 9"; sample.ownerGroup = "group1"; - sample.accessGroups=["group5"]; + sample.accessGroups = ["group5"]; return request(appUrl) .post("/api/v3/Samples") @@ -576,12 +582,12 @@ describe("2250: Sample Authorization", () => { .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) .expect(TestData.CreationForbiddenStatusCode); }); - + function defineAttachment(caption) { return { thumbnail: TestData.AttachmentCorrect.thumbnail, - caption: caption || TestData.AttachmentCorrect.caption - } + caption: caption || TestData.AttachmentCorrect.caption, + }; } // sample attachment @@ -600,12 +606,8 @@ describe("2250: Sample Authorization", () => { res.body.should.have .property("thumbnail") .and.equal(attachment.thumbnail); - res.body.should.have - .property("caption") - .and.equal(attachment.caption); - res.body.should.have - .property("ownerGroup") - .and.equal("adminingestor"); + res.body.should.have.property("caption").and.equal(attachment.caption); + res.body.should.have.property("ownerGroup").and.equal("adminingestor"); res.body.should.have.property("accessGroups"); res.body.should.have.property("createdBy"); res.body.should.have.property("updatedBy").and.be.string; @@ -630,12 +632,8 @@ describe("2250: Sample Authorization", () => { res.body.should.have .property("thumbnail") .and.equal(attachment.thumbnail); - res.body.should.have - .property("caption") - .and.equal(attachment.caption); - res.body.should.have - .property("ownerGroup") - .and.equal("sampleingestor"); + res.body.should.have.property("caption").and.equal(attachment.caption); + res.body.should.have.property("ownerGroup").and.equal("sampleingestor"); res.body.should.have.property("accessGroups"); res.body.should.have.property("createdBy"); res.body.should.have.property("updatedBy").and.be.string; @@ -660,12 +658,8 @@ describe("2250: Sample Authorization", () => { res.body.should.have .property("thumbnail") .and.equal(attachment.thumbnail); - res.body.should.have - .property("caption") - .and.equal(attachment.caption); - res.body.should.have - .property("ownerGroup") - .and.equal("group1"); + res.body.should.have.property("caption").and.equal(attachment.caption); + res.body.should.have.property("ownerGroup").and.equal("group1"); res.body.should.have.property("accessGroups"); res.body.should.have.property("createdBy"); res.body.should.have.property("updatedBy").and.be.string; @@ -690,12 +684,8 @@ describe("2250: Sample Authorization", () => { res.body.should.have .property("thumbnail") .and.equal(attachment.thumbnail); - res.body.should.have - .property("caption") - .and.equal(attachment.caption); - res.body.should.have - .property("ownerGroup") - .and.equal("group2"); + res.body.should.have.property("caption").and.equal(attachment.caption); + res.body.should.have.property("ownerGroup").and.equal("group2"); res.body.should.have.property("accessGroups"); res.body.should.have.property("createdBy"); res.body.should.have.property("updatedBy").and.be.string; @@ -720,12 +710,8 @@ describe("2250: Sample Authorization", () => { res.body.should.have .property("thumbnail") .and.equal(attachment.thumbnail); - res.body.should.have - .property("caption") - .and.equal(attachment.caption); - res.body.should.have - .property("ownerGroup") - .and.equal("nogroup"); + res.body.should.have.property("caption").and.equal(attachment.caption); + res.body.should.have.property("ownerGroup").and.equal("nogroup"); res.body.should.have.property("accessGroups"); res.body.should.have.property("createdBy"); res.body.should.have.property("updatedBy").and.be.string; @@ -750,12 +736,8 @@ describe("2250: Sample Authorization", () => { res.body.should.have .property("thumbnail") .and.equal(attachment.thumbnail); - res.body.should.have - .property("caption") - .and.equal(attachment.caption); - res.body.should.have - .property("ownerGroup") - .and.equal("adminingestor"); + res.body.should.have.property("caption").and.equal(attachment.caption); + res.body.should.have.property("ownerGroup").and.equal("adminingestor"); res.body.should.have.property("accessGroups"); res.body.should.have.property("createdBy"); res.body.should.have.property("updatedBy").and.be.string; @@ -780,12 +762,8 @@ describe("2250: Sample Authorization", () => { res.body.should.have .property("thumbnail") .and.equal(attachment.thumbnail); - res.body.should.have - .property("caption") - .and.equal(attachment.caption); - res.body.should.have - .property("ownerGroup") - .and.equal("sampleingestor"); + res.body.should.have.property("caption").and.equal(attachment.caption); + res.body.should.have.property("ownerGroup").and.equal("sampleingestor"); res.body.should.have.property("accessGroups"); res.body.should.have.property("createdBy"); res.body.should.have.property("updatedBy").and.be.string; @@ -810,12 +788,8 @@ describe("2250: Sample Authorization", () => { res.body.should.have .property("thumbnail") .and.equal(attachment.thumbnail); - res.body.should.have - .property("caption") - .and.equal(attachment.caption); - res.body.should.have - .property("ownerGroup") - .and.equal("group1"); + res.body.should.have.property("caption").and.equal(attachment.caption); + res.body.should.have.property("ownerGroup").and.equal("group1"); res.body.should.have.property("accessGroups"); res.body.should.have.property("createdBy"); res.body.should.have.property("updatedBy").and.be.string; @@ -840,12 +814,8 @@ describe("2250: Sample Authorization", () => { res.body.should.have .property("thumbnail") .and.equal(attachment.thumbnail); - res.body.should.have - .property("caption") - .and.equal(attachment.caption); - res.body.should.have - .property("ownerGroup") - .and.equal("group2"); + res.body.should.have.property("caption").and.equal(attachment.caption); + res.body.should.have.property("ownerGroup").and.equal("group2"); res.body.should.have.property("accessGroups"); res.body.should.have.property("createdBy"); res.body.should.have.property("updatedBy").and.be.string; @@ -892,12 +862,8 @@ describe("2250: Sample Authorization", () => { res.body.should.have .property("thumbnail") .and.equal(attachment.thumbnail); - res.body.should.have - .property("caption") - .and.equal(attachment.caption); - res.body.should.have - .property("ownerGroup") - .and.equal("group1"); + res.body.should.have.property("caption").and.equal(attachment.caption); + res.body.should.have.property("ownerGroup").and.equal("group1"); res.body.should.have.property("accessGroups"); res.body.should.have.property("createdBy"); res.body.should.have.property("updatedBy").and.be.string; @@ -933,12 +899,8 @@ describe("2250: Sample Authorization", () => { res.body.should.have .property("thumbnail") .and.equal(attachment.thumbnail); - res.body.should.have - .property("caption") - .and.equal(attachment.caption); - res.body.should.have - .property("ownerGroup") - .and.equal("group1"); + res.body.should.have.property("caption").and.equal(attachment.caption); + res.body.should.have.property("ownerGroup").and.equal("group1"); res.body.should.have.property("accessGroups"); res.body.should.have.property("createdBy"); res.body.should.have.property("updatedBy").and.be.string; @@ -963,12 +925,8 @@ describe("2250: Sample Authorization", () => { res.body.should.have .property("thumbnail") .and.equal(attachment.thumbnail); - res.body.should.have - .property("caption") - .and.equal(attachment.caption); - res.body.should.have - .property("ownerGroup") - .and.equal("group1"); + res.body.should.have.property("caption").and.equal(attachment.caption); + res.body.should.have.property("ownerGroup").and.equal("group1"); res.body.should.have.property("accessGroups"); res.body.should.have.property("createdBy"); res.body.should.have.property("updatedBy").and.be.string; @@ -977,7 +935,7 @@ describe("2250: Sample Authorization", () => { attachmentId9 = res.body["id"]; }); }); - + it("0370: adds an attachment as User 2 to sample 1, which should fail", async () => { return request(appUrl) .post("/api/v3/Samples/" + sampleId1 + "/attachments") @@ -1109,7 +1067,7 @@ describe("2250: Sample Authorization", () => { const filter = { where: { ownerGroup: "adminingestor", - } + }, }; return request(appUrl) @@ -1122,7 +1080,7 @@ describe("2250: Sample Authorization", () => { .expect("Content-Type", /json/) .then((res) => { res.body.should.be.an("array").and.to.have.length(2); - res.body.forEach( (e) => { + res.body.forEach((e) => { e.should.have.deep.property("sampleId"); e.sampleId.should.be.oneOf([sampleId1, sampleId5]); }); @@ -1133,7 +1091,7 @@ describe("2250: Sample Authorization", () => { const filter = { where: { ownerGroup: "group1", - } + }, }; return request(appUrl) @@ -1146,7 +1104,7 @@ describe("2250: Sample Authorization", () => { .expect("Content-Type", /json/) .then((res) => { res.body.should.be.an("array").and.to.have.length(3); - res.body.forEach( (e) => { + res.body.forEach((e) => { e.should.have.deep.property("sampleId"); e.sampleId.should.be.oneOf([sampleId3, sampleId7, sampleId9]); }); @@ -1169,7 +1127,7 @@ describe("2250: Sample Authorization", () => { const filter = { where: { ownerGroup: "sampleingestor", - } + }, }; return request(appUrl) @@ -1182,7 +1140,7 @@ describe("2250: Sample Authorization", () => { .expect("Content-Type", /json/) .then((res) => { res.body.should.be.an("array").and.to.have.length(2); - res.body.forEach( (e) => { + res.body.forEach((e) => { e.should.have.deep.property("sampleId"); e.sampleId.should.be.oneOf([sampleId2, sampleId6]); }); @@ -1193,7 +1151,7 @@ describe("2250: Sample Authorization", () => { const filter = { where: { ownerGroup: "group1", - } + }, }; return request(appUrl) @@ -1225,7 +1183,7 @@ describe("2250: Sample Authorization", () => { const filter = { where: { ownerGroup: "group1", - } + }, }; return request(appUrl) @@ -1238,7 +1196,7 @@ describe("2250: Sample Authorization", () => { .expect("Content-Type", /json/) .then((res) => { res.body.should.be.a("array").and.to.have.length(3); - res.body.forEach( (e) => { + res.body.forEach((e) => { e.should.have.deep.property("sampleId"); e.sampleId.should.be.oneOf([sampleId3, sampleId7, sampleId9]); }); @@ -1249,7 +1207,7 @@ describe("2250: Sample Authorization", () => { const filter = { where: { ownerGroup: "group2", - } + }, }; return request(appUrl) @@ -1281,7 +1239,7 @@ describe("2250: Sample Authorization", () => { const filter = { where: { ownerGroup: "group2", - } + }, }; return request(appUrl) @@ -1294,7 +1252,7 @@ describe("2250: Sample Authorization", () => { .expect("Content-Type", /json/) .then((res) => { res.body.should.be.an("array").and.to.have.length(2); - res.body.forEach( (e) => { + res.body.forEach((e) => { e.should.have.deep.property("sampleId"); e.sampleId.should.be.oneOf([sampleId4, sampleId8]); }); @@ -1305,7 +1263,7 @@ describe("2250: Sample Authorization", () => { const filter = { where: { ownerGroup: "nogroup", - } + }, }; return request(appUrl) @@ -1318,7 +1276,7 @@ describe("2250: Sample Authorization", () => { .expect("Content-Type", /json/) .then((res) => { res.body.should.be.an("array").and.to.have.length(1); - res.body.forEach( (e) => { + res.body.forEach((e) => { e.should.have.deep.property("sampleId"); e.sampleId.should.be.oneOf([sampleId10]); }); @@ -1369,7 +1327,7 @@ describe("2250: Sample Authorization", () => { .expect("Content-Type", /json/) .then((res) => { res.body.should.be.an("array").and.to.have.length(1); - res.body.forEach( (e) => { + res.body.forEach((e) => { e.should.have.deep.property("isPublished"); e.isPublished.should.be.equal(true); }); @@ -1381,7 +1339,7 @@ describe("2250: Sample Authorization", () => { // it("0640: access sample 1 as Admin Ingestor", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId1 ) + .get("/api/v3/Samples/" + sampleId1) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -1405,7 +1363,7 @@ describe("2250: Sample Authorization", () => { it("0650: access sample 2 as Admin Ingestor", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId2 ) + .get("/api/v3/Samples/" + sampleId2) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -1429,7 +1387,7 @@ describe("2250: Sample Authorization", () => { it("0660: access sample 3 as Admin Ingestor", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId3 ) + .get("/api/v3/Samples/" + sampleId3) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -1453,7 +1411,7 @@ describe("2250: Sample Authorization", () => { it("0660: access sample 4 as Admin Ingestor", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId4 ) + .get("/api/v3/Samples/" + sampleId4) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -1477,7 +1435,7 @@ describe("2250: Sample Authorization", () => { it("0670: access sample 5 as Admin Ingestor", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId5 ) + .get("/api/v3/Samples/" + sampleId5) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -1501,7 +1459,7 @@ describe("2250: Sample Authorization", () => { it("0680: access sample 6 as Admin Ingestor", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId6 ) + .get("/api/v3/Samples/" + sampleId6) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -1525,7 +1483,7 @@ describe("2250: Sample Authorization", () => { it("0690: access sample 7 as Admin Ingestor", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId7 ) + .get("/api/v3/Samples/" + sampleId7) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -1549,7 +1507,7 @@ describe("2250: Sample Authorization", () => { it("0700: access sample 8 as Admin Ingestor", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId8 ) + .get("/api/v3/Samples/" + sampleId8) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -1573,7 +1531,7 @@ describe("2250: Sample Authorization", () => { it("0710: access sample 9 as Admin Ingestor", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId9 ) + .get("/api/v3/Samples/" + sampleId9) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -1597,7 +1555,7 @@ describe("2250: Sample Authorization", () => { it("0720: access public sample 10 as Admin Ingestor", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId10 ) + .get("/api/v3/Samples/" + sampleId10) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -1621,7 +1579,7 @@ describe("2250: Sample Authorization", () => { it("0730: access sample 1 as Sample Ingestor, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId1 ) + .get("/api/v3/Samples/" + sampleId1) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenSampleIngestor}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -1637,7 +1595,7 @@ describe("2250: Sample Authorization", () => { it("0740: access sample 2 as Sample Ingestor", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId2 ) + .get("/api/v3/Samples/" + sampleId2) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenSampleIngestor}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -1661,7 +1619,7 @@ describe("2250: Sample Authorization", () => { it("0750: access sample 3 as Sample Ingestor, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId3 ) + .get("/api/v3/Samples/" + sampleId3) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenSampleIngestor}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -1677,7 +1635,7 @@ describe("2250: Sample Authorization", () => { it("0760: access sample 4 as Sample Ingestor, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId4 ) + .get("/api/v3/Samples/" + sampleId4) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenSampleIngestor}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -1693,7 +1651,7 @@ describe("2250: Sample Authorization", () => { it("0770: access sample 5 as Sample Ingestor, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId5 ) + .get("/api/v3/Samples/" + sampleId5) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenSampleIngestor}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -1709,7 +1667,7 @@ describe("2250: Sample Authorization", () => { it("0780: access sample 6 as Sample Ingestor", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId6 ) + .get("/api/v3/Samples/" + sampleId6) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenSampleIngestor}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -1733,7 +1691,7 @@ describe("2250: Sample Authorization", () => { it("0790: access sample 7 as Sample Ingestor, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId7 ) + .get("/api/v3/Samples/" + sampleId7) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenSampleIngestor}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -1749,7 +1707,7 @@ describe("2250: Sample Authorization", () => { it("0800: access sample 8 as Sample Ingestor, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId8 ) + .get("/api/v3/Samples/" + sampleId8) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenSampleIngestor}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -1765,7 +1723,7 @@ describe("2250: Sample Authorization", () => { it("0810: access sample 9 as Sample Ingestor, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId9 ) + .get("/api/v3/Samples/" + sampleId9) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenSampleIngestor}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -1781,7 +1739,7 @@ describe("2250: Sample Authorization", () => { it("0820: access public sample 10 as Sample Ingestor", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId10 ) + .get("/api/v3/Samples/" + sampleId10) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenSampleIngestor}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -1805,7 +1763,7 @@ describe("2250: Sample Authorization", () => { it("0830: access sample 1 as User 1, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId1 ) + .get("/api/v3/Samples/" + sampleId1) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser1}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -1821,7 +1779,7 @@ describe("2250: Sample Authorization", () => { it("0840: access sample 2 as User 1, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId2 ) + .get("/api/v3/Samples/" + sampleId2) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser1}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -1837,7 +1795,7 @@ describe("2250: Sample Authorization", () => { it("0850: access sample 3 as User 1", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId3 ) + .get("/api/v3/Samples/" + sampleId3) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser1}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -1861,7 +1819,7 @@ describe("2250: Sample Authorization", () => { it("0860: access sample 4 as User 1, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId4 ) + .get("/api/v3/Samples/" + sampleId4) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser1}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -1877,7 +1835,7 @@ describe("2250: Sample Authorization", () => { it("0870: access sample 5 as User 1, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId5 ) + .get("/api/v3/Samples/" + sampleId5) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser1}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -1893,7 +1851,7 @@ describe("2250: Sample Authorization", () => { it("0880: access sample 6 as User 1", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId6 ) + .get("/api/v3/Samples/" + sampleId6) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser1}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -1917,7 +1875,7 @@ describe("2250: Sample Authorization", () => { it("0890: access sample 7 as User 1", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId7 ) + .get("/api/v3/Samples/" + sampleId7) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser1}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -1941,7 +1899,7 @@ describe("2250: Sample Authorization", () => { it("0900: access sample 8 as User 1, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId8 ) + .get("/api/v3/Samples/" + sampleId8) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser1}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -1957,7 +1915,7 @@ describe("2250: Sample Authorization", () => { it("0910: access sample 9 as User 1", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId9 ) + .get("/api/v3/Samples/" + sampleId9) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser1}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -1981,7 +1939,7 @@ describe("2250: Sample Authorization", () => { it("0920: access public sample 10 as User 1", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId10 ) + .get("/api/v3/Samples/" + sampleId10) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser1}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -2005,7 +1963,7 @@ describe("2250: Sample Authorization", () => { it("0930: access sample 1 as User 2, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId1 ) + .get("/api/v3/Samples/" + sampleId1) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser2}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2021,7 +1979,7 @@ describe("2250: Sample Authorization", () => { it("0940: access sample 2 as User 2, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId2 ) + .get("/api/v3/Samples/" + sampleId2) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser2}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2037,7 +1995,7 @@ describe("2250: Sample Authorization", () => { it("0950: access sample 3 as User 2, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId3 ) + .get("/api/v3/Samples/" + sampleId3) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser2}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2053,7 +2011,7 @@ describe("2250: Sample Authorization", () => { it("0960: access sample 4 as User 2", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId4 ) + .get("/api/v3/Samples/" + sampleId4) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser2}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -2077,7 +2035,7 @@ describe("2250: Sample Authorization", () => { it("0970: access sample 5 as User 2", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId5 ) + .get("/api/v3/Samples/" + sampleId5) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser2}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -2101,7 +2059,7 @@ describe("2250: Sample Authorization", () => { it("0980: access sample 6 as User 2, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId6 ) + .get("/api/v3/Samples/" + sampleId6) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser2}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2117,7 +2075,7 @@ describe("2250: Sample Authorization", () => { it("0990: access sample 7 as User 2", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId7 ) + .get("/api/v3/Samples/" + sampleId7) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser2}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -2141,7 +2099,7 @@ describe("2250: Sample Authorization", () => { it("1000: access sample 8 as User 2", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId8 ) + .get("/api/v3/Samples/" + sampleId8) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser2}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -2165,7 +2123,7 @@ describe("2250: Sample Authorization", () => { it("1010: access sample 9 as User 2, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId9 ) + .get("/api/v3/Samples/" + sampleId9) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser2}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2181,7 +2139,7 @@ describe("2250: Sample Authorization", () => { it("1020: access public sample 10 as User 2", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId10 ) + .get("/api/v3/Samples/" + sampleId10) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser2}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -2205,7 +2163,7 @@ describe("2250: Sample Authorization", () => { it("1030: access sample 1 as User 3, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId1 ) + .get("/api/v3/Samples/" + sampleId1) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser3}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2221,7 +2179,7 @@ describe("2250: Sample Authorization", () => { it("1040: access sample 2 as User 3", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId2 ) + .get("/api/v3/Samples/" + sampleId2) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser3}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -2245,7 +2203,7 @@ describe("2250: Sample Authorization", () => { it("1050: access sample 3 as User 3", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId3 ) + .get("/api/v3/Samples/" + sampleId3) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser3}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -2269,7 +2227,7 @@ describe("2250: Sample Authorization", () => { it("1060: access sample 4 as User 3, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId4 ) + .get("/api/v3/Samples/" + sampleId4) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser3}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2285,7 +2243,7 @@ describe("2250: Sample Authorization", () => { it("1070: access sample 5 as User 3, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId5 ) + .get("/api/v3/Samples/" + sampleId5) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser3}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2301,7 +2259,7 @@ describe("2250: Sample Authorization", () => { it("1080: access sample 6 as User 3, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId6 ) + .get("/api/v3/Samples/" + sampleId6) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser3}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2317,7 +2275,7 @@ describe("2250: Sample Authorization", () => { it("1090: access sample 7 as User 3", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId7 ) + .get("/api/v3/Samples/" + sampleId7) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser3}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -2341,7 +2299,7 @@ describe("2250: Sample Authorization", () => { it("1100: access sample 8 as User 3, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId8 ) + .get("/api/v3/Samples/" + sampleId8) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser3}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2357,7 +2315,7 @@ describe("2250: Sample Authorization", () => { it("1110: access sample 9 as User 3, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId9 ) + .get("/api/v3/Samples/" + sampleId9) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser3}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2373,7 +2331,7 @@ describe("2250: Sample Authorization", () => { it("1120: access public sample 10 as User 3", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId10 ) + .get("/api/v3/Samples/" + sampleId10) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser3}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -2397,7 +2355,7 @@ describe("2250: Sample Authorization", () => { it("1130: access sample 1 as User 4, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId1 ) + .get("/api/v3/Samples/" + sampleId1) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser4}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2413,7 +2371,7 @@ describe("2250: Sample Authorization", () => { it("1140: access sample 2 as User 4, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId2 ) + .get("/api/v3/Samples/" + sampleId2) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser4}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2429,7 +2387,7 @@ describe("2250: Sample Authorization", () => { it("1150: access sample 3 as User 4, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId3 ) + .get("/api/v3/Samples/" + sampleId3) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser4}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2445,7 +2403,7 @@ describe("2250: Sample Authorization", () => { it("1160: access sample 4 as User 4", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId4 ) + .get("/api/v3/Samples/" + sampleId4) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser4}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -2469,7 +2427,7 @@ describe("2250: Sample Authorization", () => { it("1170: access sample 5 as User 4, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId5 ) + .get("/api/v3/Samples/" + sampleId5) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser4}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2485,7 +2443,7 @@ describe("2250: Sample Authorization", () => { it("1180: access sample 6 as User 4", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId6 ) + .get("/api/v3/Samples/" + sampleId6) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser4}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -2509,7 +2467,7 @@ describe("2250: Sample Authorization", () => { it("1190: access sample 7 as User 4, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId7 ) + .get("/api/v3/Samples/" + sampleId7) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser4}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2525,7 +2483,7 @@ describe("2250: Sample Authorization", () => { it("1200: access sample 8 as User 4, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId8 ) + .get("/api/v3/Samples/" + sampleId8) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser4}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2541,7 +2499,7 @@ describe("2250: Sample Authorization", () => { it("1210: access sample 9 as User 4, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId9 ) + .get("/api/v3/Samples/" + sampleId9) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser4}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2557,7 +2515,7 @@ describe("2250: Sample Authorization", () => { it("1220: access public sample 10 as User 4", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId10 ) + .get("/api/v3/Samples/" + sampleId10) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser4}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -2581,7 +2539,7 @@ describe("2250: Sample Authorization", () => { it("1230: access sample 1 as User 5", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId1 ) + .get("/api/v3/Samples/" + sampleId1) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser5}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -2605,7 +2563,7 @@ describe("2250: Sample Authorization", () => { it("1240: access sample 2 as User 5, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId2 ) + .get("/api/v3/Samples/" + sampleId2) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser5}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2621,7 +2579,7 @@ describe("2250: Sample Authorization", () => { it("1250: access sample 3 as User 5, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId3 ) + .get("/api/v3/Samples/" + sampleId3) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser5}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2637,7 +2595,7 @@ describe("2250: Sample Authorization", () => { it("1260: access sample 4 as User 5, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId4 ) + .get("/api/v3/Samples/" + sampleId4) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser5}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2653,7 +2611,7 @@ describe("2250: Sample Authorization", () => { it("1270: access sample 5 as User 5", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId5 ) + .get("/api/v3/Samples/" + sampleId5) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser5}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -2677,7 +2635,7 @@ describe("2250: Sample Authorization", () => { it("1280: access sample 6 as User 5, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId6 ) + .get("/api/v3/Samples/" + sampleId6) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser5}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2693,7 +2651,7 @@ describe("2250: Sample Authorization", () => { it("1290: access sample 7 as User 5, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId7 ) + .get("/api/v3/Samples/" + sampleId7) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser5}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2709,7 +2667,7 @@ describe("2250: Sample Authorization", () => { it("1300: access sample 8 as User 5, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId8 ) + .get("/api/v3/Samples/" + sampleId8) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser5}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2725,7 +2683,7 @@ describe("2250: Sample Authorization", () => { it("1310: access sample 9 as User 5", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId9 ) + .get("/api/v3/Samples/" + sampleId9) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser5}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -2749,7 +2707,7 @@ describe("2250: Sample Authorization", () => { it("1320: access public sample 10 as User 5", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId10 ) + .get("/api/v3/Samples/" + sampleId10) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser5}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -2773,7 +2731,7 @@ describe("2250: Sample Authorization", () => { it("1330: access sample 1 as Unauthenticated User, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId1 ) + .get("/api/v3/Samples/" + sampleId1) .set("Accept", "application/json") .expect(TestData.CreationForbiddenStatusCode); }); @@ -2787,7 +2745,7 @@ describe("2250: Sample Authorization", () => { it("1340: access sample 2 as Unauthenticated User, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId2 ) + .get("/api/v3/Samples/" + sampleId2) .set("Accept", "application/json") .expect(TestData.CreationForbiddenStatusCode); }); @@ -2801,7 +2759,7 @@ describe("2250: Sample Authorization", () => { it("1350: access sample 3 as Unauthenticated User, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId3 ) + .get("/api/v3/Samples/" + sampleId3) .set("Accept", "application/json") .expect(TestData.CreationForbiddenStatusCode); }); @@ -2815,7 +2773,7 @@ describe("2250: Sample Authorization", () => { it("1360: access sample 4 as Unauthenticated User, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId4 ) + .get("/api/v3/Samples/" + sampleId4) .set("Accept", "application/json") .expect(TestData.CreationForbiddenStatusCode); }); @@ -2829,7 +2787,7 @@ describe("2250: Sample Authorization", () => { it("1370: access sample 5 as Unauthenticated User, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId5 ) + .get("/api/v3/Samples/" + sampleId5) .set("Accept", "application/json") .expect(TestData.CreationForbiddenStatusCode); }); @@ -2843,7 +2801,7 @@ describe("2250: Sample Authorization", () => { it("1380: access sample 6 as Unauthenticated User, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId6 ) + .get("/api/v3/Samples/" + sampleId6) .set("Accept", "application/json") .expect(TestData.CreationForbiddenStatusCode); }); @@ -2857,7 +2815,7 @@ describe("2250: Sample Authorization", () => { it("1390: access sample 7 as Unauthenticated User, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId7 ) + .get("/api/v3/Samples/" + sampleId7) .set("Accept", "application/json") .expect(TestData.CreationForbiddenStatusCode); }); @@ -2871,7 +2829,7 @@ describe("2250: Sample Authorization", () => { it("1400: access sample 8 as Unauthenticated User, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId8 ) + .get("/api/v3/Samples/" + sampleId8) .set("Accept", "application/json") .expect(TestData.CreationForbiddenStatusCode); }); @@ -2885,7 +2843,7 @@ describe("2250: Sample Authorization", () => { it("1410: access sample 9 as Unauthenticated User, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId9 ) + .get("/api/v3/Samples/" + sampleId9) .set("Accept", "application/json") .expect(TestData.CreationForbiddenStatusCode); }); @@ -2899,7 +2857,7 @@ describe("2250: Sample Authorization", () => { it("1420: access public sample 10 as Unauthenticated User", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId10 ) + .get("/api/v3/Samples/" + sampleId10) .set("Accept", "application/json") .expect(TestData.SuccessfulGetStatusCode) .expect("Content-Type", /json/) @@ -2921,7 +2879,7 @@ describe("2250: Sample Authorization", () => { it("1430: access sample 1 as Archive Manager, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId1 ) + .get("/api/v3/Samples/" + sampleId1) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2937,7 +2895,7 @@ describe("2250: Sample Authorization", () => { it("1440: access sample 2 as Archive Manager, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId2 ) + .get("/api/v3/Samples/" + sampleId2) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2953,7 +2911,7 @@ describe("2250: Sample Authorization", () => { it("1450: access sample 3 as Archive Manager, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId3 ) + .get("/api/v3/Samples/" + sampleId3) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2969,7 +2927,7 @@ describe("2250: Sample Authorization", () => { it("1460: access sample 4 as Archive Manager, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId4 ) + .get("/api/v3/Samples/" + sampleId4) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -2985,7 +2943,7 @@ describe("2250: Sample Authorization", () => { it("1470: access sample 5 as Archive Manager, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId5 ) + .get("/api/v3/Samples/" + sampleId5) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3001,7 +2959,7 @@ describe("2250: Sample Authorization", () => { it("1480: access sample 6 as Archive Manager, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId6 ) + .get("/api/v3/Samples/" + sampleId6) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3016,7 +2974,7 @@ describe("2250: Sample Authorization", () => { it("1490: access sample 7 as Archive Manager, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId7 ) + .get("/api/v3/Samples/" + sampleId7) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3032,7 +2990,7 @@ describe("2250: Sample Authorization", () => { it("1500: access sample 8 as Archive Manager, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId8 ) + .get("/api/v3/Samples/" + sampleId8) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3048,7 +3006,7 @@ describe("2250: Sample Authorization", () => { it("1510: access sample 9 as Archive Manager, which should fail", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId9 ) + .get("/api/v3/Samples/" + sampleId9) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3064,7 +3022,7 @@ describe("2250: Sample Authorization", () => { it("1520: access public sample 10 as Archive Manager", async () => { return request(appUrl) - .get("/api/v3/Samples/" + sampleId10 ) + .get("/api/v3/Samples/" + sampleId10) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) .expect(TestData.SuccessfulGetStatusCode) @@ -3087,21 +3045,23 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2000", - "user" : "Admin Ingestor" - } - } + test: "2000", + user: "Admin Ingestor", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId1) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .expect(TestData.SuccessfulPatchStatusCode) .expect("Content-Type", /json/) .then((res) => { res.body.should.have.property("sampleCharacteristics"); - res.body.sampleCharacteristics.should.have.property("test").and.be.equal(characteristics["test"]); + res.body.sampleCharacteristics.should.have + .property("test") + .and.be.equal(characteristics["test"]); }); }); @@ -3109,43 +3069,47 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2010", - "user" : "Admin Ingestor" - } - } + test: "2010", + user: "Admin Ingestor", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId2) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .expect(TestData.SuccessfulPatchStatusCode) .expect("Content-Type", /json/) .then((res) => { res.body.should.have.property("sampleCharacteristics"); - res.body.sampleCharacteristics.should.have.property("test").and.be.equal(characteristics["test"]); + res.body.sampleCharacteristics.should.have + .property("test") + .and.be.equal(characteristics["test"]); }); }); - + it("2020: update sample characteristic for sample 5 as Admin Ingestor", async () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2020", - "user" : "Admin Ingestor" - } - } + test: "2020", + user: "Admin Ingestor", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId5) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .expect(TestData.SuccessfulPatchStatusCode) .expect("Content-Type", /json/) .then((res) => { res.body.should.have.property("sampleCharacteristics"); - res.body.sampleCharacteristics.should.have.property("test").and.be.equal(characteristics["test"]); + res.body.sampleCharacteristics.should.have + .property("test") + .and.be.equal(characteristics["test"]); }); }); @@ -3153,21 +3117,23 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2030", - "user" : "Admin Ingestor" - } - } + test: "2030", + user: "Admin Ingestor", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId6) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .expect(TestData.SuccessfulPatchStatusCode) .expect("Content-Type", /json/) .then((res) => { res.body.should.have.property("sampleCharacteristics"); - res.body.sampleCharacteristics.should.have.property("test").and.be.equal(characteristics["test"]); + res.body.sampleCharacteristics.should.have + .property("test") + .and.be.equal(characteristics["test"]); }); }); @@ -3175,14 +3141,14 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2040", - "user" : "Sample Ingestor" - } - } + test: "2040", + user: "Sample Ingestor", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId1) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenSampleIngestor}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3192,36 +3158,38 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2050", - "user" : "Sample Ingestor" - } - } + test: "2050", + user: "Sample Ingestor", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId2) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenSampleIngestor}` }) .expect(TestData.SuccessfulPatchStatusCode) .expect("Content-Type", /json/) .then((res) => { res.body.should.have.property("sampleCharacteristics"); - res.body.sampleCharacteristics.should.have.property("test").and.be.equal(characteristics["test"]); + res.body.sampleCharacteristics.should.have + .property("test") + .and.be.equal(characteristics["test"]); }); }); - + it("2060: update sample characteristic for sample 5 as Sample Ingestor, which should fail", async () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2060", - "user" : "Sample Ingestor" - } - } + test: "2060", + user: "Sample Ingestor", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId5) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenSampleIngestor}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3231,21 +3199,23 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2070", - "user" : "Sample Ingestor" - } - } + test: "2070", + user: "Sample Ingestor", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId6) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenSampleIngestor}` }) .expect(TestData.SuccessfulPatchStatusCode) .expect("Content-Type", /json/) .then((res) => { res.body.should.have.property("sampleCharacteristics"); - res.body.sampleCharacteristics.should.have.property("test").and.be.equal(characteristics["test"]); + res.body.sampleCharacteristics.should.have + .property("test") + .and.be.equal(characteristics["test"]); }); }); @@ -3253,14 +3223,14 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2080", - "user" : "User 1" - } - } + test: "2080", + user: "User 1", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId2) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser1}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3270,36 +3240,38 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2090", - "user" : "User 1" - } - } + test: "2090", + user: "User 1", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId3) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser1}` }) .expect(TestData.SuccessfulPatchStatusCode) .expect("Content-Type", /json/) .then((res) => { res.body.should.have.property("sampleCharacteristics"); - res.body.sampleCharacteristics.should.have.property("test").and.be.equal(characteristics["test"]); + res.body.sampleCharacteristics.should.have + .property("test") + .and.be.equal(characteristics["test"]); }); }); - + it("2100: update sample characteristic for sample 6 as User 1, which should fail", async () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2100", - "user" : "User 1" - } - } + test: "2100", + user: "User 1", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId6) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser1}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3309,21 +3281,23 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2110", - "user" : "User 1" - } - } + test: "2110", + user: "User 1", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId7) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser1}` }) .expect(TestData.SuccessfulPatchStatusCode) .expect("Content-Type", /json/) .then((res) => { res.body.should.have.property("sampleCharacteristics"); - res.body.sampleCharacteristics.should.have.property("test").and.be.equal(characteristics["test"]); + res.body.sampleCharacteristics.should.have + .property("test") + .and.be.equal(characteristics["test"]); }); }); @@ -3331,21 +3305,23 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2120", - "user" : "User 1" - } - } + test: "2120", + user: "User 1", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId9) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser1}` }) .expect(TestData.SuccessfulPatchStatusCode) .expect("Content-Type", /json/) .then((res) => { res.body.should.have.property("sampleCharacteristics"); - res.body.sampleCharacteristics.should.have.property("test").and.be.equal(characteristics["test"]); + res.body.sampleCharacteristics.should.have + .property("test") + .and.be.equal(characteristics["test"]); }); }); @@ -3353,14 +3329,14 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2130", - "user" : "User 2" - } - } + test: "2130", + user: "User 2", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId2) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser2}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3370,14 +3346,14 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2140", - "user" : "User 2" - } - } + test: "2140", + user: "User 2", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId4) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser2}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3387,14 +3363,14 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2150", - "user" : "User 2" - } - } + test: "2150", + user: "User 2", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId5) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser2}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3404,14 +3380,14 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2160", - "user" : "User 3" - } - } + test: "2160", + user: "User 3", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId3) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser3}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3421,14 +3397,14 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2170", - "user" : "User 3" - } - } + test: "2170", + user: "User 3", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId4) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser3}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3438,14 +3414,14 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2180", - "user" : "User 3" - } - } + test: "2180", + user: "User 3", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId10) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser3}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3455,14 +3431,14 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2190", - "user" : "User 4" - } - } + test: "2190", + user: "User 4", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId4) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser4}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3472,14 +3448,14 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2200", - "user" : "User 4" - } - } + test: "2200", + user: "User 4", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId5) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser4}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3489,14 +3465,14 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2210", - "user" : "User 4" - } - } + test: "2210", + user: "User 4", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId10) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser4}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3506,14 +3482,14 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2220", - "user" : "User 5" - } - } + test: "2220", + user: "User 5", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId5) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser5}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3523,14 +3499,14 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2230", - "user" : "User 5" - } - } + test: "2230", + user: "User 5", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId6) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser5}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3540,14 +3516,14 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2240", - "user" : "User 5" - } - } + test: "2240", + user: "User 5", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId10) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenUser5}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3557,14 +3533,14 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2250", - "user" : "Archive Manager" - } - } + test: "2250", + user: "Archive Manager", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId1) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3574,14 +3550,14 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2260", - "user" : "Archive Manager" - } - } + test: "2260", + user: "Archive Manager", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId10) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) .expect(TestData.CreationForbiddenStatusCode); @@ -3591,14 +3567,14 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2270", - "user" : "Unauthenticated User" - } - } + test: "2270", + user: "Unauthenticated User", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId1) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .expect(TestData.CreationForbiddenStatusCode); }); @@ -3607,19 +3583,18 @@ describe("2250: Sample Authorization", () => { const characteristics = { ...TestData.SampleCorrect["sampleCharacteristics"], ...{ - "test" : "2280", - "user" : "Unauthenticated User" - } - } + test: "2280", + user: "Unauthenticated User", + }, + }; return request(appUrl) .patch("/api/v3/Samples/" + sampleId10) - .send({"sampleCharacteristics" : characteristics}) + .send({ sampleCharacteristics: characteristics }) .set("Accept", "application/json") .expect(TestData.CreationForbiddenStatusCode); }); - // delete sample attachment it("4000: delete attachment 1 from sample 1 as Unauthenticated User, which should fail", async () => { return request(appUrl) @@ -3630,7 +3605,9 @@ describe("2250: Sample Authorization", () => { it("4010: delete attachment 10 from sample 10 as Unauthenticated User, which should fail", async () => { return request(appUrl) - .delete("/api/v3/samples/" + sampleId10 + "/attachments/" + attachmentId10) + .delete( + "/api/v3/samples/" + sampleId10 + "/attachments/" + attachmentId10, + ) .set("Accept", "application/json") .expect(TestData.DeleteForbiddenStatusCode); }); @@ -3653,9 +3630,11 @@ describe("2250: Sample Authorization", () => { it("4040: delete attachment 10 from sample 10 as User 5, which should fail", async () => { return request(appUrl) - .delete("/api/v3/samples/" + sampleId10 + "/attachments/" + attachmentId10) + .delete( + "/api/v3/samples/" + sampleId10 + "/attachments/" + attachmentId10, + ) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenUser5}` }) + .set({ Authorization: `Bearer ${accessTokenUser5}` }) .expect(TestData.DeleteForbiddenStatusCode); }); @@ -3677,9 +3656,11 @@ describe("2250: Sample Authorization", () => { it("4070: delete attachment 10 from sample 10 as User 4, which should fail", async () => { return request(appUrl) - .delete("/api/v3/samples/" + sampleId10 + "/attachments/" + attachmentId10) + .delete( + "/api/v3/samples/" + sampleId10 + "/attachments/" + attachmentId10, + ) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenUser4}` }) + .set({ Authorization: `Bearer ${accessTokenUser4}` }) .expect(TestData.DeleteForbiddenStatusCode); }); @@ -3701,9 +3682,11 @@ describe("2250: Sample Authorization", () => { it("4100: delete attachment 10 from sample 10 as User 3, which should fail", async () => { return request(appUrl) - .delete("/api/v3/samples/" + sampleId10 + "/attachments/" + attachmentId10) + .delete( + "/api/v3/samples/" + sampleId10 + "/attachments/" + attachmentId10, + ) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenUser3}` }) + .set({ Authorization: `Bearer ${accessTokenUser3}` }) .expect(TestData.DeleteForbiddenStatusCode); }); @@ -3733,9 +3716,11 @@ describe("2250: Sample Authorization", () => { it("4140: delete attachment 10 from sample 10 as User 2, which should fail", async () => { return request(appUrl) - .delete("/api/v3/samples/" + sampleId10 + "/attachments/" + attachmentId10) + .delete( + "/api/v3/samples/" + sampleId10 + "/attachments/" + attachmentId10, + ) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenUser3}` }) + .set({ Authorization: `Bearer ${accessTokenUser3}` }) .expect(TestData.DeleteForbiddenStatusCode); }); @@ -3746,7 +3731,7 @@ describe("2250: Sample Authorization", () => { .set({ Authorization: `Bearer ${accessTokenUser1}` }) .expect(TestData.SuccessfulDeleteStatusCode) .expect("Content-Type", /json/); - }); + }); it("4160: delete attachment 4 from sample 4 as User 1, which should fail", async () => { return request(appUrl) @@ -3771,13 +3756,15 @@ describe("2250: Sample Authorization", () => { .set({ Authorization: `Bearer ${accessTokenUser1}` }) .expect(TestData.SuccessfulDeleteStatusCode) .expect("Content-Type", /json/); - }); + }); it("4190: delete attachment 10 from sample 10 as User 1, which should fail", async () => { return request(appUrl) - .delete("/api/v3/samples/" + sampleId10 + "/attachments/" + attachmentId10) + .delete( + "/api/v3/samples/" + sampleId10 + "/attachments/" + attachmentId10, + ) .set("Accept", "application/json") - .set({ Authorization: `Bearer ${accessTokenUser1}` }) + .set({ Authorization: `Bearer ${accessTokenUser1}` }) .expect(TestData.DeleteForbiddenStatusCode); }); @@ -3797,7 +3784,7 @@ describe("2250: Sample Authorization", () => { .set({ Authorization: `Bearer ${accessTokenSampleIngestor}` }) .expect(TestData.DeleteForbiddenStatusCode); }); - + it("4220: delete attachment 7 from sample 7 as Sample Ingestor, which should fail", async () => { return request(appUrl) .delete("/api/v3/samples/" + sampleId7 + "/attachments/" + attachmentId7) @@ -3805,7 +3792,7 @@ describe("2250: Sample Authorization", () => { .set({ Authorization: `Bearer ${accessTokenSampleIngestor}` }) .expect(TestData.DeleteForbiddenStatusCode); }); - + it("4230: delete attachment 8 from sample 8 as Sample Ingestor, wich should fail", async () => { return request(appUrl) .delete("/api/v3/samples/" + sampleId8 + "/attachments/" + attachmentId8) @@ -3813,7 +3800,7 @@ describe("2250: Sample Authorization", () => { .set({ Authorization: `Bearer ${accessTokenSampleIngestor}` }) .expect(TestData.DeleteForbiddenStatusCode); }); - + it("4240: delete attachment 1 from sample 1 as Admin Ingestor", async () => { return request(appUrl) .delete("/api/v3/samples/" + sampleId1 + "/attachments/" + attachmentId1) @@ -3822,10 +3809,12 @@ describe("2250: Sample Authorization", () => { .expect(TestData.SuccessfulDeleteStatusCode) .expect("Content-Type", /json/); }); - + it("4250: delete attachment 3_2 from sample 3 as Admin Ingestor", async () => { return request(appUrl) - .delete("/api/v3/samples/" + sampleId3 + "/attachments/" + attachmentId3_2) + .delete( + "/api/v3/samples/" + sampleId3 + "/attachments/" + attachmentId3_2, + ) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenAdminIngestor}` }) .expect(TestData.SuccessfulDeleteStatusCode) @@ -3852,7 +3841,9 @@ describe("2250: Sample Authorization", () => { it("4280: delete attachment 7_2 from sample 7 as Archive Manager", async () => { return request(appUrl) - .delete("/api/v3/samples/" + sampleId7 + "/attachments/" + attachmentId7_2) + .delete( + "/api/v3/samples/" + sampleId7 + "/attachments/" + attachmentId7_2, + ) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) .expect(TestData.SuccessfulDeleteStatusCode) @@ -3861,7 +3852,9 @@ describe("2250: Sample Authorization", () => { it("4290: delete attachment 10 from sample 10 as Archive Manager", async () => { return request(appUrl) - .delete("/api/v3/samples/" + sampleId10 + "/attachments/" + attachmentId10) + .delete( + "/api/v3/samples/" + sampleId10 + "/attachments/" + attachmentId10, + ) .set("Accept", "application/json") .set({ Authorization: `Bearer ${accessTokenArchiveManager}` }) .expect(TestData.SuccessfulDeleteStatusCode) diff --git a/test/TestData.js b/test/TestData.js index 5a3a5310b..a22884445 100644 --- a/test/TestData.js +++ b/test/TestData.js @@ -684,23 +684,29 @@ const TestData = { ], }, - ArchiveJob: { - emailJobInitiator: "scicatarchivemanger@psi.ch", - type: "archive", - jobStatusMessage: "jobForwarded", - datasetList: [ - { - pid: "dummy", - files: [], - }, - { - pid: "dummy", - files: [], - }, - ], - jobResultObject: { - status: "okay", - message: "All systems okay", + // ArchiveJob: { + // emailJobInitiator: "scicatarchivemanger@psi.ch", + // type: "archive", + // jobStatusMessage: "jobForwarded", + // datasetList: [ + // { + // pid: "dummy", + // files: [], + // }, + // { + // pid: "dummy", + // files: [], + // }, + // ], + // jobResultObject: { + // status: "okay", + // message: "All systems okay", + // }, + // }, + + Job:{ + type: "", + jobParams: { }, }, diff --git a/test/config/jobconfig.json b/test/config/jobconfig.json index b1df4021c..6f2247141 100644 --- a/test/config/jobconfig.json +++ b/test/config/jobconfig.json @@ -1,53 +1,73 @@ -[ +{ + "configVersion": "v1.0 2024-03-01 6f3f38", + "jobs": [ { - "jobType": "archive", + "jobType": "all_access", "create": { - "actions": { - "actionType": "log" - } - }, - "update": { "auth": "#all", - "actions": { - "actionType": "log" - } - }, - "post": { "actions": [ { - "actionType": "email", - "mailer": { - "host": "smtp.myinstitution.ext", - "port": 465, - "secure": true, - "auth": { - "user": "scicatuser", - "pass": "" - } - }, - "to": "{{ join job.recipients ' '}}", - "from": "scicat@example.com", - "subject": "Archive job {{job.pid}} has completed.", - "body": "Dear {{job.owner}},\n\nArchive job {{job.pid}} has completed. Results: {{job.status}}\n" - }, - { - "actionType": "filter", - "filter": { - "status": "SUCCESSFUL" - }, - "actions": [ - { - "actionType": "url", - "url": "myscicat.myinstitution.ext/datablock/archived", - "verb": "post", - "headers": { - "AuthBearer": "{{secrets.jwt_token}}" - }, - "body": "{ structure to create archive files }" - } - ] + "actionType": "log" } ] + }, + "statusUpdate": { + "auth": "#all" + } + }, + { + "jobType": "public_access", + "create": { + "auth": "#datasetPublic" + }, + "statusUpdate": { + "auth": "#all" + } + }, + { + "jobType": "authenticated_access", + "create": { + "auth": "#authenticated" + }, + "statusUpdate": { + "auth": "#all" + } + }, + { + "jobType": "dataset_access", + "create": { + "auth": "#datasetAccess" + }, + "statusUpdate": { + "auth": "#jobOwnerGroup" + } + }, + { + "jobType": "owner_access", + "create": { + "auth": "#datasetOwner" + }, + "statusUpdate": { + "auth": "#jobOwnerUser" + } + }, + { + "jobType": "user_access", + "create": { + "auth": "user5.1" + }, + "statusUpdate": { + "auth": "user5.1" + } + }, + { + "jobType": "group_access", + "create": { + "auth": "@group5" + }, + "statusUpdate": { + "auth": "@group5" } } -] + ] +} diff --git a/test/config/pretest.js b/test/config/pretest.js index e884f4e73..1ffaa0319 100644 --- a/test/config/pretest.js +++ b/test/config/pretest.js @@ -1,19 +1,18 @@ /* eslint-disable @typescript-eslint/no-var-requires */ //NOTE: Here we load and initialize some global variables that are used throughout the tests +require("dotenv").config(); var chaiHttp = require("chai-http"); const { MongoClient } = require("mongodb"); -const uri = "mongodb://localhost:27017/scicat"; - -const client = new MongoClient(uri); +const client = new MongoClient(process.env.MONGODB_URI); async function loadChai() { const { chai } = import("chai"); chai.use(chaiHttp); await client.connect(); } -loadChai(); +loadChai(); global.appUrl = "http://localhost:3000"; global.request = require("supertest"); -global.db = client.db("scicat"); +global.db = client.db();