This commit is contained in:
thosakwe 2017-03-05 08:46:18 -05:00
parent 84bcb05fdd
commit cbddcc72a4
3 changed files with 28 additions and 42 deletions

View file

@ -4,7 +4,7 @@ import 'package:angel_framework/common.dart';
class User extends Model {
String email, username, password, salt;
final List<String> roles = [];
List<String> roles;
User(
{String id,
@ -12,8 +12,7 @@ class User extends Model {
this.username,
this.password,
this.salt,
Iterable<String> roles: const []}) {
this.roles: const []}) {
this.id = id;
this.roles.addAll(roles ?? []);
}
}

View file

@ -7,11 +7,16 @@ import '../../services/user.dart';
class AuthController extends Controller {
AngelAuth auth;
deserializer(String id) async => app.service('api/users').read(id);
/// Clients will see the result of `deserializer`, so let's pretend to be a client.
///
/// Our User service is already wired to remove sensitive data from serialized JSON.
deserializer(String id) async =>
app.service('api/users').read(id, {'provider': Providers.VIA_REST});
serializer(User user) async => user.id;
/// Attempt to log a user in
LocalAuthVerifier localVerifier(UserService userService) {
LocalAuthVerifier localVerifier(Service userService) {
return (String username, String password) async {
List<User> users = await userService.index({
'query': {'username': username}
@ -32,8 +37,8 @@ class AuthController extends Controller {
auth = new AngelAuth(jwtKey: app.jwt_secret)
..serializer = serializer
..deserializer = deserializer
..strategies.add(new LocalAuthStrategy(
localVerifier(app.container.make(UserService))));
..strategies
.add(new LocalAuthStrategy(localVerifier(app.service('api/users'))));
await super.call(app);
await app.configure(auth);
@ -41,9 +46,4 @@ class AuthController extends Controller {
@Expose('/local', method: 'POST')
login() => auth.authenticate('local');
@Expose('/register', method: 'POST')
register(RequestContext req, UserService userService) async {
// And your registration logic...
}
}

View file

@ -1,4 +1,5 @@
import 'package:angel_common/angel_common.dart';
import 'package:angel_framework/hooks.dart' as hooks;
import 'package:crypto/crypto.dart' show sha256;
import 'package:mongo_dart/mongo_dart.dart';
import 'package:random_string/random_string.dart' as rs;
@ -8,11 +9,22 @@ export '../models/user.dart';
configureServer(Db db) {
return (Angel app) async {
app.use('/api/users', new UserService(db.collection('users')));
app.use('/api/users',
new TypedService<User>(new MongoService(db.collection('users'))));
HookedService service = app.service('api/users');
app.container.singleton(service.inner);
// Prevent clients from doing anything to the `users` service,
// apart from reading a single user's data.
service.before([
HookedServiceEvent.INDEXED,
HookedServiceEvent.CREATED,
HookedServiceEvent.MODIFIED,
HookedServiceEvent.UPDATED,
HookedServiceEvent.REMOVED
], hooks.disable());
// Validate new users, and also hash their passwords.
service.beforeCreated
..listen(validateEvent(CREATE_USER))
..listen((e) {
@ -22,37 +34,12 @@ configureServer(Db db) {
hashPassword(e.data['password'], salt, app.jwt_secret)
..['salt'] = salt;
});
// Remove sensitive data from serialized JSON.
service.afterAll(hooks.remove(['password', 'salt']));
};
}
/// SHA-256 hash any string, particularly a password.
String hashPassword(String password, String salt, String pepper) =>
sha256.convert(('$salt:$password:$pepper').codeUnits).toString();
/// Manages users.
///
/// Here, we extended the base service class. This allows to only expose
/// specific methods, and also allows more freedom over things such as validation.
class UserService extends TypedService<User> {
UserService(DbCollection collection) : super(new MongoService(collection));
@override
index([Map params]) {
if (params != null && params.containsKey('provider')) {
// Nobody needs to see the entire user list except for the server.
throw new AngelHttpException.forbidden();
}
return super.index(params);
}
@override
create(data, [Map params]) {
if (params != null && params.containsKey('provider')) {
// Deny creating users to the public - this should be done by the server only.
throw new AngelHttpException.forbidden();
}
return super.create(data, params);
}
}