Merge branch '21205-ensure-unique' refs #21205
[arvados.git] / services / api / test / functional / arvados / v1 / repositories_controller_test.rb
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: AGPL-3.0
4
5 require 'test_helper'
6
7 class Arvados::V1::RepositoriesControllerTest < ActionController::TestCase
8   test "should get_all_logins with admin token" do
9     authorize_with :admin
10     get :get_all_permissions
11     assert_response :success
12   end
13
14   test "should get_all_logins with non-admin token" do
15     authorize_with :active
16     get :get_all_permissions
17     assert_response 403
18   end
19
20   test "get_all_permissions gives RW to repository owner" do
21     authorize_with :admin
22     get :get_all_permissions
23     assert_response :success
24     ok = false
25     json_response['repositories'].each do |repo|
26       if repo['uuid'] == repositories(:repository2).uuid
27         if repo['user_permissions'][users(:active).uuid]['can_write']
28           ok = true
29         end
30       end
31     end
32     assert_equal(true, ok,
33                  "No permission on own repo '@{repositories(:repository2).uuid}'")
34   end
35
36   test "get_all_permissions takes into account is_admin flag" do
37     authorize_with :admin
38     get :get_all_permissions
39     assert_response :success
40     json_response['repositories'].each do |repo|
41       assert_not_nil(repo['user_permissions'][users(:admin).uuid],
42                      "Admin user is not listed in perms for #{repo['uuid']}")
43       assert_equal(true,
44                    repo['user_permissions'][users(:admin).uuid]['can_write'],
45                    "Admin has no perms for #{repo['uuid']}")
46     end
47   end
48
49   test "get_all_permissions takes into account is_active flag" do
50     act_as_user users(:active) do
51       Repository.create! name: 'active/testrepo'
52     end
53     act_as_system_user do
54       u = users(:active)
55       u.unsetup
56       u.save!
57     end
58     authorize_with :admin
59     get :get_all_permissions
60     assert_response :success
61     json_response['repositories'].each do |r|
62       r['user_permissions'].each do |user_uuid, perms|
63         refute_equal user_uuid, users(:active).uuid
64       end
65     end
66   end
67
68   test "get_all_permissions does not give any access to user without permission" do
69     viewer_uuid = users(:project_viewer).uuid
70     assert_equal(authorized_keys(:project_viewer).authorized_user_uuid,
71                  viewer_uuid,
72                  "project_viewer must have an authorized_key for this test to work")
73     authorize_with :admin
74     get :get_all_permissions
75     assert_response :success
76     readable_repos = json_response["repositories"].select do |repo|
77       repo["user_permissions"].has_key?(viewer_uuid)
78     end
79     assert_equal(["arvados"], readable_repos.map { |r| r["name"] },
80                  "project_viewer should only have permissions on public repos")
81   end
82
83   test "get_all_permissions gives gitolite R to user with read-only access" do
84     authorize_with :admin
85     get :get_all_permissions
86     assert_response :success
87     found_it = false
88     assert_equal(authorized_keys(:spectator).authorized_user_uuid,
89                  users(:spectator).uuid,
90                  "spectator must have an authorized_key for this test to work")
91     json_response['repositories'].each do |repo|
92       next unless repo['uuid'] == repositories(:foo).uuid
93       assert_equal('R',
94                    repo['user_permissions'][users(:spectator).uuid]['gitolite_permissions'],
95                    "spectator user should have just R access to #{repo['uuid']}")
96       found_it = true
97     end
98     assert_equal true, found_it, "spectator user does not have R on foo repo"
99   end
100
101   test "get_all_permissions provides admin and active user keys" do
102     authorize_with :admin
103     get :get_all_permissions
104     assert_response :success
105     [:active, :admin].each do |u|
106       assert_equal(1, json_response['user_keys'][users(u).uuid].andand.count,
107                    "expected 1 key for #{u} (#{users(u).uuid})")
108       assert_equal(json_response['user_keys'][users(u).uuid][0]['public_key'],
109                    authorized_keys(u).public_key,
110                    "response public_key does not match fixture #{u}.")
111     end
112   end
113
114   test "get_all_permissions lists all repos regardless of permissions" do
115     act_as_system_user do
116       # Create repos that could potentially be left out of the
117       # permission list by accident.
118
119       # No authorized_key, no username (this can't even be done
120       # without skipping validations)
121       r = Repository.create name: 'root/testrepo'
122       assert r.save validate: false
123
124       r = Repository.create name: 'invalid username / repo name', owner_uuid: users(:inactive).uuid
125       assert r.save validate: false
126     end
127     authorize_with :admin
128     get :get_all_permissions
129     assert_response :success
130     assert_equal(Repository.count, json_response["repositories"].size)
131   end
132
133   test "get_all_permissions lists user permissions for users with no authorized keys" do
134     authorize_with :admin
135     AuthorizedKey.destroy_all
136     get :get_all_permissions
137     assert_response :success
138     assert_equal(Repository.count, json_response["repositories"].size)
139     repos_with_perms = []
140     json_response['repositories'].each do |repo|
141       if repo['user_permissions'].any?
142         repos_with_perms << repo['uuid']
143       end
144     end
145     assert_not_empty repos_with_perms, 'permissions are missing'
146   end
147
148   # Ensure get_all_permissions correctly describes what the normal
149   # permission system would do.
150   test "get_all_permissions obeys group permissions" do
151     act_as_user system_user do
152       r = Repository.create!(name: 'admin/groupcanwrite', owner_uuid: users(:admin).uuid)
153       g = Group.create!(group_class: 'role', name: 'repo-writers')
154       u1 = users(:active)
155       u2 = users(:spectator)
156       Link.create!(tail_uuid: g.uuid, head_uuid: r.uuid, link_class: 'permission', name: 'can_manage')
157       Link.create!(tail_uuid: u1.uuid, head_uuid: g.uuid, link_class: 'permission', name: 'can_write')
158       Link.create!(tail_uuid: u2.uuid, head_uuid: g.uuid, link_class: 'permission', name: 'can_read')
159
160       r = Repository.create!(name: 'admin/groupreadonly', owner_uuid: users(:admin).uuid)
161       g = Group.create!(group_class: 'role', name: 'repo-readers')
162       u1 = users(:active)
163       u2 = users(:spectator)
164       Link.create!(tail_uuid: g.uuid, head_uuid: r.uuid, link_class: 'permission', name: 'can_read')
165       Link.create!(tail_uuid: u1.uuid, head_uuid: g.uuid, link_class: 'permission', name: 'can_write')
166       Link.create!(tail_uuid: u2.uuid, head_uuid: g.uuid, link_class: 'permission', name: 'can_read')
167     end
168     authorize_with :admin
169     get :get_all_permissions
170     assert_response :success
171     json_response['repositories'].each do |repo|
172       repo['user_permissions'].each do |user_uuid, perms|
173         u = User.find_by_uuid(user_uuid)
174         if perms['can_read']
175           assert u.can? read: repo['uuid']
176           assert_match(/R/, perms['gitolite_permissions'])
177         else
178           refute_match(/R/, perms['gitolite_permissions'])
179         end
180         if perms['can_write']
181           assert u.can? write: repo['uuid']
182           assert_match(/RW\+/, perms['gitolite_permissions'])
183         else
184           refute_match(/W/, perms['gitolite_permissions'])
185         end
186         if perms['can_manage']
187           assert u.can? manage: repo['uuid']
188           assert_match(/RW\+/, perms['gitolite_permissions'])
189         end
190       end
191     end
192   end
193
194   test "default index includes fetch_url" do
195     authorize_with :active
196     get(:index)
197     assert_response :success
198     assert_includes(json_response["items"].map { |r| r["fetch_url"] },
199                     "git@git.zzzzz.arvadosapi.com:active/foo.git")
200   end
201
202   [
203     {cfg: "GitSSH.ExternalURL", cfgval: URI("ssh://git@example.com"), match: %r"^git@example.com:"},
204     {cfg: "GitSSH.ExternalURL", cfgval: URI(""), match: %r"^git@git.zzzzz.arvadosapi.com:"},
205     {cfg: "GitSSH", cfgval: false, refute: /^git@/ },
206     {cfg: "GitHTTP.ExternalURL", cfgval: URI("https://example.com/"), match: %r"^https://example.com/"},
207     {cfg: "GitHTTP.ExternalURL", cfgval: URI(""), match: %r"^https://git.zzzzz.arvadosapi.com/"},
208     {cfg: "GitHTTP", cfgval: false, refute: /^http/ },
209   ].each do |expect|
210     test "set #{expect[:cfg]} to #{expect[:cfgval]}" do
211       ConfigLoader.set_cfg Rails.configuration.Services, expect[:cfg].to_s, expect[:cfgval]
212       authorize_with :active
213       get :index
214       assert_response :success
215       assert_not_empty json_response['items']
216       json_response['items'].each do |r|
217         if expect[:refute]
218           r['clone_urls'].each do |u|
219             refute_match expect[:refute], u
220           end
221         else
222           assert((r['clone_urls'].any? do |u|
223                     expect[:match].match u
224                   end),
225                  "no match for #{expect[:match]} in #{r['clone_urls'].inspect}")
226         end
227       end
228     end
229   end
230
231   test "select push_url in index" do
232     authorize_with :active
233     get(:index, params: {select: ["uuid", "push_url"]})
234     assert_response :success
235     assert_includes(json_response["items"].map { |r| r["push_url"] },
236                     "git@git.zzzzz.arvadosapi.com:active/foo.git")
237   end
238
239   test "select clone_urls in index" do
240     authorize_with :active
241     get(:index, params: {select: ["uuid", "clone_urls"]})
242     assert_response :success
243     assert_includes(json_response["items"].map { |r| r["clone_urls"] }.flatten,
244                     "git@git.zzzzz.arvadosapi.com:active/foo.git")
245   end
246 end