introspective_grape 0.5.7 → 0.6.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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +22 -18
  3. data/README.md +2 -0
  4. data/introspective_grape.gemspec +5 -4
  5. data/lib/introspective_grape/api.rb +461 -459
  6. data/lib/introspective_grape/create_helpers.rb +25 -25
  7. data/lib/introspective_grape/traversal.rb +1 -1
  8. data/lib/introspective_grape/validators.rb +36 -36
  9. data/lib/introspective_grape/version.rb +5 -5
  10. data/spec/dummy/Gemfile +23 -22
  11. data/spec/dummy/app/api/api_helpers.rb +38 -37
  12. data/spec/dummy/app/api/dummy_api.rb +61 -61
  13. data/spec/dummy/app/api/permissions_helper.rb +7 -7
  14. data/spec/dummy/app/helpers/current.rb +3 -0
  15. data/spec/dummy/app/models/chat_message.rb +34 -34
  16. data/spec/dummy/app/models/chat_user.rb +16 -16
  17. data/spec/dummy/app/models/location.rb +26 -26
  18. data/spec/dummy/app/models/role.rb +30 -30
  19. data/spec/dummy/app/models/team.rb +14 -9
  20. data/spec/dummy/app/models/user/chatter.rb +79 -79
  21. data/spec/dummy/bin/bundle +3 -3
  22. data/spec/dummy/bin/rails +4 -4
  23. data/spec/dummy/bin/setup +36 -29
  24. data/spec/dummy/bin/update +31 -0
  25. data/spec/dummy/bin/yarn +11 -0
  26. data/spec/dummy/config/application.rb +30 -37
  27. data/spec/dummy/config/boot.rb +3 -6
  28. data/spec/dummy/config/environment.rb +5 -11
  29. data/spec/dummy/config/environments/development.rb +54 -42
  30. data/spec/dummy/config/environments/production.rb +81 -79
  31. data/spec/dummy/config/environments/test.rb +47 -44
  32. data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
  33. data/spec/dummy/config/initializers/assets.rb +14 -11
  34. data/spec/dummy/config/initializers/content_security_policy.rb +25 -0
  35. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -3
  36. data/spec/dummy/config/initializers/inflections.rb +16 -16
  37. data/spec/dummy/config/initializers/new_framework_defaults_5_2.rb +38 -0
  38. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -14
  39. data/spec/dummy/config/locales/en.yml +33 -23
  40. data/spec/dummy/config/storage.yml +34 -0
  41. data/spec/models/image_spec.rb +10 -14
  42. data/spec/requests/project_api_spec.rb +185 -182
  43. data/spec/requests/user_api_spec.rb +221 -221
  44. data/spec/support/request_helpers.rb +22 -21
  45. metadata +20 -157
@@ -1,221 +1,221 @@
1
- require 'rails_helper'
2
- describe Dummy::UserAPI, type: :request do
3
-
4
- let(:user) { User.last || User.make!}
5
- let(:company) { Company.last || Company.make! }
6
-
7
- before :all do
8
- User.destroy_all
9
- c = Company.make
10
- u = User.make
11
- u.roles.push Role.new(ownable: c)
12
- u.save
13
- end
14
-
15
- context :index do
16
-
17
- it "should return a list of users" do
18
- get '/api/v1/users'
19
- response.should be_successful
20
- json.length.should == 1
21
- json.first['id'].to_i.should == user.id
22
- json.first['first_name'].should == user.first_name
23
- json.first['last_name'].should == user.last_name
24
- json.first['roles_attributes'].size.should == 1
25
- json.first['roles_attributes'].first['ownable_type'].should == 'Company'
26
- json.first['roles_attributes'].first['ownable_id'].should == company.id
27
- end
28
-
29
- it "should constrain the index by a time range" do
30
- 6.times { User.make! }
31
- u = User.last
32
- u.update_column(:created_at, 1.day.ago)
33
- get '/api/v1/users', params: { created_at_start: 2.day.ago, created_at_end: 8.hours.ago }
34
- response.should be_successful
35
- json.length.should eq 1
36
- json.first['id'].to_i.should eq u.id
37
- json.first['first_name'].should eq u.first_name
38
- end
39
-
40
- it "should accept a comma separated list of ids" do
41
- 4.times { User.make! }
42
- user_ids = [User.first,User.second,User.third].map(&:id)
43
- get '/api/v1/users', params: { id: user_ids.join(',') }
44
- response.should be_successful
45
- json.length.should eq 3
46
- json.map {|j| j['id'] }.should eq user_ids
47
- end
48
-
49
- it "should not expose users' encrypted_passwords" do
50
- get "/api/v1/users"
51
- response.should be_successful
52
- json.first['encrypted_password'].should be_nil
53
- end
54
- end
55
-
56
-
57
- context :show do
58
- it "should return the specified user" do
59
- get "/api/v1/users/#{user.id}"
60
- response.should be_successful
61
- json['email'].should == user.email
62
- end
63
-
64
- it "should not expose a user's encrypted_password" do
65
- get "/api/v1/users/#{user.id}"
66
- response.should be_successful
67
- json['encrypted_password'].should be_nil
68
- end
69
-
70
- it "should return an error if the user doesn't exist" do
71
- get "/api/v1/users/#{user.id+1}"
72
- response.code.should == "404"
73
- end
74
- end
75
-
76
-
77
- context :create do
78
-
79
- it "should create a user and send the confirmation email" do
80
- post "/api/v1/users", params: { email: 'email@test.com', password: 'abc12345' }
81
- response.should be_successful
82
- json['email'].should == user.email
83
- User.last.confirmed_at.should == nil
84
- User.last.confirmation_sent_at.should_not == nil
85
- end
86
-
87
- it "should create a user and skip the confirmation email" do
88
- post "/api/v1/users", params: { email: 'email@test.com', password: 'abc12345', skip_confirmation_email: true }
89
- response.should be_successful
90
- json['email'].should == user.email
91
- User.last.confirmed_at.should_not == nil
92
- User.last.confirmation_sent_at.should == nil
93
- end
94
-
95
- it "should validate a new user" do
96
- post "/api/v1/users", params: { email: 'a'*257, password: '' }
97
- response.code.should == "400"
98
- json['error'].should == "Email: is invalid, Password: can't be blank"
99
- end
100
-
101
- it "should return only the records that were created at a nested endpoint" do
102
- new_company = Company.make!
103
- post "/api/v1/users/#{user.id}/roles", params: {ownable_type: 'Company', ownable_id: new_company.id}
104
- response.should be_successful
105
- json.size.should eq 1
106
- json.first['ownable_id'].should eq new_company.id
107
- end
108
-
109
-
110
- let(:params) do
111
- { email: 'test@test.com', password: 'abc12345', roles_attributes:[] }
112
- end
113
-
114
- let(:role) do
115
- { ownable_id: company.id, ownable_type: 'Company' }
116
- end
117
-
118
- it "should create a company admin" do
119
- params[:roles_attributes].push(role)
120
- post "/api/v1/users", params: params
121
- response.should be_successful
122
- User.last.admin?(company).should be_truthy
123
- end
124
-
125
-
126
- context "Project default passwords for new users" do
127
- let(:job) { Job.make! }
128
- let(:project) { Project.make!(jobs: [job], default_password: "super secret") }
129
- let(:params) do
130
- {
131
- email: 'test@test.com', password: '',
132
- user_project_jobs_attributes: [ job_id: project.jobs.first.id, project_id: project.id ]
133
- }
134
- end
135
-
136
- it "should set an empty password to an assigned project's default password" do
137
- post "/api/v1/users", params: params
138
- response.should be_successful
139
- json['user_project_jobs_attributes'][0]['name'].should == project.name
140
- json['user_project_jobs_attributes'][0]['title'].should == job.title
141
- end
142
-
143
- it "should return a validation error if the user's assigned project has no default password" do
144
- project.update_attributes(default_password: nil)
145
- post "/api/v1/users", params: params
146
- response.status.should == 400
147
- json['error'].should == "Password: can't be blank"
148
- end
149
- end
150
-
151
- end
152
-
153
- context :update do
154
- it "should upload a user avatar via the root route" do
155
- params = { avatar_attributes: { file: Rack::Test::UploadedFile.new(Rails.root+'../fixtures/images/avatar.jpeg', 'image/jpeg', true) } }
156
-
157
- put "/api/v1/users/#{user.id}", params: params
158
-
159
- response.should be_successful
160
- json['avatar_url'].should eq Image.last.file.url(:medium)
161
- user.avatar.should eq Image.last
162
- user.avatar_url.should eq Image.last.file.url(:medium)
163
- end
164
-
165
- it "should upload a user avatar via the nested route, to test the restful api's handling of has_one associations" do
166
- params = { file: Rack::Test::UploadedFile.new(Rails.root+'../fixtures/images/avatar.jpeg', 'image/jpeg', true) }
167
-
168
- post "/api/v1/users/#{user.id}/avatars", params: params
169
-
170
- response.should be_successful
171
- user.avatar.should == Image.last
172
- user.avatar_url.should == Image.last.file.url(:medium)
173
- user.avatar_url
174
- end
175
-
176
- it "should require a devise re-confirmation email to update a user's email address" do
177
- new_email = 'new.email@test.com'
178
- old_email = user.email
179
- put "/api/v1/users/#{user.id}", params: { email: new_email }
180
- response.should be_successful
181
- user.reload
182
- user.email.should == old_email
183
- user.unconfirmed_email.should == new_email
184
- json['email'].should == old_email
185
- end
186
-
187
- it "should skip the confirmation and update a user's email address" do
188
- new_email = 'new.email@test.com'
189
- put "/api/v1/users/#{user.id}", params: { email: new_email, skip_confirmation_email: true }
190
- response.should be_successful
191
- json['email'].should == new_email
192
- user.reload
193
- user.email.should == new_email
194
- end
195
-
196
- it "should validate the uniqueness of a user role" do
197
- put "/api/v1/users/#{user.id}", params: { roles_attributes: [{ownable_type: 'Company', ownable_id: company.id}] }
198
- response.should_not be_successful
199
- json['error'].should =~ /user has already been assigned that role/
200
- user.admin?(company).should be_truthy
201
- end
202
-
203
- it "should update a user to be company admin" do
204
- c = Company.make
205
- c.save!
206
- put "/api/v1/users/#{user.id}", params: { roles_attributes: [{ownable_type: 'Company', ownable_id: c.id}] }
207
- response.should be_successful
208
- user.reload
209
- user.admin?(c).should be_truthy
210
- end
211
-
212
- it "should destroy a user's company admin role" do
213
- user.admin?(company).should be_truthy
214
- put "/api/v1/users/#{user.id}", params: { roles_attributes: [{id: user.roles.last.id, _destroy: '1'}] }
215
- response.should be_successful
216
- user.reload
217
- user.admin?(company).should be_falsey
218
- end
219
- end
220
-
221
- end
1
+ require 'rails_helper'
2
+ describe Dummy::UserAPI, type: :request do
3
+
4
+ let(:user) { User.last || User.make!}
5
+ let(:company) { Company.last || Company.make! }
6
+
7
+ before :all do
8
+ User.destroy_all
9
+ c = Company.make
10
+ u = User.make
11
+ u.roles.push Role.new(ownable: c)
12
+ u.save
13
+ end
14
+
15
+ context :index do
16
+
17
+ it "should return a list of users" do
18
+ get '/api/v1/users'
19
+ response.should be_successful
20
+ json.length.should == 1
21
+ json.first['id'].to_i.should == user.id
22
+ json.first['first_name'].should == user.first_name
23
+ json.first['last_name'].should == user.last_name
24
+ json.first['roles_attributes'].size.should == 1
25
+ json.first['roles_attributes'].first['ownable_type'].should == 'Company'
26
+ json.first['roles_attributes'].first['ownable_id'].should == company.id
27
+ end
28
+
29
+ it "should constrain the index by a time range" do
30
+ 6.times { User.make! }
31
+ u = User.last
32
+ u.update_column(:created_at, 1.day.ago)
33
+ get '/api/v1/users', params: { created_at_start: 2.day.ago, created_at_end: 8.hours.ago }
34
+ response.should be_successful
35
+ json.length.should eq 1
36
+ json.first['id'].to_i.should eq u.id
37
+ json.first['first_name'].should eq u.first_name
38
+ end
39
+
40
+ it "should accept a comma separated list of ids" do
41
+ 4.times { User.make! }
42
+ user_ids = [User.first,User.second,User.third].map(&:id)
43
+ get '/api/v1/users', params: { id: user_ids.join(',') }
44
+ response.should be_successful
45
+ json.length.should eq 3
46
+ json.map {|j| j['id'] }.should eq user_ids
47
+ end
48
+
49
+ it "should not expose users' encrypted_passwords" do
50
+ get "/api/v1/users"
51
+ response.should be_successful
52
+ json.first['encrypted_password'].should be_nil
53
+ end
54
+ end
55
+
56
+
57
+ context :show do
58
+ it "should return the specified user" do
59
+ get "/api/v1/users/#{user.id}"
60
+ response.should be_successful
61
+ json['email'].should == user.email
62
+ end
63
+
64
+ it "should not expose a user's encrypted_password" do
65
+ get "/api/v1/users/#{user.id}"
66
+ response.should be_successful
67
+ json['encrypted_password'].should be_nil
68
+ end
69
+
70
+ it "should return an error if the user doesn't exist" do
71
+ get "/api/v1/users/#{user.id+1}"
72
+ response.code.should == "404"
73
+ end
74
+ end
75
+
76
+
77
+ context :create do
78
+
79
+ it "should create a user and send the confirmation email" do
80
+ post "/api/v1/users", params: { email: 'email@test.com', password: 'abc12345' }
81
+ response.should be_successful
82
+ json['email'].should == user.email
83
+ User.last.confirmed_at.should == nil
84
+ User.last.confirmation_sent_at.should_not == nil
85
+ end
86
+
87
+ it "should create a user and skip the confirmation email" do
88
+ post "/api/v1/users", params: { email: 'email@test.com', password: 'abc12345', skip_confirmation_email: true }
89
+ response.should be_successful
90
+ json['email'].should == user.email
91
+ User.last.confirmed_at.should_not == nil
92
+ User.last.confirmation_sent_at.should == nil
93
+ end
94
+
95
+ it "should validate a new user" do
96
+ post "/api/v1/users", params: { email: 'a'*257, password: '' }
97
+ response.code.should == "400"
98
+ json['error'].should == "Email: is invalid, Password: can't be blank"
99
+ end
100
+
101
+ it "should return only the records that were created at a nested endpoint" do
102
+ new_company = Company.make!
103
+ post "/api/v1/users/#{user.id}/roles", params: {ownable_type: 'Company', ownable_id: new_company.id}
104
+ response.should be_successful
105
+ json.size.should eq 1
106
+ json.first['ownable_id'].should eq new_company.id
107
+ end
108
+
109
+
110
+ let(:params) do
111
+ { email: 'test@test.com', password: 'abc12345', roles_attributes:[] }
112
+ end
113
+
114
+ let(:role) do
115
+ { ownable_id: company.id, ownable_type: 'Company' }
116
+ end
117
+
118
+ it "should create a company admin" do
119
+ params[:roles_attributes].push(role)
120
+ post "/api/v1/users", params: params
121
+ response.should be_successful
122
+ User.last.admin?(company).should be_truthy
123
+ end
124
+
125
+
126
+ context "Project default passwords for new users" do
127
+ let(:job) { Job.make! }
128
+ let(:project) { Project.make!(jobs: [job], default_password: "super secret") }
129
+ let(:params) do
130
+ {
131
+ email: 'test@test.com', password: '',
132
+ user_project_jobs_attributes: [ job_id: project.jobs.first.id, project_id: project.id ]
133
+ }
134
+ end
135
+
136
+ it "should set an empty password to an assigned project's default password" do
137
+ post "/api/v1/users", params: params
138
+ response.should be_successful
139
+ json['user_project_jobs_attributes'][0]['name'].should == project.name
140
+ json['user_project_jobs_attributes'][0]['title'].should == job.title
141
+ end
142
+
143
+ it "should return a validation error if the user's assigned project has no default password" do
144
+ project.update(default_password: nil)
145
+ post "/api/v1/users", params: params
146
+ response.status.should == 400
147
+ json['error'].should == "Password: can't be blank"
148
+ end
149
+ end
150
+
151
+ end
152
+
153
+ context :update do
154
+ it "should upload a user avatar via the root route" do
155
+ params = { avatar_attributes: { file: Rack::Test::UploadedFile.new(Rails.root+'../fixtures/images/avatar.jpeg', 'image/jpeg', true) } }
156
+
157
+ put "/api/v1/users/#{user.id}", params: params
158
+
159
+ response.should be_successful
160
+ json['avatar_url'].should eq Image.last.file.url(:medium)
161
+ user.avatar.should eq Image.last
162
+ user.avatar_url.should eq Image.last.file.url(:medium)
163
+ end
164
+
165
+ it "should upload a user avatar via the nested route, to test the restful api's handling of has_one associations" do
166
+ params = { file: Rack::Test::UploadedFile.new(Rails.root+'../fixtures/images/avatar.jpeg', 'image/jpeg', true) }
167
+
168
+ post "/api/v1/users/#{user.id}/avatars", params: params
169
+
170
+ response.should be_successful
171
+ user.avatar.should == Image.last
172
+ user.avatar_url.should == Image.last.file.url(:medium)
173
+ user.avatar_url
174
+ end
175
+
176
+ it "should require a devise re-confirmation email to update a user's email address" do
177
+ new_email = 'new.email@test.com'
178
+ old_email = user.email
179
+ put "/api/v1/users/#{user.id}", params: { email: new_email }
180
+ response.should be_successful
181
+ user.reload
182
+ user.email.should == old_email
183
+ user.unconfirmed_email.should == new_email
184
+ json['email'].should == old_email
185
+ end
186
+
187
+ it "should skip the confirmation and update a user's email address" do
188
+ new_email = 'new.email@test.com'
189
+ put "/api/v1/users/#{user.id}", params: { email: new_email, skip_confirmation_email: true }
190
+ response.should be_successful
191
+ json['email'].should == new_email
192
+ user.reload
193
+ user.email.should == new_email
194
+ end
195
+
196
+ it "should validate the uniqueness of a user role" do
197
+ put "/api/v1/users/#{user.id}", params: { roles_attributes: [{ownable_type: 'Company', ownable_id: company.id}] }
198
+ response.should_not be_successful
199
+ json['error'].should =~ /user has already been assigned that role/
200
+ user.admin?(company).should be_truthy
201
+ end
202
+
203
+ it "should update a user to be company admin" do
204
+ c = Company.make
205
+ c.save!
206
+ put "/api/v1/users/#{user.id}", params: { roles_attributes: [{ownable_type: 'Company', ownable_id: c.id}] }
207
+ response.should be_successful
208
+ user.reload
209
+ user.admin?(c).should be_truthy
210
+ end
211
+
212
+ it "should destroy a user's company admin role" do
213
+ user.admin?(company).should be_truthy
214
+ put "/api/v1/users/#{user.id}", params: { roles_attributes: [{id: user.roles.last.id, _destroy: '1'}] }
215
+ response.should be_successful
216
+ user.reload
217
+ user.admin?(company).should be_falsey
218
+ end
219
+ end
220
+
221
+ end
@@ -1,21 +1,22 @@
1
- require 'introspective_grape/camel_snake'
2
- module RequestHelpers
3
-
4
- def json
5
- @json ||= CamelSnakeKeys.snake_keys(JSON.parse(response.body), true)
6
- end
7
-
8
- def with_authentication(role=:superuser)
9
- return if @without_authentication
10
- current_user = User.new #double('User')
11
- allow(current_user).to receive(:admin?) { true } if role == :superuser
12
- allow(current_user).to receive(:superuser?) { true } if role == :superuser
13
-
14
- # Stubbing API helper methods requires this very nearly undocumented invokation
15
- Grape::Endpoint.before_each do |endpoint|
16
- allow(endpoint).to receive(:current_user) { current_user }
17
- end
18
- end
19
- end
20
-
21
-
1
+ require 'introspective_grape/camel_snake'
2
+ module RequestHelpers
3
+
4
+ def json
5
+ @json ||= CamelSnakeKeys.snake_keys(JSON.parse(response.body), true)
6
+ end
7
+
8
+ def with_authentication(role=:superuser)
9
+ return if @without_authentication
10
+ current_user = User.find_or_create_by(email: 'test@test.com', superuser: true, authentication_token: '1234567890', first_name: "First", last_name: "Last")
11
+ Current.user = current_user
12
+ allow(current_user).to receive(:admin?) { true } if role == :superuser
13
+ allow(current_user).to receive(:superuser?) { true } if role == :superuser
14
+
15
+ # Stubbing API helper methods requires this very nearly undocumented invokation
16
+ Grape::Endpoint.before_each do |endpoint|
17
+ allow(endpoint).to receive(:current_user) { current_user }
18
+ end
19
+ end
20
+ end
21
+
22
+