Skip to content

Commit

Permalink
refactor: change the permission on adding or updating deploytarget co…
Browse files Browse the repository at this point in the history
…nfigs for organization owners only if project is in organization
  • Loading branch information
shreddedbacon committed Oct 4, 2023
1 parent c9d04e4 commit af1cfee
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 68 deletions.
21 changes: 5 additions & 16 deletions services/api/src/resources/deploytargetconfig/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { Sql as EnvironmentSql } from '../environment/sql'
import { Helpers as projectHelpers } from '../project/helpers';
import { Helpers as organizationHelpers } from '../organization/helpers';


export const getDeployTargetConfigById = async (
root,
args,
Expand All @@ -26,9 +25,7 @@ export const getDeployTargetConfigById = async (
// since deploytargetconfigs are associated to a project
// re-use the existing `project:view` permissions check, since the same sorts of fields
// are viewable by the same permissions at the project scope
await hasPermission('project', 'view', {
project: deployTargetConfig.project
});
await projectHelpers(sqlClientPool).checkOrgProjectViewPermission(hasPermission, deployTargetConfig.project)

return deployTargetConfig;
};
Expand All @@ -47,9 +44,7 @@ export const getDeployTargetConfigsByProjectId: ResolverFn = async (
// since deploytargetconfigs are associated to a project
// re-use the existing `project:view` permissions check, since the same sorts of fields
// are viewable by the same permissions at the project scope
await hasPermission('project', 'view', {
project: pid
});
await projectHelpers(sqlClientPool).checkOrgProjectViewPermission(hasPermission, pid)

const rows = await query(sqlClientPool, Sql.selectDeployTargetConfigsByProjectId(pid));

Expand Down Expand Up @@ -196,9 +191,7 @@ export const addDeployTargetConfig: ResolverFn = async (
// since deploytargetconfigs are associated to a project
// re-use the existing `project:update` permissions check, since the same sorts of fields
// are updateable by the same permissions at the project scope
await hasPermission('project', 'update', {
project: project
});
await projectHelpers(sqlClientPool).checkOrgProjectUpdatePermission(hasPermission, project)

// check the project has an organization id, if it does, check that the organization supports the requested deploytarget
await checkProjectDeployTargetByOrg(project, deployTarget, sqlClientPool)
Expand Down Expand Up @@ -246,9 +239,7 @@ export const deleteDeployTargetConfig: ResolverFn = async (
// re-use the existing `project:update` permissions check, since the same sorts of fields
// are updateable by the same permissions at the project scope
// deleting a deploytargetconfig from a project is classed as updating the project
await hasPermission('project', 'update', {
project: project
});
await projectHelpers(sqlClientPool).checkOrgProjectUpdatePermission(hasPermission, project)

try {
await query(sqlClientPool, 'DELETE FROM deploy_target_config WHERE id = :id', {
Expand Down Expand Up @@ -292,9 +283,7 @@ export const updateDeployTargetConfig: ResolverFn = async (
// since deploytargetconfigs are associated to a project
// re-use the existing `project:update` permissions check, since the same sorts of fields
// are updateable by the same permissions at the project scope
await hasPermission('project', 'update', {
project: deployTargetConfig.project
});
await projectHelpers(sqlClientPool).checkOrgProjectUpdatePermission(hasPermission, deployTargetConfig.project)

// check the project has an organization id, if it does, check that the organization supports the requested deploytarget
await checkProjectDeployTargetByOrg(deployTargetConfig.project, deployTarget, sqlClientPool)
Expand Down
43 changes: 43 additions & 0 deletions services/api/src/resources/project/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,47 @@ import { Sql } from './sql';
// import { logger } from '../../loggers/logger';

export const Helpers = (sqlClientPool: Pool) => {
const checkOrgProjectViewPermission = async (hasPermission, pid) => {
// helper that allows fall through of permission check
// for viewProject:organization to view:project
// this allows queries to be performed by organization owners
// then falling through to the default project view for general users
const rows = await query(sqlClientPool, Sql.selectProject(pid));
const project = rows[0];
if (project.organization != null) {
try {
await hasPermission('organization', 'viewProject', {
organization: project.organization
});
// if the organization owner has permission to view project, return
return
} catch (err) {
// otherwise fall through to project view permission check
}
}
// finally check the user view:project permission
await hasPermission('project', 'view', {
project: project.id
});
}
const checkOrgProjectUpdatePermission = async (hasPermission, pid) => {
// helper checks the permission to updateProject:organization
// or the update:project permission
const rows = await query(sqlClientPool, Sql.selectProject(pid));
const project = rows[0];
if (project.organization != null) {
// if the project is in an organization, only the organization owner should be able to do this
await hasPermission('organization', 'updateProject', {
organization: project.organization
});
} else {
// if not in a project, follow the standard rbac
await hasPermission('project', 'update', {
project: project.id
});
}
}

const aliasOpenshiftToK8s = (projects: any[]) => {
return projects.map(project => {
return {
Expand Down Expand Up @@ -52,6 +93,8 @@ export const Helpers = (sqlClientPool: Pool) => {
query(sqlClientPool, Sql.selectProjectsByIds(projectIds));

return {
checkOrgProjectViewPermission,
checkOrgProjectUpdatePermission,
aliasOpenshiftToK8s,
getProjectById,
getProjectsByIds,
Expand Down
56 changes: 4 additions & 52 deletions services/api/src/resources/project/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,19 +124,7 @@ export const getProjectByEnvironmentId: ResolverFn = async (

const project = withK8s[0];

try {
await hasPermission('project', 'view', {
project: project.id
});
} catch (err) {
// if the user hasn't got permission to view the project, but the project is in the organization
// allow the user to get the project
if (project.organization != null) {
await hasPermission('organization', 'viewProject', {
organization: project.organization
});
}
}
await Helpers(sqlClientPool).checkOrgProjectViewPermission(hasPermission, project.id)

return project;
};
Expand All @@ -152,19 +140,7 @@ export const getProjectById: ResolverFn = async (

const project = withK8s[0];

try {
await hasPermission('project', 'view', {
project: project.id
});
} catch (err) {
// if the user hasn't got permission to view the project, but the project is in the organization
// allow the user to get the project
if (project.organization != null) {
await hasPermission('organization', 'viewProject', {
organization: project.organization
});
}
}
await Helpers(sqlClientPool).checkOrgProjectViewPermission(hasPermission, project.id)

return project;
};
Expand All @@ -180,19 +156,7 @@ export const getProjectByGitUrl: ResolverFn = async (

const project = withK8s[0];

try {
await hasPermission('project', 'view', {
project: project.id
});
} catch (err) {
// if the user hasn't got permission to view the project, but the project is in the organization
// allow the user to get the project
if (project.organization != null) {
await hasPermission('organization', 'viewProject', {
organization: project.organization
});
}
}
await Helpers(sqlClientPool).checkOrgProjectViewPermission(hasPermission, project.id)

return project;
};
Expand All @@ -211,19 +175,7 @@ export const getProjectByName: ResolverFn = async (
return null;
}

try {
await hasPermission('project', 'view', {
project: project.id
});
} catch (err) {
// if the user hasn't got permission to view the project, but the project is in the organization
// allow the user to get the project
if (project.organization != null) {
await hasPermission('organization', 'viewProject', {
organization: project.organization
});
}
}
await Helpers(sqlClientPool).checkOrgProjectViewPermission(hasPermission, project.id)

return project;
};
Expand Down

0 comments on commit af1cfee

Please sign in to comment.