Merge branch 'issue_54042' into 'master'
Let project reporters create issue from group boards Closes #54042 See merge request gitlab-org/gitlab-ce!29866
This commit is contained in:
commit
ec5808a645
14 changed files with 168 additions and 6 deletions
|
@ -114,7 +114,7 @@ export default {
|
|||
name="issue_title"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<project-select v-if="groupId" :group-id="groupId" />
|
||||
<project-select v-if="groupId" :group-id="groupId" :list="list" />
|
||||
<div class="clearfix prepend-top-10">
|
||||
<gl-button
|
||||
ref="submit-button"
|
||||
|
|
|
@ -6,6 +6,7 @@ import Icon from '~/vue_shared/components/icon.vue';
|
|||
import { GlLoadingIcon } from '@gitlab/ui';
|
||||
import eventHub from '../eventhub';
|
||||
import Api from '../../api';
|
||||
import { featureAccessLevel } from '~/pages/projects/shared/permissions/constants';
|
||||
|
||||
export default {
|
||||
name: 'BoardProjectSelect',
|
||||
|
@ -19,6 +20,10 @@ export default {
|
|||
required: true,
|
||||
default: 0,
|
||||
},
|
||||
list: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -49,6 +54,12 @@ export default {
|
|||
selectable: true,
|
||||
data: (term, callback) => {
|
||||
this.loading = true;
|
||||
const additionalAttrs = {};
|
||||
|
||||
if (this.list.type && this.list.type !== 'backlog') {
|
||||
additionalAttrs.min_access_level = featureAccessLevel.EVERYONE;
|
||||
}
|
||||
|
||||
return Api.groupProjects(
|
||||
this.groupId,
|
||||
term,
|
||||
|
@ -56,6 +67,7 @@ export default {
|
|||
with_issues_enabled: true,
|
||||
with_shared: false,
|
||||
include_subgroups: true,
|
||||
...additionalAttrs,
|
||||
},
|
||||
projects => {
|
||||
this.loading = false;
|
||||
|
|
|
@ -16,7 +16,7 @@ export const visibilityLevelDescriptions = {
|
|||
),
|
||||
};
|
||||
|
||||
const featureAccessLevel = {
|
||||
export const featureAccessLevel = {
|
||||
NOT_ENABLED: 0,
|
||||
PROJECT_MEMBERS: 10,
|
||||
EVERYONE: 20,
|
||||
|
|
|
@ -10,7 +10,7 @@ module BoardsHelper
|
|||
boards_endpoint: @boards_endpoint,
|
||||
lists_endpoint: board_lists_path(board),
|
||||
board_id: board.id,
|
||||
disabled: "#{!can?(current_user, :admin_list, current_board_parent)}",
|
||||
disabled: (!can?(current_user, :create_non_backlog_issues, board)).to_s,
|
||||
issue_link_base: build_issue_link_base,
|
||||
root_path: root_path,
|
||||
bulk_update_path: @bulk_issues_path,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class BoardPolicy < BasePolicy
|
||||
include FindGroupProjects
|
||||
|
||||
delegate { @subject.parent }
|
||||
|
||||
condition(:is_group_board) { @subject.group_board? }
|
||||
|
@ -13,4 +15,20 @@ class BoardPolicy < BasePolicy
|
|||
enable :read_milestone
|
||||
enable :read_issue
|
||||
end
|
||||
|
||||
condition(:reporter_of_group_projects) do
|
||||
next unless @user
|
||||
|
||||
group_projects_for(user: @user, group: @subject.parent)
|
||||
.visible_to_user_and_access_level(@user, ::Gitlab::Access::REPORTER)
|
||||
.exists?
|
||||
end
|
||||
|
||||
rule { is_group_board & reporter_of_group_projects }.policy do
|
||||
enable :create_non_backlog_issues
|
||||
end
|
||||
|
||||
rule { is_project_board & can?(:admin_issue) }.policy do
|
||||
enable :create_non_backlog_issues
|
||||
end
|
||||
end
|
||||
|
|
13
app/policies/concerns/find_group_projects.rb
Normal file
13
app/policies/concerns/find_group_projects.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module FindGroupProjects
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def group_projects_for(user:, group:)
|
||||
GroupProjectsFinder.new(
|
||||
group: group,
|
||||
current_user: user,
|
||||
options: { include_subgroups: true, only_owned: true }
|
||||
).execute
|
||||
end
|
||||
end
|
|
@ -1,6 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class GroupPolicy < BasePolicy
|
||||
include FindGroupProjects
|
||||
|
||||
desc "Group is public"
|
||||
with_options scope: :subject, score: 0
|
||||
condition(:public_group) { @subject.public? }
|
||||
|
@ -22,7 +24,7 @@ class GroupPolicy < BasePolicy
|
|||
condition(:can_change_parent_share_with_group_lock) { can?(:change_share_with_group_lock, @subject.parent) }
|
||||
|
||||
condition(:has_projects) do
|
||||
GroupProjectsFinder.new(group: @subject, current_user: @user, options: { include_subgroups: true, only_owned: true }).execute.any?
|
||||
group_projects_for(user: @user, group: @subject).any?
|
||||
end
|
||||
|
||||
with_options scope: :subject, score: 0
|
||||
|
|
5
changelogs/unreleased/issue_54042.yml
Normal file
5
changelogs/unreleased/issue_54042.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Let project reporters create issue from group boards
|
||||
merge_request: 29866
|
||||
author:
|
||||
type: fixed
|
|
@ -156,7 +156,8 @@ Parameters:
|
|||
| `with_issues_enabled` | boolean | no | Limit by projects with issues feature enabled. Default is `false` |
|
||||
| `with_merge_requests_enabled` | boolean | no | Limit by projects with merge requests feature enabled. Default is `false` |
|
||||
| `with_shared` | boolean | no | Include projects shared to this group. Default is `true` |
|
||||
| `include_subgroups` | boolean | no | Include projects in subgroups of this group. Default is `false` |
|
||||
| `include_subgroups` | boolean | no | Include projects in subgroups of this group. Default is `false` |
|
||||
| `min_access_level` | integer | no | Limit to projects where current user has at least this [access level](members.md) |
|
||||
| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
|
||||
| `with_security_reports` | boolean | no | **(ULTIMATE)** Return only projects that have security reports artifacts present in any of their builds. This means "projects with security reports enabled". Default is `false` |
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ module API
|
|||
).execute
|
||||
projects = projects.with_issues_available_for_user(current_user) if params[:with_issues_enabled]
|
||||
projects = projects.with_merge_requests_enabled if params[:with_merge_requests_enabled]
|
||||
projects = projects.visible_to_user_and_access_level(current_user, params[:min_access_level]) if params[:min_access_level]
|
||||
projects = reorder_projects(projects)
|
||||
paginate(projects)
|
||||
end
|
||||
|
@ -213,6 +214,7 @@ module API
|
|||
optional :with_merge_requests_enabled, type: Boolean, default: false, desc: 'Limit by enabled merge requests feature'
|
||||
optional :with_shared, type: Boolean, default: true, desc: 'Include projects shared to this group'
|
||||
optional :include_subgroups, type: Boolean, default: false, desc: 'Includes projects in subgroups of this group'
|
||||
optional :min_access_level, type: Integer, values: Gitlab::Access.all_values, desc: 'Limit by minimum access level of authenticated user on projects'
|
||||
|
||||
use :pagination
|
||||
use :with_custom_attributes
|
||||
|
|
|
@ -127,4 +127,44 @@ describe 'Issue Boards new issue', :js do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'group boards' do
|
||||
set(:group) { create(:group, :public) }
|
||||
set(:project) { create(:project, namespace: group) }
|
||||
set(:group_board) { create(:board, group: group) }
|
||||
set(:list) { create(:list, board: group_board, position: 0) }
|
||||
|
||||
context 'for unauthorized users' do
|
||||
before do
|
||||
sign_in(user)
|
||||
visit group_board_path(group, group_board)
|
||||
wait_for_requests
|
||||
end
|
||||
|
||||
it 'displays new issue button in open list' do
|
||||
expect(first('.board')).to have_selector('.issue-count-badge-add-button', count: 1)
|
||||
end
|
||||
|
||||
it 'does not display new issue button in label list' do
|
||||
page.within('.board.is-draggable') do
|
||||
expect(page).not_to have_selector('.issue-count-badge-add-button')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'for authorized users' do
|
||||
it 'display new issue button in label list' do
|
||||
project = create(:project, namespace: group)
|
||||
project.add_reporter(user)
|
||||
|
||||
sign_in(user)
|
||||
visit group_board_path(group, group_board)
|
||||
wait_for_requests
|
||||
|
||||
page.within('.board.is-draggable') do
|
||||
expect(page).to have_selector('.issue-count-badge-add-button')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -40,7 +40,7 @@ describe BoardsHelper do
|
|||
assign(:project, project)
|
||||
|
||||
allow(helper).to receive(:current_user) { user }
|
||||
allow(helper).to receive(:can?).with(user, :admin_list, project).and_return(true)
|
||||
allow(helper).to receive(:can?).with(user, :create_non_backlog_issues, board).and_return(true)
|
||||
end
|
||||
|
||||
it 'returns a board_lists_path as lists_endpoint' do
|
||||
|
|
|
@ -56,4 +56,57 @@ describe BoardPolicy do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'create_non_backlog_issues' do
|
||||
context 'for project boards' do
|
||||
let!(:current_user) { create(:user) }
|
||||
|
||||
subject { described_class.new(current_user, project_board) }
|
||||
|
||||
context 'when user can admin project issues' do
|
||||
it 'allows to add non backlog issues from issue board' do
|
||||
project.add_reporter(current_user)
|
||||
|
||||
expect_allowed(:create_non_backlog_issues)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user cannot admin project issues' do
|
||||
it 'does not allow to add non backlog issues from issue board' do
|
||||
project.add_guest(current_user)
|
||||
|
||||
expect_disallowed(:create_non_backlog_issues)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'for group boards' do
|
||||
let!(:current_user) { create(:user) }
|
||||
let!(:project_1) { create(:project, namespace: group) }
|
||||
let!(:project_2) { create(:project, namespace: group) }
|
||||
let!(:group_board) { create(:board, group: group) }
|
||||
|
||||
subject { described_class.new(current_user, group_board) }
|
||||
|
||||
before do
|
||||
project_1.add_guest(current_user)
|
||||
end
|
||||
|
||||
context 'when user is at least reporter in one of the child projects' do
|
||||
it 'allows to add non backlog issues from issue board' do
|
||||
project_2.add_reporter(current_user)
|
||||
|
||||
expect_allowed(:create_non_backlog_issues)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is not a reporter from any child projects' do
|
||||
it 'does not allow to add non backlog issues from issue board' do
|
||||
project_2.add_guest(current_user)
|
||||
|
||||
expect_disallowed(:create_non_backlog_issues)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -483,6 +483,22 @@ describe API::Groups do
|
|||
|
||||
describe "GET /groups/:id/projects" do
|
||||
context "when authenticated as user" do
|
||||
context 'with min access level' do
|
||||
it 'returns projects with min access level or higher' do
|
||||
group_guest = create(:user)
|
||||
group1.add_guest(group_guest)
|
||||
project4 = create(:project, group: group1)
|
||||
project1.add_guest(group_guest)
|
||||
project3.add_reporter(group_guest)
|
||||
project4.add_developer(group_guest)
|
||||
|
||||
get api("/groups/#{group1.id}/projects", group_guest), params: { min_access_level: Gitlab::Access::REPORTER }
|
||||
|
||||
project_ids = json_response.map { |proj| proj['id'] }
|
||||
expect(project_ids).to match_array([project3.id, project4.id])
|
||||
end
|
||||
end
|
||||
|
||||
it "returns the group's projects" do
|
||||
get api("/groups/#{group1.id}/projects", user1)
|
||||
|
||||
|
|
Loading…
Reference in a new issue