Skip to content

Commit 18a98c6

Browse files
authored
Feature/394 dok21 (#447)
* feat: add types for OpenAPI Specification v3.2.0 * feat: add rule DOK.21 * test: add test suite for DOK.21 * docs: add documentation for rule DOK.21 --------- Signed-off-by: Mats Johansson <extern.mats.johansson@digg.se>
1 parent d6dd138 commit 18a98c6

File tree

8 files changed

+478
-2
lines changed

8 files changed

+478
-2
lines changed

GUIDELINES.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Detta dokument specificerar reglerna som verktyget tillämpar.
4141
- [ID: DOK.17](#id-dok17)
4242
- [ID: DOK.19](#id-dok19)
4343
- [ID: DOK.20](#id-dok20)
44+
- [ID: DOK.21](#id-dok21)
4445
2. [Område: Datum- och tidsformat](#område-datum--och-tidsformat)
4546
- [ID: DOT.01](#id-dot01)
4647
- [ID: DOT.04](#id-dot04)
@@ -93,7 +94,7 @@ Detta dokument specificerar reglerna som verktyget tillämpar.
9394

9495
## Område: Dokumentation
9596

96-
**Täckningsgrad: 46%**
97+
**Täckningsgrad: 50%**
9798

9899
### ID: DOK.01
99100

@@ -405,6 +406,33 @@ I exemplet ovan, så exemplifieras regeln med GET samt en POST operation, där r
405406

406407
---
407408

409+
### ID: DOK.21
410+
411+
**Krav:** Krav på autentisering SKALL anges i specifikationen.
412+
413+
**Typ:** SKALL
414+
415+
**JSON Path Plus-uttryck:**
416+
417+
```
418+
$
419+
```
420+
421+
**Förklaring:**
422+
Regeln förutsätter att det finns minst en förekomst av objektet `security`, antingen på rot- eller operationsnivå.
423+
424+
**Exempel:**
425+
426+
![Exempelbild som visar var security-objektet kan existera i en OpenAPI description](images/dok21-1.png)
427+
428+
_Security-objektet kan existera på antingen rot- eller operationsnivå, eller båda._
429+
430+
![Exempelbild som visar att security-objektet också kan användas när API:et saknar säkerhet](images/dok21-2.png)
431+
432+
_Om säkerhet saknas så bör det signaleras genom att tilldela security-objektet en tom array._
433+
434+
---
435+
408436
## Område: Datum- och tidsformat
409437

410438
**Täckningsgrad: 50%**

REUSE.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ path = [
3030
"images/dok17.png",
3131
"images/dok19.png",
3232
"images/dok20.png",
33+
"images/dok21-1.png",
34+
"images/dok21-2.png",
3335
"images/dok3.png",
3436
"images/dok6-1.png",
3537
"images/dok6-2.png",

images/dok21-1.png

41.4 KB
Loading

images/dok21-2.png

13 KB
Loading

src/rulesets/DokRules.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ import { DiagnosticSeverity } from '@stoplight/types';
99
import { Dok03Base } from './rulesetUtil.js';
1010
import { Dok15Base } from './rulesetUtil.js';
1111
import { commonEnglishWords, commonSwedishWords } from './constants/CommonWords.js';
12+
import {
13+
OpenAPIObject,
14+
OperationObject,
15+
PathItemObject,
16+
PathsObject,
17+
SecurityRequirementObject,
18+
} from '../types/openapi-3.0.js';
1219
const moduleName: string = 'DokRules.js';
1320

1421
export class Dok15Get extends Dok15Base {
@@ -426,7 +433,71 @@ export class Dok19 extends BaseRuleset {
426433
}
427434
severity = DiagnosticSeverity.Error;
428435
}
436+
export class Dok21 extends BaseRuleset {
437+
static customProperties: CustomProperties = {
438+
område: 'Dokumentation',
439+
id: 'DOK.21',
440+
};
441+
given = '$';
442+
message = 'Krav på autentisering SKALL anges i specifikationen.';
443+
then = [
444+
{
445+
function: (targetVal: OpenAPIObject, _opts: string, paths: string[]) => {
446+
const rootSecurity: SecurityRequirementObject[] | undefined = targetVal.security;
447+
448+
if (rootSecurity) {
449+
if (Array.isArray(rootSecurity)) {
450+
return [];
451+
}
452+
}
453+
454+
const hasSecurityInAnyPath = (paths: PathsObject | undefined): boolean => {
455+
if (!paths) return false;
456+
return Object.values(paths).some((pathItem: PathItemObject | undefined) => {
457+
if (!pathItem) return false;
458+
459+
return (Object.keys(pathItem) as (keyof PathItemObject)[])
460+
.filter((k) => ['get', 'put', 'post', 'delete', 'options', 'head', 'patch', 'trace'].includes(k))
461+
.some((k) => {
462+
const op = pathItem[k] as OperationObject | undefined;
463+
return op?.security;
464+
});
465+
});
466+
};
429467

468+
if (hasSecurityInAnyPath(targetVal.paths)) {
469+
return [];
470+
}
471+
472+
return [
473+
{
474+
message: this.message,
475+
severity: this.severity,
476+
paths: paths,
477+
},
478+
];
479+
},
480+
},
481+
{
482+
function: (targetVal: string, _opts: string, paths: string[]) => {
483+
this.trackRuleExecutionHandler(
484+
JSON.stringify(targetVal, null, 2),
485+
_opts,
486+
paths,
487+
this.severity,
488+
this.constructor.name,
489+
moduleName,
490+
Dok21.customProperties,
491+
);
492+
},
493+
},
494+
];
495+
constructor() {
496+
super();
497+
super.initializeFormats(['OAS3']);
498+
}
499+
severity = DiagnosticSeverity.Error;
500+
}
430501
export class Dok01 extends BaseRuleset {
431502
static customProperties: CustomProperties = {
432503
område: 'Dokumentation',

0 commit comments

Comments
 (0)