diff --git a/README.md b/README.md index 92b394777..dd74261a5 100644 --- a/README.md +++ b/README.md @@ -81,3 +81,8 @@ All packages are licensed under the Eclipse Public License v. 2.0. You find a co 1. Run `lerna bootstrap` to install dependencies among the packages, even if a package has never been published before. Make sure you have not increased the dependency versions yet, e.g., you have a new package _newExample_ and the _oldExample_ depends on it. The _newExample_ is on version `0.0.0` (since you want to publish it as `1.0.0`) then in the _oldExample_ package.json the dependency has to be on the same version (or lower) so `"dependencies" { newExample: "^0.0.0"}}`. **Otherwise lerna will not accept linking the local _newExample_.** 2. If `lerna bootstrap` was successful you can now bump dependency versions (if required), e.g., you could now do `"dependencies" { newExample: "^1.0.0"}}` in the _oldExample_ package.json. 3. Run `lerna publish` to publish all new package versions. Lerna will then ask for every changed package whether it received a patch, minor or major update. In our example you should now select major for the _newExample_ so that it will be published as `1.0.0` version. You should login to npm via `npm login` before doing this. + +## Adapting Licenses + +One can use the VS Code plugin at to updating the copyright fields on top of each file. + diff --git a/packages/assertions/assertions-csv/changelog.md b/packages/assertions/assertions-csv/changelog.md index 1068c5a3e..2aaa13dfb 100644 --- a/packages/assertions/assertions-csv/changelog.md +++ b/packages/assertions/assertions-csv/changelog.md @@ -1,48 +1,45 @@ - # CSV Changelog - 27/05/2023 [Old CSV Path](assertions-csv/oldManual.csv) [New CSV Path](assertions-csv/manual.csv) - ## REMOVED -- `privacy-immutable-id-as-property` was removed -- `security-context-secure-fetch` was removed - +- `privacy-immutable-id-as-property` was removed +- `security-context-secure-fetch` was removed ## LINE-CHANGE -- `privacy-mutable-identifiers` was moved from Line 51 to 50 -- `privacy-temp-id-metadata` was moved from Line 52 to 51 -- `sec-body-name-json-pointer-type` was moved from Line 53 to 52 -- `sec-inj-no-intl-markup` was moved from Line 54 to 53 -- `security-jsonld-expansion` was moved from Line 56 to 54 -- `security-mutual-auth-td` was moved from Line 57 to 55 -- `security-no-execution` was moved from Line 58 to 56 -- `security-oauth-limits` was moved from Line 59 to 57 -- `security-remote-context` was moved from Line 60 to 58 -- `security-server-auth-td` was moved from Line 61 to 59 -- `security-static-context` was moved from Line 62 to 60 -- `td-context-ns-td10-namespacev10` was moved from Line 63 to 61 -- `td-default-AdditionalResponseContentType` was moved from Line 64 to 62 -- `td-default-observable` was moved from Line 65 to 63 -- `td-processor-bidi-isolation` was moved from Line 66 to 64 -- `td-producer-mixed-direction` was moved from Line 67 to 65 -- `td-security-extension` was moved from Line 68 to 66 -- `td-text-direction-first-strong` was moved from Line 69 to 67 -- `td-text-direction-language-tag` was moved from Line 70 to 68 -- `thing-model-td-generation-processor-extends` was moved from Line 71 to 69 -- `thing-model-td-generation-processor-forms` was moved from Line 72 to 70 -- `thing-model-td-generation-processor-placeholder` was moved from Line 73 to 71 -- `thing-model-td-generation-processor-required` was moved from Line 74 to 72 -- `tm-derivation-validity` was moved from Line 75 to 73 -- `tm-overwrite-interaction` was moved from Line 76 to 74 -- `tm-overwrite-types` was moved from Line 77 to 75 -- `tm-placeholder-replacement` was moved from Line 78 to 76 -- `tm-ref-recursive-extensions` was moved from Line 79 to 77 -- `tm-tmRef-overwrite-possibility` was moved from Line 80 to 78 -- `tm-tmRef-overwrite-process` was moved from Line 81 to 79 -- `tm-tmRef-overwrite-semantic-meaning` was moved from Line 82 to 80 -- `tm-tmRef2` was moved from Line 83 to 81 -- `tm-versioning-1` was moved from Line 84 to 82 +- `privacy-mutable-identifiers` was moved from Line 51 to 50 +- `privacy-temp-id-metadata` was moved from Line 52 to 51 +- `sec-body-name-json-pointer-type` was moved from Line 53 to 52 +- `sec-inj-no-intl-markup` was moved from Line 54 to 53 +- `security-jsonld-expansion` was moved from Line 56 to 54 +- `security-mutual-auth-td` was moved from Line 57 to 55 +- `security-no-execution` was moved from Line 58 to 56 +- `security-oauth-limits` was moved from Line 59 to 57 +- `security-remote-context` was moved from Line 60 to 58 +- `security-server-auth-td` was moved from Line 61 to 59 +- `security-static-context` was moved from Line 62 to 60 +- `td-context-ns-td10-namespacev10` was moved from Line 63 to 61 +- `td-default-AdditionalResponseContentType` was moved from Line 64 to 62 +- `td-default-observable` was moved from Line 65 to 63 +- `td-processor-bidi-isolation` was moved from Line 66 to 64 +- `td-producer-mixed-direction` was moved from Line 67 to 65 +- `td-security-extension` was moved from Line 68 to 66 +- `td-text-direction-first-strong` was moved from Line 69 to 67 +- `td-text-direction-language-tag` was moved from Line 70 to 68 +- `thing-model-td-generation-processor-extends` was moved from Line 71 to 69 +- `thing-model-td-generation-processor-forms` was moved from Line 72 to 70 +- `thing-model-td-generation-processor-placeholder` was moved from Line 73 to 71 +- `thing-model-td-generation-processor-required` was moved from Line 74 to 72 +- `tm-derivation-validity` was moved from Line 75 to 73 +- `tm-overwrite-interaction` was moved from Line 76 to 74 +- `tm-overwrite-types` was moved from Line 77 to 75 +- `tm-placeholder-replacement` was moved from Line 78 to 76 +- `tm-ref-recursive-extensions` was moved from Line 79 to 77 +- `tm-tmRef-overwrite-possibility` was moved from Line 80 to 78 +- `tm-tmRef-overwrite-process` was moved from Line 81 to 79 +- `tm-tmRef-overwrite-semantic-meaning` was moved from Line 82 to 80 +- `tm-tmRef2` was moved from Line 83 to 81 +- `tm-versioning-1` was moved from Line 84 to 82 diff --git a/packages/assertions/assertions-csv/report.json b/packages/assertions/assertions-csv/report.json index f8132a288..0d575f136 100644 --- a/packages/assertions/assertions-csv/report.json +++ b/packages/assertions/assertions-csv/report.json @@ -1 +1,8 @@ -{"generationDate":"Sat, 27 May 2023 01:02:28 GMT","assertionsSize":451,"implementedSize":372,"manualSize":82,"oldSize":3,"needsReviewSize":0} \ No newline at end of file +{ + "generationDate": "Sat, 27 May 2023 01:02:28 GMT", + "assertionsSize": 451, + "implementedSize": 372, + "manualSize": 82, + "oldSize": 3, + "needsReviewSize": 0 +} diff --git a/packages/assertions/assertions-td/sec-body-name-json-pointer-array.json b/packages/assertions/assertions-td/sec-body-name-json-pointer-array.json index 83e93d905..beb2c6833 100644 --- a/packages/assertions/assertions-td/sec-body-name-json-pointer-array.json +++ b/packages/assertions/assertions-td/sec-body-name-json-pointer-array.json @@ -30,7 +30,7 @@ }, "name": { "type": "string", - "pattern": "\/-" + "pattern": "/-" } }, "required": ["in", "scheme", "name"] diff --git a/packages/core/examples/tds/invalid/emptyOpArray.json b/packages/core/examples/tds/invalid/emptyOpArray.json index 1d704d56b..f814e5067 100644 --- a/packages/core/examples/tds/invalid/emptyOpArray.json +++ b/packages/core/examples/tds/invalid/emptyOpArray.json @@ -10,7 +10,7 @@ "properties": { "status": { "type": "string", - "forms": [{ "href": "https://mylamp.example.com/status", "op":[] }] + "forms": [{ "href": "https://mylamp.example.com/status", "op": [] }] } }, "actions": { diff --git a/packages/core/examples/tds/valid/semanticTD.json b/packages/core/examples/tds/valid/semanticTD.json index 4b7d5d35a..8424ecf53 100644 --- a/packages/core/examples/tds/valid/semanticTD.json +++ b/packages/core/examples/tds/valid/semanticTD.json @@ -1,10 +1,10 @@ { "@context": [ - "https://www.w3.org/2022/wot/td/v1.1", - { - "s": "http://schema.org", - "iot": "http://iotschema.org" - } + "https://www.w3.org/2022/wot/td/v1.1", + { + "s": "http://schema.org", + "iot": "http://iotschema.org" + } ], "@type": "Thing", "id": "urn:semantic", diff --git a/packages/core/td-schema.json b/packages/core/td-schema.json index 4eb9236bb..4c3086006 100644 --- a/packages/core/td-schema.json +++ b/packages/core/td-schema.json @@ -55,11 +55,7 @@ }, "subprotocol": { "type": "string", - "examples": [ - "longpoll", - "websub", - "sse" - ] + "examples": ["longpoll", "websub", "sse"] }, "thing-context-td-uri-v1": { "type": "string", @@ -181,15 +177,7 @@ }, "dataSchema-type": { "type": "string", - "enum": [ - "boolean", - "integer", - "number", - "string", - "object", - "array", - "null" - ] + "enum": ["boolean", "integer", "number", "string", "object", "array", "null"] }, "dataSchema": { "type": "object", @@ -318,10 +306,7 @@ } }, "multipleOfDefinition": { - "type": [ - "integer", - "number" - ], + "type": ["integer", "number"], "exclusiveMinimum": 0 }, "expectedResponse": { @@ -331,9 +316,7 @@ "type": "string" } }, - "required": [ - "contentType" - ] + "required": ["contentType"] }, "form_element_base": { "type": "object", @@ -376,9 +359,7 @@ "$ref": "#/definitions/additionalResponsesDefinition" } }, - "required": [ - "href" - ], + "required": ["href"], "additionalProperties": true }, "form_element_property": { @@ -393,23 +374,13 @@ "oneOf": [ { "type": "string", - "enum": [ - "readproperty", - "writeproperty", - "observeproperty", - "unobserveproperty" - ] + "enum": ["readproperty", "writeproperty", "observeproperty", "unobserveproperty"] }, { "type": "array", "items": { "type": "string", - "enum": [ - "readproperty", - "writeproperty", - "observeproperty", - "unobserveproperty" - ] + "enum": ["readproperty", "writeproperty", "observeproperty", "unobserveproperty"] }, "minItems": 1 } @@ -430,21 +401,13 @@ "oneOf": [ { "type": "string", - "enum": [ - "invokeaction", - "queryaction", - "cancelaction" - ] + "enum": ["invokeaction", "queryaction", "cancelaction"] }, { "type": "array", "items": { "type": "string", - "enum": [ - "invokeaction", - "queryaction", - "cancelaction" - ] + "enum": ["invokeaction", "queryaction", "cancelaction"] }, "minItems": 1 } @@ -465,19 +428,13 @@ "oneOf": [ { "type": "string", - "enum": [ - "subscribeevent", - "unsubscribeevent" - ] + "enum": ["subscribeevent", "unsubscribeevent"] }, { "type": "array", "items": { "type": "string", - "enum": [ - "subscribeevent", - "unsubscribeevent" - ] + "enum": ["subscribeevent", "unsubscribeevent"] }, "minItems": 1 } @@ -532,9 +489,7 @@ } }, "additionalProperties": true, - "required": [ - "op" - ] + "required": ["op"] }, "form": { "$comment": "This is NOT for validation purposes but for automatic generation of TS types. For more info, please see: https://github.com/w3c/wot-thing-description/pull/1319#issuecomment-994950057", @@ -671,9 +626,7 @@ } } }, - "required": [ - "forms" - ], + "required": ["forms"], "additionalProperties": true }, "action_element": { @@ -723,9 +676,7 @@ "type": "boolean" } }, - "required": [ - "forms" - ], + "required": ["forms"], "additionalProperties": true }, "event_element": { @@ -772,9 +723,7 @@ "$ref": "#/definitions/dataSchema" } }, - "required": [ - "forms" - ], + "required": ["forms"], "additionalProperties": true }, "base_link_element": { @@ -806,9 +755,7 @@ ] } }, - "required": [ - "href" - ], + "required": ["href"], "additionalProperties": true }, "link_element": { @@ -823,9 +770,7 @@ "properties": { "sizes": {} }, - "required": [ - "sizes" - ] + "required": ["sizes"] } }, { @@ -833,15 +778,10 @@ "description": "A basic link element should not contain icon or tm:extends", "properties": { "rel": { - "enum": [ - "icon", - "tm:extends" - ] + "enum": ["icon", "tm:extends"] } }, - "required": [ - "rel" - ] + "required": ["rel"] } } ] @@ -861,9 +801,7 @@ "pattern": "[0-9]*x[0-9]+" } }, - "required": [ - "rel" - ] + "required": ["rel"] } ] }, @@ -875,10 +813,7 @@ "scheme": "ace:ACESecurityScheme", "ace:as": "coaps://as.example.com/token", "ace:audience": "coaps://rs.example.com", - "ace:scopes": [ - "limited", - "special" - ], + "ace:scopes": ["limited", "special"], "ace:cnonce": true } ], @@ -901,9 +836,7 @@ "pattern": ".+:.*" } }, - "required": [ - "scheme" - ], + "required": ["scheme"], "additionalProperties": true }, "noSecurityScheme": { @@ -923,14 +856,10 @@ }, "scheme": { "type": "string", - "enum": [ - "nosec" - ] + "enum": ["nosec"] } }, - "required": [ - "scheme" - ], + "required": ["scheme"], "additionalProperties": true }, "autoSecurityScheme": { @@ -950,19 +879,13 @@ }, "scheme": { "type": "string", - "enum": [ - "auto" - ] + "enum": ["auto"] } }, "not": { - "required": [ - "name" - ] + "required": ["name"] }, - "required": [ - "scheme" - ], + "required": ["scheme"], "additionalProperties": true }, "comboSecurityScheme": { @@ -984,9 +907,7 @@ }, "scheme": { "type": "string", - "enum": [ - "combo" - ] + "enum": ["combo"] }, "oneOf": { "type": "array", @@ -996,10 +917,7 @@ } } }, - "required": [ - "scheme", - "oneOf" - ], + "required": ["scheme", "oneOf"], "additionalProperties": true }, { @@ -1019,9 +937,7 @@ }, "scheme": { "type": "string", - "enum": [ - "combo" - ] + "enum": ["combo"] }, "allOf": { "type": "array", @@ -1031,10 +947,7 @@ } } }, - "required": [ - "scheme", - "allOf" - ], + "required": ["scheme", "allOf"], "additionalProperties": true } ] @@ -1056,27 +969,17 @@ }, "scheme": { "type": "string", - "enum": [ - "basic" - ] + "enum": ["basic"] }, "in": { "type": "string", - "enum": [ - "header", - "query", - "body", - "cookie", - "auto" - ] + "enum": ["header", "query", "body", "cookie", "auto"] }, "name": { "type": "string" } }, - "required": [ - "scheme" - ], + "required": ["scheme"], "additionalProperties": true }, "digestSecurityScheme": { @@ -1096,34 +999,21 @@ }, "scheme": { "type": "string", - "enum": [ - "digest" - ] + "enum": ["digest"] }, "qop": { "type": "string", - "enum": [ - "auth", - "auth-int" - ] + "enum": ["auth", "auth-int"] }, "in": { "type": "string", - "enum": [ - "header", - "query", - "body", - "cookie", - "auto" - ] + "enum": ["header", "query", "body", "cookie", "auto"] }, "name": { "type": "string" } }, - "required": [ - "scheme" - ], + "required": ["scheme"], "additionalProperties": true }, "apiKeySecurityScheme": { @@ -1143,28 +1033,17 @@ }, "scheme": { "type": "string", - "enum": [ - "apikey" - ] + "enum": ["apikey"] }, "in": { "type": "string", - "enum": [ - "header", - "query", - "body", - "cookie", - "uri", - "auto" - ] + "enum": ["header", "query", "body", "cookie", "uri", "auto"] }, "name": { "type": "string" } }, - "required": [ - "scheme" - ], + "required": ["scheme"], "additionalProperties": true }, "bearerSecurityScheme": { @@ -1184,9 +1063,7 @@ }, "scheme": { "type": "string", - "enum": [ - "bearer" - ] + "enum": ["bearer"] }, "authorization": { "$ref": "#/definitions/anyUri" @@ -1199,21 +1076,13 @@ }, "in": { "type": "string", - "enum": [ - "header", - "query", - "body", - "cookie", - "auto" - ] + "enum": ["header", "query", "body", "cookie", "auto"] }, "name": { "type": "string" } }, - "required": [ - "scheme" - ], + "required": ["scheme"], "additionalProperties": true }, "pskSecurityScheme": { @@ -1233,17 +1102,13 @@ }, "scheme": { "type": "string", - "enum": [ - "psk" - ] + "enum": ["psk"] }, "identity": { "type": "string" } }, - "required": [ - "scheme" - ], + "required": ["scheme"], "additionalProperties": true }, "oAuth2SecurityScheme": { @@ -1263,9 +1128,7 @@ }, "scheme": { "type": "string", - "enum": [ - "oauth2" - ] + "enum": ["oauth2"] }, "authorization": { "$ref": "#/definitions/anyUri" @@ -1296,17 +1159,12 @@ }, { "type": "string", - "enum": [ - "code", - "client" - ] + "enum": ["code", "client"] } ] } }, - "required": [ - "scheme" - ], + "required": ["scheme"], "additionalProperties": true }, "securityScheme": { @@ -1387,9 +1245,7 @@ "type": "string" } }, - "required": [ - "instance" - ] + "required": ["instance"] }, "links": { "type": "array", @@ -1480,11 +1336,6 @@ "$ref": "#/definitions/thing-context" } }, - "required": [ - "title", - "security", - "securityDefinitions", - "@context" - ], + "required": ["title", "security", "securityDefinitions", "@context"], "additionalProperties": true -} \ No newline at end of file +} diff --git a/packages/core/tm-schema.json b/packages/core/tm-schema.json index cad49ae6f..5d0cecb71 100644 --- a/packages/core/tm-schema.json +++ b/packages/core/tm-schema.json @@ -64,11 +64,7 @@ }, "subprotocol": { "type": "string", - "examples": [ - "longpoll", - "websub", - "sse" - ] + "examples": ["longpoll", "websub", "sse"] }, "thing-context-td-uri-v1": { "type": "string", @@ -186,15 +182,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "boolean", - "integer", - "number", - "string", - "object", - "array", - "null" - ] + "enum": ["boolean", "integer", "number", "string", "object", "array", "null"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -408,10 +396,7 @@ "multipleOfDefinition": { "anyOf": [ { - "type": [ - "integer", - "number" - ], + "type": ["integer", "number"], "exclusiveMinimum": 0 }, { @@ -494,12 +479,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "readproperty", - "writeproperty", - "observeproperty", - "unobserveproperty" - ] + "enum": ["readproperty", "writeproperty", "observeproperty", "unobserveproperty"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -553,11 +533,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "invokeaction", - "queryaction", - "cancelaction" - ] + "enum": ["invokeaction", "queryaction", "cancelaction"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -570,11 +546,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "invokeaction", - "queryaction", - "cancelaction" - ] + "enum": ["invokeaction", "queryaction", "cancelaction"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -610,10 +582,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "subscribeevent", - "unsubscribeevent" - ] + "enum": ["subscribeevent", "unsubscribeevent"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -626,10 +595,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "subscribeevent", - "unsubscribeevent" - ] + "enum": ["subscribeevent", "unsubscribeevent"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -1140,9 +1106,7 @@ "properties": { "sizes": {} }, - "required": [ - "sizes" - ] + "required": ["sizes"] } }, { @@ -1152,9 +1116,7 @@ "rel": { "anyOf": [ { - "enum": [ - "icon" - ] + "enum": ["icon"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -1162,9 +1124,7 @@ ] } }, - "required": [ - "rel" - ] + "required": ["rel"] } } ] @@ -1184,9 +1144,7 @@ "pattern": "[0-9]*x[0-9]+" } }, - "required": [ - "rel" - ] + "required": ["rel"] } ] }, @@ -1198,10 +1156,7 @@ "scheme": "ace:ACESecurityScheme", "ace:as": "coaps://as.example.com/token", "ace:audience": "coaps://rs.example.com", - "ace:scopes": [ - "limited", - "special" - ], + "ace:scopes": ["limited", "special"], "ace:cnonce": true } ], @@ -1250,9 +1205,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "nosec" - ] + "enum": ["nosec"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -1289,9 +1242,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "auto" - ] + "enum": ["auto"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -1300,9 +1251,7 @@ } }, "not": { - "required": [ - "name" - ] + "required": ["name"] }, "additionalProperties": true, "propertyNames": { @@ -1332,9 +1281,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "combo" - ] + "enum": ["combo"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -1373,9 +1320,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "combo" - ] + "enum": ["combo"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -1416,9 +1361,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "basic" - ] + "enum": ["basic"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -1429,13 +1372,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "header", - "query", - "body", - "cookie", - "auto" - ] + "enum": ["header", "query", "body", "cookie", "auto"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -1475,9 +1412,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "digest" - ] + "enum": ["digest"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -1488,10 +1423,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "auth", - "auth-int" - ] + "enum": ["auth", "auth-int"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -1502,13 +1434,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "header", - "query", - "body", - "cookie", - "auto" - ] + "enum": ["header", "query", "body", "cookie", "auto"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -1548,9 +1474,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "apikey" - ] + "enum": ["apikey"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -1561,14 +1485,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "header", - "query", - "body", - "cookie", - "uri", - "auto" - ] + "enum": ["header", "query", "body", "cookie", "uri", "auto"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -1608,9 +1525,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "bearer" - ] + "enum": ["bearer"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -1630,13 +1545,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "header", - "query", - "body", - "cookie", - "auto" - ] + "enum": ["header", "query", "body", "cookie", "auto"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -1676,9 +1585,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "psk" - ] + "enum": ["psk"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -1718,9 +1625,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "oauth2" - ] + "enum": ["oauth2"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -1758,10 +1663,7 @@ "type": "string", "anyOf": [ { - "enum": [ - "code", - "client" - ] + "enum": ["code", "client"] }, { "$ref": "#/definitions/placeholder-pattern" @@ -1932,9 +1834,7 @@ "type": "string" } }, - "required": [ - "instance" - ] + "required": ["instance"] } }, { @@ -2053,8 +1953,5 @@ "$ref": "#/definitions/placeholder-pattern" } }, - "required": [ - "@context", - "@type" - ] -} \ No newline at end of file + "required": ["@context", "@type"] +} diff --git a/packages/td_to_asyncapi/examples/asyncapi.json b/packages/td_to_asyncapi/examples/asyncapi.json index 78acaa579..92ac5a099 100644 --- a/packages/td_to_asyncapi/examples/asyncapi.json +++ b/packages/td_to_asyncapi/examples/asyncapi.json @@ -132,6 +132,15 @@ } } ], + "components": { + "securitySchemes": { + "basic_sc": { + "type": "http", + "scheme": "basic", + "x-in": "header" + } + } + }, "externalDocs": { "url": "http://plugfest.thingweb.io/playground/", "description": "This AsyncAPI instance was generated from a Web of Things (WoT) - Thing Description by the WoT Playground" diff --git a/packages/td_to_asyncapi/examples/asyncapi.yaml b/packages/td_to_asyncapi/examples/asyncapi.yaml index 91f8927aa..2b54a30e0 100644 --- a/packages/td_to_asyncapi/examples/asyncapi.yaml +++ b/packages/td_to_asyncapi/examples/asyncapi.yaml @@ -81,6 +81,12 @@ tags: externalDocs: url: "https://www.w3.org/TR/wot-thing-description/#eventaffordance" description: "Find out more about Event Affordances." +components: + securitySchemes: + basic_sc: + type: "http" + scheme: "basic" + x-in: "header" externalDocs: url: "http://plugfest.thingweb.io/playground/" description: "This AsyncAPI instance was generated from a Web of Things (WoT) - Thing Description by the WoT Playground" diff --git a/packages/td_to_asyncapi/examples/td.json b/packages/td_to_asyncapi/examples/td.json index 8c6a0d72e..b3b921bbc 100644 --- a/packages/td_to_asyncapi/examples/td.json +++ b/packages/td_to_asyncapi/examples/td.json @@ -5,7 +5,9 @@ "cov": "http://www.example.org/coap-binding#", "mqv": "http://www.example.org/mqtt-binding#" }, - { "@language": "en" } + { + "@language": "en" + } ], "id": "urn:dev:home:coff:type123-SNR123456", "name": "MyCoffeeMaker", @@ -13,9 +15,16 @@ "title": "MyCoffeeMaker-Home", "description": "Order your coffee remotely!", "securityDefinitions": { - "basic_sc": { "scheme": "basic", "in": "header" }, - "psk_sc": { "scheme": "psk" }, - "nosec_sc": { "scheme": "nosec" } + "basic_sc": { + "scheme": "basic", + "in": "header" + }, + "psk_sc": { + "scheme": "psk" + }, + "nosec_sc": { + "scheme": "nosec" + } }, "security": ["nosec_sc"], "properties": { @@ -56,7 +65,9 @@ "readOnly": true, "writeOnly": false, "type": "array", - "items": { "type": "integer" }, + "items": { + "type": "integer" + }, "maxItems": 5, "minItems": 2, "forms": [ diff --git a/packages/td_to_asyncapi/index.js b/packages/td_to_asyncapi/index.js index 445f7d1f5..d52751315 100644 --- a/packages/td_to_asyncapi/index.js +++ b/packages/td_to_asyncapi/index.js @@ -18,6 +18,8 @@ const genChannels = require("./src/genChannels"); const { genInfo, genTags, genBaseServer } = require("./src/genRoot"); const defaults = require("@thing-description-playground/defaults"); +const { mapSecurity } = require("./src/mapSecurity"); + /** * Create an AsyncAPI instance from a Web of Things Thing Description * @param {object} td A Thing Description object as input @@ -28,14 +30,21 @@ function toAsyncAPI(td) { if (typeof td !== "object") { rej("TD has wrong type, should be an object"); } + const { securitySchemes, security } = mapSecurity(td.securityDefinitions, td.security); + const components = { + securitySchemes, + }; defaults.addDefaults(td); - - const servers = genBaseServer(td); + let securityPara = { + security: security, + }; + const servers = genBaseServer(td, securityPara); const asyncApiInstance = new AsyncAPI("2.0.0", genInfo(td), genChannels(td, servers), { id: td.id, servers, tags: genTags(td), + components: components, externalDocs: new ExternalDocs( "http://plugfest.thingweb.io/playground/", "This AsyncAPI instance was generated from a Web of Things (WoT) - Thing Description by the WoT Playground" diff --git a/packages/td_to_asyncapi/src/genChannels.js b/packages/td_to_asyncapi/src/genChannels.js index f03103aa0..97d26e758 100644 --- a/packages/td_to_asyncapi/src/genChannels.js +++ b/packages/td_to_asyncapi/src/genChannels.js @@ -23,7 +23,7 @@ const { Channel, Operation, Tag, Message, MqttOperationBinding, Server } = requi * @param {object} td The Thing Description input * @param {object} servers The AsyncAPI servers map */ -function genChannels(td, servers) { +function genChannels(td, servers, security) { const channels = {}; // Scan Properties @@ -53,7 +53,7 @@ function genChannels(td, servers) { interaction.forms.forEach((form) => { const dataSchema = interactionInfo.getDataSchema(interaction); const payload = dataToAsyncSchema(dataSchema); - scanPropForm(form, channels, interactionName, payload, servers, interactionInfo); + scanPropForm(form, channels, interactionName, payload, servers, interactionInfo, security); }); } }); @@ -97,7 +97,7 @@ const tryProtocols = [ * Check if form is relevant * @param {object} form One form */ -function scanPropForm(form, channels, propertyName, payload, servers, interactionInfo) { +function scanPropForm(form, channels, propertyName, payload, servers, interactionInfo, security) { const hasBase = servers.base !== undefined ? true : false; const isRelative = form.href && form.href.search("://") === -1 ? true : false; @@ -109,8 +109,11 @@ function scanPropForm(form, channels, propertyName, payload, servers, interactio tryProtocol.checkForm(form) ) { const { channel, server } = extractChannel(form.href); + let newOptionalPara = { + security: security, + }; // add server - addServer(servers, server, tryProtocol.id); + addServer(servers, server, tryProtocol.id, newOptionalPara); // add channel if (!channels[channel]) { @@ -141,7 +144,7 @@ function scanPropForm(form, channels, propertyName, payload, servers, interactio * @param {string|undefined} newServerUri * @param {string} protocol */ -function addServer(servers, newServerUri, newServerProtocol) { +function addServer(servers, newServerUri, newServerProtocol, newOptionalPara) { if ( newServerUri && Object.keys(servers).every( @@ -153,7 +156,7 @@ function addServer(servers, newServerUri, newServerProtocol) { while (Object.keys(servers).some((asyncServer) => asyncServer === i.toString())) { i++; } - servers[i.toString()] = new Server(newServerUri, newServerProtocol); + servers[i.toString()] = new Server(newServerUri, newServerProtocol, newOptionalPara); } } diff --git a/packages/td_to_asyncapi/src/genRoot.js b/packages/td_to_asyncapi/src/genRoot.js index e7f902ba5..533e07641 100644 --- a/packages/td_to_asyncapi/src/genRoot.js +++ b/packages/td_to_asyncapi/src/genRoot.js @@ -91,11 +91,11 @@ function genTags(td) { return tags; } -function genBaseServer(td) { +function genBaseServer(td, security) { const servers = {}; if (td.base) { if (td.base.startsWith("mqtt")) { - servers.base = new Server(td.base, "mqtt"); + servers.base = new Server(td.base, "mqtt", security); } } return servers; diff --git a/packages/td_to_asyncapi/src/mapSecurity.js b/packages/td_to_asyncapi/src/mapSecurity.js new file mode 100644 index 000000000..27e183166 --- /dev/null +++ b/packages/td_to_asyncapi/src/mapSecurity.js @@ -0,0 +1,418 @@ +/* + * Copyright (c) 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and + * Document License (2015-05-13) which is available at + * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. + * + * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 + */ + +module.exports = { + mapSecurity, + mapSecurityString, + mapSecurityDefinitions, + hasNoSec, + mapFormSecurity, +}; + +/** + * Convert the TD security Definitions and Security to + * AsyncAPI components->securitySchemes and security objects + * @param {object} tdDefinitions the definitions for all security schemes of the TD + * @param {string|string[]} tdSecurity security scheme names that apply per default + */ +function mapSecurity(tdDefinitions, tdSecurity) { + const { securitySchemes, scopes } = mapSecurityDefinitions(tdDefinitions); + const security = mapSecurityString(tdSecurity, securitySchemes, scopes); + if (security.length === 0 && hasNoSec(tdDefinitions, tdSecurity)) { + security.push({}); + } + + for (const key in securitySchemes) { + if (key.includes("combo_sc")) { + delete securitySchemes[key]; + } + } + + return { securitySchemes, security }; +} + +/** + * Convert the TD security and scopes information of a single form + * to an AsyncAPI security object + * @param {object} tdDefinitions the definitions for all security schemes of the TD + * @param {string|string[]|undefined} tdSecurity security scheme names that apply to this form + * @param {string|string[]|undefined} tdFormScopes oauth2 scopes that apply to this form + */ +function mapFormSecurity(tdDefinitions, tdSecurity, tdFormScopes) { + const { securitySchemes, scopes } = mapSecurityDefinitions(tdDefinitions); + let aapScopes = scopes; + if (typeof tdFormScopes === "string") { + tdFormScopes = [tdFormScopes]; + } + + if (typeof tdFormScopes === "object") { + const scopeSecurities = []; + // filter TD scopes that are not supported by the conversion + aapScopes = {}; + + Object.keys(scopes).forEach((supportedSecurity) => { + scopeSecurities.push(supportedSecurity); + const addScope = tdFormScopes.find((tdFormScope) => + scopes[supportedSecurity].some((supportedScope) => supportedScope === tdFormScope) + ); + if (addScope !== undefined) { + if (aapScopes[supportedSecurity] === undefined) { + aapScopes[supportedSecurity] = [addScope]; + } else { + aapScopes[supportedSecurity].push(addScope); + } + } + }); + + // add security scheme names if only a scope was given in the TD + scopeSecurities.forEach((scopeSecurity) => { + if (typeof tdSecurity === "string") { + tdSecurity = [tdSecurity]; + } + if (typeof tdSecurity === "object") { + if (!tdSecurity.some((tdSecString) => tdSecString === scopeSecurity)) { + tdSecurity.push(scopeSecurity); + } + } else if (tdSecurity === undefined) { + tdSecurity = scopeSecurities; + } + }); + } + const security = mapSecurityString(tdSecurity, securitySchemes, aapScopes); + + if (security.length === 0 && hasNoSec(tdDefinitions, tdSecurity)) { + security.push({}); + } + + return { security }; +} + +/** + * Mapping the TD security object to AsyncAPI + * @param {object} tdSecurity the TD security options to apply + * @param {object} aapSecuritySchemes the already mapped security schemes + * @param {object} tdScopes the found scopes as map {string: string[]} + */ +function mapSecurityString(tdSecurity, aapSecuritySchemes, tdScopes) { + const aapSecurityContainer = []; + if (typeof tdSecurity === "string") { + tdSecurity = [tdSecurity]; + } + + if (typeof tdSecurity === "object") { + tdSecurity.forEach((tdSecurityKey) => { + let aapSecurity = {}; + const securityObject = aapSecuritySchemes[tdSecurityKey]; + if (securityObject && securityObject.type === "allOf") { + securityObject.secdef.forEach((def) => { + // get scopes + let thisScopes = []; + if (tdScopes[def] !== undefined) { + thisScopes = tdScopes[def]; + } + + const supportedSchemes = Object.keys(aapSecuritySchemes); + + if (supportedSchemes.some((supportedScheme) => supportedScheme === def)) { + aapSecurity[def] = thisScopes; + } + }); + + if (Object.keys(aapSecurity).length > 0) { + aapSecurityContainer.push(aapSecurity); + } + } else if (securityObject && securityObject.type === "oneOf") { + securityObject.secdef.forEach((def) => { + aapSecurity = {}; + // get scopes + let thisScopes = []; + if (tdScopes[def] !== undefined) { + thisScopes = tdScopes[def]; + } + + const supportedSchemes = Object.keys(aapSecuritySchemes); + + if (supportedSchemes.some((supportedScheme) => supportedScheme === def)) { + aapSecurity[def] = thisScopes; + } + + if (Object.keys(aapSecurity).length > 0) { + aapSecurityContainer.push(aapSecurity); + } + }); + } else { + // get scopes + let thisScopes = []; + if (tdScopes[tdSecurityKey] !== undefined) { + thisScopes = tdScopes[tdSecurityKey]; + } + + const supportedSchemes = Object.keys(aapSecuritySchemes); + + if (supportedSchemes.some((supportedScheme) => supportedScheme === tdSecurityKey)) { + aapSecurity[tdSecurityKey] = thisScopes; + } + + if (Object.keys(aapSecurity).length > 0) { + aapSecurityContainer.push(aapSecurity); + } + } + }); + } + + return aapSecurityContainer; +} + +/** + * Map the TD security definitions to + * AsyncAPI security Schemes in components + * and return all used scopes in addition + * @param {object|undefined} tdDefinitions if no object is given, empty securitySchemes and scopes are returned + */ +function mapSecurityDefinitions(tdDefinitions) { + const securitySchemes = {}; + const scopes = {}; + + if (typeof tdDefinitions === "object") { + Object.keys(tdDefinitions).forEach((key) => { + if (typeof tdDefinitions[key].scheme === "string") { + const { aapDefinition, scope } = genaapDefinition(tdDefinitions[key]); + if (Object.keys(aapDefinition).length > 0) { + securitySchemes[key] = aapDefinition; + if (typeof scope === "object") { + scopes[key] = scope; + } + } + } + }); + } + + return { securitySchemes, scopes }; +} + +/** + * Generate an AsyncAPI securityScheme part from a given TD security definiton part + * @param {object} tdDefinition one security definition object + */ +function genaapDefinition(tdDefinition) { + const aapDefinition = {}; + const tdScheme = tdDefinition.scheme.toLowerCase(); + let addOptionals = true; + const httpSchemes = ["basic", "digest", "bearer"]; + let scope; + + if (httpSchemes.some((httpScheme) => httpScheme === tdScheme)) { + aapDefinition.type = "http"; + aapDefinition.scheme = tdScheme; + if (tdDefinition.in && tdDefinition.in !== "header") { + throw new Error("Cannot represent " + tdScheme + " authentication outside the header in AsyncAPI"); + } + } + + switch (tdScheme) { + case "nosec": + case "basic": + if (tdDefinition.name) { + aapDefinition["x-name"] = tdDefinition.name; + } + // should the x-in parameter be added if in = header? + if (tdDefinition.in) { + aapDefinition["x-in"] = tdDefinition.in; + } + break; + /*case "psk": + // do nothing? + break;*/ + + case "digest": + aapDefinition["x-qop"] = tdDefinition.qop === undefined ? "auth" : tdDefinition.qop; + if (tdDefinition.name) { + aapDefinition["x-name"] = tdDefinition.name; + } + // should the x-in parameter be added if in = header? + if (tdDefinition.in) { + aapDefinition["x-in"] = tdDefinition.in; + } + break; + + case "bearer": + aapDefinition.bearerFormat = tdDefinition.format === undefined ? "jwt" : tdDefinition.format; + aapDefinition["x-alg"] = tdDefinition.alg === undefined ? "ES256" : tdDefinition.alg; + if (tdDefinition.name) { + aapDefinition["x-name"] = tdDefinition.name; + } + // should the x-in parameter be added if in = header? + if (tdDefinition.in) { + aapDefinition["x-in"] = tdDefinition.in; + } + if (tdDefinition.authorization) { + aapDefinition["x-authorization"] = tdDefinition.authorization; + } + break; + + case "apikey": + aapDefinition.type = "httpApiKey"; + aapDefinition.in = tdDefinition.in === undefined ? "query" : tdDefinition.in; + aapDefinition.name = tdDefinition.name === undefined ? "UNKNOWN" : tdDefinition.name; + if (aapDefinition.in != "query" && aapDefinition.in != "header" && aapDefinition.in != "cookie") { + throw new Error("Cannot represent ApiKey in" + aapDefinition.in + " with AsyncAPI"); + } + break; + + case "oauth2": + if (typeof tdDefinition.scopes === "string") { + scope = [tdDefinition.scopes]; + } else if (typeof tdDefinition.scopes === "object") { + scope = tdDefinition.scopes; + } + + aapDefinition.type = "oauth2"; + aapDefinition.flows = genOAuthFlows(tdDefinition); + break; + /* + case "openidconnect": + aapDefinition.type = "openIdConnect" + aapDefinition.openIdConnectUrl = (tdDefinition.openIdConnectUrl === undefined) ? "UNKNOWN" : tdDefinition.openIdConnectUrl + //aapDefinition.flows = genOAuthFlows(tdDefinition) + break +*/ + case "combo": + // todo Implement combo security scheme + if (tdDefinition.allOf) { + aapDefinition.type = "allOf"; + aapDefinition.secdef = tdDefinition.allOf; + } else { + aapDefinition.type = "oneOf"; + aapDefinition.secdef = tdDefinition.oneOf; + } + break; + + default: + console.log("unknown security definition: " + tdScheme); + addOptionals = false; + } + + // add optional fields + if (addOptionals) { + if (tdDefinition.description) { + aapDefinition.description = tdDefinition.description; + } + if (tdDefinition.descriptions) { + aapDefinition["x-descriptions"] = tdDefinition.descriptions; + } + if (tdDefinition.proxy) { + aapDefinition["x-proxy"] = tdDefinition.proxy; + } + } + + return { aapDefinition, scope }; +} + +/** + * Map the oauth2 fields of a TD to an AsyncAPI instance + * @param {object} tdDefinition The security definition object of a TD + */ +function genOAuthFlows(tdDefinition) { + const aapFlow = {}; + if (typeof tdDefinition.flow !== "string") { + throw new Error("the oauth2 object has no flow of type string"); + } + + const tdFlow = tdDefinition.flow.toLowerCase(); + const mapTdToAap = { + implicit: ["implicit"], + password: ["password", "ropc"], + clientCredentials: ["application", "client", "clientcredentials", "clientcredential"], + authorizationCode: ["accesscode", "code", "authorizationcode"], + "x-device": ["device"], + }; + + Object.keys(mapTdToAap).forEach((key) => { + if (mapTdToAap[key].some((arrayElement) => arrayElement === tdFlow)) { + const protoFlow = {}; + if (key === "implicit" || key === "authorizationCode" || key === "x-device") { + if (tdDefinition.authorization === undefined) { + throw new Error("the authorization URI is required for oauth2 flow: " + key); + } else { + protoFlow.authorizationUrl = tdDefinition.authorization; + } + } + if ( + key === "password" || + key === "clientCredentials" || + key === "authorizationCode" || + key === "x-device" + ) { + if (tdDefinition.token === undefined) { + throw new Error("the token URI is required for oauth2 flow: " + key); + } else { + protoFlow.tokenUrl = tdDefinition.token; + } + } + if (typeof tdDefinition.refresh === "string") { + protoFlow.refreshUrl = tdDefinition.refresh; + } + if (tdDefinition.scopes === undefined) { + protoFlow.scopes = { + /* "default": "autogenerated default scope" */ + }; // TODO: is one scope required? (I don't think so) + } else { + protoFlow.scopes = {}; + if (typeof tdDefinition.scopes === "string") { + tdDefinition.scopes = [tdDefinition.scopes]; + } + tdDefinition.scopes.forEach((scope) => { + protoFlow.scopes[scope] = ""; + }); + } + aapFlow[key] = protoFlow; + } + }); + return aapFlow; +} + +/** + * Check if all applying security schemes are of type nosec + * @param {object} tdDefinitions the definitions for all security schemes of the TD + * @param {string|string[]} tdSecurity security scheme names that apply to this TD part + */ +function hasNoSec(tdDefinitions, tdSecurity) { + let foundNoSec = false; + + // find all noSec names + const noSecNames = []; + if (typeof tdDefinitions === "object") { + Object.keys(tdDefinitions).forEach((key) => { + const tdScheme = tdDefinitions[key].scheme; + if (typeof tdScheme === "string" && tdScheme.toLowerCase() === "nosec") { + noSecNames.push(key); + } + }); + } + + if (typeof tdSecurity === "string") { + tdSecurity = [tdSecurity]; + } + if (typeof tdSecurity === "undefined") { + tdSecurity = []; + } + + // check if all security Schemes are of type noSec + if (tdSecurity.length > 0) { + foundNoSec = tdSecurity.every((securityString) => noSecNames.some((noSecName) => noSecName === securityString)); + } + + return foundNoSec; +} diff --git a/packages/td_to_asyncapi/tests/mapSecurity.test.js b/packages/td_to_asyncapi/tests/mapSecurity.test.js new file mode 100644 index 000000000..a181ee64a --- /dev/null +++ b/packages/td_to_asyncapi/tests/mapSecurity.test.js @@ -0,0 +1,232 @@ +/** + * @file Modules test for mapSecurity.js, test its functionality by hardcoded example -> expected output pairs + */ + +const { mapSecurity, mapSecurityString, mapSecurityDefinitions, mapFormSecurity } = require("../src/mapSecurity"); + +// reused definitions +const oauth2Definitions = { + oauth2_sc: { + scheme: "oauth2", + flow: "code", + scopes: ["limited", "special"], + refresh: "https://refreshServer.com/", + token: "https://tokenServer.com/", + authorization: "https://authServer.com/", + }, +}; + +const oauth2Aap = { + securitySchemes: { + oauth2_sc: { + type: "oauth2", + flows: { + authorizationCode: { + authorizationUrl: "https://authServer.com/", + tokenUrl: "https://tokenServer.com/", + refreshUrl: "https://refreshServer.com/", + scopes: { + limited: "", + special: "", + }, + }, + }, + }, + }, + scopes: { + oauth2_sc: ["limited", "special"], + }, +}; + +const basicDefinitions = { + basic_sc: { + scheme: "basic", + in: "header", + }, +}; +const basicAap = { + securitySchemes: { + basic_sc: { + type: "http", + scheme: "basic", + "x-in": "header", + }, + }, + scopes: {}, +}; +const digestDefinitions = { + digest_sc: { + scheme: "digest", + in: "header", + qop: "auth", + }, +}; +const digestAap = { + scopes: {}, + securitySchemes: { + digest_sc: { + type: "http", + scheme: "digest", + "x-in": "header", + "x-qop": "auth", + }, + }, +}; +const apikeyDefinitions = { + apikey_sc: { + scheme: "apikey", + in: "header", + }, +}; +const apikeyAap = { + scopes: {}, + securitySchemes: { + apikey_sc: { + type: "httpApiKey", + in: "header", + name: "UNKNOWN", + }, + }, +}; +const comboAllOfAap = { + securitySchemes: { + basic_sc: { + type: "http", + scheme: "basic", + }, + basic_sc2: { + type: "http", + scheme: "basic", + }, + combo_sc: { + type: "allOf", + secdef: ["basic_sc", "basic_sc2"], + }, + }, +}; + +const comboOneOfAap = { + securitySchemes: { + basic_sc: { + type: "http", + scheme: "basic", + }, + basic_sc2: { + type: "http", + scheme: "basic", + }, + combo_sc: { + type: "oneOf", + secdef: ["basic_sc", "basic_sc2"], + }, + }, +}; + +const noSecDefinitions = { + nosec_sc: { + scheme: "nosec", + }, +}; + +describe("mapSecurity unit tests", () => { + describe("mapSecurityString", () => { + test("oauth2", () => { + const result = [{ oauth2_sc: ["limited"] }]; + const computed = mapSecurityString(["oauth2_sc"], oauth2Aap.securitySchemes, { oauth2_sc: ["limited"] }); + const computed2 = mapSecurityString("oauth2_sc", oauth2Aap.securitySchemes, { oauth2_sc: ["limited"] }); + expect(computed).toEqual(result); + expect(computed2).toEqual(result); + }); + + test("comboAllOf", () => { + const result = [{ basic_sc: [], basic_sc2: [] }]; + const computed = mapSecurityString("combo_sc", comboAllOfAap.securitySchemes, {}); + expect(computed).toEqual(result); + }); + + test("comboOneOf", () => { + const result = [{ basic_sc: [] }, { basic_sc2: [] }]; + const computed = mapSecurityString("combo_sc", comboOneOfAap.securitySchemes, {}); + expect(computed).toEqual(result); + }); + }); + + describe("mapSecurityDefinitions", () => { + test("basic", () => { + console.log(mapSecurityDefinitions(basicDefinitions)); + expect(mapSecurityDefinitions(basicDefinitions)).toEqual(basicAap); + }); + + test("digest", () => { + expect(mapSecurityDefinitions(digestDefinitions)).toEqual(digestAap); + }); + + test("apikey", () => { + expect(mapSecurityDefinitions(apikeyDefinitions)).toEqual(apikeyAap); + }); + + test("oauth2", () => { + expect(mapSecurityDefinitions(oauth2Definitions)).toEqual(oauth2Aap); + }); + }); +}); + +describe("mapSecurity integration tests", () => { + describe("mapFormSecurity", () => { + const result = { security: [{ oauth2_sc: ["limited"] }] }; + + test("oauth2 single scope no security", () => { + expect(mapFormSecurity(oauth2Definitions, undefined, ["limited"])).toEqual(result); + expect(mapFormSecurity(oauth2Definitions, undefined, "limited")).toEqual(result); + }); + test("oauth2 single scope with security", () => { + const security = ["oauth2_sc"]; + + expect(mapFormSecurity(oauth2Definitions, security, ["limited"])).toEqual(result); + expect(mapFormSecurity(oauth2Definitions, security, "limited")).toEqual(result); + }); + }); + + describe("mapSecurity", () => { + test("oauth2", () => { + const result = { + securitySchemes: oauth2Aap.securitySchemes, + security: [ + { + oauth2_sc: ["limited", "special"], + }, + ], + }; + expect(mapSecurity(oauth2Definitions, "oauth2_sc")).toEqual(result); + }); + + test("basic", () => { + const result = { + securitySchemes: basicAap.securitySchemes, + security: [ + { + basic_sc: [], + }, + ], + }; + expect(mapSecurity(basicDefinitions, "basic_sc")).toEqual(result); + expect(mapSecurity(basicDefinitions, ["basic_sc"])).toEqual(result); + }); + + test("nosec", () => { + const result = { + securitySchemes: {}, + security: [{}], + }; + expect(mapSecurity(noSecDefinitions, "nosec_sc")).toEqual(result); + }); + + test("empty", () => { + const result = { + securitySchemes: {}, + security: [], + }; + expect(mapSecurity(noSecDefinitions, undefined)).toEqual(result); + }); + }); +}); diff --git a/packages/web/index.html b/packages/web/index.html index 7c778505d..b5c729444 100644 --- a/packages/web/index.html +++ b/packages/web/index.html @@ -143,19 +143,37 @@ diff --git a/packages/web/script.js b/packages/web/script.js index c357afdb8..e088a33e1 100644 --- a/packages/web/script.js +++ b/packages/web/script.js @@ -260,23 +260,20 @@ const urlInput = document.querySelector("#url-input"); const linkTypeText = document.querySelectorAll("#link-type"); //Open the share link pop up and populate the url field with the new link -document - .getElementById("btn_save") - .addEventListener("click", async () => { - try{ - const URL = await util.save(docType, window.editor.getModel().getLanguageId()); - if(URL !== undefined){ - linkTypeText.forEach(linkText => { - linkText.innerText = docType.toUpperCase() - }) - urlInput.value = URL - shareLinkWrapper.classList.remove("closed") - } +document.getElementById("btn_save").addEventListener("click", async () => { + try { + const URL = await util.save(docType, window.editor.getModel().getLanguageId()); + if (URL !== undefined) { + linkTypeText.forEach((linkText) => { + linkText.innerText = docType.toUpperCase(); + }); + urlInput.value = URL; + shareLinkWrapper.classList.remove("closed"); } - catch(err){ - console.log(err); - } - }); + } catch (err) { + console.log(err); + } +}); //Open the shared link in ediTDor document @@ -284,21 +281,16 @@ document .addEventListener("click", () => util.openEditdor(docType, window.editor.getModel().getLanguageId())); //Open the shared link in another playground tab -document - .getElementById("btn-open-tab") - .addEventListener("click", () => { - window.open(urlInput.value, '_blank'); - }) +document.getElementById("btn-open-tab").addEventListener("click", () => { + window.open(urlInput.value, "_blank"); +}); //Close the share link pop up -document - .getElementById("btn-close-linkpopup") - .addEventListener("click", () => { - urlInput.value = '' - shareLinkWrapper.classList.add("closed") - }); +document.getElementById("btn-close-linkpopup").addEventListener("click", () => { + urlInput.value = ""; + shareLinkWrapper.classList.add("closed"); +}); - urlAddrObject = util.getExamplesList(docType); // Fetching list of examples from the given array(in helperFunctions.js). util.populateExamples(urlAddrObject); // Loading the examples given in list from their respective URLs diff --git a/packages/web/style.css b/packages/web/style.css index 81e48fa08..9a6d36520 100644 --- a/packages/web/style.css +++ b/packages/web/style.css @@ -429,7 +429,7 @@ i { text-decoration: underline dotted gray; } -.link-popup-wrapper{ +.link-popup-wrapper { position: fixed; top: 0; left: 0; @@ -441,11 +441,11 @@ i { background-color: rgba(0, 0, 0, 0.8); } -.link-popup-wrapper.closed{ +.link-popup-wrapper.closed { display: none; } -.link-popup{ +.link-popup { background-color: rgb(255, 255, 255); padding: 1.5rem; border-radius: 10px; @@ -453,42 +453,42 @@ i { width: 33%; } -.link-popup__header{ +.link-popup__header { font-weight: bold; font-size: 1.25rem; } -.link-popup__text{ +.link-popup__text { font-size: 1rem; color: #575757; } -.link-popup__url{ +.link-popup__url { width: 100%; display: flex; align-items: center; justify-content: center; } -.link-popup__url .url-input{ +.link-popup__url .url-input { width: 100%; height: 2.25rem; margin-left: 0; border-top-left-radius: 5px; border-bottom-left-radius: 5px; border: 2px solid #2b2b2b; - padding: .25rem .5rem; + padding: 0.25rem 0.5rem; font-size: 1rem; } -.link-popup__url .url-input:focus{ +.link-popup__url .url-input:focus { outline: none; } -.link-popup__url .btn-new-tab{ +.link-popup__url .btn-new-tab { width: fit-content; height: 2.25rem; - padding: .25rem .75rem; + padding: 0.25rem 0.75rem; border: none; background-color: #2b2b2b; border-top-right-radius: 5px; @@ -496,34 +496,34 @@ i { transition: background-color 150ms ease-in-out; } -.link-popup__url .btn-new-tab:hover{ +.link-popup__url .btn-new-tab:hover { background-color: #1f1f1f; } -.link-popup__url .btn-new-tab:focus{ +.link-popup__url .btn-new-tab:focus { outline: none; background-color: #1f1f1f; } -.btn-new-tab svg{ +.btn-new-tab svg { fill: #ffffff; height: 1rem; } -.link-popup__btn-container{ +.link-popup__btn-container { text-align: right; } -.link-popup__btn-container .btn-editdor{ +.link-popup__btn-container .btn-editdor { background-color: transparent; } -.link-popup__btn-container .btn-close{ +.link-popup__btn-container .btn-close { background-color: #138496; color: #fff; transition: background-color 250ms ease-in-out; } -.link-popup__btn-container .btn-close:hover{ +.link-popup__btn-container .btn-close:hover { background-color: #106775; } diff --git a/packages/web/util.js b/packages/web/util.js index 95d21b41d..cf5deba34 100644 --- a/packages/web/util.js +++ b/packages/web/util.js @@ -575,8 +575,8 @@ export async function openEditdor(docType, format) { const data = docType + format + value; const compressed = Validators.compress(data); - const URL = `https://eclipse.github.io/editdor/?td=${compressed}` - window.open(URL, '_blank'); + const URL = `https://eclipse.github.io/editdor/?td=${compressed}`; + window.open(URL, "_blank"); } /**