reuser 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/reuser/role.rb +19 -31
- data/lib/reuser/version.rb +6 -0
- data/lib/reuser.rb +37 -2
- data/spec/reuser/class_spec.rb +61 -0
- data/spec/reuser/instances_spec.rb +34 -0
- data/spec/reuser/role_spec.rb +49 -0
- data/spec/spec_helper.rb +5 -0
- metadata +14 -14
- data/README.md +0 -95
- data/Rakefile +0 -24
- data/lib/reuser/reuser.rb +0 -46
- data/spec/reuser/reuser_spec.rb +0 -65
- data/spec/reuser/test_reuser.rb +0 -22
- data/spec/reuser.rb +0 -1
data/lib/reuser/role.rb
CHANGED
@@ -1,46 +1,34 @@
|
|
1
|
-
require_relative('../reuser')
|
2
|
-
|
3
1
|
module ReUser
|
4
2
|
class Role
|
5
|
-
|
6
|
-
@name = name
|
7
|
-
@actions = {}
|
8
|
-
end
|
3
|
+
attr_reader :name
|
9
4
|
|
10
|
-
def
|
11
|
-
|
5
|
+
def permissions
|
6
|
+
@permissions.keys
|
12
7
|
end
|
13
8
|
|
14
|
-
def
|
15
|
-
|
9
|
+
def initialize name, permissions=[]
|
10
|
+
@name = name
|
11
|
+
@permissions = {}
|
12
|
+
self.can *permissions
|
16
13
|
end
|
17
14
|
|
18
|
-
def
|
19
|
-
|
20
|
-
|
15
|
+
def can *permissions
|
16
|
+
permissions.each do |permission|
|
17
|
+
@permissions[permission] = lambda {|*args| true }
|
21
18
|
end
|
22
19
|
end
|
23
20
|
|
24
|
-
def
|
25
|
-
|
26
|
-
if actions[name].is_a?(Proc)
|
27
|
-
actions[name].call(data)
|
28
|
-
else
|
29
|
-
true
|
30
|
-
end
|
31
|
-
end
|
21
|
+
def can? permission
|
22
|
+
@permissions[permission].is_a? Proc
|
32
23
|
end
|
33
24
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
39
|
-
@actions
|
40
|
-
end
|
25
|
+
def could permission, &block
|
26
|
+
raise "#could requires a block" unless block_given?
|
27
|
+
@permissions[permission] = block
|
28
|
+
end
|
41
29
|
|
42
|
-
|
43
|
-
|
44
|
-
|
30
|
+
def could? permission, block_args
|
31
|
+
@permissions[permission].call(block_args)
|
32
|
+
end
|
45
33
|
end
|
46
34
|
end
|
data/lib/reuser.rb
CHANGED
@@ -1,2 +1,37 @@
|
|
1
|
-
require_relative
|
2
|
-
|
1
|
+
require_relative "./reuser/role"
|
2
|
+
|
3
|
+
module ReUser
|
4
|
+
|
5
|
+
def self.included klass
|
6
|
+
|
7
|
+
klass.instance_eval do
|
8
|
+
def roles &block
|
9
|
+
@@roles ||= {}
|
10
|
+
yield if block_given?
|
11
|
+
@@roles.freeze.keys
|
12
|
+
end
|
13
|
+
|
14
|
+
def role name, permissions=[], &block
|
15
|
+
role = ( @@roles[name] ||= ReUser::Role.new(name, permissions) )
|
16
|
+
yield(role) if block_given?
|
17
|
+
role
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def can? permission
|
23
|
+
@role.can? permission
|
24
|
+
end
|
25
|
+
|
26
|
+
def cant? permission
|
27
|
+
!(can? permission)
|
28
|
+
end
|
29
|
+
|
30
|
+
def could? permission, block_args
|
31
|
+
@role.could? permission, block_args
|
32
|
+
end
|
33
|
+
|
34
|
+
def couldnt? permission, block_args
|
35
|
+
!(couldnt? permission, block_args)
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
describe "Classes including ReUser" do
|
4
|
+
let(:klass) do
|
5
|
+
kls = Class.new
|
6
|
+
kls.instance_eval do
|
7
|
+
include ReUser
|
8
|
+
|
9
|
+
roles do
|
10
|
+
role(:admin)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
kls
|
14
|
+
end
|
15
|
+
subject { klass }
|
16
|
+
|
17
|
+
context ".roles" do
|
18
|
+
it "optionally takes a block" do
|
19
|
+
lambda { subject.roles { :good } }.should_not raise_error
|
20
|
+
lambda { subject.roles }.should_not raise_error
|
21
|
+
end
|
22
|
+
|
23
|
+
it "returns an array of role names" do
|
24
|
+
subject.roles.should be_kind_of Array
|
25
|
+
subject.roles.all? {|el| el.is_a? Symbol}.should be_true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context ".role" do
|
30
|
+
|
31
|
+
it "takes a symbol" do
|
32
|
+
lambda { subject.role(:admin) }.should_not raise_error
|
33
|
+
end
|
34
|
+
|
35
|
+
it "takes a symbol, and an optional array" do
|
36
|
+
lambda { subject.role(:admin, [:read, :write]) }.should_not raise_error
|
37
|
+
end
|
38
|
+
|
39
|
+
it "returns a ReUser::Role instance" do
|
40
|
+
subject.role(:admin).should be_instance_of ReUser::Role
|
41
|
+
end
|
42
|
+
|
43
|
+
context "passing in a role that is already defined" do
|
44
|
+
it "returns the same role" do
|
45
|
+
expected = subject.role(:admin)
|
46
|
+
subject.role(:admin).should === expected
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "passing in a role that is not already defined" do
|
51
|
+
it "raises an error" do
|
52
|
+
subject.class_eval do
|
53
|
+
roles do
|
54
|
+
role(:admin)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
lambda { subject.role(:user) }.should raise_error
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
describe "Instances of a Class including ReUser" do
|
4
|
+
let(:klass) do
|
5
|
+
kls = Class.new
|
6
|
+
kls.instance_eval do
|
7
|
+
include ReUser
|
8
|
+
|
9
|
+
roles do
|
10
|
+
role :admin do |admin|
|
11
|
+
admin.can :read
|
12
|
+
admin.could :write do |language|
|
13
|
+
language == "English"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
kls
|
19
|
+
end
|
20
|
+
|
21
|
+
subject do
|
22
|
+
instance = klass.new
|
23
|
+
instance.instance_variable_set(:@role, klass.role(:admin))
|
24
|
+
instance
|
25
|
+
end
|
26
|
+
|
27
|
+
it "#can? and #could? are delegated to the ReUser::Role" do
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
it "#cant? and #couldnt? are negations of #can? and #could?" do
|
32
|
+
true
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
describe ReUser::Role do
|
4
|
+
subject do
|
5
|
+
role = ReUser::Role.new(:admin)
|
6
|
+
role.can(:read)
|
7
|
+
role
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'is initialized with a name, and optionally an array of permissions' do
|
11
|
+
role = ReUser::Role.new :admin
|
12
|
+
role.name.should == :admin
|
13
|
+
role.permissions.should == []
|
14
|
+
|
15
|
+
role = ReUser::Role.new :user
|
16
|
+
role.name.should == :user
|
17
|
+
role.permissions.should == []
|
18
|
+
|
19
|
+
role = ReUser::Role.new :user, [:read, :write]
|
20
|
+
role.name.should == :user
|
21
|
+
role.permissions.should == [:read, :write]
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'shares its name and permissions' do
|
25
|
+
its(:name) { should === :admin }
|
26
|
+
its(:permissions) { should === [:read] }
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'permissions are added and checked with #can and #can?' do
|
30
|
+
subject.can?(:read).should be_true
|
31
|
+
subject.can?(:write).should be_false
|
32
|
+
subject.can(:write)
|
33
|
+
subject.can?(:write).should be_true
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'you need to supply #could with a test block' do
|
37
|
+
lambda { subject.could(:read) }.should raise_error
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'conditional permissions are added and checked with #could and #could?' do
|
41
|
+
subject.can?(:write).should be_false
|
42
|
+
subject.could :write do |language|
|
43
|
+
language == "English"
|
44
|
+
end
|
45
|
+
subject.can?(:write).should be_true
|
46
|
+
subject.could?(:write, "Japanese").should be_false
|
47
|
+
subject.could?(:write, "English").should be_true
|
48
|
+
end
|
49
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: reuser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,23 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-02-03 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: ReUse is an Internal DSL for Ruby to create roles and manage actions.
|
15
|
-
email: isaacsanders
|
15
|
+
email: isaac@isaacsanders.com
|
16
16
|
executables: []
|
17
17
|
extensions: []
|
18
18
|
extra_rdoc_files: []
|
19
19
|
files:
|
20
20
|
- lib/reuser.rb
|
21
21
|
- lib/reuser/role.rb
|
22
|
-
- lib/reuser/
|
23
|
-
-
|
24
|
-
-
|
25
|
-
- spec/reuser.rb
|
26
|
-
- spec/reuser/
|
27
|
-
|
28
|
-
homepage: http://isaacsanders.github.com/reuser
|
22
|
+
- lib/reuser/version.rb
|
23
|
+
- spec/spec_helper.rb
|
24
|
+
- spec/reuser/class_spec.rb
|
25
|
+
- spec/reuser/role_spec.rb
|
26
|
+
- spec/reuser/instances_spec.rb
|
27
|
+
homepage: http://isaacbfsanders.com/reuser
|
29
28
|
licenses: []
|
30
29
|
post_install_message:
|
31
30
|
rdoc_options: []
|
@@ -45,11 +44,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
45
44
|
version: '0'
|
46
45
|
requirements: []
|
47
46
|
rubyforge_project:
|
48
|
-
rubygems_version: 1.8.
|
47
|
+
rubygems_version: 1.8.15
|
49
48
|
signing_key:
|
50
49
|
specification_version: 3
|
51
50
|
summary: An internal DSL for Ruby to make user role management simple.
|
52
51
|
test_files:
|
53
|
-
- spec/
|
54
|
-
- spec/reuser/
|
55
|
-
- spec/reuser/
|
52
|
+
- spec/spec_helper.rb
|
53
|
+
- spec/reuser/class_spec.rb
|
54
|
+
- spec/reuser/role_spec.rb
|
55
|
+
- spec/reuser/instances_spec.rb
|
data/README.md
DELETED
@@ -1,95 +0,0 @@
|
|
1
|
-
#ReUser
|
2
|
-
##Purpose
|
3
|
-
Whenever you start a web app where a user has specific permissions, do you
|
4
|
-
end up writing your own solution or using something that has brain-bending
|
5
|
-
abstractions? If so, ReUser is the solution for you.
|
6
|
-
##Description
|
7
|
-
ReUser is an Internal DSL for Ruby to create roles and manage actions.
|
8
|
-
##Usage
|
9
|
-
Installing ReUser is easy:
|
10
|
-
|
11
|
-
gem install reuser
|
12
|
-
|
13
|
-
Now to incorporate it into a model:
|
14
|
-
|
15
|
-
require 'reuser'
|
16
|
-
|
17
|
-
class User
|
18
|
-
include ReUser
|
19
|
-
|
20
|
-
roles do
|
21
|
-
|
22
|
-
# declare a role with the can method, taking a list of actions.
|
23
|
-
role(:admin).can :read, :write, :execute
|
24
|
-
|
25
|
-
role :user do |usr| # pass a block, so you can
|
26
|
-
usr.can :read
|
27
|
-
|
28
|
-
# declare a role, then declare a conditional action with could.
|
29
|
-
# could takes a list of names, then assigns a test to them.
|
30
|
-
# You can then ask your model:
|
31
|
-
##usr.could?(:write, 'un-owned-file')
|
32
|
-
###=> false
|
33
|
-
# or
|
34
|
-
##usr.could?(:write, 'owned-file')
|
35
|
-
###=> true
|
36
|
-
# could? will pass the second argument as the block's argument'
|
37
|
-
|
38
|
-
usr.could :write do |file|
|
39
|
-
usr.owns? file
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
# Or you can declare a role with the name, followed by an array of names
|
44
|
-
role :writer, [:read, :write]
|
45
|
-
|
46
|
-
# Then, you can declare a default, accessible by storing :default as
|
47
|
-
# your model's role, it will point to original role.
|
48
|
-
default :user
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
You can restrict the instances from doing things based on role:
|
53
|
-
|
54
|
-
def administrate
|
55
|
-
if @user.role? :admin
|
56
|
-
administer
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
Or based on their actions:
|
61
|
-
|
62
|
-
def do_something_risky
|
63
|
-
if @user.can?(:do_this)
|
64
|
-
do_it
|
65
|
-
else
|
66
|
-
tell_them_to_get_out!
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def do_something_with_obj
|
71
|
-
if @user.could?(:write, file)
|
72
|
-
write file
|
73
|
-
else
|
74
|
-
raise 'Not your file!'
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
##Issues?
|
79
|
-
Please don't hesitate to open up an issue. You can even contribute! Which
|
80
|
-
brings me to...
|
81
|
-
##Contributing!
|
82
|
-
This is open source, so I want others to help too. For now I have no plans
|
83
|
-
on adding too much more to this project, as far as functionality is
|
84
|
-
concerned, but don't let that get in your way of opening a request or forking
|
85
|
-
the project and adding something. I just ask that:
|
86
|
-
|
87
|
-
- You are polite about it.
|
88
|
-
- You test it.
|
89
|
-
- You explain it, or it is easy to read.
|
90
|
-
|
91
|
-
Following these will let us get along and make better software, quicker, and
|
92
|
-
with less bugs.(hypothetically)
|
93
|
-
|
94
|
-
I am still working on the final syntax, but we are getting closer. If you
|
95
|
-
have any suggestions on syntax, open a feature require
|
data/Rakefile
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
desc 'build the .gem file from gemspec'
|
2
|
-
task :build do
|
3
|
-
sh 'gem build reuser.gemspec'
|
4
|
-
end
|
5
|
-
|
6
|
-
desc 'install the gem from .gem file'
|
7
|
-
task :install do
|
8
|
-
sh 'gem install reuser-*.gem'
|
9
|
-
end
|
10
|
-
|
11
|
-
desc 'push the gem to rubygems.org'
|
12
|
-
task :push do
|
13
|
-
sh 'gem push reuser-*.gem'
|
14
|
-
end
|
15
|
-
|
16
|
-
desc 'make (build and install the gem from gemspec)'
|
17
|
-
task :make => [:build, :install]
|
18
|
-
|
19
|
-
require 'rspec/core/rake_task'
|
20
|
-
RSpec::Core::RakeTask.new(:spec) do |t|
|
21
|
-
t.rspec_opts = '--color'
|
22
|
-
end
|
23
|
-
|
24
|
-
task :default => :spec
|
data/lib/reuser/reuser.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
require_relative('../reuser')
|
2
|
-
|
3
|
-
module ReUser
|
4
|
-
class NoRoleError < StandardError; end;
|
5
|
-
class NoDefaultRoleError < StandardError; end;
|
6
|
-
instance_eval do
|
7
|
-
def included(subclass)
|
8
|
-
subclass.instance_eval do
|
9
|
-
def roles(&block)
|
10
|
-
@@roles ||= {}
|
11
|
-
yield if block
|
12
|
-
@@roles.freeze
|
13
|
-
@@roles.keys
|
14
|
-
end
|
15
|
-
|
16
|
-
def role(name, actions_list = nil, &block)
|
17
|
-
@@roles[name] ||= ReUser::Role.new(name)
|
18
|
-
role_name = @@roles[name]
|
19
|
-
yield(role_name) if block
|
20
|
-
if actions_list
|
21
|
-
role_name.can(*actions_list)
|
22
|
-
end
|
23
|
-
role_name
|
24
|
-
end
|
25
|
-
end
|
26
|
-
subclass.class_eval do
|
27
|
-
|
28
|
-
def can?(action)
|
29
|
-
!!@role.can?(action)
|
30
|
-
end
|
31
|
-
|
32
|
-
def cant?(action)
|
33
|
-
!@role.can?(action)
|
34
|
-
end
|
35
|
-
|
36
|
-
def could?(action, obj)
|
37
|
-
!!@role.could?(action, obj)
|
38
|
-
end
|
39
|
-
|
40
|
-
def couldnt?(action, obj)
|
41
|
-
!@role.could?(action, obj)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
data/spec/reuser/reuser_spec.rb
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
require_relative 'test_reuser'
|
2
|
-
|
3
|
-
describe TestReUser do
|
4
|
-
context "has included the ReUser module" do
|
5
|
-
it "should be able to define roles with blocks" do
|
6
|
-
test_ru = TestReUser.new(:admin)
|
7
|
-
test_ru.can?(:read).should == true
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should be able to define roles with arrays" do
|
11
|
-
test_ru = TestReUser.new(:admin)
|
12
|
-
test_ru.can?(:read).should == true
|
13
|
-
end
|
14
|
-
|
15
|
-
context "has defined the :admin and :user roles," do
|
16
|
-
context "is instantiated as test_ru" do
|
17
|
-
context "with role :user" do
|
18
|
-
before do
|
19
|
-
@test_ru = TestReUser.new(:user)
|
20
|
-
end
|
21
|
-
context " using the default role" do
|
22
|
-
it "should not be able to write" do
|
23
|
-
@test_ru.cant?(:write).should == true
|
24
|
-
end
|
25
|
-
|
26
|
-
it "should be able to read" do
|
27
|
-
@test_ru.can?(:read).should == true
|
28
|
-
end
|
29
|
-
|
30
|
-
it "should not be able to call methods restricted to `:admin` roles" do
|
31
|
-
class InsufficientPermissionsError < StandardError;end
|
32
|
-
TestReUser.class_eval do
|
33
|
-
def foo
|
34
|
-
if @role == :admin
|
35
|
-
:something
|
36
|
-
else
|
37
|
-
raise InsufficientPermissionsError, "You can't do that!"
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
lambda {@test_ru.foo}.should raise_error(InsufficientPermissionsError)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
it "should be able to execute on a 1 object." do
|
47
|
-
@test_ru.could?(:execute, 1).should == true
|
48
|
-
@test_ru.couldnt?(:execute, 3).should == true
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
context "set role to :admin" do
|
53
|
-
before do
|
54
|
-
@test_ru = TestReUser.new :admin
|
55
|
-
end
|
56
|
-
it "should be able to read, write, and execute" do
|
57
|
-
@test_ru.can?(:read).should == true
|
58
|
-
@test_ru.can?(:write).should == true
|
59
|
-
@test_ru.can?(:execute).should == true
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
data/spec/reuser/test_reuser.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
require_relative '../reuser'
|
2
|
-
|
3
|
-
class TestReUser
|
4
|
-
include ReUser
|
5
|
-
|
6
|
-
roles do
|
7
|
-
role(:admin).can(:read, :write, :execute)
|
8
|
-
role(:user) do |usr|
|
9
|
-
usr.can :read
|
10
|
-
|
11
|
-
usr.could :execute do |obj|
|
12
|
-
obj == 1
|
13
|
-
end
|
14
|
-
end
|
15
|
-
role :writer, :write
|
16
|
-
role :sysadmin, [:write, :execute]
|
17
|
-
end
|
18
|
-
|
19
|
-
def initialize(name)
|
20
|
-
@role = TestReUser.role(name)
|
21
|
-
end
|
22
|
-
end
|
data/spec/reuser.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require_relative '../lib/reuser'
|