Skip to content

Commit

Permalink
Merge pull request #2961 from bomoko/feature/refactor_task_objects
Browse files Browse the repository at this point in the history
Feature PR - Refactor task interfaces
  • Loading branch information
Tim Clifford authored Dec 9, 2021
2 parents d294adf + 69eeb9b commit 517c746
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 103 deletions.
13 changes: 0 additions & 13 deletions services/api/src/resources/task/models/taskRegistration.test.ts

This file was deleted.

58 changes: 39 additions & 19 deletions services/api/src/resources/task/models/taskRegistration.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,45 @@
export const newTaskRegistrationFromObject = (
payload: Partial<TaskRegistration>
) => {
let obj = new TaskRegistration();
return { ...obj, ...payload };
};
// export const newTaskRegistrationFromObject = (
// payload: AdvancedTaskDefinitionInterface
// ) => {
// return new TaskRegistration(payload);
// };


export class TaskRegistration {
static TYPE_STANDARD = "COMMAND"
static TYPE_ADVANCED = "IMAGE"
id: number;
export interface AdvancedTaskDefinitionInterface {
id?: number;
type: string;
name: string;
description: string;
advanced_task_definition: number;
environment: number;
project: number;
groupName: string;
command: string;
service: string;
description?: string;
environment?: number;
project?: number;
groupName?: string;
created: string;
deleted: string;
image: string;
permission: string;
permission?: string;
command?: string;
service?: string;
image?: string;
}


export const AdvancedTaskDefinitionType = {
command: 'COMMAND',
image: 'IMAGE'
};

export const getAdvancedTaskDefinitionType = (taskDef:AdvancedTaskDefinitionInterface) => {
if(taskDef.type.toLowerCase() == AdvancedTaskDefinitionType.command.toLowerCase()) {
return AdvancedTaskDefinitionType.command;
}
return AdvancedTaskDefinitionType.image;
}

export const isAdvancedTaskDefinitionSystemLevelTask = (taskDef:AdvancedTaskDefinitionInterface): boolean => {
return taskDef.project == null && taskDef.environment == null && taskDef.groupName == null;
}

export const doesAdvancedTaskDefinitionNeedAdminRights = (taskDef:AdvancedTaskDefinitionInterface): boolean => {
return isAdvancedTaskDefinitionSystemLevelTask(taskDef)
|| getAdvancedTaskDefinitionType(taskDef) == AdvancedTaskDefinitionType.image
|| taskDef.groupName != undefined;
}
147 changes: 76 additions & 71 deletions services/api/src/resources/task/task_definition_resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ import { Helpers as environmentHelpers } from '../environment/helpers';
import { Helpers as projectHelpers } from '../project/helpers';
import { Validators as envValidators } from '../environment/validators';
import {
TaskRegistration,
newTaskRegistrationFromObject
AdvancedTaskDefinitionInterface,
AdvancedTaskDefinitionType,
isAdvancedTaskDefinitionSystemLevelTask,
getAdvancedTaskDefinitionType
} from './models/taskRegistration';

const AdvancedTaskDefinitionType = {
command: 'COMMAND',
image: 'IMAGE'
};


enum AdvancedTaskDefinitionTarget {
Group,
Expand Down Expand Up @@ -164,80 +163,36 @@ export const advancedTaskDefinitionArgumentById = async (
export const addAdvancedTaskDefinition = async (
root,
{
input: {
name,
description,
image = '',
type,
service,
command,
project,
groupName,
environment,
permission,
created
}
input
},
{ sqlClientPool, hasPermission, models }
) => {
const {
name,
description,
image = '',
type,
service,
command,
project,
groupName,
environment,
permission,
created
} = input;

let projectObj = await getProjectByEnvironmentIdOrProjectId(
sqlClientPool,
environment,
project
);

const systemLevelTask =
project == null && environment == null && groupName == null;
const advancedTaskWithImage = type == AdvancedTaskDefinitionType.image;
const needsAdminRightsToCreate =
systemLevelTask || advancedTaskWithImage || groupName;

if (systemLevelTask) {
//if they pass this, they can do basically anything
//In the first release, we're not actually supporting this
//TODO: add checks once images are officially supported - for now, throw an error
throw Error('Adding Images and System Wide Tasks are not yet supported');
} else if (advancedTaskWithImage) {
//We're only going to allow administrators to add these for now ...
await hasPermission('advanced_task','create:advanced');
} else if (groupName) {
const group = await models.GroupModel.loadGroupByIdOrName({
name: groupName
});
await hasPermission('group', 'update', {
group: group.id
});
} else if (projectObj) {
//does the user have permission to actually add to this?
//i.e. are they a maintainer?
await hasPermission('task', `add:production`, {
project: projectObj.id
});
}
await checkAdvancedTaskPermissions(input, hasPermission, models, projectObj);

// There are two cases, either it's a command, in which case the command + service needs to be part of the definition
// or it's a legit advanced task and we need an image.

switch (type) {
case AdvancedTaskDefinitionType.image:
if (!image || 0 === image.length) {
throw new Error(
'Unable to create image based task with no image supplied'
);
}
break;
case AdvancedTaskDefinitionType.command:
if (!command || 0 === command.length) {
throw new Error('Unable to create Advanced task definition');
}
break;
default:
throw new Error(
'Undefined Advanced Task Definition type passed at creation time: ' +
type
);
break;
}
validateAdvancedTaskDefinitionData(input, image, command, type);

//let's see if there's already an advanced task definition with this name ...
// Note: this will all be scoped to either System, group, project, or environment
Expand Down Expand Up @@ -450,7 +405,7 @@ export const invokeRegisteredTask = async (
});

switch (task.type) {
case TaskRegistration.TYPE_STANDARD:
case AdvancedTaskDefinitionType.command:
const taskData = await Helpers(sqlClientPool).addTask({
name: task.name,
environment: environment,
Expand All @@ -460,7 +415,7 @@ export const invokeRegisteredTask = async (
});
return taskData;
break;
case TaskRegistration.TYPE_ADVANCED:
case AdvancedTaskDefinitionType.image:
// the return data here is basically what gets dropped into the DB.
// what we can do
const advancedTaskData = await Helpers(sqlClientPool).addAdvancedTask({
Expand Down Expand Up @@ -490,7 +445,7 @@ const getNamedAdvancedTaskForEnvironment = async (
advancedTaskDefinition,
environment,
models
) => {
):Promise<AdvancedTaskDefinitionInterface> => {
let rows = await resolveTasksForEnvironment(
{},
{ environment },
Expand All @@ -503,7 +458,7 @@ const getNamedAdvancedTaskForEnvironment = async (
`Task registration '${advancedTaskDefinition}' could not be found.`
);
}
return newTaskRegistrationFromObject(taskDef);
return <AdvancedTaskDefinitionInterface>taskDef;
};

export const deleteAdvancedTaskDefinition = async (
Expand Down Expand Up @@ -602,3 +557,53 @@ const advancedTaskFunctions = sqlClientPool => {
}
};
};


function validateAdvancedTaskDefinitionData(input: any, image: any, command: any, type: any) {
switch (getAdvancedTaskDefinitionType(<AdvancedTaskDefinitionInterface>input)) {
case AdvancedTaskDefinitionType.image:
if (!image || 0 === image.length) {
throw new Error(
'Unable to create image based task with no image supplied'
);
}
break;
case AdvancedTaskDefinitionType.command:
if (!command || 0 === command.length) {
throw new Error('Unable to create Advanced task definition');
}
break;
default:
throw new Error(
'Undefined Advanced Task Definition type passed at creation time: ' +
type
);
break;
}
}

async function checkAdvancedTaskPermissions(input:AdvancedTaskDefinitionInterface, hasPermission: any, models: any, projectObj: any) {
if (isAdvancedTaskDefinitionSystemLevelTask(input)) {
//if they pass this, they can do basically anything
//In the first release, we're not actually supporting this
//TODO: add checks once images are officially supported - for now, throw an error
throw Error('Adding Images and System Wide Tasks are not yet supported');
} else if (getAdvancedTaskDefinitionType(input) == AdvancedTaskDefinitionType.image) {
//We're only going to allow administrators to add these for now ...
await hasPermission('advanced_task', 'create:advanced');
} else if (input.groupName) {
const group = await models.GroupModel.loadGroupByIdOrName({
name: input.groupName
});
await hasPermission('group', 'update', {
group: group.id
});
} else if (projectObj) {
//does the user have permission to actually add to this?
//i.e. are they a maintainer?
await hasPermission('task', `add:production`, {
project: projectObj.id
});
}
}

0 comments on commit 517c746

Please sign in to comment.