This commit is contained in:
thosakwe 2017-03-28 21:52:19 -04:00
parent 3564fb4e35
commit f1ce32d07e
8 changed files with 74 additions and 20 deletions

View file

@ -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<AngelAuthResult> 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();
```

1
dart_test.yaml Normal file
View file

@ -0,0 +1 @@
# platforms: [vm, content-shell]

View file

@ -38,6 +38,9 @@ abstract class Angel {
await configurer(this);
}
/// Logs the current user out of the application.
Future logout();
Service service<T>(String path, {Type type, AngelDeserializer deserializer});
Future<http.Response> delete(String url, {Map<String, String> headers});

View file

@ -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<http.Response> sendUnstreamed(
String method, url, Map<String, String> 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);
}

View file

@ -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<String>();
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();
}
}

View file

@ -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 <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/angel_client

View file

@ -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");

View file

@ -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<Todo>());
app.use("/todos", new TypedService<Todo>(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}) {