diff --git a/app/contracts/work_packages/copy_contract.rb b/app/contracts/work_packages/copy_contract.rb index 797c03de4e27..1e8dc6430c1e 100644 --- a/app/contracts/work_packages/copy_contract.rb +++ b/app/contracts/work_packages/copy_contract.rb @@ -32,6 +32,7 @@ module WorkPackages class CopyContract < CreateContract + REQUIRED_PERMISSION = :copy_work_packages # As % Complete can be set while Work and Remaining work are not, copying is # a scenario where this field must be writable attribute :done_ratio, diff --git a/app/contracts/work_packages/create_contract.rb b/app/contracts/work_packages/create_contract.rb index 7ca7bd43c892..8de1ce604c77 100644 --- a/app/contracts/work_packages/create_contract.rb +++ b/app/contracts/work_packages/create_contract.rb @@ -30,6 +30,8 @@ module WorkPackages class CreateContract < BaseContract + REQUIRED_PERMISSION = :add_work_packages + include AdminWritableTimestamps allow_writable_timestamps :created_at @@ -40,9 +42,9 @@ class CreateContract < BaseContract # Overriding permission from WP base contract to ignore change_work_package_status for creation, # because we don't require that permission for writable status during WP creation. # Note that nil would not override and [] would ignore the default permission, so we use the default here: - permission: :add_work_packages + permission: REQUIRED_PERMISSION - default_attribute_permission :add_work_packages + default_attribute_permission REQUIRED_PERMISSION validate :user_allowed_to_add validate :user_allowed_to_manage_file_links @@ -50,8 +52,8 @@ class CreateContract < BaseContract private def user_allowed_to_add - if (model.project && !@user.allowed_in_project?(:add_work_packages, model.project)) || - !@user.allowed_in_any_project?(:add_work_packages) + if (model.project && !@user.allowed_in_project?(REQUIRED_PERMISSION, model.project)) || + !@user.allowed_in_any_project?(REQUIRED_PERMISSION) errors.add(:base, :error_unauthorized) end end diff --git a/frontend/src/app/core/apiv3/endpoints/work_packages/api-v3-work-packages-paths.ts b/frontend/src/app/core/apiv3/endpoints/work_packages/api-v3-work-packages-paths.ts index 07c3c612d787..a4ce3d8f5847 100644 --- a/frontend/src/app/core/apiv3/endpoints/work_packages/api-v3-work-packages-paths.ts +++ b/frontend/src/app/core/apiv3/endpoints/work_packages/api-v3-work-packages-paths.ts @@ -47,8 +47,10 @@ export class ApiV3WorkPackagesPaths extends ApiV3Collection(attributes) { + attributes[:send_notifications] = notify_according_to_params + attributes + }) + .mount + + mount ::API::V3::WorkPackages::Copy::CreateFormAPI + end + end + end + end + end +end diff --git a/lib/api/v3/work_packages/copy/create_form_api.rb b/lib/api/v3/work_packages/copy/create_form_api.rb new file mode 100644 index 000000000000..5be766690864 --- /dev/null +++ b/lib/api/v3/work_packages/copy/create_form_api.rb @@ -0,0 +1,44 @@ +#-- 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 WorkPackages + module Copy + class CreateFormAPI < ::API::OpenProjectAPI + resource :form do + post &::API::V3::Utilities::Endpoints::CreateForm.new(model: WorkPackage, + parse_service: WorkPackages::ParseParamsService, + process_contract: ::WorkPackages::CopyContract) + .mount + end + end + end + end + end +end diff --git a/lib/api/v3/work_packages/copy/create_form_representer.rb b/lib/api/v3/work_packages/copy/create_form_representer.rb new file mode 100644 index 000000000000..09dcf580108e --- /dev/null +++ b/lib/api/v3/work_packages/copy/create_form_representer.rb @@ -0,0 +1,47 @@ +#-- 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 WorkPackages + module Copy + class CreateFormRepresenter < FormRepresenter + include API::Decorators::CreateForm + + def form_url + api_v3_paths.work_package_copy_form(meta.source.id) + end + + def resource_url + api_v3_paths.work_package_copy(meta.source.id) + end + end + end + end + end +end diff --git a/lib/api/v3/work_packages/copy/work_package_copy_payload_representer.rb b/lib/api/v3/work_packages/copy/work_package_copy_payload_representer.rb new file mode 100644 index 000000000000..ca366c3aca6f --- /dev/null +++ b/lib/api/v3/work_packages/copy/work_package_copy_payload_representer.rb @@ -0,0 +1,45 @@ +#-- 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 WorkPackages + module Copy + class WorkPackageCopyPayloadRepresenter < ::API::V3::WorkPackages::WorkPackageRepresenter + include ::API::Utilities::PayloadRepresenter + + cached_representer disabled: true + + def writable_attributes + super + %w[status] + end + end + end + end + end +end diff --git a/lib/api/v3/work_packages/work_package_representer.rb b/lib/api/v3/work_packages/work_package_representer.rb index 14ac3de591a6..4b683fe6e812 100644 --- a/lib/api/v3/work_packages/work_package_representer.rb +++ b/lib/api/v3/work_packages/work_package_representer.rb @@ -112,7 +112,7 @@ def self_v3_path(*) end link :copy, - cache_if: -> { add_work_packages_allowed? } do + cache_if: -> { copy_work_packages_allowed? } do next if represented.new_record? { @@ -629,6 +629,11 @@ def add_work_packages_allowed? current_user.allowed_in_project?(:add_work_packages, represented.project) end + def copy_work_packages_allowed? + @copy_work_packages_allowed ||= + current_user.allowed_in_project?(:copy_work_packages, represented.project) + end + def relations self_path = api_v3_paths.work_package_relations(represented.id) visible_relations = represented diff --git a/lib/api/v3/work_packages/work_packages_api.rb b/lib/api/v3/work_packages/work_packages_api.rb index 152033faa665..f922ff6de1ec 100644 --- a/lib/api/v3/work_packages/work_packages_api.rb +++ b/lib/api/v3/work_packages/work_packages_api.rb @@ -38,8 +38,11 @@ class WorkPackagesAPI < ::API::OpenProjectAPI # The endpoint needs to be mounted before the GET :work_packages/:id. # Otherwise, the matcher for the :id also seems to match available_projects. # This is also true when the :id param is declared to be of type: Integer. + # Note: Adding `requirements: /\d*/` to the :id definition matches numbers only. mount ::API::V3::WorkPackages::AvailableProjectsOnCreateAPI mount ::API::V3::WorkPackages::Schema::WorkPackageSchemasAPI + mount ::API::V3::WorkPackages::CreateFormAPI + mount ::API::V3::WorkPackages::Copy::CopyAPI get do authorize_in_any_work_package(:view_work_packages) @@ -61,7 +64,7 @@ class WorkPackagesAPI < ::API::OpenProjectAPI }) .mount - route_param :id, type: Integer, desc: "Work package ID" do + route_param :id, type: Integer, requirements: { id: /[0-9]*/ }, desc: "Work package ID" do helpers WorkPackagesSharedHelpers helpers do @@ -89,18 +92,16 @@ class WorkPackagesAPI < ::API::OpenProjectAPI delete &::API::V3::Utilities::Endpoints::Delete.new(model: WorkPackage) .mount - mount ::API::V3::WorkPackages::WatchersAPI mount ::API::V3::Activities::ActivitiesByWorkPackageAPI mount ::API::V3::Attachments::AttachmentsByWorkPackageAPI mount ::API::V3::Repositories::RevisionsByWorkPackageAPI - mount ::API::V3::WorkPackages::UpdateFormAPI mount ::API::V3::WorkPackages::AvailableAssigneesAPI mount ::API::V3::WorkPackages::AvailableProjectsOnEditAPI mount ::API::V3::WorkPackages::AvailableRelationCandidatesAPI + mount ::API::V3::WorkPackages::UpdateFormAPI + mount ::API::V3::WorkPackages::WatchersAPI mount ::API::V3::WorkPackages::WorkPackageRelationsAPI end - - mount ::API::V3::WorkPackages::CreateFormAPI end end end