Commit b733c4c0 authored by Reuben Pereira's avatar Reuben Pereira

Allow setting of container registry visibility in project settings UI

Add a select dropdown under
`Settings > General > Visibility, project features, permissions` that
allows project admins to change the visibility of the container
registry.

The container registry visibility can now be set independently of the
project visibility.

Changelog: changed
parent 04550162
......@@ -11,6 +11,7 @@ import {
featureAccessLevel,
featureAccessLevelNone,
CVE_ID_REQUEST_BUTTON_I18N,
featureAccessLevelDescriptions,
} from '../constants';
import { toggleHiddenClassBySelector } from '../external';
import projectFeatureSetting from './project_feature_setting.vue';
......@@ -176,7 +177,7 @@ export default {
requirementsAccessLevel: featureAccessLevel.EVERYONE,
securityAndComplianceAccessLevel: featureAccessLevel.PROJECT_MEMBERS,
operationsAccessLevel: featureAccessLevel.EVERYONE,
containerRegistryEnabled: true,
containerRegistryAccessLevel: featureAccessLevel.EVERYONE,
lfsEnabled: true,
requestAccessEnabled: true,
highlightChangesClass: false,
......@@ -184,6 +185,8 @@ export default {
cveIdRequestEnabled: true,
featureAccessLevelEveryone,
featureAccessLevelMembers,
featureAccessLevel,
featureAccessLevelDescriptions,
};
return { ...defaults, ...this.currentSettings };
......@@ -248,7 +251,10 @@ export default {
},
showContainerRegistryPublicNote() {
return this.visibilityLevel === visibilityOptions.PUBLIC;
return (
this.visibilityLevel === visibilityOptions.PUBLIC &&
this.containerRegistryAccessLevel === featureAccessLevel.EVERYONE
);
},
repositoryHelpText() {
......@@ -310,6 +316,10 @@ export default {
featureAccessLevel.PROJECT_MEMBERS,
this.operationsAccessLevel,
);
this.containerRegistryAccessLevel = Math.min(
featureAccessLevel.PROJECT_MEMBERS,
this.containerRegistryAccessLevel,
);
if (this.pagesAccessLevel === featureAccessLevel.EVERYONE) {
// When from Internal->Private narrow access for only members
this.pagesAccessLevel = featureAccessLevel.PROJECT_MEMBERS;
......@@ -339,6 +349,8 @@ export default {
this.requirementsAccessLevel = featureAccessLevel.EVERYONE;
if (this.operationsAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
this.operationsAccessLevel = featureAccessLevel.EVERYONE;
if (this.containerRegistryAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
this.containerRegistryAccessLevel = featureAccessLevel.EVERYONE;
this.highlightChanges();
}
......@@ -521,19 +533,24 @@ export default {
"
>
<div v-if="showContainerRegistryPublicNote" class="text-muted">
{{
<gl-sprintf
:message="
s__(
'ProjectSettings|Note: the container registry is always visible when a project is public',
`ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'`,
)
}}
"
>
<template #access_level_description>{{
featureAccessLevelDescriptions[featureAccessLevel.EVERYONE]
}}</template>
</gl-sprintf>
</div>
<gl-toggle
v-model="containerRegistryEnabled"
class="gl-my-2"
:disabled="!repositoryEnabled"
<project-feature-setting
v-model="containerRegistryAccessLevel"
:options="repoFeatureAccessLevelOptions"
:disabled-input="!repositoryEnabled"
:label="$options.i18n.containerRegistryLabel"
label-position="hidden"
name="project[container_registry_enabled]"
name="project[project_feature_attributes][container_registry_access_level]"
/>
</project-setting-row>
<project-setting-row
......
......@@ -22,7 +22,7 @@ export const featureAccessLevel = {
EVERYONE: 20,
};
const featureAccessLevelDescriptions = {
export const featureAccessLevelDescriptions = {
[featureAccessLevel.NOT_ENABLED]: __('Enable feature to choose access level'),
[featureAccessLevel.PROJECT_MEMBERS]: __('Only Project Members'),
[featureAccessLevel.EVERYONE]: __('Everyone With Access'),
......
......@@ -745,6 +745,25 @@ You can, however, remove the Container Registry for a project:
The **Packages & Registries > Container Registry** entry is removed from the project's sidebar.
## Set visibility of the Container Registry
By default, the Container Registry is visible to everyone with access to the project.
You can, however, change the visibility of the Container Registry for a project:
1. Go to your project's **Settings > General** page.
1. Expand the section **Visibility, project features, permissions**.
1. Under **Container Registry**, select an option from the dropdown:
- **Everyone With Access** (Default): The Container Registry is visible to everyone with access
to the project. If the project is public, the Container Registry is also public. If the project
is internal or private, the Container Registry is also internal or private.
- **Only Project Members**: The Container Registry is visible only to project members with
Reporter role or higher. This is similar to the behavior of a private project with Container
Registry visibility set to **Everyone With Access**.
1. Select **Save changes**.
## Manifest lists and garbage collection
Manifest lists are commonly used for creating multi-architecture images. If you rely on manifest
......
......@@ -25956,7 +25956,7 @@ msgstr ""
msgid "ProjectSettings|No merge commits are created."
msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
......
import { GlToggle } from '@gitlab/ui';
import { GlSprintf, GlToggle } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
import projectFeatureSetting from '~/pages/projects/shared/permissions/components/project_feature_setting.vue';
import settingsPanel from '~/pages/projects/shared/permissions/components/settings_panel.vue';
......@@ -22,7 +22,7 @@ const defaultProps = {
operationsAccessLevel: 20,
pagesAccessLevel: 10,
analyticsAccessLevel: 20,
containerRegistryEnabled: true,
containerRegistryAccessLevel: 20,
lfsEnabled: true,
emailsDisabled: false,
packagesEnabled: true,
......@@ -85,8 +85,10 @@ describe('Settings Panel', () => {
const findBuildsAccessLevelInput = () =>
wrapper.find('[name="project[project_feature_attributes][builds_access_level]"]');
const findContainerRegistrySettings = () => wrapper.find({ ref: 'container-registry-settings' });
const findContainerRegistryEnabledInput = () =>
wrapper.find('[name="project[container_registry_enabled]"]');
const findContainerRegistryPublicNoteGlSprintfComponent = () =>
findContainerRegistrySettings().findComponent(GlSprintf);
const findContainerRegistryAccessLevelInput = () =>
wrapper.find('[name="project[project_feature_attributes][container_registry_access_level]"]');
const findPackageSettings = () => wrapper.find({ ref: 'package-settings' });
const findPackagesEnabledInput = () => wrapper.find('[name="project[packages_enabled]"]');
const findPagesSettings = () => wrapper.find({ ref: 'pages-settings' });
......@@ -275,24 +277,38 @@ describe('Settings Panel', () => {
it('should show the container registry public note if the visibility level is public and the registry is available', () => {
wrapper = mountComponent({
currentSettings: { visibilityLevel: visibilityOptions.PUBLIC },
currentSettings: {
visibilityLevel: visibilityOptions.PUBLIC,
containerRegistryAccessLevel: featureAccessLevel.EVERYONE,
},
registryAvailable: true,
});
expect(findContainerRegistrySettings().text()).toContain(
'Note: the container registry is always visible when a project is public',
expect(findContainerRegistryPublicNoteGlSprintfComponent().exists()).toBe(true);
expect(findContainerRegistryPublicNoteGlSprintfComponent().attributes('message')).toContain(
`Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'`,
);
});
it('should hide the container registry public note if the visibility level is public but the registry is private', () => {
wrapper = mountComponent({
currentSettings: {
visibilityLevel: visibilityOptions.PUBLIC,
containerRegistryAccessLevel: featureAccessLevel.PROJECT_MEMBERS,
},
registryAvailable: true,
});
expect(findContainerRegistryPublicNoteGlSprintfComponent().exists()).toBe(false);
});
it('should hide the container registry public note if the visibility level is private and the registry is available', () => {
wrapper = mountComponent({
currentSettings: { visibilityLevel: visibilityOptions.PRIVATE },
registryAvailable: true,
});
expect(findContainerRegistrySettings().text()).not.toContain(
'Note: the container registry is always visible when a project is public',
);
expect(findContainerRegistryPublicNoteGlSprintfComponent().exists()).toBe(false);
});
it('should enable the container registry input when the repository is enabled', () => {
......@@ -301,7 +317,7 @@ describe('Settings Panel', () => {
registryAvailable: true,
});
expect(findContainerRegistryEnabledInput().props('disabled')).toBe(false);
expect(findContainerRegistryAccessLevelInput().props('disabledInput')).toBe(false);
});
it('should disable the container registry input when the repository is disabled', () => {
......@@ -310,7 +326,7 @@ describe('Settings Panel', () => {
registryAvailable: true,
});
expect(findContainerRegistryEnabledInput().props('disabled')).toBe(true);
expect(findContainerRegistryAccessLevelInput().props('disabledInput')).toBe(true);
});
it('has label for the toggle', () => {
......@@ -319,7 +335,7 @@ describe('Settings Panel', () => {
registryAvailable: true,
});
expect(findContainerRegistrySettings().findComponent(GlToggle).props('label')).toBe(
expect(findContainerRegistryAccessLevelInput().props('label')).toBe(
settingsPanel.i18n.containerRegistryLabel,
);
});
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment