diff --git a/frontend/src/app/shared/components/fields/display/display-field.initializer.ts b/frontend/src/app/shared/components/fields/display/display-field.initializer.ts index 7b38b7ad928..a1a84fd82f9 100644 --- a/frontend/src/app/shared/components/fields/display/display-field.initializer.ts +++ b/frontend/src/app/shared/components/fields/display/display-field.initializer.ts @@ -107,6 +107,7 @@ export function initializeCoreDisplayFields(displayFieldService:DisplayFieldServ 'TimeEntriesActivity', 'Version', 'Category', + 'BacklogBucket', 'Sprint', 'CustomField::Hierarchy::Item', 'CustomOption', diff --git a/frontend/src/app/shared/components/fields/edit/edit-field.initializer.ts b/frontend/src/app/shared/components/fields/edit/edit-field.initializer.ts index 118b58bdb88..a8c953547e3 100644 --- a/frontend/src/app/shared/components/fields/edit/edit-field.initializer.ts +++ b/frontend/src/app/shared/components/fields/edit/edit-field.initializer.ts @@ -100,6 +100,7 @@ export function initializeCoreEditFields(editFieldService:EditFieldService, sele 'Version', 'TimeEntriesActivity', 'Category', + 'BacklogBucket', 'Sprint', 'CustomOption', 'CustomField::Hierarchy::Item', diff --git a/modules/backlogs/app/models/queries/backlog_buckets.rb b/modules/backlogs/app/models/queries/backlog_buckets.rb new file mode 100644 index 00000000000..62cf00316f2 --- /dev/null +++ b/modules/backlogs/app/models/queries/backlog_buckets.rb @@ -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 diff --git a/modules/backlogs/app/models/queries/backlog_buckets/backlog_bucket_query.rb b/modules/backlogs/app/models/queries/backlog_buckets/backlog_bucket_query.rb new file mode 100644 index 00000000000..33e2f2289db --- /dev/null +++ b/modules/backlogs/app/models/queries/backlog_buckets/backlog_bucket_query.rb @@ -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 diff --git a/modules/backlogs/app/models/queries/backlog_buckets/orders/default_order.rb b/modules/backlogs/app/models/queries/backlog_buckets/orders/default_order.rb new file mode 100644 index 00000000000..30311b27dd4 --- /dev/null +++ b/modules/backlogs/app/models/queries/backlog_buckets/orders/default_order.rb @@ -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 diff --git a/modules/backlogs/lib/api/v3/backlog_buckets/backlog_bucket_collection_representer.rb b/modules/backlogs/lib/api/v3/backlog_buckets/backlog_bucket_collection_representer.rb new file mode 100644 index 00000000000..23724dad31a --- /dev/null +++ b/modules/backlogs/lib/api/v3/backlog_buckets/backlog_bucket_collection_representer.rb @@ -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 diff --git a/modules/backlogs/lib/api/v3/backlog_buckets/backlog_bucket_representer.rb b/modules/backlogs/lib/api/v3/backlog_buckets/backlog_bucket_representer.rb new file mode 100644 index 00000000000..ca29a4d75e0 --- /dev/null +++ b/modules/backlogs/lib/api/v3/backlog_buckets/backlog_bucket_representer.rb @@ -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 diff --git a/modules/backlogs/lib/api/v3/backlog_buckets/backlog_buckets_api.rb b/modules/backlogs/lib/api/v3/backlog_buckets/backlog_buckets_api.rb new file mode 100644 index 00000000000..c7621343206 --- /dev/null +++ b/modules/backlogs/lib/api/v3/backlog_buckets/backlog_buckets_api.rb @@ -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 diff --git a/modules/backlogs/lib/api/v3/backlog_buckets/backlog_buckets_by_project_api.rb b/modules/backlogs/lib/api/v3/backlog_buckets/backlog_buckets_by_project_api.rb new file mode 100644 index 00000000000..a926b9aaccb --- /dev/null +++ b/modules/backlogs/lib/api/v3/backlog_buckets/backlog_buckets_by_project_api.rb @@ -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 diff --git a/modules/backlogs/lib/open_project/backlogs/engine.rb b/modules/backlogs/lib/open_project/backlogs/engine.rb index 85f0baa0baa..442274a2339 100644 --- a/modules/backlogs/lib/open_project/backlogs/engine.rb +++ b/modules/backlogs/lib/open_project/backlogs/engine.rb @@ -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 diff --git a/modules/backlogs/lib/open_project/backlogs/patches/api/work_package_representer.rb b/modules/backlogs/lib/open_project/backlogs/patches/api/work_package_representer.rb index 6b9783ce1f3..40439ffd5d8 100644 --- a/modules/backlogs/lib/open_project/backlogs/patches/api/work_package_representer.rb +++ b/modules/backlogs/lib/open_project/backlogs/patches/api/work_package_representer.rb @@ -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 diff --git a/modules/backlogs/lib/open_project/backlogs/patches/api/work_package_schema_representer.rb b/modules/backlogs/lib/open_project/backlogs/patches/api/work_package_schema_representer.rb index 813790bd4d7..bb9f518da85 100644 --- a/modules/backlogs/lib/open_project/backlogs/patches/api/work_package_schema_representer.rb +++ b/modules/backlogs/lib/open_project/backlogs/patches/api/work_package_schema_representer.rb @@ -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 diff --git a/modules/backlogs/spec/lib/api/v3/backlog_buckets/backlog_bucket_representer_rendering_spec.rb b/modules/backlogs/spec/lib/api/v3/backlog_buckets/backlog_bucket_representer_rendering_spec.rb new file mode 100644 index 00000000000..9389f227950 --- /dev/null +++ b/modules/backlogs/spec/lib/api/v3/backlog_buckets/backlog_bucket_representer_rendering_spec.rb @@ -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 diff --git a/modules/backlogs/spec/lib/api/v3/work_packages/schema/work_package_schema_representer_spec.rb b/modules/backlogs/spec/lib/api/v3/work_packages/schema/work_package_schema_representer_spec.rb index fab1ec92809..ca81938fddf 100644 --- a/modules/backlogs/spec/lib/api/v3/work_packages/schema/work_package_schema_representer_spec.rb +++ b/modules/backlogs/spec/lib/api/v3/work_packages/schema/work_package_schema_representer_spec.rb @@ -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 diff --git a/modules/backlogs/spec/lib/api/v3/work_packages/work_package_representer_rendering_spec.rb b/modules/backlogs/spec/lib/api/v3/work_packages/work_package_representer_rendering_spec.rb index b6af7bd445b..fdc2e4382c1 100644 --- a/modules/backlogs/spec/lib/api/v3/work_packages/work_package_representer_rendering_spec.rb +++ b/modules/backlogs/spec/lib/api/v3/work_packages/work_package_representer_rendering_spec.rb @@ -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 diff --git a/modules/backlogs/spec/requests/api/v3/backlog_buckets/index_resource_spec.rb b/modules/backlogs/spec/requests/api/v3/backlog_buckets/index_resource_spec.rb new file mode 100644 index 00000000000..a3ccc243e6f --- /dev/null +++ b/modules/backlogs/spec/requests/api/v3/backlog_buckets/index_resource_spec.rb @@ -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 diff --git a/modules/backlogs/spec/requests/api/v3/backlog_buckets/project_index_resource_spec.rb b/modules/backlogs/spec/requests/api/v3/backlog_buckets/project_index_resource_spec.rb new file mode 100644 index 00000000000..60a2e3651b0 --- /dev/null +++ b/modules/backlogs/spec/requests/api/v3/backlog_buckets/project_index_resource_spec.rb @@ -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 diff --git a/modules/backlogs/spec/requests/api/v3/backlog_buckets/show_resource_spec.rb b/modules/backlogs/spec/requests/api/v3/backlog_buckets/show_resource_spec.rb new file mode 100644 index 00000000000..4b03f2c04b0 --- /dev/null +++ b/modules/backlogs/spec/requests/api/v3/backlog_buckets/show_resource_spec.rb @@ -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