Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: eclipse-thingweb/dart_wot
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.25.1
Choose a base ref
..
head repository: eclipse-thingweb/dart_wot
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v0.26.0
Choose a head ref
Showing with 337 additions and 244 deletions.
  1. +2 −2 .github/workflows/ci.yml
  2. +11 −0 CHANGELOG.md
  3. +1 −1 example/complex_example.dart
  4. +1 −1 lib/src/core/credentials/ace_credentials.dart
  5. +3 −3 lib/src/core/credentials/apikey_credentials.dart
  6. +3 −3 lib/src/core/credentials/basic_credentials.dart
  7. +3 −3 lib/src/core/credentials/bearer_credentials.dart
  8. +1 −9 lib/src/core/credentials/credentials.dart
  9. +2 −2 lib/src/core/credentials/digest_credentials.dart
  10. +2 −2 lib/src/core/credentials/oauth2_credentials.dart
  11. +2 −3 lib/src/core/credentials/psk_credentials.dart
  12. +44 −2 lib/src/definitions/extensions/json_parser.dart
  13. +23 −20 lib/src/definitions/security/ace_security_scheme.dart
  14. +18 −14 lib/src/definitions/security/apikey_security_scheme.dart
  15. +13 −3 lib/src/definitions/security/auto_security_scheme.dart
  16. +14 −15 lib/src/definitions/security/basic_security_scheme.dart
  17. +22 −25 lib/src/definitions/security/bearer_security_scheme.dart
  18. +46 −0 lib/src/definitions/security/combo_security_scheme.dart
  19. +15 −19 lib/src/definitions/security/digest_security_scheme.dart
  20. +13 −3 lib/src/definitions/security/no_security_scheme.dart
  21. +20 −22 lib/src/definitions/security/oauth2_security_scheme.dart
  22. +12 −16 lib/src/definitions/security/psk_security_scheme.dart
  23. +25 −65 lib/src/definitions/security/security_scheme.dart
  24. +7 −5 lib/src/definitions/validation/thing_description_schema.dart
  25. +7 −4 lib/src/scripting_api/interaction_options.dart
  26. +1 −1 pubspec.yaml
  27. +26 −1 test/core/consumed_thing_test.dart
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ jobs:
runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: dart-lang/setup-dart@v1

- name: Install dependencies
@@ -31,7 +31,7 @@ jobs:
- name: Run tests with coverage
run: dart run coverage:test_with_coverage

- uses: codecov/codecov-action@v2
- uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: coverage/lcov.info
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
## 0.26.0

- chore: address linting issues
- refactor: decouple credentials and security scheme classes
- feat!(security_scheme): use Uri instead of String for proxy field
- feat: add ComboSecurityScheme
- refactor!: rework deserialization of security schemes
- feat(scripting_api): make InteractionOptions immutable
- style: use const constructor in complex_example
- feat: update JSON Schema definition to latest version

## 0.25.1

- fix: mark package as compatible with Dart 3.x.x
2 changes: 1 addition & 1 deletion example/complex_example.dart
Original file line number Diff line number Diff line change
@@ -135,7 +135,7 @@ Future<void> main() async {

final status3 = await consumedThing.readProperty(
'anotherStatus',
InteractionOptions(uriVariables: {'test': 'hi'}),
const InteractionOptions(uriVariables: {'test': 'hi'}),
);
final value3 = await status3.value();
print(value3);
2 changes: 1 addition & 1 deletion lib/src/core/credentials/ace_credentials.dart
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ import 'credentials.dart';
/// [Credentials] used for the [AceSecurityScheme].
class AceCredentials extends Credentials {
/// Constructor.
AceCredentials(this.accessToken) : super('ace:ACESecurityScheme');
AceCredentials(this.accessToken);

/// The access token associated with these [AceCredentials] in serialized
/// form.
6 changes: 3 additions & 3 deletions lib/src/core/credentials/apikey_credentials.dart
Original file line number Diff line number Diff line change
@@ -8,10 +8,10 @@ import '../../definitions/security/apikey_security_scheme.dart';

import 'credentials.dart';

/// [Credentials] used for the `APIKeySecurityScheme`.
class ApiKeyCredentials extends Credentials<ApiKeySecurityScheme> {
/// [Credentials] used for the [ApiKeySecurityScheme].
class ApiKeyCredentials extends Credentials {
/// Constructor.
ApiKeyCredentials(this.apiKey) : super('apikey');
ApiKeyCredentials(this.apiKey);

/// The [apiKey] associated with these [ApiKeyCredentials].
String apiKey;
6 changes: 3 additions & 3 deletions lib/src/core/credentials/basic_credentials.dart
Original file line number Diff line number Diff line change
@@ -8,12 +8,12 @@ import '../../definitions/security/basic_security_scheme.dart';

import 'credentials.dart';

/// [Credentials] used for the `BasicSecurityScheme`.
/// [Credentials] used for the [BasicSecurityScheme].
///
/// Provides an unencrypted [username] and [password] combination.
class BasicCredentials extends Credentials<BasicSecurityScheme> {
class BasicCredentials extends Credentials {
/// Constructor.
BasicCredentials(this.username, this.password) : super('basic');
BasicCredentials(this.username, this.password);

/// The [username] associated with these [BasicCredentials].
String username;
6 changes: 3 additions & 3 deletions lib/src/core/credentials/bearer_credentials.dart
Original file line number Diff line number Diff line change
@@ -8,10 +8,10 @@ import '../../definitions/security/bearer_security_scheme.dart';

import 'credentials.dart';

/// [Credentials] used for the `BearerSecurityScheme`.
class BearerCredentials extends Credentials<BearerSecurityScheme> {
/// [Credentials] used for the [BearerSecurityScheme].
class BearerCredentials extends Credentials {
/// Constructor.
BearerCredentials(this.token) : super('bearer');
BearerCredentials(this.token);

/// The [token] associated with these [BearerCredentials].
String token;
10 changes: 1 addition & 9 deletions lib/src/core/credentials/credentials.dart
Original file line number Diff line number Diff line change
@@ -4,13 +4,5 @@
//
// SPDX-License-Identifier: BSD-3-Clause

import '../../definitions/security/security_scheme.dart';

/// Base class used for defining credentials for Thing Interactions.
abstract class Credentials<T extends SecurityScheme> {
/// Constructor.
Credentials(this.securitySchemeType);

/// The name of the SecurityScheme these [Credentials] are associated with.
final String securitySchemeType;
}
abstract class Credentials {}
4 changes: 2 additions & 2 deletions lib/src/core/credentials/digest_credentials.dart
Original file line number Diff line number Diff line change
@@ -8,9 +8,9 @@ import '../../definitions/security/digest_security_scheme.dart';
import 'credentials.dart';

/// [Credentials] used for the [DigestSecurityScheme].
class DigestCredentials extends Credentials<DigestSecurityScheme> {
class DigestCredentials extends Credentials {
/// Constructor.
DigestCredentials(this.username, this.password) : super('digest');
DigestCredentials(this.username, this.password);

/// The [username] associated with these [DigestCredentials].
String username;
4 changes: 2 additions & 2 deletions lib/src/core/credentials/oauth2_credentials.dart
Original file line number Diff line number Diff line change
@@ -8,9 +8,9 @@ import '../../definitions/security/oauth2_security_scheme.dart';
import 'credentials.dart';

/// [Credentials] used for the [OAuth2SecurityScheme].
class OAuth2Credentials extends Credentials<OAuth2SecurityScheme> {
class OAuth2Credentials extends Credentials {
/// Constructor.
OAuth2Credentials([this.secret]) : super('oauth2');
OAuth2Credentials([this.secret]);

/// The optional secret for these [OAuth2Credentials].
String? secret;
5 changes: 2 additions & 3 deletions lib/src/core/credentials/psk_credentials.dart
Original file line number Diff line number Diff line change
@@ -10,10 +10,9 @@ import '../../definitions/security/psk_security_scheme.dart';
import 'credentials.dart';

/// [Credentials] used for the [PskSecurityScheme].
class PskCredentials extends Credentials<PskSecurityScheme> {
class PskCredentials extends Credentials {
/// Constructor.
PskCredentials({required this.preSharedKey, required this.identity})
: super('psk');
PskCredentials({required this.preSharedKey, required this.identity});

/// The [identity] associated with these [PskCredentials].
///
46 changes: 44 additions & 2 deletions lib/src/definitions/extensions/json_parser.dart
Original file line number Diff line number Diff line change
@@ -9,6 +9,16 @@ import '../interaction_affordances/event.dart';
import '../interaction_affordances/interaction_affordance.dart';
import '../interaction_affordances/property.dart';
import '../link.dart';
import '../security/ace_security_scheme.dart';
import '../security/apikey_security_scheme.dart';
import '../security/auto_security_scheme.dart';
import '../security/basic_security_scheme.dart';
import '../security/bearer_security_scheme.dart';
import '../security/combo_security_scheme.dart';
import '../security/digest_security_scheme.dart';
import '../security/no_security_scheme.dart';
import '../security/oauth2_security_scheme.dart';
import '../security/psk_security_scheme.dart';
import '../security/security_scheme.dart';
import '../thing_description.dart';
import '../validation/validation_exception.dart';
@@ -312,7 +322,7 @@ extension ParseField on Map<String, dynamic> {
/// defined.
Map<String, SecurityScheme>? parseSecurityDefinitions(
PrefixMapping prefixMapping,
Set<String>? parsedFields,
Set<String> parsedFields,
) {
final fieldValue =
parseMapField<dynamic>('securityDefinitions', parsedFields);
@@ -326,7 +336,7 @@ extension ParseField on Map<String, dynamic> {
for (final securityDefinition in fieldValue.entries) {
final dynamic value = securityDefinition.value;
if (value is Map<String, dynamic>) {
final securityScheme = SecurityScheme.fromJson(value, prefixMapping);
final securityScheme = value._parseSecurityScheme(prefixMapping, {});
if (securityScheme != null) {
result[securityDefinition.key] = securityScheme;
}
@@ -336,6 +346,38 @@ extension ParseField on Map<String, dynamic> {
return result;
}

SecurityScheme? _parseSecurityScheme(
PrefixMapping prefixMapping,
Set<String> parsedFields,
) {
final scheme = parseRequiredField('scheme', parsedFields);

switch (scheme) {
case 'auto':
return AutoSecurityScheme.fromJson(this, prefixMapping, parsedFields);
case 'basic':
return BasicSecurityScheme.fromJson(this, prefixMapping, parsedFields);
case 'bearer':
return BearerSecurityScheme.fromJson(this, prefixMapping, parsedFields);
case 'combo':
return ComboSecurityScheme.fromJson(this, prefixMapping, parsedFields);
case 'nosec':
return NoSecurityScheme.fromJson(this, prefixMapping, parsedFields);
case 'psk':
return PskSecurityScheme.fromJson(this, prefixMapping, parsedFields);
case 'digest':
return DigestSecurityScheme.fromJson(this, prefixMapping, parsedFields);
case 'apikey':
return ApiKeySecurityScheme.fromJson(this, prefixMapping, parsedFields);
case 'oauth2':
return OAuth2SecurityScheme.fromJson(this, prefixMapping, parsedFields);
case 'ace:ACESecurityScheme':
return AceSecurityScheme.fromJson(this, prefixMapping, parsedFields);
}

return null;
}

/// Parses [Property]s contained in this JSON object.
///
/// Adds the key `properties` to the set of [parsedFields], if defined.
43 changes: 23 additions & 20 deletions lib/src/definitions/security/ace_security_scheme.dart
Original file line number Diff line number Diff line change
@@ -10,50 +10,53 @@ import '../extensions/json_parser.dart';

import 'security_scheme.dart';

const _schemeName = 'ace:ACESecurityScheme';

/// Experimental ACE Security Scheme.
class AceSecurityScheme extends SecurityScheme {
/// Constructor.
AceSecurityScheme({
String? description,
this.as,
this.audience,
this.scopes,
this.cnonce,
Map<String, String>? descriptions,
}) : super('ace:ACESecurityScheme') {
this.description = description;
this.descriptions.addAll(descriptions ?? {});
}
super.description,
super.descriptions,
super.proxy,
super.jsonLdType,
super.additionalFields,
}) : super(_schemeName);

/// Creates an [AceSecurityScheme] from a [json] object.
AceSecurityScheme.fromJson(
Map<String, dynamic> json,
PrefixMapping prefixMapping,
) : super('ace:ACESecurityScheme') {
final Set<String> parsedFields = {};

as = json.parseField<String>('ace:as', parsedFields);
cnonce = json.parseField<bool>('ace:cnonce', parsedFields);
audience = json.parseField<String>('ace:audience', parsedFields);
scopes = json.parseArrayField<String>('ace:scopes', parsedFields);

parseSecurityJson(json, parsedFields, prefixMapping);
}
Set<String> parsedFields,
) : as = json.parseField<String>('ace:as', parsedFields),
cnonce = json.parseField<bool>('ace:cnonce', parsedFields),
audience = json.parseField<String>('ace:audience', parsedFields),
scopes = json.parseArrayField<String>('ace:scopes', parsedFields),
super.fromJson(
_schemeName,
json,
prefixMapping,
parsedFields,
);

/// URI of the authorization server.
String? as;
final String? as;

/// The intended audience for this [AceSecurityScheme].
String? audience;
final String? audience;

/// Set of authorization scope identifiers provided as an array.
///
/// These are provided in tokens returned by an authorization server and
/// associated with forms in order to identify what resources a client may
/// access and how. The values associated with a form should be chosen from
/// those defined in an [AceSecurityScheme] active on that form.
List<String>? scopes;
final List<String>? scopes;

/// Indicates whether a [cnonce] is required by the Resource Server.
bool? cnonce;
final bool? cnonce;
}
32 changes: 18 additions & 14 deletions lib/src/definitions/security/apikey_security_scheme.dart
Original file line number Diff line number Diff line change
@@ -10,36 +10,40 @@ import '../extensions/json_parser.dart';
import 'security_scheme.dart';

const _defaultInValue = 'query';
const _schemeName = 'apikey';

/// API key authentication security configuration identified by the Vocabulary
/// Term `apikey`.
class ApiKeySecurityScheme extends SecurityScheme {
/// Constructor.
ApiKeySecurityScheme({
super.description,
super.proxy,
this.name,
String? in_,
this.in_ = _defaultInValue,
super.description,
super.descriptions,
}) : in_ = in_ ?? _defaultInValue,
super('apikey');
super.proxy,
super.jsonLdType,
super.additionalFields,
}) : super(_schemeName);

/// Creates a [ApiKeySecurityScheme] from a [json] object.
ApiKeySecurityScheme.fromJson(
Map<String, dynamic> json,
PrefixMapping prefixMapping,
) : super('apikey') {
final Set<String> parsedFields = {};

name = json.parseField<String>('name', parsedFields);
in_ = json.parseField<String>('in', parsedFields) ?? _defaultInValue;

parseSecurityJson(json, parsedFields, prefixMapping);
}
Set<String> parsedFields,
) : name = json.parseField<String>('name', parsedFields),
in_ = json.parseField<String>('in', parsedFields) ?? _defaultInValue,
super.fromJson(
_schemeName,
json,
prefixMapping,
parsedFields,
);

/// Name for query, header, cookie, or uri parameters.
String? name;

/// Specifies the location of security authentication information.
late String in_;
final String in_;
}
16 changes: 13 additions & 3 deletions lib/src/definitions/security/auto_security_scheme.dart
Original file line number Diff line number Diff line change
@@ -8,14 +8,24 @@ import 'package:curie/curie.dart';

import 'security_scheme.dart';

const _schemeName = 'auto';

/// An automatic security configuration identified by the
/// vocabulary term `auto`.
class AutoSecurityScheme extends SecurityScheme {
/// Constructor.
AutoSecurityScheme({
super.description,
super.descriptions,
super.proxy,
super.jsonLdType,
super.additionalFields,
}) : super(_schemeName);

/// Creates an [AutoSecurityScheme] from a [json] object.
AutoSecurityScheme.fromJson(
Map<String, dynamic> json,
PrefixMapping prefixMapping,
) : super('auto') {
parseSecurityJson(json, {}, prefixMapping);
}
Set<String> parsedFields,
) : super.fromJson(_schemeName, json, prefixMapping, parsedFields);
}
29 changes: 14 additions & 15 deletions lib/src/definitions/security/basic_security_scheme.dart
Original file line number Diff line number Diff line change
@@ -11,35 +11,34 @@ import 'security_scheme.dart';

const _defaultInValue = 'header';

const _schemeName = 'basic';

/// Basic Authentication security configuration identified by the Vocabulary
/// Term `basic`.
class BasicSecurityScheme extends SecurityScheme {
/// Constructor.
BasicSecurityScheme({
super.description,
super.proxy,
this.name,
String? in_,
this.in_ = _defaultInValue,
super.description,
super.descriptions,
}) : in_ = in_ ?? _defaultInValue,
super('basic');
super.proxy,
super.jsonLdType,
super.additionalFields,
}) : super(_schemeName);

/// Creates a [BasicSecurityScheme] from a [json] object.
BasicSecurityScheme.fromJson(
Map<String, dynamic> json,
PrefixMapping prefixMapping,
) : super('basic') {
final Set<String> parsedFields = {};

name = json.parseField<String>('name', parsedFields);
in_ = json.parseField<String>('in', parsedFields) ?? _defaultInValue;

parseSecurityJson(json, parsedFields, prefixMapping);
}
Set<String> parsedFields,
) : name = json.parseField<String>('name', parsedFields),
in_ = json.parseField<String>('in', parsedFields) ?? _defaultInValue,
super.fromJson(_schemeName, json, prefixMapping, parsedFields);

/// Name for query, header, cookie, or uri parameters.
late final String? name;
final String? name;

/// Specifies the location of security authentication information.
late String in_ = 'header';
final String in_;
}
47 changes: 22 additions & 25 deletions lib/src/definitions/security/bearer_security_scheme.dart
Original file line number Diff line number Diff line change
@@ -13,53 +13,50 @@ const _defaultInValue = 'header';
const _defaultAlgValue = 'ES256';
const _defaultFormatValue = 'jwt';

const _schemeName = 'bearer';

/// Bearer Token security configuration identified by the Vocabulary Term
/// `bearer`.
class BearerSecurityScheme extends SecurityScheme {
/// Constructor.
BearerSecurityScheme({
this.name,
String? alg,
String? format,
this.alg = _defaultAlgValue,
this.format = _defaultFormatValue,
this.authorization,
String? in_,
super.proxy,
this.in_ = _defaultInValue,
super.description,
super.descriptions,
}) : in_ = in_ ?? _defaultInValue,
alg = alg ?? _defaultAlgValue,
format = format ?? _defaultFormatValue,
super('bearer');
super.proxy,
super.jsonLdType,
super.additionalFields,
}) : super(_schemeName);

/// Creates a [BearerSecurityScheme] from a [json] object.
BearerSecurityScheme.fromJson(
Map<String, dynamic> json,
PrefixMapping prefixMapping,
) : super('bearer') {
final Set<String> parsedFields = {};

name = json.parseField<String>('name', parsedFields);
in_ = json.parseField<String>('in', parsedFields) ?? _defaultInValue;
format =
json.parseField<String>('format', parsedFields) ?? _defaultFormatValue;
alg = json.parseField<String>('alg', parsedFields) ?? _defaultAlgValue;
authorization = json.parseField<String>('authorization', parsedFields);

parseSecurityJson(json, parsedFields, prefixMapping);
}
Set<String> parsedFields,
) : name = json.parseField<String>('name', parsedFields),
in_ = json.parseField<String>('in', parsedFields) ?? _defaultInValue,
format = json.parseField<String>('format', parsedFields) ??
_defaultFormatValue,
alg = json.parseField<String>('alg', parsedFields) ?? _defaultAlgValue,
authorization = json.parseField<String>('authorization', parsedFields),
super.fromJson(_schemeName, json, prefixMapping, parsedFields);

/// URI of the authorization server.
late final String? authorization;
final String? authorization;

/// Name for query, header, cookie, or uri parameters.
late final String? name;
final String? name;

/// Encoding, encryption, or digest algorithm.
late final String alg;
final String alg;

/// Specifies format of security authentication information.
late final String format;
final String format;

/// Specifies the location of security authentication information.
late final String in_;
final String in_;
}
46 changes: 46 additions & 0 deletions lib/src/definitions/security/combo_security_scheme.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2023 The NAMIB Project Developers. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
// SPDX-License-Identifier: BSD-3-Clause

import 'package:curie/curie.dart';

import '../extensions/json_parser.dart';
import 'security_scheme.dart';

const _schemeName = 'combo';

/// A combination of other security schemes identified by the Vocabulary Term
/// `combo` (i.e., "scheme": "combo").
class ComboSecurityScheme extends SecurityScheme {
/// Constructor.
ComboSecurityScheme({
this.allOf,
this.oneOf,
super.description,
super.descriptions,
super.proxy,
super.jsonLdType,
super.additionalFields,
}) : super(_schemeName);

/// Creates a [ComboSecurityScheme] from a [json] object.
ComboSecurityScheme.fromJson(
Map<String, dynamic> json,
PrefixMapping prefixMapping,
Set<String> parsedFields,
) : oneOf = json.parseArrayField<String>('oneOf', parsedFields),
allOf = json.parseArrayField<String>('allOf', parsedFields),
super.fromJson(_schemeName, json, prefixMapping, parsedFields);

/// Array of two or more strings identifying other named security scheme
/// definitions, any one of which, when satisfied, will allow access.
///
/// Only one may be chosen for use.
final List<String>? oneOf;

/// Array of two or more strings identifying other named security scheme
/// definitions, all of which must be satisfied for access.
final List<String>? allOf;
}
34 changes: 15 additions & 19 deletions lib/src/definitions/security/digest_security_scheme.dart
Original file line number Diff line number Diff line change
@@ -18,36 +18,32 @@ const _defaultQoPValue = 'auth';
class DigestSecurityScheme extends SecurityScheme {
/// Constructor.
DigestSecurityScheme({
String? in_,
String? qop,
super.description,
super.proxy,
this.in_ = _defaultInValue,
this.qop = _defaultQoPValue,
this.name,
super.description,
super.descriptions,
}) : in_ = in_ ?? _defaultInValue,
qop = qop ?? _defaultQoPValue,
super('digest');
super.proxy,
super.jsonLdType,
super.additionalFields,
}) : super('digest');

/// Creates a [DigestSecurityScheme] from a [json] object.
DigestSecurityScheme.fromJson(
Map<String, dynamic> json,
PrefixMapping prefixMapping,
) : super('digest') {
final Set<String> parsedFields = {};

name = json.parseField<String>('name', parsedFields);
in_ = json.parseField<String>('in', parsedFields) ?? _defaultInValue;
qop = json.parseField<String>('qop', parsedFields) ?? _defaultInValue;

parseSecurityJson(json, parsedFields, prefixMapping);
}
Set<String> parsedFields,
) : name = json.parseField<String>('name', parsedFields),
in_ = json.parseField<String>('in', parsedFields) ?? _defaultInValue,
qop = json.parseField<String>('qop', parsedFields) ?? _defaultInValue,
super.fromJson('digest', json, prefixMapping, parsedFields);

/// Name for query, header, cookie, or uri parameters.
late final String? name;
final String? name;

/// Specifies the location of security authentication information.
late final String in_;
final String in_;

/// Quality of protection.
late final String? qop;
final String qop;
}
16 changes: 13 additions & 3 deletions lib/src/definitions/security/no_security_scheme.dart
Original file line number Diff line number Diff line change
@@ -8,14 +8,24 @@ import 'package:curie/curie.dart';

import 'security_scheme.dart';

const _schemeName = 'nosec';

/// A security configuration corresponding to identified by the Vocabulary Term
/// `nosec`.
class NoSecurityScheme extends SecurityScheme {
/// Constructor.
NoSecurityScheme({
super.description,
super.descriptions,
super.proxy,
super.jsonLdType,
super.additionalFields,
}) : super(_schemeName);

/// Creates a [NoSecurityScheme] from a [json] object.
NoSecurityScheme.fromJson(
Map<String, dynamic> json,
PrefixMapping prefixMapping,
) : super('nosec') {
parseSecurityJson(json, {}, prefixMapping);
}
Set<String> parsedFields,
) : super.fromJson(_schemeName, json, prefixMapping, parsedFields);
}
42 changes: 20 additions & 22 deletions lib/src/definitions/security/oauth2_security_scheme.dart
Original file line number Diff line number Diff line change
@@ -9,60 +9,58 @@ import 'package:curie/curie.dart';
import '../extensions/json_parser.dart';
import 'security_scheme.dart';

const _schemeName = 'oauth2';

/// OAuth 2.0 authentication security configuration for systems conformant with
/// RFC 6749, RFC 8252 and (for the device flow) RFC 8628, identified by the
/// Vocabulary Term `oauth2`.
class OAuth2SecurityScheme extends SecurityScheme {
/// Constructor.
OAuth2SecurityScheme(
this.flow, {
String? description,
this.authorization,
this.scopes,
this.refresh,
this.token,
Map<String, String>? descriptions,
}) : super('oauth2') {
this.description = description;
this.descriptions.addAll(descriptions ?? {});
}
super.description,
super.descriptions,
super.proxy,
super.jsonLdType,
super.additionalFields,
}) : super(_schemeName);

/// Creates a [OAuth2SecurityScheme] from a [json] object.
OAuth2SecurityScheme.fromJson(
Map<String, dynamic> json,
PrefixMapping prefixMapping,
) : super('oauth2') {
final Set<String> parsedFields = {};

authorization = json.parseField<String>('authorization', parsedFields);
token = json.parseField<String>('token', parsedFields);
refresh = json.parseField<String>('refresh', parsedFields);
scopes = json.parseArrayField<String>('scopes', parsedFields);
flow = json.parseRequiredField<String>('flow', parsedFields);

parseSecurityJson(json, parsedFields, prefixMapping);
}
Set<String> parsedFields,
) : authorization = json.parseField<String>('authorization', parsedFields),
token = json.parseField<String>('token', parsedFields),
refresh = json.parseField<String>('refresh', parsedFields),
scopes = json.parseArrayField<String>('scopes', parsedFields),
flow = json.parseRequiredField<String>('flow', parsedFields),
super.fromJson(_schemeName, json, prefixMapping, parsedFields);

/// URI of the authorization server.
///
/// In the case of the `device` flow, the URI provided for the [authorization]
/// value refers to the device authorization endpoint.
late String? authorization;
final String? authorization;

/// URI of the token server.
late String? token;
final String? token;

/// URI of the authorization server.
late String? refresh;
final String? refresh;

/// Set of authorization scope identifiers provided as an array.
///
/// These are provided in tokens returned by an authorization server and
/// associated with forms in order to identify what resources a client may
/// access and how. The values associated with a form should be chosen from
/// those defined in an [OAuth2SecurityScheme] active on that form.
late List<String>? scopes;
final List<String>? scopes;

/// Authorization flow.
late String flow;
final String flow;
}
28 changes: 12 additions & 16 deletions lib/src/definitions/security/psk_security_scheme.dart
Original file line number Diff line number Diff line change
@@ -9,33 +9,29 @@ import 'package:curie/curie.dart';
import '../extensions/json_parser.dart';
import 'security_scheme.dart';

const _schemeName = 'psk';

/// Pre-shared key authentication security configuration identified by the
/// Vocabulary Term `psk`.
class PskSecurityScheme extends SecurityScheme {
/// Constructor.
PskSecurityScheme({
this.identity,
String? description,
String? proxy,
Map<String, String>? descriptions,
}) : super('psk') {
this.description = description;
this.proxy = proxy;
this.descriptions.addAll(descriptions ?? {});
}
super.description,
super.descriptions,
super.proxy,
super.jsonLdType,
super.additionalFields,
}) : super(_schemeName);

/// Creates a [PskSecurityScheme] from a [json] object.
PskSecurityScheme.fromJson(
Map<String, dynamic> json,
PrefixMapping prefixMapping,
) : super('psk') {
final Set<String> parsedFields = {};

identity = json.parseField<String>('identity');

parseSecurityJson(json, parsedFields, prefixMapping);
}
Set<String> parsedFields,
) : identity = json.parseField<String>('identity'),
super.fromJson(_schemeName, json, prefixMapping, parsedFields);

/// Name for query, header, cookie, or uri parameters.
String? identity;
final String? identity;
}
90 changes: 25 additions & 65 deletions lib/src/definitions/security/security_scheme.dart
Original file line number Diff line number Diff line change
@@ -7,28 +7,32 @@
import 'package:curie/curie.dart';

import '../extensions/json_parser.dart';
import 'ace_security_scheme.dart';
import 'apikey_security_scheme.dart';
import 'auto_security_scheme.dart';
import 'basic_security_scheme.dart';
import 'bearer_security_scheme.dart';
import 'digest_security_scheme.dart';
import 'no_security_scheme.dart';
import 'oauth2_security_scheme.dart';
import 'psk_security_scheme.dart';

/// Class that contains metadata describing the configuration of a security
/// mechanism.
abstract class SecurityScheme {
/// Constructor.
SecurityScheme(
this.scheme, {
this.jsonLdType,
this.description,
this.proxy,
Map<String, String>? descriptions,
}) {
this.descriptions.addAll(descriptions ?? {});
}
this.descriptions,
this.additionalFields,
});

/// Creates a [SecurityScheme] from a [json] object.
SecurityScheme.fromJson(
this.scheme,
Map<String, dynamic> json,
PrefixMapping prefixMapping,
Set<String> parsedFields,
) : proxy = json.parseUriField('proxy', parsedFields),
description = json.parseField<String>('description', parsedFields),
descriptions = json.parseMapField<String>('descriptions', parsedFields),
jsonLdType = json.parseArrayField<String>('@type'),
additionalFields =
json.parseAdditionalFields(prefixMapping, parsedFields);

/// The actual security [scheme] identifier.
///
@@ -37,64 +41,20 @@ abstract class SecurityScheme {
final String scheme;

/// The default [description] of this [SecurityScheme].
String? description;
final String? description;

/// A [Map] of multi-language [descriptions].
Map<String, String> descriptions = {};
final Map<String, String>? descriptions;

/// [Uri] of the proxy server this security configuration provides access to.
///
String? proxy;
/// If not given, the corresponding security configuration is for the
/// endpoint.
final Uri? proxy;

/// A [List] of JSON-LD `@type` annotations.
List<String>? jsonLdType = [];
final List<String>? jsonLdType;

/// Additional fields collected during the parsing of a JSON object.
final Map<String, dynamic> additionalFields = <String, dynamic>{};

/// Parses the fields shared by all [SecurityScheme]s.
void parseSecurityJson(
Map<String, dynamic> json,
Set<String> parsedFields,
PrefixMapping prefixMapping,
) {
parsedFields.add('scheme');

proxy = json.parseField<String>('proxy', parsedFields);
description = json.parseField<String>('description', parsedFields);
descriptions
.addAll(json.parseMapField<String>('descriptions', parsedFields) ?? {});
jsonLdType = json.parseArrayField<String>('@type');

additionalFields
.addAll(json.parseAdditionalFields(prefixMapping, parsedFields));
}

/// Creates a [SecurityScheme] from a [json] object.
static SecurityScheme? fromJson(
Map<String, dynamic> json,
PrefixMapping prefixMapping,
) {
switch (json['scheme']) {
case 'auto':
return AutoSecurityScheme.fromJson(json, prefixMapping);
case 'basic':
return BasicSecurityScheme.fromJson(json, prefixMapping);
case 'bearer':
return BearerSecurityScheme.fromJson(json, prefixMapping);
case 'nosec':
return NoSecurityScheme.fromJson(json, prefixMapping);
case 'psk':
return PskSecurityScheme.fromJson(json, prefixMapping);
case 'digest':
return DigestSecurityScheme.fromJson(json, prefixMapping);
case 'apikey':
return ApiKeySecurityScheme.fromJson(json, prefixMapping);
case 'oauth2':
return OAuth2SecurityScheme.fromJson(json, prefixMapping);
case 'ace:ACESecurityScheme':
return AceSecurityScheme.fromJson(json, prefixMapping);
}

return null;
}
final Map<String, dynamic>? additionalFields;
}
12 changes: 7 additions & 5 deletions lib/src/definitions/validation/thing_description_schema.dart
Original file line number Diff line number Diff line change
@@ -34,12 +34,12 @@ class ThingDescriptionValidationException extends ValidationException {

final Map<String, dynamic> _rawThingDescriptionSchema = <String, dynamic>{
'title': 'Thing Description',
'version': '1.1-10-June-2022',
'version': '1.1-23-March-2023',
'description':
'JSON Schema for validating TD instances against the TD information '
'model. TD instances can be with or without terms that have default '
'values',
'\$schema ': 'http://json-schema.org/draft-07/schema#',
'\$schema': 'http://json-schema.org/draft-07/schema#',
'\$id':
'https://raw.githubusercontent.com/w3c/wot-thing-description/main/validation/td-json-schema-validation.json',
'definitions': {
@@ -58,7 +58,8 @@ final Map<String, dynamic> _rawThingDescriptionSchema = <String, dynamic>{
'oneOf': [
{
'type': 'array',
'items': {'type': 'string'}
'items': {'type': 'string'},
'minItems': 1
},
{'type': 'string'}
]
@@ -148,7 +149,7 @@ final Map<String, dynamic> _rawThingDescriptionSchema = <String, dynamic>{
}
},
{
'\$comment': 'Only the new context URI',
'\$comment': 'Only the old context URI',
'\$ref': '#/definitions/thing-context-td-uri-v1'
}
]
@@ -261,7 +262,8 @@ final Map<String, dynamic> _rawThingDescriptionSchema = <String, dynamic>{
'type': 'object',
'properties': {
'contentType': {'type': 'string'}
}
},
'required': ['contentType']
},
'form_element_base': {
'type': 'object',
11 changes: 7 additions & 4 deletions lib/src/scripting_api/interaction_options.dart
Original file line number Diff line number Diff line change
@@ -4,24 +4,27 @@
//
// SPDX-License-Identifier: BSD-3-Clause

import 'package:meta/meta.dart';

/// Holds the interaction options that need to be exposed for application
/// scripts according to the Thing Description.
///
/// See [WoT Scripting API Specification, Section 8.12][spec link].
///
/// [spec link]: https://w3c.github.io/wot-scripting-api/#the-interactionoptions-dictionary
@immutable
class InteractionOptions {
/// Constructor
InteractionOptions({this.formIndex, this.uriVariables, this.data});
const InteractionOptions({this.formIndex, this.uriVariables, this.data});

/// Represents an application hint for which Form definition should be used
/// for the given interaction.
int? formIndex;
final int? formIndex;

/// Represents the URI template variables to be used with the interaction.
Map<String, Object>? uriVariables;
final Map<String, Object>? uriVariables;

/// Represents additional opaque data that needs to be passed to the
/// interaction.
Object? data;
final Object? data;
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: dart_wot
description: A W3C Web of Things implementation written in Dart. Supports interacting with Things using CoAP, HTTP, and MQTT.
version: 0.25.1
version: 0.26.0
homepage: https://github.com/namib-project/dart_wot

environment:
27 changes: 26 additions & 1 deletion test/core/consumed_thing_test.dart
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ import 'package:dart_wot/dart_wot.dart';
import 'package:dart_wot/src/definitions/security/apikey_security_scheme.dart';
import 'package:dart_wot/src/definitions/security/basic_security_scheme.dart';
import 'package:dart_wot/src/definitions/security/bearer_security_scheme.dart';
import 'package:dart_wot/src/definitions/security/combo_security_scheme.dart';
import 'package:dart_wot/src/definitions/security/digest_security_scheme.dart';
import 'package:dart_wot/src/definitions/security/no_security_scheme.dart';
import 'package:dart_wot/src/definitions/security/oauth2_security_scheme.dart';
@@ -79,6 +80,14 @@ void main() {
"refresh": "http://example.org",
"scopes": "test",
"flow": "client"
},
"combo_sc1": {
"scheme": "combo",
"allOf": ["digest_sc", "apikey_sc"]
},
"combo_sc2": {
"scheme": "combo",
"oneOf": ["oauth2_sc", "bearer_sc"]
}
},
"security": "nosec_sc",
@@ -166,7 +175,7 @@ void main() {

final nosecSc = parsedTd.securityDefinitions['nosec_sc'];
expect(nosecSc is NoSecurityScheme, true);
expect(nosecSc?.proxy, 'http://example.org');
expect(nosecSc?.proxy, Uri.parse('http://example.org'));
expect(nosecSc?.jsonLdType, ['Test']);

final basicSc = parsedTd.securityDefinitions['basic_sc'];
@@ -210,6 +219,22 @@ void main() {
expect(oauth2Sc.token, 'http://example.org');
expect(oauth2Sc.scopes, ['test']);
expect(oauth2Sc.flow, 'client');

final comboSc1 = parsedTd.securityDefinitions['combo_sc1'];
expect(comboSc1 is ComboSecurityScheme, true);
expect(
(comboSc1 as ComboSecurityScheme?)!.allOf,
['digest_sc', 'apikey_sc'],
);
expect(comboSc1!.oneOf, null);

final comboSc2 = parsedTd.securityDefinitions['combo_sc2'];
expect(comboSc2 is ComboSecurityScheme, true);
expect(
(comboSc2 as ComboSecurityScheme?)!.oneOf,
['oauth2_sc', 'bearer_sc'],
);
expect(comboSc2!.allOf, null);
});
});