openstax_utilities 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +15 -15
- data/lib/openstax/utilities/access_policy.rb +2 -1
- data/lib/openstax/utilities/version.rb +1 -1
- data/lib/openstax_utilities.rb +0 -2
- metadata +2 -8
- data/lib/openstax/utilities/controller_extensions.rb +0 -47
- data/lib/openstax/utilities/roar.rb +0 -135
- data/spec/lib/openstax/utilities/controller_extensions_spec.rb +0 -29
- data/spec/lib/openstax/utilities/extended_controller_spec.rb +0 -82
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YmY4Y2JiYmY4YTEzOTIyOTU5OTJiNjAxZjU5M2ViZWRlMWVmOWZlMQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZjczNDQxMjExMGQ5NmRiYTZkMDJmOTM1ZmEzMDM5ZDQ5YjdhN2Y1Mg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
OTVlMGExOGJlMzM5MmQ5ZWI3MzBjMmE4Nzk3YmMyMzNjNzBmNDBkYzZjMTVi
|
10
|
+
ZDQ3ZjkxYzI0YjA5ZTI1YzIyODdmMTNkZTViMGVhNDUzMWE2ODQ0OWU0YjNk
|
11
|
+
YzYzYzgyNDI1NDMxZGQ1ODU3NjhkZmNhNjE5ZjdlMGJiNTcyNzc=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MGJiMmE2MmYyMjNkNjhhZmNjOWFkZDE0YTJlNDViOWJkNTNkNTc1ZDVjNWY5
|
14
|
+
MzhiMjliODNlY2VhZTQ3MDIxYjBiYmI3M2FjMTJiYjA0OGVhZmQ1MzY5M2I5
|
15
|
+
YzMzYWIyZDRiYmZhNzQzNmJhMjNlZjYyYjM0OGFiYWQ5ZGQyZDE=
|
data/README.md
CHANGED
@@ -1,19 +1,32 @@
|
|
1
1
|
OpenstaxUtilities
|
2
2
|
=================
|
3
3
|
|
4
|
-
A set of common utilities for the various OpenStax projects.
|
4
|
+
A set of common utilities for the various OpenStax projects.
|
5
5
|
|
6
6
|
Documentation available on [rdoc.info](http://rdoc.info/github/openstax/openstax_utilities/master/frames).
|
7
7
|
|
8
8
|
To use this utility engine, include it in your Gemfile.
|
9
9
|
|
10
|
+
## Configuration
|
11
|
+
|
12
|
+
This engine accepts configuration options. These are best added in an initializer:
|
13
|
+
|
14
|
+
```rb
|
15
|
+
OSU.configure do |config|
|
16
|
+
config.<parameter name> = <parameter value>
|
17
|
+
...
|
18
|
+
end
|
19
|
+
```
|
20
|
+
|
21
|
+
See `lib/openstax_utilities.rb` for valid configuration options.
|
22
|
+
|
10
23
|
## Helpers
|
11
24
|
|
12
25
|
This engine's helpers are available in the main application by preceding them with `osu.`, e.g. `osu.section_block('Heading') { "guts" }`
|
13
26
|
|
14
27
|
## Access Policies
|
15
28
|
|
16
|
-
As applications grow to include different kinds of users, including signed-in and anonymous human users, as well as other applications, the logic for controlling which user has which accesses to which resources can grow complex. Controllers certainly aren't the place for this logic. In a case with one kind of User, models *may* be the place for this logic but even then this makes models know way too much about other models.
|
29
|
+
As applications grow to include different kinds of users, including signed-in and anonymous human users, as well as other applications, the logic for controlling which user has which accesses to which resources can grow complex. Controllers certainly aren't the place for this logic. In a case with one kind of User, models *may* be the place for this logic but even then this makes models know way too much about other models.
|
17
30
|
|
18
31
|
Access Policies were created to be a dedicated place to store the logic controlling who has access to what. All other code can ask the `AccessPolicy` class for this info, via the `action_allowed?` or the convenience methods `read_allowed?`, `create_allowed?`, etc. `AccessPolicy` then delegates the access decisions off to other policy classes, of which there is normally one per kind of resource (e.g. a `UserAccessPolicy`, `ContactInfoPolicy`, etc).
|
19
32
|
|
@@ -24,16 +37,3 @@ OSU::AccessPolicy.register(User, UserAccessPolicy)
|
|
24
37
|
```
|
25
38
|
|
26
39
|
This call is typically made after the policy class' definition so that it is called when the Rails application is loaded. We recommend placing the policy classes under `app/access_policies`, as all files under the `app` directory are autoloaded by Rails.
|
27
|
-
|
28
|
-
## Controller Extensions
|
29
|
-
|
30
|
-
The following methods will be added to all controllers:
|
31
|
-
|
32
|
-
`get_model(id_param, klass)` tries to use the id_param to return the model in question for
|
33
|
-
restful actions, or a new instance of klass if the id could not be found.
|
34
|
-
(e.g. on :new, :create and even :index)
|
35
|
-
By default, id_param is :id and klass is controller_name.classify.constantize.
|
36
|
-
|
37
|
-
`self.require_restful_actions_allowed!(options)` adds a before_filter that calls AccessPolicy.require_action_allowed! for all restful actions except :index. So by default it will add checks to :show, :new, :create, :edit, :update and :destroy.
|
38
|
-
options is a hash that contains any desired before_filter options, plus the optional keys :id_param and :model_class, which are passed to get_model instead.
|
39
|
-
By default, options is an empty hash.
|
@@ -32,7 +32,8 @@ module OpenStax
|
|
32
32
|
# If the incoming requestor is an ApiUser, choose to use either its
|
33
33
|
# human_user or its application. If there is a human user involved, it
|
34
34
|
# should always take precedence when testing for access.
|
35
|
-
if defined?(ApiUser) &&
|
35
|
+
if defined?(OpenStax::Api::ApiUser) &&
|
36
|
+
requestor.is_a?(OpenStax::Api::ApiUser)
|
36
37
|
requestor = requestor.human_user ? requestor.human_user : requestor.application
|
37
38
|
end
|
38
39
|
|
data/lib/openstax_utilities.rb
CHANGED
@@ -18,9 +18,7 @@ require "openstax/utilities/network"
|
|
18
18
|
require "openstax/utilities/action_list"
|
19
19
|
require "openstax/utilities/acts_as_numberable"
|
20
20
|
require "openstax/utilities/delegate_access_control"
|
21
|
-
require "openstax/utilities/roar"
|
22
21
|
require "openstax/utilities/access_policy"
|
23
|
-
require "openstax/utilities/controller_extensions"
|
24
22
|
|
25
23
|
require "openstax/utilities/classy_helper"
|
26
24
|
require "openstax/utilities/helpers/misc"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openstax_utilities
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- JP Slavinsky
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-04-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -95,7 +95,6 @@ files:
|
|
95
95
|
- lib/openstax/utilities/blocks/table_cell_block.rb
|
96
96
|
- lib/openstax/utilities/blocks/table_row_block.rb
|
97
97
|
- lib/openstax/utilities/classy_helper.rb
|
98
|
-
- lib/openstax/utilities/controller_extensions.rb
|
99
98
|
- lib/openstax/utilities/delegate_access_control.rb
|
100
99
|
- lib/openstax/utilities/engine.rb
|
101
100
|
- lib/openstax/utilities/enum.rb
|
@@ -106,7 +105,6 @@ files:
|
|
106
105
|
- lib/openstax/utilities/helpers/misc.rb
|
107
106
|
- lib/openstax/utilities/helpers/partials.rb
|
108
107
|
- lib/openstax/utilities/network.rb
|
109
|
-
- lib/openstax/utilities/roar.rb
|
110
108
|
- lib/openstax/utilities/ruby.rb
|
111
109
|
- lib/openstax/utilities/settings.rb
|
112
110
|
- lib/openstax/utilities/text.rb
|
@@ -152,8 +150,6 @@ files:
|
|
152
150
|
- spec/dummy/public/favicon.ico
|
153
151
|
- spec/dummy/script/rails
|
154
152
|
- spec/lib/openstax/utilities/access_policy_spec.rb
|
155
|
-
- spec/lib/openstax/utilities/controller_extensions_spec.rb
|
156
|
-
- spec/lib/openstax/utilities/extended_controller_spec.rb
|
157
153
|
- spec/spec_helper.rb
|
158
154
|
homepage: http://github.com/openstax/openstax_utilities
|
159
155
|
licenses:
|
@@ -220,6 +216,4 @@ test_files:
|
|
220
216
|
- spec/dummy/README.md
|
221
217
|
- spec/dummy/script/rails
|
222
218
|
- spec/lib/openstax/utilities/access_policy_spec.rb
|
223
|
-
- spec/lib/openstax/utilities/controller_extensions_spec.rb
|
224
|
-
- spec/lib/openstax/utilities/extended_controller_spec.rb
|
225
219
|
- spec/spec_helper.rb
|
@@ -1,47 +0,0 @@
|
|
1
|
-
module OpenStax
|
2
|
-
module Utilities
|
3
|
-
module ControllerExtensions
|
4
|
-
def self.included(base)
|
5
|
-
base.extend(ClassMethods)
|
6
|
-
end
|
7
|
-
|
8
|
-
# Tries to find model if id is given, or returns a new model if not
|
9
|
-
def get_model(id_param = nil, klass = nil)
|
10
|
-
id_param ||= :id
|
11
|
-
id = params[id_param]
|
12
|
-
klass ||= controller_name.classify.constantize
|
13
|
-
id.nil? ? klass.new : klass.find(id)
|
14
|
-
end
|
15
|
-
|
16
|
-
module ClassMethods
|
17
|
-
# Calls AccessPolicy.require_action_allowed! on all restful actions
|
18
|
-
# For create and update, the new params are not yet set
|
19
|
-
def require_restful_actions_allowed!(options = {})
|
20
|
-
class_eval do
|
21
|
-
before_filter({:only => [:show, :new, :create, :edit, :update,
|
22
|
-
:destroy]}.merge(options.except(:id_param,
|
23
|
-
:model_class))) do |c|
|
24
|
-
|
25
|
-
case c.action_name
|
26
|
-
when 'show'
|
27
|
-
action = :read
|
28
|
-
when 'new'
|
29
|
-
action = :create
|
30
|
-
when 'edit'
|
31
|
-
action = :update
|
32
|
-
else
|
33
|
-
action = c.action_name.to_sym
|
34
|
-
end
|
35
|
-
|
36
|
-
OSU::AccessPolicy.require_action_allowed!(action,
|
37
|
-
c.current_user, c.get_model(options[:id_param],
|
38
|
-
options[:model_class]))
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
ActionController::Base.send :include, OpenStax::Utilities::ControllerExtensions
|
@@ -1,135 +0,0 @@
|
|
1
|
-
# Copyright 2011-2014 Rice University. Licensed under the Affero General Public
|
2
|
-
# License version 3 or later. See the COPYRIGHT file for details.
|
3
|
-
|
4
|
-
module OpenStax
|
5
|
-
module Utilities
|
6
|
-
|
7
|
-
module Roar
|
8
|
-
|
9
|
-
def self.included(base)
|
10
|
-
base.send :extend, ClassMethods
|
11
|
-
end
|
12
|
-
|
13
|
-
def get_representer(represent_with, model=nil)
|
14
|
-
return nil if represent_with.nil?
|
15
|
-
if represent_with.is_a? Proc
|
16
|
-
represent_with.call(model)
|
17
|
-
else
|
18
|
-
represent_with
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def standard_read(model_klass, id, represent_with=nil)
|
23
|
-
@model = model_klass.find(id)
|
24
|
-
raise SecurityTransgression unless current_user.can_read?(@model)
|
25
|
-
respond_with @model, represent_with: get_representer(represent_with, @model)
|
26
|
-
end
|
27
|
-
|
28
|
-
def standard_update(model_klass, id, represent_with=nil)
|
29
|
-
@model = model_klass.find(id)
|
30
|
-
raise SecurityTransgression unless current_user.can_update?(@model)
|
31
|
-
consume!(@model, represent_with: get_representer(represent_with, @model))
|
32
|
-
|
33
|
-
if @model.save
|
34
|
-
head :no_content
|
35
|
-
else
|
36
|
-
render json: @model.errors, status: :unprocessable_entity
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def standard_create(model_klass, represent_with=nil)
|
41
|
-
standard_nested_create(model_klass, nil, nil, represent_with)
|
42
|
-
end
|
43
|
-
|
44
|
-
def standard_nested_create(model_klass, container_association=nil, container_id=nil, represent_with=nil)
|
45
|
-
@model = model_klass.new()
|
46
|
-
|
47
|
-
if container_association && container_id
|
48
|
-
foreign_key = model_klass.reflect_on_association(container_association).association_foreign_key
|
49
|
-
@model.send(foreign_key + '=', container_id)
|
50
|
-
end
|
51
|
-
|
52
|
-
# Unlike the implications of the representable README, "consume!" can
|
53
|
-
# actually make changes to the database. See http://goo.gl/WVLBqA.
|
54
|
-
# We do want to consume before checking the permissions so we can know
|
55
|
-
# what we're dealing with, but if user doesn't have permission we don't
|
56
|
-
# want to have changed the DB. Wrap in a transaction to protect ourselves.
|
57
|
-
|
58
|
-
model_klass.transaction do
|
59
|
-
consume!(@model, represent_with: get_representer(represent_with, @model))
|
60
|
-
raise SecurityTransgression unless current_user.can_create?(@model)
|
61
|
-
end
|
62
|
-
|
63
|
-
if @model.save
|
64
|
-
respond_with @model, represent_with: get_representer(represent_with, @model), status: :created
|
65
|
-
else
|
66
|
-
render json: @model.errors, status: :unprocessable_entity
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def standard_destroy(model_klass, id)
|
71
|
-
@model = model_klass.find(id)
|
72
|
-
raise SecurityTransgression unless current_user.can_destroy?(@model)
|
73
|
-
|
74
|
-
if @model.destroy
|
75
|
-
head :no_content
|
76
|
-
else
|
77
|
-
render json: @model.errors, status: :unprocessable_entity
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def standard_sort(model_klass)
|
82
|
-
# take array of all IDs or hash of id => position,
|
83
|
-
# regardless build up an array of all IDs in the right order and pass those to sort
|
84
|
-
|
85
|
-
new_positions = params['newPositions']
|
86
|
-
return head :no_content if new_positions.length == 0
|
87
|
-
|
88
|
-
# Can't have duplicate positions or IDs
|
89
|
-
unique_ids = new_positions.collect{|np| np['id']}.uniq
|
90
|
-
unique_positions = new_positions.collect{|np| np['position']}.uniq
|
91
|
-
|
92
|
-
return head :bad_request if unique_ids.length != new_positions.length
|
93
|
-
return head :bad_request if unique_positions.length != new_positions.length
|
94
|
-
|
95
|
-
first = model_klass.where(:id => new_positions[0]['id']).first
|
96
|
-
|
97
|
-
return head :not_found if first.blank?
|
98
|
-
|
99
|
-
originalOrdered = first.me_and_peers.ordered.all
|
100
|
-
|
101
|
-
originalOrdered.each do |item|
|
102
|
-
raise SecurityTransgression unless item.send(:container_column) == originalOrdered[0].send(:container_column) \
|
103
|
-
if item.respond_to?(:container_column)
|
104
|
-
raise SecurityTransgression unless current_user.can_sort?(item)
|
105
|
-
end
|
106
|
-
|
107
|
-
originalOrderedIds = originalOrdered.collect{|sc| sc.id}
|
108
|
-
|
109
|
-
newOrderedIds = Array.new(originalOrderedIds.size)
|
110
|
-
|
111
|
-
new_positions.each do |newPosition|
|
112
|
-
id = newPosition['id'].to_i
|
113
|
-
newOrderedIds[newPosition['position']] = id
|
114
|
-
originalOrderedIds.delete(id)
|
115
|
-
end
|
116
|
-
|
117
|
-
ptr = 0
|
118
|
-
for oldId in originalOrderedIds
|
119
|
-
while !newOrderedIds[ptr].nil?; ptr += 1; end
|
120
|
-
newOrderedIds[ptr] = oldId
|
121
|
-
end
|
122
|
-
|
123
|
-
begin
|
124
|
-
model_klass.sort!(newOrderedIds)
|
125
|
-
rescue Exception => e
|
126
|
-
return head :internal_server_error
|
127
|
-
end
|
128
|
-
|
129
|
-
head :no_content
|
130
|
-
end
|
131
|
-
|
132
|
-
end
|
133
|
-
|
134
|
-
end
|
135
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module OpenStax
|
4
|
-
module Utilities
|
5
|
-
|
6
|
-
describe ControllerExtensions do
|
7
|
-
|
8
|
-
it 'adds get_model to controllers' do
|
9
|
-
|
10
|
-
expect(ApplicationController.new).to respond_to(:get_model)
|
11
|
-
|
12
|
-
expect(UsersController.new).to respond_to(:get_model)
|
13
|
-
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'adds require_restful_actions_allowed! to controllers' do
|
17
|
-
|
18
|
-
expect(ApplicationController).to(
|
19
|
-
respond_to(:require_restful_actions_allowed!))
|
20
|
-
|
21
|
-
expect(UsersController).to respond_to(:require_restful_actions_allowed!)
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
@@ -1,82 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe UsersController, :type => :controller do
|
4
|
-
|
5
|
-
let!(:user) { User.create }
|
6
|
-
|
7
|
-
before(:all) do
|
8
|
-
UsersController.require_restful_actions_allowed!
|
9
|
-
OSU::AccessPolicy.register(User, DummyAccessPolicy)
|
10
|
-
end
|
11
|
-
|
12
|
-
context 'when user visits restful actions' do
|
13
|
-
|
14
|
-
it 'returns the correct resource with get_model' do
|
15
|
-
controller.current_user = user
|
16
|
-
|
17
|
-
get :new
|
18
|
-
expect(controller.get_model).to be_instance_of(User)
|
19
|
-
expect(controller.get_model.id).to be_nil
|
20
|
-
|
21
|
-
get :show, :id => user.id
|
22
|
-
expect(controller.get_model).to eq(user)
|
23
|
-
|
24
|
-
get :new, :user_id => user.id
|
25
|
-
expect(controller.get_model(:user_id)).to eq(user)
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'calls AccessPolicy with the expected arguments' do
|
29
|
-
controller.current_user = user
|
30
|
-
|
31
|
-
DummyAccessPolicy.last_action = nil
|
32
|
-
DummyAccessPolicy.last_requestor = nil
|
33
|
-
DummyAccessPolicy.last_resource = nil
|
34
|
-
|
35
|
-
get :index
|
36
|
-
|
37
|
-
expect(DummyAccessPolicy.last_action).to be_nil
|
38
|
-
expect(DummyAccessPolicy.last_requestor).to be_nil
|
39
|
-
expect(DummyAccessPolicy.last_resource).to be_nil
|
40
|
-
|
41
|
-
get :show, :id => user.id
|
42
|
-
|
43
|
-
expect(DummyAccessPolicy.last_action).to eq(:read)
|
44
|
-
expect(DummyAccessPolicy.last_requestor).to eq(user)
|
45
|
-
expect(DummyAccessPolicy.last_resource).to eq(user)
|
46
|
-
|
47
|
-
get :new
|
48
|
-
|
49
|
-
expect(DummyAccessPolicy.last_action).to eq(:create)
|
50
|
-
expect(DummyAccessPolicy.last_requestor).to eq(user)
|
51
|
-
expect(DummyAccessPolicy.last_resource).to be_instance_of(User)
|
52
|
-
expect(DummyAccessPolicy.last_resource.id).to be_nil
|
53
|
-
|
54
|
-
post :create, :user => user.attributes
|
55
|
-
|
56
|
-
expect(DummyAccessPolicy.last_action).to eq(:create)
|
57
|
-
expect(DummyAccessPolicy.last_requestor).to eq(user)
|
58
|
-
expect(DummyAccessPolicy.last_resource).to be_instance_of(User)
|
59
|
-
expect(DummyAccessPolicy.last_resource.id).to be_nil
|
60
|
-
|
61
|
-
get :edit, :id => user.id, :user => user.attributes
|
62
|
-
|
63
|
-
expect(DummyAccessPolicy.last_action).to eq(:update)
|
64
|
-
expect(DummyAccessPolicy.last_requestor).to eq(user)
|
65
|
-
expect(DummyAccessPolicy.last_resource).to eq(user)
|
66
|
-
|
67
|
-
put :update, :id => user.id, :user => user.attributes
|
68
|
-
|
69
|
-
expect(DummyAccessPolicy.last_action).to eq(:update)
|
70
|
-
expect(DummyAccessPolicy.last_requestor).to eq(user)
|
71
|
-
expect(DummyAccessPolicy.last_resource).to eq(user)
|
72
|
-
|
73
|
-
delete :destroy, :id => user.id
|
74
|
-
|
75
|
-
expect(DummyAccessPolicy.last_action).to eq(:destroy)
|
76
|
-
expect(DummyAccessPolicy.last_requestor).to eq(user)
|
77
|
-
expect(DummyAccessPolicy.last_resource).to eq(user)
|
78
|
-
end
|
79
|
-
|
80
|
-
end
|
81
|
-
|
82
|
-
end
|