From f1ce32d07ee983f8b53630a10b56a77687202290 Mon Sep 17 00:00:00 2001 From: thosakwe Date: Tue, 28 Mar 2017 21:52:19 -0400 Subject: [PATCH] 1.0.4 --- README.md | 36 +++++++++++++++++++++++++++++++++++- dart_test.yaml | 1 + lib/angel_client.dart | 3 +++ lib/base_angel_client.dart | 25 +++++++++++++++++-------- lib/browser.dart | 13 +++++++++++-- pubspec.yaml | 2 +- test/browser_test.dart | 6 ++---- test/for_browser_tests.dart | 8 ++++---- 8 files changed, 74 insertions(+), 20 deletions(-) create mode 100644 dart_test.yaml diff --git a/README.md b/README.md index cfedff33..d6061ae3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # angel_client -[![pub 1.0.3](https://img.shields.io/badge/pub-1.0.3-brightgreen.svg)](https://pub.dartlang.org/packages/angel_client) +[![pub 1.0.4](https://img.shields.io/badge/pub-1.0.4-brightgreen.svg)](https://pub.dartlang.org/packages/angel_client) [![build status](https://travis-ci.org/angel-dart/client.svg)](https://travis-ci.org/angel-dart/client) Client library for the Angel framework. @@ -54,3 +54,37 @@ bar() async { Just like on the server, services support `index`, `read`, `create`, `modify`, `update` and `remove`. + +## Authentication +Local auth: +```dart +var auth = await app.authenticate(type: 'local', credentials: {username: ..., password: ...}); +print(auth.token); +print(auth.user); +``` + +Revive an existing jwt: +```dart +Future reviveJwt(String jwt) { + return app.authenticate(credentials: {'token': jwt}); +} +``` + +Via Popup: +```dart +app.authenticateViaPopup('/auth/google').listen((jwt) { + // Do something with the JWT +}); +``` + +Resume a session from localStorage (browser only): +```dart +// Automatically checks for JSON-encoded 'token' in localStorage, +// and tries to revive it +await app.authenticate(); +``` + +Logout: +```dart +await app.logout(); +``` \ No newline at end of file diff --git a/dart_test.yaml b/dart_test.yaml new file mode 100644 index 00000000..c81b6f17 --- /dev/null +++ b/dart_test.yaml @@ -0,0 +1 @@ +# platforms: [vm, content-shell] \ No newline at end of file diff --git a/lib/angel_client.dart b/lib/angel_client.dart index 00acef77..2061f125 100644 --- a/lib/angel_client.dart +++ b/lib/angel_client.dart @@ -38,6 +38,9 @@ abstract class Angel { await configurer(this); } + /// Logs the current user out of the application. + Future logout(); + Service service(String path, {Type type, AngelDeserializer deserializer}); Future delete(String url, {Map headers}); diff --git a/lib/base_angel_client.dart b/lib/base_angel_client.dart index 73e56a49..7fadd73a 100644 --- a/lib/base_angel_client.dart +++ b/lib/base_angel_client.dart @@ -28,6 +28,11 @@ _buildQuery(Map params) { return '?' + query.join('&'); } +bool _invalid(http.Response response) => + response.statusCode == null || + response.statusCode < 200 || + response.statusCode >= 300; + AngelHttpException failure(http.Response response, {error, StackTrace stack}) { try { final json = JSON.decode(response.body); @@ -68,7 +73,7 @@ abstract class BaseAngelClient extends Angel { }); try { - if (response.statusCode != 200) { + if (_invalid(response)) { throw failure(response); } @@ -98,7 +103,7 @@ abstract class BaseAngelClient extends Angel { } try { - if (response.statusCode != 200) { + if (_invalid(response)) { throw failure(response); } @@ -123,6 +128,10 @@ abstract class BaseAngelClient extends Angel { client.close(); } + Future logout() async { + authToken = null; + } + /// Sends a non-streaming [Request] and returns a non-streaming [Response]. Future sendUnstreamed( String method, url, Map headers, @@ -230,7 +239,7 @@ class BaseAngelService extends Service { 'GET', '$basePath${_buildQuery(params)}', _readHeaders); try { - if (response.statusCode != 200) { + if (_invalid(response)) { throw failure(response); } @@ -248,7 +257,7 @@ class BaseAngelService extends Service { 'GET', '$basePath/$id${_buildQuery(params)}', _readHeaders); try { - if (response.statusCode != 200) { + if (_invalid(response)) { throw failure(response); } @@ -264,7 +273,7 @@ class BaseAngelService extends Service { '$basePath/${_buildQuery(params)}', _writeHeaders, makeBody(data)); try { - if (response.statusCode != 200) { + if (_invalid(response)) { throw failure(response); } @@ -280,7 +289,7 @@ class BaseAngelService extends Service { '$basePath/$id${_buildQuery(params)}', _writeHeaders, makeBody(data)); try { - if (response.statusCode != 200) { + if (_invalid(response)) { throw failure(response); } @@ -296,7 +305,7 @@ class BaseAngelService extends Service { '$basePath/$id${_buildQuery(params)}', _writeHeaders, makeBody(data)); try { - if (response.statusCode != 200) { + if (_invalid(response)) { throw failure(response); } @@ -312,7 +321,7 @@ class BaseAngelService extends Service { 'DELETE', '$basePath/$id${_buildQuery(params)}', _readHeaders); try { - if (response.statusCode != 200) { + if (_invalid(response)) { throw failure(response); } diff --git a/lib/browser.dart b/lib/browser.dart index a506c624..a47150c7 100644 --- a/lib/browser.dart +++ b/lib/browser.dart @@ -6,7 +6,7 @@ import 'dart:convert' show JSON; import 'dart:html' show CustomEvent, window; import 'package:http/browser_client.dart' as http; import 'angel_client.dart'; -import 'auth_types.dart' as auth_types; +// import 'auth_types.dart' as auth_types; import 'base_angel_client.dart'; export 'angel_client.dart'; @@ -53,13 +53,15 @@ class Rest extends BaseAngelClient { var ctrl = new StreamController(); var wnd = window.open(url, 'angel_client_auth_popup'); - new Timer.periodic(new Duration(milliseconds: 500), (timer) { + Timer t; + t = new Timer.periodic(new Duration(milliseconds: 500), (timer) { if (!ctrl.isClosed) { if (wnd.closed) { ctrl.addError(new AngelHttpException.notAuthenticated( message: errorMessage ?? 'Authentication via popup window failed.')); ctrl.close(); + timer.cancel(); } } else timer.cancel(); @@ -68,10 +70,17 @@ class Rest extends BaseAngelClient { window.on[eventName ?? 'token'].listen((CustomEvent e) { if (!ctrl.isClosed) { ctrl.add(e.detail); + t.cancel(); ctrl.close(); } }); return ctrl.stream; } + + @override + Future logout() { + window.localStorage.remove('token'); + return super.logout(); + } } diff --git a/pubspec.yaml b/pubspec.yaml index 7c910e01..963444d6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: angel_client -version: 1.0.3 +version: 1.0.4 description: Client library for the Angel framework. author: Tobe O homepage: https://github.com/angel-dart/angel_client diff --git a/test/browser_test.dart b/test/browser_test.dart index 8eb28db9..c6b71bac 100644 --- a/test/browser_test.dart +++ b/test/browser_test.dart @@ -6,8 +6,7 @@ import 'for_browser_tests.dart'; main() { test("list todos", () async { var channel = spawnHybridCode(SERVER); - int port = await channel.stream.first; - var url = "http://localhost:$port"; + String url = await channel.stream.first; print(url); var app = new Rest(url); var todoService = app.service("todos"); @@ -18,8 +17,7 @@ main() { test('create todos', () async { var channel = spawnHybridCode(SERVER); - int port = await channel.stream.first; - var url = "http://localhost:$port"; + String url = await channel.stream.first; print(url); var app = new Rest(url); var todoService = app.service("todos"); diff --git a/test/for_browser_tests.dart b/test/for_browser_tests.dart index e23cb79a..12378097 100644 --- a/test/for_browser_tests.dart +++ b/test/for_browser_tests.dart @@ -1,7 +1,7 @@ const String SERVER = ''' import 'dart:io'; import "package:angel_framework/angel_framework.dart"; -import "package:angel_framework/src/defs.dart"; +import "package:angel_framework/common.dart"; import 'package:stream_channel/stream_channel.dart'; hybridMain(StreamChannel channel) async { @@ -12,15 +12,15 @@ hybridMain(StreamChannel channel) async { return true; }); - app.use("/todos", new MemoryService()); + app.use("/todos", new TypedService(new MapService())); var server = await app.startServer(InternetAddress.LOOPBACK_IP_V4, 0); print("Server up; listening at http://localhost:\${server.port}"); - channel.sink.add(server.port); + channel.sink.add('http://\${server.address.address}:\${server.port}'); } -class Todo extends MemoryModel { +class Todo extends Model { String hello; Todo({int id, this.hello}) {