guachiman 0.3.2 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4916879c98565075de3207f59c7523e2b17cbb94
4
- data.tar.gz: f4ac1da14be00cdcfc68d3fc9bfa670f00be2db7
3
+ metadata.gz: 97d7c5faf252acffc4cd784ae04bd48dc95bbfcc
4
+ data.tar.gz: 1e87686d64536b2672e1554bb67e32007e8c2494
5
5
  SHA512:
6
- metadata.gz: ccc80328ac823ebcd3ec11e4128d3fad117815e99adda13727ec4b2fa22488696e3562bb5030b92826e2dab9ad3b00de4c1d5cfbade31942822e0e90dadddf04
7
- data.tar.gz: db6437b784d2074dda9748dc0311df09e9e192ac84a5a87d59593febbb5362a6ee1b33428e3fbd225ac2b5ad599e57639aa7ca574820cc022358babf6a293b13
6
+ metadata.gz: ac3f9f4298eb754ad5c743546304c0f258b10869fdb19e48c7f4fc342fed8544fe2f71132bc3ac6fe3810df457db54d1d32e3d6986a1ccbfb4305bf1dad564b2
7
+ data.tar.gz: 81f6dc65dacdb2250978b11914a49fe5b0a72ec423ccd0fbff188d64743ca224383c70c1e53318fa0ed06fee6ebe585dc1afd05aad5f3993372d27fcf01bb532
data/README.md CHANGED
@@ -1,13 +1,34 @@
1
1
  Guachiman
2
2
  =========
3
3
 
4
- Basic Authorization gem. Based on [RailsCast #385 Authorization from Scratch](http://railscasts.com/episodes/385-authorization-from-scratch-part-1)
5
- from Ryan Bates.
4
+
5
+ Minimal authorization library inspired by [RailsCast #385 Authorization from Scratch][1] by Ryan Bates.
6
+
7
+ Guachiman allows you to store authorization rules as a tree of permissions nested within groups.
8
+ Permissions can be either `true` or a block that takes an object. In that case the permission will
9
+ be the result of the block evaluation.
10
+
11
+ [![Codeship Status for goddamnhippie/guachiman][2]][3]
12
+
13
+ [1]: http://railscasts.com/episodes/385-authorization-from-scratch-part-1
14
+ [2]: https://www.codeship.io/projects/f3a90030-f43c-0131-65bd-5a054a318c0e/status
15
+ [3]: https://www.codeship.io/projects/28071
16
+
17
+
18
+ Upgrading to v1.0.0
19
+ -------------------
20
+
21
+ **Starting with version 1.0.0 all Rails-specific code and support has been removed.**
22
+ A new gem called guachiman-rails will be the recommended way to use Guachiman with Rails.
23
+ More info [in the repo][4].
24
+
25
+ [4]: https://github.com/goddamnhippie/guachiman-rails
26
+
6
27
 
7
28
  Installation
8
29
  ------------
9
30
 
10
- Add this line to your application's Gemfile:
31
+ Add this line to your application's `Gemfile`:
11
32
 
12
33
  ```ruby
13
34
  gem 'guachiman'
@@ -19,156 +40,74 @@ And then execute:
19
40
  $ bundle
20
41
  ```
21
42
 
22
- Or install it yourself as:
43
+ Or install it directly:
23
44
 
24
45
  ```bash
25
46
  $ gem install guachiman
26
47
  ```
27
48
 
49
+
28
50
  Usage
29
51
  -----
30
52
 
31
- Run `rails g guachiman:install`
32
-
33
- This will generate a `permission.rb` file in `app/models`.
34
-
35
- Include `Guachiman::Permissible` in `ApplicationController` and implement a `current_user` method there.
53
+ Describe your authorization objects in this way:
36
54
 
37
55
  ```ruby
38
- include Guachiman::Permissible
39
-
40
- def current_user
41
- @current_user ||= User.find_by_auth_token(cookies[:auth_token]) if cookies[:auth_token]
42
- end
43
- ```
44
-
45
- You can also override these methods to handle failed authorizations for GET, non-AJAX requests:
46
-
47
- ```ruby
48
- def not_authorized
49
- redirect_to root_path, alert: t('flashes.not_authorized')
50
- end
51
-
52
- def not_signed_in
53
- session[:next] = request.url
54
- redirect_to sign_in_path, alert: t('flashes.please_sign_in')
55
- end
56
- ```
57
-
58
- And you can also override this method to handle failed non-GET or AJAX requests:
59
-
60
- ```ruby
61
- def render_unauthorized
62
- render text: "NO", status: :unauthorized
63
- end
64
- ```
56
+ class Authorization
57
+ include Guachiman
65
58
 
66
- That's it, now you can describe your permissions in this way:
67
-
68
- ```ruby
69
- class Permission
70
- include Guachiman::Permissions
71
- include Guachiman::Params
72
-
73
- attr_reader :current_user, :current_request
74
-
75
- def initialize user, request
76
- @current_user = user
77
- @current_request = request
78
-
79
- if current_user.nil?
80
- guest
81
- elsif current_user.admin?
82
- admin
59
+ def initialize(user)
60
+ if @current_user = user
61
+ member_authorization
83
62
  else
84
- member
63
+ guest_authorization
85
64
  end
86
65
  end
87
66
 
88
67
  private
89
68
 
90
- def guest
91
- allow :sessions, [:new, :create, :destroy]
92
- allow :users, [:new, :create]
93
-
94
- allow_param :user, [:name, :email, :password]
69
+ def guest_authorization
70
+ allow :sessions, [:new]
95
71
  end
96
72
 
97
- def member
98
- guest
99
- allow :users, [:show, :edit, :update]
100
- end
73
+ def member_authorization
74
+ guest_authorization
101
75
 
102
- def admin
103
- allow_all!
76
+ allow :users, [:show, :edit, :update] do |user_id|
77
+ @current_user.id == user_id
78
+ end
104
79
  end
105
80
  end
106
81
  ```
107
82
 
108
- * `#allow` takes a **controller** params key or array of keys and an array of **actions**.
109
- * `#allow_param` takes a **model** params key or array of keys and an array of **attributes**.
110
- * `#allow_all!` is a convenience method to allow **all** controllers, actions and parameteres.
111
-
112
- You can also go a bit further in the way you specify your permissions, if you override `current_resource`:
83
+ So that you can use them like this:
113
84
 
114
85
  ```ruby
115
- class OrdersController < ApplicationController
116
- ...
117
-
118
- private
119
- def current_resource
120
- @order ||= params[:id].present? ? Order.find(params[:id]) : Order.new
121
- end
122
- end
123
- ```
86
+ user = User.find(user_id)
124
87
 
125
- The `current_resource` is passed to a block that needs to return a truthy object to allow the action.
88
+ guest_authorization = Authorization.new
89
+ user_authorization = Authorization.new(user)
126
90
 
127
- ```ruby
128
- def guest
129
- allow :sessions, [:new, :create, :destroy]
130
- allow :users, [:new, :create]
131
- allow :orders, [:show, :edit, :update] do |order|
132
- order.accessible_by_token? current_request.cookies['cart_token']
133
- end
91
+ guest_authorization.allow?(:sessions, :new)
92
+ # => true
134
93
 
135
- allow_param :user, [:name, :email, :password]
136
- end
94
+ user_authorization.allow?(:users, :show)
95
+ # => false
137
96
 
138
- def member
139
- guest
140
-
141
- allow :users, [:show, :edit, :update] do |user|
142
- current_user == user
143
- end
144
- allow :orders, [:show, :edit, :update] do |order|
145
- order.accessible_by_user? user
146
- end
147
- end
97
+ user_authorization.allow?(:users, :show, user.id)
98
+ # => true
148
99
  ```
149
100
 
150
- You can also be more specific about the param permissions setting them to be read or write.
151
-
152
- ```ruby
153
- def member
154
- ...
101
+ ### `#allow`
155
102
 
156
- allow_read_param :contact, [:name, :phone, :email]
157
- allow_write_param :contact, [:name, :phone]
158
- end
159
- ```
103
+ This is what you use to set permissions. It takes two parameters, `group` and `permissions`, and a block.
104
+ All are optional and depend on how specific you want to be.
160
105
 
161
- That can also be useful on the views because you get a `current_permission` helper that you can use like this:
106
+ ### `#allow?`
162
107
 
163
- ```erb
164
- <%= form_for @contact do |f| %>
165
- <% current_permission.write_allowed_params[:contact].each do |p| %>
166
- <%= f.text_field p %>
167
- <% end %>
108
+ This is what you use to check permissions. It takes a `group` param, a `permission` param, and an optional `object`
109
+ param to evaluate in the block.
168
110
 
169
- <%= f.submit %>
170
- <% end %>
171
- ```
172
111
 
173
112
  License
174
113
  -------
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Guachiman::VERSION
9
9
  spec.authors = ['Francesco Rodriguez', 'Gustavo Beathyate']
10
10
  spec.email = ['lrodriguezsanc@gmail.com', 'gustavo.bt@me.com']
11
- spec.summary = 'Basic authorization library'
12
- spec.description = "#{spec.summary} based on Ryan Bates' Railscasts #385 and #386"
11
+ spec.summary = 'Minimal authorization library'
12
+ spec.description = "#{ spec.summary } inspired by Ryan Bates' Railscasts #385 and #386"
13
13
  spec.homepage = 'https://github.com/goddamnhippie/guachiman'
14
14
  spec.license = 'MIT'
15
15
 
@@ -17,10 +17,7 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test)/})
18
18
  spec.require_paths = ['lib']
19
19
 
20
- spec.add_dependency 'railties', '~> 4.0', '>= 4.0.0'
21
- spec.add_dependency 'activerecord', '~> 4.0', '>= 4.0.0'
22
-
23
20
  spec.add_development_dependency 'rake', '~> 10.3', '>= 10.3.0'
24
- spec.add_development_dependency 'minitest', '~> 5.3', '>= 5.3.3'
25
- spec.add_development_dependency 'bundler', '~> 1.6', '>= 1.6.0'
21
+ spec.add_development_dependency 'minitest', '~> 5.3', '>= 5.3.3'
22
+ spec.add_development_dependency 'bundler', '~> 1.6', '>= 1.6.0'
26
23
  end
@@ -1,9 +1,22 @@
1
1
  require 'guachiman/version'
2
- require 'guachiman/permissions'
3
- require 'guachiman/params'
4
2
 
5
- if defined? Rails
6
- require 'guachiman/rails/railtie'
7
- require 'guachiman/rails/permissible'
8
- require 'active_record'
3
+ module Guachiman
4
+ def rules
5
+ @rules ||= {}
6
+ end
7
+
8
+ def allow(group, permissions, &block)
9
+ permissions.each do |permission|
10
+ rules[group] ||= {}
11
+ rules[group][permission] = (block || true)
12
+ end
13
+ end
14
+
15
+ def allow?(group, permission, object = nil)
16
+ if rule = rules[group] && rules[group][permission]
17
+ rule == true || object && rule.call(object)
18
+ else
19
+ false
20
+ end
21
+ end
9
22
  end
@@ -1,3 +1,3 @@
1
1
  module Guachiman
2
- VERSION = '0.3.2'
2
+ VERSION = '1.0.1'
3
3
  end
@@ -0,0 +1,34 @@
1
+ require 'bundler/setup'
2
+ require 'minitest/autorun'
3
+ require 'guachiman'
4
+
5
+ class GuachimanTest < MiniTest::Test
6
+ def setup
7
+ @authorization = Class.new do
8
+ include Guachiman
9
+
10
+ def initialize
11
+ allow :group, [:permission1, :permission2]
12
+
13
+ allow :group, [:permission3, :permission4] do |object|
14
+ object == 1
15
+ end
16
+ end
17
+ end.new
18
+ end
19
+
20
+ def test_basic_rules
21
+ refute @authorization.allow?(:group, :permission0)
22
+ assert @authorization.allow?(:group, :permission1)
23
+ assert @authorization.allow?(:group, :permission2)
24
+ end
25
+
26
+ def test_block_rules
27
+ refute @authorization.allow?(:group, :permission3)
28
+ refute @authorization.allow?(:group, :permission4)
29
+ refute @authorization.allow?(:group, :permission3, 0)
30
+ refute @authorization.allow?(:group, :permission4, 0)
31
+ assert @authorization.allow?(:group, :permission3, 1)
32
+ assert @authorization.allow?(:group, :permission4, 1)
33
+ end
34
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: guachiman
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Francesco Rodriguez
@@ -9,48 +9,8 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-07-08 00:00:00.000000000 Z
12
+ date: 2014-07-23 00:00:00.000000000 Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: railties
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - "~>"
19
- - !ruby/object:Gem::Version
20
- version: '4.0'
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: 4.0.0
24
- type: :runtime
25
- prerelease: false
26
- version_requirements: !ruby/object:Gem::Requirement
27
- requirements:
28
- - - "~>"
29
- - !ruby/object:Gem::Version
30
- version: '4.0'
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: 4.0.0
34
- - !ruby/object:Gem::Dependency
35
- name: activerecord
36
- requirement: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '4.0'
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- version: 4.0.0
44
- type: :runtime
45
- prerelease: false
46
- version_requirements: !ruby/object:Gem::Requirement
47
- requirements:
48
- - - "~>"
49
- - !ruby/object:Gem::Version
50
- version: '4.0'
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- version: 4.0.0
54
14
  - !ruby/object:Gem::Dependency
55
15
  name: rake
56
16
  requirement: !ruby/object:Gem::Requirement
@@ -111,8 +71,8 @@ dependencies:
111
71
  - - ">="
112
72
  - !ruby/object:Gem::Version
113
73
  version: 1.6.0
114
- description: 'Basic authorization library based on Ryan Bates'' Railscasts #385 and
115
- #386'
74
+ description: 'Minimal authorization library inspired by Ryan Bates'' Railscasts #385
75
+ and #386'
116
76
  email:
117
77
  - lrodriguezsanc@gmail.com
118
78
  - gustavo.bt@me.com
@@ -126,16 +86,9 @@ files:
126
86
  - README.md
127
87
  - Rakefile
128
88
  - guachiman.gemspec
129
- - lib/generators/guachiman/install/install_generator.rb
130
- - lib/generators/guachiman/install/templates/permission.rb
131
89
  - lib/guachiman.rb
132
- - lib/guachiman/params.rb
133
- - lib/guachiman/permissions.rb
134
- - lib/guachiman/rails/permissible.rb
135
- - lib/guachiman/rails/railtie.rb
136
90
  - lib/guachiman/version.rb
137
- - test/generators/install_generator_test.rb
138
- - test/test_helper.rb
91
+ - test/guachiman_test.rb
139
92
  homepage: https://github.com/goddamnhippie/guachiman
140
93
  licenses:
141
94
  - MIT
@@ -156,10 +109,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
156
109
  version: '0'
157
110
  requirements: []
158
111
  rubyforge_project:
159
- rubygems_version: 2.2.2
112
+ rubygems_version: 2.4.1
160
113
  signing_key:
161
114
  specification_version: 4
162
- summary: Basic authorization library
115
+ summary: Minimal authorization library
163
116
  test_files:
164
- - test/generators/install_generator_test.rb
165
- - test/test_helper.rb
117
+ - test/guachiman_test.rb
@@ -1,12 +0,0 @@
1
- module Guachiman
2
- module Generators
3
- class InstallGenerator < ::Rails::Generators::Base
4
- desc 'Install guachiman'
5
- source_root File.expand_path '../templates', __FILE__
6
-
7
- def copy_permission_model
8
- template 'permission.rb', 'app/models/permission.rb'
9
- end
10
- end
11
- end
12
- end
@@ -1,32 +0,0 @@
1
- class Permission
2
- include Guachiman::Permissions
3
- include Guachiman::Params
4
-
5
- attr_reader :current_user, :current_request
6
-
7
- def initialize user, request
8
- @current_user = user
9
- @current_request = request
10
-
11
- if current_user.nil?
12
- guest
13
- elsif current_user.admin?
14
- admin
15
- else
16
- member
17
- end
18
- end
19
-
20
- private
21
-
22
- def guest
23
- end
24
-
25
- def member
26
- guest
27
- end
28
-
29
- def admin
30
- allow_all!
31
- end
32
- end
@@ -1,48 +0,0 @@
1
- module Guachiman
2
- module Params
3
- attr_reader :read_allowed_params, :write_allowed_params
4
-
5
- [:read, :write].each do |action|
6
- ivar = "@#{action}_allowed_params"
7
-
8
- define_method "allow_#{action}_param" do |resources, attributes|
9
- instance_variable_set(ivar, {}) unless instance_variable_get ivar
10
- Array(resources).each do |resource|
11
- instance_variable_get(ivar)[resource] ||= []
12
- instance_variable_get(ivar)[resource] += Array(attributes)
13
- end
14
- end
15
-
16
- define_method "allow_#{action}_param?" do |resource, attribute|
17
- if instance_variable_get :@allow_all
18
- true
19
- elsif instance_variable_get(ivar) && instance_variable_get(ivar)[resource]
20
- instance_variable_get(ivar)[resource].include? attribute
21
- end
22
- end
23
- end
24
-
25
- def allowed_params
26
- read_allowed_params & write_allowed_params
27
- end
28
-
29
- def allow_param resources, attributes
30
- allow_read_param resources, attributes
31
- allow_write_param resources, attributes
32
- end
33
-
34
- def allow_param? resource, attribute
35
- allow_write_param?(resource, attribute) && allow_read_param?(resource, attribute)
36
- end
37
-
38
- def permit_params! params
39
- if @allow_all
40
- params.permit!
41
- elsif write_allowed_params
42
- write_allowed_params.each do |resource, attributes|
43
- params[resource] = params[resource].permit(*attributes) if params[resource].respond_to? :permit
44
- end
45
- end
46
- end
47
- end
48
- end
@@ -1,30 +0,0 @@
1
- module Guachiman
2
- module Permissions
3
- attr_reader :allowed_actions, :allow_all
4
-
5
- def allow controllers, actions, &block
6
- @allowed_actions ||= {}
7
- Array(controllers).each do |controller|
8
- Array(actions).each do |action|
9
- allowed_actions[controller] ||= {}
10
- allowed_actions[controller].merge! action => (block || true)
11
- end
12
- end
13
- end
14
-
15
- def allow? controller, action, resource=nil
16
- allowed = allow_all || check_allowed_action(controller, action)
17
- !!allowed && (allowed == true || resource && allowed.call(resource))
18
- end
19
-
20
- def allow_all!
21
- @allow_all = true
22
- end
23
-
24
- private
25
-
26
- def check_allowed_action controller, action
27
- allowed_actions && allowed_actions[controller.to_sym] && allowed_actions[controller.to_sym][action.to_sym]
28
- end
29
- end
30
- end
@@ -1,49 +0,0 @@
1
- module Guachiman
2
- module Permissible
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- before_filter :authorize
7
- helper_method :current_user
8
- helper_method :current_permission
9
- helper_method :current_resource
10
- end
11
-
12
- def current_user
13
- raise 'This method must be implemented'
14
- end
15
-
16
- def current_permission
17
- @current_permission ||= Permission.new current_user, request
18
- end
19
-
20
- def current_resource
21
- nil
22
- end
23
-
24
- def authorize
25
- if current_permission.allow? controller_name, action_name, current_resource
26
- current_permission.permit_params! params
27
- else
28
- if request.get? && !request.xhr?
29
- current_user ? not_authorized : not_signed_in
30
- else
31
- render_unauthorized
32
- end
33
- end
34
- end
35
-
36
- def not_authorized
37
- redirect_to root_path, alert: t('flashes.not_authorized')
38
- end
39
-
40
- def not_signed_in
41
- session[:next] = request.url
42
- redirect_to sign_in_path, alert: t('flashes.please_sign_in')
43
- end
44
-
45
- def render_unauthorized
46
- render text: "NO", status: :unauthorized
47
- end
48
- end
49
- end
@@ -1,8 +0,0 @@
1
- require 'rails'
2
-
3
- module Guachiman
4
- module Rails
5
- class Railtie < ::Rails::Railtie
6
- end
7
- end
8
- end
@@ -1,30 +0,0 @@
1
- require 'test_helper'
2
- require 'rails/generators/test_case'
3
- require 'generators/guachiman/install/install_generator'
4
-
5
- class InstallGeneratorTest < Rails::Generators::TestCase
6
- DESTINATION = File.expand_path File.join(File.dirname(__FILE__), '..', '..', 'tmp')
7
- FileUtils.mkdir_p DESTINATION unless Dir.exist? DESTINATION
8
-
9
- destination DESTINATION
10
-
11
- tests Guachiman::Generators::InstallGenerator
12
- setup :prepare_destination
13
-
14
- def prepare_destination
15
- FileUtils.rm_r "#{DESTINATION}/app" if Dir.exists? "#{DESTINATION}/app"
16
- FileUtils.mkdir_p "#{DESTINATION}/app"
17
- FileUtils.mkdir_p "#{DESTINATION}/app/models"
18
- end
19
-
20
- test 'create permission' do
21
- run_generator
22
-
23
- assert_file 'app/models/permission.rb' do |f|
24
- assert_match(/class Permission/, f)
25
- assert_match(/include Guachiman::Permissions/, f)
26
- assert_match(/include Guachiman::Params/, f)
27
- assert_match(/initialize user, request/, f)
28
- end
29
- end
30
- end
@@ -1,4 +0,0 @@
1
- require 'bundler/setup'
2
- require 'minitest/autorun'
3
- require 'minitest/pride'
4
- require 'guachiman'