Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SWG-9025 Fetch organization standardization configuration command #410

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ USAGE
* [`swaggerhub api:unpublish OWNER/API_NAME/VERSION`](#swaggerhub-apiunpublish)
* [`swaggerhub api:update OWNER/API_NAME/[VERSION]`](#swaggerhub-apiupdate)
* [`swaggerhub api:validate OWNER/API_NAME/[VERSION]`](#swaggerhub-apivalidate)
* [`swaggerhub api:validate:download-rules OWNER`](#swaggerhub-apivalidatedownload-rules)
* [`swaggerhub api:validate:local`](#swaggerhub-apivalidatelocal)
* [`swaggerhub configure`](#swaggerhub-configure)
* [`swaggerhub domain:create OWNER/DOMAIN_NAME/[VERSION]`](#swaggerhub-domaincreate)
Expand Down Expand Up @@ -425,6 +426,37 @@ EXAMPLES

_See code: [src/commands/api/validate/local.js](https://github.com/SmartBear/swaggerhub-cli/blob/v0.8.1/src/commands/api/validate/local.js)_

## `swaggerhub api:validate:download-rules`

Get existing SwaggerHub's organization standardization ruleset.

```
USAGE
$ swaggerhub api:validate:download-rules OWNER [-s] [-d] [-h]

ARGUMENTS
OWNER Which organization standardization rules to fetch from SwaggerHub

FLAGS
-d, --include-disabled-rules Includes disabled rules in fetched organization's ruleset
-h, --help Show CLI help.
-s, --include-system-rules Includes system rules in fetched organization's ruleset

DESCRIPTION
Get existing SwaggerHub's organization standardization ruleset.
Requires organization name argument. An error will occur if provided organization doesn't exist
or your account is not permitted to access that organization's settings.
If the flag `-s` or `--include-system-rules` is used, the returned ruleset will also include SwaggerHub system rules.
If the flag `-d` or `--include-disabled-rules` is used, the returned ruleset will also include disabled custom rules

EXAMPLES
$ swaggerhub api:validate:download-rules myOrg -s

$ swaggerhub api:validate:download-rules myOrg --include-disabled-rules -s
```

_See code: [src/commands/api/validate/download-rules.js](https://github.com/SmartBear/swaggerhub-cli/blob/v0.8.1/src/commands/api/validate/download-rules.js)_

## `swaggerhub configure`

configure application settings
Expand Down
58 changes: 58 additions & 0 deletions src/commands/api/validate/download-rules.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
const { Flags, Args } = require('@oclif/core')
const BaseCommand = require('../../../support/command/base-command')
const { pipeAsync } = require('../../../utils/general')
const { getResponseContent } = require('../../../support/command/handle-response')
const { getStandardization } = require('../../../requests/standardization')

class ValidateDownloadRulesCommand extends BaseCommand {
async run() {
const { args, flags } = await this.parse(ValidateDownloadRulesCommand)

const includeSystemRules = flags['include-system-rules'] ?? false
const includeDisabledRules = flags['include-disabled-rules'] ?? false
const organization = args['OWNER']

const organizationRuleset = await this.getExportedOrganizationRuleset(organization, {includeSystemRules, includeDisabledRules})
this.log(JSON.stringify(organizationRuleset, null, 2))
MateuszPol marked this conversation as resolved.
Show resolved Hide resolved
}

getExportedOrganizationRuleset(orgName, queryParams) {
return this.executeHttp({
execute: () => getStandardization([orgName, 'spectral'], queryParams),
onResolve: pipeAsync(getResponseContent, JSON.parse),
options: {}
})
}
}

ValidateDownloadRulesCommand.description = `Get existing SwaggerHub's organization standardization ruleset.
Requires organization name argument. An error will occur if provided organization doesn't exist
or your account is not permitted to access that organization's settings.
If the flag \`-s\` or \`--include-system-rules\` is used, the returned ruleset will also include SwaggerHub system rules.
If the flag \`-d\` or \`--include-disabled-rules\` is used, the returned ruleset will also include disabled custom rules`

ValidateDownloadRulesCommand.examples = [
'swaggerhub api:validate:download-rules myOrg -s',
'swaggerhub api:validate:download-rules myOrg --include-disabled-rules -s',
]

ValidateDownloadRulesCommand.args = {
'OWNER': Args.string({
required: true,
description: 'Which organization standardization rules to fetch from SwaggerHub'
})
}
ValidateDownloadRulesCommand.flags = {
'include-system-rules': Flags.boolean({
char: 's',
description: 'Includes system rules in fetched organization\'s ruleset',
required: false
}),
'include-disabled-rules': Flags.boolean({
char: 'd',
description: 'Includes disabled rules in fetched organization\'s ruleset',
required: false
}),
...BaseCommand.flags
}
module.exports = ValidateDownloadRulesCommand
15 changes: 14 additions & 1 deletion src/requests/standardization.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@ const postStandardization = (pathParams, body) => {
})
}

const getStandardization = (pathParams, queryParams) => {
const { SWAGGERHUB_URL, SWAGGERHUB_API_KEY } = config.getConfig()

return http({
url: [SWAGGERHUB_URL, 'standardization', ...pathParams],
query: queryParams,
accept: 'json',
auth: SWAGGERHUB_API_KEY,
method: 'GET',
})
}

module.exports = {
postStandardization
postStandardization,
getStandardization
}
91 changes: 91 additions & 0 deletions test/commands/api/validate/download-rules.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
const { expect, test } = require('@oclif/test')
const config = require('../../../../src/config')
const {
ruleset,
rulesetWithDisabledRule,
rulesetWithSystemRule,
rulesetWithDisabledAndSystemRule
} = require('../../../resources/rulesets')

const orgName = 'org1'
describe('invalid api:validate:download-rules', () => {
test
.stdout()
.command(['api:validate:download-rules'])
.exit(2)
.it('runs api:validate:download-rules with no organization name provided')

test
.stub(config, 'getConfig', () => ({ SWAGGERHUB_URL: 'https://api.swaggerhub.com' }))
.nock('https://api.swaggerhub.com/standardization',{ reqheaders: { Accept: 'application/json' }}, api => api
.get(`/org2/spectral`)
.query({ includeSystemRules : false, includeDisabledRules : false})
.reply(404, 'Access Denied')
)
.command(['api:validate:download-rules', 'org2'])
.exit(2)
.it('Access Denied returned when trying to fetch ruleset of not existing or not available organization')

test
.stub(config, 'isURLValid', () => false)
.command(['api:validate:download-rules', 'org1'])
.catch(ctx =>
expect(ctx.message).to.equal('Please verify that the configured SwaggerHub URL is correct.')
)
.it('invalid SwaggerHub URL provided in the config')
})

describe('valid api:validate:download-rules', () => {
test
.stub(config, 'getConfig', () => ({ SWAGGERHUB_URL: 'https://api.swaggerhub.com' }))
.nock('https://api.swaggerhub.com/standardization',{ reqheaders: { Accept: 'application/json' }}, api => api
.get(`/${orgName}/spectral`)
.query({ includeSystemRules : false, includeDisabledRules : false})
.reply(200, ruleset)
)
.stdout()
.command(['api:validate:download-rules', 'org1'])
.it('runs api:validate:download-rules and returns organization rules without system rules nor disabled rules', ctx => {
expect(ctx.stdout).to.contains(JSON.stringify(ruleset, null, 2))
})

test
.stub(config, 'getConfig', () => ({ SWAGGERHUB_URL: 'https://api.swaggerhub.com' }))
.nock('https://api.swaggerhub.com/standardization',{ reqheaders: { Accept: 'application/json' }}, api => api
.get(`/${orgName}/spectral`)
.query({ includeSystemRules : true, includeDisabledRules : false})
.reply(200, rulesetWithSystemRule)
)
.stdout()
.command(['api:validate:download-rules', 'org1', '-s'])
.it('runs api:validate:download-rules and returns organization rules with system rules, but without disabled rules', ctx => {
expect(ctx.stdout).to.contains(JSON.stringify(rulesetWithSystemRule, null, 2))
})

test
.stub(config, 'getConfig', () => ({ SWAGGERHUB_URL: 'https://api.swaggerhub.com' }))
.nock('https://api.swaggerhub.com/standardization',{ reqheaders: { Accept: 'application/json' }}, api => api
.get(`/${orgName}/spectral`)
.query({ includeSystemRules : false, includeDisabledRules : true})
.reply(200, rulesetWithDisabledRule)
)
.stdout()
.command(['api:validate:download-rules', 'org1', '-d'])
.it('runs api:validate:download-rules and returns organization rules without system rules, but with disabled rules', ctx => {
expect(ctx.stdout).to.contains(JSON.stringify(rulesetWithDisabledRule, null, 2))
})


test
.stub(config, 'getConfig', () => ({ SWAGGERHUB_URL: 'https://api.swaggerhub.com' }))
.nock('https://api.swaggerhub.com/standardization',{ reqheaders: { Accept: 'application/json' }}, api => api
.get(`/${orgName}/spectral`)
.query({ includeSystemRules : true, includeDisabledRules : true})
.reply(200, rulesetWithDisabledAndSystemRule)
)
.stdout()
.command(['api:validate:download-rules', 'org1', '-s', '-d'])
.it('runs api:validate:download-rules and returns organization rules with system rules and disabled rules', ctx => {
expect(ctx.stdout).to.contains(JSON.stringify(rulesetWithDisabledAndSystemRule, null, 2))
})
})
68 changes: 68 additions & 0 deletions test/resources/rulesets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const baseRulesetConfiguration = {
"extends": [
"https://api.dev.swaggerhub.com/standardization/spectral/system-rules",
"https://api.dev.swaggerhub.com/standardization/spectral/styleguide/owasp-top-10.js"
],
"documentationUrl": "https://support.smartbear.com/swaggerhub/docs/en/manage-resource-access/api-standardization.html#UUID-5425b1a0-27d3-677c-54f2-f2acab09a7a6_section-idm4667026578035233960922912739",
}

const basicRules = {
"owasp:api1:2019-no-numeric-ids": "error",
"custom-rule": {
"description": "description",
"message": "message",
"formats": [
"oas2",
"oas3_0",
"oas3_1"
],
"severity": "off",
"given": "$.info.title",
"then": {
"function": "pattern",
"functionOptions": {
"match": "some-title"
}
}
}
}

const disabledRule ={
"disabled-custom-rule": {
"description": "description",
"message": "message",
"formats": [
"oas2",
"oas3_0",
"oas3_1"
],
"severity": "off",
"given": "$.info.title",
"then": {
"function": "pattern",
"functionOptions": {
"match": "some-title"
}
}
}
}

const systemRule ={
"swaggerhub-asyncapi-tags-at-least-one": "error"
}

const ruleset = {...baseRulesetConfiguration, rules: basicRules}
const rulesetWithSystemRule = {...baseRulesetConfiguration, rules: {...basicRules, ...systemRule}}
const rulesetWithDisabledRule = {...baseRulesetConfiguration, rules: {...basicRules, ...disabledRule}}
const rulesetWithDisabledAndSystemRule = {...baseRulesetConfiguration, rules: {...basicRules, ...disabledRule, ...systemRule}}

module.exports = {
ruleset,
rulesetWithSystemRule,
rulesetWithDisabledRule,
rulesetWithDisabledAndSystemRule
}




Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need these 4 blank lines here ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh wow, thanks