Fixed bug for Auth
This commit is contained in:
parent
7f3eba8538
commit
e5743b95e2
11 changed files with 219 additions and 21 deletions
|
@ -10,7 +10,7 @@
|
||||||
* Updated: angel3_container_generator
|
* Updated: angel3_container_generator
|
||||||
* Updated: angel3_mock_request
|
* Updated: angel3_mock_request
|
||||||
* Updated: angel3_framework
|
* Updated: angel3_framework
|
||||||
* Updated: angel3_auth (4 failed test cases)
|
* Updated: angel3_auth (1 failed test cases)
|
||||||
* Updated: angel3_configuration
|
* Updated: angel3_configuration
|
||||||
* Updated: angel3_validate
|
* Updated: angel3_validate
|
||||||
* Updated: angel3_client (1 failed test cases)
|
* Updated: angel3_client (1 failed test cases)
|
||||||
|
@ -49,7 +49,7 @@
|
||||||
* Updated: angel3_auth_oauth2 (issue: oauth2 don't support http 1.0.0)
|
* Updated: angel3_auth_oauth2 (issue: oauth2 don't support http 1.0.0)
|
||||||
* Updated: angel3_auth_twitter (issue: oauth2 don't support http 1.0.0)
|
* Updated: angel3_auth_twitter (issue: oauth2 don't support http 1.0.0)
|
||||||
* Updated: angel3_mongo (issue: mongo_dart don't support http 1.0.0)
|
* Updated: angel3_mongo (issue: mongo_dart don't support http 1.0.0)
|
||||||
* Updated: angel3_markdown (issue: markdown don't support file 7.0.0)
|
* Updated: angel3_markdown (issue: basic_utils don't support http 1.0.0)
|
||||||
* Updated: angel3_shelf (issue: 2 failed test cases)
|
* Updated: angel3_shelf (issue: 2 failed test cases)
|
||||||
|
|
||||||
## 7.0.0
|
## 7.0.0
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
|
|
||||||
* Require Dart >= 3.0
|
* Require Dart >= 3.0
|
||||||
* Upgraded `http` to 1.0.0
|
* Upgraded `http` to 1.0.0
|
||||||
|
* Fixed bug causing `successRedirect` test case to fail
|
||||||
|
* Fixed bug causing `failureRedirect` test case to fail
|
||||||
|
* Fixed bug causing `login` test case to fail
|
||||||
|
* Added `example1` and `example2`
|
||||||
|
|
||||||
## 7.0.1
|
## 7.0.1
|
||||||
|
|
||||||
|
|
8
packages/auth/example/client/example1.http
Normal file
8
packages/auth/example/client/example1.http
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
### Load landing page
|
||||||
|
GET http://localhost:3000/ HTTP/1.1
|
||||||
|
|
||||||
|
### Success redirect
|
||||||
|
POST http://localhost:3000/login HTTP/1.1
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Basic jdoe1:password
|
||||||
|
|
8
packages/auth/example/client/example2.http
Normal file
8
packages/auth/example/client/example2.http
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
### Load landing page
|
||||||
|
GET http://localhost:3000/ HTTP/1.1
|
||||||
|
|
||||||
|
### Failure redirect
|
||||||
|
POST http://localhost:3000/login HTTP/1.1
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Basic password:username
|
||||||
|
|
113
packages/auth/example/example1.dart
Normal file
113
packages/auth/example/example1.dart
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
import 'package:angel3_auth/angel3_auth.dart';
|
||||||
|
import 'package:angel3_container/mirrors.dart';
|
||||||
|
import 'package:angel3_framework/angel3_framework.dart';
|
||||||
|
import 'package:angel3_framework/http.dart';
|
||||||
|
import 'package:collection/collection.dart' show IterableExtension;
|
||||||
|
import 'package:io/ansi.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
|
|
||||||
|
class User extends Model {
|
||||||
|
String? username, password;
|
||||||
|
|
||||||
|
User({this.username, this.password});
|
||||||
|
|
||||||
|
static User parse(Map<String, dynamic> map) {
|
||||||
|
return User(
|
||||||
|
username: map['username'],
|
||||||
|
password: map['password'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'id': id,
|
||||||
|
'username': username,
|
||||||
|
'password': password,
|
||||||
|
'created_at': createdAt?.toIso8601String(),
|
||||||
|
'updated_at': updatedAt?.toIso8601String()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Backend for callback test cases
|
||||||
|
*/
|
||||||
|
void main() async {
|
||||||
|
hierarchicalLoggingEnabled = true;
|
||||||
|
|
||||||
|
Angel app = Angel(reflector: MirrorsReflector());
|
||||||
|
AngelHttp angelHttp = AngelHttp(app);
|
||||||
|
app.use('/users', MapService());
|
||||||
|
|
||||||
|
var oldErrorHandler = app.errorHandler;
|
||||||
|
app.errorHandler = (e, req, res) {
|
||||||
|
app.logger.severe(e.message, e, e.stackTrace ?? StackTrace.current);
|
||||||
|
return oldErrorHandler(e, req, res);
|
||||||
|
};
|
||||||
|
|
||||||
|
app.logger = Logger('angel3_auth')
|
||||||
|
..level = Level.FINEST
|
||||||
|
..onRecord.listen((rec) {
|
||||||
|
print(rec);
|
||||||
|
|
||||||
|
if (rec.error != null) {
|
||||||
|
print(yellow.wrap(rec.error.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rec.stackTrace != null) {
|
||||||
|
print(yellow.wrap(rec.stackTrace.toString()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await app
|
||||||
|
.findService('users')
|
||||||
|
?.create({'username': 'jdoe1', 'password': 'password'});
|
||||||
|
|
||||||
|
var auth = AngelAuth<User>(
|
||||||
|
serializer: (u) => u.id ?? '',
|
||||||
|
deserializer: (id) async =>
|
||||||
|
await app.findService('users')?.read(id) as User);
|
||||||
|
//auth.serializer = (u) => u.id;
|
||||||
|
//auth.deserializer =
|
||||||
|
// (id) async => await app.findService('users')!.read(id) as User;
|
||||||
|
|
||||||
|
await app.configure(auth.configureServer);
|
||||||
|
|
||||||
|
auth.strategies['local'] = LocalAuthStrategy((username, password) async {
|
||||||
|
var users = await app
|
||||||
|
.findService('users')
|
||||||
|
?.index()
|
||||||
|
.then((it) => it.map<User>((m) => User.parse(m)).toList());
|
||||||
|
|
||||||
|
var result = users?.firstWhereOrNull(
|
||||||
|
(user) => user.username == username && user.password == password);
|
||||||
|
|
||||||
|
return Future.value(result);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.post(
|
||||||
|
'/login',
|
||||||
|
auth.authenticate('local', AngelAuthOptions(callback: (req, res, token) {
|
||||||
|
res
|
||||||
|
..write('Hello!')
|
||||||
|
..close();
|
||||||
|
})));
|
||||||
|
|
||||||
|
app.get('/', (req, res) => res.write("Hello"));
|
||||||
|
|
||||||
|
app.chain([
|
||||||
|
(req, res) {
|
||||||
|
if (!req.container!.has<User>()) {
|
||||||
|
req.container!.registerSingleton<User>(
|
||||||
|
User(username: req.params['name']?.toString()));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
]).post(
|
||||||
|
'/existing/:name',
|
||||||
|
auth.authenticate('local'),
|
||||||
|
);
|
||||||
|
|
||||||
|
await angelHttp.startServer('127.0.0.1', 3000);
|
||||||
|
}
|
62
packages/auth/example/example2.dart
Normal file
62
packages/auth/example/example2.dart
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:angel3_auth/angel3_auth.dart';
|
||||||
|
import 'package:angel3_container/mirrors.dart';
|
||||||
|
import 'package:angel3_framework/angel3_framework.dart';
|
||||||
|
import 'package:angel3_framework/http.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
|
final Map<String, String> sampleUser = {'hello': 'world'};
|
||||||
|
|
||||||
|
final AngelAuth<Map<String, String>> auth = AngelAuth<Map<String, String>>(
|
||||||
|
serializer: (user) async => '1337', deserializer: (id) async => sampleUser);
|
||||||
|
//var headers = <String, String>{'accept': 'application/json'};
|
||||||
|
var localOpts = AngelAuthOptions<Map<String, String>>(
|
||||||
|
failureRedirect: '/failure', successRedirect: '/success');
|
||||||
|
var localOpts2 =
|
||||||
|
AngelAuthOptions<Map<String, String>>(canRespondWithJson: false);
|
||||||
|
|
||||||
|
Future<Map<String, String>> verifier(String? username, String? password) async {
|
||||||
|
if (username == 'username' && password == 'password') {
|
||||||
|
return sampleUser;
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future wireAuth(Angel app) async {
|
||||||
|
auth.strategies['local'] = LocalAuthStrategy(verifier);
|
||||||
|
await app.configure(auth.configureServer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
Angel app = Angel(reflector: MirrorsReflector());
|
||||||
|
AngelHttp angelHttp = AngelHttp(app, useZone: false);
|
||||||
|
await app.configure(wireAuth);
|
||||||
|
|
||||||
|
app.get('/hello', (req, res) {
|
||||||
|
// => 'Woo auth'
|
||||||
|
return 'Woo auth';
|
||||||
|
}, middleware: [auth.authenticate('local', localOpts2)]);
|
||||||
|
|
||||||
|
app.post('/login', (req, res) => 'This should not be shown',
|
||||||
|
middleware: [auth.authenticate('local', localOpts)]);
|
||||||
|
|
||||||
|
app.get('/success', (req, res) => 'yep', middleware: [
|
||||||
|
requireAuthentication<Map<String, String>>(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
app.get('/failure', (req, res) => 'nope');
|
||||||
|
|
||||||
|
app.logger = Logger('local_test')
|
||||||
|
..onRecord.listen((rec) {
|
||||||
|
print(
|
||||||
|
'${rec.time}: ${rec.level.name}: ${rec.loggerName}: ${rec.message}');
|
||||||
|
|
||||||
|
if (rec.error != null) {
|
||||||
|
print(rec.error);
|
||||||
|
print(rec.stackTrace);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await angelHttp.startServer('127.0.0.1', 3000);
|
||||||
|
}
|
|
@ -66,7 +66,8 @@ class LocalAuthStrategy<User> extends AuthStrategy<User> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return verificationResult;
|
// Allow non-null to pass through
|
||||||
|
//return verificationResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ class User extends Model {
|
||||||
|
|
||||||
User({this.username, this.password});
|
User({this.username, this.password});
|
||||||
|
|
||||||
static User parse(Map map) {
|
static User parse(Map<String, dynamic> map) {
|
||||||
return User(
|
return User(
|
||||||
username: map['username'] as String?,
|
username: map['username'] as String?,
|
||||||
password: map['password'] as String?,
|
password: map['password'] as String?,
|
||||||
|
@ -41,6 +41,7 @@ void main() {
|
||||||
http.Client? client;
|
http.Client? client;
|
||||||
HttpServer server;
|
HttpServer server;
|
||||||
String? url;
|
String? url;
|
||||||
|
String? encodedAuth;
|
||||||
|
|
||||||
setUp(() async {
|
setUp(() async {
|
||||||
hierarchicalLoggingEnabled = true;
|
hierarchicalLoggingEnabled = true;
|
||||||
|
@ -54,7 +55,7 @@ void main() {
|
||||||
return oldErrorHandler(e, req, res);
|
return oldErrorHandler(e, req, res);
|
||||||
};
|
};
|
||||||
|
|
||||||
app.logger = Logger('angel_auth')
|
app.logger = Logger('angel3_auth')
|
||||||
..level = Level.FINEST
|
..level = Level.FINEST
|
||||||
..onRecord.listen((rec) {
|
..onRecord.listen((rec) {
|
||||||
print(rec);
|
print(rec);
|
||||||
|
@ -86,7 +87,7 @@ void main() {
|
||||||
var users = await app
|
var users = await app
|
||||||
.findService('users')
|
.findService('users')
|
||||||
?.index()
|
?.index()
|
||||||
.then((it) => it.map<User>((m) => User.parse(m as Map)).toList());
|
.then((it) => it.map<User>((m) => User.parse(m)).toList());
|
||||||
|
|
||||||
var result = users?.firstWhereOrNull(
|
var result = users?.firstWhereOrNull(
|
||||||
(user) => user.username == username && user.password == password);
|
(user) => user.username == username && user.password == password);
|
||||||
|
@ -116,6 +117,8 @@ void main() {
|
||||||
auth.authenticate('local'),
|
auth.authenticate('local'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
encodedAuth = base64.encode(utf8.encode('jdoe1:password'));
|
||||||
|
|
||||||
client = http.Client();
|
client = http.Client();
|
||||||
server = await angelHttp.startServer();
|
server = await angelHttp.startServer();
|
||||||
url = 'http://${server.address.address}:${server.port}';
|
url = 'http://${server.address.address}:${server.port}';
|
||||||
|
@ -131,7 +134,7 @@ void main() {
|
||||||
|
|
||||||
test('login', () async {
|
test('login', () async {
|
||||||
final response = await client!.post(Uri.parse('$url/login'),
|
final response = await client!.post(Uri.parse('$url/login'),
|
||||||
body: {'username': 'jdoe1', 'password': 'password'});
|
headers: {'Authorization': 'Basic $encodedAuth'});
|
||||||
print('Response: ${response.body}');
|
print('Response: ${response.body}');
|
||||||
expect(response.body, equals('Hello!'));
|
expect(response.body, equals('Hello!'));
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:angel3_auth/angel3_auth.dart';
|
import 'package:angel3_auth/angel3_auth.dart';
|
||||||
|
import 'package:angel3_container/mirrors.dart';
|
||||||
import 'package:angel3_framework/angel3_framework.dart';
|
import 'package:angel3_framework/angel3_framework.dart';
|
||||||
import 'package:angel3_framework/http.dart';
|
import 'package:angel3_framework/http.dart';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
@ -9,7 +10,7 @@ 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');
|
||||||
var localOpts2 =
|
var localOpts2 =
|
||||||
|
@ -42,7 +43,7 @@ void main() async {
|
||||||
|
|
||||||
setUp(() async {
|
setUp(() async {
|
||||||
client = http.Client();
|
client = http.Client();
|
||||||
app = Angel();
|
app = Angel(reflector: MirrorsReflector());
|
||||||
angelHttp = AngelHttp(app, useZone: false);
|
angelHttp = AngelHttp(app, useZone: false);
|
||||||
await app.configure(wireAuth);
|
await app.configure(wireAuth);
|
||||||
app.get('/hello', (req, res) {
|
app.get('/hello', (req, res) {
|
||||||
|
@ -88,19 +89,22 @@ void main() async {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('successRedirect', () async {
|
test('successRedirect', () async {
|
||||||
var postData = {'username': 'username', 'password': 'password'};
|
//var postData = {'username': 'username', 'password': 'password'};
|
||||||
|
var encodedAuth = base64.encode(utf8.encode('username:password'));
|
||||||
|
|
||||||
var response = await client.post(Uri.parse('$url/login'),
|
var response = await client.post(Uri.parse('$url/login'),
|
||||||
body: json.encode(postData),
|
headers: {'Authorization': 'Basic $encodedAuth'});
|
||||||
headers: {'content-type': 'application/json'});
|
|
||||||
expect(response.statusCode, equals(302));
|
expect(response.statusCode, equals(302));
|
||||||
expect(response.headers['location'], equals('/success'));
|
expect(response.headers['location'], equals('/success'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('failureRedirect', () async {
|
test('failureRedirect', () async {
|
||||||
var postData = {'username': 'password', 'password': 'username'};
|
//var postData = {'username': 'password', 'password': 'username'};
|
||||||
|
var encodedAuth = base64.encode(utf8.encode('password:username'));
|
||||||
|
|
||||||
var response = await client.post(Uri.parse('$url/login'),
|
var response = await client.post(Uri.parse('$url/login'),
|
||||||
body: json.encode(postData),
|
//body: json.encode(postData),
|
||||||
headers: {'content-type': 'application/json'});
|
headers: {'Authorization': 'Basic $encodedAuth'});
|
||||||
print('Status Code: ${response.statusCode}');
|
print('Status Code: ${response.statusCode}');
|
||||||
print(response.headers);
|
print(response.headers);
|
||||||
print(response.body);
|
print(response.body);
|
||||||
|
|
|
@ -79,11 +79,6 @@ class MapService extends Service<String?, Map<String, dynamic>> {
|
||||||
@override
|
@override
|
||||||
Future<Map<String, dynamic>> create(Map<String, dynamic> data,
|
Future<Map<String, dynamic>> create(Map<String, dynamic> data,
|
||||||
[Map<String, dynamic>? params]) {
|
[Map<String, dynamic>? params]) {
|
||||||
//if (data is! Map) {
|
|
||||||
// throw AngelHttpException.badRequest(
|
|
||||||
// message:
|
|
||||||
// 'MapService does not support `create` with ${data.runtimeType}.');
|
|
||||||
//}
|
|
||||||
var now = DateTime.now().toIso8601String();
|
var now = DateTime.now().toIso8601String();
|
||||||
var result = Map<String, dynamic>.from(data);
|
var result = Map<String, dynamic>.from(data);
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ environment:
|
||||||
sdk: '>=3.0.0 <4.0.0'
|
sdk: '>=3.0.0 <4.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
angel3_framework: ^8.0.0
|
angel3_framework: ^8.0.0
|
||||||
file: ^6.1.2
|
file: ^7.0.0
|
||||||
markdown: ^7.1.0
|
markdown: ^7.1.0
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
angel3_test: ^8.0.0
|
angel3_test: ^8.0.0
|
||||||
|
|
Loading…
Reference in a new issue