forest_liana 7.0.0.beta.4 → 7.0.0.beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/forest_liana/actions_controller.rb +2 -2
- data/app/controllers/forest_liana/associations_controller.rb +2 -2
- data/app/controllers/forest_liana/resources_controller.rb +15 -6
- data/app/controllers/forest_liana/scopes_controller.rb +20 -0
- data/app/controllers/forest_liana/smart_actions_controller.rb +39 -3
- data/app/controllers/forest_liana/stats_controller.rb +5 -5
- data/app/services/forest_liana/filters_parser.rb +8 -4
- data/app/services/forest_liana/has_many_dissociator.rb +2 -2
- data/app/services/forest_liana/has_many_getter.rb +2 -2
- data/app/services/forest_liana/leaderboard_stat_getter.rb +20 -14
- data/app/services/forest_liana/line_stat_getter.rb +4 -2
- data/app/services/forest_liana/permissions_checker.rb +3 -4
- data/app/services/forest_liana/permissions_getter.rb +2 -2
- data/app/services/forest_liana/pie_stat_getter.rb +6 -3
- data/app/services/forest_liana/resource_getter.rb +6 -3
- data/app/services/forest_liana/resource_updater.rb +5 -2
- data/app/services/forest_liana/resources_getter.rb +6 -5
- data/app/services/forest_liana/scope_manager.rb +102 -0
- data/app/services/forest_liana/search_query_builder.rb +6 -3
- data/app/services/forest_liana/stat_getter.rb +2 -1
- data/app/services/forest_liana/value_stat_getter.rb +4 -2
- data/config/routes.rb +3 -0
- data/lib/forest_liana/version.rb +1 -1
- data/spec/dummy/app/controllers/forest/islands_controller.rb +5 -0
- data/spec/dummy/config/routes.rb +4 -0
- data/spec/dummy/lib/forest_liana/collections/island.rb +7 -0
- data/spec/requests/actions_controller_spec.rb +100 -12
- data/spec/requests/resources_spec.rb +2 -0
- data/spec/services/forest_liana/filters_parser_spec.rb +1 -1
- data/spec/services/forest_liana/has_many_getter_spec.rb +116 -0
- data/spec/services/forest_liana/line_stat_getter_spec.rb +14 -6
- data/spec/services/forest_liana/permissions_checker_acl_disabled_spec.rb +1 -3
- data/spec/services/forest_liana/pie_stat_getter_spec.rb +114 -0
- data/spec/services/forest_liana/resource_updater_spec.rb +116 -0
- data/spec/services/forest_liana/resources_getter_spec.rb +68 -1
- data/spec/services/forest_liana/scope_manager_spec.rb +232 -0
- data/spec/services/forest_liana/value_stat_getter_spec.rb +96 -0
- metadata +18 -13
- data/app/services/forest_liana/scope_validator.rb +0 -98
- data/test/services/forest_liana/has_many_getter_test.rb +0 -75
- data/test/services/forest_liana/pie_stat_getter_test.rb +0 -29
- data/test/services/forest_liana/resource_updater_test.rb +0 -86
- data/test/services/forest_liana/scope_validator_test.rb +0 -185
- data/test/services/forest_liana/value_stat_getter_test.rb +0 -71
@@ -1,98 +0,0 @@
|
|
1
|
-
module ForestLiana
|
2
|
-
class ScopeValidator
|
3
|
-
def initialize(scope_permissions, users_variable_values)
|
4
|
-
@scope_filters = scope_permissions
|
5
|
-
@users_variable_values = users_variable_values
|
6
|
-
end
|
7
|
-
|
8
|
-
def is_scope_in_request?(scope_request)
|
9
|
-
begin
|
10
|
-
filters = JSON.parse(scope_request[:filters])
|
11
|
-
rescue JSON::ParserError
|
12
|
-
raise ForestLiana::Errors::HTTP422Error.new('Invalid filters JSON format')
|
13
|
-
end
|
14
|
-
@computed_scope = compute_condition_filters_from_scope(scope_request[:user_id])
|
15
|
-
|
16
|
-
# NOTICE: Perfom a travel in the request condition filters tree to find the scope
|
17
|
-
tagged_scope_filters = get_scope_found_in_request(filters)
|
18
|
-
|
19
|
-
# NOTICE: Permission system always send an aggregator even if there is only one condition
|
20
|
-
# In that case, if the condition is valid, then request was not edited
|
21
|
-
return !tagged_scope_filters.nil? if @scope_filters['conditions'].length == 1
|
22
|
-
|
23
|
-
# NOTICE: If there is more than one condition, do a final validation on the condition filters
|
24
|
-
return tagged_scope_filters != nil &&
|
25
|
-
tagged_scope_filters[:aggregator] == @scope_filters['aggregator'] &&
|
26
|
-
tagged_scope_filters[:conditions] &&
|
27
|
-
tagged_scope_filters[:conditions].length == @scope_filters['conditions'].length
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
def compute_condition_filters_from_scope(user_id)
|
33
|
-
computed_condition_filters = @scope_filters.clone
|
34
|
-
computed_condition_filters['conditions'].each do |condition|
|
35
|
-
if condition.include?('value') &&
|
36
|
-
!condition['value'].nil? &&
|
37
|
-
condition['value'].instance_of?(String) &&
|
38
|
-
condition['value'].start_with?('$') &&
|
39
|
-
@users_variable_values.include?(user_id)
|
40
|
-
condition['value'] = @users_variable_values[user_id][condition['value']]
|
41
|
-
end
|
42
|
-
end
|
43
|
-
return computed_condition_filters
|
44
|
-
end
|
45
|
-
|
46
|
-
def get_scope_found_in_request(filters)
|
47
|
-
return nil unless filters
|
48
|
-
return search_scope_aggregation(filters)
|
49
|
-
end
|
50
|
-
|
51
|
-
def search_scope_aggregation(node)
|
52
|
-
ensure_valid_aggregation(node)
|
53
|
-
|
54
|
-
return is_scope_condition?(node) unless node['aggregator']
|
55
|
-
|
56
|
-
# NOTICE: Remove conditions that are not from the scope
|
57
|
-
filtered_conditions = node['conditions'].map { |condition|
|
58
|
-
search_scope_aggregation(condition)
|
59
|
-
}.select { |condition|
|
60
|
-
condition
|
61
|
-
}
|
62
|
-
|
63
|
-
# NOTICE: If there is only one condition filter left and its current aggregator is
|
64
|
-
# an "and", this condition filter is the searched scope
|
65
|
-
if (filtered_conditions.length == 1 &&
|
66
|
-
filtered_conditions.first.is_a?(Hash) &&
|
67
|
-
filtered_conditions.first.include?(:aggregator) &&
|
68
|
-
node['aggregator'] == 'and')
|
69
|
-
return filtered_conditions.first
|
70
|
-
end
|
71
|
-
|
72
|
-
# NOTICE: Otherwise, validate if the current node is the scope and return nil
|
73
|
-
# if it's not
|
74
|
-
return (filtered_conditions.length == @scope_filters['conditions'].length &&
|
75
|
-
node['aggregator'] == @scope_filters['aggregator']) ?
|
76
|
-
{ aggregator: node['aggregator'], conditions: filtered_conditions } :
|
77
|
-
nil
|
78
|
-
end
|
79
|
-
|
80
|
-
def is_scope_condition?(condition)
|
81
|
-
ensure_valid_condition(condition)
|
82
|
-
return @computed_scope['conditions'].include?(condition)
|
83
|
-
end
|
84
|
-
|
85
|
-
def ensure_valid_aggregation(node)
|
86
|
-
raise ForestLiana::Errors::HTTP422Error.new('Filters cannot be a raw value') unless node.is_a?(Hash)
|
87
|
-
raise_empty_condition_in_filter_error if node.empty?
|
88
|
-
end
|
89
|
-
|
90
|
-
def ensure_valid_condition(condition)
|
91
|
-
raise_empty_condition_in_filter_error if condition.empty?
|
92
|
-
raise ForestLiana::Errors::HTTP422Error.new('Condition cannot be a raw value') unless condition.is_a?(Hash)
|
93
|
-
unless condition['field'].is_a?(String) and condition['operator'].is_a?(String)
|
94
|
-
raise ForestLiana::Errors::HTTP422Error.new('Invalid condition format')
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
@@ -1,75 +0,0 @@
|
|
1
|
-
module ForestLiana
|
2
|
-
class HasManyGetterTest < ActiveSupport::TestCase
|
3
|
-
|
4
|
-
collectionOwner = ForestLiana::Model::Collection.new({
|
5
|
-
name: 'Owner',
|
6
|
-
fields: []
|
7
|
-
})
|
8
|
-
|
9
|
-
collectionTree = ForestLiana::Model::Collection.new({
|
10
|
-
name: 'Tree',
|
11
|
-
fields: []
|
12
|
-
})
|
13
|
-
|
14
|
-
ForestLiana.apimap << collectionOwner
|
15
|
-
ForestLiana.apimap << collectionTree
|
16
|
-
ForestLiana.models << Owner
|
17
|
-
ForestLiana.models << Tree
|
18
|
-
|
19
|
-
test 'HasMany Getter page 1 size 15' do
|
20
|
-
association = Owner.reflect_on_association(:trees)
|
21
|
-
|
22
|
-
getter = HasManyGetter.new(Owner, association, {
|
23
|
-
id: 1,
|
24
|
-
association_name: 'trees',
|
25
|
-
page: { size: 15, number: 1 },
|
26
|
-
timezone: 'America/Nome'
|
27
|
-
})
|
28
|
-
getter.perform
|
29
|
-
records = getter.records
|
30
|
-
count = getter.count
|
31
|
-
|
32
|
-
assert records.count == 3
|
33
|
-
assert count = 3
|
34
|
-
assert records.first.id == 7
|
35
|
-
end
|
36
|
-
|
37
|
-
test 'HasMany Getter with sort parameter' do
|
38
|
-
association = Owner.reflect_on_association(:trees)
|
39
|
-
|
40
|
-
getter = HasManyGetter.new(Owner, association, {
|
41
|
-
id: 1,
|
42
|
-
association_name: 'trees',
|
43
|
-
sort: '-id',
|
44
|
-
page: { size: 15, number: 1 },
|
45
|
-
timezone: 'America/Nome'
|
46
|
-
})
|
47
|
-
getter.perform
|
48
|
-
records = getter.records
|
49
|
-
count = getter.count
|
50
|
-
|
51
|
-
assert records.count == 3
|
52
|
-
assert count = 3
|
53
|
-
assert records.first.id == 8
|
54
|
-
end
|
55
|
-
|
56
|
-
test 'HasMany Getter with search parameter' do
|
57
|
-
association = Owner.reflect_on_association(:trees)
|
58
|
-
|
59
|
-
getter = HasManyGetter.new(Owner, association, {
|
60
|
-
id: 1,
|
61
|
-
association_name: 'trees',
|
62
|
-
search: 'Fir',
|
63
|
-
page: { size: 15, number: 1 },
|
64
|
-
timezone: 'America/Nome'
|
65
|
-
})
|
66
|
-
getter.perform
|
67
|
-
records = getter.records
|
68
|
-
count = getter.count
|
69
|
-
|
70
|
-
assert records.count == 1
|
71
|
-
assert count = 1
|
72
|
-
assert records.first.id == 8
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
module ForestLiana
|
2
|
-
class PieStatGetterTest < ActiveSupport::TestCase
|
3
|
-
test 'Pie stat getter with an aggregate on a boolean field' do
|
4
|
-
stat = PieStatGetter.new(BooleanField, {
|
5
|
-
type: "Pie",
|
6
|
-
collection: "boolean_field",
|
7
|
-
timezone: "Europe/Paris",
|
8
|
-
aggregate: "Count",
|
9
|
-
group_by_field: "field"
|
10
|
-
})
|
11
|
-
|
12
|
-
stat.perform
|
13
|
-
assert stat.record.value.count == 0
|
14
|
-
end
|
15
|
-
|
16
|
-
test 'Pie stat getter with an aggregate on a foreign key' do
|
17
|
-
stat = PieStatGetter.new(BelongsToField, {
|
18
|
-
type: "Pie",
|
19
|
-
collection: "belongs_to_field",
|
20
|
-
timezone: "Europe/Paris",
|
21
|
-
aggregate: "Count",
|
22
|
-
group_by_field: "has_one_field_id"
|
23
|
-
})
|
24
|
-
|
25
|
-
stat.perform
|
26
|
-
assert stat.record.value.count == 30
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,86 +0,0 @@
|
|
1
|
-
module ForestLiana
|
2
|
-
class ResourceUpdaterTest < ActiveSupport::TestCase
|
3
|
-
|
4
|
-
collection = ForestLiana::Model::Collection.new({
|
5
|
-
name: 'SerializeField',
|
6
|
-
fields: [{
|
7
|
-
type: 'String',
|
8
|
-
field: 'field'
|
9
|
-
}]
|
10
|
-
})
|
11
|
-
|
12
|
-
ForestLiana.apimap << collection
|
13
|
-
ForestLiana.models << SerializeField
|
14
|
-
|
15
|
-
test 'Update a record on a "serialize" attribute with a missing value' do
|
16
|
-
params = ActionController::Parameters.new(
|
17
|
-
id: 1,
|
18
|
-
data: {
|
19
|
-
id: 1,
|
20
|
-
type: "SerializeField",
|
21
|
-
attributes: {}
|
22
|
-
}
|
23
|
-
)
|
24
|
-
updater = ResourceUpdater.new(SerializeField, params)
|
25
|
-
updater.perform
|
26
|
-
|
27
|
-
assert updater.record.valid?
|
28
|
-
assert updater.record.field == "value 1"
|
29
|
-
end
|
30
|
-
|
31
|
-
test 'Update a record on a "serialize" attribute with a null value' do
|
32
|
-
params = ActionController::Parameters.new(
|
33
|
-
id: 1,
|
34
|
-
data: {
|
35
|
-
id: 1,
|
36
|
-
type: "SerializeField",
|
37
|
-
attributes: {
|
38
|
-
field: nil
|
39
|
-
}
|
40
|
-
}
|
41
|
-
)
|
42
|
-
updater = ResourceUpdater.new(SerializeField, params)
|
43
|
-
updater.perform
|
44
|
-
|
45
|
-
assert updater.record.valid?
|
46
|
-
assert updater.record.field == []
|
47
|
-
end
|
48
|
-
|
49
|
-
test 'Update a record on a "serialize" attribute with a bad format value' do
|
50
|
-
params = ActionController::Parameters.new(
|
51
|
-
id: 1,
|
52
|
-
data: {
|
53
|
-
id: 1,
|
54
|
-
type: "SerializeField",
|
55
|
-
attributes: {
|
56
|
-
field: "Lucas"
|
57
|
-
}
|
58
|
-
}
|
59
|
-
)
|
60
|
-
updater = ResourceUpdater.new(SerializeField, params)
|
61
|
-
updater.perform
|
62
|
-
|
63
|
-
assert updater.record.valid?
|
64
|
-
assert updater.record.field == "value 1"
|
65
|
-
assert updater.errors[0][:detail] == "Bad format for 'field' attribute value."
|
66
|
-
end
|
67
|
-
|
68
|
-
test 'Update a record on a "serialize" attribute with a well formated value' do
|
69
|
-
params = ActionController::Parameters.new(
|
70
|
-
id: 1,
|
71
|
-
data: {
|
72
|
-
id: 1,
|
73
|
-
type: "SerializeField",
|
74
|
-
attributes: {
|
75
|
-
field: "[\"test\", \"test\"]"
|
76
|
-
}
|
77
|
-
}
|
78
|
-
)
|
79
|
-
updater = ResourceUpdater.new(SerializeField, params)
|
80
|
-
updater.perform
|
81
|
-
|
82
|
-
assert updater.record.valid?
|
83
|
-
assert updater.record.field == ["test", "test"]
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
@@ -1,185 +0,0 @@
|
|
1
|
-
module ForestLiana
|
2
|
-
class ScopeValidatorTest < ActiveSupport::TestCase
|
3
|
-
test 'Request with aggregated condition filters should be allowed if it matches the scope exactly' do
|
4
|
-
scope_validator = ForestLiana::ScopeValidator.new({
|
5
|
-
'aggregator' => 'and',
|
6
|
-
'conditions' => [
|
7
|
-
{ 'field' => 'name', 'value' => 'john', 'operator' => 'equal' },
|
8
|
-
{ 'field' => 'price', 'value' => '2500', 'operator' => 'equal' }
|
9
|
-
]
|
10
|
-
}, [])
|
11
|
-
|
12
|
-
allowed = scope_validator.is_scope_in_request?({
|
13
|
-
user_id: '1',
|
14
|
-
filters: JSON.generate({
|
15
|
-
aggregator: 'and',
|
16
|
-
conditions: [
|
17
|
-
{ field: 'name', value: 'john', operator: 'equal' },
|
18
|
-
{ field: 'price', value: '2500', operator: 'equal' }
|
19
|
-
]
|
20
|
-
})
|
21
|
-
})
|
22
|
-
assert allowed == true
|
23
|
-
end
|
24
|
-
|
25
|
-
test 'Request with simple condition filter should be allowed if it matches the scope exactly' do
|
26
|
-
scope_validator = ForestLiana::ScopeValidator.new({
|
27
|
-
'aggregator' => 'and',
|
28
|
-
'conditions' => [
|
29
|
-
{ 'field' => 'field', 'value' => 'value', 'operator' => 'equal' }
|
30
|
-
]
|
31
|
-
}, [])
|
32
|
-
allowed = scope_validator.is_scope_in_request?({
|
33
|
-
user_id: '1',
|
34
|
-
filters: JSON.generate({
|
35
|
-
field: 'field', value: 'value', operator: 'equal'
|
36
|
-
})
|
37
|
-
})
|
38
|
-
assert allowed == true
|
39
|
-
end
|
40
|
-
|
41
|
-
test 'Request with multiples condition filters should be allowed if it contains the scope ' do
|
42
|
-
scope_validator = ForestLiana::ScopeValidator.new({
|
43
|
-
'aggregator' => 'and',
|
44
|
-
'conditions' => [
|
45
|
-
{ 'field' => 'name', 'value' => 'doe', 'operator' => 'equal' }
|
46
|
-
]
|
47
|
-
}, []
|
48
|
-
)
|
49
|
-
|
50
|
-
allowed = scope_validator.is_scope_in_request?({
|
51
|
-
user_id: '1',
|
52
|
-
filters: JSON.generate({
|
53
|
-
aggregator: 'and',
|
54
|
-
conditions: [
|
55
|
-
{ field: 'name', value: 'doe', operator: 'equal' },
|
56
|
-
{ field: 'field2', value: 'value2', operator: 'equal' }
|
57
|
-
]
|
58
|
-
})
|
59
|
-
})
|
60
|
-
assert allowed == true
|
61
|
-
end
|
62
|
-
|
63
|
-
test 'Request with dynamic user values should be allowed if it matches the scope exactly' do
|
64
|
-
scope_validator = ForestLiana::ScopeValidator.new({
|
65
|
-
'aggregator' => 'and',
|
66
|
-
'conditions' => [
|
67
|
-
{ 'field' => 'name', 'value' => '$currentUser.lastname', 'operator' => 'equal' }
|
68
|
-
],
|
69
|
-
}, {
|
70
|
-
'1' => { '$currentUser.lastname' => 'john' }
|
71
|
-
})
|
72
|
-
|
73
|
-
allowed = scope_validator.is_scope_in_request?({
|
74
|
-
user_id: '1',
|
75
|
-
filters: JSON.generate({
|
76
|
-
'field' => 'name', 'value' => 'john', 'operator' => 'equal'
|
77
|
-
})
|
78
|
-
})
|
79
|
-
assert allowed == true
|
80
|
-
end
|
81
|
-
|
82
|
-
test 'Request with multiples aggregation and dynamic values should be allowed if it contains the scope' do
|
83
|
-
scope_validator = ForestLiana::ScopeValidator.new({
|
84
|
-
'aggregator' => 'or',
|
85
|
-
'conditions' => [
|
86
|
-
{ 'field' => 'price', 'value' => '2500', 'operator' => 'equal' },
|
87
|
-
{ 'field' => 'name', 'value' => '$currentUser.lastname', 'operator' => 'equal' }
|
88
|
-
]
|
89
|
-
}, {
|
90
|
-
'1' => { '$currentUser.lastname' => 'john' }
|
91
|
-
})
|
92
|
-
|
93
|
-
allowed = scope_validator.is_scope_in_request?({
|
94
|
-
user_id: '1',
|
95
|
-
filters: JSON.generate({
|
96
|
-
aggregator: 'and',
|
97
|
-
conditions: [
|
98
|
-
{ field: 'field', value: 'value', operator: 'equal' },
|
99
|
-
{
|
100
|
-
aggregator: 'or',
|
101
|
-
conditions: [
|
102
|
-
{ field: 'price', value: '2500', operator: 'equal' },
|
103
|
-
{ field: 'name', value: 'john', operator: 'equal' }
|
104
|
-
]
|
105
|
-
}
|
106
|
-
]
|
107
|
-
})
|
108
|
-
})
|
109
|
-
assert allowed == true
|
110
|
-
end
|
111
|
-
|
112
|
-
test 'Request that does not match the expect scope should not be allowed' do
|
113
|
-
scope_validator = ForestLiana::ScopeValidator.new({
|
114
|
-
'aggregator' => 'and',
|
115
|
-
'conditions' => [
|
116
|
-
{ 'field' => 'name', 'value' => 'john', 'operator' => 'equal' },
|
117
|
-
{ 'field' => 'price', 'value' => '2500', 'operator' => 'equal' }
|
118
|
-
]
|
119
|
-
}, [])
|
120
|
-
|
121
|
-
allowed = scope_validator.is_scope_in_request?({
|
122
|
-
user_id: '1',
|
123
|
-
filters: JSON.generate({
|
124
|
-
aggregator: 'and',
|
125
|
-
conditions: [
|
126
|
-
{ field: 'name', value: 'definitely_not_john', operator: 'equal' },
|
127
|
-
{ field: 'price', value: '0', operator: 'equal' }
|
128
|
-
]
|
129
|
-
})
|
130
|
-
})
|
131
|
-
assert allowed == false
|
132
|
-
end
|
133
|
-
|
134
|
-
test 'Request that are missing part of the scope should not be allowed' do
|
135
|
-
scope_validator = ForestLiana::ScopeValidator.new({
|
136
|
-
'aggregator' => 'and',
|
137
|
-
'conditions' => [
|
138
|
-
{ 'field' => 'name', 'value' => 'john', 'operator' => 'equal' },
|
139
|
-
{ 'field' => 'price', 'value' => '2500', 'operator' => 'equal' }
|
140
|
-
]
|
141
|
-
}, [])
|
142
|
-
|
143
|
-
allowed = scope_validator.is_scope_in_request?({
|
144
|
-
user_id: '1',
|
145
|
-
filters: JSON.generate({
|
146
|
-
aggregator: 'and',
|
147
|
-
conditions: [
|
148
|
-
{ field: 'name', value: 'john', operator: 'equal' },
|
149
|
-
]
|
150
|
-
})
|
151
|
-
})
|
152
|
-
assert allowed == false
|
153
|
-
end
|
154
|
-
|
155
|
-
test 'Request that does not have a top aggregator being "and" should not be allowed' do
|
156
|
-
scope_validator = ForestLiana::ScopeValidator.new({
|
157
|
-
'aggregator' => 'and',
|
158
|
-
'conditions' => [
|
159
|
-
{ 'field' => 'price', 'value' => '2500', 'operator' => 'equal' },
|
160
|
-
{ 'field' => 'name', 'value' => '$currentUser.lastname', 'operator' => 'equal' }
|
161
|
-
]
|
162
|
-
}, {
|
163
|
-
'1' => { '$currentUser.lastname' => 'john' }
|
164
|
-
})
|
165
|
-
|
166
|
-
allowed = scope_validator.is_scope_in_request?({
|
167
|
-
user_id: '1',
|
168
|
-
filters: JSON.generate({
|
169
|
-
aggregator: 'or',
|
170
|
-
conditions: [
|
171
|
-
{ field: 'field', value: 'value', operator: 'equal' },
|
172
|
-
{
|
173
|
-
aggregator: 'and',
|
174
|
-
conditions: [
|
175
|
-
{ field: 'price', value: '2500', operator: 'equal' },
|
176
|
-
{ field: 'name', value: 'john', operator: 'equal' }
|
177
|
-
]
|
178
|
-
}
|
179
|
-
]
|
180
|
-
})
|
181
|
-
})
|
182
|
-
assert allowed == false
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|