From d42172986a1a4b657805d15ea74d891d0cb250cf Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 20 Apr 2019 15:13:46 -0400 Subject: [PATCH] 1.0.1 --- CHANGELOG.md | 3 +++ analysis_options.yaml | 1 + lib/angel_sembast.dart | 18 +++++++++++------- pubspec.yaml | 3 ++- test/all_test.dart | 30 ++++++++++++++++++++++++++++++ 5 files changed, 47 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bdbca561..9195900b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,5 @@ +# 1.0.1 +* Fix flaw where clients could remove all records, even if `allowRemoveAll` were `false`. + # 1.0.0 * First release. \ No newline at end of file diff --git a/analysis_options.yaml b/analysis_options.yaml index eae1e42a..c230cee7 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,3 +1,4 @@ +include: package:pedantic/analysis_options.yaml analyzer: strong-mode: implicit-casts: false \ No newline at end of file diff --git a/lib/angel_sembast.dart b/lib/angel_sembast.dart index 643cdd11..53814ed0 100644 --- a/lib/angel_sembast.dart +++ b/lib/angel_sembast.dart @@ -15,7 +15,7 @@ class SembastService extends Service> { final bool allowQuery; SembastService(this.database, - {String store, this.allowRemoveAll: false, this.allowQuery: true}) + {String store, this.allowRemoveAll = false, this.allowQuery = true}) : this.store = (store == null ? database.mainStore : database.getStore(store)), super(); @@ -151,12 +151,16 @@ class SembastService extends Service> { @override Future> remove(String id, [Map params]) async { - if (id == null || - id == 'null' && - (allowRemoveAll == true || - params?.containsKey('provider') != true)) { - await store.deleteAll(await store.findKeys(new Finder())); - return {}; + if (id == null || id == 'null') { + // Remove everything... + if (!(allowRemoveAll == true || + params?.containsKey('provider') != true)) { + throw AngelHttpException.forbidden( + message: 'Clients are not allowed to delete all items.'); + } else { + await store.deleteAll(await store.findKeys(new Finder())); + return {}; + } } return database.transaction((txn) async { diff --git a/pubspec.yaml b/pubspec.yaml index 07ac297f..b822c43f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: angel_sembast description: package:sembast-powered CRUD services for the Angel framework. homepage: https://github.com/angel-dart/sembast -version: 1.0.0 +version: 1.0.1 author: Tobe O environment: sdk: ">=2.0.0-dev <3.0.0" @@ -11,5 +11,6 @@ dependencies: dev_dependencies: angel_http_exception: ^1.0.0 logging: + pedantic: ^1.0.0 test: ^1.0.0 diff --git a/test/all_test.dart b/test/all_test.dart index 7b4df3df..c4862d58 100644 --- a/test/all_test.dart +++ b/test/all_test.dart @@ -1,4 +1,5 @@ import 'dart:collection'; +import 'package:angel_framework/angel_framework.dart'; import 'package:angel_http_exception/angel_http_exception.dart'; import 'package:angel_sembast/angel_sembast.dart'; import 'package:sembast/sembast.dart'; @@ -76,6 +77,35 @@ main() async { expect(await service.index(), isEmpty); }); + test('cannot remove all unless explicitly set', () async { + expect(() => service.remove(null, {'provider': Providers.rest}), + throwsA(const TypeMatcher())); + expect( + () => service.remove(null, {'provider': Providers.rest}), + throwsA(predicate((x) => x is AngelHttpException && x.statusCode == 403, + 'throws forbidden'))); + expect(() => service.remove('null', {'provider': Providers.rest}), + throwsA(const TypeMatcher())); + expect( + () => service.remove('null', {'provider': Providers.rest}), + throwsA(predicate((x) => x is AngelHttpException && x.statusCode == 403, + 'throws forbidden'))); + }); + + test('can remove all on server side', () async { + await service.create({'bar': 'baz'}); + await service.create({'bar': 'baz'}); + await service.create({'bar': 'baz'}); + await service.remove(null); + expect(await service.index(), isEmpty); + + await service.create({'bar': 'baz'}); + await service.create({'bar': 'baz'}); + await service.create({'bar': 'baz'}); + await service.remove('null'); + expect(await service.index(), isEmpty); + }); + test('remove nonexistent', () async { expect(() => service.remove('440'), throwsA(const TypeMatcher()));