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