Class: ForestAdminAgent::Services::Permissions

Inherits:
Object
  • Object
show all
Includes:
Http::Exceptions, Utils, ForestAdminDatasourceToolkit::Components::Query::ConditionTree, ForestAdminDatasourceToolkit::Exceptions
Defined in:
lib/forest_admin_agent/services/permissions.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(caller) ⇒ Permissions

Returns a new instance of Permissions.



14
15
16
17
18
19
20
21
22
# File 'lib/forest_admin_agent/services/permissions.rb', line 14

def initialize(caller)
  @caller = caller
  @forest_api = ForestAdminAgent::Http::ForestAdminApiRequester.new
  @cache = FileCache.new(
    'permissions',
    Facades::Container.config_from_cache[:cache_dir].to_s,
    Facades::Container.config_from_cache[:permission_expiration]
  )
end

Instance Attribute Details

#cacheObject (readonly)

Returns the value of attribute cache.



12
13
14
# File 'lib/forest_admin_agent/services/permissions.rb', line 12

def cache
  @cache
end

#callerObject (readonly)

Returns the value of attribute caller.



12
13
14
# File 'lib/forest_admin_agent/services/permissions.rb', line 12

def caller
  @caller
end

#forest_apiObject (readonly)

Returns the value of attribute forest_api.



12
13
14
# File 'lib/forest_admin_agent/services/permissions.rb', line 12

def forest_api
  @forest_api
end

Class Method Details

.invalidate_cache(id_cache = nil) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/forest_admin_agent/services/permissions.rb', line 24

def self.invalidate_cache(id_cache = nil)
  cache = FileCache.new(
    'permissions',
    Facades::Container.config_from_cache[:cache_dir].to_s,
    Facades::Container.config_from_cache[:permission_expiration]
  )

  cache.clear if id_cache.nil?

  cache.delete(id_cache) unless cache.get(id_cache).nil?

  ForestAdminAgent::Facades::Container.logger.log('Info', "Invalidating #{id_cache} cache..")
end

Instance Method Details

#can?(action, collection, allow_fetch: false) ⇒ Boolean

Returns:

  • (Boolean)

Raises:



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/forest_admin_agent/services/permissions.rb', line 38

def can?(action, collection, allow_fetch: false)
  return true unless permission_system?

  user_data = get_user_data(caller.id)
  collections_data = get_collections_permissions_data(force_fetch: allow_fetch)

  is_allowed = permission_allowed?(collections_data, collection, action, user_data)

  unless is_allowed
    collections_data = get_collections_permissions_data(force_fetch: true)
    is_allowed = permission_allowed?(collections_data, collection, action, user_data)
  end

  raise ForbiddenError, "You don't have permission to #{action} this collection." unless is_allowed

  is_allowed
end

#can_chart?(parameters) ⇒ Boolean

Returns:

  • (Boolean)


56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/forest_admin_agent/services/permissions.rb', line 56

def can_chart?(parameters)
  attributes = sanitize_chart_parameters(parameters.deep_symbolize_keys)
  hash_request = "#{attributes[:type]}:#{array_hash(attributes)}"
  is_allowed = get_chart_data(caller.rendering_id).include?(hash_request)

  is_allowed ||= get_chart_data(caller.rendering_id, force_fetch: true).include?(hash_request)

  unless is_allowed
    ForestAdminAgent::Facades::Container.logger.log(
      'Debug',
      "User #{caller.id} cannot retrieve chart on rendering #{caller.rendering_id}"
    )
    raise ForbiddenError, "You don't have permission to access this collection."
  end

  ForestAdminAgent::Facades::Container.logger.log(
    'Debug',
    "User #{caller.id} can retrieve chart on rendering #{caller.rendering_id}"
  )

  is_allowed
end

#can_execute_query_segment?(collection, query, connection_name) ⇒ Boolean

Returns:

  • (Boolean)


79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/forest_admin_agent/services/permissions.rb', line 79

def can_execute_query_segment?(collection, query, connection_name)
  user_data = get_user_data(caller.id)
  if %w[admin developer editor].include?(user_data&.dig(:permissionLevel))
    ForestAdminAgent::Facades::Container.logger.log(
      'Debug',
      "User #{caller.id} can retrieve SQL segment on rendering #{caller.rendering_id}"
    )
    return true
  end

  collection_permissions = get_collection_rendering_permissions(collection, force_fetch: false)

  is_allowed = segment_permissions_valid?(collection_permissions, query, connection_name)

  unless is_allowed
    collection_permissions = get_collection_rendering_permissions(collection, force_fetch: true)
    is_allowed = segment_permissions_valid?(collection_permissions, query, connection_name)
  end

  unless is_allowed
    ForestAdminAgent::Facades::Container.logger.log(
      'Debug',
      "User #{caller.id} cannot retrieve query segment on rendering #{caller.rendering_id}"
    )

    raise ForbiddenError, "You don't have permission to use this query segment."
  end

  ForestAdminAgent::Facades::Container.logger.log(
    'Debug',
    "User #{caller.id} can retrieve query segment on rendering #{caller.rendering_id}"
  )

  is_allowed
end

#can_smart_action?(request, collection, filter, allow_fetch: true) ⇒ Boolean

Returns:

  • (Boolean)


115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/forest_admin_agent/services/permissions.rb', line 115

def can_smart_action?(request, collection, filter, allow_fetch: true)
  return true unless permission_system?

  user_data = get_user_data(caller.id)
  collections_data = get_collections_permissions_data(force_fetch: allow_fetch)
  action = find_action_from_endpoint(collection.name, request[:headers]['REQUEST_PATH'], request[:headers]['REQUEST_METHOD'])

  collection_actions = validate_smart_action_permissions(collections_data, collection, action)

  smart_action_approval = SmartActionChecker.new(
    request[:params],
    collection,
    collection_actions[action['name'].to_sym],
    caller,
    user_data[:roleId],
    filter
  )

  is_allowed = smart_action_approval.can_execute?
  ForestAdminAgent::Facades::Container.logger.log(
    'Debug',
    "User #{user_data[:roleId]} is #{"not" unless is_allowed} allowed to perform #{action["name"]}"
  )

  is_allowed
end

#get_scope(collection) ⇒ Object



142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/forest_admin_agent/services/permissions.rb', line 142

def get_scope(collection)
  permissions = get_rendering_data(caller.rendering_id)
  scope = permissions[:scopes][collection.name.to_sym]

  return nil if scope.nil?

  team = get_team(caller.rendering_id)
  user = get_user_data(caller.id)

  context_variables = ContextVariables.new(team, user)

  ContextVariablesInjector.inject_context_in_filter(scope, context_variables)
end

#get_segments(collection, force_fetch: false) ⇒ Object



156
157
158
159
160
# File 'lib/forest_admin_agent/services/permissions.rb', line 156

def get_segments(collection, force_fetch: false)
  permissions = get_rendering_data(caller.rendering_id, force_fetch: force_fetch)

  permissions[:segments][collection.name.to_sym]
end

#get_team(rendering_id) ⇒ Object



177
178
179
180
181
# File 'lib/forest_admin_agent/services/permissions.rb', line 177

def get_team(rendering_id)
  permissions = get_rendering_data(rendering_id)

  permissions[:team]
end

#get_user_data(user_id) ⇒ Object



162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/forest_admin_agent/services/permissions.rb', line 162

def get_user_data(user_id)
  cache.get_or_set('forest.users') do
    response = fetch('/liana/v4/permissions/users')
    users = {}

    response.each do |user|
      users[user[:id].to_s] = user
    end

    ForestAdminAgent::Facades::Container.logger.log('Debug', 'Refreshing user permissions cache')

    users
  end[user_id.to_s]
end