roleable 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 +17 -0
- data/.rspec +1 -0
- data/.travis.yml +6 -0
- data/CHANGELOG +3 -0
- data/Gemfile +2 -0
- data/LICENSE +22 -0
- data/README.md +123 -0
- data/Rakefile +6 -0
- data/lib/generators/roleable/install/USAGE +2 -0
- data/lib/generators/roleable/install/install_generator.rb +22 -0
- data/lib/generators/roleable/install/templates/migration.rb +21 -0
- data/lib/generators/roleable/install/templates/role.rb +5 -0
- data/lib/generators/roleable/install/templates/user_role.rb +5 -0
- data/lib/roleable.rb +5 -0
- data/lib/roleable/resource.rb +18 -0
- data/lib/roleable/role.rb +9 -0
- data/lib/roleable/subject.rb +78 -0
- data/lib/roleable/user_role.rb +60 -0
- data/lib/roleable/version.rb +3 -0
- data/roleable.gemspec +24 -0
- data/spec/roleable/resource_spec.rb +36 -0
- data/spec/roleable/subject_spec.rb +197 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/shared_contexts.rb +28 -0
- metadata +134 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
ADDED
data/CHANGELOG
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Mitch Crowe
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
# Roleable
|
2
|
+
|
3
|
+
[](http://travis-ci.org/mcrowe/roleable)
|
4
|
+
|
5
|
+
A flexible user-roles solution for active-record-backed Rails 3 applications. Allows for multiple roles scoped to instances of any model, as well as global roles (admin, for example).
|
6
|
+
|
7
|
+
Roleable is designed to be ultra simple and obvious, letting you build upon it to satisfy your needs. It is also designed to be efficient: using database indices, and well-crafted queries so that it can handle a huge number of roles.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'roleable'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Run the generator to create the `Role` and `UserRole` models and migrations:
|
22
|
+
|
23
|
+
$ rails g roleable:install
|
24
|
+
|
25
|
+
And then run the migrations:
|
26
|
+
|
27
|
+
$ rake db:migrate
|
28
|
+
|
29
|
+
(This will create the `roles` and `user_roles` tables, together with the appropriate database indices.)
|
30
|
+
|
31
|
+
## Setup
|
32
|
+
|
33
|
+
Include `Roleable::Subject` into your user (subject) model, e.g.:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
class User < ActiveRecord::Base
|
37
|
+
include Roleable::Subject
|
38
|
+
...
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
Include `Roleable::Resource` into any models you want to relate a user role to (resource), e.g.:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
class Page < ActiveRecord::Base
|
46
|
+
include Roleable::Resource
|
47
|
+
...
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
51
|
+
## Usage
|
52
|
+
|
53
|
+
### Subject
|
54
|
+
|
55
|
+
Add a role:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
# global
|
59
|
+
user.add_role(:admin)
|
60
|
+
|
61
|
+
# resource-scoped
|
62
|
+
user.add_role(:editor, page)
|
63
|
+
```
|
64
|
+
|
65
|
+
Remove a role:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
# global
|
69
|
+
user.remove_role(:admin)
|
70
|
+
|
71
|
+
# resource-scoped
|
72
|
+
user.remove_role(:editor, page)
|
73
|
+
```
|
74
|
+
|
75
|
+
Query a role:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
# global
|
79
|
+
user.has_role?(:admin)
|
80
|
+
|
81
|
+
# resource-scoped
|
82
|
+
user.has_role?(:editor, page)
|
83
|
+
```
|
84
|
+
|
85
|
+
Find the resources of a given class for which a user has a given role:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
user.resources_with_role(:editor, Page)
|
89
|
+
```
|
90
|
+
|
91
|
+
Find a user's roles for a given resource:
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
user.roles_for_resource(page)
|
95
|
+
```
|
96
|
+
|
97
|
+
Or, all the global roles for a user:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
user.roles_for_resource(nil)
|
101
|
+
```
|
102
|
+
|
103
|
+
### Resource
|
104
|
+
|
105
|
+
Find users with a given role:
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
page.users_with_role(:editor)
|
109
|
+
```
|
110
|
+
|
111
|
+
For more details check out the [API documentation](http://rubydoc.info/github/mcrowe/roleable/master/frames) on rubydoc.info.
|
112
|
+
|
113
|
+
## Requirements
|
114
|
+
|
115
|
+
Rails 3, ActiveRecord, Ruby >= 1.8.7
|
116
|
+
|
117
|
+
## Contributing
|
118
|
+
|
119
|
+
1. Fork it
|
120
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
121
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
122
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
123
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rails/generators/migration'
|
2
|
+
|
3
|
+
module Roleable
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
include Rails::Generators::Migration
|
7
|
+
source_root File.expand_path('../templates', __FILE__)
|
8
|
+
|
9
|
+
desc 'Generates a role and a user_role model, along with migrations for their tables.'
|
10
|
+
def generate_install
|
11
|
+
copy_file 'role.rb', 'app/models/role.rb'
|
12
|
+
copy_file 'user_role.rb', 'app/models/user_role.rb'
|
13
|
+
migration_template 'migration.rb', 'db/migrate/roleable_create_roles_and_user_roles.rb'
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.next_migration_number(path)
|
17
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class RoleableCreateRolesAndUserRoles < ActiveRecord::Migration
|
2
|
+
|
3
|
+
def change
|
4
|
+
create_table :roles do |t|
|
5
|
+
t.string :name
|
6
|
+
t.timestamps
|
7
|
+
end
|
8
|
+
|
9
|
+
create_table :user_roles do |t|
|
10
|
+
t.references :user
|
11
|
+
t.references :role
|
12
|
+
t.references :resource, :polymorphic => true
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
|
16
|
+
add_index :user_roles, :user_id
|
17
|
+
add_index :user_roles, :role_id
|
18
|
+
add_index :user_roles, [:resource_type, :resource_id]
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/lib/roleable.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Roleable::Resource
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
base.has_many :user_roles, :as => :resource
|
5
|
+
end
|
6
|
+
|
7
|
+
# Return a list of users that have the given role for this resource.
|
8
|
+
#
|
9
|
+
# ==== Examples
|
10
|
+
#
|
11
|
+
# page.users_with_role(:editor) # => [user1, user2, ...]
|
12
|
+
#
|
13
|
+
def users_with_role(role_name)
|
14
|
+
user_roles = ::UserRole.with_role_name(role_name)
|
15
|
+
User.joins(:user_roles).merge(user_roles)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Roleable::Subject
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
base.has_many :user_roles
|
5
|
+
end
|
6
|
+
|
7
|
+
# Add a role to the user scoped to the given resource or global if no resource given.
|
8
|
+
#
|
9
|
+
# Does nothing if a role with the given name doesn't exist, or if the user already has
|
10
|
+
# the given role.
|
11
|
+
#
|
12
|
+
# ==== Examples
|
13
|
+
#
|
14
|
+
# user.add_role(:editor, page) # Add the editor role to user, scoped to page
|
15
|
+
# user.add_role(:admin) # Add the admin role to user, globally
|
16
|
+
#
|
17
|
+
def add_role(role_name, resource = nil)
|
18
|
+
role = ::Role.find_by_name(role_name) or return
|
19
|
+
|
20
|
+
::UserRole.create_if_unique!(:user => self, :role => role, :resource => resource)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Check if the user has the given role for the given resource, or if they have the role globally
|
24
|
+
# if no resource given.
|
25
|
+
#
|
26
|
+
# Returns <tt>true</tt> if the user has the role, <tt>false</tt> otherwise.
|
27
|
+
#
|
28
|
+
# ==== Examples
|
29
|
+
#
|
30
|
+
# user.has_role?(:editor, page) # True if the user has the editor role for page
|
31
|
+
# user.has_role?(:admin) # True if the user has a global admin role
|
32
|
+
#
|
33
|
+
def has_role?(role_name, resource = nil)
|
34
|
+
user_roles = ::UserRole.with_user(self).with_resource(resource).with_role_name(role_name)
|
35
|
+
|
36
|
+
user_roles.exists?
|
37
|
+
end
|
38
|
+
|
39
|
+
# Remove the given role from the user for the given resource, or globally if no resource given.
|
40
|
+
#
|
41
|
+
# Returns <tt>true</tt> if the role was found and deleted, <tt>false</tt> otherwise.
|
42
|
+
#
|
43
|
+
# ==== Examples
|
44
|
+
#
|
45
|
+
# user.remove_role(:editor, page) # Remove the editor role from the user for page
|
46
|
+
# user.remove_role(:admin) # Remove the global admin role from the user
|
47
|
+
#
|
48
|
+
def remove_role(role_name, resource = nil)
|
49
|
+
user_roles = ::UserRole.with_user(self).with_resource(resource).with_role_name(role_name)
|
50
|
+
|
51
|
+
deleted_count = user_roles.delete_all
|
52
|
+
|
53
|
+
deleted_count > 0
|
54
|
+
end
|
55
|
+
|
56
|
+
# Return a list of resources of the given class, for which the user has the given role.
|
57
|
+
#
|
58
|
+
# ==== Examples
|
59
|
+
#
|
60
|
+
# user.resources_with_role(:editor, Page) # => [page1, page2, ...]
|
61
|
+
#
|
62
|
+
def resources_with_role(role_name, resource_class)
|
63
|
+
user_roles = ::UserRole.with_user(self).with_role_name(role_name).with_resource_class(resource_class)
|
64
|
+
resource_class.includes(:user_roles).merge(user_roles)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Return a list of roles that the user has for the given resource.
|
68
|
+
#
|
69
|
+
# ==== Examples
|
70
|
+
#
|
71
|
+
# user.roles_for_resource(page) # => [role1, role2, ...]
|
72
|
+
#
|
73
|
+
def roles_for_resource(resource)
|
74
|
+
user_roles = ::UserRole.with_user(self).with_resource(resource)
|
75
|
+
::Role.includes(:user_roles).merge(user_roles)
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Roleable::UserRole
|
2
|
+
|
3
|
+
def self.extended(base)
|
4
|
+
base.belongs_to :user
|
5
|
+
base.belongs_to :role
|
6
|
+
base.belongs_to :resource, :polymorphic => true
|
7
|
+
|
8
|
+
base.attr_accessible :role, :user, :resource
|
9
|
+
end
|
10
|
+
|
11
|
+
def with_user(user)
|
12
|
+
where(:user_id => user && user.id)
|
13
|
+
end
|
14
|
+
|
15
|
+
def with_resource(resource)
|
16
|
+
where(:resource_id => resource && resource.id, :resource_type => resource && resource_type(resource))
|
17
|
+
end
|
18
|
+
|
19
|
+
def with_role_name(role_name)
|
20
|
+
role = ::Role.find_by_name(role_name)
|
21
|
+
with_role(role)
|
22
|
+
end
|
23
|
+
|
24
|
+
def with_role(role)
|
25
|
+
where(:role_id => role && role.id)
|
26
|
+
end
|
27
|
+
|
28
|
+
def with_resource_class(resource_class)
|
29
|
+
where(:resource_type => resource_type_from_class(resource_class))
|
30
|
+
end
|
31
|
+
|
32
|
+
# Create a record with the given attributes if there are no records
|
33
|
+
# that already have those attributes.
|
34
|
+
#
|
35
|
+
# Returns the record if it was saved, otherwise nil.
|
36
|
+
def create_if_unique!(attributes)
|
37
|
+
user_role = new(attributes)
|
38
|
+
|
39
|
+
record_attributes = user_role.attributes.reject do |k, v|
|
40
|
+
%w(id updated_at created_at).include?(k)
|
41
|
+
end
|
42
|
+
|
43
|
+
if !exists?(record_attributes) && user_role.save
|
44
|
+
user_role
|
45
|
+
else
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def resource_type(resource)
|
53
|
+
resource_type_from_class(resource.class)
|
54
|
+
end
|
55
|
+
|
56
|
+
def resource_type_from_class(resource_class)
|
57
|
+
resource_class.name
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
data/roleable.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/roleable/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Mitch Crowe"]
|
6
|
+
gem.email = ["crowe.mitch@gmail.com"]
|
7
|
+
gem.description = %q{Roles solution for active-record-backed Rails 3 applications}
|
8
|
+
gem.summary = %q{Roles solution for active-record-backed Rails 3 applications}
|
9
|
+
gem.homepage = "https://github.com/mcrowe/roleable"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "roleable"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Roleable::VERSION
|
17
|
+
|
18
|
+
gem.add_development_dependency 'rake', '~> 0.9'
|
19
|
+
gem.add_development_dependency 'rspec', '~> 2.8'
|
20
|
+
gem.add_development_dependency 'sqlite3', '~> 1.3'
|
21
|
+
gem.add_development_dependency 'activerecord', '~> 3.0'
|
22
|
+
gem.add_development_dependency 'with_model', '~> 0.2'
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Roleable::Resource do
|
4
|
+
|
5
|
+
include_context 'with models'
|
6
|
+
|
7
|
+
describe '#users_with_role' do
|
8
|
+
|
9
|
+
before do
|
10
|
+
@page = Page.create
|
11
|
+
@editor_role = Role.create(:name => 'editor')
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'with a role that doesnt exist' do
|
15
|
+
it 'returns an empty list' do
|
16
|
+
@page.users_with_role(:notarole).should be_empty
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when multiple users have the given role' do
|
21
|
+
it 'returns a list of the users' do
|
22
|
+
3.times do
|
23
|
+
user = User.create
|
24
|
+
user.add_role(:editor, @page)
|
25
|
+
end
|
26
|
+
|
27
|
+
users = @page.users_with_role(:editor)
|
28
|
+
|
29
|
+
users.length.should == 3
|
30
|
+
users.first.should be_a(User)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Roleable::Subject do
|
4
|
+
|
5
|
+
include_context 'with models'
|
6
|
+
|
7
|
+
before do
|
8
|
+
@user = User.create
|
9
|
+
@admin_role = Role.create(:name => 'admin')
|
10
|
+
@editor_role = Role.create(:name => 'editor')
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#add_role' do
|
14
|
+
|
15
|
+
context 'with a role that doesnt exist' do
|
16
|
+
|
17
|
+
before do
|
18
|
+
@result = @user.add_role(:notarole)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'returns false' do
|
22
|
+
@result.should be_false
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'doesnt create a new user_role' do
|
26
|
+
UserRole.count.should == 0
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'without a resource' do
|
32
|
+
|
33
|
+
before do
|
34
|
+
@user_role = @user.add_role(:admin)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'creates a new user role' do
|
38
|
+
UserRole.count.should == 1
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'associates the user role with the given user' do
|
42
|
+
@user_role.user.should == @user
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'associates the user role with the given role' do
|
46
|
+
@user_role.role.should == @admin_role
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'sets the resource to nil' do
|
50
|
+
@user_role.resource.should == nil
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'with a resource' do
|
56
|
+
|
57
|
+
before do
|
58
|
+
@page = Page.create
|
59
|
+
@user_role = @user.add_role(:admin, @page)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'associates the user role with the given resource' do
|
63
|
+
@user_role.resource.should == @page
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'when the user already has the given role for the resource' do
|
67
|
+
it 'doesnt create another user role' do
|
68
|
+
expect { @user.add_role(:admin, @page) }.to_not change(UserRole, :count)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
describe '#has_role?' do
|
77
|
+
|
78
|
+
context 'when the given role doesnt exist' do
|
79
|
+
it 'is false' do
|
80
|
+
@user.has_role?(:notarole).should be_false
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'without a resource' do
|
85
|
+
|
86
|
+
context 'when the user DOESNT have the given role' do
|
87
|
+
it 'is false' do
|
88
|
+
@user.has_role?(:admin).should be_false
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'when the user DOES have the given role' do
|
93
|
+
it 'is true' do
|
94
|
+
@user.add_role(:admin)
|
95
|
+
@user.has_role?(:admin).should be_true
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'with a resource' do
|
102
|
+
|
103
|
+
before do
|
104
|
+
@page = Page.create
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'when the user DOESNT have the role for that resource' do
|
108
|
+
it 'is false' do
|
109
|
+
@user.has_role?(:editor, @page).should be_false
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'when the user DOES have the role for that resource' do
|
114
|
+
it 'is true' do
|
115
|
+
@user.add_role(:editor, @page)
|
116
|
+
@user.has_role?(:editor, @page).should be_true
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
describe '#remove_role' do
|
125
|
+
|
126
|
+
context 'global' do
|
127
|
+
|
128
|
+
context 'when the user doesnt have the role' do
|
129
|
+
it 'is false' do
|
130
|
+
@user.remove_role(:admin).should be_false
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context 'when the role doesnt exist' do
|
135
|
+
it 'is false' do
|
136
|
+
@user.remove_role(:notarole).should be_false
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'when the user has the given role' do
|
141
|
+
|
142
|
+
before do
|
143
|
+
@user.add_role(:admin)
|
144
|
+
@result = @user.remove_role(:admin)
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'is true' do
|
148
|
+
@result.should be_true
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'removes the given role' do
|
152
|
+
@user.has_role?(:admin).should be_false
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
describe '#resources_with_role' do
|
162
|
+
|
163
|
+
context 'when the user has the given role for several resources of the given class' do
|
164
|
+
it 'returns a list containing those resources' do
|
165
|
+
3.times do
|
166
|
+
page = Page.create
|
167
|
+
@user.add_role(:editor, page)
|
168
|
+
end
|
169
|
+
|
170
|
+
pages = @user.resources_with_role(:editor, Page)
|
171
|
+
|
172
|
+
pages.length.should == 3
|
173
|
+
pages.first.should be_a(Page)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
context 'when the user doesnt have the given role for any resources of the given class' do
|
178
|
+
it 'returns an empty list' do
|
179
|
+
@user.resources_with_role(:editor, Page).should be_empty
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
describe '#roles_for_resource' do
|
186
|
+
it 'returns a list of role objects for the roles this user has for the given resource' do
|
187
|
+
page = Page.create
|
188
|
+
@user.add_role(:editor, page)
|
189
|
+
@user.add_role(:admin, page)
|
190
|
+
|
191
|
+
roles = @user.roles_for_resource(page)
|
192
|
+
roles.length.should == 2
|
193
|
+
roles.first.should be_a(Role)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
|
4
|
+
require 'sqlite3'
|
5
|
+
require 'active_record'
|
6
|
+
require 'with_model'
|
7
|
+
require 'roleable'
|
8
|
+
|
9
|
+
Dir['spec/support/**/*.rb'].each { |f| require File.expand_path("../../#{f}", __FILE__) }
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.extend WithModel
|
13
|
+
|
14
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
15
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
shared_context 'with models' do
|
2
|
+
|
3
|
+
with_model :User do
|
4
|
+
model { include Roleable::Subject }
|
5
|
+
end
|
6
|
+
|
7
|
+
with_model :Page do
|
8
|
+
model { include Roleable::Resource }
|
9
|
+
end
|
10
|
+
|
11
|
+
with_model :Role do
|
12
|
+
table { |t| t.string :name }
|
13
|
+
model { extend Roleable::Role }
|
14
|
+
end
|
15
|
+
|
16
|
+
with_model :UserRole do
|
17
|
+
table do |t|
|
18
|
+
t.integer :user_id
|
19
|
+
t.integer :role_id
|
20
|
+
t.integer :resource_id
|
21
|
+
t.string :resource_type
|
22
|
+
|
23
|
+
t.timestamps
|
24
|
+
end
|
25
|
+
model { extend Roleable::UserRole }
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: roleable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mitch Crowe
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-14 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: &2156383080 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0.9'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2156383080
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
requirement: &2156382260 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.8'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2156382260
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: sqlite3
|
38
|
+
requirement: &2156381480 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '1.3'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2156381480
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: activerecord
|
49
|
+
requirement: &2156380900 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2156380900
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: with_model
|
60
|
+
requirement: &2156380280 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0.2'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *2156380280
|
69
|
+
description: Roles solution for active-record-backed Rails 3 applications
|
70
|
+
email:
|
71
|
+
- crowe.mitch@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- .gitignore
|
77
|
+
- .rspec
|
78
|
+
- .travis.yml
|
79
|
+
- CHANGELOG
|
80
|
+
- Gemfile
|
81
|
+
- LICENSE
|
82
|
+
- README.md
|
83
|
+
- Rakefile
|
84
|
+
- lib/generators/roleable/install/USAGE
|
85
|
+
- lib/generators/roleable/install/install_generator.rb
|
86
|
+
- lib/generators/roleable/install/templates/migration.rb
|
87
|
+
- lib/generators/roleable/install/templates/role.rb
|
88
|
+
- lib/generators/roleable/install/templates/user_role.rb
|
89
|
+
- lib/roleable.rb
|
90
|
+
- lib/roleable/resource.rb
|
91
|
+
- lib/roleable/role.rb
|
92
|
+
- lib/roleable/subject.rb
|
93
|
+
- lib/roleable/user_role.rb
|
94
|
+
- lib/roleable/version.rb
|
95
|
+
- roleable.gemspec
|
96
|
+
- spec/roleable/resource_spec.rb
|
97
|
+
- spec/roleable/subject_spec.rb
|
98
|
+
- spec/spec_helper.rb
|
99
|
+
- spec/support/shared_contexts.rb
|
100
|
+
homepage: https://github.com/mcrowe/roleable
|
101
|
+
licenses: []
|
102
|
+
post_install_message:
|
103
|
+
rdoc_options: []
|
104
|
+
require_paths:
|
105
|
+
- lib
|
106
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ! '>='
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
segments:
|
113
|
+
- 0
|
114
|
+
hash: 1300429085112405941
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
117
|
+
requirements:
|
118
|
+
- - ! '>='
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
121
|
+
segments:
|
122
|
+
- 0
|
123
|
+
hash: 1300429085112405941
|
124
|
+
requirements: []
|
125
|
+
rubyforge_project:
|
126
|
+
rubygems_version: 1.8.10
|
127
|
+
signing_key:
|
128
|
+
specification_version: 3
|
129
|
+
summary: Roles solution for active-record-backed Rails 3 applications
|
130
|
+
test_files:
|
131
|
+
- spec/roleable/resource_spec.rb
|
132
|
+
- spec/roleable/subject_spec.rb
|
133
|
+
- spec/spec_helper.rb
|
134
|
+
- spec/support/shared_contexts.rb
|