Updated auth
This commit is contained in:
parent
7652c02183
commit
7cbbc686ba
31 changed files with 182 additions and 146 deletions
|
@ -1,5 +1,11 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 4.1.1
|
||||||
|
|
||||||
|
* Changed `userId` field of `AuthToken` to String type
|
||||||
|
* Changed `serializer` return value to String type
|
||||||
|
* Changed `deserializer` input parameter to String type
|
||||||
|
|
||||||
## 4.1.0
|
## 4.1.0
|
||||||
|
|
||||||
* Updated linter to `package:lints`
|
* Updated linter to `package:lints`
|
||||||
|
|
|
@ -18,9 +18,10 @@ Ensure you have read the [User Guide](https://angel3-docs.dukefirehawk.com/guide
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
configureServer(Angel app) async {
|
configureServer(Angel app) async {
|
||||||
var auth = AngelAuth<User>();
|
var auth = AngelAuth<User>(
|
||||||
auth.serializer = ...;
|
serializer: (user) => user.id ?? '',
|
||||||
auth.deserializer = ...;
|
deserializer: (id) => fetchAUserByIdSomehow(id)
|
||||||
|
);
|
||||||
auth.strategies['local'] = LocalAuthStrategy(...);
|
auth.strategies['local'] = LocalAuthStrategy(...);
|
||||||
|
|
||||||
// POST route to handle username+password
|
// POST route to handle username+password
|
||||||
|
|
|
@ -6,7 +6,7 @@ import 'package:angel3_framework/http.dart';
|
||||||
void main() async {
|
void main() async {
|
||||||
var app = Angel();
|
var app = Angel();
|
||||||
var auth = AngelAuth<User>(
|
var auth = AngelAuth<User>(
|
||||||
serializer: (user) => user.id,
|
serializer: (user) => user.id ?? '',
|
||||||
deserializer: (id) => fetchAUserByIdSomehow(id));
|
deserializer: (id) => fetchAUserByIdSomehow(id));
|
||||||
|
|
||||||
// Middleware to decode JWT's and inject a user object...
|
// Middleware to decode JWT's and inject a user object...
|
||||||
|
@ -31,7 +31,7 @@ class User {
|
||||||
String? id, username, password;
|
String? id, username, password;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<User> fetchAUserByIdSomehow(id) async {
|
Future<User> fetchAUserByIdSomehow(String id) async {
|
||||||
// Fetch a user somehow...
|
// Fetch a user somehow...
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,41 +32,35 @@ class AuthToken {
|
||||||
SplayTreeMap.from({'alg': 'HS256', 'typ': 'JWT'});
|
SplayTreeMap.from({'alg': 'HS256', 'typ': 'JWT'});
|
||||||
|
|
||||||
String? ipAddress;
|
String? ipAddress;
|
||||||
late DateTime issuedAt;
|
|
||||||
num lifeSpan;
|
num lifeSpan;
|
||||||
dynamic userId;
|
String userId;
|
||||||
|
late DateTime issuedAt;
|
||||||
Map<String, dynamic> payload = {};
|
Map<String, dynamic> payload = {};
|
||||||
|
|
||||||
AuthToken(
|
AuthToken(
|
||||||
{this.ipAddress,
|
{this.ipAddress,
|
||||||
this.lifeSpan = -1,
|
this.lifeSpan = -1,
|
||||||
this.userId,
|
required this.userId,
|
||||||
DateTime? issuedAt,
|
DateTime? issuedAt,
|
||||||
Map payload = const {}}) {
|
Map<String, dynamic>? payload}) {
|
||||||
this.issuedAt = issuedAt ?? DateTime.now();
|
this.issuedAt = issuedAt ?? DateTime.now();
|
||||||
|
if (payload != null) {
|
||||||
this.payload.addAll(payload.keys
|
this.payload.addAll(payload.keys
|
||||||
.fold({}, ((out, k) => out?..[k.toString()] = payload[k])) ??
|
.fold({}, ((out, k) => out?..[k.toString()] = payload[k])) ??
|
||||||
{});
|
{});
|
||||||
/*
|
}
|
||||||
this.payload.addAll(payload.keys.fold(
|
|
||||||
{},
|
|
||||||
((out, k) => out..[k.toString()] = payload[k])
|
|
||||||
as Map<String, dynamic>? Function(
|
|
||||||
Map<String, dynamic>?, dynamic)) ??
|
|
||||||
{});
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
factory AuthToken.fromJson(String jsons) =>
|
factory AuthToken.fromJson(String jsons) =>
|
||||||
AuthToken.fromMap(json.decode(jsons) as Map);
|
AuthToken.fromMap(json.decode(jsons) as Map<String, dynamic>);
|
||||||
|
|
||||||
factory AuthToken.fromMap(Map data) {
|
factory AuthToken.fromMap(Map<String, dynamic> data) {
|
||||||
return AuthToken(
|
return AuthToken(
|
||||||
ipAddress: data['aud'].toString(),
|
ipAddress: data['aud'].toString(),
|
||||||
lifeSpan: data['exp'] as num,
|
lifeSpan: data['exp'] as num,
|
||||||
issuedAt: DateTime.parse(data['iat'].toString()),
|
issuedAt: DateTime.parse(data['iat'].toString()),
|
||||||
userId: data['sub'],
|
userId: data['sub'],
|
||||||
payload: data['pld'] as Map);
|
payload: data['pld']);
|
||||||
}
|
}
|
||||||
|
|
||||||
factory AuthToken.parse(String jwt) {
|
factory AuthToken.parse(String jwt) {
|
||||||
|
@ -78,7 +72,8 @@ class AuthToken {
|
||||||
}
|
}
|
||||||
|
|
||||||
var payloadString = decodeBase64(split[1]);
|
var payloadString = decodeBase64(split[1]);
|
||||||
return AuthToken.fromMap(json.decode(payloadString) as Map);
|
return AuthToken.fromMap(
|
||||||
|
json.decode(payloadString) as Map<String, dynamic>);
|
||||||
}
|
}
|
||||||
|
|
||||||
factory AuthToken.validate(String jwt, Hmac hmac) {
|
factory AuthToken.validate(String jwt, Hmac hmac) {
|
||||||
|
@ -100,7 +95,8 @@ class AuthToken {
|
||||||
message: 'JWT payload does not match hashed version.');
|
message: 'JWT payload does not match hashed version.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return AuthToken.fromMap(json.decode(payloadString) as Map);
|
return AuthToken.fromMap(
|
||||||
|
json.decode(payloadString) as Map<String, dynamic>);
|
||||||
}
|
}
|
||||||
|
|
||||||
String serialize(Hmac hmac) {
|
String serialize(Hmac hmac) {
|
||||||
|
@ -111,7 +107,7 @@ class AuthToken {
|
||||||
return data + '.' + base64Url.encode(signature);
|
return data + '.' + base64Url.encode(signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
return _splayify({
|
return _splayify({
|
||||||
'iss': 'angel_auth',
|
'iss': 'angel_auth',
|
||||||
'aud': ipAddress,
|
'aud': ipAddress,
|
||||||
|
@ -123,7 +119,7 @@ class AuthToken {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SplayTreeMap _splayify(Map map) {
|
Map<String, dynamic> _splayify(Map<String, dynamic> map) {
|
||||||
var data = {};
|
var data = {};
|
||||||
map.forEach((k, v) {
|
map.forEach((k, v) {
|
||||||
data[k] = _splay(v);
|
data[k] = _splay(v);
|
||||||
|
@ -131,11 +127,11 @@ SplayTreeMap _splayify(Map map) {
|
||||||
return SplayTreeMap.from(data);
|
return SplayTreeMap.from(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic _splay(value) {
|
dynamic _splay(dynamic value) {
|
||||||
if (value is Iterable) {
|
if (value is Iterable) {
|
||||||
return value.map(_splay).toList();
|
return value.map(_splay).toList();
|
||||||
} else if (value is Map) {
|
} else if (value is Map) {
|
||||||
return _splayify(value);
|
return _splayify(value as Map<String, dynamic>);
|
||||||
} else {
|
} else {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ class ExternalAuthOptions {
|
||||||
/// * `client_id`
|
/// * `client_id`
|
||||||
/// * `client_secret`
|
/// * `client_secret`
|
||||||
/// * `redirect_uri`
|
/// * `redirect_uri`
|
||||||
factory ExternalAuthOptions.fromMap(Map map) {
|
factory ExternalAuthOptions.fromMap(Map<String, dynamic> map) {
|
||||||
var clientId = map['client_id'];
|
var clientId = map['client_id'];
|
||||||
var clientSecret = map['client_secret'];
|
var clientSecret = map['client_secret'];
|
||||||
if (clientId == null || clientSecret == null) {
|
if (clientId == null || clientSecret == null) {
|
||||||
|
@ -55,8 +55,8 @@ class ExternalAuthOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
return ExternalAuthOptions(
|
return ExternalAuthOptions(
|
||||||
clientId: clientId as String,
|
clientId: clientId,
|
||||||
clientSecret: clientSecret as String,
|
clientSecret: clientSecret,
|
||||||
redirectUri: map['redirect_uri'],
|
redirectUri: map['redirect_uri'],
|
||||||
scopes: map['scopes'] is Iterable
|
scopes: map['scopes'] is Iterable
|
||||||
? ((map['scopes'] as Iterable).map((x) => x.toString()))
|
? ((map['scopes'] as Iterable).map((x) => x.toString()))
|
||||||
|
|
|
@ -52,10 +52,10 @@ class AngelAuth<User> {
|
||||||
Map<String, AuthStrategy<User>> strategies = {};
|
Map<String, AuthStrategy<User>> strategies = {};
|
||||||
|
|
||||||
/// Serializes a user into a unique identifier associated only with one identity.
|
/// Serializes a user into a unique identifier associated only with one identity.
|
||||||
FutureOr Function(User) serializer;
|
FutureOr<String> Function(User) serializer;
|
||||||
|
|
||||||
/// Deserializes a unique identifier into its associated identity. In most cases, this is a user object or model instance.
|
/// Deserializes a unique identifier into its associated identity. In most cases, this is a user object or model instance.
|
||||||
FutureOr<User> Function(Object) deserializer;
|
FutureOr<User> Function(String) deserializer;
|
||||||
|
|
||||||
/// Fires the result of [deserializer] whenever a user signs in to the application.
|
/// Fires the result of [deserializer] whenever a user signs in to the application.
|
||||||
Stream<User> get onLogin => _onLogin.stream;
|
Stream<User> get onLogin => _onLogin.stream;
|
||||||
|
@ -200,6 +200,7 @@ class AngelAuth<User> {
|
||||||
/// String getUsername(User user) => user.name
|
/// String getUsername(User user) => user.name
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
/*
|
||||||
@deprecated
|
@deprecated
|
||||||
Future decodeJwt(RequestContext req, ResponseContext res) async {
|
Future decodeJwt(RequestContext req, ResponseContext res) async {
|
||||||
if (req.method == 'POST' && req.path == reviveTokenEndpoint) {
|
if (req.method == 'POST' && req.path == reviveTokenEndpoint) {
|
||||||
|
@ -209,6 +210,7 @@ class AngelAuth<User> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
Future<_AuthResult<User>?> _decodeJwt(
|
Future<_AuthResult<User>?> _decodeJwt(
|
||||||
RequestContext req, ResponseContext res) async {
|
RequestContext req, ResponseContext res) async {
|
||||||
|
@ -431,7 +433,7 @@ class AngelAuth<User> {
|
||||||
req.accepts('application/json')) {
|
req.accepts('application/json')) {
|
||||||
var user = hasExisting
|
var user = hasExisting
|
||||||
? result
|
? result
|
||||||
: await deserializer((await serializer(result)) as Object);
|
: await deserializer(await serializer(result));
|
||||||
_onLogin.add(user);
|
_onLogin.add(user);
|
||||||
return {'data': user, 'token': jwt};
|
return {'data': user, 'token': jwt};
|
||||||
}
|
}
|
||||||
|
@ -469,8 +471,8 @@ class AngelAuth<User> {
|
||||||
|
|
||||||
/// Log a user in on-demand.
|
/// Log a user in on-demand.
|
||||||
Future loginById(
|
Future loginById(
|
||||||
dynamic userId, RequestContext req, ResponseContext res) async {
|
String userId, RequestContext req, ResponseContext res) async {
|
||||||
var user = await deserializer(userId as Object);
|
var user = await deserializer(userId);
|
||||||
var token =
|
var token =
|
||||||
AuthToken(userId: userId, lifeSpan: _jwtLifeSpan, ipAddress: req.ip);
|
AuthToken(userId: userId, lifeSpan: _jwtLifeSpan, ipAddress: req.ip);
|
||||||
_apply(req, res, token, user);
|
_apply(req, res, token, user);
|
||||||
|
|
|
@ -38,8 +38,8 @@ class LocalAuthStrategy<User> extends AuthStrategy<User> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<User?> authenticate(RequestContext req, ResponseContext res,
|
Future<User?> authenticate(RequestContext req, ResponseContext res,
|
||||||
[AngelAuthOptions? options_]) async {
|
[AngelAuthOptions? options]) async {
|
||||||
var options = options_ ?? AngelAuthOptions();
|
var _options = options ?? AngelAuthOptions();
|
||||||
User? verificationResult;
|
User? verificationResult;
|
||||||
|
|
||||||
if (allowBasic) {
|
if (allowBasic) {
|
||||||
|
@ -88,9 +88,9 @@ class LocalAuthStrategy<User> extends AuthStrategy<User> {
|
||||||
|
|
||||||
if (verificationResult == null ||
|
if (verificationResult == null ||
|
||||||
(verificationResult is Map && verificationResult.isEmpty)) {
|
(verificationResult is Map && verificationResult.isEmpty)) {
|
||||||
if (options.failureRedirect != null &&
|
if (_options.failureRedirect != null &&
|
||||||
options.failureRedirect!.isNotEmpty) {
|
_options.failureRedirect!.isNotEmpty) {
|
||||||
await res.redirect(options.failureRedirect, code: 401);
|
await res.redirect(_options.failureRedirect, code: 401);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
name: angel3_auth
|
name: angel3_auth
|
||||||
description: A complete authentication plugin for Angel3. Includes support for stateless JWT tokens, Basic Auth, and more.
|
description: A complete authentication plugin for Angel3. Includes support for stateless JWT tokens, Basic Auth, and more.
|
||||||
version: 4.1.0
|
version: 4.1.1
|
||||||
homepage: https://angel3-framework.web.app/
|
homepage: https://angel3-framework.web.app/
|
||||||
repository: https://github.com/dukefirehawk/angel/tree/master/packages/auth
|
repository: https://github.com/dukefirehawk/angel/tree/master/packages/auth
|
||||||
environment:
|
environment:
|
||||||
|
@ -21,5 +21,5 @@ dev_dependencies:
|
||||||
test: ^1.17.4
|
test: ^1.17.4
|
||||||
lints: ^1.0.0
|
lints: ^1.0.0
|
||||||
#dependency_overrides:
|
#dependency_overrides:
|
||||||
# angel3_container:
|
# angel3_framework:
|
||||||
# path: ../container/angel_container
|
# path: ../framework
|
||||||
|
|
|
@ -73,7 +73,7 @@ void main() {
|
||||||
?.create({'username': 'jdoe1', 'password': 'password'});
|
?.create({'username': 'jdoe1', 'password': 'password'});
|
||||||
|
|
||||||
auth = AngelAuth<User>(
|
auth = AngelAuth<User>(
|
||||||
serializer: (u) => u.id,
|
serializer: (u) => u.id ?? '',
|
||||||
deserializer: (id) async =>
|
deserializer: (id) async =>
|
||||||
await app.findService('users')?.read(id) as User);
|
await app.findService('users')?.read(id) as User);
|
||||||
//auth.serializer = (u) => u.id;
|
//auth.serializer = (u) => u.id;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import 'package:logging/logging.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
final AngelAuth<Map<String, String>> auth = AngelAuth<Map<String, String>>(
|
final AngelAuth<Map<String, String>> auth = AngelAuth<Map<String, String>>(
|
||||||
serializer: (user) async => 1337, deserializer: (id) async => sampleUser);
|
serializer: (user) async => '1337', deserializer: (id) async => sampleUser);
|
||||||
var headers = <String, String>{'accept': 'application/json'};
|
var headers = <String, String>{'accept': 'application/json'};
|
||||||
var localOpts = AngelAuthOptions<Map<String, String>>(
|
var localOpts = AngelAuthOptions<Map<String, String>>(
|
||||||
failureRedirect: '/failure', successRedirect: '/success');
|
failureRedirect: '/failure', successRedirect: '/success');
|
||||||
|
|
|
@ -11,7 +11,7 @@ void main() {
|
||||||
secureCookies: true,
|
secureCookies: true,
|
||||||
cookieDomain: 'SECURE',
|
cookieDomain: 'SECURE',
|
||||||
jwtLifeSpan: threeDays.inMilliseconds,
|
jwtLifeSpan: threeDays.inMilliseconds,
|
||||||
serializer: (u) => u,
|
serializer: (u) => u as String,
|
||||||
deserializer: (u) => u);
|
deserializer: (u) => u);
|
||||||
|
|
||||||
setUp(() => defaultCookie = Cookie('a', 'b'));
|
setUp(() => defaultCookie = Cookie('a', 'b'));
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 4.1.0
|
||||||
|
|
||||||
|
* Updated linter to `package:lints`
|
||||||
|
|
||||||
## 4.0.2
|
## 4.0.2
|
||||||
|
|
||||||
* Updated example
|
* Updated example
|
||||||
|
|
|
@ -1,21 +1,29 @@
|
||||||
MIT License (MIT)
|
BSD 3-Clause License
|
||||||
|
|
||||||
Copyright (c) 2021 dukefirehawk.com
|
Copyright (c) 2021, dukefirehawk.com
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Redistribution and use in source and binary forms, with or without
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
modification, are permitted provided that the following conditions are met:
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
copies or substantial portions of the Software.
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
this list of conditions and the following disclaimer in the documentation
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
and/or other materials provided with the distribution.
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
3. Neither the name of the copyright holder nor the names of its
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
contributors may be used to endorse or promote products derived from
|
||||||
SOFTWARE.
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
# Angel3 OAuth2 Handler
|
# Angel3 OAuth2 Handler
|
||||||
|
|
||||||
[![version](https://img.shields.io/badge/pub-v4.0.2-brightgreen)](https://pub.dartlang.org/packages/angel3_auth_oauth2)
|
![Pub Version (including pre-releases)](https://img.shields.io/pub/v/angel3_auth_oauth2?include_prereleases)
|
||||||
[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety)
|
![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)
|
[![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/master/packages/auth_oauth2/LICENSE)
|
||||||
[![License](https://img.shields.io/github/license/dukefirehawk/angel)](https://github.com/dukefirehawk/angel/tree/angel3/packages/auth_oauth2/LICENSE)
|
|
||||||
|
|
||||||
Angel3 library for authenticating users with remote identity providers via OAuth2, i.e. Facebook, Google, Azure AD, etc.
|
Angel3 library for authenticating users with remote identity providers via OAuth2, i.e. Facebook, Google, Azure AD, etc.
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1 @@
|
||||||
include: package:pedantic/analysis_options.yaml
|
include: package:lints/recommended.yaml
|
||||||
analyzer:
|
|
||||||
strong-mode:
|
|
||||||
implicit-casts: false
|
|
|
@ -48,8 +48,8 @@ void main() async {
|
||||||
|
|
||||||
// Set up the authenticator plugin.
|
// Set up the authenticator plugin.
|
||||||
var auth = AngelAuth<User>(
|
var auth = AngelAuth<User>(
|
||||||
serializer: (user) async => user.id,
|
serializer: (user) async => user.id ?? '',
|
||||||
deserializer: (id) => mappedUserService.read(id.toString()),
|
deserializer: (id) => mappedUserService.read(id),
|
||||||
jwtKey: 'oauth2 example secret',
|
jwtKey: 'oauth2 example secret',
|
||||||
allowCookie: false);
|
allowCookie: false);
|
||||||
await app.configure(auth.configureServer);
|
await app.configure(auth.configureServer);
|
||||||
|
@ -120,7 +120,7 @@ class User extends Model {
|
||||||
|
|
||||||
User({this.id, this.githubId});
|
User({this.id, this.githubId});
|
||||||
|
|
||||||
static User parse(Map map) =>
|
static User parse(Map<String, dynamic> 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<String, dynamic> serialize(User user) => user.toJson();
|
static Map<String, dynamic> serialize(User user) => user.toJson();
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
name: angel3_auth_oauth2
|
name: angel3_auth_oauth2
|
||||||
version: 4.0.2
|
version: 4.1.0
|
||||||
description: Angel3 library for authenticating users with external identity providers via OAuth2.
|
description: Angel3 library for authenticating users with external identity providers via OAuth2.
|
||||||
homepage: https://angel3-framework.web.app/
|
homepage: https://angel3-framework.web.app/
|
||||||
repository: https://github.com/dukefirehawk/angel/tree/angel3/packages/auth_oauth2
|
repository: https://github.com/dukefirehawk/angel/tree/master/packages/auth_oauth2
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.12.0 <3.0.0'
|
sdk: '>=2.12.0 <3.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
angel3_auth: ^4.0.0
|
angel3_auth: ^4.1.0
|
||||||
angel3_framework: ^4.0.0
|
angel3_framework: ^4.2.0
|
||||||
http_parser: ^4.0.0
|
http_parser: ^4.0.0
|
||||||
oauth2: ^2.0.0
|
oauth2: ^2.0.0
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
logging: ^1.0.1
|
logging: ^1.0.1
|
||||||
pedantic: ^1.11.0
|
lints: ^1.0.0
|
||||||
|
#dependency_overrides:
|
||||||
|
# angel3_auth:
|
||||||
|
# path: ../auth
|
||||||
|
|
|
@ -5,7 +5,7 @@ import 'dart:async';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:logging/logging.dart';
|
//import 'package:logging/logging.dart';
|
||||||
export 'package:angel3_http_exception/angel3_http_exception.dart';
|
export 'package:angel3_http_exception/angel3_http_exception.dart';
|
||||||
|
|
||||||
/// A function that configures an [Angel] client in some way.
|
/// A function that configures an [Angel] client in some way.
|
||||||
|
|
|
@ -25,6 +25,6 @@ dev_dependencies:
|
||||||
test: ^1.17.5
|
test: ^1.17.5
|
||||||
lints: ^1.0.0
|
lints: ^1.0.0
|
||||||
#dependency_overrides:
|
#dependency_overrides:
|
||||||
# angel3_container:
|
# angel3_auth:
|
||||||
# path: ../container/angel_container
|
# path: ../auth
|
||||||
|
|
|
@ -6,8 +6,8 @@ repository: https://github.com/dukefirehawk/angel/tree/angel3/packages/hot
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.12.0 <3.0.0'
|
sdk: '>=2.12.0 <3.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
angel3_framework: ^4.1.0
|
angel3_framework: ^4.2.0
|
||||||
angel3_websocket: ^4.0.0
|
angel3_websocket: ^4.1.0
|
||||||
belatuk_html_builder: ^3.0.0
|
belatuk_html_builder: ^3.0.0
|
||||||
charcode: ^1.2.0
|
charcode: ^1.2.0
|
||||||
glob: ^2.0.1
|
glob: ^2.0.1
|
||||||
|
@ -19,3 +19,7 @@ dev_dependencies:
|
||||||
http: ^0.13.2
|
http: ^0.13.2
|
||||||
logging: ^1.0.1
|
logging: ^1.0.1
|
||||||
lints: ^1.0.0
|
lints: ^1.0.0
|
||||||
|
#dependency_overrides:
|
||||||
|
# angel3_websocket:
|
||||||
|
# path: ../websocket
|
||||||
|
|
|
@ -17,3 +17,6 @@ dev_dependencies:
|
||||||
belatuk_pretty_logging: ^4.0.0
|
belatuk_pretty_logging: ^4.0.0
|
||||||
test: ^1.17.5
|
test: ^1.17.5
|
||||||
lints: ^1.0.0
|
lints: ^1.0.0
|
||||||
|
#dependency_overrides:
|
||||||
|
# angel3_auth:
|
||||||
|
# path: ../auth
|
||||||
|
|
|
@ -6,11 +6,14 @@ repository: https://github.com/dukefirehawk/angel/tree/angel3/packages/sync
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.12.0 <3.0.0'
|
sdk: '>=2.12.0 <3.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
angel3_framework: ^4.1.0
|
angel3_framework: ^4.2.0
|
||||||
angel3_websocket: ^4.0.0
|
angel3_websocket: ^4.1.0
|
||||||
belatuk_pub_sub: ^4.0.0
|
belatuk_pub_sub: ^4.0.0
|
||||||
stream_channel: ^2.1.0
|
stream_channel: ^2.1.0
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
angel3_test: ^4.0.0
|
angel3_test: ^4.1.0
|
||||||
test: ^1.17.8
|
test: ^1.17.5
|
||||||
lints: ^1.0.0
|
lints: ^1.0.0
|
||||||
|
#dependency_overrides:
|
||||||
|
# angel3_websocket:
|
||||||
|
# path: ../websocket
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 4.1.1
|
||||||
|
|
||||||
|
* Fixed NNBD issues
|
||||||
|
|
||||||
## 4.1.0
|
## 4.1.0
|
||||||
|
|
||||||
* Updated linter to `package:lints`
|
* Updated linter to `package:lints`
|
||||||
|
|
|
@ -6,7 +6,7 @@ import 'package:angel3_websocket/server.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
Angel? app;
|
Angel app;
|
||||||
late TestClient client;
|
late TestClient client;
|
||||||
|
|
||||||
setUp(() async {
|
setUp(() async {
|
||||||
|
@ -46,17 +46,16 @@ void main() {
|
||||||
create: (dynamic data, [params]) async => {'foo': 'bar'}));
|
create: (dynamic data, [params]) async => {'foo': 'bar'}));
|
||||||
|
|
||||||
var ws = AngelWebSocket(app);
|
var ws = AngelWebSocket(app);
|
||||||
await app!.configure(ws.configureServer);
|
await app.configure(ws.configureServer);
|
||||||
app!.all('/ws', ws.handleRequest);
|
app.all('/ws', ws.handleRequest);
|
||||||
|
|
||||||
app!.errorHandler = (e, req, res) => e.toJson();
|
app.errorHandler = (e, req, res) => e.toJson();
|
||||||
|
|
||||||
client = await connectTo(app!);
|
client = await connectTo(app);
|
||||||
});
|
});
|
||||||
|
|
||||||
tearDown(() async {
|
tearDown(() async {
|
||||||
await client.close();
|
await client.close();
|
||||||
app = null;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
group('matchers', () {
|
group('matchers', () {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
name: angel3_test
|
name: angel3_test
|
||||||
version: 4.1.0
|
version: 4.1.1
|
||||||
description: Testing utility library for the Angel3 framework. Use with package:test.
|
description: Testing utility library for the Angel3 framework. Use with package:test.
|
||||||
homepage: https://angel3-framework.web.app/
|
homepage: https://angel3-framework.web.app/
|
||||||
repository: https://github.com/dukefirehawk/angel/tree/master/packages/test
|
repository: https://github.com/dukefirehawk/angel/tree/master/packages/test
|
||||||
|
@ -19,7 +19,7 @@ dependencies:
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
test: ^1.17.5
|
test: ^1.17.5
|
||||||
lints: ^1.0.0
|
lints: ^1.0.0
|
||||||
#dependency_overrides:
|
dependency_overrides:
|
||||||
# angel3_container:
|
angel3_websocket:
|
||||||
# path: ../container/angel_container
|
path: ../websocket
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import 'package:angel3_websocket/server.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
Angel? app;
|
Angel app;
|
||||||
late TestClient client;
|
late TestClient client;
|
||||||
|
|
||||||
setUp(() async {
|
setUp(() async {
|
||||||
|
@ -48,17 +48,16 @@ void main() {
|
||||||
<String, dynamic>{'foo': 'bar'}));
|
<String, dynamic>{'foo': 'bar'}));
|
||||||
|
|
||||||
var ws = AngelWebSocket(app);
|
var ws = AngelWebSocket(app);
|
||||||
await app!.configure(ws.configureServer);
|
await app.configure(ws.configureServer);
|
||||||
app!.all('/ws', ws.handleRequest);
|
app.all('/ws', ws.handleRequest);
|
||||||
|
|
||||||
app!.errorHandler = (e, req, res) => e.toJson();
|
app.errorHandler = (e, req, res) => e.toJson();
|
||||||
|
|
||||||
client = await connectTo(app!, useZone: false);
|
client = await connectTo(app, useZone: false);
|
||||||
});
|
});
|
||||||
|
|
||||||
tearDown(() async {
|
tearDown(() async {
|
||||||
await client.close();
|
await client.close();
|
||||||
app = null;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
group('matchers', () {
|
group('matchers', () {
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 4.1.1
|
||||||
|
|
||||||
|
* Fixed issue with type casting
|
||||||
|
* Changed `app` parameter of `AngelWebSocket` to non-nullable
|
||||||
|
|
||||||
## 4.1.0
|
## 4.1.0
|
||||||
|
|
||||||
* Updated to use `package:belatuk_merge_map`
|
* Updated to use `package:belatuk_merge_map`
|
||||||
|
|
|
@ -40,17 +40,17 @@ class AngelWebSocket {
|
||||||
final StreamController<WebSocketContext> _onDisconnect =
|
final StreamController<WebSocketContext> _onDisconnect =
|
||||||
StreamController<WebSocketContext>.broadcast();
|
StreamController<WebSocketContext>.broadcast();
|
||||||
|
|
||||||
final Angel? app;
|
final Angel app;
|
||||||
|
|
||||||
/// If this is not `true`, then all client-side service parameters will be
|
/// If this is not `true`, then all client-side service parameters will be
|
||||||
/// discarded, other than `params['query']`.
|
/// discarded, other than `params['query']`.
|
||||||
final bool allowClientParams;
|
final bool allowClientParams;
|
||||||
|
|
||||||
/// An optional whitelist of allowed client origins, or [:null:].
|
/// An optional whitelist of allowed client origins, or [:null:].
|
||||||
final List<String>? allowedOrigins;
|
final List<String> allowedOrigins;
|
||||||
|
|
||||||
/// An optional whitelist of allowed client protocols, or [:null:].
|
/// An optional whitelist of allowed client protocols, or [:null:].
|
||||||
final List<String>? allowedProtocols;
|
final List<String> allowedProtocols;
|
||||||
|
|
||||||
/// If `true`, then clients can authenticate their WebSockets by sending a valid JWT.
|
/// If `true`, then clients can authenticate their WebSockets by sending a valid JWT.
|
||||||
final bool allowAuth;
|
final bool allowAuth;
|
||||||
|
@ -93,8 +93,8 @@ class AngelWebSocket {
|
||||||
this.synchronizationChannel,
|
this.synchronizationChannel,
|
||||||
this.serializer,
|
this.serializer,
|
||||||
this.deserializer,
|
this.deserializer,
|
||||||
this.allowedOrigins,
|
this.allowedOrigins = const [],
|
||||||
this.allowedProtocols}) {
|
this.allowedProtocols = const []}) {
|
||||||
serializer ??= json.encode;
|
serializer ??= json.encode;
|
||||||
deserializer ??= (params) => params;
|
deserializer ??= (params) => params;
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,7 @@ class AngelWebSocket {
|
||||||
if (e.service.configuration.containsKey('ws:filter')) {
|
if (e.service.configuration.containsKey('ws:filter')) {
|
||||||
return e.service.configuration['ws:filter'](e, socket);
|
return e.service.configuration['ws:filter'](e, socket);
|
||||||
} else if (e.params != null && e.params!.containsKey('ws:filter')) {
|
} else if (e.params != null && e.params!.containsKey('ws:filter')) {
|
||||||
return e.params!['ws:filter'](e, socket);
|
return e.params?['ws:filter'](e, socket);
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -175,13 +175,15 @@ class AngelWebSocket {
|
||||||
Future<void> batchEvent(WebSocketEvent event,
|
Future<void> batchEvent(WebSocketEvent event,
|
||||||
{Function(WebSocketContext socket)? filter, bool notify = true}) async {
|
{Function(WebSocketContext socket)? filter, bool notify = true}) async {
|
||||||
// Default implementation will just immediately fire events
|
// Default implementation will just immediately fire events
|
||||||
_clients.forEach((client) async {
|
for (var client in _clients) {
|
||||||
dynamic result = true;
|
dynamic result = true;
|
||||||
if (filter != null) result = await filter(client);
|
if (filter != null) {
|
||||||
|
result = await filter(client);
|
||||||
|
}
|
||||||
if (result == true) {
|
if (result == true) {
|
||||||
client.channel.sink.add((serializer ?? json.encode)(event.toJson()));
|
client.channel.sink.add((serializer ?? json.encode)(event.toJson()));
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
if (synchronizationChannel != null && notify != false) {
|
if (synchronizationChannel != null && notify != false) {
|
||||||
synchronizationChannel!.sink.add(event);
|
synchronizationChannel!.sink.add(event);
|
||||||
|
@ -200,11 +202,11 @@ class AngelWebSocket {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var service = app!.findService(split[0]);
|
var service = app.findService(split[0]);
|
||||||
|
|
||||||
if (service == null) {
|
if (service == null) {
|
||||||
socket.sendError(AngelHttpException.notFound(
|
socket.sendError(AngelHttpException.notFound(
|
||||||
message: 'No service \"${split[0]}\" exists.'));
|
message: 'No service "${split[0]}" exists.'));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,7 +224,7 @@ class AngelWebSocket {
|
||||||
|
|
||||||
var params = mergeMap<String, dynamic>([
|
var params = mergeMap<String, dynamic>([
|
||||||
(((deserializer ?? (params) => params)(action.params))
|
(((deserializer ?? (params) => params)(action.params))
|
||||||
as Map<String, dynamic>?)!,
|
as Map<String, dynamic>),
|
||||||
{
|
{
|
||||||
'provider': Providers.websocket,
|
'provider': Providers.websocket,
|
||||||
'__requestctx': socket.request,
|
'__requestctx': socket.request,
|
||||||
|
@ -257,7 +259,7 @@ class AngelWebSocket {
|
||||||
data: await service.remove(action.id, params));
|
data: await service.remove(action.id, params));
|
||||||
} else {
|
} else {
|
||||||
socket.sendError(AngelHttpException.methodNotAllowed(
|
socket.sendError(AngelHttpException.methodNotAllowed(
|
||||||
message: 'Method Not Allowed: \"$actionName\"'));
|
message: 'Method Not Allowed: $actionName'));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} catch (e, st) {
|
} catch (e, st) {
|
||||||
|
@ -278,7 +280,7 @@ class AngelWebSocket {
|
||||||
AuthToken token;
|
AuthToken token;
|
||||||
|
|
||||||
token = AuthToken.validate(jwt, auth.hmac);
|
token = AuthToken.validate(jwt, auth.hmac);
|
||||||
var user = await auth.deserializer(token.userId as Object);
|
var user = await auth.deserializer(token.userId);
|
||||||
socket.request
|
socket.request
|
||||||
..container!.registerSingleton<AuthToken>(token)
|
..container!.registerSingleton<AuthToken>(token)
|
||||||
..container!.registerSingleton(user, as: user.runtimeType);
|
..container!.registerSingleton(user, as: user.runtimeType);
|
||||||
|
@ -359,16 +361,16 @@ class AngelWebSocket {
|
||||||
// Send an error
|
// Send an error
|
||||||
if (e is AngelHttpException) {
|
if (e is AngelHttpException) {
|
||||||
socket.sendError(e);
|
socket.sendError(e);
|
||||||
app?.logger?.severe(e.message, e.error ?? e, e.stackTrace);
|
app.logger?.severe(e.message, e.error ?? e, e.stackTrace);
|
||||||
} else if (sendErrors) {
|
} else if (sendErrors) {
|
||||||
var err = AngelHttpException(e,
|
var err = AngelHttpException(e,
|
||||||
message: e.toString(), stackTrace: st, errors: [st.toString()]);
|
message: e.toString(), stackTrace: st, errors: [st.toString()]);
|
||||||
socket.sendError(err);
|
socket.sendError(err);
|
||||||
app?.logger?.severe(err.message, e, st);
|
app.logger?.severe(err.message, e, st);
|
||||||
} else {
|
} else {
|
||||||
var err = AngelHttpException(e);
|
var err = AngelHttpException(e);
|
||||||
socket.sendError(err);
|
socket.sendError(err);
|
||||||
app?.logger?.severe(e.toString(), e, st);
|
app.logger?.severe(e.toString(), e, st);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,7 +415,7 @@ class AngelWebSocket {
|
||||||
/// Handles an incoming [WebSocketContext].
|
/// Handles an incoming [WebSocketContext].
|
||||||
Future<void> handleClient(WebSocketContext socket) async {
|
Future<void> handleClient(WebSocketContext socket) async {
|
||||||
var origin = socket.request.headers?.value('origin');
|
var origin = socket.request.headers?.value('origin');
|
||||||
if (allowedOrigins != null && !allowedOrigins!.contains(origin)) {
|
if (allowedOrigins.isNotEmpty && !allowedOrigins.contains(origin)) {
|
||||||
throw AngelHttpException.forbidden(
|
throw AngelHttpException.forbidden(
|
||||||
message:
|
message:
|
||||||
'WebSocket connections are not allowed from the origin "$origin".');
|
'WebSocket connections are not allowed from the origin "$origin".');
|
||||||
|
@ -479,8 +481,8 @@ class AngelWebSocket {
|
||||||
throw AngelHttpException.badRequest(
|
throw AngelHttpException.badRequest(
|
||||||
message: 'Missing `sec-websocket-key` header.');
|
message: 'Missing `sec-websocket-key` header.');
|
||||||
} else if (protocol != null &&
|
} else if (protocol != null &&
|
||||||
allowedProtocols != null &&
|
allowedProtocols.isNotEmpty &&
|
||||||
!allowedProtocols!.contains(protocol)) {
|
!allowedProtocols.contains(protocol)) {
|
||||||
throw AngelHttpException.badRequest(
|
throw AngelHttpException.badRequest(
|
||||||
message: 'Disallowed `sec-websocket-protocol` header "$protocol".');
|
message: 'Disallowed `sec-websocket-protocol` header "$protocol".');
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
name: angel3_websocket
|
name: angel3_websocket
|
||||||
version: 4.1.0
|
version: 4.1.1
|
||||||
description: This library provides WebSockets support for Angel3 framework.
|
description: This library provides WebSockets support for Angel3 framework.
|
||||||
homepage: https://angel3-framework.web.app/
|
homepage: https://angel3-framework.web.app/
|
||||||
repository: https://github.com/dukefirehawk/angel/tree/master/packages/websocket
|
repository: https://github.com/dukefirehawk/angel/tree/master/packages/websocket
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.12.0 <3.0.0'
|
sdk: '>=2.12.0 <3.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
angel3_auth: ^4.0.0
|
angel3_auth: ^4.1.0
|
||||||
angel3_client: ^4.0.0
|
angel3_client: ^4.1.0
|
||||||
angel3_framework: ^4.2.0
|
angel3_framework: ^4.2.0
|
||||||
angel3_http_exception: ^3.0.0
|
angel3_http_exception: ^3.0.0
|
||||||
belatuk_merge_map: ^3.0.0
|
belatuk_merge_map: ^3.0.0
|
||||||
|
@ -22,7 +22,7 @@ dev_dependencies:
|
||||||
angel3_model: ^3.1.0
|
angel3_model: ^3.1.0
|
||||||
test: ^1.17.5
|
test: ^1.17.5
|
||||||
lints: ^1.0.0
|
lints: ^1.0.0
|
||||||
#dependency_overrides:
|
dependency_overrides:
|
||||||
# angel3_container:
|
angel3_auth:
|
||||||
# path: ../container/angel_container
|
path: ../auth
|
||||||
|
|
|
@ -9,7 +9,7 @@ import 'package:test/test.dart';
|
||||||
import 'common.dart';
|
import 'common.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
srv.Angel? app;
|
srv.Angel app;
|
||||||
late srv.AngelHttp http;
|
late srv.AngelHttp http;
|
||||||
ws.WebSockets? client;
|
ws.WebSockets? client;
|
||||||
srv.AngelWebSocket websockets;
|
srv.AngelWebSocket websockets;
|
||||||
|
@ -18,17 +18,17 @@ void main() {
|
||||||
|
|
||||||
setUp(() async {
|
setUp(() async {
|
||||||
app = srv.Angel(reflector: const MirrorsReflector());
|
app = srv.Angel(reflector: const MirrorsReflector());
|
||||||
http = srv.AngelHttp(app!, useZone: false);
|
http = srv.AngelHttp(app, useZone: false);
|
||||||
|
|
||||||
websockets = srv.AngelWebSocket(app)
|
websockets = srv.AngelWebSocket(app)
|
||||||
..onData.listen((data) {
|
..onData.listen((data) {
|
||||||
print('Received by server: $data');
|
print('Received by server: $data');
|
||||||
});
|
});
|
||||||
|
|
||||||
await app!.configure(websockets.configureServer);
|
await app.configure(websockets.configureServer);
|
||||||
app!.all('/ws', websockets.handleRequest);
|
app.all('/ws', websockets.handleRequest);
|
||||||
await app!.configure(GameController(websockets).configureServer);
|
await app.configure(GameController(websockets).configureServer);
|
||||||
app!.logger = Logger('angel_auth')..onRecord.listen(print);
|
app.logger = Logger('angel_auth')..onRecord.listen(print);
|
||||||
|
|
||||||
server = await http.startServer();
|
server = await http.startServer();
|
||||||
url = 'ws://${server!.address.address}:${server!.port}/ws';
|
url = 'ws://${server!.address.address}:${server!.port}/ws';
|
||||||
|
@ -53,7 +53,7 @@ void main() {
|
||||||
tearDown(() async {
|
tearDown(() async {
|
||||||
await client!.close();
|
await client!.close();
|
||||||
await http.close();
|
await http.close();
|
||||||
app = null;
|
//app = null;
|
||||||
client = null;
|
client = null;
|
||||||
server = null;
|
server = null;
|
||||||
url = null;
|
url = null;
|
||||||
|
|
|
@ -9,7 +9,7 @@ import 'package:test/test.dart';
|
||||||
import 'common.dart';
|
import 'common.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
srv.Angel? app;
|
srv.Angel app;
|
||||||
late srv.AngelHttp http;
|
late srv.AngelHttp http;
|
||||||
ws.WebSockets? client;
|
ws.WebSockets? client;
|
||||||
srv.AngelWebSocket websockets;
|
srv.AngelWebSocket websockets;
|
||||||
|
@ -19,16 +19,16 @@ void main() {
|
||||||
setUp(() async {
|
setUp(() async {
|
||||||
app = srv.Angel(reflector: MirrorsReflector())
|
app = srv.Angel(reflector: MirrorsReflector())
|
||||||
..use('/api/todos', TodoService());
|
..use('/api/todos', TodoService());
|
||||||
http = srv.AngelHttp(app!, useZone: false);
|
http = srv.AngelHttp(app, useZone: false);
|
||||||
|
|
||||||
websockets = srv.AngelWebSocket(app)
|
websockets = srv.AngelWebSocket(app)
|
||||||
..onData.listen((data) {
|
..onData.listen((data) {
|
||||||
print('Received by server: $data');
|
print('Received by server: $data');
|
||||||
});
|
});
|
||||||
|
|
||||||
await app!.configure(websockets.configureServer);
|
await app.configure(websockets.configureServer);
|
||||||
app!.all('/ws', websockets.handleRequest);
|
app.all('/ws', websockets.handleRequest);
|
||||||
app!.logger = Logger('angel_auth')..onRecord.listen(print);
|
app.logger = Logger('angel_auth')..onRecord.listen(print);
|
||||||
server = await http.startServer();
|
server = await http.startServer();
|
||||||
url = 'ws://${server!.address.address}:${server!.port}/ws';
|
url = 'ws://${server!.address.address}:${server!.port}/ws';
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ void main() {
|
||||||
await client!.close();
|
await client!.close();
|
||||||
await http.server!.close(force: true);
|
await http.server!.close(force: true);
|
||||||
|
|
||||||
app = null;
|
//app = null;
|
||||||
client = null;
|
client = null;
|
||||||
server = null;
|
server = null;
|
||||||
url = null;
|
url = null;
|
||||||
|
|
Loading…
Reference in a new issue