strongbolt 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.editorconfig +33 -0
- data/.gitignore +18 -0
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +130 -0
- data/LICENSE.txt +22 -0
- data/README.md +182 -0
- data/Rakefile +1 -0
- data/app/assets/javascripts/strongbolt.js +1 -0
- data/app/assets/javascripts/strongbolt/role-capabilities.js +80 -0
- data/app/controllers/strongbolt/capabilities_controller.rb +77 -0
- data/app/controllers/strongbolt/roles_controller.rb +92 -0
- data/app/controllers/strongbolt/security_controller.rb +8 -0
- data/app/controllers/strongbolt/user_groups_controller.rb +76 -0
- data/app/controllers/strongbolt/user_groups_users_controller.rb +35 -0
- data/app/controllers/strongbolt_controller.rb +2 -0
- data/app/views/strongbolt/_menu.html.erb +13 -0
- data/app/views/strongbolt/capabilities/index.html.erb +53 -0
- data/app/views/strongbolt/capabilities/show.html.erb +53 -0
- data/app/views/strongbolt/roles/_capabilities.html.erb +47 -0
- data/app/views/strongbolt/roles/_capability.html.erb +21 -0
- data/app/views/strongbolt/roles/_form.html.erb +12 -0
- data/app/views/strongbolt/roles/edit.html.erb +14 -0
- data/app/views/strongbolt/roles/index.html.erb +54 -0
- data/app/views/strongbolt/roles/new.html.erb +11 -0
- data/app/views/strongbolt/roles/show.html.erb +52 -0
- data/app/views/strongbolt/user_groups/_form.html.erb +12 -0
- data/app/views/strongbolt/user_groups/edit.html.erb +14 -0
- data/app/views/strongbolt/user_groups/index.html.erb +46 -0
- data/app/views/strongbolt/user_groups/new.html.erb +13 -0
- data/app/views/strongbolt/user_groups/show.html.erb +88 -0
- data/lib/generators/strongbolt/fix_generator.rb +23 -0
- data/lib/generators/strongbolt/indexes_generator.rb +19 -0
- data/lib/generators/strongbolt/install_generator.rb +29 -0
- data/lib/generators/strongbolt/templates/fix.rb +5 -0
- data/lib/generators/strongbolt/templates/indexes.rb +21 -0
- data/lib/generators/strongbolt/templates/migration.rb +73 -0
- data/lib/generators/strongbolt/templates/strongbolt.rb +45 -0
- data/lib/generators/strongbolt/views_generator.rb +26 -0
- data/lib/strongbolt.rb +219 -0
- data/lib/strongbolt/base.rb +7 -0
- data/lib/strongbolt/bolted.rb +125 -0
- data/lib/strongbolt/bolted_controller.rb +297 -0
- data/lib/strongbolt/capabilities_role.rb +15 -0
- data/lib/strongbolt/capability.rb +165 -0
- data/lib/strongbolt/configuration.rb +111 -0
- data/lib/strongbolt/controllers/url_helpers.rb +37 -0
- data/lib/strongbolt/engine.rb +44 -0
- data/lib/strongbolt/errors.rb +38 -0
- data/lib/strongbolt/generators/migration.rb +35 -0
- data/lib/strongbolt/helpers.rb +18 -0
- data/lib/strongbolt/rails/routes.rb +20 -0
- data/lib/strongbolt/role.rb +46 -0
- data/lib/strongbolt/roles_user_group.rb +15 -0
- data/lib/strongbolt/rspec.rb +29 -0
- data/lib/strongbolt/rspec/user.rb +90 -0
- data/lib/strongbolt/tenantable.rb +304 -0
- data/lib/strongbolt/user_abilities.rb +292 -0
- data/lib/strongbolt/user_group.rb +24 -0
- data/lib/strongbolt/user_groups_user.rb +16 -0
- data/lib/strongbolt/users_tenant.rb +12 -0
- data/lib/strongbolt/version.rb +3 -0
- data/lib/tasks/strongbolt_tasks.rake +29 -0
- data/spec/controllers/strongbolt/capabilities_controller_spec.rb +254 -0
- data/spec/controllers/strongbolt/roles_controller_spec.rb +228 -0
- data/spec/controllers/strongbolt/user_groups_controller_spec.rb +216 -0
- data/spec/controllers/strongbolt/user_groups_users_controller_spec.rb +69 -0
- data/spec/controllers/without_authorization_controller_spec.rb +20 -0
- data/spec/dummy/.rspec +2 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/controllers/posts_controller.rb +18 -0
- data/spec/dummy/app/controllers/test_controller.rb +3 -0
- data/spec/dummy/app/controllers/without_authorization_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +29 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +78 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/assets.rb +8 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/strongbolt.rb +32 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +12 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20150630212236_create_strongbolt_tables.rb +54 -0
- data/spec/dummy/db/migrate/20150630212251_create_strongbolt_tables_indexes.rb +21 -0
- data/spec/dummy/db/schema.rb +84 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/fabricators/capability_fabricator.rb +4 -0
- data/spec/fabricators/role_fabricator.rb +9 -0
- data/spec/fabricators/user_fabricator.rb +3 -0
- data/spec/fabricators/user_group_fabricator.rb +9 -0
- data/spec/fixtures/application.rb +28 -0
- data/spec/fixtures/controllers.rb +5 -0
- data/spec/spec_helper.rb +89 -0
- data/spec/strongbolt/bolted_controller_spec.rb +706 -0
- data/spec/strongbolt/bolted_spec.rb +136 -0
- data/spec/strongbolt/capability_spec.rb +251 -0
- data/spec/strongbolt/configuration_spec.rb +119 -0
- data/spec/strongbolt/controllers/url_helpers_spec.rb +34 -0
- data/spec/strongbolt/helpers_spec.rb +43 -0
- data/spec/strongbolt/role_spec.rb +90 -0
- data/spec/strongbolt/tenantable_spec.rb +281 -0
- data/spec/strongbolt/user_abilities_spec.rb +509 -0
- data/spec/strongbolt/user_group_spec.rb +37 -0
- data/spec/strongbolt/users_tenant_spec.rb +36 -0
- data/spec/strongbolt_spec.rb +274 -0
- data/spec/support/controller_macros.rb +11 -0
- data/spec/support/db_setup.rb +134 -0
- data/spec/support/helpers.rb +62 -0
- data/spec/support/transactional_specs.rb +17 -0
- data/strongbolt.gemspec +32 -0
- metadata +407 -0
@@ -0,0 +1,73 @@
|
|
1
|
+
class CreateStrongboltTables < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :strongbolt_capabilities, :force => true do |t|
|
4
|
+
t.string :name
|
5
|
+
t.string :description
|
6
|
+
t.string :model
|
7
|
+
t.string :action
|
8
|
+
t.string :attr
|
9
|
+
t.boolean :require_ownership, :default => false, :null => false
|
10
|
+
t.boolean :require_tenant_access, :default => true, :null => false
|
11
|
+
|
12
|
+
t.timestamps
|
13
|
+
end
|
14
|
+
|
15
|
+
create_table :strongbolt_roles, :force => true do |t|
|
16
|
+
t.string :name
|
17
|
+
t.integer :parent_id
|
18
|
+
t.integer :lft
|
19
|
+
t.integer :rgt
|
20
|
+
t.string :description
|
21
|
+
|
22
|
+
t.timestamps
|
23
|
+
end
|
24
|
+
|
25
|
+
create_table :strongbolt_user_groups, :force => true do |t|
|
26
|
+
t.string :name
|
27
|
+
t.text :description
|
28
|
+
|
29
|
+
t.timestamps
|
30
|
+
end
|
31
|
+
|
32
|
+
create_table :strongbolt_user_groups_users, :force => true do |t|
|
33
|
+
t.integer :user_group_id
|
34
|
+
t.integer :user_id
|
35
|
+
end
|
36
|
+
|
37
|
+
create_table :strongbolt_roles_user_groups, :force => true do |t|
|
38
|
+
t.integer :user_group_id
|
39
|
+
t.integer :role_id
|
40
|
+
end
|
41
|
+
|
42
|
+
create_table :strongbolt_capabilities_roles, :force => true do |t|
|
43
|
+
t.integer :role_id
|
44
|
+
t.integer :capability_id
|
45
|
+
end
|
46
|
+
|
47
|
+
create_table :strongbolt_users_tenants, :force => true do |t|
|
48
|
+
t.integer :user_id
|
49
|
+
t.integer :tenant_id
|
50
|
+
t.string :type
|
51
|
+
end
|
52
|
+
|
53
|
+
# Indexes
|
54
|
+
add_index :strongbolt_roles, :parent_id
|
55
|
+
add_index :strongbolt_roles, :lft
|
56
|
+
add_index :strongbolt_roles, :rgt
|
57
|
+
|
58
|
+
add_index :strongbolt_user_groups_users, :user_group_id
|
59
|
+
add_index :strongbolt_user_groups_users, :user_id
|
60
|
+
|
61
|
+
add_index :strongbolt_roles_user_groups, :user_group_id
|
62
|
+
add_index :strongbolt_roles_user_groups, :role_id
|
63
|
+
|
64
|
+
add_index :strongbolt_capabilities_roles, :role_id
|
65
|
+
add_index :strongbolt_capabilities_roles, :capability_id
|
66
|
+
|
67
|
+
add_index :strongbolt_users_tenants, :user_id
|
68
|
+
add_index :strongbolt_users_tenants, :tenant_id
|
69
|
+
add_index :strongbolt_users_tenants, :type
|
70
|
+
add_index :strongbolt_users_tenants, [:tenant_id, :type]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
Strongbolt.setup do |config|
|
2
|
+
# Configure here the logger used by Strongbolt
|
3
|
+
config.logger = Rails.logger
|
4
|
+
|
5
|
+
#
|
6
|
+
# Set here the class name of your user class, if different than "User"
|
7
|
+
#
|
8
|
+
# config.user_class = "User"
|
9
|
+
|
10
|
+
#
|
11
|
+
# You can use this block to perform specific actions when a user is denied the access somewhere
|
12
|
+
#
|
13
|
+
# config.access_denied do |user, instance, action, request|
|
14
|
+
# Rails.logger.warn "User #{user.try :id} was refused to perform #{action} on #{instance.try :inspect} with request #{request}"
|
15
|
+
# end
|
16
|
+
|
17
|
+
#
|
18
|
+
# Specify here the list of tenants used by your application
|
19
|
+
#
|
20
|
+
# config.tenants = "Client", "Region"
|
21
|
+
|
22
|
+
#
|
23
|
+
# You can specify here some controllers where you don't want to perform any controller authorization check up
|
24
|
+
# It can be useful for instance with devise controllers, to avoid subclassing them.
|
25
|
+
# Write the controller names the same way you would with routes
|
26
|
+
#
|
27
|
+
# config.skip_controller_authorization_for "devise/confirmation"
|
28
|
+
|
29
|
+
#
|
30
|
+
# List here the set of default permissions granted to every user
|
31
|
+
# You will usually let every user access its own information for instance
|
32
|
+
#
|
33
|
+
config.default_capabilities = [
|
34
|
+
{:model => "User", :require_ownership => true, :require_tenant_access => false, :actions => [:find]}
|
35
|
+
]
|
36
|
+
|
37
|
+
#
|
38
|
+
# If given a tenant, Strongbolt will try to detect all the models within your application.
|
39
|
+
# However, if some models don't have any direct or indirect dependencies on one of your tenant,
|
40
|
+
# Strongbolt won't find it.
|
41
|
+
#
|
42
|
+
# You can list here all the models of your application that doesn't indirectly belong to a tenant.
|
43
|
+
#
|
44
|
+
config.models = %MODELS%
|
45
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
|
3
|
+
module Strongbolt
|
4
|
+
module Generators
|
5
|
+
class ViewsGenerator < Rails::Generators::Base
|
6
|
+
desc "Copies Strongbolt views to your application."
|
7
|
+
|
8
|
+
argument :scope, required: false, default: nil,
|
9
|
+
desc: "The scope to copy views to"
|
10
|
+
|
11
|
+
public_task :copy_views
|
12
|
+
|
13
|
+
source_root File.expand_path("../../../../app/views", __FILE__)
|
14
|
+
|
15
|
+
def copy_views
|
16
|
+
directory :strongbolt, target_path
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def target_path
|
22
|
+
@target_path ||= "app/views/#{scope || :strongbolt}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/strongbolt.rb
ADDED
@@ -0,0 +1,219 @@
|
|
1
|
+
require "active_record"
|
2
|
+
require "awesome_nested_set"
|
3
|
+
|
4
|
+
require "grant/grantable"
|
5
|
+
require "grant/status"
|
6
|
+
require 'grant/user'
|
7
|
+
|
8
|
+
require "strongbolt/version"
|
9
|
+
require "strongbolt/errors"
|
10
|
+
require "strongbolt/configuration"
|
11
|
+
require "strongbolt/tenantable"
|
12
|
+
require "strongbolt/bolted"
|
13
|
+
require "strongbolt/bolted_controller"
|
14
|
+
require "strongbolt/user_abilities"
|
15
|
+
require "strongbolt/base"
|
16
|
+
require "strongbolt/capability"
|
17
|
+
require "strongbolt/user_groups_user"
|
18
|
+
require "strongbolt/roles_user_group"
|
19
|
+
require "strongbolt/capabilities_role"
|
20
|
+
require "strongbolt/role"
|
21
|
+
require "strongbolt/user_group"
|
22
|
+
require "strongbolt/users_tenant"
|
23
|
+
|
24
|
+
#
|
25
|
+
# Raise an error if version of AR not compatible (4.1.0 and 4.1.1)
|
26
|
+
#
|
27
|
+
ar_version = ActiveRecord.version.version
|
28
|
+
if ar_version >= "4.1.0" && ar_version <= "4.1.1"
|
29
|
+
raise StandardError, "You cannot use Strongbolt with ActiveRecord versions 4.1.0 and 4.1.1. Please upgrade to >= 4.1.2"
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# Includes every module needed (including Grant)
|
34
|
+
#
|
35
|
+
ActiveRecord::Base.send :include, Strongbolt::Bolted
|
36
|
+
|
37
|
+
#
|
38
|
+
# Default behavior, when method current_user defined on controller
|
39
|
+
#
|
40
|
+
if defined?(ActionController) and defined?(ActionController::Base)
|
41
|
+
|
42
|
+
ActionController::Base.send :include, Strongbolt::BoltedController
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Setup controllers, views, helpers and session related configuration
|
48
|
+
#
|
49
|
+
require 'strongbolt/engine' if defined?(Rails::Engine)
|
50
|
+
|
51
|
+
|
52
|
+
#
|
53
|
+
# Main module
|
54
|
+
#
|
55
|
+
module Strongbolt
|
56
|
+
extend Forwardable
|
57
|
+
|
58
|
+
def self.table_name_prefix
|
59
|
+
'strongbolt_'
|
60
|
+
end
|
61
|
+
|
62
|
+
# Delegates to the configuration the access denied
|
63
|
+
def_delegators Configuration, :access_denied, :logger, :tenants, :user_class, :user_class_constant,
|
64
|
+
:default_capabilities
|
65
|
+
module_function :access_denied, :logger, :tenants, :user_class, :user_class_constant,
|
66
|
+
:default_capabilities
|
67
|
+
|
68
|
+
# Delegates switching thread behavior
|
69
|
+
def_delegators Grant::Status, :switch_to_multithread,
|
70
|
+
:switch_to_monothread
|
71
|
+
module_function :switch_to_multithread, :switch_to_monothread
|
72
|
+
|
73
|
+
#
|
74
|
+
# Tje parent controller to all strongbolt controllers
|
75
|
+
#
|
76
|
+
mattr_accessor :parent_controller
|
77
|
+
@@parent_controller = "ApplicationController"
|
78
|
+
|
79
|
+
#
|
80
|
+
# Current User
|
81
|
+
#
|
82
|
+
def self.current_user
|
83
|
+
Grant::User.current_user
|
84
|
+
end
|
85
|
+
|
86
|
+
# We keep an hash so we don't have each time to test
|
87
|
+
# if the module is included in the list
|
88
|
+
def self.current_user= user
|
89
|
+
# If user is an instance of something and different from what we have
|
90
|
+
if user.present?
|
91
|
+
# Raise error if wrong user class
|
92
|
+
unless valid_user? user
|
93
|
+
raise Strongbolt::WrongUserClass
|
94
|
+
end
|
95
|
+
|
96
|
+
# If the user class doesn't have included the module yet
|
97
|
+
unless user.class.included_modules.include? Strongbolt::UserAbilities
|
98
|
+
user.class.send :include, Strongbolt::UserAbilities
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Then we call the original grant method
|
103
|
+
Grant::User.current_user = user unless Grant::User.current_user == user
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
# Ensures the user instance given is a valid user for that configuration
|
108
|
+
# It checks whether the class or the base_class (in case of STI) of the instance class
|
109
|
+
# has been configured as the user model
|
110
|
+
#
|
111
|
+
def self.valid_user? user
|
112
|
+
user.class.name == Strongbolt::Configuration.user_class ||
|
113
|
+
user.class.base_class.name == Strongbolt::Configuration.user_class
|
114
|
+
end
|
115
|
+
|
116
|
+
#
|
117
|
+
# Setting up Strongbolt
|
118
|
+
#
|
119
|
+
def self.setup &block
|
120
|
+
# Configuration by user
|
121
|
+
block.call Configuration
|
122
|
+
|
123
|
+
# Include the User::Abilities
|
124
|
+
begin
|
125
|
+
user_class = Configuration.user_class
|
126
|
+
user_class = user_class.constantize if user_class.is_a? String
|
127
|
+
user_class.send(:include, Strongbolt::UserAbilities) unless user_class.included_modules.include?(Strongbolt::UserAbilities)
|
128
|
+
rescue NameError
|
129
|
+
logger.warn "User class #{Configuration.user_class} wasn't found"
|
130
|
+
end
|
131
|
+
rescue => e
|
132
|
+
error = <<-CONTENT
|
133
|
+
[ERROR] Strongbolt could not initialized successfully.
|
134
|
+
This can happen when running migrations, and in this situation, you can ignore this message.
|
135
|
+
If it happens in test, make sure you've run `rake db:test:prepare` so that test database is ready.
|
136
|
+
Otherwise, please review the error below to check what happened:
|
137
|
+
|
138
|
+
Error message:
|
139
|
+
#{e.message}
|
140
|
+
|
141
|
+
#{e.backtrace.join("\n")}
|
142
|
+
CONTENT
|
143
|
+
logger.fatal error
|
144
|
+
# Display in the console when error test env
|
145
|
+
puts error if defined?(Rails) && Rails.env.test?
|
146
|
+
# If not being done in a rake task, this should propagate the error
|
147
|
+
raise e unless $0 =~ /rake$/ # && ARGV.join(" ").include?("db:")
|
148
|
+
end
|
149
|
+
|
150
|
+
#
|
151
|
+
# Perform the block without grant
|
152
|
+
#
|
153
|
+
def self.without_authorization &block
|
154
|
+
Grant::Status.without_grant &block
|
155
|
+
end
|
156
|
+
|
157
|
+
#
|
158
|
+
# Perform the block with grant
|
159
|
+
#
|
160
|
+
def self.with_authorization &block
|
161
|
+
Grant::Status.with_grant &block
|
162
|
+
end
|
163
|
+
|
164
|
+
#
|
165
|
+
# Disable authorization checking
|
166
|
+
#
|
167
|
+
def self.disable_authorization
|
168
|
+
Grant::Status.disable_grant
|
169
|
+
end
|
170
|
+
|
171
|
+
def self.enable_authorization
|
172
|
+
Grant::Status.enable_grant
|
173
|
+
end
|
174
|
+
|
175
|
+
def self.enabled?
|
176
|
+
Grant::Status.grant_enabled?
|
177
|
+
end
|
178
|
+
def self.disabled?
|
179
|
+
! enabled?
|
180
|
+
end
|
181
|
+
|
182
|
+
# Include helpers in the given scope to AC and AV.
|
183
|
+
def self.include_helpers(scope)
|
184
|
+
ActiveSupport.on_load(:action_controller) do
|
185
|
+
include scope::UrlHelpers
|
186
|
+
end
|
187
|
+
|
188
|
+
ActiveSupport.on_load(:action_view) do
|
189
|
+
include scope::UrlHelpers
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# Not to use directly
|
194
|
+
def self.tenants= tenants
|
195
|
+
@@tenants = tenants
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
#
|
200
|
+
# We add a method to any object to quickly tell which method
|
201
|
+
# should not have any authorization check perform
|
202
|
+
#
|
203
|
+
class Object
|
204
|
+
def self.perform_without_authorization *method_names
|
205
|
+
method_names.each {|name| setup_without_authorization name}
|
206
|
+
end
|
207
|
+
|
208
|
+
private
|
209
|
+
|
210
|
+
def self.setup_without_authorization method_name
|
211
|
+
aliased_name = "_with_autorization_#{method_name}"
|
212
|
+
alias_method aliased_name, method_name
|
213
|
+
define_method method_name do |*args, &block|
|
214
|
+
Strongbolt.without_authorization do
|
215
|
+
send aliased_name, *args, &block
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
#
|
2
|
+
# Included in the base class of models (ActiveRecord::Base),
|
3
|
+
# this module is the entry point of all authorization.
|
4
|
+
#
|
5
|
+
# It implements helper methods that will be used by a lot of other models
|
6
|
+
#
|
7
|
+
module Strongbolt
|
8
|
+
module Bolted
|
9
|
+
module ClassMethods
|
10
|
+
#
|
11
|
+
# Returns true if grant is currently enable, the user is set and we're not in the console
|
12
|
+
# ie when we need to perform a check
|
13
|
+
#
|
14
|
+
def bolted?
|
15
|
+
!unbolted?
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# Not secure if Grant is disabled, there's no current user
|
20
|
+
# or if we're using Rails console
|
21
|
+
#
|
22
|
+
def unbolted?
|
23
|
+
Grant::Status.grant_disabled? || (defined?(Rails) && defined?(Rails.console)) ||
|
24
|
+
Strongbolt.current_user.nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# Returns true if the model is owned, ie if it has a belongs_to
|
29
|
+
# relationship with the user class
|
30
|
+
#
|
31
|
+
def owned?
|
32
|
+
@owned ||= name == Configuration.user_class || owner_association.present?
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# Returns the association to the user, if present
|
37
|
+
#
|
38
|
+
def owner_association
|
39
|
+
@owner_association ||= reflect_on_all_associations(:belongs_to).select do |assoc|
|
40
|
+
unless assoc.options.has_key? :polymorphic
|
41
|
+
assoc.klass.name == Configuration.user_class
|
42
|
+
else
|
43
|
+
false
|
44
|
+
end
|
45
|
+
end.try(:first)
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
# Returns the name of the attribute containing the owner id
|
50
|
+
#
|
51
|
+
def owner_attribute
|
52
|
+
return unless owned?
|
53
|
+
|
54
|
+
@owner_attribute ||= if name == Configuration.user_class
|
55
|
+
:id
|
56
|
+
else
|
57
|
+
owner_association.foreign_key.to_sym
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Returns the model name for authorization
|
63
|
+
#
|
64
|
+
def name_for_authorization
|
65
|
+
@name_for_authorization ||= self.name
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
# Authorize as another model
|
70
|
+
#
|
71
|
+
def authorize_as model_name
|
72
|
+
@name_for_authorization = model_name
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
module InstanceMethods
|
78
|
+
#
|
79
|
+
# Asks permission to performa an operation on the current instance
|
80
|
+
#
|
81
|
+
def accessible?(action, attrs = :any)
|
82
|
+
unbolted? || Grant::User.current_user.can?(action, self, attrs)
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# Returns the owner id according to what's
|
87
|
+
#
|
88
|
+
def strongbolt_owner_id
|
89
|
+
raise ModelNotOwned unless self.class.owned?
|
90
|
+
|
91
|
+
send self.class.owner_attribute
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.included(receiver)
|
96
|
+
receiver.extend ClassMethods
|
97
|
+
receiver.send :include, InstanceMethods
|
98
|
+
receiver.send :include, Strongbolt::Tenantable
|
99
|
+
receiver.send :include, Grant::Grantable
|
100
|
+
|
101
|
+
# We add the grant to filter everything
|
102
|
+
receiver.class_eval do
|
103
|
+
|
104
|
+
#
|
105
|
+
# We use the grant helper method to test authorizations on all methods
|
106
|
+
#
|
107
|
+
grant(:find, :create, :update, :destroy) do |user, instance, action|
|
108
|
+
# Strongbolt.logger.debug { "Checking for #{action} on #{instance}\n\n#{Kernel.caller.join("\n")}" }
|
109
|
+
# Check the user permission unless no user or rails console
|
110
|
+
# Not using unbolted? here
|
111
|
+
granted = ((defined?(Rails) && defined?(Rails.console)) || user.nil?) ||
|
112
|
+
user.can?( action, instance )
|
113
|
+
|
114
|
+
# If not granted, trigger the access denied
|
115
|
+
unless granted
|
116
|
+
Strongbolt.access_denied user, instance, action, $request.try(:fullpath)
|
117
|
+
end
|
118
|
+
|
119
|
+
granted
|
120
|
+
end # End Grant
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|