[#73887] Add backlog buckets to API

This commit is contained in:
Tobias Dillmann
2026-05-29 10:47:07 +02:00
committed by Tobias Dillmann
parent 5b02e71a19
commit 974f5b7272
18 changed files with 796 additions and 1 deletions
@@ -107,6 +107,7 @@ export function initializeCoreDisplayFields(displayFieldService:DisplayFieldServ
'TimeEntriesActivity',
'Version',
'Category',
'BacklogBucket',
'Sprint',
'CustomField::Hierarchy::Item',
'CustomOption',
@@ -100,6 +100,7 @@ export function initializeCoreEditFields(editFieldService:EditFieldService, sele
'Version',
'TimeEntriesActivity',
'Category',
'BacklogBucket',
'Sprint',
'CustomOption',
'CustomField::Hierarchy::Item',
@@ -0,0 +1,35 @@
# frozen_string_literal: true
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
# ++
module Queries::BacklogBuckets
::Queries::Register.register(BacklogBucketQuery) do
order Orders::DefaultOrder
end
end
@@ -0,0 +1,46 @@
# frozen_string_literal: true
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
# ++
module Queries
module BacklogBuckets
class BacklogBucketQuery
include ::Queries::BaseQuery
include ::Queries::UnpersistedQuery
def self.model
::BacklogBucket
end
def default_scope
::BacklogBucket.visible(User.current)
end
end
end
end
@@ -0,0 +1,37 @@
# frozen_string_literal: true
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
# ++
class Queries::BacklogBuckets::Orders::DefaultOrder < Queries::Orders::Base
self.model = BacklogBucket
def self.key
/\A(id|name)\z/
end
end
@@ -0,0 +1,38 @@
# frozen_string_literal: true
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
# ++
module API
module V3
module BacklogBuckets
class BacklogBucketCollectionRepresenter < ::API::Decorators::OffsetPaginatedCollection
end
end
end
end
@@ -0,0 +1,61 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
require "roar/decorator"
require "roar/json/hal"
module API
module V3
module BacklogBuckets
class BacklogBucketRepresenter < ::API::Decorators::Single
include API::Decorators::LinkedResource
include API::V3::Workspaces::LinkedResource
include API::Decorators::DateProperty
self_link
associated_project as: :definingWorkspace
property :id,
render_nil: true
property :name,
render_nil: true
date_time_property :created_at
date_time_property :updated_at
def _type
"BacklogBucket"
end
end
end
end
end
@@ -0,0 +1,51 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
module API
module V3
module BacklogBuckets
class BacklogBucketsAPI < ::API::OpenProjectAPI
resources :backlog_buckets do
get &::API::V3::Utilities::Endpoints::Index
.new(model: BacklogBucket)
.mount
route_param :id, type: Integer, desc: "Backlog Bucket ID" do
after_validation do
@backlog_bucket = BacklogBucket.visible(current_user).find(params[:id])
end
get &::API::V3::Utilities::Endpoints::Show.new(model: BacklogBucket).mount
end
end
end
end
end
end
@@ -0,0 +1,50 @@
# frozen_string_literal: true
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
# ++
module API
module V3
module BacklogBuckets
class BacklogBucketsByProjectAPI < ::API::OpenProjectAPI
resources :backlog_buckets do
after_validation do
authorize_in_project(:view_sprints, project: @project)
end
get &::API::V3::Utilities::Endpoints::Index
.new(
model: BacklogBucket,
scope: -> { BacklogBucket.where(project: @project).visible.order_alphabetically }
)
.mount
end
end
end
end
end
@@ -173,12 +173,26 @@ module OpenProject::Backlogs
"#{root}/projects/#{id}/sprints"
end
add_api_path :backlog_buckets do
"#{root}/backlog_buckets"
end
add_api_path :backlog_bucket do |id|
"#{root}/backlog_buckets/#{id}"
end
add_api_path :project_backlog_buckets do |id|
"#{root}/projects/#{id}/backlog_buckets"
end
add_api_endpoint "API::V3::Root" do
mount ::API::V3::Sprints::SprintsAPI
mount ::API::V3::BacklogBuckets::BacklogBucketsAPI
end
add_api_endpoint "API::V3::Projects::ProjectsAPI", :id do
mount ::API::V3::Sprints::SprintsByProjectAPI
mount ::API::V3::BacklogBuckets::BacklogBucketsByProjectAPI
end
initializer "openproject_backlogs.event_subscriptions" do
@@ -224,9 +238,16 @@ module OpenProject::Backlogs
::Type.add_constraint attribute, ->(_type, project: nil) { project.nil? || project.backlogs_enabled? }
end
story_and_sprint_permission = ->(_type, project: nil) do
project.nil? || User.current.allowed_in_project?(:view_sprints, project)
end
::Type.add_constraint :backlog_bucket, story_and_sprint_permission
::Type.add_default_mapping(:estimates_and_progress, :story_points)
::Type.add_default_mapping(:other, :position)
::Type.add_default_mapping(:details, :sprint)
::Type.add_default_mapping(:details, :backlog_bucket)
::Queries::Register.register(::Query) do
filter Queries::WorkPackages::Filter::SprintFilter
@@ -72,6 +72,33 @@ module OpenProject::Backlogs
end
end,
setter: associated_resource_default_setter(:sprint, :sprint, :sprint)
resource :backlog_bucket,
link_cache_if: ->(*) {
represented.project.present? &&
current_user.allowed_in_project?(:view_sprints, represented.project)
},
link: ->(*) {
if represented.backlog_bucket.present?
{
href: api_v3_paths.backlog_bucket(represented.backlog_bucket_id),
title: represented.backlog_bucket.name
}
else
{
href: nil
}
end
},
getter: ->(*) do
if embed_links &&
represented.project.present? &&
represented.backlog_bucket.present? &&
current_user.allowed_in_project?(:view_sprints, represented.project)
::API::V3::BacklogBuckets::BacklogBucketRepresenter.create(represented.backlog_bucket, current_user:)
end
end,
setter: associated_resource_default_setter(:backlog_bucket, :backlog_bucket, :backlog_bucket)
end
end
end
@@ -67,6 +67,20 @@ module OpenProject::Backlogs
"#{api_v3_paths.project_sprints(represented.project_id)}?filters=#{filters}&pageSize=-1"
}
schema_with_allowed_link :backlog_bucket,
has_default: false,
required: false,
show_if: ->(*) {
current_user.allowed_in_project?(:view_sprints, represented.project) &&
backlogs_constraint_passed?(:backlog_bucket)
},
href_callback: ->(*) {
filters = CGI.escape(JSON.dump([]))
query = "filters=#{filters}&pageSize=-1"
"#{api_v3_paths.project_backlog_buckets(represented.project_id)}?#{query}"
}
define_method :backlogs_constraint_passed? do |attribute|
!represented.type || represented.type.passes_attribute_constraint?(attribute, project: represented.project)
end
@@ -0,0 +1,103 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
require "spec_helper"
RSpec.describe API::V3::BacklogBuckets::BacklogBucketRepresenter, "rendering" do
include API::V3::Utilities::PathHelper
let(:workspace) { build_stubbed(:project) }
let(:backlog_bucket) { build_stubbed(:backlog_bucket, name: "My Bucket", project: workspace) }
let(:current_user) { build_stubbed(:user) }
let(:embed_links) { true }
let(:representer) { described_class.create(backlog_bucket, current_user:, embed_links:) }
subject(:generated) { representer.to_json }
it { is_expected.to include_json("BacklogBucket".to_json).at_path("_type") }
describe "links" do
it { is_expected.to have_json_type(Object).at_path("_links") }
describe "self" do
it_behaves_like "has a titled link" do
let(:link) { "self" }
let(:href) { api_v3_paths.backlog_bucket(backlog_bucket.id) }
let(:title) { backlog_bucket.name }
end
end
describe "definingWorkspace" do
it_behaves_like "has workspace linked" do
let(:link) { "definingWorkspace" }
end
end
end
describe "properties" do
describe "_type" do
it_behaves_like "property", :_type do
let(:value) { "BacklogBucket" }
end
end
describe "id" do
it_behaves_like "property", :id do
let(:value) { backlog_bucket.id }
end
end
describe "name" do
it_behaves_like "property", :name do
let(:value) { backlog_bucket.name }
end
end
describe "createdAt" do
it_behaves_like "has UTC ISO 8601 date and time" do
let(:date) { backlog_bucket.created_at }
let(:json_path) { "createdAt" }
end
end
describe "updatedAt" do
it_behaves_like "has UTC ISO 8601 date and time" do
let(:date) { backlog_bucket.updated_at }
let(:json_path) { "updatedAt" }
end
end
end
describe "embedded" do
it_behaves_like "has workspace embedded" do
let(:embedded_path) { "_embedded/definingWorkspace" }
end
end
end
@@ -161,4 +161,28 @@ RSpec.describe API::V3::WorkPackages::Schema::WorkPackageSchemaRepresenter do
end
end
end
describe "backlogBucket" do
let(:path) { "backlogBucket" }
it_behaves_like "has basic schema properties" do
let(:type) { "BacklogBucket" }
let(:name) { I18n.t("activerecord.attributes.work_package.backlog_bucket") }
let(:required) { false }
let(:writable) { true }
let(:location) { "_links" }
end
it_behaves_like "links to allowed values via collection link" do
let(:href) { "#{api_v3_paths.project_backlog_buckets(project.id)}?filters=%5B%5D&pageSize=-1" }
end
context "when lacking permission to see the sprints (or if backlogs is disabled)" do
let(:permissions) { %i(view_work_packages edit_work_packages) }
it "has no reference to the backlog bucket" do
expect(subject).not_to have_json_path(path)
end
end
end
end
@@ -41,7 +41,8 @@ RSpec.describe API::V3::WorkPackages::WorkPackageRepresenter, "rendering" do
project:,
story_points:,
position:,
sprint:)
sprint:,
backlog_bucket:)
end
let(:type) { build_stubbed(:type) }
let(:enabled_module_names) { %w[backlogs] }
@@ -52,6 +53,7 @@ RSpec.describe API::V3::WorkPackages::WorkPackageRepresenter, "rendering" do
let(:story_points) { 23 }
let(:position) { 123 }
let(:sprint) { build_stubbed(:sprint) }
let(:backlog_bucket) { build_stubbed(:backlog_bucket) }
let(:embed_links) { true }
let(:representer) do
described_class.create(work_package, current_user:, embed_links:)
@@ -119,6 +121,34 @@ RSpec.describe API::V3::WorkPackages::WorkPackageRepresenter, "rendering" do
end
end
describe "backlogBucket" do
let(:link) { "backlogBucket" }
let(:href) { api_v3_paths.backlog_bucket(backlog_bucket.id) }
let(:title) { backlog_bucket.name }
it_behaves_like "has a titled link"
context "when lacking the permission" do
let(:permissions) { [] }
it_behaves_like "has no link"
end
context "when the project is empty (because the work package is not persisted yet)" do
let(:project) { nil }
it_behaves_like "has no link"
end
context "when the work package has no backlog bucket assigned" do
let(:backlog_bucket) { nil }
it_behaves_like "has an empty link" do
let(:link) { "backlogBucket" }
end
end
end
describe "update links" do
context "when user lacks edit permission but has manage_sprint_items" do
let(:permissions) { super() + [:manage_sprint_items] }
@@ -150,5 +180,25 @@ RSpec.describe API::V3::WorkPackages::WorkPackageRepresenter, "rendering" do
it_behaves_like "has the resource not embedded"
end
end
describe "backlogBucket" do
let(:embedded_path) { "_embedded/backlogBucket" }
let(:embedded_resource) { backlog_bucket }
let(:embedded_resource_type) { "BacklogBucket" }
it_behaves_like "has the resource embedded"
context "when lacking the permission" do
let(:permissions) { [] }
it_behaves_like "has the resource not embedded"
end
context "when the work package has no backlog bucket assigned" do
let(:backlog_bucket) { nil }
it_behaves_like "has the resource not embedded"
end
end
end
end
@@ -0,0 +1,90 @@
# frozen_string_literal: true
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
# ++
require "spec_helper"
require "rack/test"
RSpec.describe "API v3 BacklogBucket resource", content_type: :json do
include Rack::Test::Methods
include API::V3::Utilities::PathHelper
shared_let(:project) { create(:project, public: false) }
shared_let(:other_project) { create(:project, public: false) }
shared_let(:project_without_permission) { create(:project, public: false) }
shared_let(:bucket) { create(:backlog_bucket, project:) }
shared_let(:other_bucket) { create(:backlog_bucket, project: other_project) }
shared_let(:bucket_without_permission) { create(:backlog_bucket, project: project_without_permission) }
let(:permissions) { %i[view_sprints] }
current_user do
create(:user,
member_with_permissions: {
project => permissions,
other_project => permissions
})
end
describe "GET /api/v3/backlog_buckets" do
let(:get_path) { api_v3_paths.path_for(:backlog_buckets, page_size:, offset:) }
let(:page_size) { nil }
let(:offset) { nil }
before { get get_path }
context "for a user with view_sprints permission" do
it_behaves_like "API V3 collection response", 2, 2, "BacklogBucket" do
let(:elements) { [other_bucket, bucket] }
end
end
context "for a user without view_sprints permission" do
let(:permissions) { [] }
it_behaves_like "API V3 collection response", 0, 0, "BacklogBucket"
end
context "for an anonymous user" do
let(:current_user) { User.anonymous }
it_behaves_like "unauthenticated access"
end
context "with pagination" do
let(:page_size) { 1 }
let(:offset) { 2 }
it_behaves_like "API V3 collection response", 2, 1, "BacklogBucket" do
let(:elements) { [bucket] }
end
end
end
end
@@ -0,0 +1,72 @@
# frozen_string_literal: true
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
# ++
require "spec_helper"
RSpec.describe "API v3 BacklogBucket resource on project", content_type: :json do
include Rack::Test::Methods
include API::V3::Utilities::PathHelper
shared_let(:project) { create(:project, public: false) }
shared_let(:other_project) { create(:project, public: false) }
shared_let(:bucket) { create(:backlog_bucket, project:) }
shared_let(:other_bucket) { create(:backlog_bucket, project: other_project) }
let(:permissions) { %i[view_sprints] }
current_user do
create(:user, member_with_permissions: { project => permissions })
end
describe "GET /api/v3/projects/:id/backlog_buckets" do
let(:get_path) { api_v3_paths.project_backlog_buckets(project.id) }
before { get get_path }
context "for a user with view_sprints permission" do
it_behaves_like "API V3 collection response", 1, 1, "BacklogBucket" do
let(:elements) { [bucket] }
end
end
context "for a user without view_sprints permission" do
let(:permissions) { [] }
it_behaves_like "unauthorized access"
end
context "for a user being not a project member at all" do
let(:get_path) { api_v3_paths.project_backlog_buckets(other_project.id) }
it_behaves_like "not found"
end
end
end
@@ -0,0 +1,74 @@
# frozen_string_literal: true
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
require "rack/test"
require "spec_helper"
RSpec.describe "API v3 BacklogBucket resource", content_type: :json do
include Rack::Test::Methods
include API::V3::Utilities::PathHelper
shared_let(:project) { create(:project, public: false) }
shared_let(:bucket) { create(:backlog_bucket, project:) }
let(:permissions) { %i[view_sprints] }
current_user do
create(:user, member_with_permissions: { project => permissions })
end
describe "GET /api/v3/backlog_buckets/:id" do
let(:get_path) { api_v3_paths.backlog_bucket(bucket.id) }
before { get get_path }
context "for a user with view_sprints permission" do
it_behaves_like "successful response", 200, "BacklogBucket"
end
context "for a user without view_sprints permission" do
let(:permissions) { [] }
it_behaves_like "not found"
end
context "for an anonymous user" do
let(:current_user) { User.anonymous }
it_behaves_like "unauthenticated access"
end
context "for a bucket that does not exist" do
let(:get_path) { api_v3_paths.backlog_bucket(0) }
it_behaves_like "not found"
end
end
end