Commit a5652f2f authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab-ce master

parents 61c50f0c 8b55aaee
......@@ -8,8 +8,7 @@ class Projects::TagsController < Projects::ApplicationController
# Authorize
before_action :require_non_empty_project
before_action :authorize_download_code!
before_action :authorize_push_code!, only: [:new, :create]
before_action :authorize_admin_project!, only: [:destroy]
before_action :authorize_admin_tag!, only: [:new, :create, :destroy]
# rubocop: disable CodeReuse/ActiveRecord
def index
......
......@@ -297,6 +297,7 @@ class ProjectPolicy < BasePolicy
end
rule { (mirror_available & can?(:admin_project)) | admin }.enable :admin_remote_mirror
rule { can?(:push_code) }.enable :admin_tag
rule { archived }.policy do
prevent :push_code
......
......@@ -26,10 +26,8 @@
.row-fixed-content.controls.flex-row
= render 'projects/buttons/download', project: @project, ref: tag.name, pipeline: @tags_pipelines[tag.name]
- if can?(current_user, :push_code, @project)
- if can?(current_user, :admin_tag, @project)
= link_to edit_project_tag_release_path(@project, tag.name), class: 'btn btn-edit has-tooltip', title: s_('TagsPage|Edit release notes'), data: { container: "body" } do
= icon("pencil")
- if can?(current_user, :admin_project, @project)
= link_to project_tag_path(@project, tag.name), class: "btn btn-remove remove-row has-tooltip prepend-left-10 #{protected_tag?(@project, tag) ? 'disabled' : ''}", title: s_('TagsPage|Delete tag'), method: :delete, data: { confirm: s_('TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?') % { tag_name: tag.name }, container: 'body' }, remote: true do
= icon("trash-o")
= link_to project_tag_path(@project, tag.name), class: "btn btn-remove remove-row has-tooltip prepend-left-10 #{protected_tag?(@project, tag) ? 'disabled' : ''}", title: s_('TagsPage|Delete tag'), method: :delete, data: { confirm: s_('TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?') % { tag_name: tag.name }, container: 'body' }, remote: true do
= icon("trash-o")
......@@ -24,7 +24,7 @@
- tags_sort_options_hash.each do |value, title|
%li
= link_to title, filter_tags_path(sort: value), class: ("is-active" if @sort == value)
- if can?(current_user, :push_code, @project)
- if can?(current_user, :admin_tag, @project)
= link_to new_project_tag_path(@project), class: 'btn btn-success new-tag-btn' do
= s_('TagsPage|New tag')
= link_to project_tags_path(@project, rss_url_options), title: _("Tags feed"), class: 'btn d-none d-sm-inline-block has-tooltip' do
......
......@@ -19,7 +19,7 @@
= s_("TagsPage|Can't find HEAD commit for this tag")
.nav-controls
- if can?(current_user, :push_code, @project)
- if can?(current_user, :admin_tag, @project)
= link_to edit_project_tag_release_path(@project, @tag.name), class: 'btn btn-edit controls-item has-tooltip', title: s_('TagsPage|Edit release notes') do
= icon("pencil")
= link_to project_tree_path(@project, @tag.name), class: 'btn controls-item has-tooltip', title: s_('TagsPage|Browse files') do
......@@ -28,7 +28,7 @@
= icon('history')
.btn-container.controls-item
= render 'projects/buttons/download', project: @project, ref: @tag.name
- if can?(current_user, :push_code, @project) && can?(current_user, :admin_project, @project)
- if can?(current_user, :admin_tag, @project)
.btn-container.controls-item-full
= link_to project_tag_path(@project, @tag.name), class: "btn btn-remove remove-row has-tooltip #{protected_tag?(@project, @tag) ? 'disabled' : ''}", title: s_('TagsPage|Delete tag'), method: :delete, data: { confirm: s_('TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?') % { tag_name: @tag.name } } do
%i.fa.fa-trash-o
......
---
title: Allow developers to delete tags
merge_request: 29668
author:
type: changed
---
title: Add token_encrypted column to operations_feature_flags_clients table
merge_request:
author:
type: other
......@@ -149,7 +149,7 @@ Component statuses are linked to configuration documentation for each component.
| [PgBouncer Exporter](#pgbouncer-exporter) | Prometheus endpoint with PgBouncer metrics | [][pgbouncer-exporter-omnibus] | [][pgbouncer-exporter-charts] | [][pgbouncer-exporter-charts] | [](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE |
| [GitLab Monitor](#gitlab-monitor) | Generates a variety of GitLab metrics | [][gitlab-monitor-omnibus] | [][gitab-monitor-charts] | [][gitab-monitor-charts] | [](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE |
| [Node Exporter](#node-exporter) | Prometheus endpoint with system metrics | [][node-exporter-omnibus] | [][node-exporter-charts] | [][node-exporter-charts] | [](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE |
| [Mattermost](#mattermost) | Open-source Slack alternative | [][mattermost-omnibus] | [][mattermost-charts] | [][mattermost-charts] | [](../user/project/integrations/mattermost_slash_commands.md#manual-configuration), [](../user/project/integrations/mattermost.html) | ❌ | ❌ | CE & EE |
| [Mattermost](#mattermost) | Open-source Slack alternative | [][mattermost-omnibus] | [][mattermost-charts] | [][mattermost-charts] | [](../user/project/integrations/mattermost.md) | ❌ | ❌ | CE & EE |
| [MinIO](#minio) | Object storage service | [][minio-omnibus] | [][minio-charts] | [][minio-charts] | [](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#storage-architecture) | ❌ | [][minio-gdk] | CE & EE |
| [Runner](#gitlab-runner) | Executes GitLab CI jobs | [][runner-omnibus] | [][runner-charts] | [][runner-charts] | [](../user/gitlab_com/index.md#shared-runners) | [][runner-source] | [][runner-gdk] | CE & EE |
| [Database Migrations](#database-migrations) | Database migrations | [][database-migrations-omnibus] | [][database-migrations-charts] | [][database-migrations-charts] | ✅ | [][database-migrations-source] | ✅ | CE & EE |
......
......@@ -95,6 +95,7 @@ The following table depicts the various user permission levels in a project.
| Dismiss vulnerability **[ULTIMATE]** | | | ✓ | ✓ | ✓ |
| Apply code change suggestions | | | ✓ | ✓ | ✓ |
| Create and edit wiki pages | | | ✓ | ✓ | ✓ |
| Rewrite/remove Git tags | | | ✓ | ✓ | ✓ |
| Use environment terminals | | | | ✓ | ✓ |
| Run Web IDE's Interactive Web Terminals **[ULTIMATE ONLY]** | | | | ✓ | ✓ |
| Add new team members | | | | ✓ | ✓ |
......@@ -102,7 +103,6 @@ The following table depicts the various user permission levels in a project.
| Push to protected branches | | | | ✓ | ✓ |
| Turn on/off protected branch push for devs | | | | ✓ | ✓ |
| Enable/disable tag protections | | | | ✓ | ✓ |
| Rewrite/remove Git tags | | | | ✓ | ✓ |
| Edit project | | | | ✓ | ✓ |
| Add deploy keys to project | | | | ✓ | ✓ |
| Configure project hooks | | | | ✓ | ✓ |
......
# Mattermost Notifications Service
The Mattermost Notifications Service allows your GitLab project to send events (e.g., `issue created`) to your existing Mattermost team as notifications. This requires configurations in both Mattermost and GitLab.
You can also use Mattermost slash commands to control GitLab inside Mattermost. This is the separately configured [Mattermost slash commands](mattermost_slash_commands.md).
## On Mattermost
To enable Mattermost integration you must create an incoming webhook integration:
......
......@@ -6,6 +6,9 @@ Mattermost commands give users an extra interface to perform common operations
from the chat environment. This allows one to, for example, create an issue as
soon as the idea was discussed in Mattermost.
GitLab can also send events (e.g., `issue created`) to Mattermost as notifications.
This is the separately configured [Mattermost Notifications Service](mattermost.md).
## Prerequisites
Mattermost 3.4 and up is required.
......
......@@ -235,6 +235,10 @@ module API
authorize! :push_code, user_project
end
def authorize_admin_tag
authorize! :admin_tag, user_project
end
def authorize_admin_project
authorize! :admin_project, user_project
end
......
......@@ -55,7 +55,7 @@ module API
optional :release_description, type: String, desc: 'Specifying release notes stored in the GitLab database (deprecated in GitLab 11.7)'
end
post ':id/repository/tags' do
authorize_push_project
authorize_admin_tag
result = ::Tags::CreateService.new(user_project, current_user)
.execute(params[:tag_name], params[:ref], params[:message])
......@@ -87,7 +87,7 @@ module API
requires :tag_name, type: String, desc: 'The name of the tag'
end
delete ':id/repository/tags/:tag_name', requirements: TAG_ENDPOINT_REQUIREMENTS do
authorize_push_project
authorize_admin_tag
tag = user_project.repository.find_tag(params[:tag_name])
not_found!('Tag') unless tag
......
......@@ -19,7 +19,7 @@ module Gitlab
return unless tag_name
logger.log_timed(LOG_MESSAGES[:tag_checks]) do
if tag_exists? && user_access.cannot_do_action?(:admin_project)
if tag_exists? && user_access.cannot_do_action?(:admin_tag)
raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:change_existing_tags]
end
end
......
......@@ -45,7 +45,7 @@ module Gitlab
if protected?(ProtectedTag, project, ref)
protected_tag_accessible_to?(ref, action: :create)
else
user.can?(:push_code, project)
user.can?(:admin_tag, project)
end
end
......
# frozen_string_literal: true
module QA
# Failure issue: https://gitlab.com/gitlab-org/quality/nightly/issues/94
context 'Create', :quarantine do
context 'Create' do
describe 'Merge request creation from fork' do
it 'user forks a project, submits a merge request and maintainer merges it' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
......
# frozen_string_literal: true
module QA
# Failure issue: https://gitlab.com/gitlab-org/quality/nightly/issues/93
context 'Create', :quarantine do
context 'Create' do
describe 'Merge request squashing' do
it 'user squashes commits while merging' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
......
require 'spec_helper'
describe 'Maintainer creates tag' do
describe 'Developer creates tag' do
let(:user) { create(:user) }
let(:project) { create(:project, :repository, namespace: user.namespace) }
let(:group) { create(:group) }
let(:project) { create(:project, :repository, namespace: group) }
before do
project.add_maintainer(user)
project.add_developer(user)
sign_in(user)
end
......
require 'spec_helper'
describe 'Maintainer deletes tag' do
describe 'Developer deletes tag' do
let(:user) { create(:user) }
let(:project) { create(:project, :repository, namespace: user.namespace) }
let(:group) { create(:group) }
let(:project) { create(:project, :repository, namespace: group) }
before do
project.add_maintainer(user)
project.add_developer(user)
sign_in(user)
visit project_tags_path(project)
end
......
require 'spec_helper'
describe 'Maintainer updates tag' do
describe 'Developer updates tag' do
let(:user) { create(:user) }
let(:project) { create(:project, :repository, namespace: user.namespace) }
let(:group) { create(:group) }
let(:project) { create(:project, :repository, namespace: group) }
before do
project.add_maintainer(user)
project.add_developer(user)
sign_in(user)
visit project_tags_path(project)
end
......
require 'spec_helper'
describe 'Maintainer views tags' do
describe 'Developer views tags' do
let(:user) { create(:user) }
let(:group) { create(:group) }
before do
project.add_maintainer(user)
......@@ -9,7 +10,7 @@ describe 'Maintainer views tags' do
end
context 'when project has no tags' do
let(:project) { create(:project_empty_repo) }
let(:project) { create(:project_empty_repo, namespace: group) }
before do
visit project_path(project)
......@@ -25,7 +26,7 @@ describe 'Maintainer views tags' do
end
context 'when project has tags' do
let(:project) { create(:project, :repository, namespace: user.namespace) }
let(:project) { create(:project, :repository, namespace: group) }
let(:repository) { project.repository }
before do
......
......@@ -8,9 +8,8 @@ describe Gitlab::Checks::TagCheck do
describe '#validate!' do
let(:ref) { 'refs/tags/v1.0.0' }
it 'raises an error' do
allow(user_access).to receive(:can_do_action?).with(:push_code).and_return(true)
expect(user_access).to receive(:can_do_action?).with(:admin_project).and_return(false)
it 'raises an error when user does not have access' do
allow(user_access).to receive(:can_do_action?).with(:admin_tag).and_return(false)
expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to change existing tags on this project.')
end
......
......@@ -831,7 +831,7 @@ describe Gitlab::GitAccess do
push_master: true,
push_protected_branch: false,
push_remove_protected_branch: false,
push_tag: false,
push_tag: true,
push_new_tag: true,
push_all: false,
merge_into_protected_branch: false
......
......@@ -36,7 +36,7 @@ describe ProjectPolicy do
let(:developer_permissions) do
%i[
admin_milestone admin_merge_request update_merge_request create_commit_status
admin_tag admin_milestone admin_merge_request update_merge_request create_commit_status
update_commit_status create_build update_build create_pipeline
update_pipeline create_merge_request_from create_wiki push_code
resolve_note create_container_image update_container_image destroy_container_image
......
......@@ -10,7 +10,7 @@ describe API::Tags do
let(:current_user) { nil }
before do
project.add_maintainer(user)
project.add_developer(user)
end
describe 'GET /projects/:id/repository/tags' do
......
......@@ -17,6 +17,7 @@ RSpec.shared_examples 'archived project policies' do
upload_file
resolve_note
award_emoji
admin_tag
]
end
......
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