rarbac 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: