Skip to content

Commit

Permalink
Merge pull request #46 from stoplightio/fix/oas-security
Browse files Browse the repository at this point in the history
Fix oas2 versus oas3 security schemes
  • Loading branch information
casserni authored Oct 18, 2018
2 parents fd4c9bf + 749dd72 commit 4e1e6e8
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 65 deletions.
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
"license": "MIT",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"files": ["lib"],
"files": [
"lib"
],
"scripts": {
"build": "tsc -p tsconfig.json",
"format": "prettier --write \"src/**/*.{ts}\"",
Expand All @@ -19,13 +21,15 @@
"dependencies": {
"ajv": "6.5.x",
"jsonpath": "git://github.com/stoplightio/jsonpath.git#fe90d42",
"lodash.merge": "^4.6.1",
"lodash.get": "4.4.x",
"lodash.merge": "4.6.x",
"should": "13.2.x"
},
"devDependencies": {
"@types/jest": "23.3.x",
"@types/jsonpath": "0.2.x",
"@types/lodash.merge": "^4.6.4",
"@types/lodash.get": "4.4.x",
"@types/lodash.merge": "4.6.x",
"@types/node": "10.12.x",
"jest": "23.6.x",
"prettier": "1.14.x",
Expand Down
159 changes: 114 additions & 45 deletions src/rulesets/oas/functions/oasOpSecurityDefined/__tests__/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,66 +4,135 @@ import { commonOasRuleset } from '../../../index';
const ruleset = commonOasRuleset();

describe('oasOpSecurityDefined', () => {
const s = new Spectral({
rulesets: [
{
functions: ruleset.functions,
rules: {
oas2: {
'operation-security-defined': Object.assign(
ruleset.rules['oas2|oas3']['operation-security-defined'],
{
enabled: true,
}
),
describe('oas2', () => {
const s = new Spectral({
rulesets: [
{
functions: ruleset.functions,
rules: {
oas2: {
'operation-security-defined': Object.assign(
ruleset.rules.oas2['operation-security-defined'],
{
enabled: true,
}
),
},
},
},
},
],
});
],
});

test('validate a correct object (just in body)', () => {
const results = s.run({
spec: 'oas2',
target: {
securityDefinitions: {
apikey: {},
test('validate a correct object (just in body)', () => {
const results = s.run({
spec: 'oas2',
target: {
securityDefinitions: {
apikey: {},
},
paths: {
'/path': {
get: {
security: [
{
apikey: [],
},
],
},
},
},
},
paths: {
'/path': {
get: {
security: [
{
apikey: [],
},
],
});
expect(results.length).toEqual(0);
});

test('return errors on invalid object', () => {
const results = s.run({
spec: 'oas2',
target: {
securityDefinitions: {},
paths: {
'/path': {
get: {
security: [
{
apikey: [],
},
],
},
},
},
},
},
});

expect(results.length).toEqual(1);
});
expect(results.length).toEqual(0);
});

test('return errors on invalid object', () => {
const results = s.run({
spec: 'oas2',
target: {
securityDefinitions: {},
paths: {
'/path': {
get: {
security: [
describe('oas3', () => {
const s = new Spectral({
rulesets: [
{
functions: ruleset.functions,
rules: {
oas3: {
'operation-security-defined': Object.assign(
ruleset.rules.oas3['operation-security-defined'],
{
apikey: [],
},
],
enabled: true,
}
),
},
},
},
},
],
});

expect(results.length).toEqual(1);
test('validate a correct object (just in body)', () => {
const results = s.run({
spec: 'oas3',
target: {
components: {
securitySchemes: {
apikey: {},
},
},
paths: {
'/path': {
get: {
security: [
{
apikey: [],
},
],
},
},
},
},
});
expect(results.length).toEqual(0);
});

test('return errors on invalid object', () => {
const results = s.run({
spec: 'oas3',
target: {
components: {},
paths: {
'/path': {
get: {
security: [
{
apikey: [],
},
],
},
},
},
},
});

expect(results.length).toEqual(1);
});
});
});
24 changes: 18 additions & 6 deletions src/rulesets/oas/functions/oasOpSecurityDefined/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
const _get = require('lodash.get');

import { ensureRule } from '../../../../functions/utils/ensureRule';
import { IRuleFunction, IRuleOpts, IRuleResult, Rule } from '../../../../types';
import { IRule, IRuleFunction, IRuleOpts, IRuleResult, Path } from '../../../../types';

export const oasOpSecurityDefined: IRuleFunction<Rule> = (opts: IRuleOpts<Rule>) => {
const results: IRuleResult[] = [];
export type functionName = 'oasOpSecurityDefined';

const { object, meta } = opts;
export interface IOasOpSecurityDefinedRule extends IRule {
function: functionName;
input: {
schemesPath: Path;
};
}

const { paths = {}, securityDefinitions = {} } = object;
export const oasOpSecurityDefined: IRuleFunction<IOasOpSecurityDefinedRule> = (
opts: IRuleOpts<IOasOpSecurityDefinedRule>
) => {
const results: IRuleResult[] = [];

const allDefs = Object.keys(securityDefinitions);
const { object, meta, rule } = opts;
const { paths = {} } = object;
const schemes = _get(object, rule.input.schemesPath) || {};
const allDefs = Object.keys(schemes);

for (const path in paths) {
if (Object.keys(paths[path]).length > 0)
Expand Down
39 changes: 30 additions & 9 deletions src/rulesets/oas/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,6 @@ export const commonOasRuleset = (): IRuleset => {
type: RuleType.STYLE,
tags: ['operation'],
},
'operation-security-defined': {
enabled: true,
function: 'oasOpSecurityDefined',
path: '$',
summary:
'Operation `security` values must match a scheme defined in global `securityDefinitions`.',
type: RuleType.VALIDATION,
tags: ['operation'],
},
'operation-operationId-unique': {
enabled: true,
function: 'oasOpIdUnique',
Expand Down Expand Up @@ -429,6 +420,36 @@ export const commonOasRuleset = (): IRuleset => {
tags: ['api'],
},
},

oas2: {
'operation-security-defined': {
enabled: true,
function: 'oasOpSecurityDefined',
input: {
schemesPath: ['securityDefinitions'],
},
path: '$',
summary:
'Operation `security` values must match a scheme defined in the `securityDefinitions` object.',
type: RuleType.VALIDATION,
tags: ['operation'],
},
},

oas3: {
'operation-security-defined': {
enabled: true,
function: 'oasOpSecurityDefined',
input: {
schemesPath: ['components', 'securitySchemes'],
},
path: '$',
summary:
'Operation `security` values must match a scheme defined in the `components.securitySchemes` object.',
type: RuleType.VALIDATION,
tags: ['operation'],
},
},
},
};
};
16 changes: 14 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,14 @@
resolved "https://registry.yarnpkg.com/@types/jsonpath/-/jsonpath-0.2.0.tgz#13c62db22a34d9c411364fac79fd374d63445aa1"
integrity sha512-v7qlPA0VpKUlEdhghbDqRoKMxFB3h3Ch688TApBJ6v+XLDdvWCGLJIYiPKGZnS6MAOie+IorCfNYVHOPIHSWwQ==

"@types/lodash.merge@^4.6.4":
"@types/lodash.get@4.4.x":
version "4.4.4"
resolved "https://registry.yarnpkg.com/@types/lodash.get/-/lodash.get-4.4.4.tgz#34b67841594e4ddc8853341d65e971a38cb4e2f0"
integrity sha512-6igkhtKoWAEvTWCgd5uubiuxXLUY/kljQOQZV1G5Y7SrivpmCU+NWG5tGLgRBkccobrDljbJYzBM2vgCG4Oc8Q==
dependencies:
"@types/lodash" "*"

"@types/lodash.merge@4.6.x":
version "4.6.4"
resolved "https://registry.yarnpkg.com/@types/lodash.merge/-/lodash.merge-4.6.4.tgz#0eaae4c82b82d0426612ba929f53edafe5402c58"
integrity sha512-usLWpRAicaNbx0VfNDREEgGWvp88inclJLXLJ3NpT83eUE4O05LJdYNRTofHq6pb/NiMZjzNVJHdgPvPzMfu6g==
Expand Down Expand Up @@ -2299,7 +2306,12 @@ locate-path@^2.0.0:
p-locate "^2.0.0"
path-exists "^3.0.0"

lodash.merge@^4.6.1:
lodash.get@4.4.x:
version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=

lodash.merge@4.6.x:
version "4.6.1"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.1.tgz#adc25d9cb99b9391c59624f379fbba60d7111d54"
integrity sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==
Expand Down

0 comments on commit 4e1e6e8

Please sign in to comment.