Create container repository on successful push auth
Because we do not have yet two way communication between container registry and GitLab, we need to eagerly create a new container repository objects in database. We now do that after user/build successfully authenticates a push action using auth service.
This commit is contained in:
parent
236c9c1703
commit
7d3d1ec5a7
4 changed files with 70 additions and 5 deletions
|
@ -60,6 +60,7 @@ class ContainerRepository < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def self.create_from_path(path)
|
||||
self.create(project: path.repository_project, name: path.repository_name)
|
||||
self.create(project: path.repository_project,
|
||||
name: path.repository_name)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -74,9 +74,25 @@ module Auth
|
|||
|
||||
return unless actions.present?
|
||||
|
||||
# At this point user/build is already authenticated.
|
||||
#
|
||||
ensure_container_repository!(path, actions)
|
||||
|
||||
{ type: type, name: path.to_s, actions: actions }
|
||||
end
|
||||
|
||||
##
|
||||
# Because we do not have two way communication with registry yet,
|
||||
# we create a container repository image resource when push to the
|
||||
# registry is successfuly authorized.
|
||||
#
|
||||
def ensure_container_repository!(path, actions)
|
||||
return if path.has_repository?
|
||||
return unless actions.include?('push')
|
||||
|
||||
ContainerRepository.create_from_path(path)
|
||||
end
|
||||
|
||||
def can_access?(requested_project, requested_action)
|
||||
return false unless requested_project.container_registry_enabled?
|
||||
|
||||
|
|
|
@ -44,6 +44,10 @@ module ContainerRegistry
|
|||
.where(name: repository_name).any?
|
||||
end
|
||||
|
||||
def root_repository?
|
||||
@path == repository_project.full_path
|
||||
end
|
||||
|
||||
def repository_project
|
||||
@project ||= Project.where_full_path_in(components.first(3))&.first
|
||||
end
|
||||
|
|
|
@ -80,6 +80,19 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
it { is_expected.not_to include(:token) }
|
||||
end
|
||||
|
||||
shared_examples 'container repository factory' do
|
||||
it 'creates a new containe repository resource' do
|
||||
expect { subject }
|
||||
.to change { project.container_repositories.count }.by(1)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'container repository factory' do
|
||||
it 'does not create a new container repository resource' do
|
||||
expect { subject }.not_to change { ContainerRepository.count }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#full_access_token' do
|
||||
let(:project) { create(:empty_project) }
|
||||
let(:token) { described_class.full_access_token(project.path_with_namespace) }
|
||||
|
@ -89,6 +102,8 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
it_behaves_like 'an accessible' do
|
||||
let(:actions) { ['*'] }
|
||||
end
|
||||
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
|
||||
context 'user authorization' do
|
||||
|
@ -109,16 +124,20 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
end
|
||||
|
||||
it_behaves_like 'a pushable'
|
||||
it_behaves_like 'container repository factory'
|
||||
end
|
||||
|
||||
context 'allow reporter to pull images' do
|
||||
before { project.team << [current_user, :reporter] }
|
||||
|
||||
let(:current_params) do
|
||||
{ scope: "repository:#{project.path_with_namespace}:pull" }
|
||||
end
|
||||
context 'when pulling from root level repository' do
|
||||
let(:current_params) do
|
||||
{ scope: "repository:#{project.path_with_namespace}:pull" }
|
||||
end
|
||||
|
||||
it_behaves_like 'a pullable'
|
||||
it_behaves_like 'a pullable'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
end
|
||||
|
||||
context 'return a least of privileges' do
|
||||
|
@ -129,6 +148,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
end
|
||||
|
||||
it_behaves_like 'a pullable'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
|
||||
context 'disallow guest to pull or push images' do
|
||||
|
@ -139,6 +159,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
end
|
||||
|
||||
it_behaves_like 'an inaccessible'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -151,6 +172,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
end
|
||||
|
||||
it_behaves_like 'a pullable'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
|
||||
context 'disallow anyone to push images' do
|
||||
|
@ -159,6 +181,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
end
|
||||
|
||||
it_behaves_like 'an inaccessible'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -172,6 +195,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
end
|
||||
|
||||
it_behaves_like 'a pullable'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
|
||||
context 'disallow anyone to push images' do
|
||||
|
@ -180,6 +204,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
end
|
||||
|
||||
it_behaves_like 'an inaccessible'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -190,6 +215,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
end
|
||||
|
||||
it_behaves_like 'an inaccessible'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -216,6 +242,10 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
it_behaves_like 'a pullable and pushable' do
|
||||
let(:project) { current_project }
|
||||
end
|
||||
|
||||
it_behaves_like 'container repository factory' do
|
||||
let(:project) { current_project }
|
||||
end
|
||||
end
|
||||
|
||||
context 'for other projects' do
|
||||
|
@ -228,11 +258,13 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
let(:project) { create(:empty_project, :public) }
|
||||
|
||||
it_behaves_like 'a pullable'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
|
||||
shared_examples 'pullable for being team member' do
|
||||
context 'when you are not member' do
|
||||
it_behaves_like 'an inaccessible'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
|
||||
context 'when you are member' do
|
||||
|
@ -241,12 +273,14 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
end
|
||||
|
||||
it_behaves_like 'a pullable'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
|
||||
context 'when you are owner' do
|
||||
let(:project) { create(:empty_project, namespace: current_user.namespace) }
|
||||
|
||||
it_behaves_like 'a pullable'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -260,6 +294,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
|
||||
context 'when you are not member' do
|
||||
it_behaves_like 'an inaccessible'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
|
||||
context 'when you are member' do
|
||||
|
@ -268,12 +303,14 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
end
|
||||
|
||||
it_behaves_like 'a pullable'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
|
||||
context 'when you are owner' do
|
||||
let(:project) { create(:empty_project, namespace: current_user.namespace) }
|
||||
|
||||
it_behaves_like 'a pullable'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -293,12 +330,14 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
end
|
||||
|
||||
it_behaves_like 'an inaccessible'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
|
||||
context 'when you are owner' do
|
||||
let(:project) { create(:empty_project, :public, namespace: current_user.namespace) }
|
||||
|
||||
it_behaves_like 'an inaccessible'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -315,6 +354,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
end
|
||||
|
||||
it_behaves_like 'an inaccessible'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -322,6 +362,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
context 'unauthorized' do
|
||||
context 'disallow to use scope-less authentication' do
|
||||
it_behaves_like 'a forbidden'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
|
||||
context 'for invalid scope' do
|
||||
|
@ -330,6 +371,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
end
|
||||
|
||||
it_behaves_like 'a forbidden'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
|
||||
context 'for private project' do
|
||||
|
@ -351,6 +393,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
end
|
||||
|
||||
it_behaves_like 'a pullable'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
|
||||
context 'when pushing' do
|
||||
|
@ -359,6 +402,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
|
|||
end
|
||||
|
||||
it_behaves_like 'a forbidden'
|
||||
it_behaves_like 'not a container repository factory'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue