roleable 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://secure.travis-ci.org/mcrowe/roleable.png?branch=master)](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
|