Patch allowRemoveAll flaw

This commit is contained in:
Tobe O 2019-04-20 14:59:22 -04:00
parent e1b85092d5
commit 2c15ae9464
5 changed files with 39 additions and 23 deletions

View file

@ -1,3 +1,6 @@
# 2.0.2
* Fix flaw where clients could remove all records, even if `allowRemoveAll` were `false`.
# 2.0.1 # 2.0.1
* Override `readMany` and `findOne`. * Override `readMany` and `findOne`.

View file

@ -1,3 +1,4 @@
include: package:pedantic/analysis_options.yaml
analyzer: analyzer:
strong-mode: strong-mode:
implicit-casts: false implicit-casts: false

View file

@ -12,10 +12,12 @@ class MongoService extends Service<String, Map<String, dynamic>> {
/// If set to `true`, parameters in `req.query` are applied to the database query. /// If set to `true`, parameters in `req.query` are applied to the database query.
final bool allowQuery; final bool allowQuery;
/// No longer used. Will be removed by `2.1.0`.
@deprecated
final bool debug; final bool debug;
MongoService(DbCollection this.collection, MongoService(DbCollection this.collection,
{this.allowRemoveAll: false, this.allowQuery: true, this.debug: true}) {this.allowRemoveAll = false, this.allowQuery = true, this.debug = true})
: super(); : super();
SelectorBuilder _makeQuery([Map<String, dynamic> params_]) { SelectorBuilder _makeQuery([Map<String, dynamic> params_]) {
@ -51,7 +53,7 @@ class MongoService extends Service<String, Map<String, dynamic>> {
} }
} else if (key == 'query' && } else if (key == 'query' &&
(allowQuery == true || !params.containsKey('provider'))) { (allowQuery == true || !params.containsKey('provider'))) {
Map query = params[key]; var query = params[key] as Map;
query.forEach((key, v) { query.forEach((key, v) {
var value = v is Map<String, dynamic> ? _filterNoQuery(v) : v; var value = v is Map<String, dynamic> ? _filterNoQuery(v) : v;
@ -99,7 +101,7 @@ class MongoService extends Service<String, Map<String, dynamic>> {
var item = _removeSensitive(data); var item = _removeSensitive(data);
try { try {
String nonce = (await collection.db.getNonce())['nonce']; var nonce = (await collection.db.getNonce())['nonce'] as String;
var result = await collection.findAndModify( var result = await collection.findAndModify(
query: where.eq(_NONCE_KEY, nonce), query: where.eq(_NONCE_KEY, nonce),
update: item, update: item,
@ -209,13 +211,17 @@ class MongoService extends Service<String, Map<String, dynamic>> {
@override @override
Future<Map<String, dynamic>> remove(String id, Future<Map<String, dynamic>> remove(String id,
[Map<String, dynamic> params]) async { [Map<String, dynamic> params]) async {
if (id == null || if (id == null || id == 'null') {
id == 'null' && // Remove everything...
(allowRemoveAll == true || if (!(allowRemoveAll == true ||
params?.containsKey('provider') != true)) { params?.containsKey('provider') != true)) {
throw AngelHttpException.forbidden(
message: 'Clients are not allowed to delete all items.');
} else {
await collection.remove(null); await collection.remove(null);
return {}; return {};
} }
}
// var result = await read(id, params); // var result = await read(id, params);

View file

@ -1,5 +1,5 @@
name: angel_mongo name: angel_mongo
version: 2.0.1 version: 2.0.2
description: MongoDB-enabled services for the Angel framework. Well-tested. description: MongoDB-enabled services for the Angel framework. Well-tested.
author: Tobe O <thosakwe@gmail.com> author: Tobe O <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/angel_mongo homepage: https://github.com/angel-dart/angel_mongo
@ -12,4 +12,5 @@ dependencies:
mongo_dart: ">= 0.2.7 < 1.0.0" mongo_dart: ">= 0.2.7 < 1.0.0"
dev_dependencies: dev_dependencies:
http: ">= 0.11.3 < 0.12.0" http: ">= 0.11.3 < 0.12.0"
pedantic: ^1.0.0
test: ^1.0.0 test: ^1.0.0

View file

@ -80,8 +80,8 @@ main() {
response = await client.get("$url/api"); response = await client.get("$url/api");
expect(response.statusCode, isIn([200, 201])); expect(response.statusCode, isIn([200, 201]));
List<Map> users = var users = god.deserialize(response.body,
god.deserialize(response.body, outputType: <Map>[].runtimeType); outputType: <Map>[].runtimeType) as List<Map>;
expect(users.length, equals(1)); expect(users.length, equals(1));
}); });
@ -89,11 +89,11 @@ main() {
var response = await client.post("$url/api", var response = await client.post("$url/api",
body: god.serialize(testGreeting), headers: headers); body: god.serialize(testGreeting), headers: headers);
expect(response.statusCode, isIn([200, 201])); expect(response.statusCode, isIn([200, 201]));
Map created = god.deserialize(response.body); var created = god.deserialize(response.body) as Map;
response = await client.get("$url/api/${created['id']}"); response = await client.get("$url/api/${created['id']}");
expect(response.statusCode, isIn([200, 201])); expect(response.statusCode, isIn([200, 201]));
Map read = god.deserialize(response.body); var read = god.deserialize(response.body) as Map;
expect(read['id'], equals(created['id'])); expect(read['id'], equals(created['id']));
expect(read['to'], equals('world')); expect(read['to'], equals('world'));
//expect(read['createdAt'], isNot(null)); //expect(read['createdAt'], isNot(null));
@ -103,7 +103,7 @@ main() {
var response = await client.post("$url/api", var response = await client.post("$url/api",
body: god.serialize(testGreeting), headers: headers); body: god.serialize(testGreeting), headers: headers);
expect(response.statusCode, isIn([200, 201])); expect(response.statusCode, isIn([200, 201]));
Map created = god.deserialize(response.body); var created = god.deserialize(response.body) as Map;
var id = new ObjectId.fromHexString(created['id'] as String); var id = new ObjectId.fromHexString(created['id'] as String);
var read = await greetingService.findOne({'query': where.id(id)}); var read = await greetingService.findOne({'query': where.id(id)});
@ -116,7 +116,7 @@ main() {
var response = await client.post("$url/api", var response = await client.post("$url/api",
body: god.serialize(testGreeting), headers: headers); body: god.serialize(testGreeting), headers: headers);
expect(response.statusCode, isIn([200, 201])); expect(response.statusCode, isIn([200, 201]));
Map created = god.deserialize(response.body); var created = god.deserialize(response.body) as Map;
var id = new ObjectId.fromHexString(created['id'] as String); var id = new ObjectId.fromHexString(created['id'] as String);
var read = await greetingService.readMany([id.toHexString()]); var read = await greetingService.readMany([id.toHexString()]);
@ -128,11 +128,11 @@ main() {
var response = await client.post("$url/api", var response = await client.post("$url/api",
body: god.serialize(testGreeting), headers: headers); body: god.serialize(testGreeting), headers: headers);
expect(response.statusCode, isIn([200, 201])); expect(response.statusCode, isIn([200, 201]));
Map created = god.deserialize(response.body); var created = god.deserialize(response.body) as Map;
response = await client.patch("$url/api/${created['id']}", response = await client.patch("$url/api/${created['id']}",
body: god.serialize({"to": "Mom"}), headers: headers); body: god.serialize({"to": "Mom"}), headers: headers);
Map modified = god.deserialize(response.body); var modified = god.deserialize(response.body) as Map;
expect(response.statusCode, isIn([200, 201])); expect(response.statusCode, isIn([200, 201]));
expect(modified['id'], equals(created['id'])); expect(modified['id'], equals(created['id']));
expect(modified['to'], equals('Mom')); expect(modified['to'], equals('Mom'));
@ -143,11 +143,11 @@ main() {
var response = await client.post("$url/api", var response = await client.post("$url/api",
body: god.serialize(testGreeting), headers: headers); body: god.serialize(testGreeting), headers: headers);
expect(response.statusCode, isIn([200, 201])); expect(response.statusCode, isIn([200, 201]));
Map created = god.deserialize(response.body); var created = god.deserialize(response.body) as Map;
response = await client.post("$url/api/${created['id']}", response = await client.post("$url/api/${created['id']}",
body: god.serialize({"to": "Updated"}), headers: headers); body: god.serialize({"to": "Updated"}), headers: headers);
Map modified = god.deserialize(response.body); var modified = god.deserialize(response.body) as Map;
expect(response.statusCode, isIn([200, 201])); expect(response.statusCode, isIn([200, 201]));
expect(modified['id'], equals(created['id'])); expect(modified['id'], equals(created['id']));
expect(modified['to'], equals('Updated')); expect(modified['to'], equals('Updated'));
@ -157,7 +157,7 @@ main() {
test('remove item', () async { test('remove item', () async {
var response = await client.post("$url/api", var response = await client.post("$url/api",
body: god.serialize(testGreeting), headers: headers); body: god.serialize(testGreeting), headers: headers);
Map created = god.deserialize(response.body); var created = god.deserialize(response.body) as Map;
int lastCount = (await greetingService.index()).length; int lastCount = (await greetingService.index()).length;
@ -165,6 +165,11 @@ main() {
expect((await greetingService.index()).length, equals(lastCount - 1)); expect((await greetingService.index()).length, equals(lastCount - 1));
}); });
test('cannot remove all unless explicitly set', () async {
var response = await client.delete('$url/api/null');
expect(response.statusCode, 403);
});
test('\$sort and query parameters', () async { test('\$sort and query parameters', () async {
// Search by where.eq // Search by where.eq
Map world = await greetingService.create({"to": "world"}); Map world = await greetingService.create({"to": "world"});
@ -173,8 +178,8 @@ main() {
var response = await client.get("$url/api?to=world"); var response = await client.get("$url/api?to=world");
print(response.body); print(response.body);
List<Map> queried = var queried = god.deserialize(response.body,
god.deserialize(response.body, outputType: <Map>[].runtimeType); outputType: <Map>[].runtimeType) as List<Map>;
expect(queried.length, equals(1)); expect(queried.length, equals(1));
expect(queried[0].keys.length, equals(2)); expect(queried[0].keys.length, equals(2));
expect(queried[0]["id"], equals(world["id"])); expect(queried[0]["id"], equals(world["id"]));