Skip to content

Commit 2d278c0

Browse files
DrRaiderSteveBunlon
authored andcommitted
feat(smart-action): allow users to protect their smart-action APIs from unauthorized usage
1 parent 9aa63e1 commit 2d278c0

File tree

3 files changed

+92
-2
lines changed

3 files changed

+92
-2
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Change Log
22

33
## [Unreleased]
4+
### Added
5+
- Smart Action - Allow users to protect their smart-action APIs from unauthorized usage.
6+
47
### Changed
58
- Technical - Introduce conventional commits.
69
- Technical - Adapt release script to conventional commits.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
module ForestLiana
2+
class SmartActionsController < ForestLiana::ApplicationController
3+
if Rails::VERSION::MAJOR < 4
4+
before_filter :check_permission_for_smart_route
5+
else
6+
before_action :check_permission_for_smart_route
7+
end
8+
9+
private
10+
11+
def get_smart_action_request
12+
begin
13+
params[:data][:attributes]
14+
rescue => error
15+
FOREST_LOGGER.error "Smart Action execution error: #{error}"
16+
{}
17+
end
18+
end
19+
20+
def check_permission_for_smart_route
21+
begin
22+
23+
smart_action_request = get_smart_action_request
24+
if !smart_action_request.nil? && smart_action_request.has_key?(:smart_action_id)
25+
checker = ForestLiana::PermissionsChecker.new(
26+
find_resource(smart_action_request[:collection_name]),
27+
'actions',
28+
@rendering_id,
29+
get_smart_action_permission_info(forest_user, smart_action_request)
30+
)
31+
return head :forbidden unless checker.is_authorized?
32+
else
33+
FOREST_LOGGER.error 'Smart action execution error: Unable to retrieve the smart action id.'
34+
render serializer: nil, json: { status: 400 }, status: :bad_request
35+
end
36+
rescue => error
37+
FOREST_LOGGER.error "Smart Action execution error: #{error}"
38+
render serializer: nil, json: { status: 400 }, status: :bad_request
39+
end
40+
end
41+
42+
def find_resource(collection_name)
43+
begin
44+
resource = SchemaUtils.find_model_from_collection_name(collection_name)
45+
46+
if resource.nil? || !SchemaUtils.model_included?(resource) ||
47+
!resource.ancestors.include?(ActiveRecord::Base)
48+
render serializer: nil, json: { status: 404 }, status: :not_found
49+
end
50+
resource
51+
rescue => error
52+
FOREST_LOGGER.error "Find Collection error: #{error}\n#{format_stacktrace(error)}"
53+
render serializer: nil, json: { status: 404 }, status: :not_found
54+
end
55+
end
56+
57+
def get_smart_action_permission_info(user, smart_action_request)
58+
{
59+
user_id: user['id'],
60+
action_id: smart_action_request[:smart_action_id],
61+
}
62+
end
63+
end
64+
end

app/services/forest_liana/permissions_checker.rb

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ class PermissionsChecker
33
@@permissions_per_rendering = Hash.new
44
@@expiration_in_seconds = (ENV['FOREST_PERMISSIONS_EXPIRATION_IN_SECONDS'] || 3600).to_i
55

6-
def initialize(resource, permission_name, rendering_id)
6+
def initialize(resource, permission_name, rendering_id, smart_action_parameters = nil)
77
@collection_name = ForestLiana.name_for(resource)
88
@permission_name = permission_name
99
@rendering_id = rendering_id
10+
@smart_action_parameters = smart_action_parameters
1011
end
1112

1213
def is_authorized?
@@ -27,11 +28,33 @@ def get_last_retrieve
2728
@@permissions_per_rendering[@rendering_id]['last_retrieve']
2829
end
2930

31+
def smart_action_allowed?(smart_actions_permissions)
32+
if !@smart_action_parameters||
33+
!@smart_action_parameters[:user_id] ||
34+
!@smart_action_parameters[:action_id] ||
35+
!smart_actions_permissions ||
36+
!smart_actions_permissions[@smart_action_parameters[:action_id]]
37+
return false
38+
end
39+
40+
@user_id = @smart_action_parameters[:user_id]
41+
@action_id = @smart_action_parameters[:action_id]
42+
@smart_action_permissions = smart_actions_permissions[@action_id]
43+
@allowed = @smart_action_permissions['allowed']
44+
@users = @smart_action_permissions['users']
45+
46+
return @allowed && (@users.nil?|| @users.include?(@user_id.to_i));
47+
end
48+
3049
def is_allowed?
3150
permissions = get_permissions
3251
if permissions && permissions[@collection_name] &&
3352
permissions[@collection_name]['collection']
34-
permissions[@collection_name]['collection'][@permission_name]
53+
if @permission_name === 'actions'
54+
return smart_action_allowed?(permissions[@collection_name]['actions'])
55+
else
56+
return permissions[@collection_name]['collection'][@permission_name]
57+
end
3558
else
3659
false
3760
end

0 commit comments

Comments
 (0)