diff --git a/modules/wikis/app/contracts/wikis/page_links/relation_page_link_create_contract.rb b/modules/wikis/app/contracts/wikis/page_links/relation_page_link_create_contract.rb new file mode 100644 index 00000000000..a15c5ff5a07 --- /dev/null +++ b/modules/wikis/app/contracts/wikis/page_links/relation_page_link_create_contract.rb @@ -0,0 +1,66 @@ +# 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 Wikis + module PageLinks + class RelationPageLinkCreateContract < ::ModelContract + attribute :author + attribute :identifier + attribute :linkable + attribute :provider + + validates :identifier, presence: true + validates :linkable, presence: true + validates :provider, presence: true + + validate :provider_exists? + validate :author_must_be_user + validate :validate_user_allowed_to_manage + + private + + def author_must_be_user + errors.add(:author, :invalid) unless author == user + end + + def validate_user_allowed_to_manage + linkable = model.linkable + + if linkable.present? && !user.allowed_in_project?(:manage_wiki_page_links, linkable.project) + errors.add(:base, :error_unauthorized) + end + end + + def provider_exists? + errors.add(:provider, :does_not_exist) if model.provider.is_a?(InexistentProvider) + end + end + end +end diff --git a/modules/wikis/app/models/wikis/inexistent_provider.rb b/modules/wikis/app/models/wikis/inexistent_provider.rb new file mode 100644 index 00000000000..084619d2b4f --- /dev/null +++ b/modules/wikis/app/models/wikis/inexistent_provider.rb @@ -0,0 +1,41 @@ +# 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 Wikis + class InexistentProvider < Wikis::Provider + include InexistentModel + + def self.visible? = false + + def self.registry_prefix = :inexistent + + def user_connected?(_user) = false + end +end diff --git a/modules/wikis/app/services/wikis/page_links/create_service.rb b/modules/wikis/app/services/wikis/page_links/create_service.rb new file mode 100644 index 00000000000..eb9371246f6 --- /dev/null +++ b/modules/wikis/app/services/wikis/page_links/create_service.rb @@ -0,0 +1,39 @@ +# 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 Wikis + module PageLinks + class CreateService < ::BaseServices::Create + private + + def default_contract_class = RelationPageLinkCreateContract + end + end +end diff --git a/modules/wikis/app/services/wikis/page_links/set_attributes_service.rb b/modules/wikis/app/services/wikis/page_links/set_attributes_service.rb new file mode 100644 index 00000000000..1e3b0d5e045 --- /dev/null +++ b/modules/wikis/app/services/wikis/page_links/set_attributes_service.rb @@ -0,0 +1,36 @@ +# 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 Wikis + module PageLinks + class SetAttributesService < ::BaseServices::SetAttributes + end + end +end diff --git a/modules/wikis/spec/contracts/wikis/page_links/relation_page_link_create_contract_spec.rb b/modules/wikis/spec/contracts/wikis/page_links/relation_page_link_create_contract_spec.rb new file mode 100644 index 00000000000..09c6107b63c --- /dev/null +++ b/modules/wikis/spec/contracts/wikis/page_links/relation_page_link_create_contract_spec.rb @@ -0,0 +1,64 @@ +# 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 "contracts/shared/model_contract_shared_context" +require_module_spec_helper + +module Wikis + module PageLinks + RSpec.describe RelationPageLinkCreateContract do + include_context "ModelContract shared context" + let(:linkable) { create(:work_package) } + let(:project) { linkable.project } + let(:current_user) { create(:user, member_with_permissions: { project => %i(manage_wiki_page_links view_work_packages) }) } + let(:relation_page_link) { build_stubbed(:relation_wiki_page_link, author: current_user, linkable:) } + + subject(:contract) { described_class.new(relation_page_link, current_user) } + + it_behaves_like "contract is valid" + + context "when creator is not the current user" do + let(:author) { create(:user, member_with_permissions: { project => %i(manage_wiki_page_links view_work_packages) }) } + let(:relation_page_link) { build_stubbed(:relation_wiki_page_link, author:, linkable:) } + + include_examples "contract is invalid", author: :invalid + end + + context "when the provider is inexistent" do + let(:provider) { InexistentProvider.new } + + before { relation_page_link.provider = provider } + + include_examples "contract is invalid", provider: :does_not_exist + end + end + end +end diff --git a/modules/wikis/spec/services/wikis/page_links/create_service_spec.rb b/modules/wikis/spec/services/wikis/page_links/create_service_spec.rb new file mode 100644 index 00000000000..91ac63bc390 --- /dev/null +++ b/modules/wikis/spec/services/wikis/page_links/create_service_spec.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. +#++ + +require "spec_helper" +require "services/base_services/behaves_like_create_service" + +require_module_spec_helper + +module Wikis + module PageLinks + RSpec.describe CreateService do + it_behaves_like "BaseServices create service" do + let(:contract_class) { RelationPageLinkCreateContract } + let(:factory) { :relation_wiki_page_link } + end + + it "defaults to the RelationPageLinkCreateContract" do + service = described_class.new(user: nil) + + expect(service.contract_class).to eq(RelationPageLinkCreateContract) + end + end + end +end diff --git a/modules/wikis/spec/services/wikis/page_links/set_attributes_service_spec.rb b/modules/wikis/spec/services/wikis/page_links/set_attributes_service_spec.rb new file mode 100644 index 00000000000..201aed78e69 --- /dev/null +++ b/modules/wikis/spec/services/wikis/page_links/set_attributes_service_spec.rb @@ -0,0 +1,89 @@ +# 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_module_spec_helper + +module Wikis + module PageLinks + RSpec.describe SetAttributesService do + let(:model_instance) { RelationPageLink.new } + let(:contract_instance) do + instance_double(RelationPageLinkCreateContract, validate: contract_valid, errors: contract_errors) + end + + let(:contract_class) do + class_double(RelationPageLinkCreateContract, new: contract_instance) + end + + let(:contract_errors) { instance_double(ActiveModel::Errors) } + let(:contract_valid) { true } + + let(:current_user) { build(:user) } + + let(:service) do + described_class.new(user: current_user, model: model_instance, contract_class:, contract_options: {}) + end + + let(:params) { {} } + + subject(:result) { service.call(params) } + + it "returns the instance as the result" do + expect(subject.result).to eql model_instance + end + + it "is a success" do + expect(subject).to be_success + end + + context "with params" do + let(:params) { { identifier: "Foobar" } } + + it "assigns the params" do + service.call(params) + expect(model_instance.identifier).to eq "Foobar" + end + end + + context "with an invalid contract" do + let(:contract_valid) { false } + + it "returns failure" do + expect(subject).to be_failure + end + + it "returns the contract's errors" do + expect(subject.errors).to eql(contract_errors) + end + end + end + end +end