diff --git a/README.md b/README.md index 22a1f7dd..f3151d32 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # validate -[![version 1.0.0-beta](https://img.shields.io/badge/pub-v1.0.0--beta-red.svg)](https://pub.dartlang.org/packages/angel_validate) +[![version 1.0.0](https://img.shields.io/badge/pub-v1.0.0-red.svg)](https://pub.dartlang.org/packages/angel_validate) [![build status](https://travis-ci.org/angel-dart/validate.svg)](https://travis-ci.org/angel-dart/validate) (Still missing several tests) @@ -23,6 +23,7 @@ For convenience's sake, this library also exports `matcher`. * [Default Values](#default-values) * [Custom Validator Functions](#custom-validator-functions) * [Auto-parsing Numbers](#autoparse) +* [Filtering Maps](#filter) * [Custom Error Messages](#custom-error-messages) * [Extending Validators](#extending-validators) * [Bundled Matchers](#bundled-matchers) @@ -166,6 +167,16 @@ main() { You can also call `checkParsed` or `enforceParsed` as a shorthand. +# filter +This is a helper function to extract only the desired keys from a `Map`. + +```dart +var inputData = {'foo': 'bar', 'a': 'b', '1': 2}; +var only = filter(inputData, ['foo']); + +print(only); // { foo: bar } +``` + # Extending Validators You can add situation-specific rules within a child validator. You can also use `extend` to mark fields as required or forbidden that originally @@ -257,12 +268,14 @@ main() { # Use with Angel -`server.dart` exposes five helper middleware: +`server.dart` exposes seven helper middleware: * `validate(validator)`: Validates and filters `req.body`, and throws an `AngelHttpException.BadRequest` if data is invalid. * `validateEvent(validator)`: Sets `e.data` to the result of validation on a service event. * `validateQuery(validator)`: Same as `validate`, but operates on `req.query`. * `autoParseBody(fields)`: Auto-parses numbers in `req.body`. * `autoParseQuery(fields)`: Same as `autoParseBody`, but operates on `req.query`. +* `filterBody(only)`: Filters unwanted data out of `req.body`. +* `filterQuery(only)`: Same as `filterBody`, but operates on `req.query`. ```dart import 'package:angel_framework/angel_framework.dart'; diff --git a/lib/server.dart b/lib/server.dart index 397b4b12..fc5bf6ef 100644 --- a/lib/server.dart +++ b/lib/server.dart @@ -21,6 +21,28 @@ RequestMiddleware autoParseQuery(List fields) { }; } +/// Filters unwanted data out of `req.body`. +RequestMiddleware filterBody(Iterable only) { + return (RequestContext req, res) async { + var filtered = filter(req.body, only); + req.body + ..clear() + ..addAll(filtered); + return true; + }; +} + +/// Filters unwanted data out of `req.query`. +RequestMiddleware filterQuery(Iterable only) { + return (RequestContext req, res) async { + var filtered = filter(req.query, only); + req.query + ..clear() + ..addAll(filtered); + return true; + }; +} + /// Validates the data in `req.body`, and sets the body to /// filtered data before continuing the response. RequestMiddleware validate(Validator validator, diff --git a/lib/src/validator.dart b/lib/src/validator.dart index 13286ec2..12452425 100644 --- a/lib/src/validator.dart +++ b/lib/src/validator.dart @@ -14,7 +14,7 @@ typedef String CustomErrorMessageFunction(item); typedef bool Filter(value); /// Converts the desired fields to their numeric representations, if present. -Map autoParse(Map inputData, List fields) { +Map autoParse(Map inputData, Iterable fields) { Map data = {}; for (var key in inputData.keys) { @@ -33,6 +33,14 @@ Map autoParse(Map inputData, List fields) { return data; } +/// Removes undesired fields from a `Map`. +Map filter(Map inputData, Iterable only) { + return inputData.keys.fold({}, (map, key) { + if (only.contains(key)) map[key] = inputData[key]; + return map; + }); +} + /// Enforces the validity of input data, according to [Matcher]s. class Validator extends Matcher { /// Pre-defined error messages for certain fields. diff --git a/pubspec.yaml b/pubspec.yaml index a4a323ee..f6555622 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: angel_validate description: Cross-platform validation library based on `matcher`. -version: 1.0.0-beta +version: 1.0.0 author: Tobe O homepage: https://github.com/angel-dart/validate environment: diff --git a/test/basic_test.dart b/test/basic_test.dart index 654497cc..3429af59 100644 --- a/test/basic_test.dart +++ b/test/basic_test.dart @@ -1,11 +1,8 @@ import 'package:angel_validate/angel_validate.dart'; import 'package:test/test.dart'; -final Validator emailSchema = new Validator({ - 'to': isEmail -}, customErrorMessages: { - 'to': 'Hello, world!' -}); +final Validator emailSchema = new Validator({'to': isEmail}, + customErrorMessages: {'to': 'Hello, world!'}); final Validator todoSchema = new Validator({ 'id': [isInt, isPositive], @@ -30,4 +27,10 @@ main() { .enforce({'id': 'fool', 'text': 'Hello, world!', 'completed': 4}); }, throwsA(new isInstanceOf())); }); + + test('filter', () { + var inputData = {'foo': 'bar', 'a': 'b', '1': 2}; + var only = filter(inputData, ['foo']); + expect(only, equals({'foo': 'bar'})); + }); }