forest_liana 7.8.0 → 8.0.0.beta.2
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 +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({
|