portier 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE +7 -0
- data/README.md +171 -0
- data/Rakefile +11 -0
- data/lib/portier/.reek +12 -0
- data/lib/portier/application_permission.rb +89 -0
- data/lib/portier/base.rb +75 -0
- data/lib/portier/base_permission.rb +36 -0
- data/lib/portier/engine.rb +7 -0
- data/lib/portier/errors.rb +19 -0
- data/lib/portier/implants/action_controller_implant.rb +37 -0
- data/lib/portier/railtie.rb +14 -0
- data/lib/portier/view_tags_permission.rb +14 -0
- data/lib/portier.rb +12 -0
- data/portier.gemspec +22 -0
- data/spec/controllers/application_controller_spec.rb +81 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/controllers/examples_controller.rb +11 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/anonymou.rb +19 -0
- data/spec/dummy/app/permissions/anonymous_permission.rb +25 -0
- data/spec/dummy/app/permissions/products_permission.rb +9 -0
- data/spec/dummy/app/permissions/view_tags_permission.rb +5 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config/application.rb +18 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +5 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +29 -0
- data/spec/dummy/config/environments/production.rb +80 -0
- data/spec/dummy/config/environments/test.rb +36 -0
- data/spec/dummy/config/initializers/standard_rails_initializers.rb +9 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/portier/application_permission_spec.rb +23 -0
- data/spec/portier/base_permission_spec.rb +4 -0
- data/spec/portier/base_spec.rb +28 -0
- data/spec/portier/view_tags_permission_spec.rb +31 -0
- data/spec/portier_spec.rb +4 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/views_helper.rb +12 -0
- metadata +197 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c33d0423d1f9c49d68a3334e45a97174fcb13ab6
|
4
|
+
data.tar.gz: 5e359491e90f1d8cf608f5fd1caf589744f52ddc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c1b7cb91f5b65f7fc17b2f1c68070cf865a4a58aae84c4080418bc484922146f8b03802f4b17a6083fa6a11f26a23d15b5e82f4d8122856fa8d068b4c1ea289c
|
7
|
+
data.tar.gz: 785f54d140c86965f58e90fd417cd5b56ea34f033f488f210d84733de1a79b17b049a02b8de7173e87f9fd6a5b28a03a2b07a5468149666bed0a695437e85c9e
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (c) 2014 Alchimik
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
Portier
|
2
|
+
=======
|
3
|
+
|
4
|
+
Portier is an gem that manage permissions in a rails project. The permission rules are flexible, non-obstrusive, scalable and can be applied to the controller actions, and views.
|
5
|
+
|
6
|
+
Install
|
7
|
+
-------
|
8
|
+
|
9
|
+
In your Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'portier'
|
13
|
+
```
|
14
|
+
|
15
|
+
Authorizing the controller requests
|
16
|
+
-----------------------------------
|
17
|
+
|
18
|
+
### Bootstrap Portier
|
19
|
+
|
20
|
+
In order to let portier control the requests to your application, you need to add the before_filter below in your application_controller.rb. You also need to define a current_user method
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
# app/controllers/application_controller.rb
|
24
|
+
|
25
|
+
class ApplicationController < ActionController::Base
|
26
|
+
protect_from_forgery with: :exception
|
27
|
+
|
28
|
+
# This filter the requests using the permission files
|
29
|
+
before_filter :protect_app
|
30
|
+
|
31
|
+
# You can define the current_user anyway you want as long as it return the current user record.
|
32
|
+
def current_user
|
33
|
+
# This is only an example of current_user method. Feel free to do it the way you want.
|
34
|
+
begin
|
35
|
+
@current_user ||= User.find session[:current_user]
|
36
|
+
rescue
|
37
|
+
@current_user = nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
...
|
41
|
+
```
|
42
|
+
|
43
|
+
### The Permission Files
|
44
|
+
|
45
|
+
Once this is done, every controller will have to be match with a permission file. So, for the ```products_controller.rb``` you'll have to create the file ```app/permissions/products_permission.rb```.
|
46
|
+
|
47
|
+
|
48
|
+
### Describing a permission file
|
49
|
+
|
50
|
+
The permission file will define the access rules to every action called on the controller.
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
# app/permissions/products_permission.rb
|
54
|
+
|
55
|
+
class ProductsPermission < Portier::ApplicationPermission
|
56
|
+
# User will have access to any undescribed actions
|
57
|
+
def default
|
58
|
+
true
|
59
|
+
end
|
60
|
+
|
61
|
+
# The access will only granted if the product is available.
|
62
|
+
# product is provided by ApplicationPermission.
|
63
|
+
# product return the current product record
|
64
|
+
def show
|
65
|
+
product.available?
|
66
|
+
end
|
67
|
+
|
68
|
+
# You can set a custom error message with the method set_access_denied_message.
|
69
|
+
# This message will be available in the controllers and views throught the
|
70
|
+
# method access_denied_message. If it's not set, this method will return nil.
|
71
|
+
# set_access_denied_message always return false.
|
72
|
+
def create
|
73
|
+
if not current_user
|
74
|
+
set_access_denied_message "You need to log in to create this product."
|
75
|
+
elsif not current_user.can_create_product?
|
76
|
+
set_access_denied_message "You don't have the right to create product."
|
77
|
+
else
|
78
|
+
true
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# The access to the edit/update actions will only be available
|
83
|
+
# if the current user is and Administrator
|
84
|
+
# The current_user method must be defined in your ApplicationController
|
85
|
+
def modify
|
86
|
+
current_user and current_user.admin?
|
87
|
+
end
|
88
|
+
|
89
|
+
# Revoke access to the destroy action.
|
90
|
+
def destroy
|
91
|
+
false
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# consult = index and show
|
96
|
+
# add = new and create
|
97
|
+
# modify = edit and update
|
98
|
+
|
99
|
+
# Define the parameters that can be sent by the user.
|
100
|
+
# In your products_controller, you can call the method permitted_params.
|
101
|
+
# This method will be the equivalent of :
|
102
|
+
# params.require(:product).permit(:picture, :name, :description)
|
103
|
+
def permitted_params
|
104
|
+
if current_user and current_user.employe?
|
105
|
+
[:picture, :name, :description]
|
106
|
+
elsif current_user and current_user.admin?
|
107
|
+
[:picture, :name, :description, :price]
|
108
|
+
else
|
109
|
+
[]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
```
|
113
|
+
|
114
|
+
### The View Tags
|
115
|
+
|
116
|
+
In order to filter content in the views, you can add tags in the special view_tags_permission.rb.
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
# app/permissions/view_tags_permission.rb
|
120
|
+
|
121
|
+
class ViewTagsPermission < Portier::ViewTagsPermission
|
122
|
+
# Only accept this tag if the user is an administrator
|
123
|
+
def show_the_admin_link
|
124
|
+
current_user.admin?
|
125
|
+
end
|
126
|
+
end
|
127
|
+
```
|
128
|
+
|
129
|
+
In your views, you can then use the can_view? method to filter content.
|
130
|
+
|
131
|
+
```erb
|
132
|
+
<%# app/views/products/show.html.erb %>
|
133
|
+
|
134
|
+
<%= link_to 'Admin', admin_path if can_view? :show_the_admin_link %>
|
135
|
+
```
|
136
|
+
|
137
|
+
### can?
|
138
|
+
|
139
|
+
In your views, you can also use the method ```can?``` to filter content.
|
140
|
+
|
141
|
+
```erb
|
142
|
+
<%# app/views/products/show.html.erb %>
|
143
|
+
|
144
|
+
<%= link_to 'Edit product', edit_product_path(id: @product.id) if can? :edit, @product %>
|
145
|
+
```
|
146
|
+
|
147
|
+
Both ```can?``` and ```can_view?``` methods can take options
|
148
|
+
|
149
|
+
```erb
|
150
|
+
<%# app/views/products/show.html.erb %>
|
151
|
+
|
152
|
+
<%= link_to 'Admin', admin_path if can_view? :show_the_admin_link, special: true %>
|
153
|
+
```
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
# app/permissions/view_tags_permission.rb
|
157
|
+
|
158
|
+
class ViewTagsPermission < Portier::ViewTagsPermission
|
159
|
+
# Only accept this tag if the user is a special administrator
|
160
|
+
def show_the_admin_link
|
161
|
+
current_user.admin? and options[:special]
|
162
|
+
end
|
163
|
+
end
|
164
|
+
```
|
165
|
+
|
166
|
+
|
167
|
+
|
168
|
+
Copyright
|
169
|
+
---------
|
170
|
+
|
171
|
+
Copyright (c) 2014 Alchimik. See LICENSE for further details.
|
data/Rakefile
ADDED
data/lib/portier/.reek
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
---
|
2
|
+
DuplicateMethodCall:
|
3
|
+
allow_calls: ['options', 'params']
|
4
|
+
max_calls: 3
|
5
|
+
IrresponsibleModule:
|
6
|
+
enabled: false
|
7
|
+
TooManyStatements:
|
8
|
+
max_statements: 10
|
9
|
+
UncommunicativeMethodName:
|
10
|
+
enabled: false
|
11
|
+
UncommunicativeVariableName:
|
12
|
+
enabled: false
|
@@ -0,0 +1,89 @@
|
|
1
|
+
#*************************************************************************************
|
2
|
+
# Control the access for each controller actions
|
3
|
+
#*************************************************************************************
|
4
|
+
class Portier::ApplicationPermission < Portier::BasePermission
|
5
|
+
def self.action_tree(action)
|
6
|
+
case action.to_s
|
7
|
+
when 'index' then [:index, :consult, :default]
|
8
|
+
when 'show' then [:show, :consult, :default]
|
9
|
+
when 'new' then [:new, :add, :default]
|
10
|
+
when 'create' then [:create, :add, :default]
|
11
|
+
when 'edit' then [:edit, :modify, :default]
|
12
|
+
when 'update' then [:update, :modify, :default]
|
13
|
+
when 'destroy' then [:destroy, :default]
|
14
|
+
else [action.to_sym, :default]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
def build_permitted_params
|
20
|
+
ps = self.respond_to?(:permitted_params) ? permitted_params : []
|
21
|
+
|
22
|
+
begin
|
23
|
+
params.require(record_name).permit ps
|
24
|
+
rescue
|
25
|
+
{}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def can?(action, record, options={})
|
30
|
+
@current_record = record
|
31
|
+
@options = options
|
32
|
+
|
33
|
+
granted? action
|
34
|
+
end
|
35
|
+
|
36
|
+
def default
|
37
|
+
false
|
38
|
+
end
|
39
|
+
|
40
|
+
def granted?(action)
|
41
|
+
action_tree(action).each { |act| return self.send(act) if self.respond_to?(act) }
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def action_tree(action)
|
48
|
+
Portier::ApplicationPermission.action_tree(action)
|
49
|
+
end
|
50
|
+
|
51
|
+
def current_record
|
52
|
+
@current_record = find_record if not @current_record
|
53
|
+
|
54
|
+
@current_record
|
55
|
+
end
|
56
|
+
|
57
|
+
def find_record
|
58
|
+
if params[:id]
|
59
|
+
field = model.respond_to?(:default_id) ? model.default_id : :id
|
60
|
+
|
61
|
+
model.find_by Hash[field, params[:id]]
|
62
|
+
else
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def model
|
68
|
+
controller_name.singularize.camelize.constantize
|
69
|
+
end
|
70
|
+
|
71
|
+
def model_exists?
|
72
|
+
defined? model
|
73
|
+
end
|
74
|
+
|
75
|
+
def record_name
|
76
|
+
controller_name.singularize.to_sym
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
def method_missing(*args, &block)
|
81
|
+
if args.first == record_name and model_exists?
|
82
|
+
current_record
|
83
|
+
elsif current_record.class.to_s.downcase == args.first.to_s
|
84
|
+
current_record
|
85
|
+
else
|
86
|
+
raise NoMethodError.new("undefined local variable or method '#{args.first}' for #{self.class}")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/lib/portier/base.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
#*************************************************************************************
|
2
|
+
# Check if the access is granted or refused depending on the permission
|
3
|
+
# setted in the permission files.
|
4
|
+
#*************************************************************************************
|
5
|
+
class Portier::Base
|
6
|
+
attr_reader :application_controller, :current_user
|
7
|
+
|
8
|
+
delegate :request, to: :application_controller
|
9
|
+
|
10
|
+
def initialize(application_controller, current_user)
|
11
|
+
@application_controller = application_controller
|
12
|
+
@current_user = current_user
|
13
|
+
end
|
14
|
+
|
15
|
+
def access_denied_message
|
16
|
+
base_permission.access_denied_message
|
17
|
+
end
|
18
|
+
|
19
|
+
def authorize_action
|
20
|
+
raise Portier::AccessDenied if not base_permission.granted? action
|
21
|
+
end
|
22
|
+
|
23
|
+
def can?(action, object, options={})
|
24
|
+
object_name = if object.is_a? Symbol or object.is_a? String
|
25
|
+
object.to_s.singularize.pluralize
|
26
|
+
else
|
27
|
+
object.class.name.pluralize
|
28
|
+
end
|
29
|
+
permission = permission_for object_name
|
30
|
+
permission.can? action, object, options
|
31
|
+
end
|
32
|
+
|
33
|
+
def can_view?(tag, options={})
|
34
|
+
view_permission.can_view? tag, options
|
35
|
+
end
|
36
|
+
|
37
|
+
def permitted_params
|
38
|
+
base_permission.build_permitted_params if base_permission.respond_to? :permitted_params
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def action
|
44
|
+
request[:action]
|
45
|
+
end
|
46
|
+
|
47
|
+
def base_permission
|
48
|
+
@base_permission ||= permission_for controller_name
|
49
|
+
end
|
50
|
+
|
51
|
+
def controller_name
|
52
|
+
request[:controller]
|
53
|
+
end
|
54
|
+
|
55
|
+
def permission_for(target)
|
56
|
+
begin
|
57
|
+
"#{target.camelize}Permission".constantize.new(application_controller, current_user)
|
58
|
+
rescue
|
59
|
+
raise Portier::Uninitalized, "You must define #{controller_name.camelize}Permission in app/permissions/#{controller_name}_permission.rb. See documentation for more details."
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def view_permission
|
64
|
+
if not @view_permission_object
|
65
|
+
begin
|
66
|
+
@view_permission_object = "ViewTagsPermission".constantize.new(application_controller, current_user)
|
67
|
+
rescue
|
68
|
+
raise Portier::Uninitalized, "You must define ViewTagsPermission in app/permissions/view_tags_permission.rb in order to use view permission. See documentation for more details."
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
@view_permission_object
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#*************************************************************************************
|
2
|
+
# Basic Permission object to cut some duplication.
|
3
|
+
# ApplicationPermission and ViewTagsPermission inherit from it
|
4
|
+
#*************************************************************************************
|
5
|
+
class Portier::BasePermission
|
6
|
+
attr_reader :access_denied_message, :application_controller, :current_user
|
7
|
+
|
8
|
+
delegate :params, to: :application_controller
|
9
|
+
delegate :request, to: :application_controller
|
10
|
+
|
11
|
+
def initialize(application_controller, current_user)
|
12
|
+
@application_controller = application_controller
|
13
|
+
@current_user = current_user
|
14
|
+
@access_denied_message = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def set_access_denied_message(message)
|
18
|
+
@access_denied_message = message
|
19
|
+
|
20
|
+
false
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def controller
|
26
|
+
@application_controller
|
27
|
+
end
|
28
|
+
|
29
|
+
def controller_name
|
30
|
+
request[:controller]
|
31
|
+
end
|
32
|
+
|
33
|
+
def options
|
34
|
+
@options
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
module Portier
|
2
|
+
#*************************************************************************************
|
3
|
+
# Make the gem behave as an engine.
|
4
|
+
#*************************************************************************************
|
5
|
+
class Engine < Rails::Engine
|
6
|
+
end
|
7
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Portier
|
2
|
+
#*************************************************************************************
|
3
|
+
# Error that will be raised if access to the action is denied
|
4
|
+
#*************************************************************************************
|
5
|
+
class AccessDenied < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
#*************************************************************************************
|
9
|
+
# Error that will be raised if the permission wasn't defined
|
10
|
+
#*************************************************************************************
|
11
|
+
class NoPermissionError < StandardError
|
12
|
+
end
|
13
|
+
|
14
|
+
#*************************************************************************************
|
15
|
+
# Error that will be raised if the permission isn't initialized
|
16
|
+
#*************************************************************************************
|
17
|
+
class Uninitalized < StandardError
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#*************************************************************************************
|
2
|
+
# Insert methods in the Action Controller of a Rails project.
|
3
|
+
#*************************************************************************************
|
4
|
+
module Portier::Implants::ActionControllerImplant
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
helper_method :access_denied_message, :can?, :can_view?
|
9
|
+
|
10
|
+
rescue_from Portier::AccessDenied, with: :render_access_denied
|
11
|
+
end
|
12
|
+
|
13
|
+
def access_denied_message
|
14
|
+
@portier.access_denied_message
|
15
|
+
end
|
16
|
+
|
17
|
+
def can?(action, object, options={})
|
18
|
+
@portier.can? action, object, options
|
19
|
+
end
|
20
|
+
|
21
|
+
def can_view?(tag, options={})
|
22
|
+
@portier.can_view? tag, options
|
23
|
+
end
|
24
|
+
|
25
|
+
def permitted_params
|
26
|
+
@portier.permitted_params
|
27
|
+
end
|
28
|
+
|
29
|
+
def protect_app
|
30
|
+
@portier = Portier::Base.new(self, current_user)
|
31
|
+
@portier.authorize_action
|
32
|
+
end
|
33
|
+
|
34
|
+
def render_access_denied
|
35
|
+
render text: "access_denied", status: 401
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Portier
|
2
|
+
class Railtie < Rails::Railtie
|
3
|
+
initializer "portier" do |app|
|
4
|
+
ActiveSupport.on_load :action_controller do
|
5
|
+
include Portier::Implants::ActionControllerImplant
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module Implants
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'portier/implants/action_controller_implant'
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#*************************************************************************************
|
2
|
+
# Control the access using a tag.
|
3
|
+
#*************************************************************************************
|
4
|
+
class Portier::ViewTagsPermission < Portier::BasePermission
|
5
|
+
def can_view?(tag, options={})
|
6
|
+
if self.respond_to? tag.to_sym
|
7
|
+
@options = options
|
8
|
+
|
9
|
+
self.send(tag.to_sym)
|
10
|
+
else
|
11
|
+
raise Portier::NoPermissionError, "You must define the method \"#{tag}\" in the view tags file (app/permissions/view_tags_permission.rb). See documentation for more details."
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/portier.rb
ADDED
data/portier.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Gem::Specification.new do |gem|
|
2
|
+
gem.name = "portier"
|
3
|
+
gem.description = "Portier is an gem that manage permissions in a rails project. The permission rules are flexible, non-obstrusive, scalable and can be applied to the controller actions, and views."
|
4
|
+
gem.summary = "Portier is an gem that manage permissions in a rails project. The permission rules are flexible, non-obstrusive, scalable and can be applied to the controller actions, and views."
|
5
|
+
gem.homepage = "https://bitbucket.org/alchimikweb/portier"
|
6
|
+
gem.version = "1.0.3"
|
7
|
+
gem.licenses = ["MIT"]
|
8
|
+
|
9
|
+
gem.authors = ["Sebastien Rosa"]
|
10
|
+
gem.email = ["sebastien@alchimik.com"]
|
11
|
+
|
12
|
+
gem.files = `git ls-files`.split($\)
|
13
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
14
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
|
17
|
+
gem.add_dependency "rails", ['>= 4.0']
|
18
|
+
gem.add_development_dependency "sqlite3"
|
19
|
+
gem.add_development_dependency "rspec-rails"
|
20
|
+
gem.add_development_dependency "simplecov"
|
21
|
+
gem.add_development_dependency "simplecov-rcov-text"
|
22
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe ApplicationController do
|
4
|
+
controller do
|
5
|
+
before_filter :protect_app
|
6
|
+
|
7
|
+
def current_user
|
8
|
+
@user
|
9
|
+
end
|
10
|
+
|
11
|
+
def index
|
12
|
+
if can_view?(:granted_response, show: true)
|
13
|
+
render text: 'Granted!'
|
14
|
+
else
|
15
|
+
render text: 'Nothing'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def create
|
20
|
+
if can?(:create, :products)
|
21
|
+
render text: "Created! #{permitted_params}"
|
22
|
+
else
|
23
|
+
render text: "Not Created!"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def edit
|
28
|
+
render text: 'Refused!'
|
29
|
+
end
|
30
|
+
|
31
|
+
def destroy
|
32
|
+
render text: 'Destroyed!'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "when calling an open action" do
|
37
|
+
it 'should grant access' do
|
38
|
+
get :index
|
39
|
+
|
40
|
+
expect(response.status).to eq(200)
|
41
|
+
expect(response.body).to eq "Granted!"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "when calling a restricted action" do
|
46
|
+
it 'should not grant access' do
|
47
|
+
get :edit, id: '123'
|
48
|
+
|
49
|
+
expect(response.status).to eq(401)
|
50
|
+
expect(response.body).to eq "access_denied"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "when sending the role and the role is not allowed to be sent" do
|
55
|
+
it 'should not have role in the permitted_params' do
|
56
|
+
post :create, anonymou: { name: '123', email: 'a@at.com', role: 'admin' }
|
57
|
+
|
58
|
+
expect(response.status).to eq(200)
|
59
|
+
expect(response.body).to include('email')
|
60
|
+
expect(response.body).not_to include('role')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "when deleting an open record" do
|
65
|
+
it 'should grant access' do
|
66
|
+
delete :destroy, id: 'open'
|
67
|
+
|
68
|
+
expect(response.status).to eq(200)
|
69
|
+
expect(response.body).to eq "Destroyed!"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "when deleting an restricted record" do
|
74
|
+
it 'should not grant access' do
|
75
|
+
delete :destroy, id: 'restricted'
|
76
|
+
|
77
|
+
expect(response.status).to eq(401)
|
78
|
+
expect(response.body).to eq "access_denied"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/spec/dummy/Rakefile
ADDED