X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/ce4e75d03a38fc7e4a644a08e3c6044e3a7df390..a154e1e469ea09fd7a54b79367a811dac673d058:/services/api/test/unit/repository_test.rb diff --git a/services/api/test/unit/repository_test.rb b/services/api/test/unit/repository_test.rb index 4e160dd7e1..cb562ef977 100644 --- a/services/api/test/unit/repository_test.rb +++ b/services/api/test/unit/repository_test.rb @@ -1,6 +1,241 @@ +# Copyright (C) The Arvados Authors. All rights reserved. +# +# SPDX-License-Identifier: AGPL-3.0 + require 'test_helper' +require 'helpers/git_test_helper' class RepositoryTest < ActiveSupport::TestCase + include GitTestHelper + + def new_repo(owner_key, attrs={}) + set_user_from_auth owner_key + owner = users(owner_key) + Repository.new({owner_uuid: owner.uuid}.merge(attrs)) + end + + def changed_repo(repo_key, changes) + repo = repositories(repo_key) + changes.each_pair { |attr, value| repo.send("#{attr}=".to_sym, value) } + repo + end + + def default_git_url(repo_name, user_name=nil) + if user_name + "git@git.%s.arvadosapi.com:%s/%s.git" % + [Rails.configuration.ClusterID, user_name, repo_name] + else + "git@git.%s.arvadosapi.com:%s.git" % + [Rails.configuration.ClusterID, repo_name] + end + end + + def assert_server_path(path_tail, repo_sym) + assert_equal(File.join(Rails.configuration.Git.Repositories, path_tail), + repositories(repo_sym).server_path) + end + + ### name validation + + {active: "active/", admin: "admin/", system_user: ""}. + each_pair do |user_sym, name_prefix| + test "valid names for #{user_sym} repo" do + %w(a aa a0 aA Aa AA A0).each do |name| + repo = new_repo(user_sym, name: name_prefix + name) + assert(repo.valid?) + end + end + + test "name is required for #{user_sym} repo" do + refute(new_repo(user_sym).valid?) + end + + test "repo name beginning with numeral is invalid for #{user_sym}" do + repo = new_repo(user_sym, name: "#{name_prefix}0a") + refute(repo.valid?) + end + + test "name containing bad char is invalid for #{user_sym}" do + "\\.-_/!@#$%^&*()[]{}".each_char do |bad_char| + repo = new_repo(user_sym, name: "#{name_prefix}bad#{bad_char}reponame") + refute(repo.valid?) + end + end + end + + test "admin can create valid repo for other user with correct name prefix" do + owner = users(:active) + repo = new_repo(:admin, name: "#{owner.username}/validnametest", + owner_uuid: owner.uuid) + assert(repo.valid?) + end + + test "admin can create valid system repo without name prefix" do + repo = new_repo(:admin, name: "validnametest", + owner_uuid: users(:system_user).uuid) + assert(repo.valid?) + end + + test "repo name prefix must match owner_uuid username" do + repo = new_repo(:admin, name: "admin/badusernametest", + owner_uuid: users(:active).uuid) + refute(repo.valid?) + end + + test "repo name prefix must be empty for system repo" do + repo = new_repo(:admin, name: "root/badprefixtest", + owner_uuid: users(:system_user).uuid) + refute(repo.valid?) + end + + ### owner validation + + test "name must be unique per user" do + repo = new_repo(:active, name: repositories(:foo).name) + refute(repo.valid?) + end + + test "name can be duplicated across users" do + repo = new_repo(:active, name: "active/#{repositories(:arvados).name}") + assert(repo.valid?) + end + + test "repository cannot be owned by a group" do + set_user_from_auth :active + repo = Repository.new(owner_uuid: groups(:all_users).uuid, + name: "ownedbygroup") + refute(repo.valid?) + refute_empty(repo.errors[:owner_uuid] || []) + end + + ### URL generation + + test "fetch_url" do + repo = new_repo(:active, name: "active/fetchtest") + repo.save + assert_equal(default_git_url("fetchtest", "active"), repo.fetch_url) + end + + test "fetch_url owned by system user" do + set_user_from_auth :admin + repo = Repository.new(owner_uuid: users(:system_user).uuid, + name: "fetchtest") + repo.save + assert_equal(default_git_url("fetchtest"), repo.fetch_url) + end + + test "push_url" do + repo = new_repo(:active, name: "active/pushtest") + repo.save + assert_equal(default_git_url("pushtest", "active"), repo.push_url) + end + + test "push_url owned by system user" do + set_user_from_auth :admin + repo = Repository.new(owner_uuid: users(:system_user).uuid, + name: "pushtest") + repo.save + assert_equal(default_git_url("pushtest"), repo.push_url) + end + + ### Path generation + + test "disk path stored by UUID" do + assert_server_path("zzzzz-s0uqq-382brsig8rp3666/.git", :foo) + end + + test "disk path stored by name" do + assert_server_path("arvados/.git", :arvados) + end + + test "disk path for repository not on disk" do + assert_nil(Repository.new.server_path) + end + + ### Repository creation + + test "non-admin can create a repository for themselves" do + repo = new_repo(:active, name: "active/newtestrepo") + assert(repo.save) + end + + test "non-admin can't create a repository for another visible user" do + repo = new_repo(:active, name: "repoforanon", + owner_uuid: users(:anonymous).uuid) + assert_not_allowed { repo.save } + end + + test "admin can create a repository for themselves" do + repo = new_repo(:admin, name: "admin/newtestrepo") + assert(repo.save) + end + + test "admin can create a repository for others" do + repo = new_repo(:admin, name: "active/repoforactive", + owner_uuid: users(:active).uuid) + assert(repo.save) + end + + test "admin can create a system repository" do + repo = new_repo(:admin, name: "repoforsystem", + owner_uuid: users(:system_user).uuid) + assert(repo.save) + end + + ### Repository destruction + + test "non-admin can destroy their own repository" do + set_user_from_auth :active + assert(repositories(:foo).destroy) + end + + test "non-admin can't destroy others' repository" do + set_user_from_auth :active + assert_not_allowed { repositories(:repository3).destroy } + end + + test "non-admin can't destroy system repository" do + set_user_from_auth :active + assert_not_allowed { repositories(:arvados).destroy } + end + + test "admin can destroy their own repository" do + set_user_from_auth :admin + assert(repositories(:repository3).destroy) + end + + test "admin can destroy others' repository" do + set_user_from_auth :admin + assert(repositories(:foo).destroy) + end + + test "admin can destroy system repository" do + set_user_from_auth :admin + assert(repositories(:arvados).destroy) + end + + ### Changing ownership + + test "non-admin can't make their repository a system repository" do + set_user_from_auth :active + repo = changed_repo(:foo, owner_uuid: users(:system_user).uuid) + assert_not_allowed { repo.save } + end + + test "admin can give their repository to someone else" do + set_user_from_auth :admin + repo = changed_repo(:repository3, owner_uuid: users(:active).uuid, + name: "active/foo3") + assert(repo.save) + end + + test "admin can make their repository a system repository" do + set_user_from_auth :admin + repo = changed_repo(:repository3, owner_uuid: users(:system_user).uuid, + name: "foo3") + assert(repo.save) + end + test 'write permission allows changing modified_at' do act_as_user users(:active) do r = repositories(:foo) @@ -11,19 +246,6 @@ class RepositoryTest < ActiveSupport::TestCase end end - test 'write permission not sufficient for changing name' do - act_as_user users(:active) do - r = repositories(:foo) - name_was = r.name - r.name = 'newname' - assert_raises ArvadosModel::PermissionDeniedError do - r.save! - end - r.reload - assert_equal name_was, r.name - end - end - test 'write permission necessary for changing modified_at' do act_as_user users(:spectator) do r = repositories(:foo) @@ -36,4 +258,26 @@ class RepositoryTest < ActiveSupport::TestCase assert_equal modtime_was, r.modified_at end end + + ### Renaming + + test "non-admin can rename own repo" do + act_as_user users(:active) do + assert repositories(:foo).update_attributes(name: 'active/foo12345') + end + end + + test "top level repo can be touched by non-admin with can_manage" do + add_permission_link users(:active), repositories(:arvados), 'can_manage' + act_as_user users(:active) do + assert changed_repo(:arvados, modified_at: Time.now).save + end + end + + test "top level repo cannot be renamed by non-admin with can_manage" do + add_permission_link users(:active), repositories(:arvados), 'can_manage' + act_as_user users(:active) do + assert_not_allowed { changed_repo(:arvados, name: 'xarvados').save } + end + end end