dar_da_da 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +11 -0
- data/Gemfile +4 -0
- data/Guardfile +5 -0
- data/LICENSE +20 -0
- data/README.rdoc +7 -0
- data/Rakefile +8 -0
- data/dar_da_da.gemspec +31 -0
- data/init.rb +1 -0
- data/lib/dar_da_da/action_controller_extension.rb +30 -0
- data/lib/dar_da_da/active_record_extension.rb +86 -0
- data/lib/dar_da_da/config.rb +56 -0
- data/lib/dar_da_da/role.rb +45 -0
- data/lib/dar_da_da/version.rb +3 -0
- data/lib/dar_da_da.rb +18 -0
- data/spec/dar_da_da/action_controller_extension_spec.rb +17 -0
- data/spec/dar_da_da/active_record_extension_spec.rb +87 -0
- data/spec/dar_da_da/config_spec.rb +212 -0
- data/spec/dar_da_da/role_spec.rb +69 -0
- data/spec/spec_helper.rb +57 -0
- data/spec/watchr.rb +48 -0
- metadata +203 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Sebastian
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
data/Rakefile
ADDED
data/dar_da_da.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "dar_da_da/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "dar_da_da"
|
7
|
+
s.version = DarDaDa::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Sebastian Munz"]
|
10
|
+
s.email = ["sebastian@yo.lk"]
|
11
|
+
s.homepage = "https://github.com/yolk/dar_da_da"
|
12
|
+
s.summary = %q{Roles easy like sunday morning.}
|
13
|
+
s.description = %q{Roles easy like sunday morning.}
|
14
|
+
|
15
|
+
s.rubyforge_project = "dar_da_da"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_dependency 'activesupport', '>= 3.0'
|
23
|
+
s.add_dependency 'activerecord', '>= 3.0'
|
24
|
+
# Actionpack is optional!
|
25
|
+
s.add_development_dependency 'actionpack', '>= 3.0'
|
26
|
+
s.add_development_dependency 'rspec', '>= 2.4.0'
|
27
|
+
s.add_development_dependency 'guard-rspec', '>=0.1.9'
|
28
|
+
s.add_development_dependency 'growl', '>=1.0.3'
|
29
|
+
s.add_development_dependency 'rb-fsevent', '>=0.3.9'
|
30
|
+
s.add_development_dependency 'sqlite3-ruby'
|
31
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'lib', 'dar_da_da')
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module DarDaDa
|
2
|
+
module ActionControllerExtension
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(ClassMethods)
|
5
|
+
unless defined?(ActionController::ForbiddenError)
|
6
|
+
base.class_eval "class ::ActionController::ForbiddenError < ::ActionController::ActionControllerError;end"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def define_access_control(user_class, user_method_name = :current_user)
|
12
|
+
user_class.dar_dar_da.all_rights.each do |right|
|
13
|
+
self.class_eval("
|
14
|
+
private
|
15
|
+
|
16
|
+
def check_if_#{user_class.name.downcase}_is_allowed_to_#{right}
|
17
|
+
raise ActionController::ForbiddenError.new unless #{user_method_name}.allowed_to_#{right}?
|
18
|
+
end
|
19
|
+
")
|
20
|
+
|
21
|
+
self.class_eval("
|
22
|
+
def self.require_right(right, options={})
|
23
|
+
before_filter :\"check_if_#{user_class.name.downcase}_is_allowed_to_#\{right}\", options
|
24
|
+
end
|
25
|
+
")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module DarDaDa
|
2
|
+
module ActiveRecordExtension
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.decorate(base, config)
|
8
|
+
base.send :include, DarDaDa::ActiveRecordExtension::InstanceMethods
|
9
|
+
|
10
|
+
config.each do |name, role|
|
11
|
+
base.class_eval("
|
12
|
+
def #{name}?
|
13
|
+
role_symbol == :#{name}
|
14
|
+
end
|
15
|
+
|
16
|
+
scope :#{name.to_s.pluralize}, where(\"#{base.table_name}.#{config.options[:role_attribute]} = '#{name}'\")
|
17
|
+
")
|
18
|
+
end
|
19
|
+
config.all_rights.each do |right|
|
20
|
+
base.class_eval("
|
21
|
+
def allowed_to_#{right}?
|
22
|
+
allowed_to?(:#{right})
|
23
|
+
end
|
24
|
+
")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module ClassMethods
|
29
|
+
def define_roles(options={}, &block)
|
30
|
+
(self.dar_dar_da ||= DarDaDa::Config.new(options)).tap do |config|
|
31
|
+
config.reopen(&block)
|
32
|
+
DarDaDa::ActiveRecordExtension.decorate(self, config)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def dar_dar_da=(config)
|
37
|
+
write_inheritable_attribute(:dar_dar_da, config)
|
38
|
+
end
|
39
|
+
|
40
|
+
def dar_dar_da
|
41
|
+
read_inheritable_attribute(:dar_dar_da)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module InstanceMethods
|
46
|
+
def self.included(base)
|
47
|
+
base.send :before_save, :set_role_to_default_value
|
48
|
+
end
|
49
|
+
|
50
|
+
def role
|
51
|
+
role_symbol.to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
def role=(new_role)
|
55
|
+
write_role_attribute(new_role) if self.class.dar_dar_da[new_role]
|
56
|
+
end
|
57
|
+
|
58
|
+
def allowed_to?(name)
|
59
|
+
rights = self.class.dar_dar_da[role]
|
60
|
+
!!rights && !name.blank? && rights.include?(name.to_sym)
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def role_symbol
|
66
|
+
role_attribute = read_role_attribute
|
67
|
+
return self.class.dar_dar_da.options[:default_role] if role_attribute.blank?
|
68
|
+
role_attribute.to_sym
|
69
|
+
end
|
70
|
+
|
71
|
+
def read_role_attribute
|
72
|
+
read_attribute(self.class.dar_dar_da.options[:role_attribute])
|
73
|
+
end
|
74
|
+
|
75
|
+
def write_role_attribute(new_role)
|
76
|
+
write_attribute(self.class.dar_dar_da.options[:role_attribute], new_role.to_s)
|
77
|
+
end
|
78
|
+
|
79
|
+
def set_role_to_default_value
|
80
|
+
unless self.class.dar_dar_da[read_role_attribute]
|
81
|
+
write_role_attribute(self.class.dar_dar_da.options[:default_role])
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module DarDaDa
|
2
|
+
class Config < Hash
|
3
|
+
def initialize(options={}, &block)
|
4
|
+
@options = DarDaDa.config.merge(options)
|
5
|
+
@all_rights, @first_added_role_name = [], nil
|
6
|
+
reopen(&block)
|
7
|
+
end
|
8
|
+
|
9
|
+
def reopen(&block)
|
10
|
+
instance_eval(&block) if block_given?
|
11
|
+
finalize
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :options, :all_rights
|
15
|
+
|
16
|
+
def role(name, options={}, &block)
|
17
|
+
name = name.to_sym
|
18
|
+
@options[:default_role] = name if options[:default]
|
19
|
+
@first_added_role_name = name if empty?
|
20
|
+
self[name] ||= DarDaDa::Role.new(name)
|
21
|
+
self[name].instance_eval(&block) if block_given?
|
22
|
+
end
|
23
|
+
|
24
|
+
def [](role_name)
|
25
|
+
role_name = role_name.to_sym unless role_name.blank?
|
26
|
+
super(role_name)
|
27
|
+
end
|
28
|
+
|
29
|
+
def finalize
|
30
|
+
# Merge rights between roles
|
31
|
+
each do |name, role|
|
32
|
+
role.merge_rights do |role_name|
|
33
|
+
self[role_name]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Check if default_role exists
|
38
|
+
# and delete it if it does not
|
39
|
+
options.delete(:default_role) unless self[options[:default_role]]
|
40
|
+
|
41
|
+
# Set default role to first added
|
42
|
+
# if not specified
|
43
|
+
options[:default_role] = @first_added_role_name unless options[:default_role]
|
44
|
+
|
45
|
+
# Finalize roles
|
46
|
+
each{|name, role| role.finalize}
|
47
|
+
|
48
|
+
# Collect and unify all_rights
|
49
|
+
@all_rights = map do |role|
|
50
|
+
role[1].to_a
|
51
|
+
end
|
52
|
+
@all_rights.flatten!
|
53
|
+
@all_rights.uniq!
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module DarDaDa
|
2
|
+
class Role < Array
|
3
|
+
def initialize(name)
|
4
|
+
super()
|
5
|
+
@name = name.to_sym
|
6
|
+
@merge_rights_from = []
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :name, :merge_rights_from
|
10
|
+
|
11
|
+
def <<(right)
|
12
|
+
super(right.to_sym)
|
13
|
+
end
|
14
|
+
|
15
|
+
def include?(right)
|
16
|
+
super(right.to_sym)
|
17
|
+
end
|
18
|
+
alias_method :member?, :include?
|
19
|
+
|
20
|
+
def is_allowed_to(*names)
|
21
|
+
concat(names.map(&:to_sym))
|
22
|
+
end
|
23
|
+
|
24
|
+
def based_on(*roles)
|
25
|
+
roles.each do |role|
|
26
|
+
merge_rights_from << role.to_sym
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def merge_rights(stack=[], &block)
|
31
|
+
raise "You defined a circular reference when configuring DarDaDa with 'based_on'." if stack.include?(name)
|
32
|
+
stack << name
|
33
|
+
merge_rights_from.uniq.each do |role_name|
|
34
|
+
next if role_name == name
|
35
|
+
from = yield(role_name)
|
36
|
+
is_allowed_to(*from.merge_rights(stack, &block)) if from
|
37
|
+
end
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
def finalize
|
42
|
+
self.uniq!
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/dar_da_da.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'dar_da_da/config'
|
2
|
+
require 'dar_da_da/role'
|
3
|
+
require 'dar_da_da/version'
|
4
|
+
|
5
|
+
module DarDaDa
|
6
|
+
@@config = {:role_attribute => :role_name }
|
7
|
+
mattr_accessor :config
|
8
|
+
end
|
9
|
+
|
10
|
+
if defined? ActiveRecord::Base
|
11
|
+
require 'dar_da_da/active_record_extension'
|
12
|
+
ActiveRecord::Base.send(:include, DarDaDa::ActiveRecordExtension)
|
13
|
+
end
|
14
|
+
|
15
|
+
if defined? ActionController::Base
|
16
|
+
require 'dar_da_da/action_controller_extension'
|
17
|
+
ActionController::Base.send(:include, DarDaDa::ActionControllerExtension)
|
18
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe DarDaDa::ActionControllerExtension, "extended Base" do
|
4
|
+
it "should define only_if_{user}_is_allowed_to_{right} methods" do
|
5
|
+
ApplicationController.private_instance_methods.map(&:to_s).should include("check_if_user_is_allowed_to_cancel_account")
|
6
|
+
User.create!(:role => :user)
|
7
|
+
lambda{
|
8
|
+
ApplicationController.new.send(:check_if_user_is_allowed_to_cancel_account)
|
9
|
+
}.should raise_error(ActionController::ForbiddenError)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should define only_if_user_is_allowed_to class method" do
|
13
|
+
ApplicationController.methods.map(&:to_s).should include("require_right")
|
14
|
+
ApplicationController.should_receive(:before_filter).with(:check_if_user_is_allowed_to_read_acticles, :only => [:index])
|
15
|
+
ApplicationController.require_right(:read_acticles, :only => [:index])
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe DarDaDa::ActiveRecordExtension, "extended Model" do
|
4
|
+
before { @user = User.create! }
|
5
|
+
|
6
|
+
it "should set role to default_role" do
|
7
|
+
@user.role.should eql("user")
|
8
|
+
User.new.role.should eql("user")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should add role accessor to map role_attribute" do
|
12
|
+
@user.role = :author
|
13
|
+
@user.role.should eql("author")
|
14
|
+
@user.role = :unknown_role
|
15
|
+
@user.role.should eql("author")
|
16
|
+
@user.save!
|
17
|
+
@user.role.should eql("author")
|
18
|
+
@user.update_attributes!(:role => 'user')
|
19
|
+
@user.role.should eql("user")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should set default_role to user" do
|
23
|
+
User.dar_dar_da.options[:default_role].should == (:"user")
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should prevent saving role_attribute with nil or empty" do
|
27
|
+
@user.role_name = ""
|
28
|
+
@user.send(:read_role_attribute).should be_blank
|
29
|
+
@user.save!
|
30
|
+
@user.reload
|
31
|
+
@user.send(:read_role_attribute).should eql("user")
|
32
|
+
@user.role_name.should eql("user")
|
33
|
+
@user.role.should eql("user")
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should prevent saving role_attribute with not exisiting role" do
|
37
|
+
@user.role_name = "unknown"
|
38
|
+
@user.send(:read_role_attribute).should eql("unknown")
|
39
|
+
@user.save!
|
40
|
+
@user.reload
|
41
|
+
@user.send(:read_role_attribute).should eql("user")
|
42
|
+
@user.role_name.should eql("user")
|
43
|
+
@user.role.should eql("user")
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should add {role}? methods" do
|
47
|
+
@user.should be_user
|
48
|
+
@user.role = :author
|
49
|
+
@user.should be_author
|
50
|
+
@user.role = :admin
|
51
|
+
@user.should be_admin
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should add allowed_to? method" do
|
55
|
+
@user.allowed_to?(:read_acticles).should be_true
|
56
|
+
@user.allowed_to?("read_acticles").should be_true
|
57
|
+
@user.allowed_to?(:write_acticles).should be_false
|
58
|
+
@user.allowed_to?(:cancel_account).should be_false
|
59
|
+
@user.allowed_to?(:do_unknown_stuff).should be_false
|
60
|
+
@user.allowed_to?("").should be_false
|
61
|
+
@user.allowed_to?(nil).should be_false
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should add allowed_to_{right}? methods" do
|
65
|
+
@user.should be_allowed_to_read_acticles
|
66
|
+
@user.should_not be_allowed_to_write_acticles
|
67
|
+
@user.should_not be_allowed_to_cancel_account
|
68
|
+
@user.role = :author
|
69
|
+
@user.should be_allowed_to_read_acticles
|
70
|
+
@user.should be_allowed_to_write_acticles
|
71
|
+
@user.should_not be_allowed_to_cancel_account
|
72
|
+
@user.role = :admin
|
73
|
+
@user.should be_allowed_to_read_acticles
|
74
|
+
@user.should be_allowed_to_write_acticles
|
75
|
+
@user.should be_allowed_to_cancel_account
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should add named_scope for every role" do
|
79
|
+
User.destroy_all
|
80
|
+
User.create!(:role => "admin")
|
81
|
+
2.times { User.create!(:role => :author) }
|
82
|
+
3.times { User.create!(:role => :user) }
|
83
|
+
User.admins.map(&:role).should eql(["admin"])
|
84
|
+
User.authors.map(&:role).should eql(["author", "author"])
|
85
|
+
User.users.map(&:role).should eql(["user", "user", "user"])
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,212 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe DarDaDa::Config do
|
4
|
+
|
5
|
+
it "should require nothing as attribute" do
|
6
|
+
lambda { DarDaDa::Config.new }.should_not raise_error
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should be empty " do
|
10
|
+
DarDaDa::Config.new.should be_empty
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should allow accessing role by string" do
|
14
|
+
config = DarDaDa::Config.new do
|
15
|
+
role :admin
|
16
|
+
end
|
17
|
+
config["admin"].should eql(config[:admin])
|
18
|
+
config[nil]
|
19
|
+
config[""]
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "options" do
|
23
|
+
it "should have role_attribute set to role_name default" do
|
24
|
+
DarDaDa::Config.new.options[:role_attribute].should eql(:role_name)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should allow setting role_attribute via options" do
|
28
|
+
DarDaDa::Config.new(:role_attribute => :role).options[:role_attribute].should eql(:role)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should eval block inside instance" do
|
33
|
+
lambda { DarDaDa::Config.new do
|
34
|
+
raise "config_error"
|
35
|
+
end }.should raise_error("config_error")
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "role" do
|
39
|
+
|
40
|
+
it "should add new instance to roles" do
|
41
|
+
config = DarDaDa::Config.new do
|
42
|
+
role :admin
|
43
|
+
end
|
44
|
+
config.keys.should eql([:admin])
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should eval role-block inside role-instance" do
|
48
|
+
lambda { DarDaDa::Config.new do
|
49
|
+
role :admin do
|
50
|
+
raise name.to_s + "_deep_error"
|
51
|
+
end
|
52
|
+
end }.should raise_error("admin_deep_error")
|
53
|
+
|
54
|
+
config = DarDaDa::Config.new do
|
55
|
+
role :admin do
|
56
|
+
is_allowed_to :manage_users
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
config.should == ({:admin => [:manage_users]})
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should eval role-block inside of exisiting role-instance" do
|
64
|
+
config = DarDaDa::Config.new do
|
65
|
+
role :admin do
|
66
|
+
is_allowed_to :manage_users
|
67
|
+
end
|
68
|
+
|
69
|
+
role :admin do
|
70
|
+
is_allowed_to :manage_projects
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
config.should == ({:admin => [:manage_users, :manage_projects]})
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should reopen existing config and eval block" do
|
78
|
+
config = DarDaDa::Config.new
|
79
|
+
config.reopen do
|
80
|
+
role :admin
|
81
|
+
end
|
82
|
+
config.keys.should eql([:admin])
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "default_role" do
|
88
|
+
it "should have empty default_role" do
|
89
|
+
DarDaDa::Config.new.options[:default_role].should be_nil
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should set first added role to default_role by default" do
|
93
|
+
config = DarDaDa::Config.new do
|
94
|
+
role :admin
|
95
|
+
role :author
|
96
|
+
end
|
97
|
+
config.options[:default_role].should eql(:admin)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should allow setting default_role while initalizing" do
|
101
|
+
config = DarDaDa::Config.new :default_role => :admin do
|
102
|
+
role :author
|
103
|
+
role :admin
|
104
|
+
end
|
105
|
+
config.options[:default_role].should eql(:admin)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should remove nonexisiting roles after initalizing" do
|
109
|
+
config = DarDaDa::Config.new :default_role => :admin do
|
110
|
+
end
|
111
|
+
config.options[:default_role].should be_nil
|
112
|
+
config = DarDaDa::Config.new :default_role => :admin
|
113
|
+
config.options[:default_role].should be_nil
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should take first added role even when invalid other specified" do
|
117
|
+
config = DarDaDa::Config.new :default_role => :admin do
|
118
|
+
role :author
|
119
|
+
end
|
120
|
+
config.options[:default_role].should eql(:author)
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should allow setting role to default_role when given" do
|
124
|
+
config = DarDaDa::Config.new do
|
125
|
+
role :admin
|
126
|
+
role :author, :default => true
|
127
|
+
end
|
128
|
+
config.options[:default_role].should eql(:author)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "all_rights" do
|
133
|
+
it "should be empty by default" do
|
134
|
+
DarDaDa::Config.new.all_rights.should eql([])
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should collect all rights" do
|
138
|
+
config = DarDaDa::Config.new do
|
139
|
+
role :admin do
|
140
|
+
is_allowed_to :b, :a, :c
|
141
|
+
end
|
142
|
+
role :author do
|
143
|
+
is_allowed_to :e
|
144
|
+
is_allowed_to :d
|
145
|
+
end
|
146
|
+
end
|
147
|
+
config.all_rights.should include(:a, :b, :c, :d, :e)
|
148
|
+
config.all_rights.size.should eql([:a, :b, :c, :d, :e].size)
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should remove duplicates" do
|
152
|
+
config = DarDaDa::Config.new do
|
153
|
+
role :admin do
|
154
|
+
is_allowed_to :a, :b
|
155
|
+
end
|
156
|
+
role :author do
|
157
|
+
is_allowed_to :b
|
158
|
+
is_allowed_to :a
|
159
|
+
is_allowed_to :c
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
config.all_rights.should include(:a, :b, :c)
|
164
|
+
config.all_rights.size.should eql([:a, :b, :c].size)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe "based_on" do
|
169
|
+
it "should copy rights between roles" do
|
170
|
+
config = DarDaDa::Config.new do
|
171
|
+
|
172
|
+
role :author do
|
173
|
+
based_on :user
|
174
|
+
is_allowed_to :write_articles
|
175
|
+
end
|
176
|
+
|
177
|
+
role :user do
|
178
|
+
is_allowed_to :read_articles
|
179
|
+
end
|
180
|
+
|
181
|
+
role :admin do
|
182
|
+
based_on :author
|
183
|
+
is_allowed_to :cancel_accounts
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
config[:admin].should == ([:cancel_accounts, :write_articles, :read_articles])
|
188
|
+
config[:author].should == ([:write_articles, :read_articles])
|
189
|
+
config[:user].should == ([:read_articles])
|
190
|
+
end
|
191
|
+
|
192
|
+
it "should throw error on circular references" do
|
193
|
+
lambda { config = DarDaDa::Config.new do
|
194
|
+
|
195
|
+
role :author do
|
196
|
+
based_on :user
|
197
|
+
is_allowed_to :write_articles
|
198
|
+
end
|
199
|
+
|
200
|
+
role :user do
|
201
|
+
based_on :admin
|
202
|
+
is_allowed_to :read_articles
|
203
|
+
end
|
204
|
+
|
205
|
+
role :admin do
|
206
|
+
based_on :author
|
207
|
+
is_allowed_to :cancel_accounts
|
208
|
+
end
|
209
|
+
end }.should raise_error("You defined a circular reference when configuring DarDaDa with 'based_on'.")
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe DarDaDa::Role do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@role = DarDaDa::Role.new(:role1)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should require name as attribute" do
|
10
|
+
lambda { DarDaDa::Role.new }.should raise_error(ArgumentError)
|
11
|
+
DarDaDa::Role.new(:role1).name.should eql(:role1)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should store name as symbol" do
|
15
|
+
DarDaDa::Role.new("role1").name.should eql(:role1)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should be empty array" do
|
19
|
+
@role.should eql([])
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should convert strings to symbols when adding" do
|
23
|
+
@role << :r1
|
24
|
+
@role.should eql([:r1])
|
25
|
+
@role << "r2"
|
26
|
+
@role.should eql([:r1, :r2])
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should have include?/memeber? methods that convert strings to symbols" do
|
30
|
+
@role << :manage_projects
|
31
|
+
@role.include?(:manage_projects).should be_true
|
32
|
+
@role.include?("manage_projects").should be_true
|
33
|
+
@role.include?("manage_users").should be_false
|
34
|
+
@role.member?(:manage_projects).should be_true
|
35
|
+
@role.member?("manage_projects").should be_true
|
36
|
+
@role.member?("manage_users").should be_false
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "is_allowed_to" do
|
40
|
+
it "should add new instance to rights" do
|
41
|
+
@role.is_allowed_to :manage_projects
|
42
|
+
@role.should eql([:manage_projects])
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should convert strings to symbols" do
|
46
|
+
@role.is_allowed_to "manage_projects"
|
47
|
+
@role.should eql([:manage_projects])
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should allow adding multiple rights at once" do
|
51
|
+
@role.is_allowed_to :manage_projects, :cancel_account
|
52
|
+
@role.should eql([:manage_projects, :cancel_account])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "based_on" do
|
57
|
+
it "should add new instance to merge_rights_from" do
|
58
|
+
role = DarDaDa::Role.new(:admin)
|
59
|
+
role.based_on "author"
|
60
|
+
role.merge_rights_from.should eql([:author])
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should allow adding multiple roles at once" do
|
64
|
+
role = DarDaDa::Role.new(:role1)
|
65
|
+
role.based_on :author, "user"
|
66
|
+
role.merge_rights_from.should == ([:author, :user])
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rspec'
|
3
|
+
|
4
|
+
require 'active_support'
|
5
|
+
require 'active_record'
|
6
|
+
require 'action_controller'
|
7
|
+
|
8
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
9
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
10
|
+
require 'dar_da_da'
|
11
|
+
|
12
|
+
# Spec::Runner.configure do |config|
|
13
|
+
#
|
14
|
+
# end
|
15
|
+
|
16
|
+
ActiveRecord::Base.logger = Logger.new('/tmp/dar_da_da.log')
|
17
|
+
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => '/tmp/dar_da_da.sqlite')
|
18
|
+
ActiveRecord::Migration.verbose = false
|
19
|
+
|
20
|
+
ActiveRecord::Schema.define do
|
21
|
+
create_table :users, :force => true do |table|
|
22
|
+
table.string :name
|
23
|
+
table.string :role_name
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
# Purely useful for test cases...
|
29
|
+
class User < ActiveRecord::Base
|
30
|
+
define_roles do
|
31
|
+
role :admin do
|
32
|
+
based_on :author
|
33
|
+
is_allowed_to :cancel_account
|
34
|
+
end
|
35
|
+
|
36
|
+
role :author do
|
37
|
+
based_on :user
|
38
|
+
is_allowed_to :write_acticles
|
39
|
+
end
|
40
|
+
|
41
|
+
role :user, :default => true do
|
42
|
+
is_allowed_to :read_acticles
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class ApplicationController < ActionController::Base
|
48
|
+
|
49
|
+
define_access_control User
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def current_user
|
54
|
+
User.first
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
data/spec/watchr.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# Run me with:
|
2
|
+
#
|
3
|
+
# $ watchr specs.watchr.rb
|
4
|
+
|
5
|
+
# --------------------------------------------------
|
6
|
+
# Convenience Methods
|
7
|
+
# --------------------------------------------------
|
8
|
+
|
9
|
+
def run(files)
|
10
|
+
files = Array(files).reject do |file|
|
11
|
+
skip = !File.exist?(file)
|
12
|
+
puts "*** #{file} skipped - does not exist!" if skip
|
13
|
+
skip
|
14
|
+
end
|
15
|
+
|
16
|
+
if files.any?
|
17
|
+
cmd = "spec -c #{files.join(' ')}"
|
18
|
+
puts("*** Executing #{cmd}")
|
19
|
+
system(cmd)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def run_all_tests
|
24
|
+
puts "\n***** Running all tests *****\n"
|
25
|
+
cmd = Dir['spec/**/*_spec.rb']
|
26
|
+
run(cmd)
|
27
|
+
end
|
28
|
+
|
29
|
+
# --------------------------------------------------
|
30
|
+
# Watchr Rules
|
31
|
+
# --------------------------------------------------
|
32
|
+
watch( '^lib/(.*)\.rb' ) { |m| run( "spec/%s_spec.rb" % m[1] ) }
|
33
|
+
watch( '^lib/(.*)/(.*)\.rb' ) { |m| run( "spec/#{m[1]}/#{m[2]}_spec.rb" ) }
|
34
|
+
watch( '^spec/(.*)_spec\.rb' ) { |m| run( "spec/%s_spec.rb" % m[1] ) }
|
35
|
+
watch( '^spec/spec_helper\.rb' ) { run_all_tests }
|
36
|
+
|
37
|
+
# --------------------------------------------------
|
38
|
+
# Signal Handling
|
39
|
+
# --------------------------------------------------
|
40
|
+
# Ctrl-\
|
41
|
+
Signal.trap('QUIT') do
|
42
|
+
run_all_tests
|
43
|
+
end
|
44
|
+
|
45
|
+
# Ctrl-C
|
46
|
+
Signal.trap('INT') { abort("\n") }
|
47
|
+
|
48
|
+
puts "*** Watching for changes..."
|
metadata
ADDED
@@ -0,0 +1,203 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dar_da_da
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Sebastian Munz
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-04-23 00:00:00 +02:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: activesupport
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 3
|
30
|
+
- 0
|
31
|
+
version: "3.0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: activerecord
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
segments:
|
43
|
+
- 3
|
44
|
+
- 0
|
45
|
+
version: "3.0"
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: actionpack
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
segments:
|
57
|
+
- 3
|
58
|
+
- 0
|
59
|
+
version: "3.0"
|
60
|
+
type: :development
|
61
|
+
version_requirements: *id003
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec
|
64
|
+
prerelease: false
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
segments:
|
71
|
+
- 2
|
72
|
+
- 4
|
73
|
+
- 0
|
74
|
+
version: 2.4.0
|
75
|
+
type: :development
|
76
|
+
version_requirements: *id004
|
77
|
+
- !ruby/object:Gem::Dependency
|
78
|
+
name: guard-rspec
|
79
|
+
prerelease: false
|
80
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
- 1
|
88
|
+
- 9
|
89
|
+
version: 0.1.9
|
90
|
+
type: :development
|
91
|
+
version_requirements: *id005
|
92
|
+
- !ruby/object:Gem::Dependency
|
93
|
+
name: growl
|
94
|
+
prerelease: false
|
95
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
segments:
|
101
|
+
- 1
|
102
|
+
- 0
|
103
|
+
- 3
|
104
|
+
version: 1.0.3
|
105
|
+
type: :development
|
106
|
+
version_requirements: *id006
|
107
|
+
- !ruby/object:Gem::Dependency
|
108
|
+
name: rb-fsevent
|
109
|
+
prerelease: false
|
110
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
111
|
+
none: false
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
segments:
|
116
|
+
- 0
|
117
|
+
- 3
|
118
|
+
- 9
|
119
|
+
version: 0.3.9
|
120
|
+
type: :development
|
121
|
+
version_requirements: *id007
|
122
|
+
- !ruby/object:Gem::Dependency
|
123
|
+
name: sqlite3-ruby
|
124
|
+
prerelease: false
|
125
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
126
|
+
none: false
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
segments:
|
131
|
+
- 0
|
132
|
+
version: "0"
|
133
|
+
type: :development
|
134
|
+
version_requirements: *id008
|
135
|
+
description: Roles easy like sunday morning.
|
136
|
+
email:
|
137
|
+
- sebastian@yo.lk
|
138
|
+
executables: []
|
139
|
+
|
140
|
+
extensions: []
|
141
|
+
|
142
|
+
extra_rdoc_files: []
|
143
|
+
|
144
|
+
files:
|
145
|
+
- .gitignore
|
146
|
+
- Gemfile
|
147
|
+
- Guardfile
|
148
|
+
- LICENSE
|
149
|
+
- README.rdoc
|
150
|
+
- Rakefile
|
151
|
+
- dar_da_da.gemspec
|
152
|
+
- init.rb
|
153
|
+
- lib/dar_da_da.rb
|
154
|
+
- lib/dar_da_da/action_controller_extension.rb
|
155
|
+
- lib/dar_da_da/active_record_extension.rb
|
156
|
+
- lib/dar_da_da/config.rb
|
157
|
+
- lib/dar_da_da/role.rb
|
158
|
+
- lib/dar_da_da/version.rb
|
159
|
+
- spec/dar_da_da/action_controller_extension_spec.rb
|
160
|
+
- spec/dar_da_da/active_record_extension_spec.rb
|
161
|
+
- spec/dar_da_da/config_spec.rb
|
162
|
+
- spec/dar_da_da/role_spec.rb
|
163
|
+
- spec/spec_helper.rb
|
164
|
+
- spec/watchr.rb
|
165
|
+
has_rdoc: true
|
166
|
+
homepage: https://github.com/yolk/dar_da_da
|
167
|
+
licenses: []
|
168
|
+
|
169
|
+
post_install_message:
|
170
|
+
rdoc_options: []
|
171
|
+
|
172
|
+
require_paths:
|
173
|
+
- lib
|
174
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
175
|
+
none: false
|
176
|
+
requirements:
|
177
|
+
- - ">="
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
segments:
|
180
|
+
- 0
|
181
|
+
version: "0"
|
182
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
183
|
+
none: false
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
segments:
|
188
|
+
- 0
|
189
|
+
version: "0"
|
190
|
+
requirements: []
|
191
|
+
|
192
|
+
rubyforge_project: dar_da_da
|
193
|
+
rubygems_version: 1.3.7
|
194
|
+
signing_key:
|
195
|
+
specification_version: 3
|
196
|
+
summary: Roles easy like sunday morning.
|
197
|
+
test_files:
|
198
|
+
- spec/dar_da_da/action_controller_extension_spec.rb
|
199
|
+
- spec/dar_da_da/active_record_extension_spec.rb
|
200
|
+
- spec/dar_da_da/config_spec.rb
|
201
|
+
- spec/dar_da_da/role_spec.rb
|
202
|
+
- spec/spec_helper.rb
|
203
|
+
- spec/watchr.rb
|