strongbolt 0.3.6
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 +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
|