guachiman 0.3.2 → 1.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 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'