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.
- checksums.yaml +4 -4
- data/README.md +147 -3
- data/app/controllers/concerns/fe/access_control_concern.rb +39 -0
- data/app/controllers/concerns/fe/admin/question_sheets_controller_concern.rb +2 -1
- data/app/controllers/concerns/fe/answer_pages_controller_concern.rb +3 -1
- data/app/controllers/concerns/fe/answer_sheets_controller_concern.rb +4 -1
- data/app/controllers/fe/admin/elements_controller.rb +4 -3
- data/app/controllers/fe/admin/email_templates_controller.rb +2 -1
- data/app/controllers/fe/admin/question_pages_controller.rb +2 -1
- data/app/controllers/fe/reference_pages_controller.rb +4 -0
- data/app/controllers/fe/reference_sheets_controller.rb +8 -2
- data/app/controllers/fe/references_controller.rb +4 -0
- data/app/controllers/fe/submit_pages_controller.rb +2 -0
- data/app/views/fe/answer_pages/update.js.erb +2 -1
- data/app/views/fe/questions/fe/_attachment_field.html.erb +8 -8
- data/lib/fe/access_control.rb +72 -0
- data/lib/fe/engine.rb +4 -0
- data/lib/fe/version.rb +1 -1
- data/lib/fe.rb +1 -0
- data/spec/controllers/fe/admin/elements_controller_spec.rb +29 -0
- data/spec/controllers/fe/admin/email_templates_controller_spec.rb +8 -0
- data/spec/controllers/fe/admin/question_pages_controller_spec.rb +9 -0
- data/spec/controllers/fe/admin/question_sheets_controller_spec.rb +30 -0
- data/spec/controllers/fe/answer_pages_controller_spec.rb +142 -0
- data/spec/controllers/fe/answer_sheets_controller_spec.rb +114 -0
- data/spec/controllers/fe/reference_pages_controller_spec.rb +32 -0
- data/spec/controllers/fe/reference_sheets_controller_spec.rb +88 -1
- data/spec/controllers/fe/references_controller_spec.rb +29 -1
- data/spec/controllers/fe/submit_pages_controller_spec.rb +44 -1
- data/spec/dummy/app/controllers/application_controller.rb +8 -0
- data/spec/dummy/config/initializers/fe.rb +2 -0
- data/spec/lib/fe/access_control_spec.rb +173 -0
- metadata +10 -8
- data/spec/controllers/fe/reference_pages_controller.rb +0 -4
- data/spec/dummy/log/test.log +0 -9115
- data/spec/dummy/tmp/local_secret.txt +0 -1
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
describe Fe do
|
|
4
|
+
describe '.allowed_answer_sheet_types' do
|
|
5
|
+
after { Fe.answer_sheet_types = nil }
|
|
6
|
+
|
|
7
|
+
it 'defaults to the answer sheet class and reference sheet' do
|
|
8
|
+
expect(Fe.allowed_answer_sheet_types).to eq(['Fe::Application', 'Fe::ReferenceSheet'])
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'uses answer_sheet_types when set' do
|
|
12
|
+
Fe.answer_sheet_types = ['Foo']
|
|
13
|
+
expect(Fe.allowed_answer_sheet_types).to eq(['Foo'])
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe '.answer_sheet_class_for' do
|
|
18
|
+
it 'returns the default answer sheet class for a blank name' do
|
|
19
|
+
expect(Fe.answer_sheet_class_for(nil)).to eq(Fe::Application)
|
|
20
|
+
expect(Fe.answer_sheet_class_for('')).to eq(Fe::Application)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'returns an allowed class' do
|
|
24
|
+
expect(Fe.answer_sheet_class_for('Fe::ReferenceSheet')).to eq(Fe::ReferenceSheet)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
['Kernel', 'Fe::Element', '::Fe::Application', ' Fe::Application', 'fe::application'].each do |name|
|
|
28
|
+
it "rejects #{name.inspect}" do
|
|
29
|
+
expect { Fe.answer_sheet_class_for(name) }.to raise_error(ActiveRecord::RecordNotFound)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe '.element_class_for' do
|
|
35
|
+
it 'returns an allowed class' do
|
|
36
|
+
expect(Fe.element_class_for('Fe::TextField')).to eq(Fe::TextField)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
['Fe::Question', 'Fe::Application', 'Kernel'].each do |name|
|
|
40
|
+
it "rejects #{name.inspect}" do
|
|
41
|
+
expect { Fe.element_class_for(name) }.to raise_error(ActiveRecord::RecordNotFound)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe '.access_key_matches?' do
|
|
47
|
+
let(:sheet) { build(:reference_sheet, access_key: 'abc123') }
|
|
48
|
+
|
|
49
|
+
it 'is true for the sheet key' do
|
|
50
|
+
expect(Fe.access_key_matches?(sheet, 'abc123')).to be true
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
['wrong', nil, '', ['abc123'], { 'abc123' => 'v' }].each do |key|
|
|
54
|
+
it "is false for #{key.inspect}" do
|
|
55
|
+
expect(Fe.access_key_matches?(sheet, key)).to be false
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'is false when the sheet has no access key' do
|
|
60
|
+
sheet.access_key = nil
|
|
61
|
+
expect(Fe.access_key_matches?(sheet, 'abc123')).to be false
|
|
62
|
+
sheet.access_key = ''
|
|
63
|
+
expect(Fe.access_key_matches?(sheet, '')).to be false
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
describe '.verify_access_hooks!' do
|
|
68
|
+
let(:answer_hook) { :fe_can_use_answer_sheet? }
|
|
69
|
+
|
|
70
|
+
def stub_lists(answer: [], admin: [])
|
|
71
|
+
stub_const('Fe::ANSWER_SHEET_CONTROLLERS', answer)
|
|
72
|
+
stub_const('Fe::ADMIN_CONTROLLERS', admin)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it 'passes for the dummy app with the real lists' do
|
|
76
|
+
expect(Fe.verify_access_hooks!).to be_nil
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it 'raises when an answer sheet controller has no hook' do
|
|
80
|
+
stub_const('FeNoHooksController', Class.new)
|
|
81
|
+
stub_lists(answer: %w[FeNoHooksController])
|
|
82
|
+
|
|
83
|
+
expect { Fe.verify_access_hooks! }.to raise_error(Fe::MissingAccessHook) { |e|
|
|
84
|
+
expect(e.message).to include('fe_can_use_answer_sheet?', 'FeNoHooksController', 'Access control')
|
|
85
|
+
}
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'raises when an admin controller has no fe_admin?' do
|
|
89
|
+
stub_const('FeNoAdminController', Class.new)
|
|
90
|
+
stub_lists(admin: %w[FeNoAdminController])
|
|
91
|
+
|
|
92
|
+
expect { Fe.verify_access_hooks! }.to raise_error(Fe::MissingAccessHook) { |e|
|
|
93
|
+
expect(e.message).to include('fe_admin?', 'FeNoAdminController')
|
|
94
|
+
}
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it 'requires fe_admin? on the answer sheets controller' do
|
|
98
|
+
klass = Class.new do
|
|
99
|
+
protected
|
|
100
|
+
|
|
101
|
+
def fe_can_use_answer_sheet?(*) = true
|
|
102
|
+
end
|
|
103
|
+
stub_const('Fe::AnswerSheetsController', klass)
|
|
104
|
+
stub_lists(answer: %w[Fe::AnswerSheetsController])
|
|
105
|
+
|
|
106
|
+
expect { Fe.verify_access_hooks! }.to raise_error(Fe::MissingAccessHook) { |e|
|
|
107
|
+
expect(e.message).to include('fe_admin?', 'Fe::AnswerSheetsController')
|
|
108
|
+
expect(e.message).not_to include('fe_can_use_answer_sheet?')
|
|
109
|
+
}
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it 'names every missing method and class in one error' do
|
|
113
|
+
stub_const('FeNoHooksController', Class.new)
|
|
114
|
+
stub_const('FeNoAdminController', Class.new)
|
|
115
|
+
stub_lists(answer: %w[FeNoHooksController], admin: %w[FeNoAdminController])
|
|
116
|
+
|
|
117
|
+
expect { Fe.verify_access_hooks! }.to raise_error(Fe::MissingAccessHook) { |e|
|
|
118
|
+
expect(e.message).to include('fe_can_use_answer_sheet?', 'FeNoHooksController', 'fe_admin?', 'FeNoAdminController')
|
|
119
|
+
}
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'passes when both hooks are inherited from a parent' do
|
|
123
|
+
parent = Class.new do
|
|
124
|
+
protected
|
|
125
|
+
|
|
126
|
+
def fe_can_use_answer_sheet?(*) = true
|
|
127
|
+
def fe_admin? = true
|
|
128
|
+
end
|
|
129
|
+
stub_const('FeChildAnswerController', Class.new(parent))
|
|
130
|
+
stub_const('FeChildAdminController', Class.new(parent))
|
|
131
|
+
stub_lists(answer: %w[FeChildAnswerController], admin: %w[FeChildAdminController])
|
|
132
|
+
|
|
133
|
+
expect(Fe.verify_access_hooks!).to be_nil
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it 'passes when the hook comes from a prepended module' do
|
|
137
|
+
mod = Module.new do
|
|
138
|
+
def fe_can_use_answer_sheet?(*) = true
|
|
139
|
+
end
|
|
140
|
+
klass = Class.new
|
|
141
|
+
klass.prepend(mod)
|
|
142
|
+
stub_const('FePrependedController', klass)
|
|
143
|
+
stub_lists(answer: %w[FePrependedController])
|
|
144
|
+
|
|
145
|
+
expect(Fe.verify_access_hooks!).to be_nil
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it 'passes when the hook is a protected method on the class itself' do
|
|
149
|
+
klass = Class.new do
|
|
150
|
+
protected
|
|
151
|
+
|
|
152
|
+
def fe_admin? = true
|
|
153
|
+
end
|
|
154
|
+
stub_const('FeProtectedController', klass)
|
|
155
|
+
stub_lists(admin: %w[FeProtectedController])
|
|
156
|
+
|
|
157
|
+
expect(Fe.verify_access_hooks!).to be_nil
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it 'passes when the hooks are private methods' do
|
|
161
|
+
klass = Class.new do
|
|
162
|
+
private
|
|
163
|
+
|
|
164
|
+
def fe_can_use_answer_sheet?(*) = true
|
|
165
|
+
def fe_admin? = true
|
|
166
|
+
end
|
|
167
|
+
stub_const('FePrivateController', klass)
|
|
168
|
+
stub_lists(answer: %w[FePrivateController], admin: %w[FePrivateController])
|
|
169
|
+
|
|
170
|
+
expect(Fe.verify_access_hooks!).to be_nil
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fe
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- CruGlobal
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10
|
|
11
|
+
date: 2026-11-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -322,6 +322,7 @@ files:
|
|
|
322
322
|
- app/assets/stylesheets/fe/fe.screen.css.scss.erb
|
|
323
323
|
- app/assets/stylesheets/fe/reset.css
|
|
324
324
|
- app/assets/stylesheets/fe/validation.css
|
|
325
|
+
- app/controllers/concerns/fe/access_control_concern.rb
|
|
325
326
|
- app/controllers/concerns/fe/admin/question_sheets_controller_concern.rb
|
|
326
327
|
- app/controllers/concerns/fe/answer_pages_controller_concern.rb
|
|
327
328
|
- app/controllers/concerns/fe/answer_sheets_controller_concern.rb
|
|
@@ -533,6 +534,7 @@ files:
|
|
|
533
534
|
- lib/access_key_generator.rb
|
|
534
535
|
- lib/distinct_distinct_patch.rb
|
|
535
536
|
- lib/fe.rb
|
|
537
|
+
- lib/fe/access_control.rb
|
|
536
538
|
- lib/fe/engine.rb
|
|
537
539
|
- lib/fe/version.rb
|
|
538
540
|
- lib/tasks/fe_tasks.rake
|
|
@@ -543,7 +545,7 @@ files:
|
|
|
543
545
|
- spec/controllers/fe/answer_pages_controller_spec.rb
|
|
544
546
|
- spec/controllers/fe/answer_sheets_controller_spec.rb
|
|
545
547
|
- spec/controllers/fe/optimistic_concurrency_spec.rb
|
|
546
|
-
- spec/controllers/fe/
|
|
548
|
+
- spec/controllers/fe/reference_pages_controller_spec.rb
|
|
547
549
|
- spec/controllers/fe/reference_sheets_controller_spec.rb
|
|
548
550
|
- spec/controllers/fe/references_controller_spec.rb
|
|
549
551
|
- spec/controllers/fe/submit_pages_controller_spec.rb
|
|
@@ -573,6 +575,7 @@ files:
|
|
|
573
575
|
- spec/dummy/config/initializers/backtrace_silencers.rb
|
|
574
576
|
- spec/dummy/config/initializers/cookies_serializer.rb
|
|
575
577
|
- spec/dummy/config/initializers/fast_gettext.rb
|
|
578
|
+
- spec/dummy/config/initializers/fe.rb
|
|
576
579
|
- spec/dummy/config/initializers/filter_parameter_logging.rb
|
|
577
580
|
- spec/dummy/config/initializers/inflections.rb
|
|
578
581
|
- spec/dummy/config/initializers/mime_types.rb
|
|
@@ -611,12 +614,10 @@ files:
|
|
|
611
614
|
- spec/dummy/db/migrate/20160204164613_add_visible_and_visibility_cache_key_to_reference_sheets.fe_engine.rb
|
|
612
615
|
- spec/dummy/db/migrate/20181108201746_create_versions.rb
|
|
613
616
|
- spec/dummy/db/schema.rb
|
|
614
|
-
- spec/dummy/log/test.log
|
|
615
617
|
- spec/dummy/public/404.html
|
|
616
618
|
- spec/dummy/public/422.html
|
|
617
619
|
- spec/dummy/public/500.html
|
|
618
620
|
- spec/dummy/public/favicon.ico
|
|
619
|
-
- spec/dummy/tmp/local_secret.txt
|
|
620
621
|
- spec/factories/answer_sheet_question_sheets.rb
|
|
621
622
|
- spec/factories/answer_sheets.rb
|
|
622
623
|
- spec/factories/answers.rb
|
|
@@ -639,6 +640,7 @@ files:
|
|
|
639
640
|
- spec/factories/reference_questions.rb
|
|
640
641
|
- spec/factories/reference_sheets.rb
|
|
641
642
|
- spec/jobs/fe/update_reference_sheet_visibility_job_spec.rb
|
|
643
|
+
- spec/lib/fe/access_control_spec.rb
|
|
642
644
|
- spec/mailers/fe/notifier_spec.rb
|
|
643
645
|
- spec/models/fe/answer_sheet_question_sheet_spec.rb
|
|
644
646
|
- spec/models/fe/answer_spec.rb
|
|
@@ -701,7 +703,7 @@ test_files:
|
|
|
701
703
|
- spec/controllers/fe/answer_pages_controller_spec.rb
|
|
702
704
|
- spec/controllers/fe/answer_sheets_controller_spec.rb
|
|
703
705
|
- spec/controllers/fe/optimistic_concurrency_spec.rb
|
|
704
|
-
- spec/controllers/fe/
|
|
706
|
+
- spec/controllers/fe/reference_pages_controller_spec.rb
|
|
705
707
|
- spec/controllers/fe/reference_sheets_controller_spec.rb
|
|
706
708
|
- spec/controllers/fe/references_controller_spec.rb
|
|
707
709
|
- spec/controllers/fe/submit_pages_controller_spec.rb
|
|
@@ -730,6 +732,7 @@ test_files:
|
|
|
730
732
|
- spec/dummy/config/initializers/backtrace_silencers.rb
|
|
731
733
|
- spec/dummy/config/initializers/cookies_serializer.rb
|
|
732
734
|
- spec/dummy/config/initializers/fast_gettext.rb
|
|
735
|
+
- spec/dummy/config/initializers/fe.rb
|
|
733
736
|
- spec/dummy/config/initializers/filter_parameter_logging.rb
|
|
734
737
|
- spec/dummy/config/initializers/inflections.rb
|
|
735
738
|
- spec/dummy/config/initializers/mime_types.rb
|
|
@@ -769,12 +772,10 @@ test_files:
|
|
|
769
772
|
- spec/dummy/db/migrate/20160204164613_add_visible_and_visibility_cache_key_to_reference_sheets.fe_engine.rb
|
|
770
773
|
- spec/dummy/db/migrate/20181108201746_create_versions.rb
|
|
771
774
|
- spec/dummy/db/schema.rb
|
|
772
|
-
- spec/dummy/log/test.log
|
|
773
775
|
- spec/dummy/public/404.html
|
|
774
776
|
- spec/dummy/public/422.html
|
|
775
777
|
- spec/dummy/public/500.html
|
|
776
778
|
- spec/dummy/public/favicon.ico
|
|
777
|
-
- spec/dummy/tmp/local_secret.txt
|
|
778
779
|
- spec/factories/answer_sheet_question_sheets.rb
|
|
779
780
|
- spec/factories/answer_sheets.rb
|
|
780
781
|
- spec/factories/answers.rb
|
|
@@ -797,6 +798,7 @@ test_files:
|
|
|
797
798
|
- spec/factories/reference_questions.rb
|
|
798
799
|
- spec/factories/reference_sheets.rb
|
|
799
800
|
- spec/jobs/fe/update_reference_sheet_visibility_job_spec.rb
|
|
801
|
+
- spec/lib/fe/access_control_spec.rb
|
|
800
802
|
- spec/mailers/fe/notifier_spec.rb
|
|
801
803
|
- spec/models/fe/answer_sheet_question_sheet_spec.rb
|
|
802
804
|
- spec/models/fe/answer_spec.rb
|