mirror of
https://github.com/opf/openproject.git
synced 2026-06-14 03:30:14 +00:00
update patterns contract and changes to the set attributes service
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
# 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 WorkPackageTypes
|
||||
class UpdateSubjectPatternContract < BaseContract
|
||||
attribute :patterns
|
||||
|
||||
validate :validate_subject_generation_pattern
|
||||
|
||||
private
|
||||
|
||||
def validate_subject_generation_pattern
|
||||
blueprint = model.patterns.subject&.blueprint
|
||||
return if blueprint.nil?
|
||||
|
||||
valid_tokens = flat_valid_token_list
|
||||
invalid_tokens = blueprint.scan(Types::PatternResolver::TOKEN_REGEX)
|
||||
.reduce([]) do |acc, match|
|
||||
token = Types::Patterns::PatternToken.build(match).key
|
||||
valid_tokens.include?(token) ? acc : acc << token
|
||||
end
|
||||
|
||||
if invalid_tokens.any?
|
||||
errors.add(:patterns, :invalid_tokens)
|
||||
end
|
||||
end
|
||||
|
||||
def flat_valid_token_list = Types::Patterns::TokenPropertyMapper.new.tokens_for_type(model).map(&:key)
|
||||
end
|
||||
end
|
||||
@@ -30,10 +30,41 @@
|
||||
|
||||
module WorkPackageTypes
|
||||
class SetAttributesService < ::BaseServices::SetAttributes
|
||||
def initialize(user:, model:, contract_class:, contract_options: nil)
|
||||
super
|
||||
@valid_pattern = true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_attributes(params)
|
||||
super(params.except(:copy_workflow_from))
|
||||
permitted = params.except(:copy_workflow_from)
|
||||
@valid_pattern = check_patterns(permitted)
|
||||
|
||||
if @valid_pattern
|
||||
super(permitted)
|
||||
else
|
||||
super(permitted.except(:patterns))
|
||||
end
|
||||
end
|
||||
|
||||
def validate_and_result
|
||||
success, errors = validate(model, user, options: {})
|
||||
|
||||
if @valid_pattern
|
||||
ServiceResult.new(success:, errors:, result: model)
|
||||
else
|
||||
errors.add(:patterns, :is_invalid)
|
||||
ServiceResult.failure(errors:, result: model)
|
||||
end
|
||||
end
|
||||
|
||||
def check_patterns(params)
|
||||
return true if params.key?(:patterns) && params[:patterns].blank?
|
||||
|
||||
Types::Patterns::CollectionContract.new.call(params[:patterns]).success?
|
||||
rescue ArgumentError
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
# 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"
|
||||
|
||||
module WorkPackageTypes
|
||||
RSpec.describe UpdateSubjectPatternContract do
|
||||
let(:model) { create(:type, :with_subject_pattern) }
|
||||
let(:user) { create(:admin) }
|
||||
|
||||
subject(:contract) { described_class.new(model, user) }
|
||||
|
||||
context "when the user isn't admin" do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
it "the contract is invalid" do
|
||||
expect(contract.validate).to be_falsey
|
||||
end
|
||||
|
||||
it "adds and error to the contract" do
|
||||
contract.validate
|
||||
expect(contract.errors.details).to eq(base: [{ error: :error_unauthorized }])
|
||||
end
|
||||
end
|
||||
|
||||
describe "subject_pattern validation" do
|
||||
let(:valid_pattern) { { subject: { blueprint: "{{author}}", enabled: true } } }
|
||||
let(:invalid_pattern) { { subject: { blueprint: "{{vader_s_rubber_duck}}", enabled: true } } }
|
||||
|
||||
context "with no previous subject patterns" do
|
||||
let(:model) { create(:type) }
|
||||
|
||||
it "is valid with a valid pattern" do
|
||||
model.patterns = valid_pattern
|
||||
expect(contract.validate).to be_truthy
|
||||
end
|
||||
|
||||
it "is invalid if the pattern has bad tokens" do
|
||||
model.patterns = invalid_pattern
|
||||
expect(contract.validate).to be_falsey
|
||||
end
|
||||
|
||||
it "adds an error if the pattern has bad tokens" do
|
||||
model.patterns = invalid_pattern
|
||||
contract.validate
|
||||
|
||||
expect(contract.errors.details).to eq(patterns: [{ error: :invalid_tokens }])
|
||||
end
|
||||
end
|
||||
|
||||
context "with a valid subject pattern" do
|
||||
it "succeeds" do
|
||||
model.patterns = valid_pattern
|
||||
expect(model.validate).to be_truthy
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -58,6 +58,10 @@ FactoryBot.define do
|
||||
end
|
||||
end
|
||||
|
||||
trait :with_subject_pattern do
|
||||
patterns { { subject: { blueprint: "{{author}} - {{status}}/{{type}} - {{id}}", enabled: true } } }
|
||||
end
|
||||
|
||||
trait :default do
|
||||
is_default { true }
|
||||
end
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
# 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"
|
||||
|
||||
module WorkPackageTypes
|
||||
RSpec.describe SetAttributesService do
|
||||
let(:user) { create(:admin) }
|
||||
let(:model) { create(:type, :with_subject_pattern) }
|
||||
let(:params) { Hash.new }
|
||||
|
||||
subject(:service) { described_class.new(user:, model:, contract_class: UpdateSubjectPatternContract) }
|
||||
|
||||
context "when the pattern is malformed rubbish" do
|
||||
let(:params) { { patterns: "vader_s_rubber_duck" } }
|
||||
|
||||
it "fails" do
|
||||
result = service.perform(params)
|
||||
|
||||
expect(result).to be_failure
|
||||
end
|
||||
|
||||
it "adds an error on the patterns atrribute" do
|
||||
result = service.perform(params)
|
||||
expect(result.errors.details).to eq(patterns: [{ error: :is_invalid }])
|
||||
end
|
||||
|
||||
it "does not override the already existing value on the model" do
|
||||
service.perform(params)
|
||||
expect(model).not_to be_changed
|
||||
end
|
||||
end
|
||||
|
||||
context "when the pattern is invalid" do
|
||||
let(:params) { { patterns: { subject: { blueprint: "{{author}}" } } } }
|
||||
|
||||
it "fails" do
|
||||
result = service.perform(params)
|
||||
expect(result).to be_failure
|
||||
end
|
||||
|
||||
it "adds an error on the patterns attribute" do
|
||||
result = service.perform(params)
|
||||
expect(result.errors.details).to eq(patterns: [{ error: :is_invalid }])
|
||||
end
|
||||
|
||||
it "does not override the already existing value on the model" do
|
||||
service.perform(params)
|
||||
expect(model).not_to be_changed
|
||||
end
|
||||
end
|
||||
|
||||
context "when the pattern is blank" do
|
||||
let(:params) { { patterns: nil } }
|
||||
|
||||
it "succeeds" do
|
||||
expect(service.perform(params)).to be_success
|
||||
end
|
||||
|
||||
it "sets the patterns to an empty collection" do
|
||||
service.perform(params)
|
||||
expect(model.patterns).to eq(Types::Patterns::Collection.empty)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user