From 4ca801c1eac11b5c62d45cc4dcb90b9717cd5303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 11 Sep 2024 08:22:01 +0200 Subject: [PATCH 01/34] Bumped version to 14.5.1 [ci skip] --- lib/open_project/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/open_project/version.rb b/lib/open_project/version.rb index 04fc0bfcb96e..93d308ae9fff 100644 --- a/lib/open_project/version.rb +++ b/lib/open_project/version.rb @@ -33,7 +33,7 @@ module OpenProject module VERSION # :nodoc: MAJOR = 14 MINOR = 5 - PATCH = 0 + PATCH = 1 class << self # Used by semver to define the special version (if any). From 52aa9a2c05978d4aea03f012d7ced537de01496b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 19:45:18 +0000 Subject: [PATCH 02/34] build(deps): bump ruby-saml from 1.16.0 to 1.17.0 Bumps [ruby-saml](https://github.com/saml-toolkits/ruby-saml) from 1.16.0 to 1.17.0. - [Release notes](https://github.com/saml-toolkits/ruby-saml/releases) - [Changelog](https://github.com/SAML-Toolkits/ruby-saml/blob/master/CHANGELOG.md) - [Commits](https://github.com/saml-toolkits/ruby-saml/compare/v1.16.0...v1.17.0) --- updated-dependencies: - dependency-name: ruby-saml dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index f3c89a818753..3d2bb1a6c360 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1041,7 +1041,7 @@ GEM ruby-prof (1.7.0) ruby-progressbar (1.13.0) ruby-rc4 (0.1.5) - ruby-saml (1.16.0) + ruby-saml (1.17.0) nokogiri (>= 1.13.10) rexml ruby2_keywords (0.0.5) From a90c4389b7a902a0886987a67ebb4df259577466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 11 Sep 2024 15:10:43 +0200 Subject: [PATCH 03/34] Remove docker compose specific docs --- .../installation/docker/README.md | 71 +++---------------- 1 file changed, 10 insertions(+), 61 deletions(-) diff --git a/docs/installation-and-operations/installation/docker/README.md b/docs/installation-and-operations/installation/docker/README.md index 27bcdcecbe9f..08a051a153e8 100644 --- a/docs/installation-and-operations/installation/docker/README.md +++ b/docs/installation-and-operations/installation/docker/README.md @@ -1,10 +1,10 @@ --- sidebar_navigation: - title: Docker + title: Docker (all-in-one) priority: 300 --- -# Install OpenProject with Docker +# OpenProject on Docker all-in-one container [Docker](https://www.docker.com) is a way to distribute self-contained applications easily. We provide a Docker image for the Community edition that you can very easily install and upgrade on your servers. However, contrary to the manual or package-based installation, your machine needs to have the Docker Engine @@ -12,7 +12,7 @@ installed first, which usually requires a recent operating system. Please see th *** -**Supported architectures** +## Supported architectures Starting with OpenProject 12.5.6 we publish our containers for three architectures. @@ -24,75 +24,24 @@ The OpenProject **BIM Edition** is only supported on AMD64, however. *** -**Limitations** +## Limitations Note that the docker container setup does not allow for integration of repositories within OpenProject. You can reference external repositories, but cannot set them up through OpenProject itself. For that feature to work, you need to use the packaged installation method. -**Overview** +## Overview OpenProject's docker setup can be launched in two ways: -1. Multiple containers (recommended), each with a single process inside, using a Compose file. Allows to easily choose which services you want to run, and simplifies scaling and monitoring aspects. +### One container per process (recommend) -2. One container with all the processes inside. Easy but not recommended for production. This is the legacy behavior. +This is the recommended approach for using OpenProject with Docker, where each component has a single container inside, orchestrated using a Compose file. Allows to easily choose which services you want to run, and simplifies scaling and monitoring aspects. -## One container per process (recommended) +Please follow the [OpenProject for Docker compose](../docker-compose/) documentation for this installation method -### Quick Start - -First, you must clone the [openproject-deploy](https://github.com/opf/openproject-deploy/tree/stable/14/compose) repository: - -```shell -git clone https://github.com/opf/openproject-deploy --depth=1 --branch=stable/14 openproject -``` - -Then, change into the compose folder, this folder will be the location where you enter all following commands: - -```shell -cd openproject/compose -``` - -Make sure you are using the latest version of the Docker images: - -```shell -docker-compose pull -``` - -Launch the containers: - -```shell -OPENPROJECT_HTTPS=false docker-compose up -d -``` - -After a while, OpenProject should be up and running on `http://localhost:8080`. The default username and password is login: `admin`, and password: `admin`. You need to explicitly disable HTTPS mode on startup as OpenProject assumes it's running behind HTTPS in production by default. - -> **Note:** The `docker-compose.yml` file present in the repository can be adjusted to your convenience. With each pull it will be overwritten. Best practice is to use the file `docker-compose.override.yml` for that case. For instance you could mount specific configuration files, override environment variables, or switch off services you don't need. Please refer to the official [Docker Compose documentation](https://docs.docker.com/compose/extends/) for more details. - -You can stop the Compose stack by running: - -```shell -docker-compose stop -``` - -You can stop and remove all containers by running: - -```shell -docker-compose down -``` - -This will not remove your data which is persisted in named volumes, likely called `compose_opdata` (for attachments) and `compose_pgdata` (for the database). The exact name depends on the name of the directory where your `docker-compose.yml` and/or you `docker-compose.override.yml` files are stored (`compose` in this case). - -If you want to start from scratch and remove the existing data you will have to remove these volumes via -`docker volume rm compose_opdata compose_pgdata`. - -### Configuration - -Please see the [advanced configuration guide's docker paragraphs](../../configuration/#docker) - -#### BIM edition +### Single docker container -In order to install or change to BIM inside a Docker environment, please navigate to the [Docker Installation for OpenProject BIM](../../bim-edition/#docker-installation-openproject-bim) paragraph at the BIM edition documentation. +This guide will show you to install OpenProject in one container with all the processes inside. This allows for a very quick start but is not recommended for production as it hinders upgradability of the different components such as the database. ## All-in-one container From 2ccae0573cd39880a37769e28882ddb6870b128d Mon Sep 17 00:00:00 2001 From: OpenProject Actions CI Date: Thu, 12 Sep 2024 03:09:34 +0000 Subject: [PATCH 04/34] update locales from crowdin [ci skip] --- config/locales/crowdin/de.yml | 28 +++++++++---------- .../boards/config/locales/crowdin/js-kk.yml | 4 +-- modules/boards/config/locales/crowdin/kk.yml | 4 +-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/config/locales/crowdin/de.yml b/config/locales/crowdin/de.yml index 2393b8e3f85d..695a8c883fce 100644 --- a/config/locales/crowdin/de.yml +++ b/config/locales/crowdin/de.yml @@ -1661,7 +1661,7 @@ de: input_caption_table: "By default all attributes added as columns in the work package list are selected. Long text fields are not available in table based exports." pdf: export_type: - label: "PDF export type" + label: "PDF-Exporttyp" options: table: label: "Tabelle" @@ -1673,10 +1673,10 @@ de: label: "Gantt-Diagramm" caption: "Export the work packages list in a Gantt diagram view." include_images: - label: "Include images" + label: "Bilder inkludieren" caption: "Exclude images to reduce the size of the PDF export." gantt_zoom_levels: - label: "Zoom levels" + label: "Zoomstufe" caption: "Select what is the zoom level for dates displayed in the chart." options: days: "Tage" @@ -1696,18 +1696,18 @@ de: long_text_fields: input_caption: "Standardmäßig sind alle Langtextfelder ausgewählt." input_label: "Langtextfelder hinzufügen" - input_placeholder: "Search for long text fields" - drag_area_label: "Manage long text fields" + input_placeholder: "Nach Textfeldern suchen" + drag_area_label: "Textfelder hinzufügen" xls: include_relations: - label: "Include relations" - caption: "This option will create a duplicate of each work package for every relation this has with another work package." + label: "Beziehungen inkludieren" + caption: "Jedes Arbeitspakets, mit dem eine Beziehung mit dem exportierten Arbeitspaket besteht, als zusätzliche Zeile einfügen." include_descriptions: - label: "Include descriptions" - caption: "This option will add a description column in raw format." - your_work_packages_export: "Work packages are being exported" - succeeded: "Export completed" - failed: "An error has occurred while trying to export the work packages: %{message}" + label: "Beschreibungen inkludieren" + caption: "Mit dieser Option wird die Beschreibungs-Spalte im Rohformat hinzugefügt." + your_work_packages_export: "Arbeitspakete werden exportiert" + succeeded: "Export abgeschlossen" + failed: "Beim Versuch, die Arbeitspakete zu exportieren, ist ein Fehler aufgetreten: %{message}" format: atom: "Atom" csv: "CSV" @@ -2358,8 +2358,8 @@ de: label_role_plural: "Rollen" label_role_search: "Rolle für neue Mitglieder zuweisen" label_scm: "Versionskontrollsystem" - label_scroll_left: "Scroll left" - label_scroll_right: "Scroll right" + label_scroll_left: "Nach links scrollen" + label_scroll_right: "Nach rechts scrollen" label_search: "Suche" label_search_by_name: "Nach Name suchen" label_send_information: "Neue Anmeldeinformationen an den Benutzer senden" diff --git a/modules/boards/config/locales/crowdin/js-kk.yml b/modules/boards/config/locales/crowdin/js-kk.yml index 102d11ff8201..f5b6aafa59f6 100644 --- a/modules/boards/config/locales/crowdin/js-kk.yml +++ b/modules/boards/config/locales/crowdin/js-kk.yml @@ -7,7 +7,7 @@ kk: label_unnamed_list: 'Unnamed list' label_board_type: 'Board type' upsale: - teaser_text: 'Would you like to automate your workflows with Boards? Advanced boards are an Enterprise add-on. Please upgrade to a paid plan.' + teaser_text: 'Өзіңіздегі жұмыс ағымын автоматтандырғыңыз келеді ме? Жетілдірілген тақталар Enterprise қосымшасы болып келеді. Ақылы жоспарға өтуіңізді сұраймыз.' upgrade: 'Upgrade now' lists: delete: 'Delete list' @@ -62,7 +62,7 @@ kk: status: Status version: Version subproject: Subproject - subtasks: Parent-child + subtasks: Бас-бағыныңқы basic: Basic select_attribute: "Action attribute" add_list_modal: diff --git a/modules/boards/config/locales/crowdin/kk.yml b/modules/boards/config/locales/crowdin/kk.yml index 76ed0a750cc2..d60b8773affa 100644 --- a/modules/boards/config/locales/crowdin/kk.yml +++ b/modules/boards/config/locales/crowdin/kk.yml @@ -1,8 +1,8 @@ #English strings go here kk: plugin_openproject_boards: - name: "OpenProject Boards" - description: "Provides board views." + name: "OpenProject тақталары" + description: "Тақталардың берілген әлпеттері." permission_show_board_views: "View boards" permission_manage_board_views: "Manage boards" project_module_board_view: "Boards" From c0e06a0d9801d6e7b78b9679de59fd53b112e490 Mon Sep 17 00:00:00 2001 From: as-op Date: Thu, 12 Sep 2024 12:21:08 +0200 Subject: [PATCH 05/34] fix broken docker links --- .../installation/kubernetes/README.md | 2 +- .../installation-and-operations/installation/synology/README.md | 2 +- .../misc/migration-to-postgresql13/README.md | 2 +- docs/installation-and-operations/operation/restoring/README.md | 2 +- docs/installation-and-operations/operation/upgrading/README.md | 2 +- script/docs/check_links | 1 + 6 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/installation-and-operations/installation/kubernetes/README.md b/docs/installation-and-operations/installation/kubernetes/README.md index a57325d7300b..975be81b267b 100644 --- a/docs/installation-and-operations/installation/kubernetes/README.md +++ b/docs/installation-and-operations/installation/kubernetes/README.md @@ -7,6 +7,6 @@ sidebar_navigation: # Kubernetes Kubernetes is a container orchestration tool. As such it can use the -OpenProject docker container in the same manner as shown in the [docker section](../docker/#one-container-per-process-recommended). +OpenProject docker container in the same manner as shown in the [docker section](../docker/). In the [openproject-deploy](https://github.com/opf/openproject-deploy/blob/stable/14/kubernetes/README.md) repository we provide further information and an exemplary set of YAML files defining a complete OpenProject setup on Kubernetes. diff --git a/docs/installation-and-operations/installation/synology/README.md b/docs/installation-and-operations/installation/synology/README.md index ee8431a6d286..d0ca8080b429 100644 --- a/docs/installation-and-operations/installation/synology/README.md +++ b/docs/installation-and-operations/installation/synology/README.md @@ -5,7 +5,7 @@ sidebar_navigation: false # Synology Synology offers NAS devices that come with a UI for starting docker containers on them. -This means OpenProject has to be used exactly as described in the [docker](../docker/#one-container-per-process-recommended) section. +This means OpenProject has to be used exactly as described in the [docker](../docker/) section. ## Launching the container diff --git a/docs/installation-and-operations/misc/migration-to-postgresql13/README.md b/docs/installation-and-operations/misc/migration-to-postgresql13/README.md index d5d093d3a2c5..ab0fa2450f63 100644 --- a/docs/installation-and-operations/misc/migration-to-postgresql13/README.md +++ b/docs/installation-and-operations/misc/migration-to-postgresql13/README.md @@ -160,7 +160,7 @@ sudo yum remove pgsql10 ## Compose-based docker installation -> Please follow this section only if you have installed OpenProject using [this procedure](../../installation/docker/#one-container-per-process-recommended). +> Please follow this section only if you have installed OpenProject using [this procedure](../../installation/docker/). > Before attempting the upgrade, please ensure you have performed a backup of your installation by following the [backup guide](../../operation/backing-up/). You can find the upgrade instructions for your docker-compose setup in the [openproject-deploy](https://github.com/opf/openproject-deploy/blob/stable/14/compose/control/README.md#upgrade) repository. diff --git a/docs/installation-and-operations/operation/restoring/README.md b/docs/installation-and-operations/operation/restoring/README.md index 82e1ddf22bab..8b5ffa236e49 100644 --- a/docs/installation-and-operations/operation/restoring/README.md +++ b/docs/installation-and-operations/operation/restoring/README.md @@ -246,7 +246,7 @@ You may need to create the `files` directory if it doesn't exist yet. #### 4) Start OpenProject -Start the container as described in the [installation section](../../installation/docker/#one-container-per-process-recommended) +Start the container as described in the [installation section](../../installation/docker/) mounting `/var/lib/openproject/pgdata` (and `/var/lib/openproject/assets/` for attachments). ## Changing the database schema from cloud to on-premises diff --git a/docs/installation-and-operations/operation/upgrading/README.md b/docs/installation-and-operations/operation/upgrading/README.md index 4be46a4a2428..f752714d9832 100644 --- a/docs/installation-and-operations/operation/upgrading/README.md +++ b/docs/installation-and-operations/operation/upgrading/README.md @@ -159,7 +159,7 @@ sudo chown -R 102 /volume1/openproject/* ``` After that it's simply a matter of launching the new container mounted with the copied `pgdata` and `assets` folders -as described in the [installation section](../../installation/docker/#one-container-per-process-recommended). +as described in the [installation section](../../installation/docker/). ## Upgrade notes from 9.x diff --git a/script/docs/check_links b/script/docs/check_links index 9bb54e765ced..553eab0878a7 100755 --- a/script/docs/check_links +++ b/script/docs/check_links @@ -141,6 +141,7 @@ class DocsChecker @docs.push( { path: "#{@root_path}/api/v3/spec.json", anchors: [], links: [] }, { path: "#{@root_path}/api/v3/spec.yml", anchors: [], links: [] }, + { path: "#{@root_path}/installation-and-operations/installation/docker-compose", anchors: [], links: [] }, { path: "#{@root_path}/installation-and-operations/installation/helm-chart", anchors: [], links: [] }, { path: "#{@root_path}/development/translate-openproject/fair-language", anchors: [], links: [] } ) From cfde86e48b83326191b87e75f373d61716cd1a5e Mon Sep 17 00:00:00 2001 From: Markus Kahl Date: Thu, 12 Sep 2024 14:04:56 +0100 Subject: [PATCH 06/34] fix internal error opening budgets (by fixing avatar rendering in ActualLaborBudgetItemsComponent) --- .../actual_labor_budget_items_component.rb | 2 +- ...ctual_labor_budget_items_component_spec.rb | 64 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 modules/budgets/spec/components/budgets/actual_labor_budget_items_component_spec.rb diff --git a/modules/budgets/app/components/budgets/actual_labor_budget_items_component.rb b/modules/budgets/app/components/budgets/actual_labor_budget_items_component.rb index 08c79608ace6..e449c10c873b 100644 --- a/modules/budgets/app/components/budgets/actual_labor_budget_items_component.rb +++ b/modules/budgets/app/components/budgets/actual_labor_budget_items_component.rb @@ -58,7 +58,7 @@ def entry_hours(work_package, entry) end def entry_user(entry) - helpers.avatar(entry.principal, hide_name: false, size: :mini) + helpers.avatar(entry.user, hide_name: false, size: :mini) end def entry_costs(entry) diff --git a/modules/budgets/spec/components/budgets/actual_labor_budget_items_component_spec.rb b/modules/budgets/spec/components/budgets/actual_labor_budget_items_component_spec.rb new file mode 100644 index 000000000000..e371a9e801a9 --- /dev/null +++ b/modules/budgets/spec/components/budgets/actual_labor_budget_items_component_spec.rb @@ -0,0 +1,64 @@ +#-- 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 "rails_helper" + +RSpec.describe Budgets::ActualLaborBudgetItemsComponent, type: :component do + let(:project) do + create( + :project, + enabled_module_names: %i[costs work_package_tracking budgets], + members: { + user => member_role + } + ) + end + + let(:member_role) { create(:project_role, name: "Member", permissions: [:view_time_entries]) } + let(:budget) { create :budget, project: } + let(:work_package) { create :work_package, project:, budget:, author: user } + let(:user) { create :user } + + subject do + described_class.new budget:, project: + end + + before do + login_as user + end + + describe "with time entries" do + let!(:time_entry) { create :time_entry, work_package:, user: } + + it "renders the link to the time entry's user's avatar" do + rendered = render_inline(subject) + + expect(rendered).to have_css("opce-principal[data-title='\"#{user.name}\"']") + end + end +end From 71c0c7193b0df0be771491b78083e6bc0bd158b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Thu, 12 Sep 2024 15:48:58 +0200 Subject: [PATCH 07/34] Update installation methods --- .../installation/README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/installation-and-operations/installation/README.md b/docs/installation-and-operations/installation/README.md index 26e3702d8054..b446ad3df95b 100644 --- a/docs/installation-and-operations/installation/README.md +++ b/docs/installation-and-operations/installation/README.md @@ -6,15 +6,15 @@ sidebar_navigation: # Installing OpenProject -OpenProject can be setup in three different ways: +OpenProject can be setup in these different ways: -| Topic | Content | -| ------------------------------------------------ | ------------------------------------------------------------ | -| [Installation with DEB/RPM packages](./packaged) | This is the recommended way to install OpenProject | -| [Installation with Docker](./docker) | This allows to setup OpenProject in an isolated manner using Docker | -| [Installation with Kubernetes](./kubernetes) | This allows to setup OpenProject using Kubernetes | -| [Installation with Helm charts](./helm-chart) | This allows to setup OpenProject using Helm charts | -| [Other](misc/) | Extra information on installing OpenProject on specific platforms such as Kubernetes. | +| Topic | Content | +| ---------------------------------------------------- | ------------------------------------------------------------------------------------- | +| [Installation with DEB/RPM packages](./packaged) | This is the recommended way to install OpenProject | +| [Installation with Docker Compose](./docker-compose) | This allows to setup OpenProject in an isolated manner using Docker Compose | +| [Installation with single Docker container](./docker)| This allows to setup OpenProject in a single Docker container | +| [Installation with Helm charts](./helm-chart) | This allows to setup OpenProject using Helm charts | +| [Other](misc/) | Extra information on installing OpenProject on specific platforms such as Kubernetes. | > **NOTE: We recommend using the DEB/RPM package installation.** From e13c437f8e92d49f00966691581500da71938d5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Thu, 12 Sep 2024 15:49:46 +0200 Subject: [PATCH 08/34] Update reference to Kubernetes --- docs/installation-and-operations/installation/misc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation-and-operations/installation/misc/README.md b/docs/installation-and-operations/installation/misc/README.md index f0e8ce1b4c5f..b73e67d0c498 100644 --- a/docs/installation-and-operations/installation/misc/README.md +++ b/docs/installation-and-operations/installation/misc/README.md @@ -12,7 +12,7 @@ The respective sections explain everything you need to know. To make things easier here we give further instructions on how to get up and running with OpenProject on different platforms which use either the docker container or the package: -* [Kubernetes](../kubernetes) +* [Kubernetes using the OpenProject Helm chart](../helm-chart) * [Synology](../synology) * [Manual (not recommended)](../manual) From 2f0e8ed7ebb393f02dfeff8b1b5f10018924a796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Thu, 12 Sep 2024 15:52:03 +0200 Subject: [PATCH 09/34] Update reference to kubernetes / helm chart --- .../installation/kubernetes/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation-and-operations/installation/kubernetes/README.md b/docs/installation-and-operations/installation/kubernetes/README.md index 975be81b267b..3238db6e304b 100644 --- a/docs/installation-and-operations/installation/kubernetes/README.md +++ b/docs/installation-and-operations/installation/kubernetes/README.md @@ -9,4 +9,4 @@ sidebar_navigation: Kubernetes is a container orchestration tool. As such it can use the OpenProject docker container in the same manner as shown in the [docker section](../docker/). -In the [openproject-deploy](https://github.com/opf/openproject-deploy/blob/stable/14/kubernetes/README.md) repository we provide further information and an exemplary set of YAML files defining a complete OpenProject setup on Kubernetes. +If you'd like to run OpenProject on Kubernetes, please take a look at the [OpenProject helm chart](../helm-chart). From 048dd5cde19e26b29742cbb64d01d0d9af45f28f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Thu, 12 Sep 2024 17:10:06 +0200 Subject: [PATCH 10/34] Add spec --- .../features/global_roles/global_role_crud_spec.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/spec/features/global_roles/global_role_crud_spec.rb b/spec/features/global_roles/global_role_crud_spec.rb index 7fbcb68b527f..0731870ec1d1 100644 --- a/spec/features/global_roles/global_role_crud_spec.rb +++ b/spec/features/global_roles/global_role_crud_spec.rb @@ -62,4 +62,18 @@ # Then I should see "Successful creation." expect(page).to have_text "Successful creation." end + + context "with a non-member using dependent project permissions" do + let!(:non_member) { create(:non_member, permissions: %i[view_project_attributes]) } + + it "can still create it (Regression #57906)" do + # When I go to the new page of "Role" + visit new_role_path + check "Global role" + fill_in "Name", with: "Manager" + click_on "Create" + # Then I should see "Successful creation." + expect(page).to have_text "Successful creation." + end + end end From 530fd589dd6a2cba8f675073feec78daf48eb735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Thu, 12 Sep 2024 17:08:23 +0200 Subject: [PATCH 11/34] Disable role permission checkboxes that are hidden https://community.openproject.org/work_packages/57906 --- .../controllers/dynamic/admin/roles.controller.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/frontend/src/stimulus/controllers/dynamic/admin/roles.controller.ts b/frontend/src/stimulus/controllers/dynamic/admin/roles.controller.ts index 4f1b52e20d49..da3b6092fde1 100644 --- a/frontend/src/stimulus/controllers/dynamic/admin/roles.controller.ts +++ b/frontend/src/stimulus/controllers/dynamic/admin/roles.controller.ts @@ -54,8 +54,17 @@ export default class RolesController extends Controller { } globalRoleValueChanged() { - this.memberAttributesTarget.hidden = this.globalRoleValue; - this.memberPermissionsTarget.hidden = this.globalRoleValue; - this.globalPermissionsTarget.hidden = !this.globalRoleValue; + this.toggleEnabled(this.memberAttributesTarget, !this.globalRoleValue); + this.toggleEnabled(this.memberPermissionsTarget, !this.globalRoleValue); + this.toggleEnabled(this.globalPermissionsTarget, this.globalRoleValue); + } + + toggleEnabled(target:HTMLElement, enabled:boolean) { + target.hidden = !enabled; + target + .querySelectorAll('input,select') + .forEach((input:HTMLInputElement) => { + input.disabled = !enabled; + }); } } From d76dc513671e179f15b7bc48f5610287e89d01c8 Mon Sep 17 00:00:00 2001 From: OpenProject Actions CI Date: Thu, 12 Sep 2024 15:57:56 +0000 Subject: [PATCH 12/34] update locales from crowdin [ci skip] --- config/locales/crowdin/de.yml | 40 ++++++++++++++++---------------- config/locales/crowdin/js-de.yml | 2 +- config/locales/crowdin/js-lt.yml | 2 +- config/locales/crowdin/lt.yml | 8 +++---- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/config/locales/crowdin/de.yml b/config/locales/crowdin/de.yml index 695a8c883fce..0581d4408526 100644 --- a/config/locales/crowdin/de.yml +++ b/config/locales/crowdin/de.yml @@ -1657,27 +1657,27 @@ de: label: "XLS" columns: input_label_report: "Spalten zur Attributtabelle hinzufügen" - input_caption_report: "By default all attributes added as columns in the work package list are selected. Long text fields are not available in the attribute table, but can be displayed below it." - input_caption_table: "By default all attributes added as columns in the work package list are selected. Long text fields are not available in table based exports." + input_caption_report: "Standardmäßig sind alle Attribute, die als Spalten in der Arbeitspaketliste hinzugefügt wurden, ausgewählt. Textfelder sind in der Attribut-Tabelle nicht verfügbar, können aber unterhalb der Tabelle angezeigt werden." + input_caption_table: "Standardmäßig sind alle Attribute, die als Spalten in der Arbeitspaketliste hinzugefügt wurden, ausgewählt. Textfelder sind in tabellenbasierten Exporten nicht verfügbar." pdf: export_type: label: "PDF-Exporttyp" options: table: label: "Tabelle" - caption: "Export the work packages list in a table with the desired columns." + caption: "Exportieren Sie die Liste der Arbeitspakete in eine Tabelle mit den gewünschten Spalten." report: label: "Report" - caption: "Export the work package on a detailed report of all work packages in the list." + caption: "Exportieren Sie das Arbeitspaket in einen detaillierten Bericht über alle Arbeitspakete in der Liste." gantt: label: "Gantt-Diagramm" - caption: "Export the work packages list in a Gantt diagram view." + caption: "Exportieren Sie die Liste der Arbeitspakete in einer Gantt-Diagramm-Ansicht." include_images: label: "Bilder inkludieren" - caption: "Exclude images to reduce the size of the PDF export." + caption: "Schließen Sie Bilder aus, um die Größe des PDF-Exports zu reduzieren." gantt_zoom_levels: label: "Zoomstufe" - caption: "Select what is the zoom level for dates displayed in the chart." + caption: "Wählen Sie die Zoomstufe für die im Diagramm angezeigten Daten." options: days: "Tage" weeks: "Wochen" @@ -3117,9 +3117,9 @@ de: setting_work_package_done_ratio_field: "Arbeitsbezogen" setting_work_package_done_ratio_status: "Statusbezogen" setting_work_package_done_ratio_explanation_pre_14_4_without_percent_complete_edition_html: > - In work-based mode, % Complete is calculated from how much work is done in relation to total work. In status-based mode, each status has a % Complete value associated with it. Changing status will change % Complete. + Im arbeitsbezogenen Modus beschreibt % abgeschlossen das Verhältnis zwischen verbeibendem Aufwand und Gesamtaufwand. Im statusbasierten Modus ist jedem Status ein Wert für % abgeschlossen zugeordnet. Wenn Sie den Status ändern, ändert sich % abgeschlossen. setting_work_package_done_ratio_explanation_html: > - In work-based mode, % Complete can be freely set to any value. If you optionally enter a value for Work, Remaining work will automatically be derived. In status-based mode, each status has a % Complete value associated with it. Changing status will change % Complete. + Im arbeitsbezogenen Modus ist % abgeschlossen frei wählbar. Falls Sie einen Wert für Aufwand angeben, wird Verbleibender Aufand automatisch abgeleitet. Im statusbasierten Modus ist jedem Status ein Wert für % abgeschlossen zugeordnet. Wenn Sie den Status ändern, ändert sich % abgeschlossen. setting_work_package_properties: "Arbeitspaket-Eigenschaften" setting_work_package_startdate_is_adddate: "Neue Arbeitspakete haben \"Heute\" als Anfangsdatum" setting_work_packages_projects_export_limit: "Arbeitspakete / Exportlimit für Projekte" @@ -3501,26 +3501,26 @@ de: progress: label_note: "Hinweis:" modal: - work_based_help_text: "Each field is automatically calculated from the two others when possible." + work_based_help_text: "Jedes Feld wird, wenn möglich, automatisch aus den beiden anderen berechnet." work_based_help_text_pre_14_4_without_percent_complete_edition: "% Abgeschlossen wird automatisch aus Aufwand und Verbleibender Aufwand abgeleitet." status_based_help_text: "% Abgeschlossen wird durch den Status des Arbeitspakets festgelegt." migration_warning_text: "Im aufwandsbezogenen Modus, kann % Fertig nicht manuell eingegeben werden und ist immer an den Aufwand gebunden. Der vorhandene Wert wurde beibehalten, kann aber nicht bearbeitet werden. Bitte geben Sie zuerst den Wert für Aufwand ein." derivation_hints: done_ratio: - cleared_because_remaining_work_is_empty: "Cleared because Remaining work is empty." - cleared_because_work_is_0h: "Cleared because Work is 0h." - derived: "Derived from Work and Remaining work." + cleared_because_remaining_work_is_empty: "Gelöscht, weil Verbleibender Aufwand leer ist." + cleared_because_work_is_0h: "Gelöscht, weil Aufwand 0h beträgt." + derived: "Von Aufwand und Verbleibendem Aufwand abgeleitet." estimated_hours: - cleared_because_remaining_work_is_empty: "Cleared because Remaining work is empty." - derived: "Derived from Remaining work and % Complete." - same_as_remaining_work: "Set to same value as Remaining work." + cleared_because_remaining_work_is_empty: "Gelöscht, weil Verbleibender Aufwand leer ist." + derived: "Von Aufwand und % abgeschlossen abgeleitet." + same_as_remaining_work: "Auf denselben Wert wie Verbleibender Aufwand gesetzt." remaining_hours: - cleared_because_work_is_empty: "Cleared because Work is empty." - cleared_because_percent_complete_is_empty: "Cleared because % Complete is empty." + cleared_because_work_is_empty: "Gelöscht, weil Aufwand leer ist." + cleared_because_percent_complete_is_empty: "Gelöscht, da % abgeschlossen leer ist." decreased_like_work: "Verringert um den gleichen Betrag wie Aufwand." - derived: "Derived from Work and % Complete." + derived: "Abgeleitet von Aufwand und % abgeschlossen." increased_like_work: "Erhöht um den gleichen Betrag wie Aufwand." - same_as_work: "Set to same value as Work." + same_as_work: "Auf denselben Wert wie Aufwand gesetzt." permissions: comment: "Kommentar" comment_description: "Kann dieses Arbeitspaket anzeigen und kommentieren." diff --git a/config/locales/crowdin/js-de.yml b/config/locales/crowdin/js-de.yml index 66d38cfd34db..729b038f35e5 100644 --- a/config/locales/crowdin/js-de.yml +++ b/config/locales/crowdin/js-de.yml @@ -280,7 +280,7 @@ de: warning_progress_calculation_mode_change_from_status_to_field_pre_14_4_without_percent_complete_edition_html: >- Wenn Sie den Modus der Fortschrittsberechnung von statusbezogen auf aufwandsbezogen ändern, wird % Abgeschlossen zu einem nicht editierbaren Feld, dessen Wert von Aufwand und Verbleibender Aufwand abgeleitet wird. Vorhandene Werte für % Abgeschlossen werden beibehalten. Wenn die Werte für Aufwand und Verbleibender Aufwand nicht vorhanden waren, werden sie benötigt, um % Abgeschlossen zu ändern. warning_progress_calculation_mode_change_from_status_to_field_html: >- - Changing progress calculation mode from status-based to work-based will make the % Complete field freely editable. If you optionally enter values for Work or Remaining work, they will also be linked to % Complete. Changing Remaining work can then update % Complete. + Wenn Sie den Modus der Fortschrittsberechnung von statusbasiert auf arbeitsbasiert ändern, ist das Feld % abgeschlossen frei editierbar. Wenn Sie optional Werte für Aufwand oder Verbleibenden Aufwand eingeben, werden diese auch mit % abgeschlossen verknüpft. Eine Änderung des verbleibenden Aufwands aktualisiert dann % abgschlossen. warning_progress_calculation_mode_change_from_field_to_status_html: >- Wenn Sie den Modus der Fortschrittsberechnung von aufwandsbezogen auf statusbezogen ändern, gehen alle bestehenden Werte für % Fertigstellung verloren und werden durch Werte ersetzt, die mit dem jeweiligen Status verbunden sind. Bestehende Werte für Verbleibender Aufwand können ebenfalls neu berechnet werden, um diese Änderung widerzuspiegeln. Diese Aktion ist nicht umkehrbar. custom_actions: diff --git a/config/locales/crowdin/js-lt.yml b/config/locales/crowdin/js-lt.yml index 1a437c88b35d..bcb33257c337 100644 --- a/config/locales/crowdin/js-lt.yml +++ b/config/locales/crowdin/js-lt.yml @@ -1350,7 +1350,7 @@ lt: close: "Close modal" open_project_storage_modal: waiting_title: - timeout: "Timeout" + timeout: "Skirtojo laiko pabaiga" waiting_subtitle: network_off: "Yra tinklo problema." network_on: "Tinklas grįžo. Mes bandome." diff --git a/config/locales/crowdin/lt.yml b/config/locales/crowdin/lt.yml index 1fa5ec882b3f..483876a1246e 100644 --- a/config/locales/crowdin/lt.yml +++ b/config/locales/crowdin/lt.yml @@ -270,7 +270,7 @@ lt: favored: "Mėgstami projektai" archived: "Archyvuoti projektai" shared: "Shared project lists" - my_lists: "My project lists" + my_lists: "Mano projektų sąrašai" new: placeholder: "Naujas projektų sąrašas" delete_modal: @@ -297,7 +297,7 @@ lt: actions: label_enable_single: "Aktyvus šiame projekte, spauskite, jei norite išjungti" label_disable_single: "Neakvyus šiame projekte, spauskite, jei norite įjungti" - remove_from_project: "Remove from project" + remove_from_project: "Pašalinti iš projekto" label_enable_all: "Įjungti visus" label_disable_all: "Išjungti visus" is_required_blank_slate: @@ -493,7 +493,7 @@ lt: is_readonly: "Tik skaityti" excluded_from_totals: "Excluded from totals" themes: - dark: "Dark (Beta)" + dark: "Tamsus (Beta versija)" light: "Šviesi" light_high_contrast: "Šviesi kontrastinga" types: @@ -3650,7 +3650,7 @@ lt: publishing_denied: "You do not have permission to make project lists public." access_warning: "Users will only see the projects they have access to. Sharing project lists does not impact individual project permissions." user_details: - owner: "List owner" + owner: "Sąrašo savininkas" can_view_because_public: "Can already view because list is shared with everyone" can_manage_public_lists: "Can edit due to global permissions" public_flag: From 831be706d56c9cae17d85c5f60eec37ef1b78cae Mon Sep 17 00:00:00 2001 From: OpenProject Actions CI Date: Sun, 15 Sep 2024 03:12:41 +0000 Subject: [PATCH 13/34] update locales from crowdin [ci skip] --- config/locales/crowdin/js-ro.yml | 28 +++++++++---------- config/locales/crowdin/ro.yml | 18 ++++++------ .../backlogs/config/locales/crowdin/ro.yml | 2 +- modules/costs/config/locales/crowdin/ro.yml | 2 +- .../ldap_groups/config/locales/crowdin/ro.yml | 2 +- .../storages/config/locales/crowdin/js-ro.yml | 6 ++-- .../config/locales/crowdin/ro.yml | 2 +- 7 files changed, 30 insertions(+), 30 deletions(-) diff --git a/config/locales/crowdin/js-ro.yml b/config/locales/crowdin/js-ro.yml index 507cb4421572..c38641a049c3 100644 --- a/config/locales/crowdin/js-ro.yml +++ b/config/locales/crowdin/js-ro.yml @@ -483,7 +483,7 @@ ro: label_project: "Proiect" label_project_list: "Listă proiecte" label_project_plural: "Proiecte" - label_visibility_settings: "Setări de vizibilitate" + label_visibility_settings: "Setări vizibilitate" label_quote_comment: "Citare comentariu" label_recent: "Recente" label_reset: "Resetare" @@ -495,7 +495,7 @@ ro: label_repository_plural: "Repo-uri" label_save_as: "Salvare ca" label_search_columns: "Search a column" - label_select_project: "Selectați un proiect" + label_select_project: "Selectează un proiect" label_select_watcher: "Selectaţi un observator..." label_selected_filter_list: "Filtre selectate" label_show_attributes: "Afișați toate câmpurile" @@ -639,7 +639,7 @@ ro: no_results: at_all: "Aici vor apărea notificări noi atunci când există o activitate care vă interesează." with_current_filter: "Nu există notificări în această vizualizare în acest moment" - mark_all_read: "Marchează Tot ca Citit" + mark_all_read: "Marchează tot ca citit" mark_as_read: "Marchează ca Citit" text_update_date_by: "%{date} by" total_count_warning: "Se afișează %{newest_count} cele mai recente notificări. %{more_count} în plus nu sunt afișate." @@ -654,7 +654,7 @@ ro: link_text: "Click here to load them." settings: change_notification_settings: 'Puteți modifica setările de notificare pentru a vă asigura că nu pierdeți niciodată o actualizare importantă.' - title: "Setări de notificare" + title: "Setări notificare" notify_me: "Anunta-ma" reminders: no_notification: Nicio notificare @@ -694,7 +694,7 @@ ro: teaser_text: "Cu alertele de date, veți fi notificat cu privire la următoarele date de început sau de sfârșit, astfel încât să nu ratați sau să uitați niciodată un termen limită important." overdue: În caz de întârziere project_specific: - title: "Setări de notificare specifice proiectului" + title: "Setări notificare specifice proiectului" description: "Aceste setări specifice proiectului prevalează asupra setărilor implicite de mai sus." add: "Adăugați o setare pentru proiect" already_selected: "Acest proiect este deja selectat" @@ -1017,7 +1017,7 @@ ro: label_content: "Click aici pentru a sări peste tabelul cu pachete de lucru și a ajunge la paginare" placeholders: default: "-" - date: "Selectați data" + date: "Selectează data" query: column_names: "Coloane" group_by: "Grupare rezultate" @@ -1114,7 +1114,7 @@ ro: save: "Salvare" save_as: "Salvare ca" export: "Exportare" - visibility_settings: "Setări de vizibilitate" + visibility_settings: "Setări vizibilitate" share_calendar: "Subscribe to calendar" page_settings: "Redenumire" delete: "Șterge" @@ -1223,14 +1223,14 @@ ro: invite_principal_to_project: "Invitați %{principal} la %{project}" project: label: "Proiect" - required: "Vă rugăm să selectați un proiect" - lacking_permission: "Vă rugăm să selectați un alt proiect, deoarece nu aveți permisiuni pentru a atribui utilizatori la cel selectat în prezent." + required: "Te rog să selectezi un proiect" + lacking_permission: "Te rog să selectezi un alt proiect, deoarece nu ai permisiuni pentru a atribui utilizatori la cel selectat în prezent." lacking_permission_info: "Nu aveți permisiunea de a atribui utilizatori la proiectul în care vă aflați în prezent. Trebuie să selectați un alt proiect." next_button: "Înainte" no_results: "Nu au fost găsite proiecte" no_invite_rights: "Nu aveți voie să invitați membri în acest proiect" type: - required: "Vă rugăm să selectați tipul de invitat" + required: "Te rog să selectezi tipul de invitat" user: title: "Utilizator" description: "Permisiuni bazate pe rolul atribuit în proiectul selectat" @@ -1254,15 +1254,15 @@ ro: no_results_group: "Nu au fost găsite grupuri" next_button: "Înainte" required: - user: "Vă rugăm să selectați un utilizator" - placeholder: "Vă rugăm să selectați limba dvs" - group: "Vă rugăm să selectați limba dvs" + user: "Te rog să selectezi un utilizator" + placeholder: "Te rog să selectezi un substituent" + group: "Te rog să selectezi un grup" role: label: "Rolul în %{project}" no_roles_found: "Nu au fost găsite roluri" description: >- This is the role that the user will receive when they join your project. Rolul definește acțiunile pe care utilizatorul are voie să le întreprindă și informațiile pe care le poate vedea. Aflați mai multe despre roluri și permisiuni. - required: "Vă rugăm să selectați un rol" + required: "Te rog să selectezi un rol" next_button: "Înainte" message: label: "Mesaj invitație" diff --git a/config/locales/crowdin/ro.yml b/config/locales/crowdin/ro.yml index 22a38da9be28..78baed63974e 100644 --- a/config/locales/crowdin/ro.yml +++ b/config/locales/crowdin/ro.yml @@ -1910,7 +1910,7 @@ ro: shared: "Partajat" watched: "Observator" facets: - unread: "necitită" + unread: "Necitite" unread_title: "Afișare necitite" all: "Toate" all_title: "Afișare toate" @@ -2260,7 +2260,7 @@ ro: label_never: "Niciodată" label_new: "Nou" label_new_features: "Caracteristici noi" - label_new_statuses_allowed: "Stări noi permise" + label_new_statuses_allowed: "Setări noi permise" label_news_singular: "Noutăţi" label_news_added: "Noutăți adăugate" label_news_comment_added: "Comentariu adăugat la noutăți" @@ -2407,7 +2407,7 @@ ro: label_send_test_email: "Trimite e-mail de test" label_session: "Sesiune" label_setting_plural: "Setări" - label_system_settings: "Setări de sistem" + label_system_settings: "Setări sistem" label_show_completed_versions: "Afișare versiuni complete" label_columns: "Coloane" label_sort: "Sortare" @@ -2518,7 +2518,7 @@ ro: label_work_packages_settings: "Work packages settings" label_work_package_status: "Stare pachet de lucru" label_work_package_status_new: "Stare nouă" - label_work_package_status_plural: "Stări pachete de lucru" + label_work_package_status_plural: "Setări pachete de lucru" label_work_package_types: "Tipuri de pachete de lucru" label_work_package_tracking: "Urmărire pachete de lucru" label_work_package_view_all: "Toate pachetele de lucru" @@ -2583,7 +2583,7 @@ ro: digests: including_mention_singular: "inclusiv o mențiune" including_mention_plural: "inclusiv %{number_mentioned} menționări" - unread_notification_singular: "1 notificare necitită" + unread_notification_singular: "o notificare necitită" unread_notification_plural: "%{number_unread} notificări necitite" you_have: "Aveți" logo_alt_text: "Logo-ul" @@ -2887,7 +2887,7 @@ ro: permission_rename_wiki_pages: "Redenumire pagini wiki" permission_save_queries: "Salvați vizualizările" permission_search_project: "Caută proiect" - permission_select_custom_fields: "Selectați câmpurile personalizate" + permission_select_custom_fields: "Selectează câmpuri personalizate" permission_select_project_custom_fields: "Select project attributes" permission_select_project_modules: "Selectare module proiect" permission_share_work_packages: "Share work packages" @@ -3257,7 +3257,7 @@ ro: mode_long: inline: "Evidențiați atributul (atributele) inline" none: "Fără evidențiere" - status: "Rândul întreg după statut" + status: "Întregul rând după Stare" type: "Întregul rând pe tipuri" priority: "Întregul rând în funcție de Prioritate" icalendar: @@ -3298,7 +3298,7 @@ ro: markdown: "Markdown" plain: "Text simplu" status_active: "activ" - status_archived: "Arhivat" + status_archived: "arhivat" status_blocked: "blocked" status_invited: invitat status_locked: blocat @@ -3494,7 +3494,7 @@ ro: registered: "înregistrat" reset_failed_logins: "Resetare autentificări eşuate" status_user_and_brute_force: "%{user} şi %{brute_force}" - status_change: "Schimbare de stare" + status_change: "Schimbare stare" text_change_disabled_for_provider_login: "Numele este setat de furnizorul de logare și, prin urmare, nu poate fi modificat." text_change_disabled_for_ldap_login: "The name and email is set by LDAP and can thus not be changed." unlock: "Deblochează" diff --git a/modules/backlogs/config/locales/crowdin/ro.yml b/modules/backlogs/config/locales/crowdin/ro.yml index 7dd5d1d49753..c74578c3b05f 100644 --- a/modules/backlogs/config/locales/crowdin/ro.yml +++ b/modules/backlogs/config/locales/crowdin/ro.yml @@ -134,7 +134,7 @@ ro: label_wiki: "Wiki" permission_view_master_backlog: "Vizualizare master backlog" permission_view_taskboards: "Vizualizați tablourile de sarcini" - permission_select_done_statuses: "Selectați statusuri terminate" + permission_select_done_statuses: "Selectează stările realizate" permission_update_sprints: "Sprinturi" points_accepted: "puncte acceptate" points_committed: "puncte comise" diff --git a/modules/costs/config/locales/crowdin/ro.yml b/modules/costs/config/locales/crowdin/ro.yml index 3ab544c7d99c..ad71d7d4edf3 100644 --- a/modules/costs/config/locales/crowdin/ro.yml +++ b/modules/costs/config/locales/crowdin/ro.yml @@ -78,7 +78,7 @@ ro: caption_set_rate: "Setați rata curentă" caption_show_locked: "Afișați tipurile blocate" description_date_for_new_rate: "Data pentru noua rată" - group_by_others: "Selectați ce tipuri de grup este permis acest tip de profil. (Lăsați toate marcate pentru a permite crearea oricărui tip de grup.)" + group_by_others: "nici într-un grup" label_between: "între" label_cost_filter_add: "Adăugați un filtru de intrare a costurilor" label_costlog: "Costuri unitare înregistrate" diff --git a/modules/ldap_groups/config/locales/crowdin/ro.yml b/modules/ldap_groups/config/locales/crowdin/ro.yml index cac477bd99f4..2df085c35361 100644 --- a/modules/ldap_groups/config/locales/crowdin/ro.yml +++ b/modules/ldap_groups/config/locales/crowdin/ro.yml @@ -64,7 +64,7 @@ ro: plural: 'Grupuri LDAP sincronizate' singular: 'Grup LDAP sincronizat' form: - auth_source_text: 'Selectați ce conexiune LDAP trebuie utilizată.' + auth_source_text: 'Selectează ce conexiune LDAP trebuie utilizată.' sync_users_text: > Dacă activați această opțiune, utilizatorii găsiți vor fi, de asemenea, creați automat în OpenProject. Fără această opțiune, doar conturile existente în OpenProject vor fi adăugate la grupuri. dn_text: 'Introduceți DN-ul complet al grupului în LDAP' diff --git a/modules/storages/config/locales/crowdin/js-ro.yml b/modules/storages/config/locales/crowdin/js-ro.yml index afde0e1ccc4b..ad61339388e9 100644 --- a/modules/storages/config/locales/crowdin/js-ro.yml +++ b/modules/storages/config/locales/crowdin/js-ro.yml @@ -11,7 +11,7 @@ ro: login_to: "Autentificare în %{storageType}" no_connection: "Nu există %{storageType} conexiune" open_storage: "Deschide %{storageType}" - select_location: "Selectați locația" + select_location: "Selectează locația" choose_location: "Alege Locația" types: nextcloud: "Nextcloud" @@ -54,8 +54,8 @@ ro: remove_confirmation: > Sigur doriți să deconectați fișierul de la acest pachet de lucru? Deconectarea nu afectează fișierul original și doar elimină conexiunea la acest pachet de lucru. remove_short: "Ștergeți linkul" - select: "Selectați fișierele" - select_all: "Selectați tot" + select: "Selectează fișiere" + select_all: "Selectează tot" selection: zero: "Selectaţi fişierele pentru a conecta" one: "Link 1 fișier" diff --git a/modules/two_factor_authentication/config/locales/crowdin/ro.yml b/modules/two_factor_authentication/config/locales/crowdin/ro.yml index 717e80c0e557..3a3b11bd3c82 100644 --- a/modules/two_factor_authentication/config/locales/crowdin/ro.yml +++ b/modules/two_factor_authentication/config/locales/crowdin/ro.yml @@ -8,7 +8,7 @@ ro: attributes: two_factor_authentication/device: identifier: "Identificator" - default: "URL a paginii dorinței (lăsați gol pentru a utiliza setările implicite)" + default: "Utilizează ca implicit" two_factor_authentication/device/sms: phone_number: "Număr de telefon" errors: From a63b1b62b7585ce87f5c6e936488dc9530a092f4 Mon Sep 17 00:00:00 2001 From: OpenProject Actions CI Date: Wed, 18 Sep 2024 03:11:08 +0000 Subject: [PATCH 14/34] update locales from crowdin [ci skip] --- modules/backlogs/config/locales/crowdin/th.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/backlogs/config/locales/crowdin/th.yml b/modules/backlogs/config/locales/crowdin/th.yml index b8902a53355c..17dc6b64aaf3 100644 --- a/modules/backlogs/config/locales/crowdin/th.yml +++ b/modules/backlogs/config/locales/crowdin/th.yml @@ -27,14 +27,14 @@ th: attributes: work_package: position: "ตำแหน่ง" - story_points: "Story Points" + story_points: "" backlogs_work_package_type: "Backlog type" errors: models: work_package: attributes: blocks_ids: - can_only_contain_work_packages_of_current_sprint: "can only contain IDs of work packages in the current sprint." + can_only_contain_work_packages_of_current_sprint: "" must_block_at_least_one_work_package: "must contain the ID of at least one ticket." version_id: task_version_must_be_the_same_as_story_version: "must be the same as the parent story's version." From 9d36c750ad5d35b1ca494cb096f66e9ef93c797f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Wed, 18 Sep 2024 13:41:36 +0200 Subject: [PATCH 15/34] Restore ldap-only warning for mail --- app/views/my/account.html.erb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/views/my/account.html.erb b/app/views/my/account.html.erb index 316e5c7db6f6..3b67ce5144bd 100644 --- a/app/views/my/account.html.erb +++ b/app/views/my/account.html.erb @@ -74,9 +74,7 @@ See COPYRIGHT and LICENSE files for more details.
<%= f.text_field :mail, required: true, container_class: '-middle', disabled: login_via_ldap %> - <% if login_via_provider %> - <%= t('user.text_change_disabled_for_provider_login') %> - <% elsif login_via_ldap %> + <% if login_via_ldap %> <%= t('user.text_change_disabled_for_ldap_login') %> <% end %>
From 9a98107cc9bb88dbdfa42c22be50df2cb0933bfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Thu, 19 Sep 2024 09:58:56 +0200 Subject: [PATCH 16/34] Bump puma to 6.4.3 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 3d2bb1a6c360..c6683433d8dd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -869,7 +869,7 @@ GEM eventmachine_httpserver http_parser.rb (~> 0.6.0) multi_json - puma (6.4.2) + puma (6.4.3) nio4r (~> 2.0) puma-plugin-statsd (2.6.0) puma (>= 5.0, < 7) From e8349570ce2aa8d3aa871ce3cd8f6eadc89f7e0d Mon Sep 17 00:00:00 2001 From: Markus Kahl Date: Thu, 12 Sep 2024 15:40:05 +0100 Subject: [PATCH 17/34] fix typo in finish direct upload job --- app/workers/attachments/finish_direct_upload_job.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/workers/attachments/finish_direct_upload_job.rb b/app/workers/attachments/finish_direct_upload_job.rb index dcf878310109..18865d4cc3df 100644 --- a/app/workers/attachments/finish_direct_upload_job.rb +++ b/app/workers/attachments/finish_direct_upload_job.rb @@ -79,7 +79,7 @@ def validate_attachment(attachment, whitelist) contract = create_contract attachment, whitelist unless contract.valid? - errors = contracterrors.full_messages.join(", ") + errors = contract.errors.full_messages.join(", ") raise "Failed to validate attachment #{attachment.id}: #{errors}" end end From e56fa03e9c63ca8d9a8fd455e473b15a41be15b5 Mon Sep 17 00:00:00 2001 From: OpenProject Actions CI Date: Sun, 22 Sep 2024 03:13:12 +0000 Subject: [PATCH 18/34] update locales from crowdin [ci skip] --- config/locales/crowdin/js-ro.yml | 6 ++--- config/locales/crowdin/ro.seeders.yml | 2 +- .../backlogs/config/locales/crowdin/js-ro.yml | 2 +- .../backlogs/config/locales/crowdin/ro.yml | 10 ++++---- modules/costs/config/locales/crowdin/ro.yml | 24 +++++++++---------- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/config/locales/crowdin/js-ro.yml b/config/locales/crowdin/js-ro.yml index c38641a049c3..446298d02e23 100644 --- a/config/locales/crowdin/js-ro.yml +++ b/config/locales/crowdin/js-ro.yml @@ -112,7 +112,7 @@ ro: inline: "Evidențiați în linie:" entire_card_by: "Întreaga carte de" remove_from_list: "Alegeți intervalul din listă" - caption_rate_history: "Istoricul ratei" + caption_rate_history: "Istoric cotă" clipboard: browser_error: "Your browser doesn't support copying to clipboard. Please copy it manually: %{content}" copied_successful: "Copiat cu succes în clipboard!" @@ -583,7 +583,7 @@ ro: sprints: "În dreapta aveți lista de rezultate și erorile restante, în stânga aveți sprintele respective. Aici poți crea epicuri, povestiri pentru utilizatori și erori, prioritizează prin drag & drop și adaugă-le la un sprint." task_board_arrow: "Pentru a vedea panoul de sarcini, deschideți meniul Sprint..." task_board_select: "... și selectați intrarea Task board." - task_board: "Grupul de lucru vizualizează progresul pentru această sprint. Dă click pe pictograma plus (+) de lângă o povestire de utilizator pentru a adăuga sarcini noi sau impedimente.
Starea poate fi actualizată de drag și drop." + task_board: "Grupul de lucru vizualizează progresul pentru această iterație. Dă click pe pictograma plus (+) de lângă o cerință de utilizator pentru a adăuga sarcini noi sau impedimente.
Starea poate fi actualizată cu glisare și plasare." boards: overview: "Selectează secțiunile pentru a schimba vizualizarea și administrarea proiectului tău folosind vizualizarea secțiunilor agile." lists_kanban: "Aici puteţi crea mai multe liste (coloane) în cadrul secţiunii. Această funcţie vă permite să creaţi o tabelă Kanban, de exemplu." @@ -639,7 +639,7 @@ ro: no_results: at_all: "Aici vor apărea notificări noi atunci când există o activitate care vă interesează." with_current_filter: "Nu există notificări în această vizualizare în acest moment" - mark_all_read: "Marchează tot ca citit" + mark_all_read: "Marchează toate ca și citite" mark_as_read: "Marchează ca Citit" text_update_date_by: "%{date} by" total_count_warning: "Se afișează %{newest_count} cele mai recente notificări. %{more_count} în plus nu sunt afișate." diff --git a/config/locales/crowdin/ro.seeders.yml b/config/locales/crowdin/ro.seeders.yml index d30a1063be4c..7e67db5199c5 100644 --- a/config/locales/crowdin/ro.seeders.yml +++ b/config/locales/crowdin/ro.seeders.yml @@ -468,7 +468,7 @@ ro: item_4: name: Epic item_5: - name: Scenariu de utilizare + name: Cerință utilizator item_6: name: Defect welcome: diff --git a/modules/backlogs/config/locales/crowdin/js-ro.yml b/modules/backlogs/config/locales/crowdin/js-ro.yml index 973c029778f8..ec3398de1ef4 100644 --- a/modules/backlogs/config/locales/crowdin/js-ro.yml +++ b/modules/backlogs/config/locales/crowdin/js-ro.yml @@ -23,4 +23,4 @@ ro: js: work_packages: properties: - storyPoints: "Puncte" + storyPoints: "Puncte cerință" diff --git a/modules/backlogs/config/locales/crowdin/ro.yml b/modules/backlogs/config/locales/crowdin/ro.yml index c74578c3b05f..974ccf5b79e6 100644 --- a/modules/backlogs/config/locales/crowdin/ro.yml +++ b/modules/backlogs/config/locales/crowdin/ro.yml @@ -37,7 +37,7 @@ ro: can_only_contain_work_packages_of_current_sprint: "poate conține numai ID-uri ale pachetelor de lucru din sprintul curent." must_block_at_least_one_work_package: "trebuie să conțină ID-ul a cel puțin un bilet." version_id: - task_version_must_be_the_same_as_story_version: "trebuie să fie aceeași cu versiunea povestirii-mamă." + task_version_must_be_the_same_as_story_version: "trebuie să fie aceeași cu versiunea cerinței părinte." sprint: cannot_end_before_it_starts: "Sprint nu se poate termina înainte de a începe." backlogs: @@ -68,7 +68,7 @@ ro: remaining_hours_ideal: "Munca rămasă (ideal)" show_burndown_chart: "Size Chart" story: "Articol" - story_points: "Puncte" + story_points: "Puncte cerință" story_points_ideal: "Puncte" task: "Sarcină" task_color: "Sarcină" @@ -86,7 +86,7 @@ ro: backlogs_sprint_unestimated: "Sprinturi închise sau active cu povești neestimate" backlogs_sprint_unsized: "Proiectul are povești pe sprinturi active sau recent închise care nu au fost dimensionate" backlogs_sprints: "Sprinturi" - backlogs_story: "Articol" + backlogs_story: "Cerință" backlogs_story_type: "Tipuri de povești" backlogs_task: "Sarcină" backlogs_task_type: "Sarcină" @@ -144,7 +144,7 @@ ro: project_module_backlogs: "Restanțe" rb_label_copy_tasks: "Copierea pachetelor de lucru" rb_label_copy_tasks_all: "Toate" - rb_label_copy_tasks_none: "Nimic" + rb_label_copy_tasks_none: "Niciuna" rb_label_copy_tasks_open: "Deschis" rb_label_link_to_original: "Includeți un link către povestea originală" remaining_hours: "muncă rămasă" @@ -152,7 +152,7 @@ ro: required_burn_rate_points: "rata de ardere necesară (puncte)" todo_work_package_description: "%{summary}: %{url}\n%{description}" todo_work_package_summary: "%{type}: %{summary}" - version_settings_display_label: "Coloană în backlog" + version_settings_display_label: "Coloană în restanță" version_settings_display_option_left: "stanga" version_settings_display_option_none: "niciuna" version_settings_display_option_right: "dreapta" diff --git a/modules/costs/config/locales/crowdin/ro.yml b/modules/costs/config/locales/crowdin/ro.yml index ad71d7d4edf3..5dd3e9b46714 100644 --- a/modules/costs/config/locales/crowdin/ro.yml +++ b/modules/costs/config/locales/crowdin/ro.yml @@ -41,7 +41,7 @@ ro: spent_costs: "Costuri" spent_units: "Unități consumate" rate: - rate: "Impozit" + rate: "Tarif" user: default_rates: "Tarife" models: @@ -49,7 +49,7 @@ ro: one: "Tipul de cost" few: "Tipuri de costuri" other: "Tipuri de costuri" - rate: "Impozit" + rate: "Evaluează" errors: models: work_package: @@ -73,11 +73,11 @@ ro: caption_materials: "Unități" caption_rate_history: "Istoricul ratei" caption_rate_history_for: "Istoric al ratei pentru %{user}" - caption_rate_history_for_project: "Istoricul ratei pentru %{user} în proiectul %{project}" - caption_save_rate: "Salvează rata" - caption_set_rate: "Setați rata curentă" + caption_rate_history_for_project: "Istoricul cotei pentru %{user} în proiectul %{project}" + caption_save_rate: "Salvează tarif" + caption_set_rate: "Setează tarif curent" caption_show_locked: "Afișați tipurile blocate" - description_date_for_new_rate: "Data pentru noua rată" + description_date_for_new_rate: "Data pentru noul tarif" group_by_others: "nici într-un grup" label_between: "între" label_cost_filter_add: "Adăugați un filtru de intrare a costurilor" @@ -88,7 +88,7 @@ ro: label_costs_per_page: "Costuri pe pagină" label_currency: "Moneda" label_currency_format: "Formatul monedei" - label_current_default_rate: "Rata actuală de neplată" + label_current_default_rate: "Tarif implicit actual" label_date_on: "pe" label_deleted_cost_types: "Tipuri de costuri șterse" label_locked_cost_types: "Tipuri de costuri blocate" @@ -109,7 +109,7 @@ ro: label_no: "Nu" label_option_plural: "Opțiuni" label_overall_costs: "Costuri totale" - label_rate: "Impozit" + label_rate: "Evaluează" label_rate_plural: "Tarife" label_status_finished: "Finalizat" label_units: "Unități de cost" @@ -125,13 +125,13 @@ ro: permission_edit_own_cost_entries: "Editați propriile costuri unitare contabilizate" permission_edit_hourly_rates: "Editați tarifele orare" permission_edit_own_hourly_rate: "Editați propriile tarife orare" - permission_edit_rates: "Editarea ratelor" + permission_edit_rates: "Editează tarife" permission_log_costs: "Costurile unitare ale cărților" permission_log_own_costs: "Costurile unitare de contabilizare pentru sine" permission_view_cost_entries: "Vizualizați costurile rezervate" - permission_view_cost_rates: "Vizualizați tarifele de cost" - permission_view_hourly_rates: "Toate pachetele de lucru" - permission_view_own_cost_entries: "Vizualizați propriile costuri înregistrate" + permission_view_cost_rates: "Vizualizează tarifele" + permission_view_hourly_rates: "Vezi toate tarifele orare" + permission_view_own_cost_entries: "Vizualizează propriile costuri înregistrate" permission_view_own_hourly_rate: "Vezi propriul tarif orar" permission_view_own_time_entries: "Vizualizați propriul timp petrecut" project_module_costs: "Timp și costuri" From f7d7a191f531e7370157dcb40be1817ad87c146f Mon Sep 17 00:00:00 2001 From: Niels Lindenthal Date: Sun, 22 Sep 2024 06:41:00 +0200 Subject: [PATCH 19/34] adding information about data flows between GitLab and GitHub with OpenProject --- .../processing-of-personal-data/README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/security-and-privacy/processing-of-personal-data/README.md b/docs/security-and-privacy/processing-of-personal-data/README.md index c3ed7cbcd19b..0b35434299d5 100644 --- a/docs/security-and-privacy/processing-of-personal-data/README.md +++ b/docs/security-and-privacy/processing-of-personal-data/README.md @@ -7,7 +7,7 @@ keywords: GDPR, data flow, processing personal data, data privacy information --- # Processing of personal data -Status of this document: 2024-01-10 +Status of this document: 2024-09-22 ## Purpose of this document @@ -116,6 +116,16 @@ Depending on the individual use and permissions of the user the following person - Change history - Person mentioned in a file (incl. file attributes) +#### GitHub pull requests (cg-01) + +* Assignment of a person to a pull request in GitHub (author, reviewer, participant) +* Change history + +#### GitLab merge requests and issues (cg-02) + +* Assignment of a person to a merge request or issue in GitLab (author, reviewer, participant) +* Change history + #### Meetings (cm-01) - Assignment of a person (author, invitee, participant) to a meeting @@ -591,6 +601,7 @@ flowchart LR #### Processed data +* cg-01 * cw-02 #### Security measure @@ -638,6 +649,7 @@ flowchart LR #### Processed data +* cg-02 * cw-02 #### Security measure From 1f4d3a34620f4c322ed3788c09c7c9b57c8c033c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Sun, 22 Sep 2024 21:00:23 +0200 Subject: [PATCH 20/34] Fix replacing references of presenter_id --- .../principals/replace_references_service.rb | 11 ++- ...eferences_service_call_integration_spec.rb | 45 +++++----- .../principals/replace_references_context.rb | 86 +++++++++++++++++++ ...eferences_service_call_integration_spec.rb | 4 +- 4 files changed, 123 insertions(+), 23 deletions(-) create mode 100644 spec/services/principals/replace_references_context.rb diff --git a/app/services/principals/replace_references_service.rb b/app/services/principals/replace_references_service.rb index d74dcd0b1dc9..e1c0810a49c1 100644 --- a/app/services/principals/replace_references_service.rb +++ b/app/services/principals/replace_references_service.rb @@ -49,6 +49,7 @@ def rewrite_active_models(from, to) rewrite_actor(from, to) rewrite_owner(from, to) rewrite_logged_by(from, to) + rewrite_presenter(from, to) end def rewrite_custom_value(from, to) @@ -135,12 +136,20 @@ def rewrite_logged_by(from, to) end end + def rewrite_presenter(from, to) + [ + MeetingAgendaItem + ].each do |klass| + rewrite(klass, :presenter_id, from, to) + end + end + def journal_classes [Journal] + Journal::BaseJournal.subclasses end def foreign_keys - %w[author_id user_id assigned_to_id responsible_id logged_by_id] + %w[author_id user_id assigned_to_id responsible_id logged_by_id presenter_id] end def rewrite(klass, attribute, from, to) diff --git a/modules/meeting/spec/services/principals/replace_references_service_call_integration_spec.rb b/modules/meeting/spec/services/principals/replace_references_service_call_integration_spec.rb index 1a46851cc7d0..aa6c6ff398d6 100644 --- a/modules/meeting/spec/services/principals/replace_references_service_call_integration_spec.rb +++ b/modules/meeting/spec/services/principals/replace_references_service_call_integration_spec.rb @@ -30,38 +30,43 @@ require "spec_helper" require_module_spec_helper +require Rails.root.join('spec/services/principals/replace_references_context') RSpec.describe Principals::ReplaceReferencesService, "#call", type: :model do + subject(:service_call) { instance.call(from: principal, to: to_principal) } + + shared_let(:other_user) { create(:user) } shared_let(:principal) { create(:user) } shared_let(:to_principal) { create(:user) } - subject(:service_call) { instance.call(from: principal, to: to_principal) } - let(:instance) do described_class.new end - shared_examples "replaces the creator" do - before do - model - end - - it "is successful" do - expect(service_call) - .to be_success + context "with MeetingAgendaItem" do + it_behaves_like "rewritten record", + :meeting_agenda_item, + :author_id do + let(:attributes) do + { + author_id: principal.id, + created_at: "NOW()", + updated_at: "NOW()" + } + end end - it "replaces principal with to_principal" do - service_call - model.reload + it_behaves_like "rewritten record", + :meeting_agenda_item, + :presenter_id do + let(:attributes) do + { + presenter_id: principal.id, + created_at: "NOW()", + updated_at: "NOW()" + } - expect(model.author).to eql to_principal - end - end - - context "with MeetingAgendaItem" do - it_behaves_like "replaces the creator" do - let(:model) { create(:meeting_agenda_item, author: principal) } + end end end end diff --git a/spec/services/principals/replace_references_context.rb b/spec/services/principals/replace_references_context.rb new file mode 100644 index 000000000000..8c8063b26754 --- /dev/null +++ b/spec/services/principals/replace_references_context.rb @@ -0,0 +1,86 @@ +#-- 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. +#++ + +RSpec.shared_examples_for "rewritten record" do |factory, attribute, format = Integer| + let!(:model) do + klass = FactoryBot.factories.find(factory).build_class + all_attributes = other_attributes.merge(attribute => principal_id) + + inserted = ActiveRecord::Base.connection.select_one <<~SQL.squish + INSERT INTO #{klass.table_name} + (#{all_attributes.keys.join(', ')}) + VALUES + (#{all_attributes.values.join(', ')}) + RETURNING id + SQL + + klass.find(inserted["id"]) + end + + let(:other_attributes) do + defined?(attributes) ? attributes : {} + end + + def expected(user, format) + if format == String + user.id.to_s + else + user.id + end + end + + context "for #{factory}" do + context "with the replaced user" do + let(:principal_id) { principal.id } + + before do + service_call + model.reload + end + + it "replaces #{attribute}" do + expect(model.send(attribute)) + .to eql expected(to_principal, format) + end + end + + context "with a different user" do + let(:principal_id) { other_user.id } + + before do + service_call + model.reload + end + + it "keeps #{attribute}" do + expect(model.send(attribute)) + .to eql expected(other_user, format) + end + end + end +end diff --git a/spec/services/principals/replace_references_service_call_integration_spec.rb b/spec/services/principals/replace_references_service_call_integration_spec.rb index eed56ed882dc..e10e39371e80 100644 --- a/spec/services/principals/replace_references_service_call_integration_spec.rb +++ b/spec/services/principals/replace_references_service_call_integration_spec.rb @@ -27,6 +27,7 @@ #++ require "spec_helper" +require_relative "replace_references_context" RSpec.describe Principals::ReplaceReferencesService, "#call", type: :model do subject(:service_call) { instance.call(from: principal, to: to_principal) } @@ -330,8 +331,7 @@ def expected(user, format) it_behaves_like "rewritten record", :journal_wiki_page_journal, - :author_id do - end + :author_id end context "with WorkPackage" do From 26a5140b4a28acae03439f3454ba62a2d96c9ae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Sun, 22 Sep 2024 21:05:51 +0200 Subject: [PATCH 21/34] Bunmp saml to 1.10.5 --- Gemfile.lock | 6 +++--- modules/auth_saml/openproject-auth_saml.gemspec | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index c6683433d8dd..52fe7ca18b01 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -68,7 +68,7 @@ PATH remote: modules/auth_saml specs: openproject-auth_saml (1.0.0) - omniauth-saml (~> 1.10.1) + omniauth-saml (~> 1.10.5) PATH remote: modules/avatars @@ -780,9 +780,9 @@ GEM bigdecimal (>= 3.0) ostruct (>= 0.2) okcomputer (1.18.5) - omniauth-saml (1.10.3) + omniauth-saml (1.10.5) omniauth (~> 1.3, >= 1.3.2) - ruby-saml (~> 1.9) + ruby-saml (~> 1.17) op-clamav-client (3.4.2) open4 (1.3.4) openid_connect (2.2.1) diff --git a/modules/auth_saml/openproject-auth_saml.gemspec b/modules/auth_saml/openproject-auth_saml.gemspec index 00f0550855e7..7aa3b2f6c426 100644 --- a/modules/auth_saml/openproject-auth_saml.gemspec +++ b/modules/auth_saml/openproject-auth_saml.gemspec @@ -10,6 +10,6 @@ Gem::Specification.new do |s| s.files = Dir["{app,lib}/**/*"] + %w(README.md) - s.add_dependency "omniauth-saml", "~> 1.10.1" + s.add_dependency "omniauth-saml", "~> 1.10.5" s.metadata["rubygems_mfa_required"] = "true" end From b8cda370887c61676ca61bc3257b60e8c5dff592 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Sun, 22 Sep 2024 22:28:34 +0200 Subject: [PATCH 22/34] Disable turbo on project settings --- app/components/projects/row_component.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/components/projects/row_component.rb b/app/components/projects/row_component.rb index d775a4669c73..961a9583d518 100644 --- a/app/components/projects/row_component.rb +++ b/app/components/projects/row_component.rb @@ -293,7 +293,8 @@ def more_menu_settings_item scheme: :default, icon: :gear, label: I18n.t(:label_project_settings), - href: project_settings_general_path(project) + href: project_settings_general_path(project), + data: { turbo: false } } end end From a37b36dc1b743a8cdc5e4ad0fcaea74d143d2ee2 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Mon, 23 Sep 2024 11:37:31 +0200 Subject: [PATCH 23/34] [#57928] make users removable from global role --- app/contracts/members/delete_base_contract.rb | 41 +++++++++++++++++++ app/contracts/members/delete_contract.rb | 10 +---- .../members/global_delete_contract.rb | 33 +++++++++++++++ app/services/members/delete_service.rb | 9 ++++ spec/features/users/user_memberships_spec.rb | 18 ++++++++ .../pages/admin/individual_principals/edit.rb | 19 +++++++++ 6 files changed, 121 insertions(+), 9 deletions(-) create mode 100644 app/contracts/members/delete_base_contract.rb create mode 100644 app/contracts/members/global_delete_contract.rb diff --git a/app/contracts/members/delete_base_contract.rb b/app/contracts/members/delete_base_contract.rb new file mode 100644 index 000000000000..b0041998d9ec --- /dev/null +++ b/app/contracts/members/delete_base_contract.rb @@ -0,0 +1,41 @@ +#-- 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 Members + # Abstract contract for deleting members. Should not be used directly. Look at the child classes for + # individual use cases. + class DeleteBaseContract < ::DeleteContract + validate :member_is_deletable + + protected + + def member_is_deletable + errors.add(:base, :not_deletable) unless model.some_roles_deletable? + end + end +end diff --git a/app/contracts/members/delete_contract.rb b/app/contracts/members/delete_contract.rb index f876029feaa0..a9c95a40e08e 100644 --- a/app/contracts/members/delete_contract.rb +++ b/app/contracts/members/delete_contract.rb @@ -27,15 +27,7 @@ #++ module Members - class DeleteContract < ::DeleteContract + class DeleteContract < DeleteBaseContract delete_permission :manage_members - - validate :member_is_deletable - - private - - def member_is_deletable - errors.add(:base, :not_deletable) unless model.some_roles_deletable? - end end end diff --git a/app/contracts/members/global_delete_contract.rb b/app/contracts/members/global_delete_contract.rb new file mode 100644 index 000000000000..5ff9c0ff7ef2 --- /dev/null +++ b/app/contracts/members/global_delete_contract.rb @@ -0,0 +1,33 @@ +#-- 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 Members + class GlobalDeleteContract < DeleteBaseContract + delete_permission :admin + end +end diff --git a/app/services/members/delete_service.rb b/app/services/members/delete_service.rb index 0bf8ff9ad196..b29e067a7f95 100644 --- a/app/services/members/delete_service.rb +++ b/app/services/members/delete_service.rb @@ -60,4 +60,13 @@ def cleanup_for_group(member) .new(member.principal, current_user: user, contract_class: EmptyContract) .call end + + def default_contract_class + # We have different contracts for project roles and global roles + if model.project.present? + "#{namespace}::DeleteContract".constantize + else + "#{namespace}::GlobalDeleteContract".constantize + end + end end diff --git a/spec/features/users/user_memberships_spec.rb b/spec/features/users/user_memberships_spec.rb index 7aadd630045c..f89a4950ecff 100644 --- a/spec/features/users/user_memberships_spec.rb +++ b/spec/features/users/user_memberships_spec.rb @@ -39,6 +39,24 @@ current_user { create(:admin) } it_behaves_like "principal membership management flows" + + context "when setting global permissions" do + let(:global_role) { create(:global_role) } + let!(:global_user) { create(:global_member, principal:, roles: [global_role]) } + + it "removes a global user (bug #57928)" do + # Check if user with global role is there + principal_page.visit! + principal_page.open_global_roles_tab! + principal_page.expect_global_roles(["Global Role 1"]) + + # Remove the global role from the user + principal_page.remove_global_role!("Global Role 1") + + # Verify that it is gone + principal_page.expect_global_roles([]) + end + end end it_behaves_like "global user principal membership management flows", :manage_user diff --git a/spec/support/pages/admin/individual_principals/edit.rb b/spec/support/pages/admin/individual_principals/edit.rb index d9accf52db7f..80760b9ed083 100644 --- a/spec/support/pages/admin/individual_principals/edit.rb +++ b/spec/support/pages/admin/individual_principals/edit.rb @@ -111,6 +111,25 @@ def select_project!(project_name) results_selector: "body" end + def open_global_roles_tab! + within(".PageHeader-tabNav") do + click_on "Global roles" + end + end + + def expect_global_roles(roles) + roles_in_on_page = page.find_all("#table_principal_roles tr td.role") + + expect(roles_in_on_page.map(&:text)).to eq(roles) + end + + def remove_global_role!(role) + within("#table_principal_roles") do + role_td = find("tr td.role", text: role) + role_td.ancestor("tr").find("td.buttons a").click + end + end + def activate! within ".toolbar-items" do click_button "Activate" From 2b0fc260f5bdcebb39de51c88061aa5bd32860ff Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Mon, 23 Sep 2024 14:06:01 +0200 Subject: [PATCH 24/34] [#57928] use factory given name in spec expectation --- spec/features/users/user_memberships_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/users/user_memberships_spec.rb b/spec/features/users/user_memberships_spec.rb index f89a4950ecff..828ddcc928c8 100644 --- a/spec/features/users/user_memberships_spec.rb +++ b/spec/features/users/user_memberships_spec.rb @@ -48,7 +48,7 @@ # Check if user with global role is there principal_page.visit! principal_page.open_global_roles_tab! - principal_page.expect_global_roles(["Global Role 1"]) + principal_page.expect_global_roles([global_role.name]) # Remove the global role from the user principal_page.remove_global_role!("Global Role 1") From 129df74aaf3259a2e28317a577fd6c2da2655f76 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Mon, 23 Sep 2024 14:07:29 +0200 Subject: [PATCH 25/34] [#57928] use test-selector in feature spec --- app/helpers/members_helper.rb | 6 ++++-- spec/features/users/user_memberships_spec.rb | 2 +- spec/support/pages/admin/individual_principals/edit.rb | 6 +++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/app/helpers/members_helper.rb b/app/helpers/members_helper.rb index 83adce4f65d3..a310b638b0e4 100644 --- a/app/helpers/members_helper.rb +++ b/app/helpers/members_helper.rb @@ -36,11 +36,13 @@ def global_member_role_deletion_link(member, role) if member.roles.length == 1 link_to("", principal_membership_path(member.principal, member), - { method: :delete, class: "icon icon-delete", title: t(:button_delete) }) + { method: :delete, class: "icon icon-delete", title: t(:button_delete), + data: { "test-selector" => "delete-global-role" } }) else link_to("", principal_membership_path(member.principal, member, "membership[role_ids]" => member.roles - [role]), - { method: :patch, class: "icon icon-delete", title: t(:button_delete) }) + { method: :patch, class: "icon icon-delete", title: t(:button_delete), + data: { "test-selector" => "delete-global-role" } }) end end diff --git a/spec/features/users/user_memberships_spec.rb b/spec/features/users/user_memberships_spec.rb index 828ddcc928c8..8d14f5811842 100644 --- a/spec/features/users/user_memberships_spec.rb +++ b/spec/features/users/user_memberships_spec.rb @@ -51,7 +51,7 @@ principal_page.expect_global_roles([global_role.name]) # Remove the global role from the user - principal_page.remove_global_role!("Global Role 1") + principal_page.remove_global_role!(global_role.id) # Verify that it is gone principal_page.expect_global_roles([]) diff --git a/spec/support/pages/admin/individual_principals/edit.rb b/spec/support/pages/admin/individual_principals/edit.rb index 80760b9ed083..cfd6bd594878 100644 --- a/spec/support/pages/admin/individual_principals/edit.rb +++ b/spec/support/pages/admin/individual_principals/edit.rb @@ -123,10 +123,10 @@ def expect_global_roles(roles) expect(roles_in_on_page.map(&:text)).to eq(roles) end - def remove_global_role!(role) + def remove_global_role!(role_id) within("#table_principal_roles") do - role_td = find("tr td.role", text: role) - role_td.ancestor("tr").find("td.buttons a").click + role_tr = find("#assigned_global_role_#{role_id}") + role_tr.find("a[data-test-selector='delete-global-role']").click end end From 2e4b0eb70f3040d2c7c13db47c208435f438ba9b Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Mon, 23 Sep 2024 15:15:43 +0200 Subject: [PATCH 26/34] [#57928] add delete service spec --- spec/services/members/delete_service_spec.rb | 33 ++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/spec/services/members/delete_service_spec.rb b/spec/services/members/delete_service_spec.rb index d3fedf4f552b..22f5865ead04 100644 --- a/spec/services/members/delete_service_spec.rb +++ b/spec/services/members/delete_service_spec.rb @@ -142,4 +142,37 @@ end end end + + context "when deleting global role memberships" do + let(:user) { create(:user) } + let(:global_role) { create(:global_role) } + let!(:membership) { create(:global_member, principal: user, roles: [global_role]) } + + subject { described_class.new(user: current_user, model: membership) } + + context "as an admin" do + let(:current_user) { create(:admin) } + + it "deletes them" do + expect(membership.member_roles.map(&:role_id)).to eq([global_role.id]) + + subject.call + + expect(membership.member_roles.map(&:role_id)).to be_empty + end + end + + context "as a non-admin user" do + let(:current_user) { create(:user) } + + it "does not delete them" do + expect(membership.member_roles.map(&:role_id)).to eq([global_role.id]) + + result = subject.call + expect(result).not_to be_success + + expect(membership.member_roles.map(&:role_id)).to eq([global_role.id]) + end + end + end end From 4a44e6d39999e46643b8d044bed21b7d72939dcf Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Mon, 23 Sep 2024 15:32:31 +0200 Subject: [PATCH 27/34] [#57928] add global delete contract spec --- .../members/global_delete_contract_spec.rb | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 spec/contracts/members/global_delete_contract_spec.rb diff --git a/spec/contracts/members/global_delete_contract_spec.rb b/spec/contracts/members/global_delete_contract_spec.rb new file mode 100644 index 000000000000..e154fb64cb88 --- /dev/null +++ b/spec/contracts/members/global_delete_contract_spec.rb @@ -0,0 +1,89 @@ +#-- 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" + +RSpec.describe Members::GlobalDeleteContract do + include_context "ModelContract shared context" + + let(:contract) { described_class.new(member, current_user) } + let(:member) { build_stubbed(:global_member, roles:, principal:) } + let(:roles) { [build_stubbed(:global_role)] } + let(:principal) { build_stubbed(:user) } + + context "when member is deletable" do + it_behaves_like "contract is valid for active admins and invalid for regular users" + + include_examples "contract reuses the model errors" do + let(:current_user) { build_stubbed(:user) } + end + + context "for admin" do + let(:current_user) { build_stubbed(:admin) } + + it_behaves_like "contract is valid" + end + + context "for regular users" do + let(:current_user) { build_stubbed(:user) } + + before do + mock_permissions_for(current_user) do |mock| + mock.allow_globally(&:allow_everything) + end + end + + it_behaves_like "contract is invalid" + end + end + + context "when member is not deletable" do + before do + allow(member).to receive(:some_roles_deletable?).and_return(false) + end + + context "for admin" do + let(:current_user) { build_stubbed(:admin) } + + it_behaves_like "contract is invalid" + end + + context "for regular user" do + let(:current_user) { build_stubbed(:user) } + + before do + mock_permissions_for(current_user) do |mock| + mock.allow_globally(&:allow_everything) + end + end + + it_behaves_like "contract is invalid" + end + end +end From 06935022ff8e50b61c6e91d4dc781b4508e5e171 Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Mon, 23 Sep 2024 15:32:46 +0200 Subject: [PATCH 28/34] [#57928] use #project_role? --- app/services/members/delete_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/members/delete_service.rb b/app/services/members/delete_service.rb index b29e067a7f95..23fe5c76ecab 100644 --- a/app/services/members/delete_service.rb +++ b/app/services/members/delete_service.rb @@ -63,7 +63,7 @@ def cleanup_for_group(member) def default_contract_class # We have different contracts for project roles and global roles - if model.project.present? + if model.project_role? "#{namespace}::DeleteContract".constantize else "#{namespace}::GlobalDeleteContract".constantize From 244f4911571469957a38214de744479a39942abf Mon Sep 17 00:00:00 2001 From: Christophe Bliard Date: Mon, 23 Sep 2024 15:40:22 +0200 Subject: [PATCH 29/34] Make rubocop happier --- .../replace_references_service_call_integration_spec.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/meeting/spec/services/principals/replace_references_service_call_integration_spec.rb b/modules/meeting/spec/services/principals/replace_references_service_call_integration_spec.rb index aa6c6ff398d6..4a365f702503 100644 --- a/modules/meeting/spec/services/principals/replace_references_service_call_integration_spec.rb +++ b/modules/meeting/spec/services/principals/replace_references_service_call_integration_spec.rb @@ -30,7 +30,7 @@ require "spec_helper" require_module_spec_helper -require Rails.root.join('spec/services/principals/replace_references_context') +require Rails.root.join("spec/services/principals/replace_references_context") RSpec.describe Principals::ReplaceReferencesService, "#call", type: :model do subject(:service_call) { instance.call(from: principal, to: to_principal) } @@ -65,7 +65,6 @@ created_at: "NOW()", updated_at: "NOW()" } - end end end From ec9219c11b7ed1be37fd45ad2c37db6acb31e83f Mon Sep 17 00:00:00 2001 From: Tobias Dillmann Date: Mon, 23 Sep 2024 15:44:48 +0200 Subject: [PATCH 30/34] [#57928] refactor with better naming --- .../{delete_contract.rb => delete_from_project_contract.rb} | 2 +- ...{global_delete_contract.rb => delete_globally_contract.rb} | 2 +- app/services/members/delete_service.rb | 4 ++-- ..._contract_spec.rb => delete_from_project_contract_spec.rb} | 2 +- ...lete_contract_spec.rb => delete_globally_contract_spec.rb} | 2 +- spec/services/members/delete_service_spec.rb | 4 ++++ 6 files changed, 10 insertions(+), 6 deletions(-) rename app/contracts/members/{delete_contract.rb => delete_from_project_contract.rb} (95%) rename app/contracts/members/{global_delete_contract.rb => delete_globally_contract.rb} (96%) rename spec/contracts/members/{delete_contract_spec.rb => delete_from_project_contract_spec.rb} (98%) rename spec/contracts/members/{global_delete_contract_spec.rb => delete_globally_contract_spec.rb} (98%) diff --git a/app/contracts/members/delete_contract.rb b/app/contracts/members/delete_from_project_contract.rb similarity index 95% rename from app/contracts/members/delete_contract.rb rename to app/contracts/members/delete_from_project_contract.rb index a9c95a40e08e..109a644e3ee0 100644 --- a/app/contracts/members/delete_contract.rb +++ b/app/contracts/members/delete_from_project_contract.rb @@ -27,7 +27,7 @@ #++ module Members - class DeleteContract < DeleteBaseContract + class DeleteFromProjectContract < DeleteBaseContract delete_permission :manage_members end end diff --git a/app/contracts/members/global_delete_contract.rb b/app/contracts/members/delete_globally_contract.rb similarity index 96% rename from app/contracts/members/global_delete_contract.rb rename to app/contracts/members/delete_globally_contract.rb index 5ff9c0ff7ef2..3b1f2c2746f4 100644 --- a/app/contracts/members/global_delete_contract.rb +++ b/app/contracts/members/delete_globally_contract.rb @@ -27,7 +27,7 @@ #++ module Members - class GlobalDeleteContract < DeleteBaseContract + class DeleteGloballyContract < DeleteBaseContract delete_permission :admin end end diff --git a/app/services/members/delete_service.rb b/app/services/members/delete_service.rb index 23fe5c76ecab..79a1b2dbc441 100644 --- a/app/services/members/delete_service.rb +++ b/app/services/members/delete_service.rb @@ -64,9 +64,9 @@ def cleanup_for_group(member) def default_contract_class # We have different contracts for project roles and global roles if model.project_role? - "#{namespace}::DeleteContract".constantize + "#{namespace}::DeleteFromProjectContract".constantize else - "#{namespace}::GlobalDeleteContract".constantize + "#{namespace}::DeleteGloballyContract".constantize end end end diff --git a/spec/contracts/members/delete_contract_spec.rb b/spec/contracts/members/delete_from_project_contract_spec.rb similarity index 98% rename from spec/contracts/members/delete_contract_spec.rb rename to spec/contracts/members/delete_from_project_contract_spec.rb index a3bf312e60e8..9c3d7846504d 100644 --- a/spec/contracts/members/delete_contract_spec.rb +++ b/spec/contracts/members/delete_from_project_contract_spec.rb @@ -29,7 +29,7 @@ require "spec_helper" require "contracts/shared/model_contract_shared_context" -RSpec.describe Members::DeleteContract do +RSpec.describe Members::DeleteFromProjectContract do include_context "ModelContract shared context" let(:contract) { described_class.new(member, current_user) } diff --git a/spec/contracts/members/global_delete_contract_spec.rb b/spec/contracts/members/delete_globally_contract_spec.rb similarity index 98% rename from spec/contracts/members/global_delete_contract_spec.rb rename to spec/contracts/members/delete_globally_contract_spec.rb index e154fb64cb88..c260613ce37a 100644 --- a/spec/contracts/members/global_delete_contract_spec.rb +++ b/spec/contracts/members/delete_globally_contract_spec.rb @@ -29,7 +29,7 @@ require "spec_helper" require "contracts/shared/model_contract_shared_context" -RSpec.describe Members::GlobalDeleteContract do +RSpec.describe Members::DeleteGloballyContract do include_context "ModelContract shared context" let(:contract) { described_class.new(member, current_user) } diff --git a/spec/services/members/delete_service_spec.rb b/spec/services/members/delete_service_spec.rb index 22f5865ead04..a89de4d1ff60 100644 --- a/spec/services/members/delete_service_spec.rb +++ b/spec/services/members/delete_service_spec.rb @@ -31,6 +31,10 @@ RSpec.describe Members::DeleteService, type: :model do it_behaves_like "BaseServices delete service" do + let(:contract_class) do + "#{namespace}::DeleteFromProjectContract".constantize + end + let(:principal) { user } before do model_instance.principal = principal From 1c3d86814269a93f67ab338c537ba3b90a2f2600 Mon Sep 17 00:00:00 2001 From: Christophe Bliard Date: Mon, 23 Sep 2024 17:44:48 +0200 Subject: [PATCH 31/34] Remove extracted shared examples Extracted to `spec/services/principals/replace_references_context.rb` in a previous commit. --- ...eferences_service_call_integration_spec.rb | 59 ------------------- 1 file changed, 59 deletions(-) diff --git a/spec/services/principals/replace_references_service_call_integration_spec.rb b/spec/services/principals/replace_references_service_call_integration_spec.rb index e10e39371e80..ecc39f569aa9 100644 --- a/spec/services/principals/replace_references_service_call_integration_spec.rb +++ b/spec/services/principals/replace_references_service_call_integration_spec.rb @@ -83,65 +83,6 @@ end end - shared_examples_for "rewritten record" do |factory, attribute, format = Integer| - let!(:model) do - klass = FactoryBot.factories.find(factory).build_class - all_attributes = other_attributes.merge(attribute => principal_id) - - inserted = ActiveRecord::Base.connection.select_one <<~SQL.squish - INSERT INTO #{klass.table_name} - (#{all_attributes.keys.join(', ')}) - VALUES - (#{all_attributes.values.join(', ')}) - RETURNING id - SQL - - klass.find(inserted["id"]) - end - - let(:other_attributes) do - defined?(attributes) ? attributes : {} - end - - def expected(user, format) - if format == String - user.id.to_s - else - user.id - end - end - - context "for #{factory}" do - context "with the replaced user" do - let(:principal_id) { principal.id } - - before do - service_call - model.reload - end - - it "replaces #{attribute}" do - expect(model.send(attribute)) - .to eql expected(to_principal, format) - end - end - - context "with a different user" do - let(:principal_id) { other_user.id } - - before do - service_call - model.reload - end - - it "keeps #{attribute}" do - expect(model.send(attribute)) - .to eql expected(other_user, format) - end - end - end - end - context "with Attachment" do it_behaves_like "rewritten record", :attachment, From c703673657f3ea1cad7f86c7ce96bdaefb25d3df Mon Sep 17 00:00:00 2001 From: Christophe Bliard Date: Mon, 23 Sep 2024 18:05:45 +0200 Subject: [PATCH 32/34] refactor: Remove boiler-plate code --- ...eferences_service_call_integration_spec.rb | 26 +++------------- .../principals/replace_references_context.rb | 10 +++--- ...eferences_service_call_integration_spec.rb | 31 ++++--------------- 3 files changed, 17 insertions(+), 50 deletions(-) diff --git a/modules/meeting/spec/services/principals/replace_references_service_call_integration_spec.rb b/modules/meeting/spec/services/principals/replace_references_service_call_integration_spec.rb index 4a365f702503..8e5947900259 100644 --- a/modules/meeting/spec/services/principals/replace_references_service_call_integration_spec.rb +++ b/modules/meeting/spec/services/principals/replace_references_service_call_integration_spec.rb @@ -35,9 +35,9 @@ RSpec.describe Principals::ReplaceReferencesService, "#call", type: :model do subject(:service_call) { instance.call(from: principal, to: to_principal) } - shared_let(:other_user) { create(:user) } - shared_let(:principal) { create(:user) } - shared_let(:to_principal) { create(:user) } + shared_let(:other_user) { create(:user, firstname: "other user") } + shared_let(:principal) { create(:user, firstname: "old principal") } + shared_let(:to_principal) { create(:user, firstname: "new principal") } let(:instance) do described_class.new @@ -46,26 +46,10 @@ context "with MeetingAgendaItem" do it_behaves_like "rewritten record", :meeting_agenda_item, - :author_id do - let(:attributes) do - { - author_id: principal.id, - created_at: "NOW()", - updated_at: "NOW()" - } - end - end + :author_id it_behaves_like "rewritten record", :meeting_agenda_item, - :presenter_id do - let(:attributes) do - { - presenter_id: principal.id, - created_at: "NOW()", - updated_at: "NOW()" - } - end - end + :presenter_id end end diff --git a/spec/services/principals/replace_references_context.rb b/spec/services/principals/replace_references_context.rb index 8c8063b26754..2c9c0537e720 100644 --- a/spec/services/principals/replace_references_context.rb +++ b/spec/services/principals/replace_references_context.rb @@ -30,6 +30,8 @@ let!(:model) do klass = FactoryBot.factories.find(factory).build_class all_attributes = other_attributes.merge(attribute => principal_id) + all_attributes[:created_at] ||= "NOW()" if klass.column_names.include?("created_at") + all_attributes[:updated_at] ||= "NOW()" if klass.column_names.include?("updated_at") inserted = ActiveRecord::Base.connection.select_one <<~SQL.squish INSERT INTO #{klass.table_name} @@ -55,7 +57,7 @@ def expected(user, format) end context "for #{factory}" do - context "with the replaced user" do + context "when #{attribute} is set to the replaced user" do let(:principal_id) { principal.id } before do @@ -63,13 +65,13 @@ def expected(user, format) model.reload end - it "replaces #{attribute}" do + it "replaces its value" do expect(model.send(attribute)) .to eql expected(to_principal, format) end end - context "with a different user" do + context "when #{attribute} is set to a different user" do let(:principal_id) { other_user.id } before do @@ -77,7 +79,7 @@ def expected(user, format) model.reload end - it "keeps #{attribute}" do + it "keeps its value" do expect(model.send(attribute)) .to eql expected(other_user, format) end diff --git a/spec/services/principals/replace_references_service_call_integration_spec.rb b/spec/services/principals/replace_references_service_call_integration_spec.rb index ecc39f569aa9..5daffad06e58 100644 --- a/spec/services/principals/replace_references_service_call_integration_spec.rb +++ b/spec/services/principals/replace_references_service_call_integration_spec.rb @@ -200,9 +200,7 @@ :meeting_agenda, :author_id do let(:attributes) do - { type: "'MeetingAgenda'", - created_at: "NOW()", - updated_at: "NOW()" } + { type: "'MeetingAgenda'" } end end @@ -210,32 +208,19 @@ :meeting_minutes, :author_id do let(:attributes) do - { type: "'MeetingMinutes'", - created_at: "NOW()", - updated_at: "NOW()" } + { type: "'MeetingMinutes'" } end end it_behaves_like "rewritten record", :journal_meeting_content_journal, - :author_id do - let(:attributes) do - {} - end - end + :author_id end context "with MeetingParticipant" do it_behaves_like "rewritten record", :meeting_participant, - :user_id do - let(:attributes) do - { - created_at: "NOW()", - updated_at: "NOW()" - } - end - end + :user_id end context "with News" do @@ -466,9 +451,7 @@ { recipient_id: user.id, resource_id: 1234, - resource_type: "'WorkPackage'", - created_at: "NOW()", - updated_at: "NOW()" + resource_type: "'WorkPackage'" } end end @@ -483,9 +466,7 @@ name: "'foo'", uid: "'bar'", secret: "'bar'", - redirect_uri: "'urn:whatever'", - created_at: "NOW()", - updated_at: "NOW()" + redirect_uri: "'urn:whatever'" } end end From 6f60ef737759fa52029977efa881bde5b8027f9a Mon Sep 17 00:00:00 2001 From: Christophe Bliard Date: Mon, 23 Sep 2024 18:07:02 +0200 Subject: [PATCH 33/34] Ensure author_id of Journal::MeetingAgendaItemJournal are rewritten too --- .../meeting_agenda_item_journal_factory.rb | 31 +++++++++++++++++++ ...eferences_service_call_integration_spec.rb | 6 ++++ 2 files changed, 37 insertions(+) create mode 100644 modules/meeting/spec/factories/meeting_agenda_item_journal_factory.rb diff --git a/modules/meeting/spec/factories/meeting_agenda_item_journal_factory.rb b/modules/meeting/spec/factories/meeting_agenda_item_journal_factory.rb new file mode 100644 index 000000000000..e57694bcf6fb --- /dev/null +++ b/modules/meeting/spec/factories/meeting_agenda_item_journal_factory.rb @@ -0,0 +1,31 @@ +#-- 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. +#++ + +FactoryBot.define do + factory :journal_meeting_agenda_item_journal, class: "Journal::MeetingAgendaItemJournal" +end diff --git a/modules/meeting/spec/services/principals/replace_references_service_call_integration_spec.rb b/modules/meeting/spec/services/principals/replace_references_service_call_integration_spec.rb index 8e5947900259..a3156bf03e54 100644 --- a/modules/meeting/spec/services/principals/replace_references_service_call_integration_spec.rb +++ b/modules/meeting/spec/services/principals/replace_references_service_call_integration_spec.rb @@ -52,4 +52,10 @@ :meeting_agenda_item, :presenter_id end + + context "with Journal::MeetingAgendaItemJournal" do + it_behaves_like "rewritten record", + :journal_meeting_agenda_item_journal, + :author_id + end end From 76b2c78a49a69c68c6c7a0213ddf9210892a4e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Tue, 24 Sep 2024 12:57:32 +0200 Subject: [PATCH 34/34] Add release-notes file --- docs/release-notes/14-5-1/README.md | 45 +++++++++++++++++++++++++++++ docs/release-notes/README.md | 7 +++++ 2 files changed, 52 insertions(+) create mode 100644 docs/release-notes/14-5-1/README.md diff --git a/docs/release-notes/14-5-1/README.md b/docs/release-notes/14-5-1/README.md new file mode 100644 index 000000000000..37a09e27f62a --- /dev/null +++ b/docs/release-notes/14-5-1/README.md @@ -0,0 +1,45 @@ +--- +title: OpenProject 14.5.1 +sidebar_navigation: + title: 14.5.1 +release_version: 14.5.1 +release_date: 2024-09-24 +--- + +# OpenProject 14.5.1 + +Release date: 2024-09-24 + +We released OpenProject [OpenProject 14.5.1](https://community.openproject.org/versions/2118). +The release contains several bug fixes and we recommend updating to the newest version. +In these Release Notes, we will give an overview of important feature changes. +At the end, you will find a complete list of all changes and bug fixes. + + + +## Bug fixes and changes + + + + +- Bugfix: Internal server error opening budget \[[#57905](https://community.openproject.org/wp/57905)\] +- Bugfix: User can't create a new global role \[[#57906](https://community.openproject.org/wp/57906)\] +- Bugfix: German translations not complete \[[#57908](https://community.openproject.org/wp/57908)\] +- Bugfix: User can't be removed from global role \[[#57928](https://community.openproject.org/wp/57928)\] +- Bugfix: Incorrect read-only label for SSO logins \[[#57961](https://community.openproject.org/wp/57961)\] +- Bugfix: The Project Settings-Information page does not load \[[#57981](https://community.openproject.org/wp/57981)\] +- Bugfix: Bump ruby-saml to address CVE-2024-45409 \[[#57984](https://community.openproject.org/wp/57984)\] +- Bugfix: Cannot delete users who created meeting agenda items \[[#57986](https://community.openproject.org/wp/57986)\] + + + + +## Contributions +A very special thank you goes to our sponsors for this release. +Also a big thanks to our Community members for reporting bugs and helping us identify and provide fixes. +Special thanks for reporting and finding bugs go to Александр Татаринцев, Niklas Grönblom. + +Last but not least, we are very grateful for our very engaged translation contributors on Crowdin, who translated quite a few OpenProject strings! +Would you like to help out with translations yourself? +Then take a look at our translation guide and find out exactly how you can contribute. +It is very much appreciated! diff --git a/docs/release-notes/README.md b/docs/release-notes/README.md index 67fc2a42f316..29ae784e31ea 100644 --- a/docs/release-notes/README.md +++ b/docs/release-notes/README.md @@ -13,6 +13,13 @@ Stay up to date and get an overview of the new features included in the releases +## 14.5.1 + +Release date: 2024-09-24 + +[Release Notes](14-5-1/) + + ## 14.5.0 Release date: 2024-09-11