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; import '../models/user.dart'; import '../validators/user.dart'; export '../models/user.dart'; configureServer(Db db) { return (Angel app) async { app.use('/api/users', new TypedService<User>(new MongoService(db.collection('users')))); HookedService service = app.service('api/users'); // 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()); // Don't broadcast user events over WebSockets - they're sensitive data! service.beforeAll((e) { e.params['broadcast'] = false; }); // Validate new users, and also hash their passwords. service.beforeCreated // ..listen(validateEvent(CREATE_USER)) ..listen((e) { var salt = rs.randomAlphaNumeric(12); e.data ..['password'] = 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();