dar_da_da 0.0.1
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.
- 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
|