fe 2.3.2 → 2.4.0

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +147 -3
  3. data/app/controllers/concerns/fe/access_control_concern.rb +39 -0
  4. data/app/controllers/concerns/fe/admin/question_sheets_controller_concern.rb +2 -1
  5. data/app/controllers/concerns/fe/answer_pages_controller_concern.rb +3 -1
  6. data/app/controllers/concerns/fe/answer_sheets_controller_concern.rb +4 -1
  7. data/app/controllers/fe/admin/elements_controller.rb +4 -3
  8. data/app/controllers/fe/admin/email_templates_controller.rb +2 -1
  9. data/app/controllers/fe/admin/question_pages_controller.rb +2 -1
  10. data/app/controllers/fe/reference_pages_controller.rb +4 -0
  11. data/app/controllers/fe/reference_sheets_controller.rb +8 -2
  12. data/app/controllers/fe/references_controller.rb +4 -0
  13. data/app/controllers/fe/submit_pages_controller.rb +2 -0
  14. data/app/views/fe/answer_pages/update.js.erb +2 -1
  15. data/app/views/fe/questions/fe/_attachment_field.html.erb +8 -8
  16. data/lib/fe/access_control.rb +72 -0
  17. data/lib/fe/engine.rb +4 -0
  18. data/lib/fe/version.rb +1 -1
  19. data/lib/fe.rb +1 -0
  20. data/spec/controllers/fe/admin/elements_controller_spec.rb +29 -0
  21. data/spec/controllers/fe/admin/email_templates_controller_spec.rb +8 -0
  22. data/spec/controllers/fe/admin/question_pages_controller_spec.rb +9 -0
  23. data/spec/controllers/fe/admin/question_sheets_controller_spec.rb +30 -0
  24. data/spec/controllers/fe/answer_pages_controller_spec.rb +142 -0
  25. data/spec/controllers/fe/answer_sheets_controller_spec.rb +114 -0
  26. data/spec/controllers/fe/reference_pages_controller_spec.rb +32 -0
  27. data/spec/controllers/fe/reference_sheets_controller_spec.rb +88 -1
  28. data/spec/controllers/fe/references_controller_spec.rb +29 -1
  29. data/spec/controllers/fe/submit_pages_controller_spec.rb +44 -1
  30. data/spec/dummy/app/controllers/application_controller.rb +8 -0
  31. data/spec/dummy/config/initializers/fe.rb +2 -0
  32. data/spec/lib/fe/access_control_spec.rb +173 -0
  33. metadata +10 -8
  34. data/spec/controllers/fe/reference_pages_controller.rb +0 -4
  35. data/spec/dummy/log/test.log +0 -9115
  36. data/spec/dummy/tmp/local_secret.txt +0 -1
@@ -49,3 +49,33 @@ describe Fe::Admin::QuestionSheetsController, type: :controller do
49
49
  end
50
50
  end
51
51
  end
52
+
53
+ describe Fe::Admin::QuestionSheetsController, type: :controller do
54
+ context 'when the host says the person is not an admin' do
55
+ before { allow(controller).to receive(:fe_admin?).and_return(false) }
56
+
57
+ it 'returns 403 on #index' do
58
+ get :index
59
+ expect(response).to have_http_status(:forbidden)
60
+ end
61
+
62
+ it 'does not destroy on #destroy' do
63
+ qs = create(:question_sheet)
64
+ expect { delete :destroy, params: {id: qs.id} }.not_to change { Fe::QuestionSheet.count }
65
+ expect(response).to have_http_status(:forbidden)
66
+ end
67
+
68
+ it 'stops the request after fe_access_denied redirects' do
69
+ expect(controller).to receive(:fe_access_denied).with(:admin) { controller.redirect_to '/denied' }
70
+ get :index
71
+ expect(response).to redirect_to('/denied')
72
+ end
73
+ end
74
+
75
+ it 'returns 403 on #index when the host defines no fe_admin?' do
76
+ allow(controller).to receive(:respond_to?).and_call_original
77
+ allow(controller).to receive(:respond_to?).with(:fe_admin?, true).and_return(false)
78
+ get :index
79
+ expect(response).to have_http_status(:forbidden)
80
+ end
81
+ end
@@ -1,6 +1,59 @@
1
1
  require 'rails_helper'
2
2
 
3
3
  describe Fe::AnswerPagesController, type: :controller do
4
+ context 'answer_sheet_type param' do
5
+ it 'rejects a class that is not an allowed answer sheet type' do
6
+ page = create(:page)
7
+ expect {
8
+ get :show, params: {id: page.id, answer_sheet_id: 1, answer_sheet_type: 'Kernel'}
9
+ }.to raise_error(ActiveRecord::RecordNotFound)
10
+ end
11
+ end
12
+ context 'access control' do
13
+ let(:answer_sheet) { create(:answer_sheet) }
14
+ let(:page) { create(:page) }
15
+ let(:element) { create(:text_field_element) }
16
+
17
+ before do
18
+ create(:answer_sheet_question_sheet, answer_sheet: answer_sheet, question_sheet: page.question_sheet)
19
+ create(:page_element, element: element, page: page)
20
+ end
21
+
22
+ it 'returns 403 on update and stores nothing when the host refuses' do
23
+ create(:answer, answer_sheet: answer_sheet, question: element, value: 'before')
24
+ allow(controller).to receive(:fe_can_use_answer_sheet?).and_return(false)
25
+
26
+ put :update, params: {
27
+ answers: { "#{element.id}" => 'after' }, id: page.id, answer_sheet_id: answer_sheet.id
28
+ }, xhr: true, format: :js
29
+
30
+ expect(response).to have_http_status(:forbidden)
31
+ expect(Fe::Answer.find_by(answer_sheet_id: answer_sheet.id, question_id: element.id).value).to eq('before')
32
+ end
33
+ it 'asks the host for :look on show' do
34
+ expect(controller).to receive(:fe_can_use_answer_sheet?).with(answer_sheet, :look).and_return(false)
35
+ get :show, params: {id: page.id, answer_sheet_id: answer_sheet.id}
36
+ expect(response).to have_http_status(:forbidden)
37
+ end
38
+
39
+ context 'when a subclass re-declares before_action :get_answer_sheet' do
40
+ controller(Fe::AnswerPagesController) { before_action :get_answer_sheet }
41
+
42
+ it 'still asks the host, returns 403 on update and stores nothing' do
43
+ filters = controller.class._process_action_callbacks.map(&:filter)
44
+ expect(filters.index(:get_answer_sheet)).to be > filters.index(:fe_authorize_answer_sheet!)
45
+ create(:answer, answer_sheet: answer_sheet, question: element, value: 'before')
46
+ expect(controller).to receive(:fe_can_use_answer_sheet?).with(answer_sheet, :change).and_return(false)
47
+
48
+ put :update, params: {
49
+ answers: { "#{element.id}" => 'after' }, id: page.id, answer_sheet_id: answer_sheet.id
50
+ }, xhr: true, format: :js
51
+
52
+ expect(response).to have_http_status(:forbidden)
53
+ expect(Fe::Answer.find_by(answer_sheet_id: answer_sheet.id, question_id: element.id).value).to eq('before')
54
+ end
55
+ end
56
+ end
4
57
  context '#edit' do
5
58
  let(:answer_sheet) { create(:answer_sheet) }
6
59
  let(:page) { create(:page) }
@@ -142,4 +195,93 @@ describe Fe::AnswerPagesController, type: :controller do
142
195
  end
143
196
  end
144
197
  end
198
+
199
+ context 'a reference writer with an attachment field, under the README example hook' do
200
+ let(:ref_page) { create(:page) }
201
+ let(:attachment) { create(:attachment_field_element) }
202
+ let(:reference_question) { create(:reference_question, related_question_sheet_id: ref_page.question_sheet.id) }
203
+ let(:reference_sheet) do
204
+ create(:reference_sheet, question_id: reference_question.id, applicant_answer_sheet_id: create(:answer_sheet).id,
205
+ access_key: 'good-key')
206
+ end
207
+ let(:sheet_params) { {id: ref_page.id, answer_sheet_id: reference_sheet.id, answer_sheet_type: 'Fe::ReferenceSheet'} }
208
+
209
+ before do
210
+ create(:page_element, element: attachment, page: ref_page)
211
+ allow(controller).to receive(:fe_can_use_answer_sheet?) do |sheet, _access|
212
+ sheet.is_a?(Fe::ReferenceSheet) && Fe.access_key_matches?(sheet, controller.params[:a])
213
+ end
214
+ end
215
+
216
+ # The dummy app has no asset manifest entry for the uploadify files the partial names.
217
+ def without_precompiled_asset_check
218
+ check_precompiled = ActionView::Base.check_precompiled_asset
219
+ ActionView::Base.check_precompiled_asset = false
220
+ yield
221
+ ensure
222
+ ActionView::Base.check_precompiled_asset = check_precompiled
223
+ end
224
+
225
+ it 'puts the reference key on the upload and page reload URLs' do
226
+ without_precompiled_asset_check { get :edit, params: sheet_params.merge(a: 'good-key') }
227
+
228
+ expect(response).to have_http_status(:ok)
229
+ expect(response.body).to match(%r{/save_file\?[^"]*\ba=good-key})
230
+ expect(response.body).to match(%r{/page/#{ref_page.id}/edit\?[^"]*\ba=good-key})
231
+ end
232
+
233
+ it 'lets the writer reach save_file with the key' do
234
+ post :save_file, params: sheet_params.merge(question_id: attachment.id, a: 'good-key'), xhr: true, format: :js
235
+
236
+ expect(response).to have_http_status(:ok)
237
+ end
238
+
239
+ it 'refuses save_file without the key' do
240
+ post :save_file, params: sheet_params.merge(question_id: attachment.id), xhr: true, format: :js
241
+
242
+ expect(response).to have_http_status(:forbidden)
243
+ end
244
+
245
+ context 'with a file already attached' do
246
+ # fe leaves file storage to the host app, which defines Fe::Answer#attachment.
247
+ let(:stored_file) do
248
+ '/files/report.pdf'.dup.tap do |file|
249
+ file.define_singleton_method(:attached?) { true }
250
+ file.define_singleton_method(:filename) { 'report.pdf' }
251
+ file.define_singleton_method(:expiring_url) { file }
252
+ end
253
+ end
254
+ let!(:answer) do
255
+ create(:answer, answer_sheet_id: reference_sheet.id, question_id: attachment.id, attachment_file_name: 'report.pdf')
256
+ end
257
+
258
+ before { allow_any_instance_of(Fe::Answer).to receive(:attachment).and_return(stored_file) }
259
+
260
+ it 'puts the reference key on the delete_file links' do
261
+ without_precompiled_asset_check { get :edit, params: sheet_params.merge(a: 'good-key') }
262
+
263
+ expect(response).to have_http_status(:ok)
264
+ delete_urls = response.body.scan(%r{/delete_file\?[^"]*})
265
+ expect(delete_urls).not_to be_empty
266
+ expect(delete_urls).to all(match(/\ba=good-key/))
267
+ expect(delete_urls).to all(match(/\banswer_sheet_type=Fe%3A%3AReferenceSheet\b/))
268
+ end
269
+
270
+ it 'deletes the file with the key and keeps the key on the delete link it sends back' do
271
+ delete :delete_file, params: sheet_params.merge(question_id: attachment.id, a: 'good-key'), xhr: true, format: :js
272
+
273
+ expect(response).to have_http_status(:ok)
274
+ expect(Fe::Answer.exists?(answer.id)).to be false
275
+ expect(response.body).to match(%r{/delete_file\?[^"]*\ba=good-key})
276
+ expect(response.body).to match(%r{/delete_file\?[^"]*\banswer_sheet_type=Fe%3A%3AReferenceSheet\b})
277
+ end
278
+
279
+ it 'refuses delete_file without the key and keeps the file' do
280
+ delete :delete_file, params: sheet_params.merge(question_id: attachment.id), xhr: true, format: :js
281
+
282
+ expect(response).to have_http_status(:forbidden)
283
+ expect(Fe::Answer.exists?(answer.id)).to be true
284
+ end
285
+ end
286
+ end
145
287
  end
@@ -4,6 +4,120 @@ describe Fe::AnswerSheetsController, type: :controller do
4
4
  let(:question_sheet) { create(:question_sheet) }
5
5
  let(:answer_sheet) { create(:answer_sheet, applicant_id: create(:fe_person).id) }
6
6
 
7
+ context 'access control' do
8
+ before do
9
+ create(:answer_sheet_question_sheet, question_sheet: question_sheet, answer_sheet: answer_sheet)
10
+ create(:page, question_sheet: question_sheet)
11
+ end
12
+
13
+ it 'asks the host for :look on show' do
14
+ expect(controller).to receive(:fe_can_use_answer_sheet?).with(answer_sheet, :look).and_return(true)
15
+ get :show, params: {id: answer_sheet.id}
16
+ end
17
+ it 'asks the host for :change on edit' do
18
+ expect(controller).to receive(:fe_can_use_answer_sheet?).with(answer_sheet, :change).and_return(true)
19
+ get :edit, params: {id: answer_sheet.id}
20
+ end
21
+ context 'when the host refuses' do
22
+ before { allow(controller).to receive(:fe_can_use_answer_sheet?).and_return(false) }
23
+
24
+ it 'returns 403 without running the action' do
25
+ get :edit, params: {id: answer_sheet.id}
26
+ expect(response).to have_http_status(:forbidden)
27
+ expect(assigns(:presenter)).to be_nil
28
+ end
29
+ it 'lets fe_access_denied redirect' do
30
+ expect(controller).to receive(:fe_access_denied).with(:answer_sheet) { controller.redirect_to '/denied' }
31
+ get :edit, params: {id: answer_sheet.id}
32
+ expect(response).to redirect_to('/denied')
33
+ end
34
+ it 'returns 403 when fe_access_denied renders nothing' do
35
+ allow(controller).to receive(:fe_access_denied)
36
+ get :edit, params: {id: answer_sheet.id}
37
+ expect(response).to have_http_status(:forbidden)
38
+ end
39
+ end
40
+ it 'propagates exceptions from the host hook' do
41
+ allow(controller).to receive(:fe_can_use_answer_sheet?).and_raise(RuntimeError, 'nope')
42
+ expect { get :edit, params: {id: answer_sheet.id} }.to raise_error(RuntimeError, 'nope')
43
+ end
44
+ it 'returns 403 when the host defines no hook' do
45
+ allow(controller).to receive(:respond_to?).and_call_original
46
+ allow(controller).to receive(:respond_to?).with(:fe_can_use_answer_sheet?, true).and_return(false)
47
+ get :edit, params: {id: answer_sheet.id}
48
+ expect(response).to have_http_status(:forbidden)
49
+ end
50
+
51
+ context 'when a subclass re-declares before_action :get_answer_sheet' do
52
+ controller(Fe::AnswerSheetsController) { before_action :get_answer_sheet }
53
+
54
+ it 'still asks the host and returns 403 on edit' do
55
+ filters = controller.class._process_action_callbacks.map(&:filter)
56
+ expect(filters.index(:get_answer_sheet)).to be > filters.index(:fe_authorize_answer_sheet!)
57
+ expect(controller).to receive(:fe_can_use_answer_sheet?).with(answer_sheet, :change).and_return(false)
58
+
59
+ get :edit, params: {id: answer_sheet.id}
60
+
61
+ expect(response).to have_http_status(:forbidden)
62
+ expect(assigns(:presenter)).to be_nil
63
+ end
64
+ end
65
+
66
+ context 'when a re-declared loader redirects' do
67
+ controller(Fe::AnswerSheetsController) do
68
+ before_action :get_answer_sheet
69
+
70
+ def get_answer_sheet
71
+ redirect_to '/elsewhere'
72
+ end
73
+ end
74
+
75
+ it 'stops the request without asking the host' do
76
+ expect(controller).not_to receive(:fe_can_use_answer_sheet?)
77
+
78
+ get :edit, params: {id: answer_sheet.id}
79
+
80
+ expect(response).to redirect_to('/elsewhere')
81
+ end
82
+ end
83
+ end
84
+ context 'when the person is not an admin' do
85
+ before { allow(controller).to receive(:fe_admin?).and_return(false) }
86
+
87
+ it 'returns 403 on index' do
88
+ get :index
89
+ expect(response).to have_http_status(:forbidden)
90
+ end
91
+
92
+ it 'returns 403 on create and makes no answer sheet' do
93
+ question_sheet
94
+ expect { post :create, params: {question_sheet_id: question_sheet.id} }
95
+ .not_to change { Fe.answer_sheet_class.constantize.count }
96
+ expect(response).to have_http_status(:forbidden)
97
+ end
98
+
99
+ context 'with a subclass that defines its own create' do
100
+ controller(Fe::AnswerSheetsController) do
101
+ def create
102
+ head :ok
103
+ end
104
+ end
105
+
106
+ it 'leaves the host action alone' do
107
+ post :create, params: {question_sheet_id: question_sheet.id}
108
+ expect(response).to have_http_status(:ok)
109
+ end
110
+ end
111
+
112
+ context 'with a subclass that inherits create' do
113
+ controller(Fe::AnswerSheetsController) {}
114
+
115
+ it 'returns 403' do
116
+ post :create, params: {question_sheet_id: question_sheet.id}
117
+ expect(response).to have_http_status(:forbidden)
118
+ end
119
+ end
120
+ end
7
121
  context '#index' do
8
122
  it 'should work' do
9
123
  create(:answer_sheet_question_sheet, question_sheet: question_sheet, answer_sheet: answer_sheet)
@@ -0,0 +1,32 @@
1
+ require 'rails_helper'
2
+
3
+ describe Fe::ReferencePagesController, type: :controller do
4
+ let(:sheet) { create(:answer_sheet) }
5
+
6
+ def draw_routes
7
+ with_routing do |set|
8
+ set.draw do
9
+ get 'fe/reference_pages/:application_id/edit' => 'fe/reference_pages#edit'
10
+ put 'fe/reference_pages/:application_id' => 'fe/reference_pages#update'
11
+ end
12
+ self.routes = set
13
+ yield
14
+ end
15
+ end
16
+
17
+ context 'when the host denies the answer sheet' do
18
+ before { allow(controller).to receive(:fe_can_use_answer_sheet?).and_return(false) }
19
+
20
+ it 'returns 403 for edit' do
21
+ draw_routes { get :edit, params: {application_id: sheet.id} }
22
+
23
+ expect(response).to have_http_status(:forbidden)
24
+ end
25
+
26
+ it 'returns 403 for update' do
27
+ draw_routes { put :update, params: {application_id: sheet.id} }
28
+
29
+ expect(response).to have_http_status(:forbidden)
30
+ end
31
+ end
32
+ end
@@ -1,4 +1,91 @@
1
1
  require 'rails_helper'
2
2
 
3
- describe Fe::ReferenceSheetsController do
3
+ describe Fe::ReferenceSheetsController, type: :controller do
4
+ it 'renders not_found for a wrong access key without asking the host' do
5
+ reference_sheet = create(:reference_sheet)
6
+ expect(controller).not_to receive(:fe_can_use_answer_sheet?)
7
+
8
+ get :edit, params: {id: reference_sheet.id, a: 'wrong'}
9
+
10
+ expect(response).to render_template('fe/reference_sheets/not_found')
11
+ end
12
+
13
+ it 'renders not_found with a 404 on show for a wrong access key without asking the host' do
14
+ reference_sheet = create(:reference_sheet, access_key: 'good-key')
15
+ expect(controller).not_to receive(:fe_can_use_answer_sheet?)
16
+
17
+ get :show, params: {id: reference_sheet.id, a: 'wrong'}
18
+
19
+ expect(response).to have_http_status(:not_found)
20
+ expect(response).to render_template('fe/reference_sheets/not_found')
21
+ end
22
+
23
+ it 'renders not_found with a 404 on show when the reference sheet does not exist' do
24
+ get :show, params: {id: 0}
25
+
26
+ expect(response).to have_http_status(:not_found)
27
+ expect(response).to render_template('fe/reference_sheets/not_found')
28
+ end
29
+
30
+ it 'renders done' do
31
+ with_routing do |set|
32
+ set.draw { get 'fe/references/done' => 'fe/reference_sheets#done' }
33
+
34
+ self.routes = set
35
+
36
+ get :done
37
+ end
38
+
39
+ expect(response).to have_http_status(:ok)
40
+ expect(response).to render_template('fe/reference_sheets/done')
41
+ end
42
+
43
+ context 'with a valid access key' do
44
+ let(:ref_qs) { create(:question_sheet) }
45
+ let(:question) { create(:reference_question, related_question_sheet: ref_qs) }
46
+ let(:applicant_sheet) { create(:answer_sheet, applicant_id: create(:fe_person).id) }
47
+ let(:reference_sheet) { create(:reference_sheet, question: question, applicant_answer_sheet: applicant_sheet, access_key: 'good-key') }
48
+
49
+ before { ref_qs.pages << create(:page) }
50
+
51
+ it 'renders show when the host allows it' do
52
+ allow(controller).to receive(:fe_can_use_answer_sheet?).and_return(true)
53
+
54
+ get :show, params: {id: reference_sheet.id, a: 'good-key'}
55
+
56
+ expect(response).to have_http_status(:ok)
57
+ expect(response).to render_template('fe/answer_sheets/show')
58
+ end
59
+
60
+ it 'asks the host for :look on show and returns 403 when it refuses' do
61
+ expect(controller).to receive(:fe_can_use_answer_sheet?).with(reference_sheet, :look).and_return(false)
62
+
63
+ get :show, params: {id: reference_sheet.id, a: 'good-key'}
64
+
65
+ expect(response).to have_http_status(:forbidden)
66
+ end
67
+
68
+ it 'stops submit with a 404 before loading the sheet or asking the host' do
69
+ expect(controller).not_to receive(:get_answer_sheet)
70
+ expect(controller).not_to receive(:fe_can_use_answer_sheet?)
71
+
72
+ with_routing do |set|
73
+ set.draw { post 'fe/reference_sheets/:id/submit', to: 'fe/reference_sheets#submit' }
74
+
75
+ self.routes = set
76
+
77
+ expect {
78
+ post :submit, params: {id: reference_sheet.id, a: 'good-key'}
79
+ }.not_to change { reference_sheet.reload.status }
80
+ end
81
+
82
+ expect(response).to have_http_status(:not_found)
83
+ end
84
+
85
+ it 'still renders edit' do
86
+ get :edit, params: {id: reference_sheet.id, a: 'good-key'}
87
+
88
+ expect(response).to render_template('fe/answer_sheets/edit')
89
+ end
90
+ end
4
91
  end
@@ -1,4 +1,32 @@
1
1
  require 'rails_helper'
2
2
 
3
- describe Fe::ReferencesController do
3
+ describe Fe::ReferencesController, type: :controller do
4
+ let(:sheet) { create(:answer_sheet) }
5
+
6
+ def draw_routes
7
+ with_routing do |set|
8
+ set.draw do
9
+ get 'fe/references/:application_id/:id/edit' => 'fe/references#edit'
10
+ get 'fe/references/:application_id/:id' => 'fe/references#show'
11
+ end
12
+ self.routes = set
13
+ yield
14
+ end
15
+ end
16
+
17
+ context 'when the host denies the answer sheet' do
18
+ before { allow(controller).to receive(:fe_can_use_answer_sheet?).and_return(false) }
19
+
20
+ it 'returns 403 for edit' do
21
+ draw_routes { get :edit, params: {application_id: sheet.id, id: 'key'} }
22
+
23
+ expect(response).to have_http_status(:forbidden)
24
+ end
25
+
26
+ it 'returns 403 for show' do
27
+ draw_routes { get :show, params: {application_id: sheet.id, id: 'key'} }
28
+
29
+ expect(response).to have_http_status(:forbidden)
30
+ end
31
+ end
4
32
  end
@@ -1,4 +1,47 @@
1
1
  require 'rails_helper'
2
2
 
3
- describe Fe::SubmitPagesController do
3
+ describe Fe::SubmitPagesController, type: :controller do
4
+ render_views false
5
+
6
+ let(:sheet) { create(:answer_sheet) }
7
+
8
+ def draw_routes
9
+ with_routing do |set|
10
+ set.draw do
11
+ get 'fe/submit_pages/:application_id/edit' => 'fe/submit_pages#edit'
12
+ put 'fe/submit_pages/:application_id' => 'fe/submit_pages#update'
13
+ end
14
+ self.routes = set
15
+ yield
16
+ end
17
+ end
18
+
19
+ context 'when the host denies the answer sheet' do
20
+ before { allow(controller).to receive(:fe_can_use_answer_sheet?).and_return(false) }
21
+
22
+ it 'returns 403 for edit' do
23
+ draw_routes { get :edit, params: {application_id: sheet.id} }
24
+
25
+ expect(response).to have_http_status(:forbidden)
26
+ end
27
+
28
+ it 'returns 403 for update' do
29
+ draw_routes { put :update, params: {application_id: sheet.id} }
30
+
31
+ expect(response).to have_http_status(:forbidden)
32
+ end
33
+ end
34
+
35
+ context 'when the host allows the answer sheet' do
36
+ before do
37
+ allow(controller).to receive(:fe_can_use_answer_sheet?).and_return(true)
38
+ allow(controller).to receive(:next_custom_page)
39
+ end
40
+
41
+ it 'returns 200 for edit' do
42
+ draw_routes { get :edit, params: {application_id: sheet.id} }
43
+
44
+ expect(response).to have_http_status(:ok)
45
+ end
46
+ end
4
47
  end
@@ -7,4 +7,12 @@ class ApplicationController < ActionController::Base
7
7
 
8
8
  def check_valid_user
9
9
  end
10
+
11
+ def fe_can_use_answer_sheet?(answer_sheet, access)
12
+ true
13
+ end
14
+
15
+ def fe_admin?
16
+ true
17
+ end
10
18
  end
@@ -0,0 +1,2 @@
1
+ # Booting the check autoloads the controllers before SimpleCov starts; access_control_spec calls it directly.
2
+ Fe.verify_access_hooks_on_boot = false