kant 0.0.3 → 0.0.4

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: d0b65ae77365d3fb81725cb1dad2634d25b51640
4
- data.tar.gz: dac368c947e0ab658ce42dbc0570214d218dbec5
3
+ metadata.gz: 4405afa9ea78fb2fcee60f09c4f31521626ae1b1
4
+ data.tar.gz: b337033ed3ecc3119602b260a0c9aff1c14013ed
5
5
  SHA512:
6
- metadata.gz: 4a6684cc5fbbe9d9a90a8b14aa7c32b75dfc112eac379630c383646679f9cf0588e932057ad0eb585a2ea6ec7108287342cf73ca458aacad83cc8d82d3338628
7
- data.tar.gz: bd2b8391077f3f7ec7b13b03375bf6e4310fe9f57ff3dc957a9be82785cfc2f786a575f35f216eefc0c27a61a3372496d9d2dfa728b063ed911cff30e8362caa
6
+ metadata.gz: 6fed5522437eab76c2d21f814ebbeeaa472acdc11605ae95ab109e756a3d31d1f52330d63577d0baa6506ca3b08a8da853458a39d9e20d555c1fe6ef2e850b31
7
+ data.tar.gz: 1440cbd44f47d426e31832e65eaa21a7cbf439042ea17328808273b9a5bc97fed20a46b4a6e9425195541ec1e0c549a3173ed2c52c5293f2e2484ccf4b05a4b8
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Kant v0.0.3
1
+ # Kant v0.0.4
2
2
 
3
3
  Kant is a tiny authorization library for your Ruby (especially Rails and/or
4
4
  ActiveRecord) projects.
@@ -37,12 +37,12 @@ module Kant
37
37
  #
38
38
  # ability.accessible(:read, Content)
39
39
  # # => a Content scope
40
- def accessible(action, scope)
40
+ def accessible(action, scope, *rest)
41
41
  abilities = resolve_scope(scope)
42
42
  _scope_method = scope_method(abilities, action)
43
43
 
44
44
  if _scope_method
45
- abilities.send(_scope_method, scope, user)
45
+ abilities.send(_scope_method, scope, user, *rest)
46
46
  else
47
47
  scope.none
48
48
  end
data/lib/kant/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Kant
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
2
  require 'kant/policy_access'
3
+ require 'kant/access_denied'
3
4
 
4
5
  describe Kant::PolicyAccess do
5
6
  setup_models
@@ -99,6 +100,7 @@ describe Kant::PolicyAccess do
99
100
 
100
101
  describe "#accessible" do
101
102
  let(:user) { User.create!(email: 'foo@bar.com') }
103
+ let(:another_user) { User.create!(email: 'foo@baz.com') }
102
104
  subject(:policy_access) { Kant::PolicyAccess.new(user) }
103
105
 
104
106
  it "delegates to a Policy module" do
@@ -130,6 +132,94 @@ describe Kant::PolicyAccess do
130
132
 
131
133
  expect(policy_access.accessible(:read, Todo)).to eq(Todo.none)
132
134
  end
135
+
136
+ # The motivation here is that, when performing authorization for "index"
137
+ # actions, this often involves some context. For example, the user might be
138
+ # listing all the todos under a particular project (GET /projects/1/todos).
139
+ # In a lot of cases it might be possible to define an ActiveRecord or SQL
140
+ # query that describes what records the user can access regardless of
141
+ # context, but in some cases this might result in a very complicated query.
142
+ # (Unfortunately, the example below really doesn't really do the motivation
143
+ # justice.)
144
+ #
145
+ # Imagine instead that a user can normally only access their own User
146
+ # record (the check being `user == me`). However, when the user is part of
147
+ # a project they can also see other users in the company that the project
148
+ # is a part of. (For example, so that they can send a DM to a user.)
149
+ #
150
+ # - Company
151
+ # - has many Projects
152
+ # - has many Users
153
+ #
154
+ # Imagine what the query would look like to return all the users I can
155
+ # message...
156
+ #
157
+ # def self.readable_for_messaging(users, me)
158
+ # my_companies = Company.joins(:projects).merge(me.projects)
159
+ # my_companies_projects = Project.joins(:company).merge(my_companies)
160
+ # my_companies_users = User.joins(:projects).merge(my_companies_projects)
161
+ # users.merge(my_companies_users)
162
+ # end
163
+ #
164
+ # Some notes here:
165
+ #
166
+ # 1. This honestly isn't such a gross example, in production this logic can
167
+ # get much, much worse.
168
+ # 2. Even so, you can see it gets pretty complicated.
169
+ # 3. In practice what we have to do after all this is query the resulting
170
+ # scope for users in a particular company... which means more gross queries.
171
+ #
172
+ # Instead, by having extra params in the *able function, we can specify a
173
+ # context (typically this will probably match the shape of the endpoint, so
174
+ # if your endpoint is /companies/1/users then your *able function will
175
+ # probably take an extra `companies:` param).
176
+ #
177
+ # def self.readable_for_messaging(users, me, company:)
178
+ # my_companies = Company.joins(:projects).merge(me.projects)
179
+ # if !my_companies.where(id: company.id).any?
180
+ # fail Kant::AccessDenied, "no access"
181
+ # end
182
+ #
183
+ # users.joins(:projects).where(projects: { company_id: company.id })
184
+ # end
185
+ it "passes along other params to the *able method" do
186
+ # module TodoPolicy
187
+ # def self.readable_as_owner(todos, user, project:)
188
+ # if project.owner_id == user.id
189
+ # todos.where(project_id: project_id, completed: true)
190
+ # else
191
+ # fail Kant::AccessDenied, "user does not have access to this project"
192
+ # end
193
+ # end
194
+ # end
195
+ todo_policy = Class.new do
196
+ define_singleton_method(:readable_as_owner) do |todos, user, project:|
197
+ if project.owner_id == user.id
198
+ todos.where(project_id: project.id, completed: true)
199
+ else
200
+ fail Kant::AccessDenied, "user does not have access to this project"
201
+ end
202
+ end
203
+ end
204
+
205
+ stub_const("TodoPolicy", todo_policy)
206
+
207
+ my_project = Project.create!(owner: user)
208
+ another_project = Project.create!(owner: another_user)
209
+ my_complete_todo = Todo.create!(project: my_project, completed: true)
210
+ my_incomplete_todo = Todo.create!(project: my_project, completed: false)
211
+ another_complete_todo = Todo.create!(project: another_project, completed: true)
212
+
213
+ expect{
214
+ policy_access.accessible(:read_as_owner, Todo)
215
+ }.to raise_error(ArgumentError)
216
+
217
+ expect(policy_access.accessible(:read_as_owner, Todo, project: my_project)).to eq([my_complete_todo])
218
+
219
+ expect{
220
+ policy_access.accessible(:read_as_owner, Todo, project: another_project)
221
+ }.to raise_error(Kant::AccessDenied)
222
+ end
133
223
  end
134
224
 
135
225
  describe "the policies_module option in initializer" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Przepiora
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-07 00:00:00.000000000 Z
11
+ date: 2018-05-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler