forest_liana 7.8.0 → 8.0.0.beta.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/forest_liana/actions_controller.rb +5 -3
- data/app/controllers/forest_liana/application_controller.rb +15 -0
- data/app/controllers/forest_liana/resources_controller.rb +31 -57
- data/app/controllers/forest_liana/smart_actions_controller.rb +44 -58
- data/app/controllers/forest_liana/stats_controller.rb +14 -58
- data/app/services/forest_liana/ability/exceptions/access_denied.rb +16 -0
- data/app/services/forest_liana/ability/exceptions/action_condition_error.rb +16 -0
- data/app/services/forest_liana/ability/exceptions/require_approval.rb +18 -0
- data/app/services/forest_liana/ability/exceptions/trigger_forbidden.rb +16 -0
- data/app/services/forest_liana/ability/fetch.rb +23 -0
- data/app/services/forest_liana/ability/permission/request_permission.rb +19 -0
- data/app/services/forest_liana/ability/permission/smart_action_checker.rb +71 -0
- data/app/services/forest_liana/ability/permission.rb +148 -0
- data/app/services/forest_liana/ability.rb +24 -0
- data/app/services/forest_liana/filters_parser.rb +7 -7
- data/app/services/forest_liana/leaderboard_stat_getter.rb +7 -7
- data/app/services/forest_liana/line_stat_getter.rb +8 -8
- data/app/services/forest_liana/pie_stat_getter.rb +17 -17
- data/app/services/forest_liana/stat_getter.rb +1 -2
- data/app/services/forest_liana/value_stat_getter.rb +7 -7
- data/lib/forest_liana/bootstrapper.rb +1 -1
- data/lib/forest_liana/version.rb +1 -1
- data/spec/dummy/lib/forest_liana/collections/island.rb +1 -1
- data/spec/requests/actions_controller_spec.rb +3 -4
- data/spec/requests/count_spec.rb +5 -9
- data/spec/requests/resources_spec.rb +55 -11
- data/spec/requests/stats_spec.rb +103 -42
- data/spec/services/forest_liana/ability/ability_spec.rb +48 -0
- data/spec/services/forest_liana/ability/permission/smart_action_checker_spec.rb +357 -0
- data/spec/services/forest_liana/ability/permission_spec.rb +332 -0
- data/spec/services/forest_liana/filters_parser_spec.rb +0 -12
- data/spec/services/forest_liana/line_stat_getter_spec.rb +9 -9
- data/spec/services/forest_liana/pie_stat_getter_spec.rb +7 -7
- data/spec/services/forest_liana/value_stat_getter_spec.rb +11 -11
- data/spec/spec_helper.rb +1 -0
- metadata +33 -17
- data/app/services/forest_liana/permissions_checker.rb +0 -223
- data/app/services/forest_liana/permissions_formatter.rb +0 -52
- data/app/services/forest_liana/permissions_getter.rb +0 -59
- data/spec/services/forest_liana/permissions_checker_acl_disabled_spec.rb +0 -713
- data/spec/services/forest_liana/permissions_checker_acl_enabled_spec.rb +0 -845
- data/spec/services/forest_liana/permissions_checker_live_queries_spec.rb +0 -175
- data/spec/services/forest_liana/permissions_formatter_spec.rb +0 -222
- data/spec/services/forest_liana/permissions_getter_spec.rb +0 -83
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'digest'
|
2
|
+
require 'deepsort'
|
3
|
+
|
4
|
+
module ForestLiana
|
5
|
+
module Ability
|
6
|
+
module Permission
|
7
|
+
include Fetch
|
8
|
+
|
9
|
+
TTL = (ENV['FOREST_PERMISSIONS_EXPIRATION_IN_SECONDS'] || 1).to_i.second
|
10
|
+
|
11
|
+
def is_crud_authorized?(action, user, collection)
|
12
|
+
return true unless has_permission_system?
|
13
|
+
|
14
|
+
user_data = get_user_data(user['id'])
|
15
|
+
collections_data = get_collections_permissions_data
|
16
|
+
|
17
|
+
begin
|
18
|
+
is_allowed = collections_data[collection.name][action].include? user_data['roleId']
|
19
|
+
# re-fetch if user permission is not allowed (may have been changed)
|
20
|
+
unless is_allowed
|
21
|
+
collections_data = get_collections_permissions_data(true)
|
22
|
+
is_allowed = collections_data[collection.name][action].include? user_data['roleId']
|
23
|
+
end
|
24
|
+
|
25
|
+
is_allowed
|
26
|
+
rescue
|
27
|
+
raise ForestLiana::Errors::ExpectedError.new(409, :conflict, "The collection #{collection} doesn't exist", 'collection not found')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def is_smart_action_authorized?(user, collection, parameters, endpoint, http_method)
|
32
|
+
user_data = get_user_data(user['id'])
|
33
|
+
collections_data = get_collections_permissions_data
|
34
|
+
begin
|
35
|
+
action = find_action_from_endpoint(collection.name, endpoint, http_method).name
|
36
|
+
|
37
|
+
smart_action_approval = SmartActionChecker.new(parameters, collection, collections_data[collection.name][:actions][action], user_data)
|
38
|
+
smart_action_approval.can_execute?
|
39
|
+
rescue
|
40
|
+
raise ForestLiana::Errors::ExpectedError.new(409, :conflict, "The collection #{collection} doesn't exist", 'collection not found')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def is_chart_authorized?(user, parameters)
|
45
|
+
parameters = parameters.to_h
|
46
|
+
parameters.delete('timezone')
|
47
|
+
parameters.delete('controller')
|
48
|
+
parameters.delete('action')
|
49
|
+
parameters.delete('collection')
|
50
|
+
parameters.delete('contextVariables')
|
51
|
+
|
52
|
+
|
53
|
+
hash_request = "#{parameters['type']}:#{Digest::SHA1.hexdigest(parameters.deep_sort.to_s)}"
|
54
|
+
allowed = get_chart_data(user['rendering_id']).to_s.include? hash_request
|
55
|
+
|
56
|
+
unless allowed
|
57
|
+
allowed = get_chart_data(user['rendering_id'], true).to_s.include? hash_request
|
58
|
+
end
|
59
|
+
|
60
|
+
allowed
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def get_user_data(user_id)
|
66
|
+
cache = Rails.cache.fetch('forest.users', expires_in: TTL) do
|
67
|
+
users = {}
|
68
|
+
get_permissions('/liana/v4/permissions/users').each do |user|
|
69
|
+
users[user['id'].to_s] = user
|
70
|
+
end
|
71
|
+
|
72
|
+
users
|
73
|
+
end
|
74
|
+
|
75
|
+
cache[user_id.to_s]
|
76
|
+
end
|
77
|
+
|
78
|
+
def get_collections_permissions_data(force_fetch = false)
|
79
|
+
Rails.cache.delete('forest.collections') if force_fetch == true
|
80
|
+
cache = Rails.cache.fetch('forest.collections', expires_in: TTL) do
|
81
|
+
collections = {}
|
82
|
+
get_permissions('/liana/v4/permissions/environment')['collections'].each do |name, collection|
|
83
|
+
collections[name] = format_collection_crud_permission(collection).merge!(format_collection_action_permission(collection))
|
84
|
+
end
|
85
|
+
|
86
|
+
collections
|
87
|
+
end
|
88
|
+
|
89
|
+
cache
|
90
|
+
end
|
91
|
+
|
92
|
+
def get_chart_data(rendering_id, force_fetch = false)
|
93
|
+
Rails.cache.delete('forest.stats') if force_fetch == true
|
94
|
+
Rails.cache.fetch('forest.stats', expires_in: TTL) do
|
95
|
+
stat_hash = []
|
96
|
+
get_permissions('/liana/v4/permissions/renderings/' + rendering_id)['stats'].each do |stat|
|
97
|
+
stat_hash << "#{stat['type']}:#{Digest::SHA1.hexdigest(stat.sort.to_h.to_s)}"
|
98
|
+
end
|
99
|
+
|
100
|
+
stat_hash
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def has_permission_system?
|
105
|
+
Rails.cache.fetch('forest.has_permission') do
|
106
|
+
(get_permissions('/liana/v4/permissions/environment') == true) ? false : true
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def format_collection_crud_permission(collection)
|
111
|
+
{
|
112
|
+
'browse' => collection['collection']['browseEnabled']['roles'],
|
113
|
+
'read' => collection['collection']['readEnabled']['roles'],
|
114
|
+
'edit' => collection['collection']['editEnabled']['roles'],
|
115
|
+
'add' => collection['collection']['addEnabled']['roles'],
|
116
|
+
'delete' => collection['collection']['deleteEnabled']['roles'],
|
117
|
+
'export' => collection['collection']['exportEnabled']['roles'],
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
121
|
+
def format_collection_action_permission(collection)
|
122
|
+
actions = {}
|
123
|
+
actions[:actions] = {}
|
124
|
+
collection['actions'].each do |id, action|
|
125
|
+
actions[:actions][id] = {
|
126
|
+
'triggerEnabled' => action['triggerEnabled']['roles'],
|
127
|
+
'triggerConditions' => action['triggerConditions'],
|
128
|
+
'approvalRequired' => action['approvalRequired']['roles'],
|
129
|
+
'approvalRequiredConditions' => action['approvalRequiredConditions'],
|
130
|
+
'userApprovalEnabled' => action['userApprovalEnabled']['roles'],
|
131
|
+
'userApprovalConditions' => action['userApprovalConditions'],
|
132
|
+
'selfApprovalEnabled' => action['selfApprovalEnabled']['roles'],
|
133
|
+
}
|
134
|
+
end
|
135
|
+
|
136
|
+
actions
|
137
|
+
end
|
138
|
+
|
139
|
+
def find_action_from_endpoint(collection_name, endpoint, http_method)
|
140
|
+
collection = ForestLiana.apimap.find { |collection| collection.name.to_s == collection_name }
|
141
|
+
|
142
|
+
return nil unless collection
|
143
|
+
|
144
|
+
collection.actions.find { |action| (action.endpoint == endpoint || "/#{action.endpoint}" == endpoint) && action.http_method == http_method }
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ForestLiana
|
2
|
+
module Ability
|
3
|
+
include ForestLiana::Ability::Permission
|
4
|
+
|
5
|
+
ALLOWED_PERMISSION_LEVELS = %w[admin editor developer].freeze
|
6
|
+
|
7
|
+
def forest_authorize!(action, user, collection, args = {})
|
8
|
+
case action
|
9
|
+
when 'browse', 'read', 'edit', 'add', 'delete', 'export'
|
10
|
+
raise ForestLiana::Ability::Exceptions::AccessDenied.new unless is_crud_authorized?(action, user, collection)
|
11
|
+
when 'chart'
|
12
|
+
if ALLOWED_PERMISSION_LEVELS.exclude?(user['permission_level'])
|
13
|
+
raise ForestLiana::Errors::HTTP422Error.new('The argument parameters is missing') if args[:parameters].nil?
|
14
|
+
raise ForestLiana::Ability::Exceptions::AccessDenied.new unless is_chart_authorized?(user, args[:parameters])
|
15
|
+
end
|
16
|
+
when 'action'
|
17
|
+
raise ForestLiana::Errors::HTTP422Error.new('You must implement the arguments : parameters, endpoint & http_method') if args[:parameters].nil? || args[:endpoint].nil? || args[:http_method].nil?
|
18
|
+
is_smart_action_authorized?(user, collection, args[:parameters], args[:endpoint], args[:http_method])
|
19
|
+
else
|
20
|
+
raise ForestLiana::Ability::Exceptions::AccessDenied.new
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -2,13 +2,9 @@ module ForestLiana
|
|
2
2
|
class FiltersParser
|
3
3
|
AGGREGATOR_OPERATOR = %w(and or)
|
4
4
|
|
5
|
-
def initialize(filters, resource, timezone)
|
6
|
-
|
7
|
-
|
8
|
-
rescue JSON::ParserError
|
9
|
-
raise ForestLiana::Errors::HTTP422Error.new('Invalid filters JSON format')
|
10
|
-
end
|
11
|
-
|
5
|
+
def initialize(filters, resource, timezone, params = nil)
|
6
|
+
@filters = filters.instance_of?(ActionController::Parameters) ? filters.to_h : JSON.parse(filters)
|
7
|
+
@params = params
|
12
8
|
@resource = resource
|
13
9
|
@operator_date_parser = OperatorDateIntervalParser.new(timezone)
|
14
10
|
@joins = []
|
@@ -91,6 +87,10 @@ module ForestLiana
|
|
91
87
|
value = condition['value']
|
92
88
|
field_name = condition['field']
|
93
89
|
|
90
|
+
if value.is_a?(String) && value.start_with?('{{')
|
91
|
+
value = @params[:contextVariables][value.gsub(/[{}]/, '')]
|
92
|
+
end
|
93
|
+
|
94
94
|
if @operator_date_parser.is_date_operator?(operator)
|
95
95
|
condition = @operator_date_parser.get_date_filter(operator, value)
|
96
96
|
return "#{parse_field_name(field_name)} #{condition}"
|
@@ -2,13 +2,13 @@ module ForestLiana
|
|
2
2
|
class LeaderboardStatGetter < StatGetter
|
3
3
|
def initialize(parent_model, params, forest_user)
|
4
4
|
@scoped_parent_model = get_scoped_model(parent_model, forest_user, params[:timezone])
|
5
|
-
child_model = @scoped_parent_model.reflect_on_association(params[:
|
5
|
+
child_model = @scoped_parent_model.reflect_on_association(params[:relationshipFieldName]).klass
|
6
6
|
@scoped_child_model = get_scoped_model(child_model, forest_user, params[:timezone])
|
7
|
-
@label_field = params[:
|
8
|
-
@aggregate = params[:
|
9
|
-
@aggregate_field = params[:
|
7
|
+
@label_field = params[:labelFieldName]
|
8
|
+
@aggregate = params[:aggregator].downcase
|
9
|
+
@aggregate_field = params[:aggregateFieldName]
|
10
10
|
@limit = params[:limit]
|
11
|
-
@
|
11
|
+
@group_by = "#{@scoped_parent_model.table_name}.#{@label_field}"
|
12
12
|
end
|
13
13
|
|
14
14
|
def perform
|
@@ -17,7 +17,7 @@ module ForestLiana
|
|
17
17
|
result = @scoped_child_model
|
18
18
|
.joins(includes)
|
19
19
|
.where({ @scoped_parent_model.name.downcase.to_sym => @scoped_parent_model })
|
20
|
-
.group(@
|
20
|
+
.group(@group_by)
|
21
21
|
.order(order)
|
22
22
|
.limit(@limit)
|
23
23
|
.send(@aggregate, @aggregate_field)
|
@@ -31,7 +31,7 @@ module ForestLiana
|
|
31
31
|
|
32
32
|
return model.unscoped if scope_filters.blank?
|
33
33
|
|
34
|
-
FiltersParser.new(scope_filters, model, timezone).apply_filters
|
34
|
+
FiltersParser.new(scope_filters, model, timezone, @params).apply_filters
|
35
35
|
end
|
36
36
|
|
37
37
|
def order
|
@@ -10,7 +10,7 @@ module ForestLiana
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def get_format
|
13
|
-
case @params[:
|
13
|
+
case @params[:timeRange].try(:downcase)
|
14
14
|
when 'day'
|
15
15
|
'%d/%m/%Y'
|
16
16
|
when 'week'
|
@@ -25,17 +25,17 @@ module ForestLiana
|
|
25
25
|
def perform
|
26
26
|
value = get_resource()
|
27
27
|
|
28
|
-
filters = ForestLiana::ScopeManager.append_scope_for_user(@params[:
|
28
|
+
filters = ForestLiana::ScopeManager.append_scope_for_user(@params[:filter], @user, @resource.name)
|
29
29
|
|
30
30
|
unless filters.blank?
|
31
|
-
value = FiltersParser.new(filters, @resource, @params[:timezone]).apply_filters
|
31
|
+
value = FiltersParser.new(filters, @resource, @params[:timezone], @params).apply_filters
|
32
32
|
end
|
33
33
|
|
34
34
|
Groupdate.week_start = :monday
|
35
35
|
|
36
|
-
value = value.send(
|
36
|
+
value = value.send(timeRange, group_by_date_field, time_zone: client_timezone)
|
37
37
|
|
38
|
-
value = value.send(@params[:
|
38
|
+
value = value.send(@params[:aggregator].downcase, @params[:aggregateFieldName])
|
39
39
|
.map do |k, v|
|
40
40
|
{ label: k.strftime(get_format), values: { value: v }}
|
41
41
|
end
|
@@ -46,11 +46,11 @@ module ForestLiana
|
|
46
46
|
private
|
47
47
|
|
48
48
|
def group_by_date_field
|
49
|
-
"#{@resource.table_name}.#{@params[:
|
49
|
+
"#{@resource.table_name}.#{@params[:groupByFieldName]}"
|
50
50
|
end
|
51
51
|
|
52
|
-
def
|
53
|
-
"group_by_#{@params[:
|
52
|
+
def timeRange
|
53
|
+
"group_by_#{@params[:timeRange].try(:downcase) || 'month'}"
|
54
54
|
end
|
55
55
|
|
56
56
|
end
|
@@ -3,30 +3,30 @@ module ForestLiana
|
|
3
3
|
attr_accessor :record
|
4
4
|
|
5
5
|
def perform
|
6
|
-
if @params[:
|
6
|
+
if @params[:groupByFieldName]
|
7
7
|
timezone_offset = @params[:timezone].to_i
|
8
8
|
resource = optimize_record_loading(@resource, get_resource)
|
9
9
|
|
10
|
-
filters = ForestLiana::ScopeManager.append_scope_for_user(@params[:
|
10
|
+
filters = ForestLiana::ScopeManager.append_scope_for_user(@params[:filter], @user, @resource.name)
|
11
11
|
|
12
12
|
unless filters.blank?
|
13
|
-
resource = FiltersParser.new(filters, resource, @params[:timezone]).apply_filters
|
13
|
+
resource = FiltersParser.new(filters, resource, @params[:timezone], @params).apply_filters
|
14
14
|
end
|
15
15
|
|
16
16
|
result = resource
|
17
|
-
.group(
|
17
|
+
.group(groupByFieldName)
|
18
18
|
.order(order)
|
19
|
-
.send(@params[:
|
19
|
+
.send(@params[:aggregator].downcase, @params[:aggregateFieldName])
|
20
20
|
.map do |key, value|
|
21
21
|
# NOTICE: Display the enum name instead of an integer if it is an
|
22
22
|
# "Enum" field type on old Rails version (before Rails
|
23
23
|
# 5.1.3).
|
24
24
|
if @resource.respond_to?(:defined_enums) &&
|
25
|
-
@resource.defined_enums.has_key?(@params[:
|
25
|
+
@resource.defined_enums.has_key?(@params[:groupByFieldName]) &&
|
26
26
|
key.is_a?(Integer)
|
27
|
-
key = @resource.defined_enums[@params[:
|
28
|
-
elsif @resource.columns_hash[@params[:
|
29
|
-
@resource.columns_hash[@params[:
|
27
|
+
key = @resource.defined_enums[@params[:groupByFieldName]].invert[key]
|
28
|
+
elsif @resource.columns_hash[@params[:groupByFieldName]] &&
|
29
|
+
@resource.columns_hash[@params[:groupByFieldName]].type == :datetime
|
30
30
|
key = (key + timezone_offset.hours).strftime('%d/%m/%Y %T')
|
31
31
|
end
|
32
32
|
|
@@ -37,13 +37,13 @@ module ForestLiana
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
def
|
41
|
-
if @params[:
|
42
|
-
association, field = @params[:
|
40
|
+
def groupByFieldName
|
41
|
+
if @params[:groupByFieldName].include? ':'
|
42
|
+
association, field = @params[:groupByFieldName].split ':'
|
43
43
|
resource = @resource.reflect_on_association(association.to_sym)
|
44
44
|
"#{resource.table_name}.#{field}"
|
45
45
|
else
|
46
|
-
"#{@resource.table_name}.#{@params[:
|
46
|
+
"#{@resource.table_name}.#{@params[:groupByFieldName]}"
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
@@ -51,14 +51,14 @@ module ForestLiana
|
|
51
51
|
order = 'DESC'
|
52
52
|
|
53
53
|
# NOTICE: The generated alias for a count is "count_all", for a sum the
|
54
|
-
# alias looks like "sum_#{
|
55
|
-
if @params[:
|
56
|
-
field = @params[:
|
54
|
+
# alias looks like "sum_#{aggregateFieldName}"
|
55
|
+
if @params[:aggregator].downcase == 'sum'
|
56
|
+
field = @params[:aggregateFieldName].downcase
|
57
57
|
else
|
58
58
|
# `count_id` is required only for rails v5
|
59
59
|
field = Rails::VERSION::MAJOR == 5 || @includes.size > 0 ? 'id' : 'all'
|
60
60
|
end
|
61
|
-
"#{@params[:
|
61
|
+
"#{@params[:aggregator].downcase}_#{field} #{order}"
|
62
62
|
end
|
63
63
|
|
64
64
|
end
|
@@ -3,13 +3,13 @@ module ForestLiana
|
|
3
3
|
attr_accessor :record
|
4
4
|
|
5
5
|
def perform
|
6
|
-
return if @params[:
|
6
|
+
return if @params[:aggregator].blank?
|
7
7
|
resource = optimize_record_loading(@resource, get_resource)
|
8
8
|
|
9
|
-
filters = ForestLiana::ScopeManager.append_scope_for_user(@params[:
|
9
|
+
filters = ForestLiana::ScopeManager.append_scope_for_user(@params[:filter], @user, @resource.name)
|
10
10
|
|
11
11
|
unless filters.blank?
|
12
|
-
filter_parser = FiltersParser.new(filters, resource, @params[:timezone])
|
12
|
+
filter_parser = FiltersParser.new(filters, resource, @params[:timezone], @params)
|
13
13
|
resource = filter_parser.apply_filters
|
14
14
|
raw_previous_interval = filter_parser.get_previous_interval_condition
|
15
15
|
|
@@ -27,21 +27,21 @@ module ForestLiana
|
|
27
27
|
private
|
28
28
|
|
29
29
|
def count(value)
|
30
|
-
uniq = @params[:
|
30
|
+
uniq = @params[:aggregator].downcase == 'count'
|
31
31
|
|
32
32
|
if Rails::VERSION::MAJOR >= 4
|
33
33
|
if uniq
|
34
34
|
# NOTICE: uniq is deprecated since Rails 5.0
|
35
35
|
value = Rails::VERSION::MAJOR >= 5 ? value.distinct : value.uniq
|
36
36
|
end
|
37
|
-
value.send(@params[:
|
37
|
+
value.send(@params[:aggregator].downcase, aggregate_field)
|
38
38
|
else
|
39
|
-
value.send(@params[:
|
39
|
+
value.send(@params[:aggregator].downcase, aggregate_field, distinct: uniq)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
43
|
def aggregate_field
|
44
|
-
@params[:
|
44
|
+
@params[:aggregateFieldName] || @resource.primary_key
|
45
45
|
end
|
46
46
|
|
47
47
|
end
|
@@ -202,7 +202,7 @@ module ForestLiana
|
|
202
202
|
def setup_forest_liana_meta
|
203
203
|
ForestLiana.meta = {
|
204
204
|
liana: 'forest-rails',
|
205
|
-
liana_version: ForestLiana::VERSION,
|
205
|
+
liana_version: ForestLiana::VERSION.sub!('.beta', '-beta'),
|
206
206
|
stack: {
|
207
207
|
database_type: database_type,
|
208
208
|
orm_version: Gem.loaded_specs["activerecord"].version.version,
|
data/lib/forest_liana/version.rb
CHANGED
@@ -171,10 +171,9 @@ describe 'Requesting Actions routes', :type => :request do
|
|
171
171
|
expect(JSON.parse(response.body)).to eq({'fields' => [foo.merge({:value => nil}).transform_keys { |key| key.to_s.camelize(:lower) }.stringify_keys]})
|
172
172
|
end
|
173
173
|
|
174
|
-
it 'should respond
|
174
|
+
it 'should respond 422 with bad params' do
|
175
175
|
post '/forest/actions/my_action/hooks/load', params: {}, headers: headers
|
176
|
-
expect(response.status).to eq(
|
177
|
-
expect(JSON.parse(response.body)).to eq({'error' => 'Error in smart action load hook: cannot retrieve action from collection'})
|
176
|
+
expect(response.status).to eq(422)
|
178
177
|
end
|
179
178
|
|
180
179
|
it 'should respond 500 with bad hook result type' do
|
@@ -315,7 +314,7 @@ describe 'Requesting Actions routes', :type => :request do
|
|
315
314
|
|
316
315
|
describe 'calling the action' do
|
317
316
|
before(:each) do
|
318
|
-
allow_any_instance_of(ForestLiana::
|
317
|
+
allow_any_instance_of(ForestLiana::Ability).to receive(:forest_authorize!) { true }
|
319
318
|
end
|
320
319
|
|
321
320
|
let(:all_records) { false }
|
data/spec/requests/count_spec.rb
CHANGED
@@ -2,22 +2,18 @@ require 'rails_helper'
|
|
2
2
|
|
3
3
|
describe 'Requesting Owner', :type => :request do
|
4
4
|
before(:each) do
|
5
|
+
Owner.destroy_all
|
6
|
+
|
5
7
|
1.upto(10) do |i|
|
6
8
|
owner = Owner.create(name: "Owner #{i}")
|
7
9
|
Tree.create(name: "Tree #{i}", owner_id: owner.id)
|
8
10
|
end
|
9
|
-
end
|
10
11
|
|
11
|
-
after(:each) do
|
12
|
-
Owner.destroy_all
|
13
|
-
end
|
14
|
-
|
15
|
-
before(:each) do
|
16
12
|
allow(ForestLiana::IpWhitelist).to receive(:retrieve) { true }
|
17
13
|
allow(ForestLiana::IpWhitelist).to receive(:is_ip_whitelist_retrieved) { true }
|
18
14
|
allow(ForestLiana::IpWhitelist).to receive(:is_ip_valid) { true }
|
19
15
|
|
20
|
-
allow_any_instance_of(ForestLiana::
|
16
|
+
allow_any_instance_of(ForestLiana::Ability).to receive(:forest_authorize!) { true }
|
21
17
|
|
22
18
|
allow(ForestLiana::ScopeManager).to receive(:fetch_scopes).and_return({})
|
23
19
|
end
|
@@ -68,12 +64,12 @@ describe 'Requesting Owner', :type => :request do
|
|
68
64
|
}
|
69
65
|
|
70
66
|
it 'should respond 200' do
|
71
|
-
get '/forest/Owner/
|
67
|
+
get '/forest/Owner/5/relationships/trees/count', params: params, headers: headers
|
72
68
|
expect(response.status).to eq(200)
|
73
69
|
end
|
74
70
|
|
75
71
|
it 'should equal to 1' do
|
76
|
-
get '/forest/Owner/
|
72
|
+
get '/forest/Owner/5/relationships/trees/count', params: params, headers: headers
|
77
73
|
expect(response.body).to eq('{"count":1}')
|
78
74
|
end
|
79
75
|
end
|
@@ -1,28 +1,42 @@
|
|
1
1
|
require 'rails_helper'
|
2
2
|
|
3
3
|
describe 'Requesting Tree resources', :type => :request do
|
4
|
-
|
4
|
+
|
5
|
+
before do
|
5
6
|
user = User.create(name: 'Michel')
|
6
7
|
tree = Tree.create(name: 'Lemon Tree', owner: user, cutter: user)
|
7
|
-
end
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
Rails.cache.write('forest.users', {'1' => { 'id' => 1, 'roleId' => 1, 'rendering_id' => '1' }})
|
10
|
+
Rails.cache.write('forest.has_permission', true)
|
11
|
+
Rails.cache.write(
|
12
|
+
'forest.collections',
|
13
|
+
{
|
14
|
+
'Tree' => {
|
15
|
+
'browse' => [1],
|
16
|
+
'read' => [1],
|
17
|
+
'edit' => [1],
|
18
|
+
'add' => [1],
|
19
|
+
'delete' => [1],
|
20
|
+
'export' => [1],
|
21
|
+
'actions' => {}
|
22
|
+
}
|
23
|
+
}
|
24
|
+
)
|
13
25
|
|
14
|
-
before(:each) do
|
15
26
|
allow(ForestLiana::IpWhitelist).to receive(:retrieve) { true }
|
16
27
|
allow(ForestLiana::IpWhitelist).to receive(:is_ip_whitelist_retrieved) { true }
|
17
28
|
allow(ForestLiana::IpWhitelist).to receive(:is_ip_valid) { true }
|
18
|
-
|
19
|
-
allow_any_instance_of(ForestLiana::PermissionsChecker).to receive(:is_authorized?) { true }
|
20
|
-
|
29
|
+
# allow_any_instance_of(ForestLiana::Ability).to receive(:forest_authorize!) { true }
|
21
30
|
allow(ForestLiana::ScopeManager).to receive(:fetch_scopes).and_return({})
|
22
31
|
end
|
23
32
|
|
33
|
+
after do
|
34
|
+
User.destroy_all
|
35
|
+
Tree.destroy_all
|
36
|
+
end
|
37
|
+
|
24
38
|
token = JWT.encode({
|
25
|
-
id:
|
39
|
+
id: 1,
|
26
40
|
email: 'michael.kelso@that70.show',
|
27
41
|
first_name: 'Michael',
|
28
42
|
last_name: 'Kelso',
|
@@ -53,6 +67,36 @@ describe 'Requesting Tree resources', :type => :request do
|
|
53
67
|
expect(response.status).to eq(200)
|
54
68
|
end
|
55
69
|
|
70
|
+
it 'should return 403 when user permission is not allowed' do
|
71
|
+
Rails.cache.delete('forest.users')
|
72
|
+
Rails.cache.write('forest.users', {'1' => { 'id' => 1, 'roleId' => 2, 'rendering_id' => '1' }})
|
73
|
+
allow_any_instance_of(ForestLiana::Ability::Fetch)
|
74
|
+
.to receive(:get_permissions)
|
75
|
+
.with('/liana/v4/permissions/environment')
|
76
|
+
.and_return(
|
77
|
+
{
|
78
|
+
"collections" => {
|
79
|
+
"Tree" => {
|
80
|
+
"collection" => {
|
81
|
+
"browseEnabled" => { "roles" => [1] },
|
82
|
+
"readEnabled" => { "roles" => [1] },
|
83
|
+
"editEnabled" => { "roles" => [1] },
|
84
|
+
"addEnabled" => { "roles" => [1] },
|
85
|
+
"deleteEnabled" => { "roles" => [1] },
|
86
|
+
"exportEnabled" => { "roles" => [1] }
|
87
|
+
},
|
88
|
+
"actions"=> {}
|
89
|
+
}
|
90
|
+
}
|
91
|
+
}
|
92
|
+
)
|
93
|
+
|
94
|
+
get '/forest/Tree', params: params, headers: headers
|
95
|
+
|
96
|
+
expect(response.status).to eq(403)
|
97
|
+
expect(JSON.parse(response.body)['errors'][0]['detail']).to eq 'You don\'t have permission to access this resource'
|
98
|
+
end
|
99
|
+
|
56
100
|
it 'should respond the tree data' do
|
57
101
|
get '/forest/Tree', params: params, headers: headers
|
58
102
|
expect(JSON.parse(response.body)).to eq({
|