sinatra_resource 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data/.document +5 -0
  2. data/.gitignore +7 -0
  3. data/LICENSE +20 -0
  4. data/README.mdown +28 -0
  5. data/Rakefile +34 -0
  6. data/VERSION +1 -0
  7. data/examples/datacatalog/Rakefile +23 -0
  8. data/examples/datacatalog/app.rb +15 -0
  9. data/examples/datacatalog/config/config.rb +66 -0
  10. data/examples/datacatalog/config/config.yml +11 -0
  11. data/examples/datacatalog/config.ru +6 -0
  12. data/examples/datacatalog/lib/base.rb +9 -0
  13. data/examples/datacatalog/lib/resource.rb +73 -0
  14. data/examples/datacatalog/lib/roles.rb +15 -0
  15. data/examples/datacatalog/models/categorization.rb +31 -0
  16. data/examples/datacatalog/models/category.rb +28 -0
  17. data/examples/datacatalog/models/source.rb +33 -0
  18. data/examples/datacatalog/models/user.rb +51 -0
  19. data/examples/datacatalog/resources/categories.rb +32 -0
  20. data/examples/datacatalog/resources/sources.rb +35 -0
  21. data/examples/datacatalog/resources/users.rb +26 -0
  22. data/examples/datacatalog/tasks/db.rake +29 -0
  23. data/examples/datacatalog/tasks/test.rake +16 -0
  24. data/examples/datacatalog/test/helpers/assertions/assert_include.rb +17 -0
  25. data/examples/datacatalog/test/helpers/assertions/assert_not_include.rb +17 -0
  26. data/examples/datacatalog/test/helpers/lib/model_factories.rb +49 -0
  27. data/examples/datacatalog/test/helpers/lib/model_helpers.rb +30 -0
  28. data/examples/datacatalog/test/helpers/lib/request_helpers.rb +53 -0
  29. data/examples/datacatalog/test/helpers/model_test_helper.rb +5 -0
  30. data/examples/datacatalog/test/helpers/resource_test_helper.rb +5 -0
  31. data/examples/datacatalog/test/helpers/shared/api_keys.rb +48 -0
  32. data/examples/datacatalog/test/helpers/shared/common_body_responses.rb +15 -0
  33. data/examples/datacatalog/test/helpers/shared/status_codes.rb +61 -0
  34. data/examples/datacatalog/test/helpers/test_cases/model_test_case.rb +6 -0
  35. data/examples/datacatalog/test/helpers/test_cases/resource_test_case.rb +36 -0
  36. data/examples/datacatalog/test/helpers/test_helper.rb +36 -0
  37. data/examples/datacatalog/test/models/categorization_test.rb +40 -0
  38. data/examples/datacatalog/test/models/category_test.rb +35 -0
  39. data/examples/datacatalog/test/models/source_test.rb +37 -0
  40. data/examples/datacatalog/test/models/user_test.rb +77 -0
  41. data/examples/datacatalog/test/resources/categories/categories_delete_test.rb +112 -0
  42. data/examples/datacatalog/test/resources/categories/categories_get_many_test.rb +58 -0
  43. data/examples/datacatalog/test/resources/categories/categories_get_one_test.rb +75 -0
  44. data/examples/datacatalog/test/resources/categories/categories_post_test.rb +135 -0
  45. data/examples/datacatalog/test/resources/categories/categories_put_test.rb +140 -0
  46. data/examples/datacatalog/test/resources/sources/sources_delete_test.rb +112 -0
  47. data/examples/datacatalog/test/resources/sources/sources_get_many_test.rb +58 -0
  48. data/examples/datacatalog/test/resources/sources/sources_get_one_test.rb +74 -0
  49. data/examples/datacatalog/test/resources/sources/sources_post_test.rb +184 -0
  50. data/examples/datacatalog/test/resources/sources/sources_put_test.rb +227 -0
  51. data/examples/datacatalog/test/resources/users/users_delete_test.rb +134 -0
  52. data/examples/datacatalog/test/resources/users/users_get_many_test.rb +111 -0
  53. data/examples/datacatalog/test/resources/users/users_get_one_test.rb +75 -0
  54. data/examples/datacatalog/test/resources/users/users_post_test.rb +142 -0
  55. data/examples/datacatalog/test/resources/users/users_put_test.rb +171 -0
  56. data/lib/builder/helpers.rb +319 -0
  57. data/lib/builder/mongo_helpers.rb +70 -0
  58. data/lib/builder.rb +84 -0
  59. data/lib/exceptions.rb +10 -0
  60. data/lib/resource.rb +171 -0
  61. data/lib/roles.rb +163 -0
  62. data/lib/sinatra_resource.rb +6 -0
  63. data/notes/keywords.mdown +1 -0
  64. data/notes/permissions.mdown +181 -0
  65. data/notes/questions.mdown +18 -0
  66. data/notes/see_also.mdown +3 -0
  67. data/notes/synonyms.mdown +7 -0
  68. data/notes/to_do.mdown +7 -0
  69. data/notes/uniform_interface.mdown +22 -0
  70. data/sinatra_resource.gemspec +183 -0
  71. data/spec/sinatra_resource_spec.rb +7 -0
  72. data/spec/spec_helper.rb +9 -0
  73. data/tasks/spec.rake +13 -0
  74. data/tasks/yard.rake +13 -0
  75. metadata +253 -0
@@ -0,0 +1,75 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../helpers/resource_test_helper')
2
+
3
+ class UsersGetOneResourceTest < ResourceTestCase
4
+
5
+ def app; DataCatalog::Users end
6
+
7
+ before do
8
+ @user = create_user
9
+ end
10
+
11
+ after do
12
+ @user.destroy
13
+ end
14
+
15
+ context "get /:id" do
16
+ context "anonymous" do
17
+ before do
18
+ get "/#{@user.id}"
19
+ end
20
+
21
+ use "return 401 because the API key is missing"
22
+ end
23
+
24
+ context "incorrect API key" do
25
+ before do
26
+ get "/#{@user.id}", :api_key => BAD_API_KEY
27
+ end
28
+
29
+ use "return 401 because the API key is invalid"
30
+ end
31
+ end
32
+
33
+ %w(basic curator admin).each do |role|
34
+ context "#{role} : get /:fake_id" do
35
+ before do
36
+ get "/#{FAKE_ID}", :api_key => api_key_for(role)
37
+ end
38
+
39
+ use "return 404 Not Found"
40
+ use "return an empty response body"
41
+ end
42
+ end
43
+
44
+ %w(basic curator).each do |role|
45
+ context "#{role} : get /:id" do
46
+ before do
47
+ get "/#{@user.id}", :api_key => api_key_for(role)
48
+ end
49
+
50
+ use "return 200 Ok"
51
+ doc_properties %w(name id created_at updated_at)
52
+ end
53
+ end
54
+
55
+ context "owner : get /:id" do
56
+ before do
57
+ get "/#{@user.id}", :api_key => @user._api_key
58
+ end
59
+
60
+ use "return 200 Ok"
61
+ doc_properties %w(name email role _api_key id created_at updated_at)
62
+ end
63
+
64
+ %w(admin).each do |role|
65
+ context "#{role} : get /:id" do
66
+ before do
67
+ get "/#{@user.id}", :api_key => api_key_for(role)
68
+ end
69
+
70
+ use "return 200 Ok"
71
+ doc_properties %w(name email role _api_key id created_at updated_at)
72
+ end
73
+ end
74
+
75
+ end
@@ -0,0 +1,142 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../helpers/resource_test_helper')
2
+
3
+ class UsersPostResourceTest < ResourceTestCase
4
+
5
+ include DataCatalog
6
+
7
+ def app; Users end
8
+
9
+ before do
10
+ @user_count = User.all.length
11
+ @valid_params = {
12
+ :name => "New User",
13
+ :role => "basic"
14
+ }
15
+ @extra_admin_params = {
16
+ :role => "basic",
17
+ :_api_key => "222200004444"
18
+ }
19
+ end
20
+
21
+ shared "no new users" do
22
+ test "should not change number of user documents in database" do
23
+ assert_equal @user_count, User.all.length
24
+ end
25
+ end
26
+
27
+ shared "one new user" do
28
+ test "should add one user document to database" do
29
+ assert_equal @user_count + 1, User.all.length
30
+ end
31
+ end
32
+
33
+ shared "correct Location header" do
34
+ test "should set Location header correctly" do
35
+ base_uri = Config.environment_config["base_uri"]
36
+ path = %(/users/#{parsed_response_body["id"]})
37
+ expected = URI.join(base_uri, path).to_s
38
+ assert_equal expected, last_response.headers['Location']
39
+ end
40
+ end
41
+
42
+ context "post /" do
43
+ context "anonymous" do
44
+ before do
45
+ post "/", @valid_params
46
+ end
47
+
48
+ use "return 401 because the API key is missing"
49
+ use "no new users"
50
+ end
51
+
52
+ context "incorrect API key" do
53
+ before do
54
+ post "/", @valid_params.merge(:api_key => BAD_API_KEY)
55
+ end
56
+
57
+ use "return 401 because the API key is invalid"
58
+ use "no new users"
59
+ end
60
+ end
61
+
62
+ %w(basic curator).each do |role|
63
+ [:name, :role].each do |missing|
64
+ context "#{role} : post / but missing #{missing}" do
65
+ before do
66
+ post "/", valid_params_for(role).delete_if { |k, v| k == missing }
67
+ end
68
+
69
+ use "return 401 Unauthorized"
70
+ use "no new users"
71
+ end
72
+ end
73
+
74
+ [:role, :_api_key, :id, :created_at, :updated_at].each do |invalid|
75
+ context "#{role} : post / but with #{invalid}" do
76
+ before do
77
+ post "/", valid_params_for(role).merge(invalid => 9)
78
+ end
79
+
80
+ use "return 401 Unauthorized"
81
+ use "no new users"
82
+ end
83
+ end
84
+
85
+ context "#{role} : post / with valid params" do
86
+ before do
87
+ post "/", valid_params_for(role)
88
+ end
89
+
90
+ use "return 401 Unauthorized"
91
+ use "no new users"
92
+ end
93
+ end
94
+
95
+ %w(admin).each do |role|
96
+ [:name, :role].each do |missing|
97
+ context "#{role} : post / but missing #{missing}" do
98
+ before do
99
+ post "/", valid_params_for(role).
100
+ merge(@extra_admin_params).delete_if { |k, v| k == missing }
101
+ end
102
+
103
+ use "return 400 Bad Request"
104
+ use "no new users"
105
+ missing_param missing
106
+ end
107
+ end
108
+
109
+ [:id, :created_at, :updated_at].each do |invalid|
110
+ context "#{role} : post / but with #{invalid}" do
111
+ before do
112
+ post "/", valid_params_for(role).
113
+ merge(@extra_admin_params).merge(invalid => 9)
114
+ end
115
+
116
+ use "return 400 Bad Request"
117
+ use "no new users"
118
+ invalid_param invalid
119
+ end
120
+ end
121
+
122
+ context "#{role} : post / with valid params" do
123
+ before do
124
+ post "/", valid_params_for(role).merge(@extra_admin_params)
125
+ end
126
+
127
+ use "return 201 Created"
128
+ use "correct Location header"
129
+ use "one new user"
130
+ doc_properties %w(name email role _api_key id created_at updated_at)
131
+
132
+ test "should set all fields in database" do
133
+ user = User.find_by_id(parsed_response_body["id"])
134
+ raise "Cannot find user" unless user
135
+ @valid_params.merge(@extra_admin_params).each_pair do |key, value|
136
+ assert_equal value, user[key]
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ end
@@ -0,0 +1,171 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../helpers/resource_test_helper')
2
+
3
+ class UsersPutResourceTest < ResourceTestCase
4
+
5
+ include DataCatalog
6
+
7
+ def app; Users end
8
+
9
+ before do
10
+ @user = create_user
11
+ @user_copy = @user.dup
12
+ @valid_params = {
13
+ :name => "Changed User",
14
+ :role => "curator"
15
+ }
16
+ @extra_admin_params = {
17
+ :_api_key => "222200004444"
18
+ }
19
+ end
20
+
21
+ after do
22
+ @user.destroy
23
+ end
24
+
25
+ shared "user unchanged" do
26
+ test "should not change user in database" do
27
+ assert_equal @user_copy, User.find_by_id(@user.id)
28
+ end
29
+ end
30
+
31
+ context "put /:id" do
32
+ context "anonymous" do
33
+ before do
34
+ put "/#{@user.id}", @valid_params
35
+ end
36
+
37
+ use "return 401 because the API key is missing"
38
+ use "user unchanged"
39
+ end
40
+
41
+ context "incorrect API key" do
42
+ before do
43
+ put "/#{@user.id}", @valid_params.merge(:api_key => BAD_API_KEY)
44
+ end
45
+
46
+ use "return 401 because the API key is invalid"
47
+ use "user unchanged"
48
+ end
49
+ end
50
+
51
+ %w(basic curator).each do |role|
52
+ [:created_at, :updated_at].each do |invalid|
53
+ context "#{role} : put / but with #{invalid}" do
54
+ before do
55
+ put "/#{@user.id}", valid_params_for(role).
56
+ merge(@extra_admin_params).merge(invalid => 9)
57
+ end
58
+
59
+ use "return 401 Unauthorized"
60
+ use "user unchanged"
61
+ end
62
+ end
63
+
64
+ [:name, :role].each do |erase|
65
+ context "#{role} : put / but blanking out #{erase}" do
66
+ before do
67
+ put "/#{@user.id}", valid_params_for(role).
68
+ merge(@extra_admin_params).merge(erase => "")
69
+ end
70
+
71
+ use "return 401 Unauthorized"
72
+ use "user unchanged"
73
+ end
74
+ end
75
+
76
+ [:name, :role].each do |missing|
77
+ context "#{role} : put /:id without #{missing}" do
78
+ before do
79
+ put "/#{@user.id}", valid_params_for(role).
80
+ merge(@extra_admin_params).delete_if { |k, v| k == missing }
81
+ end
82
+
83
+ use "return 401 Unauthorized"
84
+ use "user unchanged"
85
+ end
86
+ end
87
+
88
+ context "#{role} : put /:id with valid params" do
89
+ before do
90
+ put "/#{@user.id}", valid_params_for(role).merge(@extra_admin_params)
91
+ end
92
+
93
+ use "return 401 Unauthorized"
94
+ use "user unchanged"
95
+ end
96
+ end
97
+
98
+ %w(admin).each do |role|
99
+ [:created_at, :updated_at].each do |invalid|
100
+ context "#{role} : put / but with #{invalid}" do
101
+ before do
102
+ put "/#{@user.id}", valid_params_for(role).
103
+ merge(@extra_admin_params).merge(invalid => 9)
104
+ end
105
+
106
+ use "return 400 Bad Request"
107
+ use "user unchanged"
108
+ invalid_param invalid
109
+ end
110
+ end
111
+
112
+ [:name, :role].each do |erase|
113
+ context "#{role} : put / but blanking out #{erase}" do
114
+ before do
115
+ put "/#{@user.id}", valid_params_for(role).
116
+ merge(@extra_admin_params).merge(erase => "")
117
+ end
118
+
119
+ use "return 400 Bad Request"
120
+ use "user unchanged"
121
+ missing_param erase
122
+ end
123
+ end
124
+
125
+ context "#{role} : put /:id with no parameters" do
126
+ before do
127
+ put "/#{@user.id}", :api_key => api_key_for(role)
128
+ end
129
+
130
+ use "return 400 because no parameters were given"
131
+ use "user unchanged"
132
+ end
133
+
134
+ [:name, :role].each do |missing|
135
+ context "#{role} : put /:id without #{missing}" do
136
+ before do
137
+ put "/#{@user.id}", valid_params_for(role).
138
+ merge(@extra_admin_params).delete_if { |k, v| k == missing }
139
+ end
140
+
141
+ use "return 200 Ok"
142
+ doc_properties %w(name email role _api_key id created_at updated_at)
143
+
144
+ test "should change correct fields in database" do
145
+ user = User.find_by_id(@user.id)
146
+ @valid_params.merge(@extra_admin_params).each_pair do |key, value|
147
+ assert_equal(value, user[key]) if key != missing
148
+ end
149
+ assert_equal @user_copy[missing], user[missing]
150
+ end
151
+ end
152
+ end
153
+
154
+ context "#{role} : put /:id with valid params" do
155
+ before do
156
+ put "/#{@user.id}", valid_params_for(role).merge(@extra_admin_params)
157
+ end
158
+
159
+ use "return 200 Ok"
160
+ doc_properties %w(name email role _api_key id created_at updated_at)
161
+
162
+ test "should change all fields in database" do
163
+ user = User.find_by_id(@user.id)
164
+ @valid_params.merge(@extra_admin_params).each_pair do |key, value|
165
+ assert_equal value, user[key]
166
+ end
167
+ end
168
+ end
169
+ end
170
+
171
+ end
@@ -0,0 +1,319 @@
1
+ module SinatraResource
2
+
3
+ class Builder
4
+
5
+ module Helpers
6
+
7
+ # Build a resource, based on +document+, appropriate for +role+.
8
+ #
9
+ # @param [Symbol] role
10
+ # a role (such as :anonymous, :basic, or :admin)
11
+ #
12
+ # @param [MongoMapper::Document] document
13
+ #
14
+ # @return [Hash<String => Object>]
15
+ def build_resource(role, document)
16
+ resource = {}
17
+ config[:properties].each_pair do |property, hash|
18
+ if authorized?(:read, role, property)
19
+ resource[property.to_s] = value(property, document, hash)
20
+ end
21
+ end
22
+ resource
23
+ end
24
+
25
+ # Builds a list of resources, based on +documents+, using the
26
+ # appropriate role for each document. (Delegates to +lookup_role+.)
27
+ #
28
+ # @param [Array<MongoMapper::Document>] documents
29
+ #
30
+ # @param [String] api_key
31
+ #
32
+ # @return [Array<Hash<String => Object>>]
33
+ def build_resources(documents)
34
+ documents.map do |document|
35
+ build_resource(lookup_role(document), document)
36
+ end
37
+ end
38
+
39
+ # Halt unless the current params are ok for +action+ and +role+.
40
+ #
41
+ # @param [Symbol] action
42
+ # :read, :create, :update, or :delete
43
+ #
44
+ # @param [Symbol] role
45
+ # a role (such as :anonymous, :basic, or :admin)
46
+ #
47
+ # @return [undefined]
48
+ def check_params(action, role)
49
+ params_check_action(action)
50
+ params_check_action_and_role(action, role)
51
+ end
52
+
53
+ # Halt unless the current role has permission to carry out +action+
54
+ #
55
+ # @param [Symbol] action
56
+ # :read, :create, :update, or :delete
57
+ #
58
+ # @param [Symbol] role
59
+ # a role (such as :anonymous, :basic, or :admin)
60
+ #
61
+ # @return [undefined]
62
+ def check_permission(action, role)
63
+ before_authorization(action, role)
64
+ unless authorized?(action, role)
65
+ error 401, convert(body_for(:unauthorized))
66
+ end
67
+ end
68
+
69
+ # Convert +object+ to desired format.
70
+ #
71
+ # For example, an application might want to convert +object+ to JSON or
72
+ # XML.
73
+ #
74
+ # Applications must override this method.
75
+ #
76
+ # @param [Object] object
77
+ #
78
+ # @return [String]
79
+ def convert
80
+ raise NotImplementedError
81
+ end
82
+
83
+ # Display +object+ as appropriate for +action+.
84
+ #
85
+ # @param [Object] object
86
+ #
87
+ # @return [String]
88
+ def display(action, object)
89
+ case action
90
+ when :read
91
+ when :create
92
+ response.status = 201
93
+ path = config[:path] + %(/#{object["id"]})
94
+ response.headers['Location'] = full_uri(path)
95
+ when :update
96
+ when :delete
97
+ response.status = 204
98
+ end
99
+ convert(object)
100
+ end
101
+
102
+ # Convert a path to a full URI.
103
+ #
104
+ # Applications must override this method.
105
+ #
106
+ # @param [String] path
107
+ #
108
+ # @return [String]
109
+ def full_uri(path)
110
+ raise NotImplementedError
111
+ end
112
+
113
+ # Get role, using +id+ if specified. Delegates to +lookup_role+.
114
+ #
115
+ # When +id+ is present, it can help determine 'relative' roles such
116
+ # as 'ownership' of the current user of a particular document.
117
+ #
118
+ # @param [String, nil] id
119
+ #
120
+ # @return [Symbol]
121
+ def get_role(id=nil)
122
+ lookup_role(id ? config[:model].find_by_id(id) : nil)
123
+ end
124
+
125
+ # Return the minimum role required for +action+, and, if specified,
126
+ # +property+.
127
+ #
128
+ # @param [Symbol] action
129
+ # :read, :create, :update, or :delete
130
+ #
131
+ # @return [Symbol]
132
+ # a role (such as :anonymous, :basic, or :admin)
133
+ def minimum_role(action, property=nil)
134
+ if property.nil?
135
+ config[:permission][to_read_or_modify(action)]
136
+ else
137
+ config[:properties][property][to_r_or_w(action)]
138
+ end || :anonymous
139
+ end
140
+
141
+ protected
142
+
143
+ # Is +role+ authorized for +action+, and, if specified, +property+?
144
+ #
145
+ # @param [Symbol] role
146
+ # a role (such as :anonymous, :basic, or :admin)
147
+ #
148
+ # @param [Symbol] action
149
+ # :read, :create, :update, or :delete
150
+ #
151
+ # @param [Symbol] property
152
+ # a property of a resource
153
+ #
154
+ # @return [Boolean]
155
+ def authorized?(action, role, property=nil)
156
+ klass = config[:roles]
157
+ klass.validate_role(role)
158
+ klass.satisfies?(role, minimum_role(action, property))
159
+ end
160
+
161
+ # Application-level hook that runs as part of +check_permission+,
162
+ # before +authorized?(action, role)+ is called.
163
+ #
164
+ # For example, an application might want to throw custom errors
165
+ # in certain situations before +authorized?+ runs.
166
+ #
167
+ # Applications must override this method.
168
+ #
169
+ # @param [Symbol] action
170
+ # :read, :create, :update, or :delete
171
+ #
172
+ # @param [Symbol] role
173
+ # a role (such as :anonymous, :basic, or :admin)
174
+ #
175
+ # @return [String]
176
+ def before_authorization(action, role)
177
+ raise NotImplementedError
178
+ end
179
+
180
+ # Default body message for a +situation+
181
+ #
182
+ # @param [Symbol] situation
183
+ #
184
+ # @param [Object] object
185
+ #
186
+ # @return [String]
187
+ def body_for(situation, object=nil)
188
+ case situation
189
+ when :errors
190
+ { "errors" => object }
191
+ when :internal_server_error
192
+ ""
193
+ when :invalid_document
194
+ { "errors" => object.errors.errors }
195
+ when :invalid_params
196
+ { "errors" => { "invalid_params" => object } }
197
+ when :no_params
198
+ { "errors" => "no_params" }
199
+ when :non_empty_params
200
+ { "errors" => "non_empty_params" }
201
+ when :not_found
202
+ ""
203
+ when :unauthorized
204
+ ""
205
+ end
206
+ end
207
+
208
+ # Lookup the rol, using +document+ if specified.
209
+ #
210
+ # Applications must override this method.
211
+ #
212
+ # @param [MongoMapper::Document, nil] document
213
+ #
214
+ # @return [Symbol]
215
+ def lookup_role(document=nil)
216
+ raise NotImplementedError
217
+ end
218
+
219
+ # Are the params suitable for +action+? Raise 400 Bad Request if not.
220
+ #
221
+ # @param [Symbol] action
222
+ # :read, :create, :update, or :delete
223
+ #
224
+ # @return [undefined]
225
+ def params_check_action(action)
226
+ case action
227
+ when :read
228
+ unless params.empty?
229
+ error 400, convert(body_for(:non_empty_params))
230
+ end
231
+ when :create
232
+ # No need to complain. If there are problems,
233
+ # params_check_action_and_role will catch them.
234
+ when :update
235
+ if params.empty?
236
+ error 400, convert(body_for(:no_params))
237
+ end
238
+ when :delete
239
+ unless params.empty?
240
+ error 400, convert(body_for(:non_empty_params))
241
+ end
242
+ end
243
+ end
244
+
245
+ # Checks each parameter to make sure it is authorized for +action+ and
246
+ # +role+. Raises a 400 Bad Request if not authorized.
247
+ #
248
+ # @param [Symbol] action
249
+ # :read, :create, :update, or :delete
250
+ #
251
+ # @param [Symbol] role
252
+ # a role (such as :anonymous, :basic, or :admin)
253
+ #
254
+ # @return [undefined]
255
+ def params_check_action_and_role(action, role)
256
+ invalid = []
257
+ params.each_pair do |property, value|
258
+ invalid << property if !authorized?(action, role, property.intern)
259
+ end
260
+ unless invalid.empty?
261
+ error 400, convert(body_for(:invalid_params, invalid))
262
+ end
263
+ end
264
+
265
+ # Converts +action+ to :r or :w (i.e. read or write).
266
+ #
267
+ # @param [Symbol] action
268
+ # :read, :create, or :update
269
+ #
270
+ # @return [Symbol]
271
+ # :r or :w
272
+ def to_r_or_w(action)
273
+ case action
274
+ when :read then :r
275
+ when :create then :w
276
+ when :update then :w
277
+ else raise "Unexpected action : #{action.inspect}"
278
+ end
279
+ end
280
+
281
+ # Converts +action+ to (:read or :modify).
282
+ #
283
+ # @param [Symbol] action
284
+ # :read, :create, :update, or :delete
285
+ #
286
+ # @return [Symbol]
287
+ # :read or :modify
288
+ def to_read_or_modify(action)
289
+ case action
290
+ when :read then :read
291
+ when :create then :modify
292
+ when :update then :modify
293
+ when :delete then :modify
294
+ else raise "Unexpected action : #{action.inspect}"
295
+ end
296
+ end
297
+
298
+ # Lookup +attribute+ in +document+
299
+ #
300
+ # @param [Symbol] attribute
301
+ # an attribute of +document+
302
+ #
303
+ # @param [MongoMapper::Document] document
304
+ #
305
+ # @return [undefined]
306
+ def value(attribute, document, property_hash)
307
+ proc = property_hash[:read_proc]
308
+ if proc
309
+ proc.call(document)
310
+ else
311
+ document[attribute == :id ? :_id : attribute]
312
+ end
313
+ end
314
+
315
+ end
316
+
317
+ end
318
+
319
+ end