Skip to content

Commit 86f8ffc

Browse files
authored
feat: add rule DOK.08
Signed-off-by: Mats Johansson <extern.mats.johansson@digg.se>
1 parent d9b3479 commit 86f8ffc

File tree

7 files changed

+247
-4
lines changed

7 files changed

+247
-4
lines changed

.prettierrc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
"printWidth": 120,
77
"htmlWhitespaceSensitivity": "ignore",
88
"bracketSameLine": false,
9-
"vueIndentScriptAndStyle": true
9+
"vueIndentScriptAndStyle": true,
10+
"trailingComma": "all"
1011
}
11-

GUIDELINES.md

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ Detta dokument specificerar reglerna som verktyget tillämpar.
3434
- [ID: DOK.03](#id-dok03)
3535
- [ID: DOK.06](#id-dok06)
3636
- [ID: DOK.07](#id-dok07)
37+
- [ID: DOK.08](#id-dok08)
3738
- [ID: DOK.15](#id-dok15)
3839
- [ID: DOK.17](#id-dok17)
3940
- [ID: DOK.19](#id-dok19)
@@ -79,8 +80,7 @@ Detta dokument specificerar reglerna som verktyget tillämpar.
7980
- [ID: SAK.16](#id-sak16)
8081
- [ID: SAK.18](#id-sak18)
8182
10. [Område: Förutsättningar](#område-förutsättningar)
82-
83-
- [ID: FOR.02](#id-for02)
83+
- [ID: FOR.02](#id-for02)
8484

8585
## Område: Dokumentation
8686

@@ -203,6 +203,43 @@ Regeln förutsätter att det finns en förekomst av objektet `info` med underlig
203203

204204
---
205205

206+
### ID: DOK.08
207+
208+
**Krav:** Ett API:s servicenivå SKALL finnas tydligt beskriven i dokumentationen.
209+
210+
**Typ:** SKALL
211+
212+
**JSON Path Plus-uttryck:**
213+
214+
```
215+
$
216+
```
217+
218+
**Förklaring:**
219+
Regeln förutsätter att det finns en förekomst av minst ett av objekten `info.termsOfService`, `info.x-sla` eller `externalDocs` med följande strukturer:
220+
221+
- info
222+
223+
- termsOfService
224+
- x-sla
225+
- availability
226+
- responseTime
227+
- support
228+
229+
- externalDocs
230+
- description
231+
- url
232+
233+
`externalDocs.description` måste innehålla texten "service level agreement" eller "SLA", och `externalDocs.url` måste vara en giltig URL.
234+
235+
**Exempel:**
236+
237+
![Exempelbild på ovan nämnda objekts placering i en OpenAPI Description](images/dok8.png)
238+
239+
_Ett av objekten räcker för att uppfylla regeln._
240+
241+
---
242+
206243
### ID: DOK.15
207244

208245
**Krav:** I dokumentationen av API:et SKALL exempel på API:ets fråga (en:request) och svar (en:reply) finnas i sin helhet.

REUSE.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ path = [
3434
"images/dok6-1.png",
3535
"images/dok6-2.png",
3636
"images/dok7.png",
37+
"images/dok8.png",
3738
"images/dot1-2.png",
3839
"images/dot1.png",
3940
"images/dot4.png",

images/dok8.png

68.6 KB
Loading

rulesets/DokRules.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,78 @@ export class Dok07 extends BaseRuleset {
214214
}
215215
severity = DiagnosticSeverity.Warning;
216216
}
217+
export class Dok08 extends BaseRuleset {
218+
static customProperties: CustomProperties = {
219+
område: 'Dokumentation',
220+
id: 'DOK.08',
221+
};
222+
given = '$';
223+
message = 'Ett API:s servicenivå SKALL finnas tydligt beskriven i dokumentationen.';
224+
then = [
225+
{
226+
function: (targetVal: any, _opts: string, paths: string[]) => {
227+
const isValidUrl = (url: string): boolean => {
228+
const urlPattern = new RegExp('^(https?:\\/\\/)?(www\\.)?([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,}(\\/\\S*)?$');
229+
return urlPattern.test(url);
230+
};
231+
232+
const hasValidSlaFields = (sla: any): boolean => {
233+
return !!(sla?.availability && sla?.responseTime && sla?.support);
234+
};
235+
236+
const includesSlaTerm = (description: string): boolean => {
237+
const slaTerms = ['service level agreement', 'sla'];
238+
return slaTerms.some((term) => description.includes(term));
239+
};
240+
241+
if (targetVal?.info?.termsOfService) {
242+
return [];
243+
}
244+
245+
const customSlaField = targetVal?.info?.['x-sla'];
246+
if (customSlaField && hasValidSlaFields(customSlaField)) {
247+
return [];
248+
}
249+
250+
const externalDocs = targetVal?.externalDocs;
251+
if (
252+
externalDocs?.description &&
253+
externalDocs?.url &&
254+
isValidUrl(externalDocs.url) &&
255+
includesSlaTerm(externalDocs.description.toLowerCase())
256+
) {
257+
return [];
258+
}
259+
260+
return [
261+
{
262+
message: this.message,
263+
severity: this.severity,
264+
paths: paths,
265+
},
266+
];
267+
},
268+
},
269+
{
270+
function: (targetVal: string, _opts: string, paths: string[]) => {
271+
this.trackRuleExecutionHandler(
272+
JSON.stringify(targetVal, null, 2),
273+
_opts,
274+
paths,
275+
this.severity,
276+
this.constructor.name,
277+
moduleName,
278+
Dok08.customProperties,
279+
);
280+
},
281+
},
282+
];
283+
constructor() {
284+
super();
285+
super.initializeFormats(['OAS2', 'OAS3']);
286+
}
287+
severity = DiagnosticSeverity.Error;
288+
}
217289
export class Dok19 extends BaseRuleset {
218290
static customProperties: CustomProperties = {
219291
område: 'Dokumentation',

tests/dok.test.ts

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,138 @@ testRule('Dok07', [
185185
],
186186
},
187187
]);
188+
testRule('Dok08', [
189+
{
190+
name: 'giltigt testfall - info.termsOfService finns',
191+
document: {
192+
openapi: '3.1.0',
193+
info: {
194+
version: '1.0',
195+
termsOfService: 'https://url-till-servicelevel-agreement.com/api-sla',
196+
},
197+
},
198+
errors: [],
199+
},
200+
{
201+
name: 'giltigt testfall - info.x-sla finns med samtliga tre fält',
202+
document: {
203+
openapi: '3.1.0',
204+
info: {
205+
version: '1.0',
206+
'x-sla': {
207+
availability: 'test',
208+
responseTime: 24,
209+
support: '24/7',
210+
},
211+
},
212+
},
213+
errors: [],
214+
},
215+
{
216+
name: 'ogiltigt testfall - info.x-sla finns men ett fält saknas',
217+
document: {
218+
openapi: '3.1.0',
219+
info: {
220+
version: '1.0',
221+
'x-sla': {
222+
availability: 'test',
223+
responseTime: 24,
224+
},
225+
},
226+
},
227+
errors: [
228+
{
229+
message: 'Ett API:s servicenivå SKALL finnas tydligt beskriven i dokumentationen.',
230+
severity: DiagnosticSeverity.Error,
231+
},
232+
],
233+
},
234+
{
235+
name: 'giltigt testfall - externalDocs finns med giltig url och description',
236+
document: {
237+
openapi: '3.1.0',
238+
info: {
239+
version: '1.0',
240+
},
241+
externalDocs: {
242+
description: 'Text som innehåller service level agreement',
243+
url: 'https://sla.se',
244+
},
245+
},
246+
errors: [],
247+
},
248+
{
249+
name: 'ogiltigt testfall - externalDocs finns men description saknar "service level agreement"',
250+
document: {
251+
openapi: '3.1.0',
252+
info: {
253+
version: '1.0',
254+
},
255+
externalDocs: {
256+
description: 'Text som inte innehåller vad den ska',
257+
url: 'https://sla.se',
258+
},
259+
},
260+
errors: [
261+
{
262+
message: 'Ett API:s servicenivå SKALL finnas tydligt beskriven i dokumentationen.',
263+
severity: DiagnosticSeverity.Error,
264+
},
265+
],
266+
},
267+
{
268+
name: 'ogiltigt testfall - externalDocs finns men url:en är ogiltig',
269+
document: {
270+
openapi: '3.1.0',
271+
info: {
272+
version: '1.0',
273+
},
274+
externalDocs: {
275+
description: 'Text som innehåller service level agreement',
276+
url: 'ftp:/sla.se',
277+
},
278+
},
279+
errors: [
280+
{
281+
message: 'Ett API:s servicenivå SKALL finnas tydligt beskriven i dokumentationen.',
282+
severity: DiagnosticSeverity.Error,
283+
},
284+
],
285+
},
286+
{
287+
name: 'ogiltigt testfall - externalDocs finns men ett fält saknas',
288+
document: {
289+
openapi: '3.1.0',
290+
info: {
291+
version: '1.0',
292+
},
293+
externalDocs: {
294+
description: 'Text som innehåller service level agreement',
295+
},
296+
},
297+
errors: [
298+
{
299+
message: 'Ett API:s servicenivå SKALL finnas tydligt beskriven i dokumentationen.',
300+
severity: DiagnosticSeverity.Error,
301+
},
302+
],
303+
},
304+
{
305+
name: 'ogiltigt testfall - SLA saknas helt',
306+
document: {
307+
openapi: '3.1.0',
308+
info: {
309+
version: '1.0',
310+
},
311+
},
312+
errors: [
313+
{
314+
message: 'Ett API:s servicenivå SKALL finnas tydligt beskriven i dokumentationen.',
315+
severity: DiagnosticSeverity.Error,
316+
},
317+
],
318+
},
319+
]);
188320
testRule('Dok17', [
189321
{
190322
name: 'giltigt testfall',

tests/util/rulesetTest.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ const ruleTypes = [
5959
DokRules.Dok20,
6060
DokRules.Dok06,
6161
DokRules.Dok07,
62+
DokRules.Dok08,
6263
FelRules.Fel01,
6364
FelRules.Fel02,
6465
FnsRules.Fns08,

0 commit comments

Comments
 (0)