From 42bd1f365dbeb87a0ffb591a3ddb9a04b4ad4d5e Mon Sep 17 00:00:00 2001 From: ManhNTX Date: Fri, 5 Aug 2022 16:24:56 +0700 Subject: [PATCH] create module rule_filter for tmail --- prebuild.sh | 3 + rule_filter/.gitignore | 30 ++++++++ rule_filter/.metadata | 10 +++ rule_filter/README.md | 3 + rule_filter/analysis_options.yaml | 4 + rule_filter/lib/capability_rule_filter.dart | 3 + .../lib/converter/rule_id_converter.dart | 13 ++++ .../lib/get/get_rule_filter_method.dart | 36 +++++++++ .../lib/get/get_rule_filter_response.dart | 30 ++++++++ rule_filter/lib/rule.dart | 6 ++ rule_filter/lib/rule_action.dart | 22 ++++++ rule_filter/lib/rule_append_in.dart | 25 ++++++ rule_filter/lib/rule_condition.dart | 59 ++++++++++++++ rule_filter/lib/rule_filter.dart | 24 ++++++ rule_filter/lib/rule_id.dart | 25 ++++++ .../lib/set/set_rule_filter_method.dart | 42 ++++++++++ .../lib/set/set_rule_filter_response.dart | 77 +++++++++++++++++++ rule_filter/lib/tmail_rule.dart | 38 +++++++++ rule_filter/pubspec.yaml | 74 ++++++++++++++++++ rule_filter/test/rule_filter_test.dart | 8 ++ 20 files changed, 532 insertions(+) create mode 100644 rule_filter/.gitignore create mode 100644 rule_filter/.metadata create mode 100644 rule_filter/README.md create mode 100644 rule_filter/analysis_options.yaml create mode 100644 rule_filter/lib/capability_rule_filter.dart create mode 100644 rule_filter/lib/converter/rule_id_converter.dart create mode 100644 rule_filter/lib/get/get_rule_filter_method.dart create mode 100644 rule_filter/lib/get/get_rule_filter_response.dart create mode 100644 rule_filter/lib/rule.dart create mode 100644 rule_filter/lib/rule_action.dart create mode 100644 rule_filter/lib/rule_append_in.dart create mode 100644 rule_filter/lib/rule_condition.dart create mode 100644 rule_filter/lib/rule_filter.dart create mode 100644 rule_filter/lib/rule_id.dart create mode 100644 rule_filter/lib/set/set_rule_filter_method.dart create mode 100644 rule_filter/lib/set/set_rule_filter_response.dart create mode 100644 rule_filter/lib/tmail_rule.dart create mode 100644 rule_filter/pubspec.yaml create mode 100644 rule_filter/test/rule_filter_test.dart diff --git a/prebuild.sh b/prebuild.sh index 7db616c66..9ad3f28c7 100644 --- a/prebuild.sh +++ b/prebuild.sh @@ -14,6 +14,9 @@ flutter pub get && flutter pub run build_runner build --delete-conflicting-outpu cd ../contact flutter pub get && flutter pub run build_runner build --delete-conflicting-outputs +cd ../rule_filter +flutter pub get && flutter pub run build_runner build --delete-conflicting-outputs + cd .. flutter pub get && flutter pub run build_runner build --delete-conflicting-outputs diff --git a/rule_filter/.gitignore b/rule_filter/.gitignore new file mode 100644 index 000000000..96486fd93 --- /dev/null +++ b/rule_filter/.gitignore @@ -0,0 +1,30 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.packages +build/ diff --git a/rule_filter/.metadata b/rule_filter/.metadata new file mode 100644 index 000000000..e7011f64f --- /dev/null +++ b/rule_filter/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + channel: stable + +project_type: package diff --git a/rule_filter/README.md b/rule_filter/README.md new file mode 100644 index 000000000..3e52a366c --- /dev/null +++ b/rule_filter/README.md @@ -0,0 +1,3 @@ +# rule filter + +TMail Rule Filter extension \ No newline at end of file diff --git a/rule_filter/analysis_options.yaml b/rule_filter/analysis_options.yaml new file mode 100644 index 000000000..a5744c1cf --- /dev/null +++ b/rule_filter/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/rule_filter/lib/capability_rule_filter.dart b/rule_filter/lib/capability_rule_filter.dart new file mode 100644 index 000000000..006956735 --- /dev/null +++ b/rule_filter/lib/capability_rule_filter.dart @@ -0,0 +1,3 @@ +import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart'; + +final capabilityRuleFilter = CapabilityIdentifier(Uri.parse('com:linagora:params:jmap:filter')); \ No newline at end of file diff --git a/rule_filter/lib/converter/rule_id_converter.dart b/rule_filter/lib/converter/rule_id_converter.dart new file mode 100644 index 000000000..07f4a660a --- /dev/null +++ b/rule_filter/lib/converter/rule_id_converter.dart @@ -0,0 +1,13 @@ +import 'package:jmap_dart_client/jmap/core/id.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:rule_filter/rule_id.dart'; + +class RuleIdConverter implements JsonConverter { + const RuleIdConverter(); + + @override + RuleId fromJson(String json) => RuleId(Id(json)); + + @override + String toJson(RuleId object) => object.id.value; +} \ No newline at end of file diff --git a/rule_filter/lib/get/get_rule_filter_method.dart b/rule_filter/lib/get/get_rule_filter_method.dart new file mode 100644 index 000000000..531fb7519 --- /dev/null +++ b/rule_filter/lib/get/get_rule_filter_method.dart @@ -0,0 +1,36 @@ +import 'package:jmap_dart_client/http/converter/account_id_converter.dart'; +import 'package:jmap_dart_client/http/converter/id_converter.dart'; +import 'package:jmap_dart_client/http/converter/properties_converter.dart'; +import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart'; +import 'package:jmap_dart_client/jmap/core/method/request/get_method.dart'; +import 'package:jmap_dart_client/jmap/core/request/request_invocation.dart'; +import 'package:jmap_dart_client/jmap/core/request/result_reference.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:rule_filter/capability_rule_filter.dart'; + +part 'get_rule_filter_method.g.dart'; + +@IdConverter() +@AccountIdConverter() +@PropertiesConverter() +@JsonSerializable(explicitToJson: true) +class GetRuleFilterMethod extends GetMethod { + GetRuleFilterMethod(AccountId accountId) : super(accountId); + + @override + MethodName get methodName => MethodName('Filter/get'); + + @override + Set get requiredCapabilities => { + capabilityRuleFilter + }; + + @override + List get props => [methodName, accountId, ids, requiredCapabilities]; + + factory GetRuleFilterMethod.fromJson(Map json) => _$GetRuleFilterMethodFromJson(json); + + @override + Map toJson() => _$GetRuleFilterMethodToJson(this); +} \ No newline at end of file diff --git a/rule_filter/lib/get/get_rule_filter_response.dart b/rule_filter/lib/get/get_rule_filter_response.dart new file mode 100644 index 000000000..1306d22ab --- /dev/null +++ b/rule_filter/lib/get/get_rule_filter_response.dart @@ -0,0 +1,30 @@ +import 'package:jmap_dart_client/http/converter/account_id_converter.dart'; +import 'package:jmap_dart_client/http/converter/id_converter.dart'; +import 'package:jmap_dart_client/http/converter/state_converter.dart'; +import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/id.dart'; +import 'package:jmap_dart_client/jmap/core/method/response/get_response.dart'; +import 'package:jmap_dart_client/jmap/core/state.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:rule_filter/tmail_rule.dart'; + +part 'get_rule_filter_response.g.dart'; + +@StateConverter() +@AccountIdConverter() +@IdConverter() +@JsonSerializable() +class GetRuleFilterResponse extends GetResponse { + GetRuleFilterResponse(AccountId accountId, State state, List list, List? notFound) : super(accountId, state, list, notFound); + + factory GetRuleFilterResponse.fromJson(Map json) => _$GetRuleFilterResponseFromJson(json); + + static GetRuleFilterResponse deserialize(Map json) { + return GetRuleFilterResponse.fromJson(json); + } + + Map toJson() => _$GetRuleFilterResponseToJson(this); + + @override + List get props => [accountId, state, list, notFound]; +} \ No newline at end of file diff --git a/rule_filter/lib/rule.dart b/rule_filter/lib/rule.dart new file mode 100644 index 000000000..b344a6cdf --- /dev/null +++ b/rule_filter/lib/rule.dart @@ -0,0 +1,6 @@ +import 'package:equatable/equatable.dart'; + +abstract class Rule with EquatableMixin { + @override + List get props => []; +} \ No newline at end of file diff --git a/rule_filter/lib/rule_action.dart b/rule_filter/lib/rule_action.dart new file mode 100644 index 000000000..1be1fe968 --- /dev/null +++ b/rule_filter/lib/rule_action.dart @@ -0,0 +1,22 @@ +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:rule_filter/rule_append_in.dart'; + +part 'rule_action.g.dart'; + +@JsonSerializable() +class RuleAction with EquatableMixin { + final RuleAppendIn appendIn; + + RuleAction(this.appendIn); + + @override + List get props => [ + appendIn, + ]; + + factory RuleAction.fromJson(Map json) => + _$RuleActionFromJson(json); + + Map toJson() => _$RuleActionToJson(this); +} diff --git a/rule_filter/lib/rule_append_in.dart b/rule_filter/lib/rule_append_in.dart new file mode 100644 index 000000000..d2aed3473 --- /dev/null +++ b/rule_filter/lib/rule_append_in.dart @@ -0,0 +1,25 @@ +import 'package:equatable/equatable.dart'; +import 'package:jmap_dart_client/http/converter/mailbox_id_converter.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'rule_append_in.g.dart'; + +@MailboxIdConverter() +@JsonSerializable() +class RuleAppendIn with EquatableMixin { + final List mailboxIds; + + RuleAppendIn(this.mailboxIds); + + @override + List get props => [ + mailboxIds, + ]; + + factory RuleAppendIn.fromJson(Map json) => + _$RuleAppendInFromJson(json); + + Map toJson() => _$RuleAppendInToJson(this); + +} diff --git a/rule_filter/lib/rule_condition.dart b/rule_filter/lib/rule_condition.dart new file mode 100644 index 000000000..af26ad959 --- /dev/null +++ b/rule_filter/lib/rule_condition.dart @@ -0,0 +1,59 @@ +import 'package:jmap_dart_client/jmap/core/filter/filter_condition.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'rule_condition.g.dart'; + +@JsonEnum() +enum Field { + @JsonValue('from') + from, + @JsonValue('to') + to, + @JsonValue('cc') + cc, + @JsonValue('recipient') + recipient, + @JsonValue('subject') + subject, +} + +@JsonEnum() +enum Comparator { + @JsonValue('contains') + contains, + @JsonValue('not-contains') + notContains, + @JsonValue('exactly-equals') + exactlyEquals, + @JsonValue('not-exactly-equals') + notExactlyEquals, +} + +@JsonSerializable() +class RuleCondition extends FilterCondition { + final Field field; + + final Comparator comparator; + + final String value; + + RuleCondition( + this.field, + this.comparator, + this.value, + ); + + @override + List get props => [ + field, + comparator, + value, + ]; + + factory RuleCondition.fromJson(Map json) => + _$RuleConditionFromJson(json); + + @override + Map toJson() => _$RuleConditionToJson(this); + +} diff --git a/rule_filter/lib/rule_filter.dart b/rule_filter/lib/rule_filter.dart new file mode 100644 index 000000000..8d9270511 --- /dev/null +++ b/rule_filter/lib/rule_filter.dart @@ -0,0 +1,24 @@ +import 'package:jmap_dart_client/jmap/core/filter/filter.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:rule_filter/converter/rule_id_converter.dart'; +import 'package:rule_filter/rule_id.dart'; + +part 'rule_filter.g.dart'; + +@RuleIdConverter() +@JsonSerializable() +class RuleFilter extends Filter { + + final RuleId id; + + RuleFilter(this.id); + + factory RuleFilter.fromJson(Map json) => + _$RuleFilterFromJson(json); + + @override + Map toJson() => _$RuleFilterToJson(this); + + @override + List get props => [id]; +} \ No newline at end of file diff --git a/rule_filter/lib/rule_id.dart b/rule_filter/lib/rule_id.dart new file mode 100644 index 000000000..e37e4785e --- /dev/null +++ b/rule_filter/lib/rule_id.dart @@ -0,0 +1,25 @@ +import 'package:equatable/equatable.dart'; +import 'package:jmap_dart_client/http/converter/id_converter.dart'; +import 'package:jmap_dart_client/jmap/core/id.dart'; +import 'package:json_annotation/json_annotation.dart'; + +enum RuleIdType { + singleton('singleton'); + const RuleIdType(this.value); + final String value; +} + +@JsonSerializable() +@IdConverter() +class RuleId with EquatableMixin { + final Id id; + + RuleId(this.id); + + @override + List get props => [id]; +} + +extension RuleIdSingleton on RuleId { + static get ruleIdSingleton => RuleId(Id(RuleIdType.singleton.value)); +} \ No newline at end of file diff --git a/rule_filter/lib/set/set_rule_filter_method.dart b/rule_filter/lib/set/set_rule_filter_method.dart new file mode 100644 index 000000000..f6a164e58 --- /dev/null +++ b/rule_filter/lib/set/set_rule_filter_method.dart @@ -0,0 +1,42 @@ +import 'package:jmap_dart_client/http/converter/account_id_converter.dart'; +import 'package:jmap_dart_client/http/converter/set/set_method_properties_converter.dart'; +import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart'; +import 'package:jmap_dart_client/jmap/core/method/request/set_method.dart'; +import 'package:jmap_dart_client/jmap/core/request/request_invocation.dart'; +import 'package:rule_filter/capability_rule_filter.dart'; +import 'package:rule_filter/tmail_rule.dart'; + +class SetRuleFilterMethod extends SetMethod { + SetRuleFilterMethod(AccountId accountId) : super(accountId); + + @override + MethodName get methodName => MethodName('Filter/set'); + + @override + Set get requiredCapabilities => { + capabilityRuleFilter, + }; + + @override + Map toJson() { + final val = { + 'accountId': const AccountIdConverter().toJson(accountId), + }; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('ifInState', ifInState?.value); + writeNotNull('update', update + ?.map((id, update) => SetMethodPropertiesConverter().fromMapIdToJson(id, update.toJson()))); + + return val; + } + + @override + List get props => [accountId, ifInState, update,]; +} \ No newline at end of file diff --git a/rule_filter/lib/set/set_rule_filter_response.dart b/rule_filter/lib/set/set_rule_filter_response.dart new file mode 100644 index 000000000..d88fe6ebc --- /dev/null +++ b/rule_filter/lib/set/set_rule_filter_response.dart @@ -0,0 +1,77 @@ +import 'package:jmap_dart_client/http/converter/account_id_converter.dart'; +import 'package:jmap_dart_client/http/converter/id_converter.dart'; +import 'package:jmap_dart_client/http/converter/state_converter.dart'; +import 'package:jmap_dart_client/http/converter/state_nullable_converter.dart'; +import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/error/set_error.dart'; +import 'package:jmap_dart_client/jmap/core/id.dart'; +import 'package:jmap_dart_client/jmap/core/method/response/set_response.dart'; +import 'package:jmap_dart_client/jmap/core/state.dart'; +import 'package:rule_filter/tmail_rule.dart'; + +class SetRuleFilterResponse extends SetResponse { + SetRuleFilterResponse( + AccountId accountId, + State newState, { + State? oldState, + Map? created, + Map? updated, + Set? destroyed, + Map? notCreated, + Map? notUpdated, + Map? notDestroyed + }) : super( + accountId, + newState, + oldState: oldState, + created: created, + updated: updated, + destroyed: destroyed, + notCreated: notCreated, + notUpdated: notUpdated, + notDestroyed: notDestroyed + ); + + static SetRuleFilterResponse deserialize(Map json) { + return SetRuleFilterResponse( + const AccountIdConverter().fromJson(json['accountId'] as String), + const StateConverter().fromJson(json['newState'] as String), + oldState: const StateNullableConverter().fromJson(json['oldState'] as String?), + created: (json['created'] as Map?) + ?.map((key, value) => MapEntry( + const IdConverter().fromJson(key), + TMailRule.fromJson(value as Map))), + updated: (json['updated'] as Map?) + ?.map((key, value) => MapEntry( + const IdConverter().fromJson(key), + value != null ? TMailRule.fromJson(value as Map) : null)), + destroyed: (json['destroyed'] as List?) + ?.map((id) => const IdConverter().fromJson(id)).toSet(), + notCreated: (json['notCreated'] as Map?) + ?.map((key, value) => MapEntry( + const IdConverter().fromJson(key), + SetError.fromJson(value))), + notUpdated: (json['notUpdated'] as Map?) + ?.map((key, value) => MapEntry( + const IdConverter().fromJson(key), + SetError.fromJson(value))), + notDestroyed: (json['notDestroyed'] as Map?) + ?.map((key, value) => MapEntry( + const IdConverter().fromJson(key), + SetError.fromJson(value))), + ); + } + + @override + List get props => [ + oldState, + newState, + created, + updated, + destroyed, + notCreated, + notUpdated, + notDestroyed, + accountId, + ]; +} \ No newline at end of file diff --git a/rule_filter/lib/tmail_rule.dart b/rule_filter/lib/tmail_rule.dart new file mode 100644 index 000000000..73ddd0174 --- /dev/null +++ b/rule_filter/lib/tmail_rule.dart @@ -0,0 +1,38 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'package:rule_filter/converter/rule_id_converter.dart'; +import 'package:rule_filter/rule.dart'; +import 'package:rule_filter/rule_action.dart'; +import 'package:rule_filter/rule_condition.dart'; +import 'package:rule_filter/rule_id.dart'; + +part 'tmail_rule.g.dart'; + +@JsonSerializable() +@RuleIdConverter() +class TMailRule extends Rule { + + final RuleId id; + final String name; + final RuleCondition condition; + final RuleAction action; + + TMailRule( + this.id, + this.name, + this.condition, + this.action, + ); + + factory TMailRule.fromJson(Map json) => + _$TMailRuleFromJson(json); + + Map toJson() => _$TMailRuleToJson(this); + + @override + List get props => [ + id, + name, + condition, + action, + ]; +} \ No newline at end of file diff --git a/rule_filter/pubspec.yaml b/rule_filter/pubspec.yaml new file mode 100644 index 000000000..2ae478190 --- /dev/null +++ b/rule_filter/pubspec.yaml @@ -0,0 +1,74 @@ +name: rule_filter +description: rule_filter for tmail +version: 0.0.1 +publish_to: none + +environment: + sdk: ">=2.17.6 <3.0.0" + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + + model: + path: ../model + + equatable: 2.0.3 + + json_annotation: 4.5.0 + + jmap_dart_client: + git: + url: https://github.com/linagora/jmap-dart-client.git + ref: master + + http_mock_adapter: 0.3.2 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^1.0.0 + + build_runner: 2.1.11 + + json_serializable: 6.2.0 + + mockito: 5.2.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # To add assets to your package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.dev/assets-and-images/#from-packages + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # To add custom fonts to your package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.dev/custom-fonts/#from-packages diff --git a/rule_filter/test/rule_filter_test.dart b/rule_filter/test/rule_filter_test.dart new file mode 100644 index 000000000..4c13a02d5 --- /dev/null +++ b/rule_filter/test/rule_filter_test.dart @@ -0,0 +1,8 @@ +import 'package:flutter_test/flutter_test.dart'; + +import 'package:rule_filter/rule_filter.dart'; + +void main() { + test('adds one to input values', () { + }); +}