diff --git a/packages/auth_oauth2/AUTHORS.md b/packages/auth_oauth2/AUTHORS.md new file mode 100644 index 00000000..ac95ab58 --- /dev/null +++ b/packages/auth_oauth2/AUTHORS.md @@ -0,0 +1,12 @@ +Primary Authors +=============== + +* __[Thomas Hii](dukefirehawk.apps@gmail.com)__ + + Thomas is the current maintainer of the code base. He has refactored and migrated the + code base to support NNBD. + +* __[Tobe O](thosakwe@gmail.com)__ + + Tobe has written much of the original code prior to NNBD migration. He has moved on and + is no longer involved with the project. diff --git a/packages/auth_oauth2/CHANGELOG.md b/packages/auth_oauth2/CHANGELOG.md index ae11c7b5..3bb7e4c6 100644 --- a/packages/auth_oauth2/CHANGELOG.md +++ b/packages/auth_oauth2/CHANGELOG.md @@ -1,3 +1,9 @@ +# 4.0.0 +* Migrated to support Dart SDK 2.12.x NNBD + +# 3.0.0 +* Migrated to work with Dart SDK 2.12.x Non NNBD + # 2.1.0 * Angel 2 + Dart 2 update * Support for handling errors + rejections. diff --git a/packages/auth_oauth2/README.md b/packages/auth_oauth2/README.md index cd6cddc0..495eb02d 100644 --- a/packages/auth_oauth2/README.md +++ b/packages/auth_oauth2/README.md @@ -1,8 +1,11 @@ -# auth_oauth2 +# angel3_auth_oauth2 +[![version](https://img.shields.io/badge/pub-v4.0.0-brightgreen)](https://pub.dartlang.org/packages/angel3_auth_oauth2) +[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety) +[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion) -[![Pub](https://img.shields.io/pub/v/angel_auth_oauth2.svg)](https://pub.dartlang.org/packages/angel_auth_oauth2) +[![License](https://img.shields.io/github/license/dukefirehawk/angel)](https://github.com/dukefirehawk/angel/tree/angel3/packages/auth_oauth2/LICENSE) -`package:angel_auth` strategy for OAuth2 login, i.e. Facebook or Github. +`package:angel3_auth` strategy for OAuth2 login, i.e. Facebook or Github. # Usage First, create an options object: @@ -77,7 +80,7 @@ Set up two routes: In the case of the callback route, you may want to display an HTML page that closes a popup window. In this case, use `confirmPopupAuthentication`, which is bundled with -`package:angel_auth`, as a `callback` function: +`package:angel3_auth`, as a `callback` function: ```dart configureServer(Angel app) async { diff --git a/packages/auth_oauth2/example/main.dart b/packages/auth_oauth2/example/main.dart index 983da4e6..93edda42 100644 --- a/packages/auth_oauth2/example/main.dart +++ b/packages/auth_oauth2/example/main.dart @@ -1,8 +1,8 @@ import 'dart:convert'; -import 'package:angel_auth/angel_auth.dart'; -import 'package:angel_framework/angel_framework.dart'; -import 'package:angel_framework/http.dart'; -import 'package:angel_auth_oauth2/angel_auth_oauth2.dart'; +import 'package:angel3_auth/angel3_auth.dart'; +import 'package:angel3_framework/angel3_framework.dart'; +import 'package:angel3_framework/http.dart'; +import 'package:angel3_auth_oauth2/angel3_auth_oauth2.dart'; import 'package:http_parser/http_parser.dart'; import 'package:logging/logging.dart'; @@ -63,7 +63,7 @@ void main() async { (client, req, res) async { var response = await client.get(Uri.parse('https://api.github.com/user')); var ghUser = json.decode(response.body); - var id = ghUser['id'] as int; + var id = ghUser['id'] as int?; var matchingUsers = await mappedUserService.index({ 'query': {'github_id': id} @@ -85,7 +85,7 @@ void main() async { }, // We have to pass this parser function when working with Github. - getParameters: parseParamsFromGithub, + //getParameters: parseParamsFromGithub, ); // Mount some routes @@ -98,7 +98,7 @@ void main() async { // // Use `confirmPopupAuthentication`, which is bundled with // `package:angel_auth`. - var user = req.container.make(); + var user = req.container!.make()!; res.write('Your user info: ${user.toJson()}\n\n'); res.write('Your JWT: $jwt'); await res.close(); @@ -113,14 +113,14 @@ void main() async { class User extends Model { @override - String id; + String? id; - int githubId; + int? githubId; User({this.id, this.githubId}); static User parse(Map map) => - User(id: map['id'] as String, githubId: map['github_id'] as int); + User(id: map['id'] as String?, githubId: map['github_id'] as int?); static Map serialize(User user) => user.toJson(); diff --git a/packages/auth_oauth2/lib/angel_auth_oauth2.dart b/packages/auth_oauth2/lib/angel3_auth_oauth2.dart similarity index 74% rename from packages/auth_oauth2/lib/angel_auth_oauth2.dart rename to packages/auth_oauth2/lib/angel3_auth_oauth2.dart index 2583d54e..6a16c6ad 100644 --- a/packages/auth_oauth2/lib/angel_auth_oauth2.dart +++ b/packages/auth_oauth2/lib/angel3_auth_oauth2.dart @@ -1,8 +1,8 @@ -library angel_auth_oauth2; +library angel3_auth_oauth2; import 'dart:async'; -import 'package:angel_auth/angel_auth.dart'; -import 'package:angel_framework/angel_framework.dart'; +import 'package:angel3_auth/angel3_auth.dart'; +import 'package:angel3_framework/angel3_framework.dart'; import 'package:http_parser/http_parser.dart'; import 'package:oauth2/oauth2.dart' as oauth2; @@ -28,33 +28,33 @@ class OAuth2Strategy implements AuthStrategy { final Uri tokenEndpoint; /// An optional callback used to parse the response from a server who does not follow the OAuth 2.0 spec. - final Map Function(MediaType, String) getParameters; + final Map Function(MediaType?, String)? getParameters; /// An optional delimiter used to send requests to server who does not follow the OAuth 2.0 spec. final String delimiter; - Uri _redirect; + Uri? _redirect; OAuth2Strategy(this.options, this.authorizationEndpoint, this.tokenEndpoint, this.verifier, this.onError, {this.getParameters, this.delimiter = ' '}); - oauth2.AuthorizationCodeGrant _createGrant() => - new oauth2.AuthorizationCodeGrant(options.clientId, authorizationEndpoint, - tokenEndpoint, - secret: options.clientSecret, - delimiter: delimiter, - getParameters: getParameters); + oauth2.AuthorizationCodeGrant _createGrant() => oauth2.AuthorizationCodeGrant( + options.clientId, authorizationEndpoint, tokenEndpoint, + secret: options.clientSecret, + delimiter: delimiter, + getParameters: getParameters); @override - FutureOr authenticate(RequestContext req, ResponseContext res, - [AngelAuthOptions options]) async { + FutureOr authenticate(RequestContext req, ResponseContext res, + [AngelAuthOptions? options]) async { if (options != null) { var result = await authenticateCallback(req, res, options); - if (result is User) + if (result is User) { return result; - else + } else { return null; + } } if (_redirect == null) { @@ -65,20 +65,20 @@ class OAuth2Strategy implements AuthStrategy { ); } - res.redirect(_redirect); + await res.redirect(_redirect); return null; } /// The endpoint that is invoked by the third-party after successful authentication. Future authenticateCallback(RequestContext req, ResponseContext res, - [AngelAuthOptions options]) async { + [AngelAuthOptions? options]) async { var grant = _createGrant(); grant.getAuthorizationUrl(this.options.redirectUri, scopes: this.options.scopes); try { var client = - await grant.handleAuthorizationResponse(req.uri.queryParameters); + await grant.handleAuthorizationResponse(req.uri!.queryParameters); return await verifier(client, req, res); } on oauth2.AuthorizationException catch (e) { return await onError(e, req, res); diff --git a/packages/auth_oauth2/pubspec.yaml b/packages/auth_oauth2/pubspec.yaml index fe84396d..0e74db71 100644 --- a/packages/auth_oauth2/pubspec.yaml +++ b/packages/auth_oauth2/pubspec.yaml @@ -1,24 +1,14 @@ -name: angel_auth_oauth2 +name: angel3_auth_oauth2 +version: 4.0.0 description: angel_auth strategy for OAuth2 login, i.e. Facebook, Github, etc. -version: 3.0.0 -#author: Tobe O -publish_to: none +homepage: https://github.com/dukefirehawk/angel/tree/angel3/packages/auth_oauth2 environment: - sdk: ">=2.10.0 <3.0.0" -homepage: https://github.com/angel-dart/auth_oauth2.git + sdk: '>=2.12.0 <3.0.0' dependencies: - angel_auth: - git: - url: https://github.com/dukefirehawk/angel.git - ref: sdk-2.12.x - path: packages/auth - angel_framework: - git: - url: https://github.com/dukefirehawk/angel.git - ref: sdk-2.12.x - path: packages/framework + angel3_auth: ^4.0.0 + angel3_framework: ^4.0.0 http_parser: ^4.0.0 oauth2: ^2.0.0 dev_dependencies: - logging: ^1.0.0 - pedantic: ^1.0.0 \ No newline at end of file + logging: ^1.0.1 + pedantic: ^1.11.0 \ No newline at end of file diff --git a/packages/cache/AUTHORS.md b/packages/cache/AUTHORS.md new file mode 100644 index 00000000..ac95ab58 --- /dev/null +++ b/packages/cache/AUTHORS.md @@ -0,0 +1,12 @@ +Primary Authors +=============== + +* __[Thomas Hii](dukefirehawk.apps@gmail.com)__ + + Thomas is the current maintainer of the code base. He has refactored and migrated the + code base to support NNBD. + +* __[Tobe O](thosakwe@gmail.com)__ + + Tobe has written much of the original code prior to NNBD migration. He has moved on and + is no longer involved with the project. diff --git a/packages/cache/CHANGELOG.md b/packages/cache/CHANGELOG.md index cf5dc962..18ea3bfe 100644 --- a/packages/cache/CHANGELOG.md +++ b/packages/cache/CHANGELOG.md @@ -1,3 +1,9 @@ +# 4.0.0 +* Migrated to support Dart SDK 2.12.x NNBD + +# 3.0.0 +* Migrated to work with Dart SDK 2.12.x Non NNBD + # 2.0.1 * Add `ignoreQueryAndFragment` to `ResponseCache`. * Rename `CacheService.ignoreQuery` to `ignoreParams`. diff --git a/packages/cache/README.md b/packages/cache/README.md index 238be5e6..a0948900 100644 --- a/packages/cache/README.md +++ b/packages/cache/README.md @@ -1,6 +1,9 @@ -# cache -[![Pub](https://img.shields.io/pub/v/angel_cache.svg)](https://pub.dartlang.org/packages/angel_cache) -[![build status](https://travis-ci.org/angel-dart/cache.svg)](https://travis-ci.org/angel-dart/cache) +# angel3_cache +[![version](https://img.shields.io/badge/pub-v4.0.0-brightgreen)](https://pub.dartlang.org/packages/angel3_cache) +[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety) +[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion) + +[![License](https://img.shields.io/github/license/dukefirehawk/angel)](https://github.com/dukefirehawk/angel/tree/angel3/packages/cache/LICENSE) Support for server-side caching in [Angel](https://angel-dart.github.io). @@ -17,13 +20,13 @@ This can improve the performance of sending objects that are complex to serializ You can pass a [shouldCache] callback to determine which values should be cached. ```dart -main() async { - var app = new Angel()..lazyParseBodies = true; +void main() async { + var app = Angel()..lazyParseBodies = true; app.use( '/api/todos', - new CacheService( - database: new AnonymousService( + CacheService( + database: AnonymousService( index: ([params]) { print('Fetched directly from the underlying service at ${new DateTime.now()}!'); return ['foo', 'bar', 'baz']; @@ -51,10 +54,10 @@ To initialize a simple cache: ```dart Future configureServer(Angel app) async { // Simple instance. - var cache = new ResponseCache(); + var cache = ResponseCache(); // You can also pass an invalidation timeout. - var cache = new ResponseCache(timeout: const Duration(days: 2)); + var cache = ResponseCache(timeout: const Duration(days: 2)); // Close the cache when the application closes. app.shutdownHooks.add((_) => cache.close()); @@ -62,8 +65,8 @@ Future configureServer(Angel app) async { // Use `patterns` to specify which resources should be cached. cache.patterns.addAll([ 'robots.txt', - new RegExp(r'\.(png|jpg|gif|txt)$'), - new Glob('public/**/*'), + RegExp(r'\.(png|jpg|gif|txt)$'), + Glob('public/**/*'), ]); // REQUIRED: The middleware that serves cached responses @@ -85,7 +88,7 @@ to ensure no arbitrary attacker can hack your cache: Future configureServer(Angel app) async { app.addRoute('PURGE', '*', (req, res) { if (req.ip != '127.0.0.1') - throw new AngelHttpException.forbidden(); + throw AngelHttpException.forbidden(); return cache.purge(req.uri.path); }); } diff --git a/packages/cache/example/cache_service.dart b/packages/cache/example/cache_service.dart index 6745e49c..51937e29 100644 --- a/packages/cache/example/cache_service.dart +++ b/packages/cache/example/cache_service.dart @@ -1,6 +1,6 @@ -import 'package:angel_cache/angel_cache.dart'; -import 'package:angel_framework/angel_framework.dart'; -import 'package:angel_framework/http.dart'; +import 'package:angel3_cache/angel3_cache.dart'; +import 'package:angel3_framework/angel3_framework.dart'; +import 'package:angel3_framework/http.dart'; main() async { var app = Angel(); @@ -13,7 +13,7 @@ main() async { print( 'Fetched directly from the underlying service at ${new DateTime.now()}!'); return ['foo', 'bar', 'baz']; - }, read: (id, [params]) { + }, read: (dynamic id, [params]) { return {id: '$id at ${new DateTime.now()}'}; }), ), diff --git a/packages/cache/example/main.dart b/packages/cache/example/main.dart index c6851400..fb174508 100644 --- a/packages/cache/example/main.dart +++ b/packages/cache/example/main.dart @@ -1,6 +1,6 @@ -import 'package:angel_cache/angel_cache.dart'; -import 'package:angel_framework/angel_framework.dart'; -import 'package:angel_framework/http.dart'; +import 'package:angel3_cache/angel3_cache.dart'; +import 'package:angel3_framework/angel3_framework.dart'; +import 'package:angel3_framework/http.dart'; import 'package:glob/glob.dart'; main() async { @@ -23,8 +23,8 @@ main() async { app.addRoute('PURGE', '*', (req, res) { if (req.ip != '127.0.0.1') throw AngelHttpException.forbidden(); - cache.purge(req.uri.path); - print('Purged ${req.uri.path}'); + cache.purge(req.uri!.path); + print('Purged ${req.uri!.path}'); }); // The response finalizer that actually saves the content diff --git a/packages/cache/lib/angel_cache.dart b/packages/cache/lib/angel3_cache.dart similarity index 100% rename from packages/cache/lib/angel_cache.dart rename to packages/cache/lib/angel3_cache.dart diff --git a/packages/cache/lib/src/cache.dart b/packages/cache/lib/src/cache.dart index 059e1cb5..3bfc7865 100644 --- a/packages/cache/lib/src/cache.dart +++ b/packages/cache/lib/src/cache.dart @@ -1,6 +1,6 @@ import 'dart:async'; import 'dart:io' show HttpDate; -import 'package:angel_framework/angel_framework.dart'; +import 'package:angel3_framework/angel3_framework.dart'; import 'package:pool/pool.dart'; /// A flexible response cache for Angel. @@ -14,7 +14,7 @@ class ResponseCache { final List patterns = []; /// An optional timeout, after which a given response will be removed from the cache, and the contents refreshed. - final Duration timeout; + final Duration? timeout; final Map _cache = {}; final Map _writeLocks = {}; @@ -38,21 +38,21 @@ class ResponseCache { Future ifModifiedSince(RequestContext req, ResponseContext res) async { if (req.method != 'GET' && req.method != 'HEAD') return true; - if (req.headers.ifModifiedSince != null) { - var modifiedSince = req.headers.ifModifiedSince; + if (req.headers!.ifModifiedSince != null) { + var modifiedSince = req.headers!.ifModifiedSince; // Check if there is a cache entry. for (var pattern in patterns) { if (pattern.allMatches(_getEffectivePath(req)).isNotEmpty && _cache.containsKey(_getEffectivePath(req))) { - var response = _cache[_getEffectivePath(req)]; + var response = _cache[_getEffectivePath(req)]!; //print('timestamp ${response.timestamp} vs since ${modifiedSince}'); - if (response.timestamp.compareTo(modifiedSince) <= 0) { + if (response.timestamp.compareTo(modifiedSince!) <= 0) { if (timeout != null) { // If the cache timeout has been met, don't send the cached response. if (new DateTime.now().toUtc().difference(response.timestamp) >= - timeout) return true; + timeout!) return true; } res.statusCode = 304; @@ -66,7 +66,7 @@ class ResponseCache { } String _getEffectivePath(RequestContext req) => - ignoreQueryAndFragment == true ? req.uri.path : req.uri.toString(); + ignoreQueryAndFragment == true ? req.uri!.path : req.uri.toString(); /// Serves content from the cache, if applicable. Future handleRequest(RequestContext req, ResponseContext res) async { @@ -77,7 +77,7 @@ class ResponseCache { // Check if there is a cache entry. // // If `if-modified-since` is present, this check has already been performed. - if (req.headers.ifModifiedSince == null) { + if (req.headers!.ifModifiedSince == null) { for (var pattern in patterns) { if (pattern.allMatches(_getEffectivePath(req)).isNotEmpty) { var now = new DateTime.now().toUtc(); @@ -87,10 +87,10 @@ class ResponseCache { if (timeout != null) { // If the cache timeout has been met, don't send the cached response. - if (now.difference(response.timestamp) >= timeout) return true; + if (now.difference(response!.timestamp) >= timeout!) return true; } - _setCachedHeaders(response.timestamp, req, res); + _setCachedHeaders(response!.timestamp, req, res); res ..headers.addAll(response.headers) ..add(response.body) @@ -123,8 +123,8 @@ class ResponseCache { if (timeout == null) return true; // Otherwise, don't invalidate unless the timeout has been exceeded. - var response = _cache[_getEffectivePath(req)]; - if (now.difference(response.timestamp) < timeout) return true; + var response = _cache[_getEffectivePath(req)]!; + if (now.difference(response.timestamp) < timeout!) return true; // If the cache entry should be invalidated, then invalidate it. purge(_getEffectivePath(req)); @@ -135,7 +135,7 @@ class ResponseCache { _writeLocks.putIfAbsent(_getEffectivePath(req), () => new Pool(1)); await writeLock.withResource(() { _cache[_getEffectivePath(req)] = new _CachedResponse( - new Map.from(res.headers), res.buffer.toBytes(), now); + new Map.from(res.headers), res.buffer!.toBytes(), now); }); _setCachedHeaders(now, req, res); @@ -154,7 +154,7 @@ class ResponseCache { ..['last-modified'] = HttpDate.format(modified); if (timeout != null) { - var expiry = new DateTime.now().add(timeout); + var expiry = new DateTime.now().add(timeout!); res.headers['expires'] = HttpDate.format(expiry); } } diff --git a/packages/cache/lib/src/cache_service.dart b/packages/cache/lib/src/cache_service.dart index d86c3ca3..527f540e 100644 --- a/packages/cache/lib/src/cache_service.dart +++ b/packages/cache/lib/src/cache_service.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:collection/collection.dart'; -import 'package:angel_framework/angel_framework.dart'; -import 'package:meta/meta.dart'; +import 'package:angel3_framework/angel3_framework.dart'; /// An Angel [Service] that caches data from another service. /// @@ -21,22 +20,20 @@ class CacheService extends Service { /// If you want to return a cached result more-often-than-not, you may want to enable this. final bool ignoreParams; - final Duration timeout; + final Duration? timeout; final Map> _cache = {}; - _CachedItem> _indexed; + _CachedItem>? _indexed; CacheService( - {@required this.database, - @required this.cache, + {required this.database, + required this.cache, this.ignoreParams: false, - this.timeout}) { - assert(database != null); - } + this.timeout}) {} Future _getCached( - Map params, - _CachedItem get(), + Map? params, + _CachedItem? get(), FutureOr getFresh(), FutureOr getCached(), FutureOr save(T data, DateTime now)) async { @@ -46,7 +43,7 @@ class CacheService extends Service { if (cached != null) { // If the entry has expired, don't send from the cache var expired = - timeout != null && now.difference(cached.timestamp) >= timeout; + timeout != null && now.difference(cached.timestamp) >= timeout!; if (timeout == null || !expired) { // Read from the cache if necessary @@ -54,7 +51,7 @@ class CacheService extends Service { (params != null && cached.params != null && const MapEquality().equals( - params['query'] as Map, cached.params['query'] as Map)); + params['query'] as Map?, cached.params['query'] as Map?)); if (queryEqual) { return await getCached(); } @@ -69,7 +66,7 @@ class CacheService extends Service { } @override - Future> index([Map params]) { + Future> index([Map? params]) { return _getCached( params, () => _indexed, @@ -83,7 +80,7 @@ class CacheService extends Service { } @override - Future read(Id id, [Map params]) async { + Future read(Id id, [Map? params]) async { return _getCached( params, () => _cache[id], @@ -97,27 +94,27 @@ class CacheService extends Service { } @override - Future create(data, [Map params]) { + Future create(data, [Map? params]) { _indexed = null; return database.create(data, params); } @override - Future modify(Id id, Data data, [Map params]) { + Future modify(Id id, Data data, [Map? params]) { _indexed = null; _cache.remove(id); return database.modify(id, data, params); } @override - Future update(Id id, Data data, [Map params]) { + Future update(Id id, Data data, [Map? params]) { _indexed = null; _cache.remove(id); return database.modify(id, data, params); } @override - Future remove(Id id, [Map params]) { + Future remove(Id id, [Map? params]) { _indexed = null; _cache.remove(id); return database.remove(id, params); @@ -127,7 +124,7 @@ class CacheService extends Service { class _CachedItem { final params; final DateTime timestamp; - final Data data; + final Data? data; _CachedItem(this.params, this.timestamp, [this.data]); diff --git a/packages/cache/lib/src/serializer.dart b/packages/cache/lib/src/serializer.dart index 39d622ba..0c74fc14 100644 --- a/packages/cache/lib/src/serializer.dart +++ b/packages/cache/lib/src/serializer.dart @@ -1,5 +1,5 @@ import 'dart:async'; -import 'package:angel_framework/angel_framework.dart'; +import 'package:angel3_framework/angel3_framework.dart'; /// A middleware that enables the caching of response serialization. /// @@ -7,8 +7,8 @@ import 'package:angel_framework/angel_framework.dart'; /// /// You can pass a [shouldCache] callback to determine which values should be cached. RequestHandler cacheSerializationResults( - {Duration timeout, - FutureOr Function(RequestContext, ResponseContext, Object) + {Duration? timeout, + FutureOr Function(RequestContext, ResponseContext, Object)? shouldCache}) { return (RequestContext req, ResponseContext res) async { var oldSerializer = res.serializer; @@ -20,7 +20,7 @@ RequestHandler cacheSerializationResults( // return cache.putIfAbsent(value, () => oldSerializer(value)); //} - return oldSerializer(value); + return oldSerializer!(value); }; return true; diff --git a/packages/cache/pubspec.yaml b/packages/cache/pubspec.yaml index 19d5f5b7..0a8264eb 100644 --- a/packages/cache/pubspec.yaml +++ b/packages/cache/pubspec.yaml @@ -1,26 +1,17 @@ -name: angel_cache -version: 3.0.0 -homepage: https://github.com/angel-dart/cache -description: Support for server-side caching in Angel. -author: Tobe O -publish_to: none +name: angel3_cache +version: 4.0.0 +description: Support for server-side caching in Angel3 Framework +homepage: https://github.com/dukefirehawk/angel/tree/angel3/packages/cache environment: - sdk: ">=2.10.0 <3.0.0" + sdk: '>=2.12.0 <3.0.0' dependencies: - angel_framework: - git: - url: https://github.com/dukefirehawk/angel.git - ref: sdk-2.12.x - path: packages/framework - collection: ^1.0.0 - meta: ^1.0.0 - pool: ^1.0.0 + angel3_framework: ^4.0.0 + collection: ^1.15.0 + meta: ^1.4.0 + pool: ^1.5.0 dev_dependencies: - angel_test: - git: - url: https://github.com/dukefirehawk/angel.git - ref: sdk-2.12.x - path: packages/test - glob: ^2.0.0 - http: ^0.13.0 - test: ^1.16.5 \ No newline at end of file + angel3_test: ^4.0.0 + glob: ^2.0.1 + http: ^0.13.3 + test: ^1.17.5 + pedantic: ^1.11.0 diff --git a/packages/cache/test/cache_test.dart b/packages/cache/test/cache_test.dart index 2131bbc0..f1f02561 100644 --- a/packages/cache/test/cache_test.dart +++ b/packages/cache/test/cache_test.dart @@ -1,17 +1,17 @@ import 'dart:async'; import 'dart:io'; -import 'package:angel_cache/angel_cache.dart'; -import 'package:angel_framework/angel_framework.dart'; -import 'package:angel_test/angel_test.dart'; +import 'package:angel3_cache/angel3_cache.dart'; +import 'package:angel3_framework/angel3_framework.dart'; +import 'package:angel3_test/angel3_test.dart'; import 'package:http/http.dart' as http; import 'package:glob/glob.dart'; import 'package:test/test.dart'; main() async { group('no timeout', () { - TestClient client; - DateTime lastModified; - http.Response response1, response2; + late TestClient client; + late DateTime lastModified; + late http.Response response1, response2; setUp(() async { var app = new Angel(); @@ -29,8 +29,8 @@ main() async { }); app.addRoute('PURGE', '*', (req, res) { - cache.purge(req.uri.path); - print('Purged ${req.uri.path}'); + cache.purge(req.uri!.path); + print('Purged ${req.uri!.path}'); }); app.responseFinalizers.add(cache.responseFinalizer); @@ -38,14 +38,15 @@ main() async { var oldHandler = app.errorHandler; app.errorHandler = (e, req, res) { if (e.error == null) return oldHandler(e, req, res); - return Zone.current.handleUncaughtError(e.error, e.stackTrace); + return Zone.current + .handleUncaughtError(e.error as Object, e.stackTrace!); }; client = await connectTo(app); response1 = await client.get(Uri.parse('/date.txt')); response2 = await client.get(Uri.parse('/date.txt')); print(response2.headers); - lastModified = HttpDate.parse(response2.headers['last-modified']); + lastModified = HttpDate.parse(response2.headers['last-modified']!); print('Response 1 status: ${response1.statusCode}'); print('Response 2 status: ${response2.statusCode}'); print('Response 1 body: ${response1.body}'); diff --git a/packages/cors/AUTHORS.md b/packages/cors/AUTHORS.md new file mode 100644 index 00000000..ac95ab58 --- /dev/null +++ b/packages/cors/AUTHORS.md @@ -0,0 +1,12 @@ +Primary Authors +=============== + +* __[Thomas Hii](dukefirehawk.apps@gmail.com)__ + + Thomas is the current maintainer of the code base. He has refactored and migrated the + code base to support NNBD. + +* __[Tobe O](thosakwe@gmail.com)__ + + Tobe has written much of the original code prior to NNBD migration. He has moved on and + is no longer involved with the project. diff --git a/packages/cors/CHANGELOG.md b/packages/cors/CHANGELOG.md index 6c8e8eea..7041c586 100644 --- a/packages/cors/CHANGELOG.md +++ b/packages/cors/CHANGELOG.md @@ -1,2 +1,8 @@ +# 4.0.0 +* Migrated to support Dart SDK 2.12.x NNBD + +# 3.0.0 +* Migrated to work with Dart SDK 2.12.x Non NNBD + # 2.0.0 * Updates for Dart 2 and Angel 2. \ No newline at end of file diff --git a/packages/cors/README.md b/packages/cors/README.md index 54f71173..a553fbc5 100644 --- a/packages/cors/README.md +++ b/packages/cors/README.md @@ -1,6 +1,10 @@ -# cors -[![Pub](https://img.shields.io/pub/v/angel_cors.svg)](https://pub.dartlang.org/packages/angel_cors) -[![build status](https://travis-ci.org/angel-dart/cors.svg)](https://travis-ci.org/angel-dart/cors) +# angel3_cors +[![version](https://img.shields.io/badge/pub-v4.0.0-brightgreen)](https://pub.dartlang.org/packages/angel3_cors) +[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety) +[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion) + +[![License](https://img.shields.io/github/license/dukefirehawk/angel)](https://github.com/dukefirehawk/angel/tree/angel3/packages/cors/LICENSE) + Angel CORS middleware. Port of [the original Express CORS middleware](https://github.com/expressjs/cors). diff --git a/packages/cors/example/example.dart b/packages/cors/example/example.dart index 42b18494..ab669423 100644 --- a/packages/cors/example/example.dart +++ b/packages/cors/example/example.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:angel_cors/angel_cors.dart'; -import 'package:angel_framework/angel_framework.dart'; +import 'package:angel3_cors/angel3_cors.dart'; +import 'package:angel3_framework/angel3_framework.dart'; Future configureServer(Angel app) async { // The default options will allow CORS for any request. @@ -43,7 +43,7 @@ Future configureServer(Angel app) async { app.fallback(dynamicCors((req, res) { return CorsOptions( origin: [ - req.headers.value('origin') ?? 'https://pub.dartlang.org', + req.headers!.value('origin') ?? 'https://pub.dartlang.org', RegExp(r'\.com$'), ], ); diff --git a/packages/cors/lib/angel_cors.dart b/packages/cors/lib/angel3_cors.dart similarity index 80% rename from packages/cors/lib/angel_cors.dart rename to packages/cors/lib/angel3_cors.dart index 8d376f89..c21516cc 100644 --- a/packages/cors/lib/angel_cors.dart +++ b/packages/cors/lib/angel3_cors.dart @@ -1,16 +1,16 @@ /// Angel CORS middleware. -library angel_cors; +library angel3_cors; import 'dart:async'; -import 'package:angel_framework/angel_framework.dart'; +import 'package:angel3_framework/angel3_framework.dart'; import 'src/cors_options.dart'; export 'src/cors_options.dart'; /// Determines if a request origin is CORS-able. -typedef bool _CorsFilter(String origin); +typedef _CorsFilter = bool Function(String origin); -bool _isOriginAllowed(String origin, [allowedOrigin]) { +bool _isOriginAllowed(String? origin, [allowedOrigin]) { allowedOrigin ??= []; if (allowedOrigin is Iterable) { return allowedOrigin.any((x) => _isOriginAllowed(origin, x)); @@ -38,12 +38,12 @@ Future Function(RequestContext, ResponseContext) dynamicCors( /// Applies the given [CorsOptions]. Future Function(RequestContext, ResponseContext) cors( - [CorsOptions options]) { + [CorsOptions? options]) { options ??= CorsOptions(); return (req, res) async { // access-control-allow-credentials - if (options.credentials == true) { + if (options!.credentials == true) { res.headers['access-control-allow-credentials'] = 'true'; } @@ -51,9 +51,9 @@ Future Function(RequestContext, ResponseContext) cors( if (req.method == 'OPTIONS' && options.allowedHeaders.isNotEmpty) { res.headers['access-control-allow-headers'] = options.allowedHeaders.join(','); - } else if (req.headers['access-control-request-headers'] != null) { + } else if (req.headers!['access-control-request-headers'] != null) { res.headers['access-control-allow-headers'] = - req.headers.value('access-control-request-headers'); + req.headers!.value('access-control-request-headers')!; } // access-control-expose-headers @@ -80,11 +80,11 @@ Future Function(RequestContext, ResponseContext) cors( ..headers['access-control-allow-origin'] = options.origin as String ..headers['vary'] = 'origin'; } else { - bool isAllowed = - _isOriginAllowed(req.headers.value('origin'), options.origin); + var isAllowed = + _isOriginAllowed(req.headers!.value('origin'), options.origin); res.headers['access-control-allow-origin'] = - isAllowed ? req.headers.value('origin') : false.toString(); + isAllowed ? req.headers!.value('origin')! : false.toString(); if (isAllowed) { res.headers['vary'] = 'origin'; @@ -92,7 +92,8 @@ Future Function(RequestContext, ResponseContext) cors( } if (req.method != 'OPTIONS') return true; - res.statusCode = options.successStatus ?? 204; + //res.statusCode = options.successStatus ?? 204; + res.statusCode = options.successStatus; res.contentLength = 0; await res.close(); return options.preflightContinue; diff --git a/packages/cors/lib/src/cors_options.dart b/packages/cors/lib/src/cors_options.dart index 34f07f40..bcc22825 100644 --- a/packages/cors/lib/src/cors_options.dart +++ b/packages/cors/lib/src/cors_options.dart @@ -22,7 +22,7 @@ class CorsOptions { /// Configures the **Access-Control-Max-Age** CORS header. Set to an integer to pass the header, otherwise it is omitted. /// /// Default: `null` - final int maxAge; + final int? maxAge; /// The status code to be sent on successful `OPTIONS` requests, if [preflightContinue] is `false`. final int successStatus; @@ -50,7 +50,7 @@ class CorsOptions { CorsOptions( {Iterable allowedHeaders = const [], - this.credentials, + this.credentials = false, this.maxAge, Iterable methods = const [ 'GET', @@ -64,10 +64,10 @@ class CorsOptions { this.successStatus = 204, this.preflightContinue = false, Iterable exposedHeaders = const []}) { - if (allowedHeaders != null) this.allowedHeaders.addAll(allowedHeaders); + this.allowedHeaders.addAll(allowedHeaders); - if (methods != null) this.methods.addAll(methods); + this.methods.addAll(methods); - if (exposedHeaders != null) this.exposedHeaders.addAll(exposedHeaders); + this.exposedHeaders.addAll(exposedHeaders); } } diff --git a/packages/cors/pubspec.yaml b/packages/cors/pubspec.yaml index 2dc178cc..ebb2a3c7 100644 --- a/packages/cors/pubspec.yaml +++ b/packages/cors/pubspec.yaml @@ -1,23 +1,13 @@ -author: Tobe O +name: angel3_cors +version: 4.0.0 description: Angel CORS middleware. Port of expressjs/cors to the Angel framework. +homepage: https://github.com/dukefirehawk/angel/tree/angel3/packages/cors environment: - sdk: ">=2.10.0 <3.0.0" -homepage: https://github.com/angel-dart/cors.git -name: angel_cors -version: 3.0.0 -publish_to: none + sdk: '>=2.12.0 <3.0.0' dependencies: - angel_framework: - git: - url: https://github.com/dukefirehawk/angel.git - ref: sdk-2.12.x - path: packages/framework + angel3_framework: ^4.0.0 dev_dependencies: - angel_test: - git: - url: https://github.com/dukefirehawk/angel.git - ref: sdk-2.12.x - path: packages/test - http: ^0.13.0 + angel3_test: ^4.0.0 + http: ^0.13.3 pedantic: ^1.11.0 - test: ^1.16.5 + test: ^1.17.5 diff --git a/packages/cors/test/cors_test.dart b/packages/cors/test/cors_test.dart index e347a013..bb354a9d 100644 --- a/packages/cors/test/cors_test.dart +++ b/packages/cors/test/cors_test.dart @@ -1,13 +1,13 @@ -import 'package:angel_framework/angel_framework.dart'; -import 'package:angel_framework/http.dart'; -import 'package:angel_cors/angel_cors.dart'; +import 'package:angel3_framework/angel3_framework.dart'; +import 'package:angel3_framework/http.dart'; +import 'package:angel3_cors/angel3_cors.dart'; import 'package:http/http.dart' as http; import 'package:test/test.dart'; -main() { - Angel app; - AngelHttp server; - http.Client client; +void main() { + Angel? app; + late AngelHttp server; + http.Client? client; setUp(() async { app = Angel() @@ -24,7 +24,7 @@ main() { cors(CorsOptions( origin: ['foo.bar', 'baz.quux'], )), - (req, res) => req.headers['origin'] + (req, res) => req.headers!['origin'] ])) ..get( '/origins', @@ -32,7 +32,7 @@ main() { cors(CorsOptions( origin: 'foo.bar', )), - (req, res) => req.headers['origin'] + (req, res) => req.headers!['origin'] ])) ..get( '/originr', @@ -40,7 +40,7 @@ main() { cors(CorsOptions( origin: RegExp(r'^foo\.[^x]+$'), )), - (req, res) => req.headers['origin'] + (req, res) => req.headers!['origin'] ])) ..get( '/originp', @@ -48,7 +48,7 @@ main() { cors(CorsOptions( origin: (String s) => s.endsWith('.bar'), )), - (req, res) => req.headers['origin'] + (req, res) => req.headers!['origin'] ])) ..options('/status', cors(CorsOptions(successStatus: 418))) ..fallback(cors(CorsOptions())) @@ -57,7 +57,7 @@ main() { }) ..fallback((req, res) => throw AngelHttpException.notFound()); - server = AngelHttp(app); + server = AngelHttp(app!); await server.startServer('127.0.0.1', 0); client = http.Client(); }); @@ -70,93 +70,93 @@ main() { test('status 204 by default', () async { var rq = http.Request('OPTIONS', server.uri.replace(path: '/max_age')); - var response = await client.send(rq).then(http.Response.fromStream); + var response = await client!.send(rq).then(http.Response.fromStream); expect(response.statusCode, 204); }); test('content length 0 by default', () async { var rq = http.Request('OPTIONS', server.uri.replace(path: '/max_age')); - var response = await client.send(rq).then(http.Response.fromStream); + var response = await client!.send(rq).then(http.Response.fromStream); expect(response.contentLength, 0); }); test('custom successStatus', () async { var rq = http.Request('OPTIONS', server.uri.replace(path: '/status')); - var response = await client.send(rq).then(http.Response.fromStream); + var response = await client!.send(rq).then(http.Response.fromStream); expect(response.statusCode, 418); }); test('max age', () async { var rq = http.Request('OPTIONS', server.uri.replace(path: '/max_age')); - var response = await client.send(rq).then(http.Response.fromStream); + var response = await client!.send(rq).then(http.Response.fromStream); expect(response.headers['access-control-max-age'], '250'); }); test('methods', () async { var rq = http.Request('OPTIONS', server.uri.replace(path: '/methods')); - var response = await client.send(rq).then(http.Response.fromStream); + var response = await client!.send(rq).then(http.Response.fromStream); expect(response.headers['access-control-allow-methods'], 'GET,POST'); }); test('dynamicCors.credentials', () async { var rq = http.Request('OPTIONS', server.uri.replace(path: '/credentials_d')); - var response = await client.send(rq).then(http.Response.fromStream); + var response = await client!.send(rq).then(http.Response.fromStream); expect(response.headers['access-control-allow-credentials'], 'true'); }); test('credentials', () async { var rq = http.Request('OPTIONS', server.uri.replace(path: '/credentials')); - var response = await client.send(rq).then(http.Response.fromStream); + var response = await client!.send(rq).then(http.Response.fromStream); expect(response.headers['access-control-allow-credentials'], 'true'); }); test('exposed headers', () async { var rq = http.Request('OPTIONS', server.uri.replace(path: '/headers')); - var response = await client.send(rq).then(http.Response.fromStream); + var response = await client!.send(rq).then(http.Response.fromStream); expect(response.headers['access-control-expose-headers'], 'x-foo,x-bar'); }); test('invalid origin', () async { - var response = await client.get(server.uri.replace(path: '/originl'), + var response = await client!.get(server.uri.replace(path: '/originl'), headers: {'origin': 'foreign'}); expect(response.headers['access-control-allow-origin'], 'false'); }); test('list origin', () async { - var response = await client.get(server.uri.replace(path: '/originl'), + var response = await client!.get(server.uri.replace(path: '/originl'), headers: {'origin': 'foo.bar'}); expect(response.headers['access-control-allow-origin'], 'foo.bar'); expect(response.headers['vary'], 'origin'); - response = await client.get(server.uri.replace(path: '/originl'), + response = await client!.get(server.uri.replace(path: '/originl'), headers: {'origin': 'baz.quux'}); expect(response.headers['access-control-allow-origin'], 'baz.quux'); expect(response.headers['vary'], 'origin'); }); test('string origin', () async { - var response = await client.get(server.uri.replace(path: '/origins'), + var response = await client!.get(server.uri.replace(path: '/origins'), headers: {'origin': 'foo.bar'}); expect(response.headers['access-control-allow-origin'], 'foo.bar'); expect(response.headers['vary'], 'origin'); }); test('regex origin', () async { - var response = await client.get(server.uri.replace(path: '/originr'), + var response = await client!.get(server.uri.replace(path: '/originr'), headers: {'origin': 'foo.bar'}); expect(response.headers['access-control-allow-origin'], 'foo.bar'); expect(response.headers['vary'], 'origin'); }); test('predicate origin', () async { - var response = await client.get(server.uri.replace(path: '/originp'), + var response = await client!.get(server.uri.replace(path: '/originp'), headers: {'origin': 'foo.bar'}); expect(response.headers['access-control-allow-origin'], 'foo.bar'); expect(response.headers['vary'], 'origin'); }); test('POST works', () async { - final response = await client.post(server.uri); + final response = await client!.post(server.uri); expect(response.statusCode, equals(200)); print('Response: ${response.body}'); print('Headers: ${response.headers}'); @@ -164,7 +164,7 @@ main() { }); test('mirror headers', () async { - final response = await client + final response = await client! .post(server.uri, headers: {'access-control-request-headers': 'foo'}); expect(response.statusCode, equals(200)); print('Response: ${response.body}'); diff --git a/packages/oauth2/AUTHORS.md b/packages/oauth2/AUTHORS.md new file mode 100644 index 00000000..ac95ab58 --- /dev/null +++ b/packages/oauth2/AUTHORS.md @@ -0,0 +1,12 @@ +Primary Authors +=============== + +* __[Thomas Hii](dukefirehawk.apps@gmail.com)__ + + Thomas is the current maintainer of the code base. He has refactored and migrated the + code base to support NNBD. + +* __[Tobe O](thosakwe@gmail.com)__ + + Tobe has written much of the original code prior to NNBD migration. He has moved on and + is no longer involved with the project. diff --git a/packages/oauth2/CHANGELOG.md b/packages/oauth2/CHANGELOG.md index 5c550e2e..8e0ba186 100644 --- a/packages/oauth2/CHANGELOG.md +++ b/packages/oauth2/CHANGELOG.md @@ -1,3 +1,9 @@ +# 4.0.0 +* Migrated to support Dart SDK 2.12.x NNBD + +# 3.0.0 +* Migrated to work with Dart SDK 2.12.x Non NNBD + # 2.3.0 * Remove `implicitGrant`, and inline it into `requestAuthorizationCode`. diff --git a/packages/oauth2/README.md b/packages/oauth2/README.md index a32fb001..98c2065b 100644 --- a/packages/oauth2/README.md +++ b/packages/oauth2/README.md @@ -1,6 +1,9 @@ -# oauth2 -[![Pub](https://img.shields.io/pub/v/angel_oauth2.svg)](https://pub.dartlang.org/packages/angel_oauth2) -[![build status](https://travis-ci.org/angel-dart/oauth2.svg)](https://travis-ci.org/angel-dart/oauth2) +# angel3_oauth2 +[![version](https://img.shields.io/badge/pub-v4.0.0-brightgreen)](https://pub.dartlang.org/packages/angel3_oauth2) +[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety) +[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion) + +[![License](https://img.shields.io/github/license/dukefirehawk/angel)](https://github.com/dukefirehawk/angel/tree/angel3/packages/oauth2/LICENSE) A class containing handlers that can be used within [Angel](https://angel-dart.github.io/) to build a spec-compliant @@ -16,8 +19,8 @@ In your `pubspec.yaml`: ```yaml dependencies: - angel_framework: ^2.0.0-alpha - angel_oauth2: ^2.0.0 + angel3_framework: ^4.0.0 + angel3_oauth2: ^4.0.0 ``` # Usage @@ -28,7 +31,7 @@ Your server needs to have definitions of at least two types: Define a server class as such: ```dart -import 'package:angel_oauth2/angel_oauth2.dart' as oauth2; +import 'package:angel3_oauth2/angel3_oauth2.dart' as oauth2; class MyServer extends oauth2.AuthorizationServer {} ``` diff --git a/packages/oauth2/example/main.dart b/packages/oauth2/example/main.dart index 0da19454..071a751d 100644 --- a/packages/oauth2/example/main.dart +++ b/packages/oauth2/example/main.dart @@ -3,7 +3,7 @@ import 'dart:async'; import 'package:angel_framework/angel_framework.dart'; import 'package:angel_oauth2/angel_oauth2.dart'; -main() async { +void main() async { var app = Angel(); var oauth2 = _ExampleAuthorizationServer(); var _rgxBearer = RegExp(r'^[Bb]earer ([^\n\s]+)$'); @@ -17,7 +17,7 @@ main() async { // Assume that all other requests must be authenticated... app.fallback((req, res) { var authToken = - req.headers.value('authorization')?.replaceAll(_rgxBearer, '')?.trim(); + req.headers!.value('authorization')?.replaceAll(_rgxBearer, '').trim(); if (authToken == null) { throw AngelHttpException.forbidden(); @@ -38,13 +38,13 @@ class User {} class _ExampleAuthorizationServer extends AuthorizationServer { @override - FutureOr findClient(String clientId) { + FutureOr findClient(String? clientId) { // TODO: Add your code to find the app associated with a client ID. throw UnimplementedError(); } @override - FutureOr verifyClient(ThirdPartyApp client, String clientSecret) { + FutureOr verifyClient(ThirdPartyApp client, String? clientSecret) { // TODO: Add your code to verify a client secret, if given one. throw UnimplementedError(); } @@ -52,7 +52,7 @@ class _ExampleAuthorizationServer @override FutureOr requestAuthorizationCode( ThirdPartyApp client, - String redirectUri, + String? redirectUri, Iterable scopes, String state, RequestContext req, @@ -64,9 +64,9 @@ class _ExampleAuthorizationServer @override FutureOr exchangeAuthorizationCodeForToken( - ThirdPartyApp client, - String authCode, - String redirectUri, + ThirdPartyApp? client, + String? authCode, + String? redirectUri, RequestContext req, ResponseContext res) { // TODO: Here, you'll convert the auth code into a full-fledged token. diff --git a/packages/oauth2/lib/angel_oauth2.dart b/packages/oauth2/lib/angel3_oauth2.dart similarity index 100% rename from packages/oauth2/lib/angel_oauth2.dart rename to packages/oauth2/lib/angel3_oauth2.dart diff --git a/packages/oauth2/lib/src/exception.dart b/packages/oauth2/lib/src/exception.dart index 0264bd92..061c90b4 100644 --- a/packages/oauth2/lib/src/exception.dart +++ b/packages/oauth2/lib/src/exception.dart @@ -1,11 +1,11 @@ -import 'package:angel_http_exception/angel_http_exception.dart'; +import 'package:angel3_http_exception/angel3_http_exception.dart'; /// An Angel-friendly wrapper around OAuth2 [ErrorResponse] instances. class AuthorizationException extends AngelHttpException { final ErrorResponse errorResponse; AuthorizationException(this.errorResponse, - {StackTrace stackTrace, int statusCode, error}) + {StackTrace? stackTrace, int? statusCode, error}) : super(error ?? errorResponse, stackTrace: stackTrace, message: '', statusCode: statusCode ?? 400); @@ -16,8 +16,9 @@ class AuthorizationException extends AngelHttpException { 'error_description': errorResponse.description, }; - if (errorResponse.uri != null) + if (errorResponse.uri != null) { m['error_uri'] = errorResponse.uri.toString(); + } return m; } @@ -78,10 +79,10 @@ class ErrorResponse { final String description; /// An optional [Uri] directing users to more information about the error. - final Uri uri; + final Uri? uri; /// The exact value received from the client, if a "state" parameter was present in the client authorization request. - final String state; + final String? state; const ErrorResponse(this.code, this.description, this.state, {this.uri}); diff --git a/packages/oauth2/lib/src/pkce.dart b/packages/oauth2/lib/src/pkce.dart index 713bda83..8f55d8fa 100644 --- a/packages/oauth2/lib/src/pkce.dart +++ b/packages/oauth2/lib/src/pkce.dart @@ -9,7 +9,7 @@ class Pkce { final String codeChallengeMethod; /// The proof key that is used to secure public clients. - final String codeChallenge; + final String? codeChallenge; Pkce(this.codeChallengeMethod, this.codeChallenge) { assert(codeChallengeMethod == 'plain' || codeChallengeMethod == 's256', @@ -17,7 +17,7 @@ class Pkce { } /// Attempts to parse a [codeChallenge] and [codeChallengeMethod] from a [Map]. - factory Pkce.fromJson(Map data, {String state, Uri uri}) { + factory Pkce.fromJson(Map data, {String? state, Uri? uri}) { var codeChallenge = data['code_challenge']?.toString(); var codeChallengeMethod = data['code_challenge_method']?.toString() ?? 'plain'; @@ -44,7 +44,7 @@ class Pkce { bool get isS256 => codeChallengeMethod == 's256'; /// Determines if a given [codeVerifier] is valid. - void validate(String codeVerifier, {String state, Uri uri}) { + void validate(String codeVerifier, {String? state, Uri? uri}) { String foreignChallenge; if (isS256) { @@ -57,7 +57,7 @@ class Pkce { if (foreignChallenge != codeChallenge) { throw AuthorizationException( ErrorResponse(ErrorResponse.invalidGrant, - "The given `code_verifier` parameter is invalid.", state, + 'The given `code_verifier` parameter is invalid.', state, uri: uri), ); } diff --git a/packages/oauth2/lib/src/response.dart b/packages/oauth2/lib/src/response.dart index aacf5dd3..444c0254 100644 --- a/packages/oauth2/lib/src/response.dart +++ b/packages/oauth2/lib/src/response.dart @@ -4,13 +4,13 @@ class AuthorizationTokenResponse { final String accessToken; /// An optional key that can be used to refresh the [accessToken] past its expiration. - final String refreshToken; + final String? refreshToken; /// An optional, but recommended integer that signifies the time left until the [accessToken] expires. - final int expiresIn; + final int? expiresIn; /// Optional, if identical to the scope requested by the client; otherwise, required. - final Iterable scope; + final Iterable? scope; const AuthorizationTokenResponse(this.accessToken, {this.refreshToken, this.expiresIn, this.scope}); @@ -19,7 +19,7 @@ class AuthorizationTokenResponse { var map = {'access_token': accessToken}; if (refreshToken?.isNotEmpty == true) map['refresh_token'] = refreshToken; if (expiresIn != null) map['expires_in'] = expiresIn; - if (scope != null) map['scope'] = scope.toList(); + if (scope != null) map['scope'] = scope!.toList(); return map; } } @@ -40,12 +40,12 @@ class DeviceCodeResponse { /// OPTIONAL. A verification URI that includes the [userCode] (or /// other information with the same function as the [userCode]), /// designed for non-textual transmission. - final Uri verificationUriComplete; + final Uri? verificationUriComplete; /// OPTIONAL. The minimum amount of time in seconds that the client /// SHOULD wait between polling requests to the token endpoint. If no /// value is provided, clients MUST use 5 as the default. - final int interval; + final int? interval; /// The lifetime, in *seconds* of the [deviceCode] and [userCode]. final int expiresIn; diff --git a/packages/oauth2/lib/src/server.dart b/packages/oauth2/lib/src/server.dart index 3a103ec7..f4e7cfda 100644 --- a/packages/oauth2/lib/src/server.dart +++ b/packages/oauth2/lib/src/server.dart @@ -1,16 +1,16 @@ import 'dart:async'; import 'dart:convert'; -import 'package:angel_framework/angel_framework.dart'; +import 'package:angel3_framework/angel3_framework.dart'; import 'exception.dart'; import 'pkce.dart'; import 'response.dart'; import 'token_type.dart'; /// A request handler that performs an arbitrary authorization token grant. -typedef FutureOr ExtensionGrant( +typedef ExtensionGrant = FutureOr Function( RequestContext req, ResponseContext res); -Future _getParam(RequestContext req, String name, String state, +Future _getParam(RequestContext req, String name, String state, {bool body = false, bool throwIfEmpty = true}) async { Map data; @@ -46,7 +46,7 @@ Future> _getScopes(RequestContext req, data = req.queryParameters; } - return data['scope']?.toString()?.split(' ') ?? []; + return data['scope']?.toString().split(' ') ?? []; } /// An OAuth2 authorization server, which issues access tokens to third parties. @@ -60,14 +60,14 @@ abstract class AuthorizationServer { Map get extensionGrants => {}; /// Finds the [Client] application associated with the given [clientId]. - FutureOr findClient(String clientId); + FutureOr? findClient(String? clientId); /// Verify that a [client] is the one identified by the [clientSecret]. - FutureOr verifyClient(Client client, String clientSecret); + FutureOr verifyClient(Client client, String? clientSecret); /// Retrieves the PKCE `code_verifier` parameter from a [RequestContext], or throws. Future getPkceCodeVerifier(RequestContext req, - {bool body = true, String state, Uri uri}) async { + {bool body = true, String? state, Uri? uri}) async { var data = body ? await req.parseBody().then((_) => req.bodyAsMap) : req.queryParameters; @@ -75,14 +75,14 @@ abstract class AuthorizationServer { if (codeVerifier == null) { throw AuthorizationException(ErrorResponse(ErrorResponse.invalidRequest, - "Missing `code_verifier` parameter.", state, + 'Missing `code_verifier` parameter.', state, uri: uri)); } else if (codeVerifier is! String) { throw AuthorizationException(ErrorResponse(ErrorResponse.invalidRequest, - "The `code_verifier` parameter must be a string.", state, + 'The `code_verifier` parameter must be a string.', state, uri: uri)); } else { - return codeVerifier as String; + return codeVerifier; } } @@ -95,7 +95,7 @@ abstract class AuthorizationServer { /// the same. FutureOr requestAuthorizationCode( Client client, - String redirectUri, + String? redirectUri, Iterable scopes, String state, RequestContext req, @@ -113,16 +113,16 @@ abstract class AuthorizationServer { /// Exchanges an authorization code for an authorization token. FutureOr exchangeAuthorizationCodeForToken( - Client client, - String authCode, - String redirectUri, + Client? client, + String? authCode, + String? redirectUri, RequestContext req, ResponseContext res) { throw AuthorizationException( ErrorResponse( ErrorResponse.unsupportedResponseType, 'Authorization code grants are not supported.', - req.uri.queryParameters['state'] ?? '', + req.uri!.queryParameters['state'] ?? '', ), statusCode: 400, ); @@ -130,8 +130,8 @@ abstract class AuthorizationServer { /// Refresh an authorization token. FutureOr refreshAuthorizationToken( - Client client, - String refreshToken, + Client? client, + String? refreshToken, Iterable scopes, RequestContext req, ResponseContext res) async { @@ -148,9 +148,9 @@ abstract class AuthorizationServer { /// Issue an authorization token to a user after authenticating them via [username] and [password]. FutureOr resourceOwnerPasswordCredentialsGrant( - Client client, - String username, - String password, + Client? client, + String? username, + String? password, Iterable scopes, RequestContext req, ResponseContext res) async { @@ -167,7 +167,7 @@ abstract class AuthorizationServer { /// Performs a client credentials grant. Only use this in situations where the client is 100% trusted. FutureOr clientCredentialsGrant( - Client client, RequestContext req, ResponseContext res) async { + Client? client, RequestContext req, ResponseContext res) async { var body = await req.parseBody().then((_) => req.bodyAsMap); throw AuthorizationException( ErrorResponse( @@ -196,7 +196,7 @@ abstract class AuthorizationServer { /// Produces an authorization token from a given device code. FutureOr exchangeDeviceCodeForToken( Client client, - String deviceCode, + String? deviceCode, String state, RequestContext req, ResponseContext res) async { @@ -213,7 +213,7 @@ abstract class AuthorizationServer { /// Returns the [Uri] that a client can be redirected to in the case of an implicit grant. Uri completeImplicitGrant(AuthorizationTokenResponse token, Uri redirectUri, - {String state}) { + {String? state}) { var queryParameters = {}; queryParameters.addAll({ @@ -223,17 +223,18 @@ abstract class AuthorizationServer { if (state != null) queryParameters['state'] = state; - if (token.expiresIn != null) + if (token.expiresIn != null) { queryParameters['expires_in'] = token.expiresIn.toString(); + } - if (token.scope != null) queryParameters['scope'] = token.scope.join(' '); + if (token.scope != null) queryParameters['scope'] = token.scope!.join(' '); var fragment = queryParameters.keys.fold(StringBuffer(), (buf, k) { if (buf.isNotEmpty) buf.write('&'); return buf ..write( - '$k=' + Uri.encodeComponent(queryParameters[k]), + '$k=' + Uri.encodeComponent(queryParameters[k]!), ); }).toString(); @@ -244,14 +245,14 @@ abstract class AuthorizationServer { /// of grant the client is requesting. Future authorizationEndpoint( RequestContext req, ResponseContext res) async { - String state = ''; + var state = ''; try { var query = req.queryParameters; state = query['state']?.toString() ?? ''; var responseType = await _getParam(req, 'response_type', state); - req.container.registerLazySingleton((_) { + req.container!.registerLazySingleton((_) { return Pkce.fromJson(req.queryParameters, state: state); }); @@ -260,7 +261,7 @@ abstract class AuthorizationServer { var clientId = await _getParam(req, 'client_id', state); // Find client - var client = await findClient(clientId); + var client = await findClient(clientId)!; if (client == null) { throw AuthorizationException(ErrorResponse( @@ -309,16 +310,16 @@ abstract class AuthorizationServer { /// A request handler that either exchanges authorization codes for authorization tokens, /// or refreshes authorization tokens. Future tokenEndpoint(RequestContext req, ResponseContext res) async { - String state = ''; - Client client; + var state = ''; + Client? client; try { - AuthorizationTokenResponse response; + AuthorizationTokenResponse? response; var body = await req.parseBody().then((_) => req.bodyAsMap); state = body['state']?.toString() ?? ''; - req.container.registerLazySingleton((_) { + req.container!.registerLazySingleton((_) { return Pkce.fromJson(req.bodyAsMap, state: state); }); @@ -328,11 +329,11 @@ abstract class AuthorizationServer { if (grantType != 'urn:ietf:params:oauth:grant-type:device_code' && grantType != null) { var match = - _rgxBasic.firstMatch(req.headers.value('authorization') ?? ''); + _rgxBasic.firstMatch(req.headers!.value('authorization') ?? ''); if (match != null) { match = _rgxBasicAuth - .firstMatch(String.fromCharCodes(base64Url.decode(match[1]))); + .firstMatch(String.fromCharCodes(base64Url.decode(match[1]!))); } if (match == null) { @@ -402,7 +403,7 @@ abstract class AuthorizationServer { ); } } else if (extensionGrants.containsKey(grantType)) { - response = await extensionGrants[grantType](req, res); + response = await extensionGrants[grantType!]!(req, res); } else if (grantType == null) { // This is a device code grant. var clientId = await _getParam(req, 'client_id', state, body: true); diff --git a/packages/oauth2/pubspec.yaml b/packages/oauth2/pubspec.yaml index 519fae2b..49d04691 100644 --- a/packages/oauth2/pubspec.yaml +++ b/packages/oauth2/pubspec.yaml @@ -1,23 +1,19 @@ -name: angel_oauth2 -author: Tobe O +name: angel3_oauth2 +version: 4.0.0 description: A class containing handlers that can be used within Angel to build a spec-compliant OAuth 2.0 server. -homepage: https://github.com/angel-dart/oauth2.git -version: 2.3.0 +homepage: https://github.com/dukefirehawk/angel/tree/angel3/packages/oauth2 environment: - sdk: ">=2.10.0 <2.12.0" + sdk: '>=2.12.0 <3.0.0' dependencies: - angel_framework: #^2.0.0-rc.0 - path: ../framework - angel_http_exception: #^1.0.0 - path: ../http_exception - crypto: ^2.0.0 + angel3_framework: ^4.0.0 + angel3_http_exception: ^3.0.0 + crypto: ^3.0.1 + collection: ^1.15.0-nullsafety.4 dev_dependencies: - angel_validate: #^2.0.0-alpha - path: ../validate - angel_test: #^2.0.0-alpha - path: ../test - logging: - oauth2: ^1.0.0 - pedantic: ^1.0.0 - test: ^1.15.7 - uuid: ^2.0.0 + angel3_validate: ^4.0.0 + angel3_test: ^4.0.0 + logging: ^1.0.1 + oauth2: ^2.0.0 + pedantic: ^1.11.0 + test: ^1.17.5 + uuid: ^3.0.4 diff --git a/packages/oauth2/test/auth_code_test.dart b/packages/oauth2/test/auth_code_test.dart index 043305c3..23261287 100644 --- a/packages/oauth2/test/auth_code_test.dart +++ b/packages/oauth2/test/auth_code_test.dart @@ -1,25 +1,25 @@ import 'dart:async'; import 'dart:collection'; import 'dart:convert'; -import 'package:angel_framework/angel_framework.dart'; -import 'package:angel_framework/http.dart'; -import 'package:angel_oauth2/angel_oauth2.dart'; -import 'package:angel_test/angel_test.dart'; +import 'package:angel3_framework/angel3_framework.dart'; +import 'package:angel3_framework/http.dart'; +import 'package:angel3_oauth2/angel3_oauth2.dart'; +import 'package:angel3_test/angel3_test.dart'; import 'package:logging/logging.dart'; import 'package:oauth2/oauth2.dart' as oauth2; import 'package:test/test.dart'; import 'package:uuid/uuid.dart'; import 'common.dart'; -main() { +void main() { Angel app; - Uri authorizationEndpoint, tokenEndpoint, redirectUri; - TestClient testClient; + late Uri authorizationEndpoint, tokenEndpoint, redirectUri; + late TestClient testClient; setUp(() async { app = Angel(); app.configuration['properties'] = app.configuration; - app.container.registerSingleton(AuthCodes()); + app.container!.registerSingleton(AuthCodes()); var server = _Server(); @@ -62,7 +62,7 @@ main() { test('show authorization form', () async { var grant = createGrant(); var url = grant.getAuthorizationUrl(redirectUri, state: 'hello'); - var response = await testClient.client.get(url); + var response = await testClient.client!.get(url); print('Body: ${response.body}'); expect( response.body, @@ -73,7 +73,7 @@ main() { test('preserves state', () async { var grant = createGrant(); var url = grant.getAuthorizationUrl(redirectUri, state: 'goodbye'); - var response = await testClient.client.get(url); + var response = await testClient.client!.get(url); print('Body: ${response.body}'); expect(json.decode(response.body)['state'], 'goodbye'); }); @@ -81,7 +81,7 @@ main() { test('sends auth code', () async { var grant = createGrant(); var url = grant.getAuthorizationUrl(redirectUri); - var response = await testClient.client.get(url); + var response = await testClient.client!.get(url); print('Body: ${response.body}'); expect( json.decode(response.body), @@ -95,7 +95,7 @@ main() { test('exchange code for token', () async { var grant = createGrant(); var url = grant.getAuthorizationUrl(redirectUri); - var response = await testClient.client.get(url); + var response = await testClient.client!.get(url); print('Body: ${response.body}'); var authCode = json.decode(response.body)['code'].toString(); @@ -106,7 +106,7 @@ main() { test('can send refresh token', () async { var grant = createGrant(); var url = grant.getAuthorizationUrl(redirectUri, state: 'can_refresh'); - var response = await testClient.client.get(url); + var response = await testClient.client!.get(url); print('Body: ${response.body}'); var authCode = json.decode(response.body)['code'].toString(); @@ -122,20 +122,20 @@ class _Server extends AuthorizationServer { final Uuid _uuid = Uuid(); @override - FutureOr findClient(String clientId) { + FutureOr? findClient(String? clientId) { return clientId == pseudoApplication.id ? pseudoApplication : null; } @override Future verifyClient( - PseudoApplication client, String clientSecret) async { + PseudoApplication client, String? clientSecret) async { return client.secret == clientSecret; } @override Future requestAuthorizationCode( PseudoApplication client, - String redirectUri, + String? redirectUri, Iterable scopes, String state, RequestContext req, @@ -147,28 +147,29 @@ class _Server extends AuthorizationServer { client, redirectUri, scopes, state, req, res, implicit); } - if (state == 'hello') + if (state == 'hello') { return 'Hello ${pseudoApplication.id}:${pseudoApplication.secret}'; + } var authCode = _uuid.v4(); - var authCodes = req.container.make(); + var authCodes = req.container!.make()!; authCodes[authCode] = state; res.headers['content-type'] = 'application/json'; var result = {'code': authCode}; - if (state?.isNotEmpty == true) result['state'] = state; + if (state.isNotEmpty == true) result['state'] = state; return result; } @override Future exchangeAuthorizationCodeForToken( - PseudoApplication client, - String authCode, - String redirectUri, + PseudoApplication? client, + String? authCode, + String? redirectUri, RequestContext req, ResponseContext res) async { - var authCodes = req.container.make(); - var state = authCodes[authCode]; + var authCodes = req.container!.make()!; + var state = authCodes[authCode!]; var refreshToken = state == 'can_refresh' ? '${authCode}_refresh' : null; return AuthorizationTokenResponse('${authCode}_access', refreshToken: refreshToken); @@ -179,7 +180,7 @@ class AuthCodes extends MapBase with MapMixin { var inner = {}; @override - String operator [](Object key) => inner[key]; + String? operator [](Object? key) => inner[key as String]; @override void operator []=(String key, String value) => inner[key] = value; @@ -191,5 +192,5 @@ class AuthCodes extends MapBase with MapMixin { Iterable get keys => inner.keys; @override - String remove(Object key) => inner.remove(key); + String? remove(Object? key) => inner.remove(key); } diff --git a/packages/oauth2/test/client_credentials_test.dart b/packages/oauth2/test/client_credentials_test.dart index b5693d54..da2bec66 100644 --- a/packages/oauth2/test/client_credentials_test.dart +++ b/packages/oauth2/test/client_credentials_test.dart @@ -1,13 +1,13 @@ import 'dart:async'; import 'dart:convert'; -import 'package:angel_framework/angel_framework.dart'; -import 'package:angel_test/angel_test.dart'; -import 'package:angel_oauth2/angel_oauth2.dart'; +import 'package:angel3_framework/angel3_framework.dart'; +import 'package:angel3_test/angel3_test.dart'; +import 'package:angel3_oauth2/angel3_oauth2.dart'; import 'package:test/test.dart'; import 'common.dart'; void main() { - TestClient client; + late TestClient client; setUp(() async { var app = Angel(); @@ -30,7 +30,7 @@ void main() { test('authenticate via client credentials', () async { var response = await client.post( - '/oauth2/token', + Uri.parse('oauth2/token'), headers: { 'Authorization': 'Basic ' + base64Url.encode('foo:bar'.codeUnits), }, @@ -58,7 +58,7 @@ void main() { test('force correct id', () async { var response = await client.post( - '/oauth2/token', + Uri.parse('/oauth2/token'), headers: { 'Authorization': 'Basic ' + base64Url.encode('fooa:bar'.codeUnits), }, @@ -73,7 +73,7 @@ void main() { test('force correct secret', () async { var response = await client.post( - '/oauth2/token', + Uri.parse('/oauth2/token'), headers: { 'Authorization': 'Basic ' + base64Url.encode('foo:bara'.codeUnits), }, @@ -90,19 +90,21 @@ void main() { class _AuthorizationServer extends AuthorizationServer { @override - PseudoApplication findClient(String clientId) { + PseudoApplication? findClient(String? clientId) { return clientId == pseudoApplication.id ? pseudoApplication : null; } @override Future verifyClient( - PseudoApplication client, String clientSecret) async { + PseudoApplication client, String? clientSecret) async { return client.secret == clientSecret; } @override Future clientCredentialsGrant( - PseudoApplication client, RequestContext req, ResponseContext res) async { + PseudoApplication? client, + RequestContext req, + ResponseContext res) async { return AuthorizationTokenResponse('foo'); } } diff --git a/packages/oauth2/test/common.dart b/packages/oauth2/test/common.dart index ba248d68..6a51e6c9 100644 --- a/packages/oauth2/test/common.dart +++ b/packages/oauth2/test/common.dart @@ -14,7 +14,7 @@ const List pseudoUsers = [ ]; class PseudoUser { - final String username, password; + final String? username, password; const PseudoUser({this.username, this.password}); } diff --git a/packages/oauth2/test/device_code_test.dart b/packages/oauth2/test/device_code_test.dart index d327fbff..59a71b82 100644 --- a/packages/oauth2/test/device_code_test.dart +++ b/packages/oauth2/test/device_code_test.dart @@ -1,14 +1,14 @@ import 'dart:async'; -import 'package:angel_framework/angel_framework.dart'; -import 'package:angel_test/angel_test.dart'; -import 'package:angel_oauth2/angel_oauth2.dart'; -import 'package:angel_validate/angel_validate.dart'; +import 'package:angel3_framework/angel3_framework.dart'; +import 'package:angel3_test/angel3_test.dart'; +import 'package:angel3_oauth2/angel3_oauth2.dart'; +import 'package:angel3_validate/angel3_validate.dart'; import 'package:logging/logging.dart'; import 'package:test/test.dart'; import 'common.dart'; -main() { - TestClient client; +void main() { + late TestClient client; setUp(() async { var app = Angel(); @@ -38,7 +38,7 @@ main() { group('get initial code', () { test('invalid client id', () async { - var response = await client.post('/oauth2/token', body: { + var response = await client.post(Uri.parse('/oauth2/token'), body: { 'client_id': 'barr', }); print(response.body); @@ -46,7 +46,7 @@ main() { }); test('valid client id, no scopes', () async { - var response = await client.post('/oauth2/token', body: { + var response = await client.post(Uri.parse('/oauth2/token'), body: { 'client_id': 'foo', }); print(response.body); @@ -55,16 +55,16 @@ main() { allOf( hasStatus(200), isJson({ - "device_code": "foo", - "user_code": "bar", - "verification_uri": "https://regiostech.com?scopes", - "expires_in": 3600 + 'device_code': 'foo', + 'user_code': 'bar', + 'verification_uri': 'https://regiostech.com?scopes', + 'expires_in': 3600 }), )); }); test('valid client id, with scopes', () async { - var response = await client.post('/oauth2/token', body: { + var response = await client.post(Uri.parse('/oauth2/token'), body: { 'client_id': 'foo', 'scope': 'bar baz quux', }); @@ -74,11 +74,11 @@ main() { allOf( hasStatus(200), isJson({ - "device_code": "foo", - "user_code": "bar", - "verification_uri": Uri.parse("https://regiostech.com").replace( + 'device_code': 'foo', + 'user_code': 'bar', + 'verification_uri': Uri.parse('https://regiostech.com').replace( queryParameters: {'scopes': 'bar,baz,quux'}).toString(), - "expires_in": 3600 + 'expires_in': 3600 }), )); }); @@ -86,7 +86,7 @@ main() { group('get token', () { test('valid device code + timing', () async { - var response = await client.post('/oauth2/token', body: { + var response = await client.post(Uri.parse('/oauth2/token'), body: { 'grant_type': 'urn:ietf:params:oauth:grant-type:device_code', 'client_id': 'foo', 'device_code': 'bar', @@ -97,7 +97,7 @@ main() { response, allOf( hasStatus(200), - isJson({"token_type": "bearer", "access_token": "foo"}), + isJson({'token_type': 'bearer', 'access_token': 'foo'}), )); }); @@ -108,7 +108,7 @@ main() { // The logic for throwing errors and turning them into responses // has already been tested. test('failure', () async { - var response = await client.post('/oauth2/token', body: { + var response = await client.post(Uri.parse('/oauth2/token'), body: { 'grant_type': 'urn:ietf:params:oauth:grant-type:device_code', 'client_id': 'foo', 'device_code': 'brute', @@ -120,9 +120,9 @@ main() { allOf( hasStatus(400), isJson({ - "error": "slow_down", - "error_description": - "Ho, brother! Ho, whoa, whoa, whoa now! You got too much dip on your chip!" + 'error': 'slow_down', + 'error_description': + 'Ho, brother! Ho, whoa, whoa, whoa now! You got too much dip on your chip!' }), )); }); @@ -132,13 +132,13 @@ main() { class _AuthorizationServer extends AuthorizationServer { @override - PseudoApplication findClient(String clientId) { + PseudoApplication? findClient(String? clientId) { return clientId == pseudoApplication.id ? pseudoApplication : null; } @override Future verifyClient( - PseudoApplication client, String clientSecret) async { + PseudoApplication client, String? clientSecret) async { return client.secret == clientSecret; } @@ -156,14 +156,14 @@ class _AuthorizationServer @override FutureOr exchangeDeviceCodeForToken( PseudoApplication client, - String deviceCode, + String? deviceCode, String state, RequestContext req, ResponseContext res) { if (deviceCode == 'brute') { throw AuthorizationException(ErrorResponse( ErrorResponse.slowDown, - "Ho, brother! Ho, whoa, whoa, whoa now! You got too much dip on your chip!", + 'Ho, brother! Ho, whoa, whoa, whoa now! You got too much dip on your chip!', state)); } diff --git a/packages/oauth2/test/implicit_grant_test.dart b/packages/oauth2/test/implicit_grant_test.dart index c1dba844..4f7ff798 100644 --- a/packages/oauth2/test/implicit_grant_test.dart +++ b/packages/oauth2/test/implicit_grant_test.dart @@ -1,13 +1,13 @@ import 'dart:async'; -import 'package:angel_framework/angel_framework.dart'; -import 'package:angel_test/angel_test.dart'; -import 'package:angel_oauth2/angel_oauth2.dart'; -import 'package:angel_validate/angel_validate.dart'; +import 'package:angel3_framework/angel3_framework.dart'; +import 'package:angel3_test/angel3_test.dart'; +import 'package:angel3_oauth2/angel3_oauth2.dart'; +import 'package:angel3_validate/angel3_validate.dart'; import 'package:test/test.dart'; import 'common.dart'; -main() { - TestClient client; +void main() { + late TestClient client; setUp(() async { var app = Angel(); @@ -30,7 +30,8 @@ main() { test('authenticate via implicit grant', () async { var response = await client.get( - '/oauth2/authorize?response_type=token&client_id=foo&redirect_uri=http://foo.com&state=bar', + Uri.parse( + '/oauth2/authorize?response_type=token&client_id=foo&redirect_uri=http://foo.com&state=bar'), ); print('Headers: ${response.headers}'); @@ -47,27 +48,27 @@ main() { class _AuthorizationServer extends AuthorizationServer { @override - PseudoApplication findClient(String clientId) { + PseudoApplication? findClient(String? clientId) { return clientId == pseudoApplication.id ? pseudoApplication : null; } @override Future verifyClient( - PseudoApplication client, String clientSecret) async { + PseudoApplication client, String? clientSecret) async { return client.secret == clientSecret; } @override Future requestAuthorizationCode( PseudoApplication client, - String redirectUri, + String? redirectUri, Iterable scopes, String state, RequestContext req, ResponseContext res, bool implicit) async { var tok = AuthorizationTokenResponse('foo'); - var uri = completeImplicitGrant(tok, Uri.parse(redirectUri), state: state); + var uri = completeImplicitGrant(tok, Uri.parse(redirectUri!), state: state); return res.redirect(uri); } } diff --git a/packages/oauth2/test/password_test.dart b/packages/oauth2/test/password_test.dart index 0dae0a84..09c53d8d 100644 --- a/packages/oauth2/test/password_test.dart +++ b/packages/oauth2/test/password_test.dart @@ -1,15 +1,16 @@ import 'dart:async'; -import 'package:angel_framework/angel_framework.dart'; -import 'package:angel_framework/http.dart'; -import 'package:angel_oauth2/angel_oauth2.dart'; +import 'package:angel3_framework/angel3_framework.dart'; +import 'package:angel3_framework/http.dart'; +import 'package:angel3_oauth2/angel3_oauth2.dart'; +import 'package:collection/collection.dart' show IterableExtension; import 'package:logging/logging.dart'; import 'package:oauth2/oauth2.dart' as oauth2; import 'package:test/test.dart'; import 'common.dart'; -main() { - Angel app; - Uri tokenEndpoint; +void main() { + late Angel app; + late Uri tokenEndpoint; setUp(() async { app = Angel(); @@ -50,7 +51,7 @@ main() { }); test('force correct username+password', () async { - oauth2.Client client; + oauth2.Client? client; try { client = await oauth2.resourceOwnerPasswordGrant( @@ -88,20 +89,20 @@ main() { class _AuthorizationServer extends AuthorizationServer { @override - PseudoApplication findClient(String clientId) { + PseudoApplication? findClient(String? clientId) { return clientId == pseudoApplication.id ? pseudoApplication : null; } @override Future verifyClient( - PseudoApplication client, String clientSecret) async { + PseudoApplication client, String? clientSecret) async { return client.secret == clientSecret; } @override Future refreshAuthorizationToken( - PseudoApplication client, - String refreshToken, + PseudoApplication? client, + String? refreshToken, Iterable scopes, RequestContext req, ResponseContext res) async { @@ -110,15 +111,14 @@ class _AuthorizationServer @override Future resourceOwnerPasswordCredentialsGrant( - PseudoApplication client, - String username, - String password, + PseudoApplication? client, + String? username, + String? password, Iterable scopes, RequestContext req, ResponseContext res) async { - var user = pseudoUsers.firstWhere( - (u) => u.username == username && u.password == password, - orElse: () => null); + var user = pseudoUsers.firstWhereOrNull( + (u) => u.username == username && u.password == password); if (user == null) { var body = await req.parseBody().then((_) => req.bodyAsMap); diff --git a/packages/oauth2/test/pkce_test.dart b/packages/oauth2/test/pkce_test.dart index 53426bfb..806ef0a1 100644 --- a/packages/oauth2/test/pkce_test.dart +++ b/packages/oauth2/test/pkce_test.dart @@ -1,21 +1,21 @@ import 'dart:async'; import 'dart:collection'; -import 'package:angel_framework/angel_framework.dart'; -import 'package:angel_framework/http.dart'; -import 'package:angel_oauth2/angel_oauth2.dart'; -import 'package:angel_test/angel_test.dart'; +import 'package:angel3_framework/angel3_framework.dart'; +import 'package:angel3_framework/http.dart'; +import 'package:angel3_oauth2/angel3_oauth2.dart'; +import 'package:angel3_test/angel3_test.dart'; import 'package:logging/logging.dart'; import 'package:test/test.dart'; import 'common.dart'; -main() { +void main() { Angel app; - Uri authorizationEndpoint, tokenEndpoint; - TestClient testClient; + late Uri authorizationEndpoint, tokenEndpoint; + late TestClient testClient; setUp(() async { app = Angel(); - app.container.registerSingleton(AuthCodes()); + app.container!.registerSingleton(AuthCodes()); var server = _Server(); @@ -53,14 +53,14 @@ main() { 'redirect_uri': 'https://freddie.mercu.ry', 'code_challenge': 'foo', }); - var response = await testClient - .get(url.toString(), headers: {'accept': 'application/json'}); + var response = + await testClient.get(url, headers: {'accept': 'application/json'}); print(response.body); expect( response, allOf( hasStatus(200), - isJson({"code": "ok"}), + isJson({'code': 'ok'}), )); }); @@ -72,14 +72,14 @@ main() { 'code_challenge': 'foo', 'code_challenge_method': 'plain', }); - var response = await testClient - .get(url.toString(), headers: {'accept': 'application/json'}); + var response = + await testClient.get(url, headers: {'accept': 'application/json'}); print(response.body); expect( response, allOf( hasStatus(200), - isJson({"code": "ok"}), + isJson({'code': 'ok'}), )); }); @@ -91,14 +91,14 @@ main() { 'code_challenge': 'foo', 'code_challenge_method': 's256', }); - var response = await testClient - .get(url.toString(), headers: {'accept': 'application/json'}); + var response = + await testClient.get(url, headers: {'accept': 'application/json'}); print(response.body); expect( response, allOf( hasStatus(200), - isJson({"code": "ok"}), + isJson({'code': 'ok'}), )); }); @@ -110,16 +110,16 @@ main() { 'code_challenge': 'foo', 'code_challenge_method': 'bar', }); - var response = await testClient - .get(url.toString(), headers: {'accept': 'application/json'}); + var response = + await testClient.get(url, headers: {'accept': 'application/json'}); print(response.body); expect( response, allOf( hasStatus(400), isJson({ - "error": "invalid_request", - "error_description": + 'error': 'invalid_request', + 'error_description': "The `code_challenge_method` parameter must be either 'plain' or 's256'." }), )); @@ -131,16 +131,16 @@ main() { 'client_id': 'freddie mercury', 'redirect_uri': 'https://freddie.mercu.ry' }); - var response = await testClient - .get(url.toString(), headers: {'accept': 'application/json'}); + var response = + await testClient.get(url, headers: {'accept': 'application/json'}); print(response.body); expect( response, allOf( hasStatus(400), isJson({ - "error": "invalid_request", - "error_description": "Missing `code_challenge` parameter." + 'error': 'invalid_request', + 'error_description': 'Missing `code_challenge` parameter.' }), )); }); @@ -150,7 +150,7 @@ main() { test('with correct verifier', () async { var url = tokenEndpoint.replace( userInfo: '${pseudoApplication.id}:${pseudoApplication.secret}'); - var response = await testClient.post(url.toString(), headers: { + var response = await testClient.post(url, headers: { 'accept': 'application/json', // 'authorization': 'Basic ' + base64Url.encode(ascii.encode(url.userInfo)) }, body: { @@ -166,13 +166,13 @@ main() { response, allOf( hasStatus(200), - isJson({"token_type": "bearer", "access_token": "yes"}), + isJson({'token_type': 'bearer', 'access_token': 'yes'}), )); }); test('with incorrect verifier', () async { var url = tokenEndpoint.replace( userInfo: '${pseudoApplication.id}:${pseudoApplication.secret}'); - var response = await testClient.post(url.toString(), headers: { + var response = await testClient.post(url, headers: { 'accept': 'application/json', // 'authorization': 'Basic ' + base64Url.encode(ascii.encode(url.userInfo)) }, body: { @@ -189,9 +189,9 @@ main() { allOf( hasStatus(400), isJson({ - "error": "invalid_grant", - "error_description": - "The given `code_verifier` parameter is invalid." + 'error': 'invalid_grant', + 'error_description': + 'The given `code_verifier` parameter is invalid.' }), )); }); @@ -199,7 +199,7 @@ main() { test('with missing verifier', () async { var url = tokenEndpoint.replace( userInfo: '${pseudoApplication.id}:${pseudoApplication.secret}'); - var response = await testClient.post(url.toString(), headers: { + var response = await testClient.post(url, headers: { 'accept': 'application/json', // 'authorization': 'Basic ' + base64Url.encode(ascii.encode(url.userInfo)) }, body: { @@ -215,8 +215,8 @@ main() { allOf( hasStatus(400), isJson({ - "error": "invalid_request", - "error_description": "Missing `code_verifier` parameter." + 'error': 'invalid_request', + 'error_description': 'Missing `code_verifier` parameter.' }), )); }); @@ -225,34 +225,34 @@ main() { class _Server extends AuthorizationServer { @override - FutureOr findClient(String clientId) { + FutureOr findClient(String? clientId) { return pseudoApplication; } @override Future verifyClient( - PseudoApplication client, String clientSecret) async { + PseudoApplication client, String? clientSecret) async { return client.secret == clientSecret; } @override Future requestAuthorizationCode( PseudoApplication client, - String redirectUri, + String? redirectUri, Iterable scopes, String state, RequestContext req, ResponseContext res, bool implicit) async { - req.container.make(); + req.container!.make(); return {'code': 'ok'}; } @override Future exchangeAuthorizationCodeForToken( - PseudoApplication client, - String authCode, - String redirectUri, + PseudoApplication? client, + String? authCode, + String? redirectUri, RequestContext req, ResponseContext res) async { var codeVerifier = await getPkceCodeVerifier(req); @@ -266,7 +266,7 @@ class AuthCodes extends MapBase with MapMixin { var inner = {}; @override - String operator [](Object key) => inner[key]; + String? operator [](Object? key) => inner[key as String]; @override void operator []=(String key, String value) => inner[key] = value; @@ -278,5 +278,5 @@ class AuthCodes extends MapBase with MapMixin { Iterable get keys => inner.keys; @override - String remove(Object key) => inner.remove(key); + String? remove(Object? key) => inner.remove(key); }