Merge branch '6663-git-server' refs #6663
[arvados.git] / apps / workbench / test / integration / anonymous_access_test.rb
1 require 'integration_helper'
2
3 class AnonymousAccessTest < ActionDispatch::IntegrationTest
4   # These tests don't do state-changing API calls. Save some time by
5   # skipping the database reset.
6   reset_api_fixtures :after_each_test, false
7   reset_api_fixtures :after_suite, true
8
9   setup do
10     need_javascript
11     Rails.configuration.anonymous_user_token = api_fixture('api_client_authorizations')['anonymous']['api_token']
12   end
13
14   PUBLIC_PROJECT = "/projects/#{api_fixture('groups')['anonymously_accessible_project']['uuid']}"
15
16   def verify_site_navigation_anonymous_enabled user, is_active
17     if user
18       if user['is_active']
19         assert_text 'Unrestricted public data'
20         assert_selector 'a', text: 'Projects'
21         page.find("#projects-menu").click
22         assert_selector 'a', text: 'Add a new project'
23         assert_selector 'a', text: 'Browse public projects'
24         assert page.has_text?('Projects shared with me'), 'Not found text - Project shared with me'
25       else
26         assert_text 'indicate that you have read and accepted the user agreement'
27       end
28       within('.navbar-fixed-top') do
29         assert_selector 'a', text: Rails.configuration.site_name.downcase
30         assert(page.has_link?("notifications-menu"), 'no user menu')
31         page.find("#notifications-menu").click
32         within('.dropdown-menu') do
33           assert_selector 'a', text: 'Log out'
34         end
35       end
36     else  # anonymous
37       assert_text 'Unrestricted public data'
38       within('.navbar-fixed-top') do
39         assert_text Rails.configuration.site_name.downcase
40         assert_no_selector 'a', text: Rails.configuration.site_name.downcase
41         assert_selector 'a', text: 'Log in'
42         assert_selector 'a', text: 'Browse public projects'
43       end
44     end
45   end
46
47   [
48     [nil, nil, false, false],
49     ['inactive', api_fixture('users')['inactive'], false, false],
50     ['active', api_fixture('users')['active'], true, true],
51   ].each do |token, user, is_active|
52     test "visit public project as user #{token.inspect} when anonymous browsing is enabled" do
53       if !token
54         visit PUBLIC_PROJECT
55       else
56         visit page_with_token(token, PUBLIC_PROJECT)
57       end
58
59       verify_site_navigation_anonymous_enabled user, is_active
60     end
61   end
62
63   test "selection actions when anonymous user accesses shared project" do
64     visit PUBLIC_PROJECT
65
66     assert_selector 'a', text: 'Description'
67     assert_selector 'a', text: 'Data collections'
68     assert_selector 'a', text: 'Jobs and pipelines'
69     assert_selector 'a', text: 'Pipeline templates'
70     assert_selector 'a', text: 'Subprojects'
71     assert_selector 'a', text: 'Advanced'
72     assert_no_selector 'a', text: 'Other objects'
73     assert_no_selector 'button', text: 'Add data'
74
75     click_link 'Data collections'
76     click_button 'Selection'
77     within('.selection-action-container') do
78       assert_selector 'li', text: 'Compare selected'
79       assert_no_selector 'li', text: 'Create new collection with selected collections'
80       assert_no_selector 'li', text: 'Copy selected'
81       assert_no_selector 'li', text: 'Move selected'
82       assert_no_selector 'li', text: 'Remove selected'
83     end
84   end
85
86   test "anonymous user accesses data collections tab in shared project" do
87     visit PUBLIC_PROJECT
88     click_link 'Data collections'
89     collection = api_fixture('collections')['user_agreement_in_anonymously_accessible_project']
90     assert_text 'GNU General Public License'
91
92     assert_selector 'a', text: 'Data collections'
93
94     # click on show collection
95     within "tr[data-object-uuid=\"#{collection['uuid']}\"]" do
96       click_link 'Show'
97     end
98
99     # in collection page
100     assert_no_selector 'input', text: 'Create sharing link'
101     assert_no_text 'Sharing and permissions'
102     assert_no_selector 'a', text: 'Upload'
103     assert_no_selector 'button', 'Selection'
104
105     within '#collection_files tr,li', text: 'GNU_General_Public_License,_version_3.pdf' do
106       assert page.has_no_selector?('[value*="GNU_General_Public_License"]')
107       find 'a[title~=View]'
108       find 'a[title~=Download]'
109     end
110   end
111
112   test 'view file' do
113     magic = rand(2**512).to_s 36
114     CollectionsController.any_instance.stubs(:file_enumerator).returns([magic])
115     collection = api_fixture('collections')['public_text_file']
116     visit '/collections/' + collection['uuid']
117     find('tr,li', text: 'Hello world.txt').
118       find('a[title~=View]').click
119     assert_text magic
120   end
121
122   [
123     'running_job',
124     'completed_job',
125     'pipelineInstance'
126   ].each do |type|
127     test "anonymous user accesses jobs and pipelines tab in shared project and clicks on #{type}" do
128       visit PUBLIC_PROJECT
129       click_link 'Data collections'
130       assert_text 'GNU General Public License'
131
132       click_link 'Jobs and pipelines'
133       assert_text 'Pipeline in publicly accessible project'
134
135       # click on the specified job
136       if type.include? 'job'
137         verify_job_row type
138       else
139         verify_pipeline_instance_row
140       end
141     end
142   end
143
144   def verify_job_row look_for
145     within first('tr', text: look_for) do
146       click_link 'Show'
147     end
148     assert_text 'Public Projects Unrestricted public data'
149     assert_text 'script_version'
150
151     assert_text 'zzzzz-tpzed-xurymjxw79nv3jz' # modified by user
152     assert_no_selector 'a', text: 'zzzzz-tpzed-xurymjxw79nv3jz'
153     assert_no_selector 'a', text: 'Move job'
154     assert_no_selector 'button', text: 'Cancel'
155     assert_no_selector 'button', text: 'Re-run job'
156   end
157
158   def verify_pipeline_instance_row
159     within first('tr[data-kind="arvados#pipelineInstance"]') do
160       assert_text 'Pipeline in publicly accessible project'
161       click_link 'Show'
162     end
163
164     # in pipeline instance page
165     assert_text 'Public Projects Unrestricted public data'
166     assert_text 'This pipeline is complete'
167     assert_no_selector 'a', text: 'Re-run with latest'
168     assert_no_selector 'a', text: 'Re-run options'
169   end
170
171   test "anonymous user accesses pipeline templates tab in shared project" do
172     visit PUBLIC_PROJECT
173     click_link 'Data collections'
174     assert_text 'GNU General Public License'
175
176     assert_selector 'a', text: 'Pipeline templates'
177
178     click_link 'Pipeline templates'
179     assert_text 'Pipeline template in publicly accessible project'
180
181     within first('tr[data-kind="arvados#pipelineTemplate"]') do
182       click_link 'Show'
183     end
184
185     # in template page
186     assert_text 'Public Projects Unrestricted public data'
187     assert_text 'script version'
188     assert_no_selector 'a', text: 'Run this pipeline'
189   end
190
191   test "anonymous user accesses subprojects tab in shared project" do
192     visit PUBLIC_PROJECT + '#Subprojects'
193
194     assert_text 'Subproject in anonymous accessible project'
195
196     within first('tr[data-kind="arvados#group"]') do
197       click_link 'Show'
198     end
199
200     # in subproject
201     assert_text 'Description for subproject in anonymous accessible project'
202   end
203
204   [
205     ['pipeline_in_publicly_accessible_project', true],
206     ['pipeline_in_publicly_accessible_project_but_other_objects_elsewhere', false],
207     ['pipeline_in_publicly_accessible_project_but_other_objects_elsewhere', false, 'spectator'],
208     ['pipeline_in_publicly_accessible_project_but_other_objects_elsewhere', true, 'admin'],
209
210     ['completed_job_in_publicly_accessible_project', true],
211     ['job_in_publicly_accessible_project_but_other_objects_elsewhere', false],
212   ].each do |fixture, objects_readable, user=nil|
213     test "access #{fixture} in public project with objects readable=#{objects_readable} with user #{user}" do
214       pipeline_page = true if fixture.include?('pipeline')
215
216       if pipeline_page
217         object = api_fixture('pipeline_instances')[fixture]
218         page = "/pipeline_instances/#{object['uuid']}"
219         expect_log_text = "Log for foo"
220       else      # job
221         object = api_fixture('jobs')[fixture]
222         page = "/jobs/#{object['uuid']}"
223         expect_log_text = "stderr crunchstat"
224       end
225
226       if user
227         visit page_with_token user, page
228       else
229         visit page
230       end
231
232       # click job link, if in pipeline page
233       click_link 'foo' if pipeline_page
234
235       if objects_readable
236         assert_selector 'a[href="#Log"]', text: 'Log'
237         assert_no_selector 'a[data-toggle="disabled"]', text: 'Log'
238         assert_no_text 'Output data not available'
239         if pipeline_page
240           assert_text 'This pipeline was created from'
241           assert_selector 'a', text: object['components']['foo']['job']['uuid']
242           # We'd like to test the Log tab on job pages too, but we can't right
243           # now because Poltergeist 1.x doesn't support JavaScript's
244           # Function.prototype.bind, which is used by job_log_graph.js.
245           click_link "Log"
246           assert_text expect_log_text
247         end
248       else
249         assert_selector 'a[data-toggle="disabled"]', text: 'Log'
250         assert_text 'Output data not available'
251         assert_text object['job']
252         if pipeline_page
253           assert_no_text 'This pipeline was created from'  # template is not readable
254           assert_no_selector 'a', text: object['components']['foo']['job']['uuid']
255         end
256         click_link "Log"
257         assert_text 'Output data not available'
258         assert_no_text expect_log_text
259       end
260     end
261   end
262
263   [
264     ['new_pipeline_in_publicly_accessible_project', true],
265     ['new_pipeline_in_publicly_accessible_project', true, 'spectator'],
266     ['new_pipeline_in_publicly_accessible_project_but_other_objects_elsewhere', false],
267     ['new_pipeline_in_publicly_accessible_project_but_other_objects_elsewhere', false, 'spectator'],
268     ['new_pipeline_in_publicly_accessible_project_but_other_objects_elsewhere', true, 'admin'],
269     ['new_pipeline_in_publicly_accessible_project_with_dataclass_file_and_other_objects_elsewhere', false],
270     ['new_pipeline_in_publicly_accessible_project_with_dataclass_file_and_other_objects_elsewhere', false, 'spectator'],
271     ['new_pipeline_in_publicly_accessible_project_with_dataclass_file_and_other_objects_elsewhere', true, 'admin'],
272   ].each do |fixture, objects_readable, user=nil|
273     test "access #{fixture} in public project with objects readable=#{objects_readable} with user #{user}" do
274       object = api_fixture('pipeline_instances')[fixture]
275       page = "/pipeline_instances/#{object['uuid']}"
276       if user
277         visit page_with_token user, page
278       else
279         visit page
280       end
281
282       # click Components tab
283       click_link 'Components'
284
285       if objects_readable
286         assert_text 'This pipeline was created from'
287         if user == 'admin'
288           assert_text 'input'
289           assert_selector 'a', text: 'Choose'
290           assert_selector 'a', text: 'Run'
291           assert_no_selector 'a.disabled', text: 'Run'
292         else
293           assert_selector 'a', text: object['components']['foo']['script_parameters']['input']['value']
294           user ? (assert_selector 'a', text: 'Run') : (assert_no_selector 'a', text: 'Run')
295         end
296       else
297         assert_no_text 'This pipeline was created from'  # template is not readable
298         input = object['components']['foo']['script_parameters']['input']['value']
299         assert_no_selector 'a', text: input
300         if user
301           input = input.gsub('/', '\\/')
302           assert_text "One or more inputs provided are not readable"
303           assert_selector "input[type=text][value=#{input}]"
304           assert_selector 'a.disabled', text: 'Run'
305         else
306           assert_no_text "One or more inputs provided are not readable"
307           assert_text input
308           assert_no_selector 'a', text: 'Run'
309         end
310       end
311     end
312   end
313 end