fat_model_auth 3.0.0 → 5.0.0

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
+ SHA256:
3
+ metadata.gz: bd46f66b0c3c0944de66eef838846681673ede771bc05da2aec7839ff7abf906
4
+ data.tar.gz: 636e991ce6505513fe7707c092b6c340bc167c9393ab7b2663dd31f946d0a3b5
5
+ SHA512:
6
+ metadata.gz: 7543fc723da9599c19b098b22cbd63e524d0897355122e537d19c31c0e0f2df272ff83aa6995bf36a91dc46f29365a0b757369908915959ee3036c523c9b2d2d
7
+ data.tar.gz: ffafe0bd236e7586f063c2c009e062927b614c59ab83d7e31cc4ed413f7a2bb5a22ff7a6718a8f8c3da55ababc27fecf83fd1127d7cac141895bc87ca07bc86d
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Brent
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,232 @@
1
+ [![CI](https://github.com/brentgreeff/fat_model_auth/actions/workflows/ci.yml/badge.svg)](https://github.com/brentgreeff/fat_model_auth/actions/workflows/ci.yml)
2
+
3
+ - [Example app - view installation diff](https://github.com/brentgreeff/basic_rails_5_api/commit/6f0cedff4077c1609d32567bfb889fc8fa908db7)
4
+
5
+ # FatModelAuth
6
+
7
+ Wikipedia defines Authorization as:
8
+
9
+ > “the function of specifying access rights to resources”
10
+
11
+ Fat Model Auth allows the resources themselves to define these rights.
12
+
13
+ ## Install
14
+
15
+ Add to Gemfile
16
+
17
+ $ gem fat_model_auth
18
+
19
+ ## Fat Model Auth is a simple, clean authorization system for Rails
20
+
21
+ How simple?
22
+
23
+ ## ArticlesController
24
+
25
+ ```
26
+ before_action :load_article
27
+
28
+ def edit
29
+ end
30
+
31
+ def update
32
+ end
33
+
34
+ private
35
+
36
+ def load_article
37
+ Article.find(params[:id])
38
+ end
39
+ ```
40
+
41
+ We want to ensure only the Article's author can view the edit page or update the article.
42
+
43
+ ### Add a before filter to the articles_controller:
44
+
45
+ `before_action :auth_required, only: [:edit, :update]`
46
+
47
+ Since this is the article controller, the resource in question is the @article.
48
+
49
+ auth_required must be called after the resource is already loaded.
50
+
51
+ Like this:
52
+
53
+ ```
54
+ before_action :load_article, only: [:edit, :update]
55
+ before_action :auth_required, only: [:edit, :update]
56
+ ```
57
+
58
+ auth_required will infer the name of the resource from the controller. In the case of articles_controller, it will look for an @article instance variable.
59
+
60
+ Try and view the articles#edit page from a browser, or event better: re-run the spec.
61
+
62
+ You should get an exception:
63
+
64
+ `undefined method 'allows' for #<Article:0x204a8d8>`
65
+
66
+ This means the gem is working correctly.
67
+
68
+ fat_model_auth has generated a call to the @article model:
69
+
70
+ `@article.allows(current_user).to_edit?`
71
+
72
+ You need to define a `current_user` method in the application_controller, so that the current user is passed in for evaluation.
73
+
74
+ If `current_user` is `nil`, the controller will always return access_denied.
75
+
76
+
77
+ ## In the Article Model
78
+
79
+ * Add the following:
80
+
81
+ ```
82
+ allows :edit, :update,
83
+ if: -> (article, user) { article.author == user }
84
+ ```
85
+
86
+ The article model now supports the allows instance method, with 2 chains:
87
+
88
+ `@article.allows(current_user).to_edit?`
89
+
90
+ - called from the #edit action when using the auth_required before_action.
91
+
92
+ `@article.allows(current_user).to_update?`
93
+
94
+ - called on the update action.
95
+
96
+ ### Access Denied is 404
97
+
98
+ Trying to access a resource without permission returns 404.
99
+
100
+ By returning 403 (Forbidden) you might be revealing potentially sensitive information.
101
+
102
+ 404 = that doesn't exist.
103
+
104
+ 403 = Yes that does exist, but you need to try harder to get access to it.
105
+
106
+
107
+ ### New & Create
108
+
109
+ When dealing with the #new & #create actions we need a slightly different approach.
110
+
111
+ Quite often we will build the new object in the action.
112
+
113
+ ```
114
+ def create
115
+ @article = current_user.articles.build(params[:article])
116
+ return if access_denied?
117
+ end
118
+ ```
119
+
120
+ When you call access_denied? fat_model_auth will ask the @article if access is allowed.
121
+
122
+ The following call is generated for you:
123
+
124
+ `@article.allows(current_user).to_create?`
125
+
126
+
127
+ ### What if you need different rules for different actions?
128
+
129
+ ```
130
+ allows :edit,
131
+ if: -> (article, user) { article.author.can_edit? }
132
+
133
+ allows :update,
134
+ if: -> (article, user) { article.allows_updating? }
135
+
136
+ allows :delete,
137
+ unless: -> (article, user) { user.can_delete?(article) }
138
+ ```
139
+
140
+ Both if: and unless: symbols are supported.
141
+
142
+
143
+ ### What if you are loading an @article in the StoriesController
144
+
145
+ We need to tell the controller which object will act as the authority.
146
+
147
+ class StoriesController < ApplicationController
148
+ def override_authority
149
+ @article
150
+ end
151
+ end
152
+
153
+
154
+ ## View (templates)
155
+
156
+ Control which links, buttons or controls are displayed to a user:
157
+
158
+ `<%= link_to('EDIT', edit_article_path(article)) if allowed_to? edit: article -%>`
159
+
160
+
161
+ Control which blocks of html are accessible:
162
+
163
+ ```
164
+ <% if allowed_to? edit_or_destroy: article -%>
165
+ <funky>html</funky>
166
+ <% end %>
167
+ ```
168
+
169
+
170
+ ## Test First
171
+
172
+ Before adding unit tests, its best to start with a request_spec or another kind of integration test which is focussed on user interaction.
173
+
174
+ If the integration test covers the logic in the model then that might be sufficient.
175
+
176
+ ## Request specs
177
+ ```
178
+ login_as no_good_user
179
+
180
+ get "/articles/#{article.to_param}/edit"
181
+
182
+ expect( response ).to have_http_status(404)
183
+ ```
184
+
185
+ If you are using a mock user, you can stub the response
186
+
187
+ ```
188
+ let(:yes) { FatModelAuth::CannedGateKeeper.allows(:edit) }
189
+
190
+ it "allows"
191
+ expect(article).to receive(:allows).and_return(yes)
192
+ end
193
+ ```
194
+
195
+ or
196
+
197
+ ```
198
+ let(:no) { FatModelAuth::CannedGateKeeper.denies(:edit) }
199
+
200
+ it "does not allow"
201
+ expect(article).to receive(:allows).and_returns(no)
202
+ end
203
+ ```
204
+
205
+ ## Model specs
206
+
207
+ ### EDIT
208
+
209
+ `expect( article.allows( peon ).to_edit? ).to be false`
210
+
211
+ `expect( article.allows( admin ).to_edit? ).to be true`
212
+
213
+ ### UPDATE
214
+
215
+ `expect( article.allows( peon ).to_update? ).to be false`
216
+
217
+ `expect( article.allows( admin ).to_update? ).to be true`
218
+
219
+
220
+ ## Development
221
+
222
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
223
+
224
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
225
+
226
+ ## Contributing
227
+
228
+ Bug reports and pull requests are welcome on GitHub at https://github.com/brentgreeff/fat_model_auth.
229
+
230
+ ## License
231
+
232
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -1,40 +1,44 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatModelAuth
2
4
  class CannedGateKeeper
3
-
4
- def self.allows(method)
5
- self.new(method => true)
5
+ def self.allows(action)
6
+ new(action => true)
6
7
  end
7
-
8
- def self.denies(method)
9
- self.new(method => false)
8
+
9
+ def self.denies(action)
10
+ new(action => false)
10
11
  end
11
-
12
+
12
13
  def self.build(params)
13
- self.new(params)
14
+ new(params)
14
15
  end
15
-
16
- def allows(user)
17
- self
18
- end
19
-
16
+
20
17
  def initialize(params)
21
18
  @map = {}
22
19
  add_rules(params)
23
20
  end
24
-
25
- def add_rules(params)
26
- for param in params
27
- response = param.pop
28
- @map["to_#{param.pop}?".to_sym] = lambda { response }
29
- end
21
+
22
+ def allows(_user)
23
+ self
30
24
  end
31
-
32
- def method_missing(method, *args)
33
- unless @map.has_key? method
34
- raise NoMethodError, "undefined method allows(user).#{method} for #{self.class}"
35
- end
36
-
25
+
26
+ def method_missing(method, *_args)
27
+ raise NoMethodError, "undefined method allows(user).#{method} for #{self.class}" unless @map.key?(method)
28
+
37
29
  @map[method].call
38
30
  end
31
+
32
+ def respond_to_missing?(method, include_private = false)
33
+ @map.key?(method) || super
34
+ end
35
+
36
+ private
37
+
38
+ def add_rules(params)
39
+ params.each do |action, response|
40
+ @map[:"to_#{action}?"] = -> { response }
41
+ end
42
+ end
39
43
  end
40
44
  end
@@ -1,20 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatModelAuth
2
- class AuthException < Exception; end
3
-
4
+ class AuthException < StandardError; end
5
+
4
6
  module ControllerHelpers
5
7
  protected
6
-
8
+
7
9
  def auth_required
8
- authority = get_authority
9
-
10
- access_granted = authority.allows(current_user).send "to_#{params[:action]}?"
10
+ access_granted = authority.allows(current_user).send("to_#{params[:action]}?")
11
11
  respond_with_404_page unless access_granted
12
12
  end
13
-
13
+
14
14
  def access_denied?
15
- authority = get_authority
16
-
17
- access_granted = authority.allows(current_user).send "to_#{params[:action]}?"
15
+ access_granted = authority.allows(current_user).send("to_#{params[:action]}?")
16
+
18
17
  if access_granted
19
18
  false
20
19
  else
@@ -22,24 +21,29 @@ module FatModelAuth
22
21
  true
23
22
  end
24
23
  end
25
-
24
+
26
25
  private
27
-
28
- def get_authority
29
- if self.respond_to? :override_authority
30
- authority = override_authority
31
- raise FatModelAuth::AuthException, "override_authority defined but nil" if authority.nil?
26
+
27
+ def authority
28
+ if respond_to?(:override_authority, true)
29
+ result = override_authority
30
+ raise FatModelAuth::AuthException, 'override_authority defined but nil' if result.nil?
31
+
32
32
  else
33
- authority_name = params[:controller].singularize
34
- authority = instance_variable_get("@#{authority_name}")
35
- raise FatModelAuth::AuthException, "#{authority_name} is nil" if authority.nil?
33
+ authority_name = controller_name.singularize
34
+ result = instance_variable_get("@#{authority_name}")
35
+ raise FatModelAuth::AuthException, "#{authority_name} is nil" if result.nil?
36
+
36
37
  end
37
-
38
- return authority
38
+ result
39
39
  end
40
-
40
+
41
41
  def respond_with_404_page
42
- render "#{Rails.root}/public/404.html", :status => 404
42
+ if defined?(Rails) && Rails.respond_to?(:application) && Rails.application
43
+ render file: Rails.public_path.join('404.html'), status: :not_found, layout: false
44
+ else
45
+ head :not_found
46
+ end
43
47
  end
44
48
  end
45
49
  end
@@ -1,33 +1,56 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatModelAuth
2
4
  class GateKeeper
3
-
4
5
  def initialize(params)
5
6
  @map = {}
6
7
  add_rules(params)
7
8
  end
8
-
9
+
9
10
  def add_rules(params)
10
- auth_condition = params.pop[:if]
11
- methods = params
12
-
13
- for method in methods
14
- @map["to_#{method}?".to_sym] = auth_condition
11
+ *methods, options = params
12
+ unless options.is_a?(Hash) && (options[:if] || options[:unless])
13
+ raise ArgumentError, 'allows requires an :if or :unless condition'
14
+ end
15
+
16
+ auth_condition = options[:if] || negate(options[:unless])
17
+
18
+ methods.each do |method|
19
+ key = :"to_#{method}?"
20
+ raise ArgumentError, "rule for :#{method} is already defined" if @map.key?(key)
21
+
22
+ @map[key] = auth_condition
15
23
  end
16
24
  end
17
-
25
+
18
26
  def check(model, user)
19
- @model = model
20
- @user = user
21
- self
27
+ Checker.new(@map, model, user)
28
+ end
29
+
30
+ private
31
+
32
+ def negate(predicate)
33
+ proc { |*args| !predicate.call(*args) }
22
34
  end
23
-
24
- def method_missing(method, *args)
25
- unless @map.has_key? method
26
- raise NoMethodError, "undefined method allows(user).#{method} for #{@model.inspect}"
35
+
36
+ class Checker
37
+ def initialize(map, model, user)
38
+ @map = map
39
+ @model = model
40
+ @user = user
41
+ end
42
+
43
+ def method_missing(method, *_args)
44
+ raise NoMethodError, "undefined method allows(user).#{method} for #{@model.inspect}" unless @map.key?(method)
45
+
46
+ return false if @user.nil?
47
+
48
+ @map[method].call(@model, @user)
49
+ end
50
+
51
+ def respond_to_missing?(method, include_private = false)
52
+ @map.key?(method) || super
27
53
  end
28
- return false if @user.nil?
29
-
30
- @map[method].call(@model, @user)
31
54
  end
32
55
  end
33
56
  end
@@ -1,18 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatModelAuth
2
4
  module ModelHelpers
3
5
  def allows(*params)
4
- if self.respond_to? :gate_keeper
5
- class_eval do
6
- self.gate_keeper.add_rules(params)
7
- end
6
+ if respond_to?(:gate_keeper) && gate_keeper
7
+ gate_keeper.add_rules(params)
8
8
  else
9
- class_eval do
10
- cattr_accessor :gate_keeper
11
- self.gate_keeper = FatModelAuth::GateKeeper.new(params)
12
-
13
- define_method "allows" do |user|
14
- self.gate_keeper.check(self, user)
15
- end
9
+ class_attribute :gate_keeper
10
+ self.gate_keeper = FatModelAuth::GateKeeper.new(params)
11
+
12
+ define_method :allows do |user|
13
+ self.class.gate_keeper.check(self, user)
16
14
  end
17
15
  end
18
16
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/railtie'
4
+
5
+ module FatModelAuth
6
+ class Railtie < Rails::Railtie
7
+ initializer 'fat_model_auth.initialize' do |_app|
8
+ ActiveSupport.on_load :action_controller do
9
+ include FatModelAuth::ControllerHelpers
10
+ end
11
+
12
+ ActiveSupport.on_load :active_record do
13
+ extend FatModelAuth::ModelHelpers
14
+ end
15
+
16
+ ActiveSupport.on_load :action_view do
17
+ include FatModelAuth::ViewHelpers
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FatModelAuth
4
+ VERSION = '5.0.0'
5
+ end
@@ -1,18 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatModelAuth
2
4
  module ViewHelpers
3
5
  def allowed_to?(options)
4
- authority = options.values.first
5
-
6
- get_actions(options).each do |action|
7
- return true if authority.allows(current_user).send "to_#{action}?"
6
+ actions, authority = options.first
7
+ raise FatModelAuth::AuthException, "#{authority.inspect} is nil" if authority.nil?
8
+
9
+ actions.to_s.split('_or_').any? do |action|
10
+ authority.allows(current_user).send("to_#{action}?")
8
11
  end
9
- return false
10
- end
11
-
12
- private
13
-
14
- def get_actions(options)
15
- return options.keys.first.to_s.split('_or_')
16
12
  end
17
13
  end
18
14
  end
@@ -1,9 +1,18 @@
1
- require 'fat_model_auth/canned_gate_keeper'
2
- require 'fat_model_auth/controller_helpers'
3
- require 'fat_model_auth/gate_keeper'
4
- require 'fat_model_auth/model_helpers'
5
- require 'fat_model_auth/view_helpers'
6
-
7
- ActionController::Base.send(:include, FatModelAuth::ControllerHelpers)
8
- ActiveRecord::Base.send(:extend, FatModelAuth::ModelHelpers)
9
- ActionView::Base.send(:include, FatModelAuth::ViewHelpers)
1
+ # frozen_string_literal: true
2
+
3
+ require 'action_pack'
4
+ require 'active_support'
5
+
6
+ require 'fat_model_auth/version'
7
+
8
+ require 'fat_model_auth/railtie' if defined?(Rails)
9
+
10
+ module FatModelAuth
11
+ extend ActiveSupport::Autoload
12
+
13
+ autoload :ControllerHelpers, 'fat_model_auth/controller_helpers'
14
+ autoload :ModelHelpers, 'fat_model_auth/model_helpers'
15
+ autoload :ViewHelpers, 'fat_model_auth/view_helpers'
16
+ autoload :GateKeeper, 'fat_model_auth/gate_keeper'
17
+ autoload :CannedGateKeeper, 'fat_model_auth/canned_gate_keeper'
18
+ end
metadata CHANGED
@@ -1,79 +1,210 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: fat_model_auth
3
- version: !ruby/object:Gem::Version
4
- hash: 7
5
- prerelease: false
6
- segments:
7
- - 3
8
- - 0
9
- - 0
10
- version: 3.0.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 5.0.0
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - Brent Greeff
14
- autorequire:
15
8
  bindir: bin
16
9
  cert_chain: []
17
-
18
- date: 2010-10-30 00:00:00 +01:00
19
- default_executable:
20
- dependencies: []
21
-
22
- description: Clean resource based Authorisation plugin for Rails.
23
- email: email@brentgreeff.com
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: actionpack
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '7.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '7.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: activerecord
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '7.0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '7.0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: activesupport
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '7.0'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '7.0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: bundler-audit
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: lefthook
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: ostruct
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: rake
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rspec
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ - !ruby/object:Gem::Dependency
125
+ name: rubocop-rails-omakase
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ type: :development
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ - !ruby/object:Gem::Dependency
139
+ name: rubocop-rspec
140
+ requirement: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ type: :development
146
+ prerelease: false
147
+ version_requirements: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ - !ruby/object:Gem::Dependency
153
+ name: sqlite3
154
+ requirement: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ type: :development
160
+ prerelease: false
161
+ version_requirements: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ description: Models define access rules via a DSL. Controllers call auth_required.
167
+ Access denied returns 404.
168
+ email:
169
+ - email@brentgreeff.com
24
170
  executables: []
25
-
26
171
  extensions: []
27
-
28
- extra_rdoc_files:
29
- - MIT-LICENSE
30
- - README.rdoc
31
- files:
32
- - MIT-LICENSE
33
- - README.rdoc
34
- - Rakefile
35
- - VERSION
172
+ extra_rdoc_files: []
173
+ files:
174
+ - LICENSE.txt
175
+ - README.md
36
176
  - lib/fat_model_auth.rb
37
177
  - lib/fat_model_auth/canned_gate_keeper.rb
38
178
  - lib/fat_model_auth/controller_helpers.rb
39
179
  - lib/fat_model_auth/gate_keeper.rb
40
180
  - lib/fat_model_auth/model_helpers.rb
181
+ - lib/fat_model_auth/railtie.rb
182
+ - lib/fat_model_auth/version.rb
41
183
  - lib/fat_model_auth/view_helpers.rb
42
- - test/fat_model_auth_test.rb
43
- - test/test_helper.rb
44
- has_rdoc: true
45
- homepage: http://github.com/brentgreeff/fat_model_auth
46
- licenses: []
47
-
48
- post_install_message:
49
- rdoc_options:
50
- - --charset=UTF-8
51
- require_paths:
184
+ homepage: https://github.com/brentgreeff/fat_model_auth
185
+ licenses:
186
+ - MIT
187
+ metadata:
188
+ rubygems_mfa_required: 'true'
189
+ homepage_uri: https://github.com/brentgreeff/fat_model_auth
190
+ source_code_uri: https://github.com/brentgreeff/fat_model_auth
191
+ changelog_uri: https://github.com/brentgreeff/fat_model_auth/blob/main/CHANGELOG.md
192
+ rdoc_options: []
193
+ require_paths:
52
194
  - lib
53
- required_ruby_version: !ruby/object:Gem::Requirement
54
- none: false
55
- requirements:
195
+ required_ruby_version: !ruby/object:Gem::Requirement
196
+ requirements:
56
197
  - - ">="
57
- - !ruby/object:Gem::Version
58
- hash: 3
59
- segments:
60
- - 0
61
- version: "0"
62
- required_rubygems_version: !ruby/object:Gem::Requirement
63
- none: false
64
- requirements:
198
+ - !ruby/object:Gem::Version
199
+ version: '3.3'
200
+ required_rubygems_version: !ruby/object:Gem::Requirement
201
+ requirements:
65
202
  - - ">="
66
- - !ruby/object:Gem::Version
67
- hash: 3
68
- segments:
69
- - 0
70
- version: "0"
203
+ - !ruby/object:Gem::Version
204
+ version: '0'
71
205
  requirements: []
72
-
73
- rubyforge_project:
74
- rubygems_version: 1.3.7
75
- signing_key:
76
- specification_version: 3
77
- summary: Clean resource based Authorisation plugin for Rails.
206
+ rubygems_version: 3.6.9
207
+ specification_version: 4
208
+ summary: 'Resource-level Rails authorization: models declare rules, controllers enforce
209
+ them.'
78
210
  test_files: []
79
-
data/MIT-LICENSE DELETED
@@ -1,20 +0,0 @@
1
- Copyright (c) 2009 [Brent Greeff]
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.rdoc DELETED
@@ -1,172 +0,0 @@
1
- = Fat Model Auth
2
-
3
- Wikipedia defines Authorization as 'the function of specifying access rights to resources'.
4
- Fat Model Auth allows the resources themselves to define these rights.
5
-
6
- == Fat Model Auth is a simple, clean authorization system for Rails
7
-
8
- * How simple?
9
-
10
- == Controller
11
-
12
- * Imagine you have a controller for Articles:
13
-
14
- before_filter :load_article
15
-
16
- def edit
17
- end
18
-
19
- def update
20
- # Update shazam
21
- end
22
-
23
- private
24
-
25
- def load_article
26
- Article.find(params[:id])
27
- end
28
-
29
- * We want to ensure only the Articles Author can view the edit page or update
30
- * an Article.
31
-
32
- * Just Add a before filter:
33
-
34
- before_filter :auth_required, :only => [:edit, :update]
35
-
36
- * Add it AFTER you load the article
37
-
38
- Go ahead and try and view the article
39
-
40
- * We are missing something:
41
-
42
- undefined method 'allows' for #<Article:0x204a8d8>
43
-
44
- == Model
45
-
46
- * Just add the following to your Article model:
47
-
48
- allows :edit, :update,
49
- :if => proc {|article, user| article.author == user}
50
-
51
- * Need different rules for different actions:
52
-
53
- allows :edit,
54
- :if => proc {|article, user| article.author.name.eql? 'Jeff'}
55
-
56
- allows :update,
57
- :if => proc {|article, user| article.allows_updating?}
58
-
59
-
60
- Control which functions are displayed to a user
61
-
62
- == View
63
-
64
- <%= link_to('EDIT', edit_article_path(article)) if allowed_to? :edit => article -%>
65
-
66
- * What about groups of controls:
67
-
68
- <% if allowed_to? :edit_or_destroy => article -%>
69
- <funky>html</funky>
70
- <% end %>
71
-
72
-
73
- Thats it.
74
-
75
- == Test First
76
-
77
- The rules that define access control, are defined in the model.
78
- If you are testing first, start with a unit test:
79
-
80
- * EDIT
81
-
82
- assert @article.allows(@article.author).to_edit?
83
-
84
- deny @article.allows(@someone_else).to_edit?
85
-
86
- * UPDATE
87
-
88
- assert @article.allows(@jeff).to_update?
89
-
90
- deny @article.allows(@sammy).to_update?
91
-
92
- These magic methods are created when you define 'allows' on your model.
93
-
94
- When you say 'auth_required' in a before filter:
95
- The plugin looks for an object based on the name of the controller:
96
-
97
- So if you put the before filter in the 'articles_controller'
98
- and you call the 'edit' action,
99
-
100
- it generates the following call:
101
-
102
- @article.allows(current_user).to_edit?
103
-
104
-
105
- What happens if I am editing articles but I am not in the articles_controller?
106
-
107
- * Just add this to the controller
108
-
109
- class RestlessController < ApplicationController
110
- def override_authority
111
- @article
112
- end
113
- end
114
-
115
- == Remember
116
-
117
- 1. A nil current_user will always return access_denied.
118
-
119
- == Access Denied is 404
120
-
121
- Thats right deal with it or fork it.
122
-
123
- Trying to access a resource without permission returns 404
124
- In other words:
125
-
126
- "Say What?"
127
-
128
- == New & Create and complex conditons
129
-
130
- If you have complex conditions or when creating a new object
131
- it may not have the information you need in a before filter.
132
-
133
- You can always get the same result by being explicit in the method:
134
-
135
- # Articles controller
136
-
137
- def create
138
- @article = current_user.articles.build(params[:article])
139
- return if access_denied?
140
- end
141
-
142
- == Testing my controllers
143
-
144
- login_as @no_good_user
145
- get :edit, :id => @article.id
146
-
147
- assert_response :not_found
148
- assert_template 'public/404'
149
-
150
- If you are using mock user, you may want to stub the response
151
-
152
- @article.expects(:allows).returns(FatModelAuth::CannedGateKeeper.allows(:edit))
153
-
154
- or
155
-
156
- @article.expects(:allows).returns(FatModelAuth::CannedGateKeeper.denies(:edit))
157
-
158
-
159
- == Testing my views
160
-
161
- Who does that?
162
-
163
- step 1. Install should_pricot
164
-
165
- login_as @no_good_user
166
- get :edit, :id => @article.id
167
-
168
- element('#power_user a[@href="/create/havok"]').should_be_missing
169
-
170
-
171
-
172
- Copyright (c) 2009 [Brent Greeff], released under the MIT license
data/Rakefile DELETED
@@ -1,23 +0,0 @@
1
- require 'rake'
2
- require 'rake/testtask'
3
- require 'rake/rdoctask'
4
-
5
- desc 'Default: run unit tests.'
6
- task :default => :test
7
-
8
- desc 'Test the fat_model_auth plugin.'
9
- Rake::TestTask.new(:test) do |t|
10
- t.libs << 'lib'
11
- t.libs << 'test'
12
- t.pattern = 'test/**/*_test.rb'
13
- t.verbose = true
14
- end
15
-
16
- desc 'Generate documentation for the fat_model_auth plugin.'
17
- Rake::RDocTask.new(:rdoc) do |rdoc|
18
- rdoc.rdoc_dir = 'rdoc'
19
- rdoc.title = 'FatModelAuth'
20
- rdoc.options << '--line-numbers' << '--inline-source'
21
- rdoc.rdoc_files.include('README')
22
- rdoc.rdoc_files.include('lib/**/*.rb')
23
- end
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 2.0.0
@@ -1,8 +0,0 @@
1
- require 'test_helper'
2
-
3
- class FatModelAuthTest < ActiveSupport::TestCase
4
- # Replace this with your real tests.
5
- test "the truth" do
6
- assert true
7
- end
8
- end
data/test/test_helper.rb DELETED
@@ -1,3 +0,0 @@
1
- require 'rubygems'
2
- require 'active_support'
3
- require 'active_support/test_case'