-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #177 from OpenPathfinder/feat/adminRepoCreationOnly
- Loading branch information
Showing
6 changed files
with
387 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
const knexInit = require('knex') | ||
const { getConfig } = require('../../src/config') | ||
const adminRepoCreationOnly = require('../../src/checks/complianceChecks/adminRepoCreationOnly') | ||
const { | ||
resetDatabase, initializeStore | ||
} = require('../../__utils__') | ||
const { sampleGithubOrg } = require('../../__fixtures__') | ||
|
||
const { dbSettings } = getConfig('test') | ||
|
||
let knex | ||
let project | ||
let check | ||
|
||
let addProject, | ||
addGithubOrg, | ||
getAllResults, | ||
getAllTasks, | ||
getAllAlerts, | ||
addAlert, | ||
addTask, | ||
addResult, | ||
getCheckByCodeName | ||
|
||
beforeAll(async () => { | ||
knex = knexInit(dbSettings); | ||
({ | ||
addProject, | ||
addGithubOrganization: addGithubOrg, | ||
getAllResults, | ||
getAllTasks, | ||
getAllAlerts, | ||
addAlert, | ||
addTask, | ||
addResult, | ||
getCheckByCodeName | ||
} = initializeStore(knex)) | ||
check = await getCheckByCodeName('adminRepoCreationOnly') | ||
}) | ||
|
||
beforeEach(async () => { | ||
await resetDatabase(knex) | ||
project = await addProject({ name: sampleGithubOrg.login }) | ||
}) | ||
|
||
afterAll(async () => { | ||
await knex.destroy() | ||
}) | ||
|
||
describe('Integration: adminRepoCreationOnly', () => { | ||
test('Should add results without alerts or tasks', async () => { | ||
// Add a passed check scenario | ||
await addGithubOrg({ | ||
login: sampleGithubOrg.login, | ||
html_url: sampleGithubOrg.html_url, | ||
project_id: project.id, | ||
members_can_create_public_repositories: false | ||
}) | ||
// Check that the database is empty | ||
let results = await getAllResults() | ||
expect(results.length).toBe(0) | ||
let alerts = await getAllAlerts() | ||
expect(alerts.length).toBe(0) | ||
let tasks = await getAllTasks() | ||
expect(tasks.length).toBe(0) | ||
// Run the check | ||
await expect(adminRepoCreationOnly(knex)).resolves.toBeUndefined() | ||
// Check that the database has the expected results | ||
results = await getAllResults() | ||
expect(results.length).toBe(1) | ||
expect(results[0].status).toBe('passed') | ||
expect(results[0].compliance_check_id).toBe(check.id) | ||
alerts = await getAllAlerts() | ||
expect(alerts.length).toBe(0) | ||
tasks = await getAllTasks() | ||
expect(tasks.length).toBe(0) | ||
}) | ||
|
||
test('Should delete (previous alerts and tasks) and add results', async () => { | ||
// Prepare the Scenario | ||
await addGithubOrg({ | ||
login: sampleGithubOrg.login, | ||
html_url: sampleGithubOrg.html_url, | ||
project_id: project.id, | ||
members_can_create_public_repositories: false | ||
}) | ||
await addAlert({ compliance_check_id: check.id, project_id: project.id, title: 'existing', description: 'existing', severity: 'critical' }) | ||
await addTask({ compliance_check_id: check.id, project_id: project.id, title: 'existing', description: 'existing', severity: 'critical' }) | ||
// Check that the database has the expected results | ||
let results = await getAllResults() | ||
expect(results.length).toBe(0) | ||
let alerts = await getAllAlerts() | ||
expect(alerts.length).toBe(1) | ||
expect(alerts[0].compliance_check_id).toBe(check.id) | ||
let tasks = await getAllTasks() | ||
expect(tasks.length).toBe(1) | ||
expect(tasks[0].compliance_check_id).toBe(check.id) | ||
// Run the check | ||
await adminRepoCreationOnly(knex) | ||
// Check that the database has the expected results | ||
results = await getAllResults() | ||
expect(results.length).toBe(1) | ||
expect(results[0].status).toBe('passed') | ||
alerts = await getAllAlerts() | ||
expect(alerts.length).toBe(0) | ||
tasks = await getAllTasks() | ||
expect(tasks.length).toBe(0) | ||
}) | ||
test('Should add (alerts and tasks) and update results', async () => { | ||
// Prepare the Scenario | ||
await addGithubOrg({ login: sampleGithubOrg.login, html_url: sampleGithubOrg.html_url, project_id: project.id, members_can_create_public_repositories: true }) | ||
await addResult({ compliance_check_id: check.id, project_id: project.id, status: 'passed', rationale: 'failed previously', severity: 'critical' }) | ||
// Check that the database has the expected results | ||
let results = await getAllResults() | ||
expect(results.length).toBe(1) | ||
expect(results[0].compliance_check_id).toBe(check.id) | ||
let alerts = await getAllAlerts() | ||
expect(alerts.length).toBe(0) | ||
let tasks = await getAllTasks() | ||
expect(tasks.length).toBe(0) | ||
// Run the check | ||
await adminRepoCreationOnly(knex) | ||
// Check that the database has the expected results | ||
results = await getAllResults() | ||
expect(results.length).toBe(1) | ||
expect(results[0].status).toBe('failed') | ||
expect(results[0].rationale).not.toBe('failed previously') | ||
alerts = await getAllAlerts() | ||
expect(alerts.length).toBe(1) | ||
expect(alerts[0].compliance_check_id).toBe(check.id) | ||
tasks = await getAllTasks() | ||
expect(tasks.length).toBe(1) | ||
expect(tasks[0].compliance_check_id).toBe(check.id) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
const validators = require('../validators') | ||
const { initializeStore } = require('../../store') | ||
const debug = require('debug')('checks:adminRepoCreationOnly') | ||
|
||
module.exports = async (knex, { projects } = {}) => { | ||
const { | ||
getAllGithubOrganizationsByProjectsId, getCheckByCodeName, | ||
getAllProjects, addAlert, addTask, upsertComplianceCheckResult, | ||
deleteAlertsByComplianceCheckId, deleteTasksByComplianceCheckId | ||
} = initializeStore(knex) | ||
debug('Collecting relevant data...') | ||
const check = await getCheckByCodeName('adminRepoCreationOnly') | ||
if (!projects || (Array.isArray(projects) && projects.length === 0)) { | ||
projects = await getAllProjects() | ||
} | ||
const organizations = await getAllGithubOrganizationsByProjectsId(projects.map(p => p.id)) | ||
|
||
debug('Extracting the validation results...') | ||
const analysis = validators.adminRepoCreationOnly({ organizations, check, projects }) | ||
|
||
debug('Deleting previous alerts and tasks to avoid orphaned records...') | ||
await deleteAlertsByComplianceCheckId(check.id) | ||
await deleteTasksByComplianceCheckId(check.id) | ||
|
||
debug('Upserting the new results...') | ||
await Promise.all(analysis.results.map(result => upsertComplianceCheckResult(result))) | ||
|
||
debug('Inserting the new Alerts and Tasks...') | ||
await Promise.all(analysis.alerts.map(alert => addAlert(alert))) | ||
await Promise.all(analysis.tasks.map(task => addTask(task))) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
const debug = require('debug')('checks:validator:adminRepoCreationOnly') | ||
const { getSeverityFromPriorityGroup, groupArrayItemsByCriteria } = require('../../utils') | ||
|
||
const groupByProject = groupArrayItemsByCriteria('project_id') | ||
|
||
// @see: https://github.com/OpenPathfinder/visionBoard/issues/75 | ||
module.exports = ({ organizations = [], check, projects = [] }) => { | ||
debug('Validating that only admins can create public repositories...') | ||
debug('Grouping organizations by project...') | ||
const organizationsGroupedByProject = groupByProject(organizations) | ||
|
||
const alerts = [] | ||
const results = [] | ||
const tasks = [] | ||
|
||
debug('Processing organizations...') | ||
organizationsGroupedByProject.forEach((projectOrgs) => { | ||
debug(`Processing project (${projectOrgs[0].project_id})`) | ||
const project = projects.find(p => p.id === projectOrgs[0].project_id) | ||
|
||
const baseData = { | ||
project_id: projectOrgs[0].project_id, | ||
compliance_check_id: check.id, | ||
severity: getSeverityFromPriorityGroup(check.default_priority_group) | ||
} | ||
|
||
const result = { ...baseData } | ||
const task = { ...baseData } | ||
const alert = { ...baseData } | ||
|
||
const failedOrgs = projectOrgs.filter(org => org.members_can_create_public_repositories === true).map(org => org.login) | ||
const unknownOrgs = projectOrgs.filter(org => org.members_can_create_public_repositories === null).map(org => org.login) | ||
|
||
if (projectOrgs.every(org => org.members_can_create_public_repositories === false)) { | ||
result.status = 'passed' | ||
result.rationale = 'Only Admins can create public repositories in the organization(s)' | ||
} else if (failedOrgs.length) { | ||
result.status = 'failed' | ||
result.rationale = `Not Only Admins can create public repositories in the following (${failedOrgs.join(',')}) organization(s)` | ||
alert.title = `Not Only Admins can create public repositories in the following (${failedOrgs.join(',')}) organization(s)` | ||
alert.description = `Check the details on ${check.details_url}` | ||
task.title = `Limit public repo creation to admins for the following (${failedOrgs.join(',')}) organization(s)` | ||
task.description = `Check the details on ${check.details_url}` | ||
} else if (unknownOrgs.length) { | ||
result.status = 'unknown' | ||
result.rationale = `It was not possible to confirm if only admins can create public repositories in the following (${unknownOrgs.join(',')}) organization(s)` | ||
} | ||
// Include only the task if was populated | ||
if (Object.keys(task).length > Object.keys(baseData).length) { | ||
debug(`Adding task for project (${project.id})`) | ||
tasks.push(task) | ||
} | ||
// Include only the alert if was populated | ||
if (Object.keys(alert).length > Object.keys(baseData).length) { | ||
debug(`Adding alert for project (${project.id})`) | ||
alerts.push(alert) | ||
} | ||
// Always include the result | ||
results.push(result) | ||
debug(`Processed project (${project.id})`) | ||
}) | ||
|
||
return { | ||
alerts, | ||
results, | ||
tasks | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,11 @@ | ||
const githubOrgMFA = require('./githubOrgMFA') | ||
const softwareDesignTraining = require('./softwareDesignTraining') | ||
const adminRepoCreationOnly = require('./adminRepoCreationOnly') | ||
|
||
const validators = { | ||
githubOrgMFA, | ||
softwareDesignTraining | ||
softwareDesignTraining, | ||
adminRepoCreationOnly | ||
} | ||
|
||
module.exports = validators |
Oops, something went wrong.