right_on 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/.travis.yml +14 -0
- data/Gemfile +7 -0
- data/LICENSE +21 -0
- data/README.md +60 -0
- data/Rakefile +12 -0
- data/db/migration.rb +34 -0
- data/db/rights_roles.yml +16 -0
- data/gemfiles/rails3.gemfile +7 -0
- data/gemfiles/rails4.gemfile +6 -0
- data/lib/right_on/action_controller_extensions.rb +68 -0
- data/lib/right_on/generators/USAGE +8 -0
- data/lib/right_on/generators/right_migration_generator.rb +59 -0
- data/lib/right_on/generators/templates/right_migration.rb +32 -0
- data/lib/right_on/permission_denied_response.rb +43 -0
- data/lib/right_on/rails.rb +5 -0
- data/lib/right_on/railtie.rb +12 -0
- data/lib/right_on/restricted_by_right.rb +56 -0
- data/lib/right_on/right.rb +171 -0
- data/lib/right_on/rights_manager.rb +140 -0
- data/lib/right_on/role.rb +16 -0
- data/lib/right_on/role_model.rb +33 -0
- data/lib/right_on/tasks/rights_roles.rake +12 -0
- data/lib/right_on/tasks/seeds_rights.rake +28 -0
- data/lib/right_on/version.rb +3 -0
- data/lib/right_on.rb +12 -0
- data/right_on.gemspec +33 -0
- data/spec/action_controller_extensions_spec.rb +34 -0
- data/spec/right_on_spec.rb +206 -0
- data/spec/role_model_spec.rb +45 -0
- data/spec/schema.rb +44 -0
- data/spec/spec_helper.rb +42 -0
- data/spec/support/bootstrap.rb +15 -0
- data/spec/support/coverage_loader.rb +26 -0
- data/views/_edit_rights.html.haml +15 -0
- data/views/_rights_roles_matrix.html.haml +24 -0
- metadata +268 -0
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'input_reader'
|
2
|
+
require 'rails/generators'
|
3
|
+
|
4
|
+
# Extra require so generator can be used in rake task
|
5
|
+
require 'right_on/generators/right_migration_generator'
|
6
|
+
|
7
|
+
module RightOn
|
8
|
+
class RightsManager
|
9
|
+
class << self
|
10
|
+
|
11
|
+
def controllers
|
12
|
+
controllers_path = File.join("#{Rails.root}",'app','controllers')
|
13
|
+
controllers_suffix = '_controller.rb'
|
14
|
+
controllers_files = File.join(controllers_path, '**', '*' + controllers_suffix)
|
15
|
+
Dir[controllers_files].map do |f|
|
16
|
+
[File.dirname(f)[(controllers_path.length + 1)..-1],
|
17
|
+
File.basename(f,controllers_suffix)].compact.join('/')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def missing_rights
|
23
|
+
rights = Right.all.map(&:controller)
|
24
|
+
controllers.reject { |c| rights.include?(c) }
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def add_right(options = {})
|
29
|
+
options = parse_right_options(options)
|
30
|
+
add_and_run_right_migration(options)
|
31
|
+
add_right_fixture(options)
|
32
|
+
puts "Added right #{options[:name]}"
|
33
|
+
add_right if options[:unattended].blank? && InputReader.get_boolean(:prompt => "Add another right?(Y/N)")
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def add_right_record(options = {})
|
38
|
+
unless Right.find_by_name(options[:name])
|
39
|
+
Right.create(options.slice(:controller, :action, :name, :roles))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
# Converts options from {:key => 'value', :key2 => 'value2', :blank => ''}
|
45
|
+
# to "--key=value --key2=value2" (Notice how blank is not included)
|
46
|
+
def build_unix_options(options = {})
|
47
|
+
options.select{|k,v| v.present?}.map do |key, value|
|
48
|
+
"--#{key}=#{value}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def add_right_migration(options = {})
|
54
|
+
migration_options = options.slice(:controller, :action, :right)
|
55
|
+
puts options.inspect
|
56
|
+
puts "#{options[:name]} #{build_unix_options(migration_options)}"
|
57
|
+
migration_file = Rails::Generators.invoke("right_on:right_migration",
|
58
|
+
[options[:name]] + build_unix_options(migration_options)
|
59
|
+
)
|
60
|
+
raise "Could not generate migration" unless migration_file.present?
|
61
|
+
migration_file.first
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
def add_and_run_right_migration(options = {})
|
66
|
+
migration_file = add_right_migration(options)
|
67
|
+
ENV['VERSION'] = File.basename(migration_file).split('_').first
|
68
|
+
Rake::Task['db:migrate:up'].invoke
|
69
|
+
ENV.delete 'VERSION'
|
70
|
+
true
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
def add_right_fixture(options = {})
|
75
|
+
right_roles_yaml_path = File.join("#{Rails.root}",'db','fixtures','rights_roles.yml')
|
76
|
+
right_roles = YAML::load_file(right_roles_yaml_path)
|
77
|
+
|
78
|
+
group = options[:group].presence || options[:controller]
|
79
|
+
|
80
|
+
right_roles['rights'][group] ||= []
|
81
|
+
right_roles['rights'][group].delete(options[:controller])
|
82
|
+
|
83
|
+
right = right_roles['rights'][group].find do |right|
|
84
|
+
right.is_a?(Hash) && right.keys.include?(options[:controller])
|
85
|
+
end
|
86
|
+
|
87
|
+
if options[:action].present?
|
88
|
+
right ||= (right_roles['rights'][group] << {}).last
|
89
|
+
right[options[:controller]] ||= []
|
90
|
+
right[options[:controller]] << options[:action] unless right[options[:controller]].include?(options[:action])
|
91
|
+
elsif !right
|
92
|
+
right_roles['rights'][group] << options[:controller]
|
93
|
+
end
|
94
|
+
|
95
|
+
options[:bootstrap_roles].each do |role_title|
|
96
|
+
(right_roles['roles'][role_title] || []) << [options[:controller].presence,options[:action].presence].compact.join("#")
|
97
|
+
end
|
98
|
+
|
99
|
+
File.open(right_roles_yaml_path, "w") do |f|
|
100
|
+
f.write(right_roles.to_yaml)
|
101
|
+
end
|
102
|
+
|
103
|
+
true
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
def parse_right_options(options = {})
|
110
|
+
parsed_options = {}
|
111
|
+
|
112
|
+
parsed_options[:controller] = options[:controller].presence ||
|
113
|
+
InputReader.select_item(missing_rights, :prompt => "Right:", :allow_blank => true) ||
|
114
|
+
InputReader.get_string(:allow_blank => false, :prompt => "Controller:")
|
115
|
+
|
116
|
+
parsed_options[:action] = options[:action].presence ||
|
117
|
+
InputReader.get_string(:allow_blank => true, :prompt => "Action:")
|
118
|
+
|
119
|
+
parsed_options[:name] = options[:name].presence ||
|
120
|
+
InputReader.get_string(:allow_blank => true, :prompt => "Name:") ||
|
121
|
+
[parsed_options[:controller].presence, parsed_options[:action].presence].compact.join('#')
|
122
|
+
|
123
|
+
parsed_options[:group] = options[:group].presence ||
|
124
|
+
InputReader.get_string(:allow_blank => true, :prompt => "Group:")
|
125
|
+
|
126
|
+
parsed_options[:right] = options[:right].presence ||
|
127
|
+
InputReader.select_item(Right.all, :selection_attribute => :name, :allow_blank => true, :prompt => "Assign new right to anyone with right:").name
|
128
|
+
|
129
|
+
right_roles_yaml_path = File.join("#{Rails.root}",'db','fixtures','rights_roles.yml')
|
130
|
+
right_roles = YAML::load_file(right_roles_yaml_path)
|
131
|
+
bootstrap_roles = right_roles['roles'].keys
|
132
|
+
parsed_options[:bootstrap_roles] = options[:bootstrap_role].presence ||
|
133
|
+
InputReader.select_items(bootstrap_roles, :allow_blank => true, :prompt => "Assign to which bootstrap roles:")
|
134
|
+
|
135
|
+
parsed_options
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module RightOn
|
2
|
+
class Role < ActiveRecord::Base
|
3
|
+
|
4
|
+
has_and_belongs_to_many :rights, :class_name => 'RightOn::Right'
|
5
|
+
|
6
|
+
validates_presence_of :title
|
7
|
+
validates_uniqueness_of :title
|
8
|
+
|
9
|
+
def to_s
|
10
|
+
self.title.try(:titleize)
|
11
|
+
end
|
12
|
+
|
13
|
+
alias_method :name, :to_s
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module RightOn
|
2
|
+
module RoleModel
|
3
|
+
def self.included(base)
|
4
|
+
base.module_eval 'has_and_belongs_to_many :roles, :class_name => "RightOn::Role"'
|
5
|
+
Role.module_eval "has_and_belongs_to_many :#{base.table_name}"
|
6
|
+
end
|
7
|
+
|
8
|
+
def roles_allowed_to_assign
|
9
|
+
Role.accessible_to(self)
|
10
|
+
end
|
11
|
+
|
12
|
+
def rights
|
13
|
+
@rights ||=
|
14
|
+
Right
|
15
|
+
.select('distinct rights.*')
|
16
|
+
.joins(:roles)
|
17
|
+
.where('rights_roles.role_id IN (?)', role_ids)
|
18
|
+
end
|
19
|
+
|
20
|
+
def has_access_to?(client_type)
|
21
|
+
has_right?(client_type.right)
|
22
|
+
end
|
23
|
+
|
24
|
+
def has_right?(right_or_string)
|
25
|
+
right = right_or_string.is_a?(Right) ? right_or_string : Right.find_by_name(right_or_string)
|
26
|
+
rights.include?(right)
|
27
|
+
end
|
28
|
+
|
29
|
+
def has_privileges_of?(other_user)
|
30
|
+
(other_user.rights - rights).empty?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
namespace :rights do
|
2
|
+
desc "Check for controllers without rights"
|
3
|
+
task :check => :environment do
|
4
|
+
puts "Missing rights for controllers:"
|
5
|
+
puts RightOn::RightsManager.missing_rights
|
6
|
+
end
|
7
|
+
|
8
|
+
desc "Add rights for missing controllers"
|
9
|
+
task :add, [:controller, :action] => :environment do |t, args|
|
10
|
+
RightOn::RightsManager.add_right(args)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
namespace "db" do
|
2
|
+
namespace "seed" do
|
3
|
+
desc "Seed initial rights to each role"
|
4
|
+
task :rights => :environment do
|
5
|
+
load "#{Rails.root}/db/fixtures/rights_roles.rb"
|
6
|
+
end
|
7
|
+
|
8
|
+
namespace "rights" do
|
9
|
+
desc "Remove existing rights data and reinitiate it with seeds."
|
10
|
+
task :redo => :environment do
|
11
|
+
message = []
|
12
|
+
message << "This rake task will delete all existing rights and reload Roles with the default rights"
|
13
|
+
message << "Every roles will lose their existing rights unless specified in db/fixtures/rights_roles.yml"
|
14
|
+
|
15
|
+
RakeUserInterface.confirmation_required(message) do
|
16
|
+
RightOn::Right.transaction do
|
17
|
+
if RightOn::Right.count > 0
|
18
|
+
puts "Removing existing Right data..."
|
19
|
+
RightOn::Right.destroy_all
|
20
|
+
end
|
21
|
+
|
22
|
+
Rake::Task["db:seed:rights"].invoke
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/right_on.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
module RightOn
|
2
|
+
require 'active_record'
|
3
|
+
|
4
|
+
require 'dependent_restrict'
|
5
|
+
require 'right_on/restricted_by_right'
|
6
|
+
ActiveRecord::Base.send(:include, RestrictedByRight)
|
7
|
+
|
8
|
+
require 'rails'
|
9
|
+
require 'right_on/railtie'
|
10
|
+
require 'right_on/rights_manager'
|
11
|
+
end
|
12
|
+
|
data/right_on.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'right_on/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'right_on'
|
8
|
+
spec.version = RightOn::VERSION
|
9
|
+
spec.authors = ["Michael Noack", "Alessandro Berardi"]
|
10
|
+
spec.email = 'development@travellink.com.au'
|
11
|
+
spec.description = "This helps systems manage rights and roles on a controller/action basis."
|
12
|
+
spec.summary = "Set of extensions to core rails to give rights and roles."
|
13
|
+
spec.homepage = 'http://github.com/sealink/right_on'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency('activerecord', [">= 3.2.0", "< 5.0.0"])
|
22
|
+
spec.add_dependency('activesupport', [">= 3.2.0", "< 5.0.0"])
|
23
|
+
spec.add_dependency('dependent_restrict', [">= 0.2.1"])
|
24
|
+
spec.add_dependency('input_reader', ["~> 0.0"])
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
26
|
+
spec.add_development_dependency 'rake'
|
27
|
+
spec.add_development_dependency 'rspec'
|
28
|
+
spec.add_development_dependency 'simplecov'
|
29
|
+
spec.add_development_dependency 'simplecov-rcov'
|
30
|
+
spec.add_development_dependency 'coveralls'
|
31
|
+
spec.add_development_dependency 'sqlite3'
|
32
|
+
spec.add_development_dependency 'travis'
|
33
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'action_controller'
|
4
|
+
class AdminController < ActionController::Base
|
5
|
+
include RightOn::ActionControllerExtensions
|
6
|
+
def current_user
|
7
|
+
Thread.current[:user]
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe AdminController do
|
12
|
+
let(:basic_user) { User.where(name: 'basic').first }
|
13
|
+
let(:admin_user) { User.where(name: 'admin').first }
|
14
|
+
|
15
|
+
before do
|
16
|
+
Bootstrap.reset_database
|
17
|
+
controller.params = {controller: 'admin', action: 'index'}
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:controller) { AdminController.new }
|
21
|
+
context 'basic user' do
|
22
|
+
before { Thread.current[:user] = basic_user }
|
23
|
+
it 'should not allow access' do
|
24
|
+
expect(controller.access_allowed?).to be false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'admin user' do
|
29
|
+
before { Thread.current[:user] = admin_user }
|
30
|
+
it 'should allow access' do
|
31
|
+
expect(controller.access_allowed?).to be true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,206 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe User do
|
4
|
+
let(:basic_user) { User.where(name: 'basic').first }
|
5
|
+
let(:admin_user) { User.where(name: 'admin').first }
|
6
|
+
|
7
|
+
before do
|
8
|
+
Bootstrap.reset_database
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should compare privileges' do
|
12
|
+
expect(admin_user.has_privileges_of?(basic_user)).to eq true
|
13
|
+
expect(basic_user.has_privileges_of?(admin_user)).to eq false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe RightOn::Right do
|
18
|
+
before do
|
19
|
+
RightOn::Right.delete_all
|
20
|
+
Model.delete_all
|
21
|
+
|
22
|
+
@model = Model.create!(:name => 'Test')
|
23
|
+
|
24
|
+
@users = RightOn::Right.create!(:name => 'users', :controller => 'users')
|
25
|
+
@other = RightOn::Right.create!(:name => 'models', :controller => 'models')
|
26
|
+
@index = RightOn::Right.create!(:name => 'models#index', :controller => 'models', :action => 'index')
|
27
|
+
@change = RightOn::Right.create!(:name => 'models#change', :controller => 'models', :action => 'change')
|
28
|
+
@view = RightOn::Right.create!(:name => 'models#view', :controller => 'models', :action => 'view')
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should display nicely with sensible_name and to_s' do
|
32
|
+
expect(@model.right.to_s).to eq 'Model: Test'
|
33
|
+
expect(@other.to_s).to eq 'models'
|
34
|
+
expect(@index.to_s).to eq 'models#index'
|
35
|
+
|
36
|
+
expect(@model.right.sensible_name).to eq 'Model: Test'
|
37
|
+
expect(@other.sensible_name).to eq 'Models'
|
38
|
+
expect(@index.sensible_name).to eq 'Models - Index'
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should create right for restricted right' do
|
42
|
+
right = @model.right
|
43
|
+
expect(right).to_not be_nil
|
44
|
+
expect(right.name).to eq 'Model: Test'
|
45
|
+
expect{right.destroy}.to raise_error(ActiveRecord::DetailedDeleteRestrictionError)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should identify correct groups' do
|
49
|
+
rights = RightOn::Right.regular_rights_with_group.sort_by{|r| r.name} # Sort for ruby 1.9 compatibility
|
50
|
+
expect(rights.map(&:name)).to eq %w(models models#change models#index models#view users)
|
51
|
+
expect(rights.map(&:group)).to eq %w(general general general general admin)
|
52
|
+
|
53
|
+
expect(RightOn::Right.by_groups).to eq(
|
54
|
+
'general' => [@other, @index, @view, @change],
|
55
|
+
'admin' => [@users],
|
56
|
+
'other' => [@model.right]
|
57
|
+
)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should determine if it is allowed based on context' do
|
61
|
+
index_action = {:controller => 'models', :action => 'index'}
|
62
|
+
edit_action = {:controller => 'models', :action => 'edit'}
|
63
|
+
hello_action = {:controller => 'models', :action => 'hello'}
|
64
|
+
|
65
|
+
expect(@model.right.allowed?(index_action)).to eq false
|
66
|
+
|
67
|
+
expect(@users.allowed?(:controller => 'users', :action => 'index')).to eq true
|
68
|
+
expect(@users.allowed?(:controller => 'users', :action => 'edit' )).to eq true
|
69
|
+
expect(@users.allowed?(:controller => 'users', :action => 'hello')).to eq true
|
70
|
+
|
71
|
+
expect(@other.allowed?(index_action)).to eq false # as specific action exists
|
72
|
+
expect(@other.allowed?(edit_action )).to eq false # as specific action exists
|
73
|
+
expect(@other.allowed?(hello_action)).to eq true # as hello isn't defined
|
74
|
+
|
75
|
+
expect(@index.allowed?(index_action)).to eq true
|
76
|
+
expect(@index.allowed?(edit_action )).to eq false
|
77
|
+
expect(@index.allowed?(hello_action)).to eq false
|
78
|
+
|
79
|
+
expect(@view.allowed?(index_action)).to eq true
|
80
|
+
expect(@view.allowed?(edit_action )).to eq false
|
81
|
+
expect(@view.allowed?(hello_action)).to eq false
|
82
|
+
|
83
|
+
expect(@change.allowed?(index_action)).to eq true
|
84
|
+
expect(@change.allowed?(edit_action )).to eq true
|
85
|
+
expect(@change.allowed?(hello_action)).to eq false
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe RightOn::Right, "when created" do
|
90
|
+
it "should validate presence of name" do
|
91
|
+
subject.valid?
|
92
|
+
expect(subject.errors[:name]).to_not be_blank
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe RightOn::Right, "with a name and controller" do
|
97
|
+
before do
|
98
|
+
@new_right = RightOn::Right.new(:name => "tickets", :controller => "tickets")
|
99
|
+
@new_right.save!
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should create a new right" do
|
103
|
+
expect(@new_right.name).to eq "tickets"
|
104
|
+
expect(@new_right.controller).to eq "tickets"
|
105
|
+
expect(@new_right.save).to eq true
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
describe RightOn::Right, "with a name, controller and action" do
|
111
|
+
before do
|
112
|
+
@new_right = RightOn::Right.new(:name => "tickets@destroy", :controller => "tickets", :action => "destroy")
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should create a new right" do
|
116
|
+
expect(@new_right.name).to eq "tickets@destroy"
|
117
|
+
expect(@new_right.controller).to eq "tickets"
|
118
|
+
expect(@new_right.action).to eq "destroy"
|
119
|
+
expect(@new_right.save).to eq true
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe RightOn::Right, "with only a name" do
|
124
|
+
before do
|
125
|
+
@new_right = RightOn::Right.new(:name => "tickets2")
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should create a new right" do
|
129
|
+
expect(@new_right.save).to eq true
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe RightOn::Right, "with the same name" do
|
134
|
+
before do
|
135
|
+
@old_right = RightOn::Right.new(:name => "tickets3", :controller => "tickets")
|
136
|
+
@old_right.save!
|
137
|
+
@new_right = RightOn::Right.new(:name => "tickets3", :controller => "tickets")
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should not create a new right" do
|
141
|
+
expect(@new_right.save).to eq false
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe RightOn::Role, "can have many rights" do
|
146
|
+
let(:role1) { RightOn::Role.new(:title => 'role 1') }
|
147
|
+
|
148
|
+
specify { expect(role1.to_s).to eq 'Role 1' }
|
149
|
+
|
150
|
+
context 'when assigned rights' do
|
151
|
+
let(:right1) { RightOn::Right.create!(:name => 'right 1') }
|
152
|
+
let(:right2) { RightOn::Right.create!(:name => 'right 2') }
|
153
|
+
|
154
|
+
before do
|
155
|
+
role1.save!
|
156
|
+
role1.rights = [right1, right2]
|
157
|
+
end
|
158
|
+
|
159
|
+
after do
|
160
|
+
role1.destroy
|
161
|
+
right1.destroy
|
162
|
+
right2.destroy
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should have and belong to many" do
|
166
|
+
expect(role1.rights.size).to eq 2
|
167
|
+
expect(right1.roles.size).to eq 1
|
168
|
+
expect(right2.roles.size).to eq 1
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe 'when checking accessibility to a controller' do
|
174
|
+
|
175
|
+
let(:test_controller_right) { RightOn::Right.new(name: 'test', controller: 'test') }
|
176
|
+
let(:user) { double(rights: [test_controller_right]) }
|
177
|
+
let(:controller) { 'test' }
|
178
|
+
let(:action) { 'index' }
|
179
|
+
let(:params) { {controller: 'test', action: 'index'} }
|
180
|
+
|
181
|
+
before do
|
182
|
+
stub_const 'TestController', double(current_user: user, params: params)
|
183
|
+
TestController.extend RightOn::ActionControllerExtensions
|
184
|
+
allow(TestController).to receive(:rights_from).and_return(nil)
|
185
|
+
end
|
186
|
+
|
187
|
+
specify { expect(TestController.access_allowed?(controller)).to be_truthy }
|
188
|
+
specify { expect(TestController.access_allowed?('other')).to be_falsey }
|
189
|
+
specify { expect(TestController.access_allowed_to_controller?(controller)).to be_truthy }
|
190
|
+
specify { expect(TestController.access_allowed_to_controller?('other')).to be_falsey }
|
191
|
+
|
192
|
+
describe 'when inheriting rights' do
|
193
|
+
let(:controller) { 'test_inherited' }
|
194
|
+
|
195
|
+
before do
|
196
|
+
stub_const 'TestInheritedController', double(current_user: user, params: params)
|
197
|
+
TestInheritedController.extend RightOn::ActionControllerExtensions
|
198
|
+
allow(TestInheritedController).to receive(:rights_from).and_return(:test)
|
199
|
+
end
|
200
|
+
|
201
|
+
specify { expect(TestInheritedController.access_allowed?(controller)).to be_falsey }
|
202
|
+
specify { expect(TestInheritedController.access_allowed?('other')).to be_falsey }
|
203
|
+
specify { expect(TestInheritedController.access_allowed_to_controller?(controller)).to be_truthy }
|
204
|
+
specify { expect(TestInheritedController.access_allowed_to_controller?('other')).to be_falsey }
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RightOn::RoleModel do
|
4
|
+
let(:admin_role) { RightOn::Role.create!(title: 'admin') }
|
5
|
+
let(:product_right) { RightOn::Right.create!(name: 'Products', controller: 'products') }
|
6
|
+
|
7
|
+
before do
|
8
|
+
RightOn::Role.delete_all
|
9
|
+
RightOn::Right.delete_all
|
10
|
+
admin_role.rights << product_right
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:basic_user) { User.create! }
|
14
|
+
let(:admin) { User.create!(roles: [admin_role]) }
|
15
|
+
|
16
|
+
it 'basic user should have no access' do
|
17
|
+
expect(basic_user.rights).to be_empty
|
18
|
+
expect(basic_user.has_right?('Products')).to be false
|
19
|
+
expect(basic_user.has_right?(product_right)).to be false
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'admin user should have full access' do
|
23
|
+
expect(admin.rights.size).to eq 1
|
24
|
+
expect(admin.has_right?('Products')).to be true
|
25
|
+
expect(admin.has_right?(product_right)).to be true
|
26
|
+
end
|
27
|
+
|
28
|
+
it '#has_privileges_of?' do
|
29
|
+
expect(admin.has_privileges_of?(basic_user)).to be true
|
30
|
+
expect(basic_user.has_privileges_of?(admin)).to be false
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when associating rights of other objects' do
|
34
|
+
let(:model1) { Model.create! }
|
35
|
+
|
36
|
+
before do
|
37
|
+
admin_role.rights << model1.right
|
38
|
+
end
|
39
|
+
|
40
|
+
it '#has_access_to?' do
|
41
|
+
expect(admin.has_access_to?(model1)).to be true
|
42
|
+
expect(basic_user.has_access_to?(model1)).to be false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/spec/schema.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
ActiveRecord::Schema.define(:version => 1) do
|
2
|
+
create_table :rights do |t|
|
3
|
+
t.string :name, :controller, :action, :limit => 150
|
4
|
+
t.timestamps null: true
|
5
|
+
end
|
6
|
+
|
7
|
+
change_table :rights do |t|
|
8
|
+
t.index :action
|
9
|
+
t.index [:controller, :action]
|
10
|
+
t.index :name
|
11
|
+
end
|
12
|
+
|
13
|
+
create_table :rights_roles, :id => false do |t|
|
14
|
+
t.integer :right_id, :role_id
|
15
|
+
end
|
16
|
+
|
17
|
+
change_table :rights_roles do |t|
|
18
|
+
t.index [:right_id, :role_id]
|
19
|
+
t.index [:role_id, :right_id]
|
20
|
+
end
|
21
|
+
|
22
|
+
create_table :roles do |t|
|
23
|
+
t.string :title
|
24
|
+
t.text :description
|
25
|
+
t.integer :right_id
|
26
|
+
t.timestamps null: true
|
27
|
+
end
|
28
|
+
|
29
|
+
add_index :roles, :right_id
|
30
|
+
|
31
|
+
create_table :models do |t|
|
32
|
+
t.string :name
|
33
|
+
t.integer :right_id
|
34
|
+
end
|
35
|
+
|
36
|
+
create_table :users do |t|
|
37
|
+
t.string :name
|
38
|
+
end
|
39
|
+
|
40
|
+
create_table :roles_users do |t|
|
41
|
+
t.integer :role_id, :user_id
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper.rb"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
|
8
|
+
require 'rubygems'
|
9
|
+
require 'bundler/setup'
|
10
|
+
Bundler.require :default, :test
|
11
|
+
|
12
|
+
require 'support/bootstrap'
|
13
|
+
require 'support/coverage_loader'
|
14
|
+
|
15
|
+
require 'right_on'
|
16
|
+
require 'right_on/rails'
|
17
|
+
|
18
|
+
RSpec.configure do |config|
|
19
|
+
config.run_all_when_everything_filtered = true
|
20
|
+
config.filter_run :focus
|
21
|
+
config.before :all do
|
22
|
+
RightOn::Right.cache = ActiveSupport::Cache::MemoryStore.new
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
DB_FILE = 'tmp/test_db'
|
27
|
+
FileUtils.mkdir_p File.dirname(DB_FILE)
|
28
|
+
FileUtils.rm_f DB_FILE
|
29
|
+
|
30
|
+
ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => DB_FILE
|
31
|
+
|
32
|
+
load('spec/schema.rb')
|
33
|
+
|
34
|
+
RightOn::Right.rights_yaml 'db/rights_roles.yml'
|
35
|
+
|
36
|
+
class Model < ActiveRecord::Base
|
37
|
+
restricted_by_right
|
38
|
+
end
|
39
|
+
|
40
|
+
class User < ActiveRecord::Base
|
41
|
+
include RightOn::RoleModel
|
42
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Bootstrap
|
2
|
+
def self.reset_database
|
3
|
+
RightOn::Right.delete_all
|
4
|
+
RightOn::Role.delete_all
|
5
|
+
User.delete_all
|
6
|
+
|
7
|
+
basic_right = RightOn::Right.create!(:name => 'basic', :controller => 'basic')
|
8
|
+
admin_right = RightOn::Right.create!(:name => 'admin', :controller => 'admin')
|
9
|
+
basic_role = RightOn::Role.create!(:title => 'Basic', :rights => [basic_right])
|
10
|
+
admin_role = RightOn::Role.create!(:title => 'Admin', :rights => [admin_right])
|
11
|
+
|
12
|
+
User.create!(name: 'basic', roles: [basic_role])
|
13
|
+
User.create!(name: 'admin', roles: [basic_role, admin_role])
|
14
|
+
end
|
15
|
+
end
|