introspective_grape 0.5.7 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
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
+