Updated client
This commit is contained in:
parent
6dbc1f5b9a
commit
38cc17e381
8 changed files with 85 additions and 5 deletions
|
@ -1,6 +1,11 @@
|
|||
|
||||
# Change Log
|
||||
|
||||
## 4.0.2
|
||||
|
||||
* Added logging
|
||||
* Added unit test for authentication
|
||||
|
||||
## 4.0.1
|
||||
|
||||
* Updated README
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# Angel3 Client
|
||||
|
||||
[![version](https://img.shields.io/badge/pub-v4.0.1-brightgreen)](https://pub.dartlang.org/packages/angel3_client)
|
||||
[![version](https://img.shields.io/badge/pub-v4.0.2-brightgreen)](https://pub.dartlang.org/packages/angel3_client)
|
||||
[![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/client/LICENSE)
|
||||
|
||||
A browser, mobile and command line based client that supports querying Angel3 servers
|
||||
A browser, mobile and command line based client that supports querying Angel3 backend.
|
||||
|
||||
## Usage
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'dart:async';
|
|||
import 'package:collection/collection.dart';
|
||||
import 'dart:convert';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:logging/logging.dart';
|
||||
export 'package:angel3_http_exception/angel3_http_exception.dart';
|
||||
|
||||
/// A function that configures an [Angel] client in some way.
|
||||
|
@ -18,6 +19,8 @@ typedef AngelDeserializer<T> = T? Function(dynamic x);
|
|||
|
||||
/// Represents an Angel server that we are querying.
|
||||
abstract class Angel extends http.BaseClient {
|
||||
final _log = Logger('Angel');
|
||||
|
||||
/// A mutable member. When this is set, it holds a JSON Web Token
|
||||
/// that is automatically attached to every request sent.
|
||||
///
|
||||
|
|
|
@ -8,6 +8,7 @@ import 'package:http/src/request.dart' as http;
|
|||
import 'package:http/src/response.dart' as http;
|
||||
import 'package:http/src/streamed_response.dart' as http;
|
||||
import 'package:path/path.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'angel3_client.dart';
|
||||
|
||||
const Map<String, String> _readHeaders = {'Accept': 'application/json'};
|
||||
|
@ -47,6 +48,7 @@ AngelHttpException failure(http.Response response,
|
|||
}
|
||||
|
||||
abstract class BaseAngelClient extends Angel {
|
||||
final _log = Logger('BaseAngelClient');
|
||||
final StreamController<AngelAuthResult> _onAuthenticated =
|
||||
StreamController<AngelAuthResult>();
|
||||
final List<Service> _services = [];
|
||||
|
@ -89,6 +91,8 @@ abstract class BaseAngelClient extends Angel {
|
|||
|
||||
try {
|
||||
//var v = json.decode(response.body);
|
||||
_log.info(response.headers);
|
||||
|
||||
var v = jsonDecode(response.body);
|
||||
|
||||
if (v is! Map || !v.containsKey('data') || !v.containsKey('token')) {
|
||||
|
@ -102,6 +106,7 @@ abstract class BaseAngelClient extends Angel {
|
|||
} on AngelHttpException {
|
||||
rethrow;
|
||||
} catch (e, st) {
|
||||
_log.severe('Authentication failed');
|
||||
throw failure(response, error: e, stack: st);
|
||||
}
|
||||
}
|
||||
|
@ -147,6 +152,7 @@ abstract class BaseAngelClient extends Angel {
|
|||
request.bodyFields =
|
||||
body.map((k, v) => MapEntry(k, v is String ? v : v.toString()));
|
||||
} else {
|
||||
_log.severe('Body is not a String, List<int>, or Map<String, String>');
|
||||
throw ArgumentError.value(body, 'body',
|
||||
'must be a String, List<int>, or Map<String, String>.');
|
||||
}
|
||||
|
|
|
@ -5,12 +5,14 @@ import 'dart:async';
|
|||
import 'package:http/http.dart' as http;
|
||||
import 'package:angel3_json_god/angel3_json_god.dart' as god;
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:logging/logging.dart';
|
||||
import 'angel3_client.dart';
|
||||
import 'base_angel_client.dart';
|
||||
export 'angel3_client.dart';
|
||||
|
||||
/// Queries an Angel server via REST.
|
||||
class Rest extends BaseAngelClient {
|
||||
//final _log = Logger('REST');
|
||||
final List<Service> _services = [];
|
||||
|
||||
Rest(String path) : super(http.Client() as http.BaseClient, path);
|
||||
|
@ -42,6 +44,8 @@ class Rest extends BaseAngelClient {
|
|||
|
||||
/// Queries an Angel service via REST.
|
||||
class RestService<Id, Data> extends BaseAngelService<Id, Data> {
|
||||
final _log = Logger('RestService');
|
||||
|
||||
final Type? type;
|
||||
|
||||
RestService(http.BaseClient client, BaseAngelClient app, url, this.type)
|
||||
|
@ -49,7 +53,7 @@ class RestService<Id, Data> extends BaseAngelService<Id, Data> {
|
|||
|
||||
@override
|
||||
Data? deserialize(x) {
|
||||
print(x);
|
||||
_log.info(x);
|
||||
if (type != null) {
|
||||
return x.runtimeType == type
|
||||
? x as Data?
|
||||
|
@ -61,7 +65,7 @@ class RestService<Id, Data> extends BaseAngelService<Id, Data> {
|
|||
|
||||
@override
|
||||
String makeBody(x) {
|
||||
print(x);
|
||||
_log.info(x);
|
||||
if (type != null) {
|
||||
return super.makeBody(god.serializeObject(x));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: angel3_client
|
||||
version: 4.0.1
|
||||
version: 4.0.2
|
||||
description: A browser, mobile and command line based client that supports querying Angel3 servers
|
||||
homepage: https://angel3-framework.web.app/
|
||||
repository: https://github.com/dukefirehawk/angel/tree/angel3/packages/client
|
||||
|
@ -12,11 +12,13 @@ dependencies:
|
|||
http: ^0.13.1
|
||||
meta: ^1.3.0
|
||||
path: ^1.8.0
|
||||
logging: ^1.0.0
|
||||
dev_dependencies:
|
||||
angel3_framework: ^4.0.0
|
||||
angel3_model: ^3.0.0
|
||||
angel3_mock_request: ^2.0.0
|
||||
angel3_container: ^3.0.0
|
||||
angel3_auth: ^4.0.0
|
||||
async: ^2.6.1
|
||||
build_runner: ^1.12.2
|
||||
build_web_compilers: ^2.16.5
|
||||
|
|
|
@ -76,6 +76,7 @@ void main() {
|
|||
test('credentials send right body', () async {
|
||||
await app
|
||||
.authenticate(type: 'local', credentials: {'username': 'password'});
|
||||
print(app.client.spec?.headers);
|
||||
expect(
|
||||
await read(app.client.spec!.request.finalize()),
|
||||
json.encode({'username': 'password'}),
|
||||
|
|
59
packages/client/test/auth_test.dart
Normal file
59
packages/client/test/auth_test.dart
Normal file
|
@ -0,0 +1,59 @@
|
|||
import 'package:angel3_auth/angel3_auth.dart';
|
||||
import 'package:angel3_client/io.dart' as c;
|
||||
import 'package:angel3_framework/angel3_framework.dart';
|
||||
import 'package:angel3_framework/http.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
const Map<String, String> USER = {'username': 'foo', 'password': 'bar'};
|
||||
var localOpts = AngelAuthOptions<Map<String, String>>(canRespondWithJson: true);
|
||||
|
||||
void main() {
|
||||
late Angel app;
|
||||
late AngelHttp http;
|
||||
late c.Angel client;
|
||||
|
||||
setUp(() async {
|
||||
app = Angel();
|
||||
http = AngelHttp(app, useZone: false);
|
||||
var auth = AngelAuth(
|
||||
serializer: (_) async => 'baz', deserializer: (_) async => USER);
|
||||
|
||||
auth.strategies['local'] = LocalAuthStrategy(
|
||||
(username, password) async {
|
||||
if (username == 'foo' && password == 'bar') {
|
||||
return USER;
|
||||
}
|
||||
|
||||
return {};
|
||||
},
|
||||
);
|
||||
|
||||
app.post('/auth/local', auth.authenticate('local', localOpts));
|
||||
|
||||
await app.configure(auth.configureServer);
|
||||
|
||||
app.logger = Logger('auth_test')
|
||||
..onRecord.listen((rec) {
|
||||
print(
|
||||
'${rec.time}: ${rec.level.name}: ${rec.loggerName}: ${rec.message}');
|
||||
});
|
||||
|
||||
var server = await http.startServer();
|
||||
|
||||
client = c.Rest('http://${server.address.address}:${server.port}');
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
http.close();
|
||||
client.close();
|
||||
});
|
||||
|
||||
test('auth event fires', () async {
|
||||
var localAuth = await client.authenticate(type: 'local', credentials: USER);
|
||||
print('JWT: ${localAuth.token}');
|
||||
print('Data: ${localAuth.data}');
|
||||
|
||||
expect(localAuth.data, USER);
|
||||
});
|
||||
}
|
Loading…
Reference in a new issue