rarbac 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6b27af0301b8f3c532aa0109fff3bec28f527d3f
4
+ data.tar.gz: 859f26fabf0a378010d3ecc0f2674207deb3fb57
5
+ SHA512:
6
+ metadata.gz: e227b442d14f4f9a0941cae20ffc07cb8ec8761210cf121453744b68a33d87a095bc8e8f258b73c4948cf2b6b1a52aa4580ea4f4187299291556645dd8aedc34
7
+ data.tar.gz: df61f081255dfed12d44deb4678bfa8de5a0c618e823a561e11e7e5218048857ce256af6773f7c37f2f6f427e0889ceb6abaaaf5194332096f660d68a1a63bdd
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2014 Tyler Margison
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.md ADDED
@@ -0,0 +1,189 @@
1
+ rarbac
2
+ ======
3
+
4
+ ## What is rarbac?
5
+
6
+ `rarbac` stands for "Rails Role-Based Access Control". I couldn't find a good
7
+ gem that did RBAC and integrated with a Rails app, so I made one. Since this is
8
+ basically a stripped down Rails project, I created it as a Rails engine
9
+ (a.k.a. plugin).
10
+
11
+ However, there was a UC Berkley project which did well but fell a little short
12
+ and does not appear to be maintained any more, called
13
+ [rails_access](https://github.com/ucberkeley/rails_access). You will probably
14
+ see similarities in the data structure between that project and this
15
+ one.
16
+
17
+ ## Installation
18
+
19
+ You simply add the gem and then mount the engine.
20
+
21
+ In your Gemfile:
22
+
23
+ ```ruby
24
+ gem 'rarbac'
25
+ ```
26
+
27
+ In `config/routes.rb`:
28
+
29
+ ```ruby
30
+ mount Rarbac::Engine, at: "rarbac"
31
+ ```
32
+
33
+ The project includes migrations for non-user data. Your Rails app must have, and
34
+ supply, its own user model. To generate the migrations for `rarbac` simply run:
35
+
36
+ rake rarbac:install:migrations
37
+
38
+ Then run migrations. One more step to ensure everything works properly. Open
39
+ your user model and add the following to it:
40
+
41
+ ```ruby
42
+ has_many :user_roles, class_name: "Rarbac::UserRole"
43
+ has_many :roles, through: :user_roles, class_name: "Rarbac::Role"
44
+ has_many :permissions, through: :roles, class_name: "Rarbac::Permission"
45
+ has_many :actions, through: :permissions, class_name: "Rarbac::Action"
46
+
47
+ include Rarbac::UserHelper
48
+ ```
49
+
50
+ That may seem like a lot, but really we're just off-loading a lot of the
51
+ querying work to the underlying `ActiveRecord` base (or whatever else you are
52
+ using). If we didn't do this we would have to do things like:
53
+
54
+ ```ruby
55
+ user.user_roles.roles.permissions.where(...)
56
+ ```
57
+
58
+ By including all those `has_many X through: Y` statements, we can go straight to
59
+ what we want:
60
+
61
+ ```ruby
62
+ user.permissions.where(...)
63
+ ```
64
+
65
+ With migrations installed, run, and the user model setup, start your application
66
+ and enjoy! Read on to make the most out of `rarbac`.
67
+
68
+ ## How it works
69
+
70
+ You will have a few new models, under the namespace `Rarbac`, called `Role`,
71
+ `Action`, `Permission`, and `UserRole`.
72
+
73
+ The `Role` model/table holds a collections of roles, with an optional
74
+ description. e.g. "guest", "user", "admin".
75
+
76
+ The `Action` model/table holds a collection of actions that a user may perform
77
+ in the system. e.g. "new_post", "delete_post", "new_comment".
78
+
79
+ The `Permission` model/table links roles to actions. e.g. "the `admin` role has
80
+ permission to the `delete_post` action".
81
+
82
+ The `UserRole` model/table links users to roles. e.g. "Jill has the `user`
83
+ role".
84
+
85
+ It is important to note that user ids are not uniquely kept in the `UserRole`
86
+ model, so you may have a single user with more than one role.
87
+
88
+ ### Controller Filters
89
+
90
+ You may use the `Rarbac` controller filters/functions by including
91
+ `Rarbac::ApplicationHelper`. The only assumption made is the presence of a
92
+ resource (function or attribute) named `current_user`. This is modeled after the
93
+ popular authentication gem [Devise](https://github.com/plataformatec/devise).
94
+
95
+ You may add `before_filter :ensure_permission!` to create role-based authorization
96
+ on the controller and action being executed. For example:
97
+
98
+ ```ruby
99
+ class PostsController < Rarbac::ApplicationController
100
+ before_filter :ensure_permission!
101
+
102
+ def show
103
+ ...
104
+ end
105
+
106
+ def destroy
107
+ ...
108
+ end
109
+ end
110
+ ```
111
+
112
+ If you had an `Action` specified for "posts#destroy", this would ensure that
113
+ `current_user` had permission to that action. If no such action existed,
114
+ however, it is assumed that you don't need permission and anyone, even
115
+ un-authenticated users, would be allowed access to that route.
116
+
117
+ You may also customize your filters using the normal application controller
118
+ options:
119
+
120
+ ```ruby
121
+ before_filter :ensure_permission!, only: :destroy
122
+ ```
123
+
124
+ Now the filter only runs when the `destroy` action is being executed. You may
125
+ also use the block method of invoking a filter to further customize your
126
+ options:
127
+
128
+ ```ruby
129
+ before_filter only: :destroy do |controller|
130
+ controller.ensure_permission!(:delete_post)
131
+ end
132
+ ```
133
+
134
+ But wait, there's more! What if you want to check a role rather than an
135
+ individual permission to some action? Maybe an entire controller should be
136
+ off-limits to everyone but those with the `admin` role. That's easy:
137
+
138
+ ```ruby
139
+ before_filter do |controller|
140
+ controller.ensure_role!(:admin)
141
+ end
142
+ ```
143
+
144
+ Bonus: it accepts arrays of roles.
145
+
146
+ ```ruby
147
+ before_filter do |controller|
148
+ controller.ensure_role!(:author, :admin)
149
+ # The above uses an "OR" operation; use the plural to perform "AND"
150
+ # e.g. controller.ensure_roles!(:author, :admin)
151
+ end
152
+ ```
153
+
154
+ Don't forget that you may create your own filter functions and call `ensure_*`
155
+ from there. However, if you create a custom filter and have access to
156
+ `current_user`, it might be better, and more configurable, to use the model
157
+ functions defined in the next section.
158
+
159
+ ### Model Functions
160
+
161
+ With the appropriate permissions added to your user model you may very easily
162
+ check on a user's roles:
163
+
164
+ ```ruby
165
+ user.has_role?(:admin)
166
+ user.has_role?(:admin, :author) # Singular noun implies "OR" operation
167
+ # e.g. has_role?(:admin) || has_role?(:author)
168
+ user.has_roles?(:admin, :author) # Plural noun implies "AND" operation
169
+ # e.g. has_role?(:admin) && has_role?(:author)
170
+ ```
171
+
172
+ And also permissions:
173
+
174
+ ```ruby
175
+ user.has_permission?(:delete_post)
176
+ ```
177
+
178
+ It's important to note that permissions don't accept arrays. Why? Because very
179
+ rarely should you be checking for a collection of permissions in a single
180
+ "question". If you want to know if a user has permission to multiple actions,
181
+ more likely you actually want to know if the user is assigned to one or more
182
+ roles instead. That's why the `has_role?` and `has_roles?` functions have the
183
+ argument-array option.
184
+
185
+ ### View Helpers
186
+
187
+ There is no explicit view helper system. The idea is that the controller filters
188
+ will help control when a view is rendered, and the model functions can further
189
+ control what is rendered within a template.
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Rarbac'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+ Bundler::GemHelper.install_tasks
21
+
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any styles
10
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
+ * file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,4 @@
1
+ module Rarbac
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,55 @@
1
+ module Rarbac
2
+ # Defines application helpers, useful in controllers to add RBAC filters.
3
+ module ApplicationHelper
4
+ # Ensure that `current_user` has at least one of the given roles. If no
5
+ # block is given, a failed check will render a header-only response with
6
+ # status code 403 (Forbidden).
7
+ #
8
+ # @param [Array<String>] args an argument list of roles.
9
+ # @param [Proc] block if given, invoked with a single parameter, which is
10
+ # the result of the role check.
11
+ def ensure_role!(*args, &block)
12
+ has_something?(:has_role?, args, block)
13
+ end
14
+
15
+ # Ensure that `current_user` has all of the given roles. If no block is
16
+ # given, a failed check will render a header-only response with status code
17
+ # 403 (Forbidden).
18
+ #
19
+ # @param [Array<String>] args an argument list of roles.
20
+ # @param [Proc] block if given, invoked with a single parameter, which is
21
+ # the result of the role check.
22
+ def ensure_roles!(*args, &block)
23
+ has_something?(:has_roles?, args, block)
24
+ end
25
+
26
+ # Ensure that `current_user` has permission to a given action. If no action
27
+ # name is supplied, this will instead use the currently-executing controller
28
+ # and action names. If no block is given, a failed check will render a
29
+ # header-only response with status code 403 (Forbidden).
30
+ #
31
+ # @param [String] action name of the action to check permissions for.
32
+ # @param [Proc] block if given, invoked with a single parameter, which is
33
+ # the result of the role check.
34
+ def ensure_permission!(action=nil, &block)
35
+ unless action
36
+ # TODO: If not supplied an action, determine the controller name and
37
+ # action being invoked, and use that to generate an appropriate action
38
+ # name to check.
39
+ end
40
+
41
+ has_something?(:has_permission?, action, block)
42
+ end
43
+
44
+ private
45
+
46
+ def has_something?(method, args, &block)
47
+ success = current_user.send(method, args)
48
+ if block
49
+ block.call(success)
50
+ elsif !success
51
+ head status: 403
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,38 @@
1
+ module Rarbac
2
+ # A collection of useful functions to be used by the user model.
3
+ #
4
+ # include Rarbac::UserHelper
5
+ #
6
+ # That's it! Now you have access to some awesome RBAC helper functions.
7
+ module UserHelper
8
+ # Determines if the user has one or more of the given roles linked to it.
9
+ #
10
+ # @param [String] args an argument list of one or more roles to check for.
11
+ # @return [true|false] true if the user is linked to at least one of the
12
+ # given roles.
13
+ def has_role?(*args)
14
+ throw Exception.new("Must supply at least one role.") if args.empty?
15
+ roles.where(name: args).count > 0
16
+ end
17
+
18
+ # Determines if the user has all of the given roles linked to it.
19
+ #
20
+ # @param [String] args an argument list of one or more roles to check for.
21
+ # @return [true|false] true if the user is linked to all of the given roles.
22
+ def has_roles?(*args)
23
+ throw Exception.new("Must supply at least one role.") if args.empty?
24
+ roles.where(name: args).count == args.count
25
+ end
26
+
27
+ # Determines if the user has permission to a given action. If the action
28
+ # does not exist at all, it is assumed the action is publicly available.
29
+ #
30
+ # @param [String] action name of the action to check permission for.
31
+ # @return [true|false] true if the user has at least one role linked to it
32
+ # with permission to the given action.
33
+ def has_permission?(action)
34
+ return true if Action.where(name: action).count == 0
35
+ actions.where(name: action).count > 0
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,7 @@
1
+ module Rarbac
2
+ # Represents an action. Actions are linked to roles by way of the Permission
3
+ # model.
4
+ class Action < ActiveRecord::Base
5
+ has_many :permissions
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Rarbac
2
+ # Permissions link actions to roles.
3
+ class Permission < ActiveRecord::Base
4
+ belongs_to :role
5
+ belongs_to :action
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Rarbac
2
+ # Represents a role. Roles are linked to actions by way of the Permission
3
+ # model.
4
+ class Role < ActiveRecord::Base
5
+ has_many :permissions
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Rarbac
2
+ # Links users to roles.
3
+ class UserRole < ActiveRecord::Base
4
+ belongs_to :user
5
+ belongs_to :role
6
+ end
7
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Rarbac</title>
5
+ <%= stylesheet_link_tag "rarbac/application", media: "all" %>
6
+ <%= javascript_include_tag "rarbac/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ Rarbac::Engine.routes.draw do
2
+ end
@@ -0,0 +1,10 @@
1
+ class CreateRarbacRoles < ActiveRecord::Migration
2
+ def change
3
+ create_table :rarbac_roles do |t|
4
+ t.string :name
5
+ t.string :description
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ class CreateRarbacActions < ActiveRecord::Migration
2
+ def change
3
+ create_table :rarbac_actions do |t|
4
+ t.string :name
5
+ t.string :description
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ class CreateRarbacPermissions < ActiveRecord::Migration
2
+ def change
3
+ create_table :rarbac_permissions do |t|
4
+ t.integer :role_id
5
+ t.integer :action_id
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :rarbac_permissions, :role_id
11
+ add_index :rarbac_permissions, :action_id
12
+ add_index :rarbac_permissions, [:role_id, :action_id], unique: true
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ class CreateRarbacUserRoles < ActiveRecord::Migration
2
+ def change
3
+ create_table :rarbac_user_roles do |t|
4
+ t.integer :user_id
5
+ t.integer :role_id
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :rarbac_user_roles, :user_id
11
+ add_index :rarbac_user_roles, :role_id
12
+ add_index :rarbac_user_roles, [:user_id, :role_id], unique: true
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ module Rarbac
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Rarbac
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module Rarbac
2
+ VERSION = "0.0.1"
3
+ end
data/lib/rarbac.rb ADDED
@@ -0,0 +1,4 @@
1
+ require "rarbac/engine"
2
+
3
+ module Rarbac
4
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :rarbac do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rarbac
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tyler Margison
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sqlite3
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: An implementation of RBAC as a Rails engine/plugin.
42
+ email: kolorahl@gmail.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - LICENSE
48
+ - README.md
49
+ - Rakefile
50
+ - app/assets/stylesheets/rarbac/application.css
51
+ - app/controllers/rarbac/application_controller.rb
52
+ - app/helpers/rarbac/application_helper.rb
53
+ - app/helpers/rarbac/user_helper.rb
54
+ - app/models/rarbac/action.rb
55
+ - app/models/rarbac/permission.rb
56
+ - app/models/rarbac/role.rb
57
+ - app/models/rarbac/user_role.rb
58
+ - app/views/layouts/rarbac/application.html.erb
59
+ - config/routes.rb
60
+ - db/migrate/20140711030732_create_rarbac_roles.rb
61
+ - db/migrate/20140711030959_create_rarbac_actions.rb
62
+ - db/migrate/20140711031154_create_rarbac_permissions.rb
63
+ - db/migrate/20140711031434_create_rarbac_user_roles.rb
64
+ - lib/rarbac.rb
65
+ - lib/rarbac/engine.rb
66
+ - lib/rarbac/version.rb
67
+ - lib/tasks/rarbac_tasks.rake
68
+ homepage: https://github.com/kolorahl/rarbac
69
+ licenses:
70
+ - MIT
71
+ metadata: {}
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 2.3.0
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: RBAC for Rails
92
+ test_files: []
93
+ has_rdoc: