diff --git a/app/contracts/concerns/admin_writable_timestamps.rb b/app/contracts/concerns/admin_writable_timestamps.rb new file mode 100644 index 000000000000..8a83ee22eb85 --- /dev/null +++ b/app/contracts/concerns/admin_writable_timestamps.rb @@ -0,0 +1,47 @@ +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 2012-2024 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 AdminWritableTimestamps + extend ActiveSupport::Concern + + class_methods do + def allow_writable_timestamps(attributes = %i[created_at updated_at]) + Array(attributes).each do |attr| + attribute attr, + writable: -> { default_attributes_admin_writable? } + end + end + end + + private + + # Adds an error if user is archived or not an admin. + def default_attributes_admin_writable? + user.admin? && Setting.apiv3_write_readonly_attributes? + end +end diff --git a/app/contracts/projects/create_contract.rb b/app/contracts/projects/create_contract.rb index 2db60762324c..78b38a775c73 100644 --- a/app/contracts/projects/create_contract.rb +++ b/app/contracts/projects/create_contract.rb @@ -28,6 +28,11 @@ module Projects class CreateContract < BaseContract + include AdminWritableTimestamps + # Projects update their updated_at timestamp due to awesome_nested_set + # so allowing writing here would be useless. + allow_writable_timestamps :created_at + private def validate_user_allowed_to_manage diff --git a/app/contracts/work_packages/create_contract.rb b/app/contracts/work_packages/create_contract.rb index a8090b4ff267..22bf6421b02d 100644 --- a/app/contracts/work_packages/create_contract.rb +++ b/app/contracts/work_packages/create_contract.rb @@ -30,10 +30,12 @@ module WorkPackages class CreateContract < BaseContract + include AdminWritableTimestamps + allow_writable_timestamps + attribute :author_id, - writable: false do - errors.add :author_id, :invalid if model.author != user - end + writable: -> { default_attributes_admin_writable? } + attribute :status_id, # 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. diff --git a/app/models/journal.rb b/app/models/journal.rb index c41a6d787f97..5760be8a3059 100644 --- a/app/models/journal.rb +++ b/app/models/journal.rb @@ -63,6 +63,7 @@ class Journal < ApplicationRecord work_package_children_changed_times work_package_related_changed_times working_days_changed + default_attribute_written system_update ].freeze diff --git a/app/services/work_packages/set_attributes_service.rb b/app/services/work_packages/set_attributes_service.rb index aef4758227ba..15c21a1d5dfb 100644 --- a/app/services/work_packages/set_attributes_service.rb +++ b/app/services/work_packages/set_attributes_service.rb @@ -66,6 +66,7 @@ def set_calculated_attributes(attributes) update_project_dependent_attributes reassign_invalid_status_if_type_changed set_templated_description + set_cause_for_readonly_attributes end def derivable_attribute @@ -416,4 +417,12 @@ def parent_due_later_than_start? (due && !start) || ((due && start) && (due > start)) end + + def set_cause_for_readonly_attributes + return unless work_package.changes.keys.intersect?(%w(created_at updated_at author)) + + work_package.journal_cause = { + "type" => "default_attribute_written" + } + end end diff --git a/app/views/admin/settings/api_settings/show.html.erb b/app/views/admin/settings/api_settings/show.html.erb index 046c3dd5cc31..1f3e78ea358b 100644 --- a/app/views/admin/settings/api_settings/show.html.erb +++ b/app/views/admin/settings/api_settings/show.html.erb @@ -39,6 +39,14 @@ See COPYRIGHT and LICENSE files for more details.
<%= t(:setting_apiv3_max_page_instructions_html) %>
+<%= t(:setting_apiv3_write_readonly_attributes_instructions_html, + api_documentation_link: static_link_to(:api_docs) + ) %>
+