diff --git a/Gemfile.lock b/Gemfile.lock index d29d028652a6..a42f3d97d4f2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -44,8 +44,8 @@ GIT GIT remote: https://github.com/opf/omniauth-openid_connect-providers.git - revision: 7559f44e70203f94572a90e1b4d1d1f8279cd40f - ref: 7559f44e70203f94572a90e1b4d1d1f8279cd40f + revision: c7e2498a8b093cfc5693d4960cae2e903a5e10cd + ref: c7e2498a8b093cfc5693d4960cae2e903a5e10cd specs: omniauth-openid_connect-providers (0.2.0) omniauth-openid-connect (>= 0.2.1) diff --git a/Gemfile.modules b/Gemfile.modules index 94b8bca78ae8..1d0afff0f85c 100644 --- a/Gemfile.modules +++ b/Gemfile.modules @@ -10,7 +10,7 @@ end gem 'omniauth-openid_connect-providers', git: 'https://github.com/opf/omniauth-openid_connect-providers.git', - ref: '7559f44e70203f94572a90e1b4d1d1f8279cd40f' + ref: 'c7e2498a8b093cfc5693d4960cae2e903a5e10cd' gem 'omniauth-openid-connect', git: 'https://github.com/opf/omniauth-openid-connect.git', diff --git a/README.md b/README.md index 5af14aace6a1..0f9a689fbba0 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ will keep our community secure. If you happen to come across a security issue we you to disclose it to us privately to allow our users and community enough time to upgrade. Security issues will always take precedence over anything else in the pipeline. -For more information on how to disclose a security vulnerability, [please see this page](docs/development/security/README.md). +For more information on how to disclose a security vulnerability, [please see this page](docs/security-and-privacy/statement-on-security/README.md). ## License diff --git a/SECURITY.md b/SECURITY.md index a7850e2afd0c..abb0dc227922 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1 +1 @@ -Please find our statement on security in this document: https://www.openproject.org/docs/development/security/ +Please find our statement on security in this document: https://www.openproject.org/docs/security-and-privacy/statement-on-security/ diff --git a/app/models/user.rb b/app/models/user.rb index f94cd4a2355e..19687c3bed3c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -29,6 +29,7 @@ require 'digest/sha1' class User < Principal + VALID_NAME_REGEX = /\A[\d\p{Alpha}\p{Mark}\p{Space}\p{Emoji}'’´\-_.,@()+&*–]+\z/ CURRENT_USER_LOGIN_ALIAS = 'me'.freeze USER_FORMATS_STRUCTURE = { firstname_lastname: %i[firstname lastname], @@ -122,7 +123,10 @@ def self.blocked_condition(blocked) # Login must contain letters, numbers, underscores only validates :login, format: { with: /\A[a-z0-9_\-@.+ ]*\z/i } validates :login, length: { maximum: 256 } + validates :firstname, :lastname, length: { maximum: 256 } + validates :firstname, :lastname, format: { with: VALID_NAME_REGEX, allow_blank: true } + validates :mail, email: true, unless: Proc.new { |user| user.mail.blank? } validates :mail, length: { maximum: 256, allow_nil: true } diff --git a/config/locales/crowdin/bg.yml b/config/locales/crowdin/bg.yml index 36b6e0e510a8..7b61eef3bc1d 100644 --- a/config/locales/crowdin/bg.yml +++ b/config/locales/crowdin/bg.yml @@ -1862,7 +1862,7 @@ bg: label_nothing_display: "Нищо за показване" label_nobody: "nobody" label_not_found: 'not found' - label_none: "none" + label_none: "никой" label_none_parentheses: "(none)" label_not_contains: "doesn't contain" label_not_equals: "is not" diff --git a/config/locales/crowdin/ca.yml b/config/locales/crowdin/ca.yml index af21a9298c8f..596c5a713ae6 100644 --- a/config/locales/crowdin/ca.yml +++ b/config/locales/crowdin/ca.yml @@ -130,7 +130,7 @@ ca: Afegeix un filtre RFC4515 opcional per aplicar els resultats retornats per usuaris filtrats en el LDAP. Això, pot ser utilitzat per a restringir el set d'usuaris que OpenProject troba per autentificar i agrupar la sincronització. filter_string_concat: | - OpanProject sempre filtre segons l'atribut d'inici de sessió subministrat per l'usuari per tal d'identificar el registre. Si has subministrat un filtre aquí, serà encadenat amb un "I". Per defecte, un filtre catch-all (objectClass=*) serà utilitzat. + OpenProject sempre filtre segons l'atribut d'inici de sessió subministrat per l'usuari per tal d'identificar el registre. Si heu proporcionat un filtre aquí, serà encadenat amb un "I". Per defecte, un filtre catch-all (objectClass=*) serà utilitzat. onthefly_register: | Si actives aquesta casella, OpenProject automàticament crearà nous usuaris a partir de les seves entrades LDAP durant la seva primera autentificació a OpenProject. Deixa-la desactivada si sols voleu permetre a comptes existents a OpenProject que s'autentifiquin via LDAP! @@ -176,7 +176,7 @@ ca: label_no_color: "Sense color" label_properties: "Propietats" label_really_delete_color: > - Estàs segur que vols eliminar el següent color? Els tipus amb aquest color no s'eliminaràn. + Esteu segur que voleu suprimir el següent tipus de projecte? Els projectes amb aquest tipus no se suprimiran. custom_actions: actions: name: "Accions" @@ -1806,7 +1806,7 @@ ca: label_max_size: "Mida màxima" label_me: "jo mateix" label_member_new: "Nou membre" - label_member_all_admin: "(Tots els roles a causa de l'estat d'administrador)" + label_member_all_admin: "(Tots els rols a causa de l'estat d'administrador)" label_member_plural: "Membres" lable_membership_added: 'Membre afegit' lable_membership_updated: 'Membre actualitzat' diff --git a/config/locales/crowdin/cs.yml b/config/locales/crowdin/cs.yml index b67c88be718f..0f07c5b71506 100644 --- a/config/locales/crowdin/cs.yml +++ b/config/locales/crowdin/cs.yml @@ -455,7 +455,7 @@ cs: account: "Účet" attr_firstname: "Jméno (atribut)" attr_lastname: "Příjmení (atribut)" - attr_login: "Uživatelské jméno (atribut)" + attr_login: "Atribut uživatelského jména" attr_mail: "Email (atribut)" base_dn: "Base DN" host: "Host" @@ -981,7 +981,7 @@ cs: created_by_on_time_entry: "time logged by %{user} on %{datetime}" created_on: "vytvořeno dne %{datetime}" created_on_time_entry: "time logged on %{datetime}" - updated_by_on: "Aktualizováno uživatelem {{user}} dne {{date}}" + updated_by_on: "Aktualizováno uživatelem %{user} dne %{datetime}" updated_by_on_time_entry: "logged time updated by %{user} on %{datetime}" updated_on: "aktualizováno dne %{datetime}" updated_on_time_entry: "logged time updated on %{datetime}" @@ -1426,7 +1426,7 @@ cs: work_package_edit: 'Pracovní balíček upraven' work_package_note: 'Poznámka k pracovnímu balíčku přidána' title: - project: "Projekt {name}" + project: "Projekt %{name}" subproject: "Podprojekt: %{name}" export: your_work_packages_export: "Export pracovních balíčků" @@ -1638,7 +1638,7 @@ cs: label_available_project_versions: "Dostupné verze" label_available_project_work_package_categories: "Dostupné kategorie pracovních balíčků" label_available_project_work_package_types: "Dostupné kategorie pracovních balíčků" - label_available_projects: "Available projects" + label_available_projects: "Dostupné projekty" label_api_documentation: "API dokumentace" label_backup: "Záloha" label_between: "mezi" @@ -1936,7 +1936,7 @@ cs: label_permissions_report: "Přehled oprávnění" label_personalize_page: "Přizpůsobit tuto stránku" label_placeholder_user: "Placeholder uživatel" - label_placeholder_user_new: "Nový placeholder uživatel" + label_placeholder_user_new: "" label_placeholder_user_plural: "Placeholder uživatelé" label_planning: "Plánování" label_please_login: "Přihlaste se prosím" diff --git a/config/locales/crowdin/de.yml b/config/locales/crowdin/de.yml index 7efb32204075..ff3ccfe8a3c6 100644 --- a/config/locales/crowdin/de.yml +++ b/config/locales/crowdin/de.yml @@ -927,7 +927,7 @@ de: custom_field: "Benutzerdefiniertes Feld" 'doorkeeper/application': "OAuth-Anwendung" forum: "Forum" - global_role: "Global role" + global_role: "Globale Rolle" group: "Gruppe" member: "Mitglied" news: "Neuigkeiten" @@ -1585,13 +1585,13 @@ de: label_ldap_auth_source: "LDAP-Verbindung" label_ldap_auth_source_plural: "LDAP-Verbindungen" label_authentication: "Authentifizierung" - label_available_global_roles: "Available global roles" + label_available_global_roles: "Verfügbare globale Rollen" label_available_project_forums: "Verfügbare Foren" label_available_project_repositories: "Verfügbare Projektarchive" label_available_project_versions: "Verfügbare Versionen" label_available_project_work_package_categories: "Verfügbare Arbeitspaket-Kategorien" label_available_project_work_package_types: "Verfügbare Arbeitspaket-Typen" - label_available_projects: "Available projects" + label_available_projects: "Verfügbare Projekte" label_api_documentation: "API-Dokumentation" label_backup: "Backup" label_between: "zwischen" diff --git a/config/locales/crowdin/fr.yml b/config/locales/crowdin/fr.yml index 25c2b41a32bc..78a55b5a3f45 100644 --- a/config/locales/crowdin/fr.yml +++ b/config/locales/crowdin/fr.yml @@ -517,7 +517,7 @@ fr: true: "public" false: "privé" queries: "Requêtes" - status_code: 'État du projet' + status_code: 'Statut du projet' status_explanation: 'Description du statut du projet' status_codes: not_started: 'Non démarré' @@ -1008,7 +1008,7 @@ fr: created_at: "Créé le" custom_options: "Valeurs possibles" custom_values: "Champs personnalisés" - date: "date" + date: "Date" default_columns: "Colonnes par défaut" description: "Description" derived_due_date: "Date de fin dérivée" @@ -1665,7 +1665,7 @@ fr: label_custom_field_default_type: "Type défaut" label_custom_style: "Apparence" label_database_version: "Version de PostgreSQL" - label_date: "date" + label_date: "Date" label_date_and_time: "Date et heure" label_date_format: "Format de date" label_date_from: "De" @@ -2338,7 +2338,7 @@ fr: permission_add_work_package_notes: "Ajouter des notes" permission_add_work_packages: "Ajouter des lots de travaux" permission_add_messages: "Poster des messages" - permission_add_project: "Create projects" + permission_add_project: "Créer des projets" permission_archive_project: "Archiver le projet" permission_create_user: "Créer des utilisateurs" permission_manage_user: "Modifier les utilisateurs" @@ -2351,7 +2351,7 @@ fr: permission_comment_news: "Commenter les actualités" permission_commit_access: "Accès au dépôt en lecture/écriture (« commit »)" permission_copy_projects: "Copier des projets" - permission_create_backup: "Create backups" + permission_create_backup: "Créer des sauvegardes" permission_delete_work_package_watchers: "Supprimer des observateurs" permission_delete_work_packages: "Supprimer des lots de travaux" permission_delete_messages: "Supprimer des messages" @@ -2608,7 +2608,7 @@ fr: setting_consent_decline_mail: "Adresse mail de contact de l'accord" setting_cross_project_work_package_relations: "Autoriser les relations entre lots de travaux de projets différents" setting_first_week_of_year: "La première semaine de l'année contient" - setting_date_format: "date" + setting_date_format: "Date" setting_default_language: "Langage par défaut" setting_default_projects_modules: "Modules activés par défaut pour les nouveaux projets" setting_default_projects_public: "Les nouveaux projets sont publics par défaut" diff --git a/config/locales/crowdin/js-ar.yml b/config/locales/crowdin/js-ar.yml index 33c6c69f9e73..80025947ddff 100644 --- a/config/locales/crowdin/js-ar.yml +++ b/config/locales/crowdin/js-ar.yml @@ -1160,9 +1160,11 @@ ar: hour: one: "1 h" other: "%{count} h" + zero: "0 h" day: one: "%{count} يوم" other: "%{count} يوم" + zero: "0 days" zen_mode: button_activate: 'Activate zen mode' button_deactivate: 'Deactivate zen mode' diff --git a/config/locales/crowdin/js-cs.yml b/config/locales/crowdin/js-cs.yml index 2d7aa3d7bca4..613c0c2e589f 100644 --- a/config/locales/crowdin/js-cs.yml +++ b/config/locales/crowdin/js-cs.yml @@ -348,7 +348,7 @@ cs: new_features_html: > The release contains various new features and improvements:
ical_sharing_modal: - title: "Subscribe to calendar" + title: "Přihlásit kalendář k odběru" inital_setup_error_message: "Při načítání dat došlo k chybě." description: "You can use the URL (iCalendar) to subscribe to this calendar in an external client and view up-to-date work package information from there." warning: "Please don't share this URL with other users. Anyone with this link will be able to view work package details without an account or password." @@ -416,7 +416,7 @@ cs: label_filename: "Soubor" label_filesize: "Velikost" label_general: "Obecné" - label_global_roles: "Global roles" + label_global_roles: "Globální role" label_greater_or_equal: ">=" label_group: 'Skupina' label_group_by: "Seskupit podle" @@ -530,7 +530,7 @@ cs: label_add_attachments: "Připojit soubory" label_formattable_attachment_hint: "Připojit a propojit soubory smazáním tohoto pole nebo vložením ze schránky." label_remove_file: "Odstranit %{fileName}" - label_remove_watcher: "Odstranit pozorovatele %{name}" + label_remove_watcher: "Odstranit sledujícího %{name}" label_remove_all_files: Odstranit všechny soubory label_add_description: "Přidat popis pro %{file}" label_upload_notification: "Nahrávám soubory..." @@ -590,7 +590,7 @@ cs: no_unread: "Žádná nepřečtená oznámení" reasons: mentioned: 'zmíněn' - watched: 'pozorovatel' + watched: 'sledovatel' assigned: 'Řešitel' responsible: 'Odpovědný' created: 'Vytvořeno' @@ -606,7 +606,7 @@ cs: property_today: 'je dnes' property_is: 'is in %{difference_in_days}' property_was: 'was %{difference_in_days} ago' - property_is_deleted: 'byl smazán' + property_is_deleted: 'is deleted' upsale: title: 'Upozornění na datum' description: 'With date alerts, you will be notified of upcoming start or finish dates so that you never miss or forget an important deadline.' @@ -675,7 +675,7 @@ cs: work_package_scheduled: 'Všechny změny data' global: immediately: - title: 'Účast' + title: 'Participace' description: 'Upozornění pro všechny aktivity v pracovních balíčcích, do kterých jste zapojeni (Řešitel, odpovědný nebo sledující).' delayed: title: 'Neúčast' @@ -782,7 +782,7 @@ cs: watchers: label_loading: načítám sledující... label_error_loading: Při načítání pozorovatelů došlo k chybě - label_search_watchers: Hledat pozorovatele + label_search_watchers: Hledat sledující label_add: Přidat sledující label_discard: Zrušit výběr typeahead_placeholder: Hledání možných přihlížejících diff --git a/config/locales/crowdin/js-fr.yml b/config/locales/crowdin/js-fr.yml index b90bca0ec5cc..2017753075ca 100644 --- a/config/locales/crowdin/js-fr.yml +++ b/config/locales/crowdin/js-fr.yml @@ -677,7 +677,7 @@ fr: description: 'Notifications pour toute activité sur les lots de travaux vous concernant (assigné, responsable ou observateur).' delayed: title: 'Non participants' - description: 'Notifications additionnelles lors d''activité sur tous les projects.' + description: 'Notifications additionnelles lors d''activités sur tous les projets.' date_alerts: title: 'Alarmes' description: 'Notifications automatiques lorsque des dates importantes approchent pour les lots de travaux ouverts vous concernant (assigné, responsable ou observateur).' diff --git a/config/locales/crowdin/js-sr.yml b/config/locales/crowdin/js-sr.yml index abbfa8c30acd..b998b8a6a249 100644 --- a/config/locales/crowdin/js-sr.yml +++ b/config/locales/crowdin/js-sr.yml @@ -95,7 +95,7 @@ sr: button_save: "Save" button_settings: "Settings" button_uncheck_all: "Uncheck all" - button_update: "Ažuriranje" + button_update: "Ažuriraj" button_export-pdf: "Download PDF" button_export-atom: "Download Atom" button_create: "Create" diff --git a/config/locales/crowdin/js-zh-CN.yml b/config/locales/crowdin/js-zh-CN.yml index bcf34837822a..b880787a37a1 100644 --- a/config/locales/crowdin/js-zh-CN.yml +++ b/config/locales/crowdin/js-zh-CN.yml @@ -107,7 +107,7 @@ zh-CN: remove_from_list: '从列表中移除卡' caption_rate_history: "费率历史记录" clipboard: - browser_error: "您的浏览器不支持复制到剪贴板。请手动复制:%{content}。" + browser_error: "您的浏览器不支持复制到剪贴板,请手动复制:%{content}" copied_successful: "成功复制到剪贴板!" chart: type: '图表类型' diff --git a/config/locales/crowdin/ka.yml b/config/locales/crowdin/ka.yml index dcd0b7782114..9241dc507092 100644 --- a/config/locales/crowdin/ka.yml +++ b/config/locales/crowdin/ka.yml @@ -463,7 +463,7 @@ ka: changeset: repository: "Repository" color: - hexcode: "Hex code" + hexcode: "თექვსმეტობითი კოდი" comment: commented: "კომენტარით" #an object that this comment belongs to custom_action: @@ -834,7 +834,7 @@ ka: attributes: user_id: not_allowed_to_view: "is not allowed to view this resource." - locked: "is locked." + locked: "დაბლოკილია." wiki_page: error_conflict: "The wiki page has been updated by someone else while you were editing it." attributes: @@ -971,7 +971,7 @@ ka: updated_by_on_time_entry: "logged time updated by %{user} on %{datetime}" updated_on: "updated on %{datetime}" updated_on_time_entry: "logged time updated on %{datetime}" - parent_without_of: "Subproject" + parent_without_of: "ქვეპროექტი" parent_no_longer: "No longer subproject of" time_entry: hour: @@ -2341,7 +2341,7 @@ ka: permission_add_project: "Create projects" permission_archive_project: "Archive project" permission_create_user: "Create users" - permission_manage_user: "Edit users" + permission_manage_user: "მომხმარებლების ჩასწორება" permission_manage_placeholder_user: "Create, edit, and delete placeholder users" permission_add_subprojects: "Create subprojects" permission_add_work_package_watchers: "Add watchers" @@ -2360,7 +2360,7 @@ ka: permission_delete_timelines: "Delete timelines" permission_delete_wiki_pages: "Delete wiki pages" permission_delete_wiki_pages_attachments: "Delete attachments" - permission_edit_work_package_notes: "Edit notes" + permission_edit_work_package_notes: "შენიშვნების ჩასწორება" permission_edit_work_packages: "Edit work packages" permission_edit_messages: "Edit messages" permission_edit_own_work_package_notes: "Edit own notes" @@ -2392,7 +2392,7 @@ ka: permission_move_work_packages: "Move work packages" permission_protect_wiki_pages: "Protect wiki pages" permission_rename_wiki_pages: "Rename wiki pages" - permission_save_queries: "Save views" + permission_save_queries: "ხედების შენახვა" permission_select_custom_fields: "Select custom fields" permission_select_project_modules: "Select project modules" permission_manage_types: "Select types" @@ -2436,7 +2436,7 @@ ka: project_module_forums: "ფორუმები" project_module_work_package_tracking: "Work packages" project_module_news: "სიახლეები" - project_module_repository: "Repository" + project_module_repository: "რეპოზიტორია" project_module_wiki: "ვიკი" query: attribute_and_direction: "%{attribute} (%{direction})" diff --git a/config/locales/crowdin/nl.yml b/config/locales/crowdin/nl.yml index 77f0ad333669..d82e61759420 100644 --- a/config/locales/crowdin/nl.yml +++ b/config/locales/crowdin/nl.yml @@ -449,14 +449,14 @@ nl: ldap_auth_source: account: "Account" attr_firstname: "Firstname attribute" - attr_lastname: "Lastname attribute" - attr_login: "Username attribute" - attr_mail: "Email attribute" + attr_lastname: "Achternaam attribuut" + attr_login: "Gebruikersnaam attribuut" + attr_mail: "E-mail attribuut" base_dn: "Base DN" host: "Host" - onthefly: "Automatic user creation" - port: "Port" - tls_certificate_string: "LDAP server SSL certificate" + onthefly: "Automatische gebruiker aanmaken" + port: "Poort" + tls_certificate_string: "LDAP server SSL-certificaat" changeset: repository: "Repository" color: @@ -556,7 +556,7 @@ nl: color: "Kleur" user: admin: "Beheerder" - ldap_auth_source: "LDAP connection" + ldap_auth_source: "LDAP verbinding" current_password: "Huidig wachtwoord" force_password_change: "Afdwingen van wachtwoordwijziging bij volgende login" language: "Taal" diff --git a/config/locales/crowdin/tr.seeders.yml b/config/locales/crowdin/tr.seeders.yml index 43fe30dc197c..2b351a6ff443 100644 --- a/config/locales/crowdin/tr.seeders.yml +++ b/config/locales/crowdin/tr.seeders.yml @@ -154,7 +154,7 @@ tr: item_1: name: Milestones item_2: - name: Tasks + name: Görevler item_3: name: Takım planlayıcısı boards: @@ -379,7 +379,7 @@ tr: item_0: subject: Create wireframes for new landing page item_3: - subject: Contact form + subject: İletişim formu item_4: subject: Feature carousel children: diff --git a/docker/prod/Dockerfile b/docker/prod/Dockerfile index b2f057ca67cc..b881ee5445bd 100644 --- a/docker/prod/Dockerfile +++ b/docker/prod/Dockerfile @@ -73,6 +73,8 @@ ENV APP_USER=app ENV APP_PATH=/app ENV APP_DATA_PATH=/var/openproject/assets ENV PGVERSION="13" +ENV CURRENT_PGVERSION="13" +ENV NEXT_PGVERSION="15" ENV PGBIN="/usr/lib/postgresql/$PGVERSION/bin" ENV BUNDLE_WITHOUT="development:test" @@ -92,7 +94,7 @@ ENV OPENPROJECT_RAILS__CACHE__STORE=file_store RUN useradd -d /home/$APP_USER -m $APP_USER RUN mkdir -p $APP_PATH && chown $APP_USER:$APP_USER $APP_PATH -RUN mkdir -p $APP_DATA_PATH && chown $APP_USER:$APP_USER $APP_DATA_PATH +RUN mkdir -p $APP_DATA_PATH && chown $APP_USER:$APP_USER $APP_DATA_PATH && chmod g+rwx $APP_DATA_PATH WORKDIR $APP_PATH @@ -103,11 +105,12 @@ RUN --mount=type=cache,target=/var/cache/apt \ curl \ gnupg2 \ && curl -sSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ - && echo 'deb http://apt.postgresql.org/pub/repos/apt/ bullseye-pgdg main' $PGVERSION > /etc/apt/sources.list.d/pgdg.list \ + && echo 'deb http://apt.postgresql.org/pub/repos/apt/ bullseye-pgdg main' > /etc/apt/sources.list.d/pgdg.list \ && apt-get update -qq \ && apt-get install -yq --no-install-recommends \ libpq5 \ - postgresql-client-$PGVERSION \ + postgresql-client-$CURRENT_PGVERSION \ + postgresql-client-$NEXT_PGVERSION \ libffi7 \ unrtf tesseract-ocr poppler-utils catdoc imagemagick \ && apt-get purge -y curl gnupg2 \ @@ -123,6 +126,11 @@ COPY --chown=$APP_USER:$APP_USER --from=assets /app/public/assets /app/public/as COPY --chown=$APP_USER:$APP_USER --from=assets /app/config/frontend_assets.manifest.json /app/config/frontend_assets.manifest.json COPY --chown=$APP_USER:$APP_USER . . +# We need this so puma is allowed to create the tmp/pids folder and +# temporary upload files when running with a uid other than 1000 (app) +# but with an allowed supplemental group (1000). +RUN tmp_path=$APP_PATH/tmp; (mkdir -p $tmp_path || true) && chown $APP_USER:$APP_USER $tmp_path && chmod g+rw $tmp_path + USER $APP_USER RUN ln -s $APP_PATH/docker/prod/setup/.irbrc /home/$APP_USER/ @@ -187,10 +195,6 @@ RUN cp Gemfile.lock.bak Gemfile.lock && rm Gemfile.lock.bak RUN ./docker/prod/setup/postinstall.sh -# We need this so puma is allowed to create the tmp/pids folder and files -# even when the container is run as a user other than 1000 (app) -RUN tmp_path=$APP_PATH/tmp; (mkdir -p $tmp_path || true) && chmod og+rw $tmp_path - # Expose ports for apache and postgres EXPOSE 80 5432 diff --git a/docker/prod/setup/postinstall.sh b/docker/prod/setup/postinstall.sh index 416eb24c813e..f1d9c75fd281 100755 --- a/docker/prod/setup/postinstall.sh +++ b/docker/prod/setup/postinstall.sh @@ -3,8 +3,6 @@ set -e set -o pipefail -export PGBIN="$(pg_config --bindir)" - display_error() { echo " !--> ERROR on postinstall:" tail -n 200 /tmp/dockerize.log diff --git a/docs/development/application-architecture/README.md b/docs/development/application-architecture/README.md index e510edbfd8bf..da6a0692ecac 100644 --- a/docs/development/application-architecture/README.md +++ b/docs/development/application-architecture/README.md @@ -15,36 +15,74 @@ keywords: architecture overview, hybrid application, Ruby on Rails, Angular %%{init: {'theme':'neutral'}}%% flowchart TD - A[Client Browser] -->|"HTTP(s) requests"| B(Load Balancer / Proxy) - A1[API or Native clients] -->|"HTTP(s) requests"| B(Load Balancer / Proxy) - A2[SVN or Git clients] -->|"HTTP(s) requests"| B(Load Balancer / Proxy) - B -->|Proxy| openproject - - subgraph openproject[OpenProject] + browser[Web browser] -->|"HTTPS requests"| loadbalancer(Load balancer / proxy) + A1[Native client] -->|"HTTPS requests"| loadbalancer + A2[SVN or Git client] -->|"HTTPS requests"| loadbalancer + loadbalancer -->|Proxy| openproject + + subgraph openproject[OpenProject Core Application] + openprojectrailsapp[Rails application] C[Puma app server] D[Background worker] end - subgraph integrations[External integrations] - O[Other integrations] - N[Nextcloud] - end + subgraph integrations[External Integrations] + direction TB + idp["Identity provider (idp)"] + nex["Nextcloud (nex)"] + gih["GitHub (gih)"] + cal["Calendar (cal)"] + O["API integrations (api)"] + W["Outgoing webhooks"] +end - subgraph services[Services] - M[memcached] + subgraph services[Internal Services] + direction TB + M[Memcached] P[PostgreSQL] S[Object storage or NFS] + email["Email gateways (eml)"] end - openproject <--> services - openproject --> integrations - B <--> integrations + openproject <-->|"TCP requests"| services + openproject -->|"HTTPS requests"| integrations + loadbalancer <-->|"HTTPS requsts"| integrations + + subgraph localclients[Local Client / User device] + direction TB + browser + A1 + A2 + + +end -``` +``` +## Involved services + +| Service | Relationship to OpenProject | Communication interfaces and mechanisms | Access modes
(R - read)
(W - write) | References | +| ----------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | --------------------------------------------- | ------------------------------------------------------------ | +| Web browser | Performs requests to the application | HTTPS | RW | n/a | +| Native client | Performs requests to the application | HTTPS | RW | n/a | +| SVN client | Performs SVN requests to the application web server | HTTPS | RW | [Repository integrations](https://www.openproject.org/docs/user-guide/repository/) | +| Git client | Performs Git Smart HTTP requests to the application server | HTTPS | RW | [Repository integrations](https://www.openproject.org/docs/user-guide/repository/) | +| Load balancer / Proxy | Depending on installation mechanism, terminates TLS/SSL, accepts and proxies or load balances web requests to the different OpenProject web application servers | HTTPS / PROXY | - | [Configuration for packaged installations](https://www.openproject.org/docs/installation-and-operations/installation/packaged/#step-3-apache2-web-server-and-ssl-termination)
[Configuration for Docker/Kubernetes](https://www.openproject.org/docs/installation-and-operations/installation/docker/#disabling-https-mode) | +| Puma application server | Accepts web requests, runs the OpenProject web facing application | Web requests (HTTP/HTTPS)
Database (TCP)
Memcached (TCP)
Email gateways (SMTP)
External integration requests (HTTPS) | RW | [Database TLS setup](https://www.openproject.org/docs/installation-and-operations/configuration/#database-configuration-and-ssl)
[Cache configuration](https://www.openproject.org/docs/installation-and-operations/configuration/#cache-configuration-options)
[SMTP configuration](https://www.openproject.org/docs/installation-and-operations/configuration/outbound-emails/)
[Integrations guide](https://www.openproject.org/docs/system-admin-guide/integrations/) | +| Memached / Redis / File cache | Application-level cache (if enabled) | TCP connections | RW | [Cache configuration](https://www.openproject.org/docs/installation-and-operations/configuration/#cache-configuration-options) | +| PostgreSQL | Database management system | (Encrypted) TCP connections between web and background workers | | [Database TLS setup](https://www.openproject.org/docs/installation-and-operations/configuration/#database-configuration-and-ssl)
| +| Background worker | Handles asynchronous jobs, such as backup requests, email delivery, | Database (TCP)
Memcached (TCP)
Email gateways (SMTP)
External integration requests (HTTPS) | RW | [Database TLS setup](https://www.openproject.org/docs/installation-and-operations/configuration/#database-configuration-and-ssl)
[Cache configuration](https://www.openproject.org/docs/installation-and-operations/configuration/#cache-configuration-options)
[SMTP configuration](https://www.openproject.org/docs/installation-and-operations/configuration/outbound-emails/)
[Integrations guide](https://www.openproject.org/docs/system-admin-guide/integrations/) | +| Attached storages or Object storage | Access for attachments for the OpenProject application.
Either directly (or networked) attached storages, or configuration of an S3-compatible Object store | Local filesystem access (local drives, NFS)
HTTPS (S3-compatible storage) | RW | [Configuration of the attachment storage](https://www.openproject.org/docs/installation-and-operations/configuration/#attachments-storage) | +| Email gateways | Send emails (e.g., notifications) from OpenProject application | SMTP | W (deliver mails to relay) | [SMTP configuration](https://www.openproject.org/docs/installation-and-operations/configuration/outbound-emails/) | +| Identity providers | External authentication providers (e.g., Keycloak, ADFS, etc.) | HTTPS through standard protocols (OpenID connect, SAML, OAuth 2.0) | R (Redirect and read user info) | [OpenID connect provider configuration](https://www.openproject.org/docs/system-admin-guide/authentication/openid-providers/)
[SAML provider configuration](https://www.openproject.org/docs/system-admin-guide/authentication/saml/)
[OAuth 2.0 application configuration](https://www.openproject.org/docs/system-admin-guide/authentication/oauth-applications/) | +| Nextcloud | External biliteral integration | HTTPS | RW | [Nextcloud integration guide](https://www.openproject.org/docs/system-admin-guide/integrations/nextcloud/) | +| GitHub | Pull Request / Issue referencing Integration into Openproject | HTTPS (Webhooks) | R (Incoming webhook from GitHub) | [GitHub integration guide](https://www.openproject.org/docs/system-admin-guide/integrations/github-integration/) | +| Calendars | External calendars requesting dynamic ICS calendar files from OpenProject | HTTPS (iCalendar/webdav) | R (Outgoing calendar data) | [Calendar subscriptions configuration](https://www.openproject.org/docs/system-admin-guide/calendars-and-dates/#calendar-subscriptions) | +| API integrations | Structural access to OpenProject through API endpoints. Optional access to users and third party organizations depending on authorized scopes | HTTPS | (Optional) R
(Optional) W
| [API configuration](https://www.openproject.org/docs/system-admin-guide/api-and-webhooks/) | +| Outgoing Webhooks | Outgoing requests for changes within the application | HTTPS | R (Outgoing webhook data) | [Webhook configuration an adminstration](https://www.openproject.org/docs/system-admin-guide/api-and-webhooks/#webhooks) | @@ -115,6 +153,17 @@ On the other hand, changes to the following are considered breaking changes and This list is not conclusive but rather serves to highlight the difference to the previous list of non breaking changes. +
+ +## Version tracing in containers and packages + +OpenProject embeds some release information into the packages and containers to ensure they are traceable. For all containers, the following files exist under `/app`. For packages, these files reside under `/opt/openproject/` and `/opt/openproject/config`, depending on the used version. + +- **CORE_VERSION**: Reference to the commit of the https://github.com/opf/openproject core repository of OpenProject that is the foundation of the build +- **CORE_URL** URL to the commit at GitHub for easier reference +- **PRODUCT_VERSION** Commit of the flavour/product version. In case of the [openDesk container](https://hub.docker.com/r/openproject/open_desk), contains a reference to the openDesk repository https://github.com/opf/openproject-open_desk +- **BUILDER_VERSION** Internal reference of the building CI repository that we use to create and publish the images. + ## Support of releases @@ -147,10 +196,6 @@ The version is represented as [tags](https://www.openproject.org/docs/developmen A typical installation of OpenProject uses a web server such as NGINX or Apache to proxy requests to and from the internal [Puma](https://puma.io/) application server. All web requests are handled internally by it. A background job queue is used to execute longer running data requests or asynchronous communications. -For more information on the data flow between these components, please also see our [data flow documentation](../data-flow). - - - ## Puma application server OpenProject uses a Puma application server to run and handle requests for the Rails stack. All HTTP(S) requests to OpenProject are handled by it. Puma is a configurable multi-process, multithreading server. The exact number of servers being operated depends on your deployment method of OpenProject. See the [process control and scaling documentation](https://www.openproject.org/docs/installation-and-operations/operation/control/) for more information. diff --git a/docs/development/concepts/queries/README.md b/docs/development/concepts/queries/README.md index a1c775250a95..421a75ff00e9 100644 --- a/docs/development/concepts/queries/README.md +++ b/docs/development/concepts/queries/README.md @@ -71,7 +71,7 @@ Clients can define a query once, save it and use it later on to load the same se ### Query collections responses -Since queries can be saved and should be listed to the user such as in the work package sidebar, they can also be requested as a collection of resources through `/api/v3/queries`. This endpoint can also be filtered. For more details on that, see the [respective APIv3 Queries filtering section](../../../api/endpoints/queries/#filtering). +Since queries can be saved and should be listed to the user such as in the work package sidebar, they can also be requested as a collection of resources through `/api/v3/queries`. This endpoint can also be filtered. For more details on that, see the [respective APIv3 Queries filtering section](../../../api/endpoints/queries/#query-filter-instance). This response will end up representing the available queries on the `work packages` module sidebar as shown below. diff --git a/docs/development/concepts/secure-coding/README.md b/docs/development/concepts/secure-coding/README.md index 5ddbe40db850..823ca1fa7416 100644 --- a/docs/development/concepts/secure-coding/README.md +++ b/docs/development/concepts/secure-coding/README.md @@ -72,6 +72,9 @@ OpenProject uses industry standard authentication mechanisms that follow the bes OpenProject recommends these authenticiation mechanisms: +- All connections to and from OpenProject should be secured through TLS/SSL transport encryption. OpenProject assumes connections are secured through TLS/SSL by default in all production systems. Note that OpenProject does not provide TLS/SSL termination itself for Docker-based installations. The customer's IT department needs to configure and maintain the TLS certificates at the load balancer or proxying server before connections reach the application server. +- For any external connection (Database, LDAP, etc.), OpenProject uses openssl library for the host or container's openssl certificate store. Use your distribution's mechanisms to add verified certificate or certificate chains. For more infomration, see the [Ruby OpenSSL X509 Store documentation](https://ruby-doc.org/stdlib-2.4.0/libdoc/openssl/rdoc/OpenSSL/X509/Store.html). + - For smaller to medium organizations with no centralized authentication mechanism, use the internal username / password authentication mechanism for secure storing of your user's credentials using BCrypt salted cryptographic hash function. - For organizations with a centralized and accessible LDAP server, [OpenProject provides LDAP userbind authentication](https://www.openproject.org/docs/system-admin-guide/authentication/ldap-authentication/) to foward the authentication request to your LDAP server. Use TLS or LDAPS encrypted connections to the LDAP server to ensure transport level security. Optionally, synchronize roles and permissions using the [LDAP Group sync functionality](https://www.openproject.org/docs/system-admin-guide/authentication/ldap-authentication/ldap-group-synchronization/). - If your organization operates a central authentication services, it is very likely it supports one of the standard remote authentication mechanisms for single sign-on, such as [OpenID connect](https://www.openproject.org/docs/system-admin-guide/authentication/openid-providers/), [SAML](https://www.openproject.org/docs/system-admin-guide/authentication/saml/), or [Kerberos](https://www.openproject.org/docs/system-admin-guide/authentication/kerberos/). Use these mechanisms to ensure a standardized and secure authentication of users without requiring the storage of any credentials at OpenProject while providing a high level of usability due to centralized logins. @@ -221,6 +224,45 @@ As OpenProject may handle and distribute sensitive user data, attack vectors suc +## Logging and Error Handling + +Inconsiderate use of error handling, logging, and monitoring mechanisms of a web frameworks can lead to the following risks and impacts. + +**Risks and Impacts** + +- *Information Disclosure:* Improper error handling may reveal sensitive information or internal details about the application's infrastructure. Resulting consequences are Exposure of sensitive data, such as database errors or stack traces, which can aid attackers in planning further attacks. +- *Data Leakage:* Inadequate logging and error handling can inadvertently log sensitive user data or credentials. This may result in unauthorized access to user data, privacy violations, and compliance breaches. +- *Log Injection Attacks:* Lack of input validation on log entries can expose the application to log injection attacks where attackers manipulate log entries to inject malicious code or content. Resulting impacts are Malicious code execution, log manipulation, and potential system compromise. + +**Guidelines** + +- Implement proper exception handling to catch and handle unexpected errors. Log the exceptions for further analysis. +- The application should fail in a secure manner. If an error occurs, the system should revert to a safe state that doesn't expose sensitive information or functionality. +- Use generic error messages for end users to prevent information leakage. Avoid exposing stack traces, database error messages, or any detailed system information. If providing summaries or error reports to users, make sure no sensitive data or system information is included. +- Scrub and filter user data being logged or output in error messages to prevent data leakage. +- Only log necessary information. Avoid logging sensitive data such as passwords, payment information, or Personally Identifiable Information (PII). +- Log data in a standard format to make parsing, auditing, and monitoring of that information easy. +- Ensure that actions are aborted in case of errors + + + +**Usage at OpenProject** + +- Exception handlers catch all StandardErrors whenever your controller inherits from ApplicationController +- Exception responses are disconnected from the actual errors and provide user-friendly messages without error details +- Database transaction wrapping for any actions is wrapped in the [BaseContracted services](https://github.com/opf/openproject/blob/dev/app/services/base_services/base_contracted.rb#L54). Transactions are automatically rolled back in [Rails when exceptions occur](https://api.rubyonrails.org/v5.0.1/classes/ActiveRecord/Transactions/ClassMethods.html). +- OpenProject uses a LogRage formatter for flexible, yet easily parseable formats + + + +**References** + +https://cheatsheetseries.owasp.org/cheatsheets/Error_Handling_Cheat_Sheet.html + +https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html + + + ## External dependencies OpenProject includes a number of external dependencies both in Ruby as well as in the JavaScript ecosystem. Regardless of the selection of these dependencies, maintaining and keeping the dependencies up-to-date is a critical part of the security of the application. We have seen a lot of attacks surface in the past years originating from either outdated or manipulated dependencies. @@ -252,39 +294,41 @@ https://cheatsheetseries.owasp.org/cheatsheets/Vulnerable_Dependency_Management_ -## Logging and Error Handling +## Packaging and containerization -Inconsiderate use of error handling, logging, and monitoring mechanisms of a web frameworks can lead to the following risks and impacts. +Packaging and containerization are critical artefacts in the delivery pipeline of OpenProject. They encapsulate the application and its environment, ensuring consistent operation across different systems and infrastructures. These artefacts need to provide a secure and stable default for maintaining and upgrading OpenProject. -**Risks and Impacts** +Properly managed packaging and containerization pipelines ensure smooth installations, upgrades, and scaling, enhancing the deployment process and - as a result - the overall user experience. This section highlights risks connected to improper containerization or packaging as well as our main objectives and best practices to provide a secure, efficient, and reliable software delivery process. -- *Information Disclosure:* Improper error handling may reveal sensitive information or internal details about the application's infrastructure. Resulting consequences are Exposure of sensitive data, such as database errors or stack traces, which can aid attackers in planning further attacks. -- *Data Leakage:* Inadequate logging and error handling can inadvertently log sensitive user data or credentials. This may result in unauthorized access to user data, privacy violations, and compliance breaches. -- *Log Injection Attacks:* Lack of input validation on log entries can expose the application to log injection attacks where attackers manipulate log entries to inject malicious code or content. Resulting impacts are Malicious code execution, log manipulation, and potential system compromise. +OpenProject provides several installation mechanisms: -**Guidelines** +- [Packaged installations](https://www.openproject.org/docs/installation-and-operations/installation/packaged/) using the distribution's package manager for dependency control -- Implement proper exception handling to catch and handle unexpected errors. Log the exceptions for further analysis. -- The application should fail in a secure manner. If an error occurs, the system should revert to a safe state that doesn't expose sensitive information or functionality. -- Use generic error messages for end users to prevent information leakage. Avoid exposing stack traces, database error messages, or any detailed system information. If providing summaries or error reports to users, make sure no sensitive data or system information is included. -- Scrub and filter user data being logged or output in error messages to prevent data leakage. -- Only log necessary information. Avoid logging sensitive data such as passwords, payment information, or Personally Identifiable Information (PII). -- Log data in a standard format to make parsing, auditing, and monitoring of that information easy. -- Ensure that actions are aborted in case of errors +- [Slim and all-in-one docker images](https://www.openproject.org/docs/installation-and-operations/installation/docker/) for manual operation with docker +- [OpenProject helm chart](https://www.openproject.org/docs/installation-and-operations/installation/helm-chart/) , as a "package" for kubernetes clusters + -**Usage at OpenProject** - -- Exception handlers catch all StandardErrors whenever your controller inherits from ApplicationController -- Exception responses are disconnected from the actual errors and provide user-friendly messages without error details -- Database transaction wrapping for any actions is wrapped in the [BaseContracted services](https://github.com/opf/openproject/blob/dev/app/services/base_services/base_contracted.rb#L54). Transactions are automatically rolled back in [Rails when exceptions occur](https://api.rubyonrails.org/v5.0.1/classes/ActiveRecord/Transactions/ClassMethods.html). -- OpenProject uses a LogRage formatter for flexible, yet easily parseable formats +**Risks and Impact** +- *Security Vulnerabilities*: Containers may inherit vulnerabilities from base images or packages. +- *Update Management*: Inability to provide an easy and fast upgrade may lead to installations remaining outdated and as a result, vulnerable to known exploits. +- *Configuration Drift*: Variations in configurations across different environments can lead to unexpected behaviors. They also make documentation of these variations harder, and lead to confusion for administrators and users. +- *Resource Utilization*: Inefficient containerization can lead to excessive resource usage or an unstable software. +- *Dependency conflicts*: Heterogenous installations may result in dependency conflicts or incompatibilities when using packages for installations. +- *Orchestration Complexity*: With more dependencies and services, deployments add complexity that can introduce errors in service discovery, networking, and persistence. +- *Compliance and Compatibility*: Ensuring that packaging and containerization meet known regulatory compliance requirements and are compatible with commonly used platforms. -**References** -https://cheatsheetseries.owasp.org/cheatsheets/Error_Handling_Cheat_Sheet.html +**Guidelines** -https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html +- *Use Immutable Tags*: Provide specific, immutable tags for Docker images and fixed packaged versions to ensure consistency and provide clear upgrade paths instead of automatically pulling the latest image +- *Scan for Vulnerabilities*: Regularly scan container images for vulnerabilities and promptly update them. On top of statical code analysis for code and dependencies (see above), OpenProject uses Snyk and Docker scout for its public docker images to be informed of which vulnerabilities exist in the base images. +- *Minimal base Images*: Use minimal base images for Docker containers to reduce the attack surface. OpenProject currently uses a `ruby-${version}-${debianversion}` image as its base. +- *Configuration Management*: Ensure configuration management is consistent between deployments. OpenProject provides an interface to ENV-based configuration for packages and Docker to ensure both can be configured similarly. Where necessary, different configuration mechanisms are documented for the different installation mechanisms. +- *Resource Limits*: Set resource limits and requests in container definitions to prevent resource contention. The packaged installation provides a set of default scaling services. The OpenProject helm-charts define limits and resource requirements in the helm values. +- *Monitor and Logging*: Implement robust monitoring and logging to track the health and performance of containers. [OpenProject provides individually pluggable health checks for various services as well as flexible logging](https://www.openproject.org/docs/installation-and-operations/operation/monitoring/). +- *Continuous Integration/Continuous Deployment (CI/CD)*: Automate the building, testing, and deployment of containers using CI/CD pipelines. OpenProject builds `dev` containers and packages for every change to the core application. +- *Documentation*: Maintain comprehensive documentation for installation and configuration processes across different mechanisms. OpenProject documents all changes as part of the standard development workflow. Documentation is released together with OpenProject to ensure consistency. [The documentation workflow is part of the product development handbook.](../../product-development-handbook/) diff --git a/docs/development/data-flow/README.md b/docs/development/data-flow/README.md deleted file mode 100644 index bd2811fc3e2f..000000000000 --- a/docs/development/data-flow/README.md +++ /dev/null @@ -1,129 +0,0 @@ -# Data flow and usage - -Regardless of the type of installation of OpenProject, the following diagram provides a high-level overview of through which systems data related to OpenProject is flowing. - - - -```mermaid -%%{init: {'theme':'neutral'}}%% - -flowchart TD - A[Client Browser] -->|"HTTP(s) requests"| B(Load Balancer / Proxy) - A1[API or Native clients] -->|"HTTP(s) requests"| B(Load Balancer / Proxy) - A2[SVN or Git clients] -->|"HTTP(s) requests"| B(Load Balancer / Proxy) - B -->|Proxy| openproject - - subgraph openproject[OpenProject] - C[Puma app server] - D[Background worker] - end - - - subgraph integrations[External integrations] - O[Other integrations] - N[Nextcloud] - end - - subgraph services[Services] - M[memcached] - P[PostgreSQL] - S[Object storage or NFS] - end - - - openproject <--> services - openproject --> integrations - B <--> integrations - -``` - -As a web application, the primary data flow is between the Client browser (or attached API clients) through an external proxying web server (this might be a load balancer or proxying server). We're assuming it is the one responsible for terminating TLS connections for the course of this document - although encrypted connections between Load balancer and Puma server are possible. In case of packaged or kubernetes installations, this proxying server might be part of the OpenProject stack (e.g., an Apache2 packaged installation server or nginx ingress). - -The external web server acts as a proxy/reverse-proxy for the OpenProject Puma application server, relaying requests for it to handle and respond. In the course of the request, access to external services such as the PostgreSQL database, a caching server, or attached storages might be performed. In case of S3-compatible object storage set ups, OpenProject performs calls to the object storage to put or request files from it. Likewise, for network-attached storages linked into the application, underlying network requests are performed. These are out of scope for this evaluation, as they are provided and maintained by the operator of the system. - -In the course of using the application, background tasks are enqueued in the database such as outgoing emails, cleanup tasks, or notification processing. These tasks are performed in a separate process, the background worker queue. This process accesses the same services as the application server process to access or modify data. It might connect to external integrations such as a Nextcloud instance to set up file sharings depending on actions performed by the users. - - - -## Exemplary request flow - -- **User request**: An end-user sends an HTTPS request to the load balancer or proxying server. - -- **Load balancer**: The external load balancer or proxying server receives the request, terminates TLS, and forwards the HTTP request to the Puma application server. - -- **Puma server**: Processes the request and invokes the appropriate Rails middlewares and controller. - -- **Rails application**: - - - Authenticates the user according to the mechanisms outlined in the [secure coding guidelines](../concepts/secure-coding) - - Validates session and input data - - Responsible for error handling, logging, and auditing aggregation - - - Retrieves or updates resources to the PostgreSQL database via models - - Calls or interacts with external services for requests, such as retrieving files or attachments from object storage - - - Renders the appropriate views - -- **Response**: Sends the HTTP response back through the Puma server and load balancer to the end-user. - -- **Background worker:** Operate on periodical background data, or perform actions requested by the web request of user (sending emails, exporting data, communicating with external services) - - - -## Schema information - -OpenProject's database schema is considered an internal API, please do not rely on it as a stable point of references. Schema modifications by the OpenProject core might be performed in any upgrade, including patch releases. Modifications to the database schema are considered a third-party customization and might prevent us from giving proper support. If you have an active support contract with OpenProject, please note that modifications affect our warranty. For more information, please consult the [Terms of Services](https://www.openproject.org/legal/terms-of-service/#-5-warranty). - -We recommend you use existing database tools to inspect and export the database as an ERD. That being said, we've prepared an export of an ERD of the current state of the database. Note that this diagram is not regularly updated. Use tools like IntelliJ database explorer or [mermerd](https://github.com/KarnerTh/mermerd) to generate a live ERD of your database set up instead. - -[![OpenProject database schema ERD](openproject-erd.jpg)](openproject-erd.jpg) - - - -# Use of technical cookies - -OpenProject makes use of technical cookies to identity the browser client and/or remember information such as 2FA login state. The core application makes use of these cookies: - -| **Cookie name** | **Description** | **Expiry** | **Security flags** | **Implementation** | -| ---------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ----------------------------------------------------- | ------------------------------------------------------------ | -| `_open_project_session` (name is configurable) | contains the information about the logged in user as well as information stored between requests on the user's choices (e.g. the filters for costs are in part stored there) | Session
+ configurable server-sideTTL | secure
httponly
Samesite=Lax
encrypted | [Code ref](https://github.com/opf/openproject/blob/release/13.0/config/initializers/session_store.rb#L34-L39) | -| `autologin` (name is configurable) | (Optional feature, requires opt-in under Administration > Authentication settings)
enables the user to automatically log in again after the session expired (e.g. because the browser was closed). It is set when the user checks the '*Stay logged in*' box in the login form.
| Cookie 1 year
+ server-side token N days (configurable) | secure
httponly
Samesite=Lax
encrypted | [Code ref](https://github.com/opf/openproject/blob/release/13.0/app/controllers/concerns/accounts/user_login.rb#L19C1-L29) | -| `op2fa_remember_token` | the presence of that cookie suppresses the need for the user to provide a second factor upon login for N days (configurable by administration) if the user selects to do so when entering the 2fa information. | N days (configurable) | secure
httponly
Samesite=Lax
encrypted | [Code ref](https://github.com/opf/openproject/blob/release/13.0/modules/two_factor_authentication/app/controllers/concerns/two_factor_authentication/remember_token.rb#L28-L34) | - - - -On top of that, for cloud instances: - -- `openproject_cloud_instances` contains a list of instances the user recently accessed. -- additional technical cookies might be set by the load balancer and intermediate processes (i.e., to remember a sticky load balancer and ensuring subsequent requests are routed similarly). - - - -# Processing of Personally Identifiable Information - -As OpenProject is dealing with user account data, it is processing personally identifiable information (PII). This data encompasses: - -- User's first and last name -- E-Mail address(es) -- Other uniquely identifiable information used as authentication data of external identity providers (such as SAML or OpenID Connect) -- User pictures / Avatars -- IP addresses in log files -- Possibly data that is filled as part of user custom fields, configurable data fields shown and editable for users. The content of these fields are user-provided and not systematically processed by OpenProject however. - - - -Affected services: - -- PostgreSQL database (stores user account data) -- Object storage or NFS (stores user pictures as files) -- Memcached (Might contain references to cached information of user data) - - - -## Deletion and Anonymization of PII - -Whenever users in OpenProject are fully deleted, the system scrubs and removes all structural PII. For more information on user account deletion, please see [the user administration guide](../../system-admin-guide/users-permissions/users/#delete-users). - -Deleting a user account is a permanent action and cannot be reversed. All actions performed in the name of the user are being scrubbed and replaced with a singular "Deleted user" reference in order to maintain integrity of database references, such as being an author of a work package that remains. Finally, the user data itself will be deleted, removing all structural traces of PII in the system. Due to the user references changing, respective cache keys for information such as work packages or projects are invalidated automatically. Note that user-input data such as text or comments cannot be deleted or scrubbed in an automated fashion. - -Log files might still retain PII data of the user for the configured retention period. Memory references in memcached might still refer to (invalidated) user data until it is being reassigned. diff --git a/docs/development/data-flow/openproject-erd.jpg b/docs/development/data-flow/openproject-erd.jpg deleted file mode 100644 index d5ad108d5a4e..000000000000 Binary files a/docs/development/data-flow/openproject-erd.jpg and /dev/null differ diff --git a/docs/development/product-development-handbook/README.md b/docs/development/product-development-handbook/README.md index 94a43e76f278..ee18747b119c 100644 --- a/docs/development/product-development-handbook/README.md +++ b/docs/development/product-development-handbook/README.md @@ -14,7 +14,7 @@ keywords: product development, requirement process, RICE score OpenProject aims to connect distributed teams and organizations and make project management intuitive and fun. The application is continuously developed and maintained by an active international community to provide a powerful feature set and yet intuitive user interface. The overall purpose is to create customer benefit. To achieve this, OpenProject follows a requirements and product development process that empathizes identifying and building the functionality which most aligns with OpenProject’s product vision and delivers customer value. -This guide is an evolving description of the steps taken from collecting requirements all the way to implementation and release. The goal is to provide a single source of truth and provide a guideline for team members, community contributors and interested customers. As such this document will continuously be updated. +This guide is an evolving description of the steps taken from collecting requirements all the way to implementation and release. The goal is to provide a single source of truth and provide a guideline for team members, community contributors and interested customers. As such this document will continuously be updated whenever involved components, roles, or permissions are changing. ## 2. Process overview @@ -160,16 +160,29 @@ For internal or customer requirements requirements may directly be created, eval Based on the Product Managers judgement (taking among other things the RICE score and customer backing into account) validated and prioritized features (status: “In specification”) are specified in more detail: 1. PM specifies the solution and creates mockups (e.g. PowerPoint, Google Docs, …). + 2. PM updates the Opportunity Canvas (especially “Solution” section). + 3. PM and Developer validate solution (technical feasibility / solution). + + *If this solution touches security relevant components of the application, a Security Engineer is involved to identity and model the associated risks and impacts (thread modelling) according to the documented risks in the [Secure Coding Guidelines](https://www.openproject.org/docs/development/concepts/secure-coding/#secure-coding-guidelines).* + 4. PM / UX Researcher validates the solution through user interviews. (optional) + 5. PM / UX Researcher iterates through possible solutions based on user interviews and updates the Opportunity canvas. (optional) + 6. PM / Developer adds more detailed effort and cost estimates. + 7. Designer is assigned to the "Designer" field of the feature. + 8. Designer creates visuals based on mockups (if necessary). + 9. PM validates design with users (user interviews) (optional) + 10. PM in coordination with Developer assigns feature to upcoming product version. + 11. PM hands over features to the Developer. + 12. PM highlights features that require change in documentation if necessary (custom field “Requires doc change”). The features in a product version need to be specified at least one iteration prior to development start. If a feature is added to the current version it needs to be specified with high priority. If it is added to the next version it can be specified with a lower priority but still higher then other features in the product backlog. @@ -213,8 +226,9 @@ Ideally the preparation of both QA and development happen at the same time so th 4. Developer hands over "Implementation" work package upon completion to another developer for review (status: “In review”). 5. Developer (different from the one implementing the code) performs a review and, if changes are accepted according to the points mentioned below merges the pull request and closes the "Implementation" work package. 1. [Secure coding guidelines](https://www.openproject.org/docs/development/concepts/secure-coding/) have been evaluated for the proposed changes. - 2. [Code review guidelines](https://www.openproject.org/docs/development/code-review-guidelines/) are followed by the submitter and reviewer - 3. [Pull request targets the correct version](https://www.openproject.org/docs/development/git-workflow/#create-a-pull-request), and has a related work package that will form the changelog. + 2. New or changed functionality is covered following the [Writing and Running Tests guide](https://www.openproject.org/docs/development/running-tests/) to ensure the entire required spectrum of tests were added. + 3. [Code review guidelines](https://www.openproject.org/docs/development/code-review-guidelines/) are followed by the submitter and reviewer + 4. [Pull request targets the correct version](https://www.openproject.org/docs/development/git-workflow/#create-a-pull-request), and has a related work package that will form the changelog. 7. The feature lead developer updates the status of the feature to "merged" once the feature is fully implemented. This can be done even with bugs still open that QA has already identified. 8. Developer highlights features that require change in documentation if necessary (custom field “Requires doc change”). @@ -226,12 +240,14 @@ Changes to the technical documentation, e.g API documentation, are done in paral ### 3.2.3 Building phase 3: Quality Assurance -| Involved | Output | -|------------------------------|:---------------| -| - QA | Tested feature | +| Involved | Output | +| -------- | :----------------------------------------------------------- | +| - DevOps | [Edge or Staging environments](https://www.openproject.org/docs/development/application-architecture/#environments) are updated automatically or manually with necessary changes | +| - QA | Tested feature | 1. Tester adapts test plan if acceptance criteria was altered since the original creation of the test plan. -2. Tester tests feature (based on test plan) +2. Tester performs and verifies additional tests according to the [Writing and Running Tests guide](https://www.openproject.org/docs/development/running-tests/) to ensure the application has been tested according to specifications and requirements. +3. Tester tests feature (based on test plan) 1. Tester adjusts status when no errors in feature (status: “tested”). 2. Tester adjusts status when errors occur (status: “test failed”) and notifies developer (move back to phase 2 - Implementation) @@ -241,11 +257,14 @@ When all features, bugs have been tested successfully, regression testing was pe ### 3.2.3 Building phase 4: Acceptance test -| Involved | Output | -|-------------------|:-----------------| -| - Product manager | Accepted feature | +| Involved | Output | +| --------------------------------------------------------- | :----------------------------------------------------------- | +| - Product manager
- (possibly) External Stakeholders | Accepted feature (acceptenace succeeded) OR
Changes necessary (acceptance failed) | 1. PM tests features to see if requirements are met, discusses necessary changes with developer (acceptance test) (status: “closed”). +1. If external stakeholders are involved and depending on any additional agreements between OpenProject and the external stakeholders, an additional presentation or feature presentation is performed as part of the acceptance testing. The result of this test may result in additional iterations of the steps Buidling phase 1 - 3. + +If required changes are identified or predefined acceptance criteria is not met, the acceptance test is failed, the respective work packages are returned ot the developers/product team for additional changes or specification work ### 3.2.4 Building phase 4: Documentation @@ -278,7 +297,7 @@ Developed features are bundled into a version that is released to the public via Those steps can be repeated multiple times (restarting at step 2) until the release candidate is deemed stable enough to be released. For patch level releases, where only bugs are addressed, the process for a version starts at this point. - + ## 3.3 Release phase During the release phase, the new OpenProject version is rolled out, release notes are published and lessons learned are documented. @@ -457,4 +476,3 @@ An Opportunity Canvas may not always be required - especially when a problem is - [Opportunity Canvas Template](https://docs.google.com/document/d/1sgNrEx_PRCwewI9-46mN0qnyzz2AWq_SwFc6gLOcrbI/edit) - diff --git a/docs/development/running-tests/README.md b/docs/development/running-tests/README.md index 2779e4ca034d..cb34e88a02d8 100644 --- a/docs/development/running-tests/README.md +++ b/docs/development/running-tests/README.md @@ -18,6 +18,8 @@ Testing OpenProject is distributed between different roles and members, dependin ## Functional testing +Functional testing ensures that the application works against the set of requirements or specifications. Tests should therefore make sure all the acceptance criteria are met. + The following types of functional tests are used at OpenProject. | **Type** | Description | Examples, References | @@ -54,7 +56,9 @@ Unit testing concerns testing of isolating individual components of the applicat - **Assert**: Check that the method or process behaved as expected. - Keep examples of unit specs simples and descriptive - Write tests during or before development, not as an afterthought -- Test the entire range of potential inputs, including negative tests and validation of potentially malicious user input +- Test the entire range of potential inputs, including *negative* tests and validation of potentially malicious user input. + + Negative testing consists of test cases which define how software reacts to user’s invalid input or unexpected behavior. The aim is not only to prevent the application from crashing but to improve quality by specifying clear and understandable error messages so that users know what kind of input is expected and correct. - Avoid calling the database if not necessary - Use `FactoryBot` to set up test data in a structured, but randomized way to prevent brittle tests - Mock external components and services, and ensure you test the boundaries of the associated components @@ -174,6 +178,17 @@ Sanity and regression tests are manually performed tests by QA for relevant comp +**Usage at OpenProject** + +For writing and executing manual sanity and regression testing, especially focusing on functional requirements, one of the tools in use at OpenProject is TestLink (https://testlink.org/) to achieve the following goals: + +- Test cases have clear preconditions so that the tester prepares for executing each case with enough knowledge about requirements. +- Test cases are as specific as possible. They should check the proper working of one single point/case and should therefore have no more than 8-10 steps. +- Test cases are updated with every change of the specifications. +- Test cases have precise execution steps and expected results. + + + **References** - https://www.browserstack.com/guide/sanity-testing @@ -210,6 +225,10 @@ Acceptance tests evaluate both functional and non-functional requirements. ## Non-functional testing +Non-functional testing goes beyond the functionality of the product and is aimed at end-user experience. Test cases should hence make sure to define what is expected in terms of security, performance, compatibility, accessibility etc. + +Examples for non-functional test cases: software should be compatible with most used desktop and mobile browsers, as well as operating systems; all the actions can be performed with keyboard navigation; page loading should take no more than X seconds; users who lost access should no longer be able to login etc. + | Type | Description | Examples, References | |-----------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | [Stress and performance tests](#performance-tests) | (Half-)automated or manual testing of the response of the application during higher load, or expected upper boundaries of customer-defined data | e.g., running and evaluating new query plans on existing, anonymized or simulated data that matches potential or known performance bottlenecks | @@ -261,6 +280,7 @@ Automated or manual security tests for OpenProject are evaluating common weaknes **Best practices** - Use statical and dynamical code analysis for automated vulnerability testing. OpenProject uses CodeQL and Brakeman as part of the CI pipeline to give early feedback to common vulnerabilities. +- OpenProject uses [Docker Scout](https://www.docker.com/products/docker-scout/) for the Docker images hosted on Docker Hub for automated vulnerability scanning and analysis of the built container, including all dependencies. - Follow our [secure coding guidelines](../concepts/secure-coding/) when proposing changes to the application, especially when modifying or adding features to authentication, authorization, 2FA, or sensitive data operations. - If possible, automate security tests for common vulnerabilities for input in your development. - Train on recent vulnerabilities and checklists such as [OWASP Top Ten](https://owasp.org/www-project-top-ten/) or [OWASP cheat sheets](https://cheatsheetseries.owasp.org/index.html) to stay up-to-date on security testing and extend our security test suite with new information. @@ -278,10 +298,11 @@ Upgrade tests are manually performed for major code changes and data migrations **Key objectives and effects** 1. **Verify seamless installation**: Ensure that OpenProject can be installed as documented. -2. **Check version compatibility**: Test the compatibility of the upgraded application with existing configurations, databases, and other dependent software. -3. **Validate migrations**: Confirm that during an upgrade, data migration occurs without data loss or corruption. -4. **Technical support**: Reduce the number of support tickets related to installation and upgrade issues. -5. **Operational efficiency**: Minimize downtime and service interruptions during the upgrade process. +2. **Correct and minimal configuration:** Ensure that the default configuration is minimal but sufficient to operate OpenProject securely, and check that the required necessary configuration is minimal. New configuration primitives should receive a secure default. +3. **Check version compatibility**: Test the compatibility of the upgraded application with existing configurations, databases, and other dependent software. +4. **Validate migrations**: Confirm that during an upgrade, data migration occurs without data loss or corruption. +5. **Technical support**: Reduce the number of support tickets related to installation and upgrade issues. +6. **Operational efficiency**: Minimize downtime and service interruptions during the upgrade process. @@ -290,6 +311,7 @@ Upgrade tests are manually performed for major code changes and data migrations - Use automated testing scripts to simulate various installation and upgrade scenarios. - Provide and test the rollback of data migrations to make sure they work as intended. - Keep up-to-date documentation for the installation and upgrade procedures, including a list of known issues and workarounds. +- Example of test cases would be ensuring that software works in a satisfying manner on major browsers and operating systems which are defined in https://www.openproject.org/docs/installation-and-operations/system-requirements/ diff --git a/docs/enterprise-guide/enterprise-cloud-guide/gdpr-compliance/README.md b/docs/enterprise-guide/enterprise-cloud-guide/gdpr-compliance/README.md index ba400711fe16..9cbd17f7aad7 100644 --- a/docs/enterprise-guide/enterprise-cloud-guide/gdpr-compliance/README.md +++ b/docs/enterprise-guide/enterprise-cloud-guide/gdpr-compliance/README.md @@ -73,4 +73,4 @@ Please navigate to -> Administration -> GDPR and you can now online review and s -Find out more about [OpenProject's security features](../../../development/security/#openproject-security-features). +Find out more about [OpenProject's security features](../../../security-and-privacy/statement-on-security/#openproject-security-features). diff --git a/docs/installation-and-operations/installation/helm-chart/README.md b/docs/installation-and-operations/installation/helm-chart/README.md index acbf87b70154..6c6b29001d27 100644 --- a/docs/installation-and-operations/installation/helm-chart/README.md +++ b/docs/installation-and-operations/installation/helm-chart/README.md @@ -22,6 +22,24 @@ This chart bootstraps an OpenProject instance, optionally with a PostgreSQL data - Helm 3.0.0+ - PV provisioner support in the underlying infrastructure + + +### ReadWriteMany volumes + +By default and when using filesystem-based attachments, OpenProject requires the Kubernetes cluster to support `ReadWriteMany` (rwx) volumes. This is due to the fact that multiple container instances need access to write to the attachment storage. + +To avoid using ReadWriteMany, you will need to configure an S3 compatible object storage instead which is shown in the [advanced configuration guide](../../configuration/#attachments-storage). + +``` +persistence: + enabled: false + +s3: + enabled: true + accessKeyId: + # etc. +``` + ## Installing the Chart You can install the chart with the release name `my-openproject` in its own namespace like this: @@ -33,7 +51,20 @@ helm upgrade --create-namespace --namespace openproject --install my-openproject The namespace is optional, but using it does make it easier to manage the resources created for OpenProject. +### Helm chart signing + +We sign our chart using the [Helm Provenance and Integrity](https://helm.sh/docs/topics/provenance/) functionality. You can find the used public key here + +- https://github.com/opf/helm-charts/blob/main/signing.key +- https://keys.openpgp.org/vks/v1/by-fingerprint/CB1CA0488A75B7471EA1B087CF56DD6A0AE260E5 +We recommend using the [Helm GnuPG plugin](https://github.com/technosophos/helm-gpg). With it you can manually verify the signature like this: + +```bash +helm repo add openproject https://charts.openproject.org +helm fetch --prov openproject/openproject +helm gpg verify openproject-*.tgz +``` ## Configuration @@ -125,8 +156,48 @@ Either increase the cluster's resources to have at least 4 CPUs or install the O --set resources.limits.cpu=2 ``` -### Root access in OpenShift +### OpenShift -The OpenProject container performs tasks as root during setup. -In [OpenShift](https://www.redhat.com/en/technologies/cloud-computing/openshift) this is not allowed. You will have to [add](https://examples.openshift.pub/deploy/scc-anyuid/) the `anyuid` SCC (Security Context Constraint) -to OpenProject's service account. +For OpenProject to work in OpenShift without further adjustments, +you need to use the following pod security context. + +``` +podSecurityContext: + supplementalGroups: [1000] + fsGroup: null +``` + +By default OpenProject requests `fsGroup: 1000` in the pod security context. +This is not allowed by default. You have to allow it using +a custom SCC (Security Context Constraint) in the cluster. + +The use of `supplementalGroups` is not necessary if you request the correct UID in the security context. + +``` +securityContext: + runAsUser: 1000 + runAsGroup: 1000 +``` + +But this will not be allowed by default either. So the easiest way is the use of the `podSecurityContext` shown above. + +Due to the default restrictions in OpenShift there may also be issues running +PostgreSQL and memcached. Again, you may have to create an SCC to fix this +or adjust the policies in the subcharts accordingly. + +Assuming no further options for both, simply disabling the security context values to use the default works as well. + +``` +postgresql: + primary: + containerSecurityContext: + enabled: false + podSecurityContext: + enabled: false + +memcached: + containerSecurityContext: + enabled: false + podSecurityContext: + enabled: false +``` diff --git a/docs/installation-and-operations/misc/migration/README.md b/docs/installation-and-operations/misc/migration/README.md index f13bb010ddea..65ce530c5e17 100644 --- a/docs/installation-and-operations/misc/migration/README.md +++ b/docs/installation-and-operations/misc/migration/README.md @@ -25,9 +25,10 @@ To stop the servers from being accessed on the old installation, stop the servic ## Install new package -Follow the first step (**Installation**) of our [packaged installation guides](https://www.openproject.org/download-and-installation/). +Follow the first step (**Installation**) of our [packaged installation guides](../../installation/packaged/) up until _but excluding_ the [Step 0: Start the wizard](../../installation/packaged/#step-0-start-the-wizard) step. -After this step, you should have an installed version of `openproject`. +With this done, you should have an installed version of OpenProject with the `openproject` command existing. Do not yet run `openproject configure`, because you will first take over the configuration +from your previous installation. ### Moving Configuration diff --git a/docs/installation-and-operations/operation/control/README.md b/docs/installation-and-operations/operation/control/README.md index 4297183b5e2c..9962d47f863d 100644 --- a/docs/installation-and-operations/operation/control/README.md +++ b/docs/installation-and-operations/operation/control/README.md @@ -145,6 +145,8 @@ Launch an interactive console to directly interact with the underlying Ruby on R docker exec -it $CID bash -c "RAILS_ENV=production bundle exec rails console" ``` + + ## docker-compose based installation #### Spawn a rails console @@ -157,3 +159,32 @@ The following command will spawn a Rails console in the container: ```shell docker-compose run web bash -c "RAILS_ENV=production bundle exec rails console" ``` + + + +## Kubernetes and Helm-Charts + +For Kubernetes installations, you can use `kubectl` to access pods and get information about them. For example, to get a shell in one of the worker pods, you would have to do the following. + +First, get the pod name of the worker. Assuming your kubectl cluster has OpenProject installed at the `openproject` namespace: + +``` +kubectl get pods -n openproject +``` + + + +Then spawn a shell in the relevant one + +``` +kubectl exec -n openproject -it pods/openproject-worker-656c77d594-xjdck -- bash +``` + + + +This spawns a bash console. In there, you could for example run a rails console like follows: + +``` +bundle exec rails console +``` + diff --git a/docs/release-notes/12/12-0-4/README.md b/docs/release-notes/12/12-0-4/README.md index bcf126b86086..37fa1dde930d 100644 --- a/docs/release-notes/12/12-0-4/README.md +++ b/docs/release-notes/12/12-0-4/README.md @@ -26,7 +26,7 @@ The vulnerability has been fixed in version 12.0.4. Versions prior to 12.0.0 are If you are unable to upgrade in a timely fashion, the following patch can be applied: [https://github.com/opf/openproject/pull/9983.patch](https://github.com/opf/openproject/pull/9983.patch) #### Credits -This security issue was responsibly disclosed by [Daniel Santos](https://github.com/bananabr) (Twitter [@bananabr](https://twitter.com/bananabr)). Thank you for reaching out to us and your help in identifying this issue. If you have a security vulnerability you would like to disclose, please see our [statement on security](https://www.openproject.org/docs/development/security/). +This security issue was responsibly disclosed by [Daniel Santos](https://github.com/bananabr) (Twitter [@bananabr](https://twitter.com/bananabr)). Thank you for reaching out to us and your help in identifying this issue. If you have a security vulnerability you would like to disclose, please see our [statement on security](https://www.openproject.org/docs/security-and-privacy/statement-on-security/). ### Bug fixes and changes - Fixed: Frontend including editor and time logging unusable when there are many activities \[[#40314](https://community.openproject.com/wp/40314)\] diff --git a/docs/release-notes/12/12-5-4/README.md b/docs/release-notes/12/12-5-4/README.md index f1a9178b1e69..d8c97050e46f 100644 --- a/docs/release-notes/12/12-5-4/README.md +++ b/docs/release-notes/12/12-5-4/README.md @@ -19,7 +19,7 @@ The release contains two security related bug fixes and we recommend updating to When a user registers and confirms their first two-factor authentication (2FA) device for an account, existing logged in sessions for that user account are not terminated. Likewise, if an administrators creates a mobile phone 2FA device on behalf of a user, their existing sessions are not terminated. The issue has been resolved in OpenProject version 12.5.4 by actively terminating sessions of user accounts having registered and confirmed a 2FA device. -This security related issue was responsibly disclosed by [Vaishnavi Pardeshi](mailto:researchervaishnavi0@gmail.com). Thank you for reaching out to us and your help in identifying this issue. If you have a security vulnerability you would like to disclose, please see our [statement on security](https://www.openproject.org/docs/development/security/). +This security related issue was responsibly disclosed by [Vaishnavi Pardeshi](mailto:researchervaishnavi0@gmail.com). Thank you for reaching out to us and your help in identifying this issue. If you have a security vulnerability you would like to disclose, please see our [statement on security](https://www.openproject.org/docs/security-and-privacy/statement-on-security/). For more information, [please see our security advisory](https://github.com/opf/openproject/security/advisories/GHSA-xfp9-qqfj-x28q). @@ -33,7 +33,7 @@ When a user requests a password reset, an email is sent with a link to confirm a The issue has been resolved in OpenProject version 12.5.4 by actively revoking any active password reset tokens for user accounts having changed their passwords successfully within the application. -This security related issue was responsibly disclosed by [Vaishnavi Pardeshi](mailto:researchervaishnavi0@gmail.com). Thank you for reaching out to us and your help in identifying this issue. If you have a security vulnerability you would like to disclose, please see our [statement on security](https://www.openproject.org/docs/development/security/). +This security related issue was responsibly disclosed by [Vaishnavi Pardeshi](mailto:researchervaishnavi0@gmail.com). Thank you for reaching out to us and your help in identifying this issue. If you have a security vulnerability you would like to disclose, please see our [statement on security](https://www.openproject.org/docs/security-and-privacy/statement-on-security/). diff --git a/docs/release-notes/13-0-8/README.md b/docs/release-notes/13-0-8/README.md new file mode 100644 index 000000000000..42a5800f4725 --- /dev/null +++ b/docs/release-notes/13-0-8/README.md @@ -0,0 +1,30 @@ +--- +title: OpenProject 13.0.8 +sidebar_navigation: + title: 13.0.8 +release_version: 13.0.8 +release_date: 2023-12-05 +--- + +# OpenProject 13.0.8 + +Release date: 2023-12-05 + +We released [OpenProject 13.0.8](https://community.openproject.com/versions/1942). +The release contains several bug fixes and we recommend updating to the newest version. + + +#### Bug fixes and changes + +- Fixed: Logging time using "My spent time" widget returns previous day (likely time zone issue) \[[#49779](https://community.openproject.com/wp/49779)\] +- Fixed: Internal server error upon login via Microsoft Entra ID (AzureAD) \[[#50167](https://community.openproject.com/wp/50167)\] +- Fixed: IFC conversion fails (libhostfxr.so not found) (reintroduced bug) \[[#50172](https://community.openproject.com/wp/50172)\] +- Fixed: +Custom field button moved left (instead of being on the right) of the Custom fields page in Project settings \[[#50285](https://community.openproject.com/wp/50285)\] +- Fixed: Make Nextcloud synchronization more stable in 13.0. \[[#51265](https://community.openproject.com/wp/51265)\] + +#### Contributions +A big thanks to community members for reporting bugs and helping us identifying and providing fixes. + +Special thanks for reporting and finding bugs go to + +Daniel Grabowski, Jeffrey McDole diff --git a/docs/release-notes/8/8-3-2/README.md b/docs/release-notes/8/8-3-2/README.md index 7c03a9a4521b..1794ee301e35 100644 --- a/docs/release-notes/8/8-3-2/README.md +++ b/docs/release-notes/8/8-3-2/README.md @@ -32,7 +32,7 @@ For the full advisory and patches for older unsupported versions, post](https://groups.google.com/d/msg/openproject-security/XlucAJMxmzM/hESpOaFVAwAJ). For our statement on security and further information on how to responsible disclose security related issues to us, please see our -[statement on security](../../../development/security/). +[statement on security](https://www.openproject.org/docs/security-and-privacy/statement-on-security/). Thanks to Thanaphon Soo from the [SEC Consult Vulnerability Lab](https://www.sec-consult.com) for identifying and responsibly diff --git a/docs/release-notes/README.md b/docs/release-notes/README.md index 20ed43d5c0d6..6766be3e1e1b 100644 --- a/docs/release-notes/README.md +++ b/docs/release-notes/README.md @@ -14,6 +14,13 @@ Stay up to date and get an overview of the new features included in the releases +## 13.0.8 + +Release date: 2023-12-05 + +[Release Notes](13-0-8/) + + ## 13.0.7 Release date: 2023-10-23 diff --git a/docs/security-and-privacy/README.md b/docs/security-and-privacy/README.md new file mode 100644 index 000000000000..a157a16fbc30 --- /dev/null +++ b/docs/security-and-privacy/README.md @@ -0,0 +1,22 @@ +--- +sidebar_navigation: + title: Security and privacy + priority: 920 +--- + +# Security and privacy + +Data protection and information security are of central importance for the OpenProject team and are one of the main motives for the development of this open source software. + +The purpose of this document is to equip users of OpenProject with the necessary information for operating OpenProject securely and in compliance with the GDPR. This section provides an overview of the current status of data protection and data security documentation, with plans for gradual expansion. + +## Data privacy + +* Privacy policy: [OpenProject privacy policy](https://www.openproject.org/legal/privacy/) +* Data privacy documentation: [Processing of personal data](./processing-of-personal-data/) + +## Data security + +* Security documentation: BSI Grundschutzchecks (coming Q1 2024) +* Statement on data security: [Statement on data security](./statement-on-security) + diff --git a/docs/security-and-privacy/processing-of-personal-data/README.md b/docs/security-and-privacy/processing-of-personal-data/README.md new file mode 100644 index 000000000000..6a2bdc45a8a5 --- /dev/null +++ b/docs/security-and-privacy/processing-of-personal-data/README.md @@ -0,0 +1,616 @@ +--- +sidebar_navigation: + title: Processing of personal data + priority: 500 +description: Documentation of the data flows of personal data in OpenProject +keywords: GDPR, data flow, processing personal data, data privacy information +--- +# Processing of personal data + +Status of this document: 2023-11-01 + +## Purpose of this document + +This document outlines how personal data flows through the OpenProject software and aims to assist data controllers in organizations using OpenProject on their own infrastructure in creating GDPR-compliant data protection documentation. + +> **Note:** Customers of the [OpenProject GmbH](https://www.openproject.org/legal/imprint/) that subscribed to the [OpenProject Enterprise Edition Cloud](https://www.openproject.org/enterprise-edition/) (a software-as-a-service) please check the following legal documents: +> +> * [Privacy Policy](https://www.openproject.org/legal/privacy/) +> * [Data Processing Agreement](https://www.openproject.org/legal/data-processing-agreement/) +> * [Sub-Processors](https://www.openproject.org/legal/data-processing-agreement/sub-processors/) +> * [Technical and Organizational Data Security Measures](https://www.openproject.org/legal/data-processing-agreement/technical-and-organizational-data-security-measures/) + +## Groups of personal data + +OpenProject is a project management and team collaboration software. The personal data processed by the software can be categorized into four different groups: + +- **User master data:** essential for administering user accounts. +- **Functional assignments:** connects users to various entities such as work packages, projects, teams, budgets, time logs, etc. +- **Logfiles:** automatically generated records of user activity. +- **Content data:** Person mentioned in text or shown in pictures. Those persons do not necessarily need to be a user. + +### A: Usage without user account + +Depending on the individual [permission](../../system-admin-guide/users-permissions/) and [authentication](../../system-admin-guide/authentication/) settings an OpenProject project can be accessed for read-only [anonymously](../../system-admin-guide/users-permissions/roles-permissions/#anonymous) without a user account. The [OpenProject community platform](https://community.openproject.org) is an example of an OpenProject installation where individual projects where set to public. + +Anonymity is not complete because the underlying webserver might still generate its common logfile (weblog). + +### B: User master data + +To sign-in to the OpenProject platform, the [registration of a user account](../../system-admin-guide/users-permissions/users/#create-users) is required. For registered user's the following personal data are processed: + +##### User profile (bu-01) + +- Name +- Username +- Avatar + +##### User settings (bu-02) + +- Email address +- Notification settings +- Email reminder settings +- Language settings +- Time zone settings +- Display settings (contrast modes, custom themes) + +##### User authentication (bu-03) + +* Access tokens +* User sessions +* Password (encrypted) +* Phone number for sending one-time passwords via SMS +* OATH secret codes + +##### User notification settings (bu-04) + +- Default notification settings +- Project-specific notification settings +- Default email reminder settings +- Project-specific email reminder settings + +##### User roles and permissions (bu-05) + +- Group memberships +- Project roles +- Global roles + +##### User rates (bu-06) + +* Default hourly rate +* Hourly rate per project + +**Note:** Administrators can add so-called [custom fields](../../system-admin-guide/custom-fields/) to their OpenProject installation which extend the data fields of a user. + +### C: Using OpenProject + +Depending on the individual use and permissions of the user the following personal data is processed: + +##### Boards (cb-01) + +- Assignment of a person to a work package (author, assignee, responsible, user custom fields) +- Change history +- Person mentioned in a board + +##### Budgets (cb-02) + +- Assignments of a person to a budget +- Change history +- Person mentioned in a budget description + +##### Comments (cc-01) + +- Author of a comment +- Change history +- Reactions of a user to a comment +- Person mentioned in a comment + +##### Documents (cd-01) + +- Assignment of a document to an uploader or creator +- Change history +- Person mentioned in a document (incl. file attributes) + +##### Email notifications (ce-01) + +- Email header including sender and recipients +- Person mentioned in an email + +##### Meetings (cm-01) + +- Assignment of a person (author, invitee, participant) to a meeting +- Change history +- Person mentioned in an agenda item + +##### Projects (cp-01) + +- Assignment of a person to a project (author, project member) + +- Change history + +- Person mentioned in a project overview + +- Person mentioned in a project attribute + +- Persons mentioned in a project status information + + +##### Project calendars (cp-02) + +- Assignment of objects shown in the calendar (meetings, work packages, versions, milestones) to a person +- Change history +- Person mentioned in a calendar item + +##### Project news (cp-03) + +- Author of a project news +- Change history +- Person mentioned in a project news + +##### Team planner (ct-01) + +- Assignment of a work package to a person +- Change history +- Persons mentioned in team planners + +##### Time tracking (ct-02) + +- Assignments of a time entry to a person +- Change history +- Person mentioned in a time entry + +##### Wiki pages (cw-01) + +- Assignment of an wiki page edit to a person (author, contributor) +- Change history +- Person mentioned in a wiki page + +##### Work packages (cw-02) + +- Assignment of a work package to a person +- Change history +- Person mentioned in a list or project schedule +- Person mentioned in an attributs or text field +- Person mentioned in a linked file +- Person mentioned in a linked pull request (i.e. GitHub) + + +### D: Logging + +#### Logged information + +Activities in OpenProject are automatically journalized. It allows users to understand the change history of those objects (e.g. the [baseline comparison](../../user-guide/work-packages/baseline-comparison/)). + +Independently of the change history every interaction (i.e. web request) of a browser or other client results in an entry written to the server logfiles. These files support the operation of the application as they provide information on faulty behavior of the system (i.e. bugs and lack of performance). + +Those log files contain the following person related data: +* id of the user performing the request +* time of the request +* url called +* parameters sent to the server as part of the request which comprises the user's input in the form of e.g. work package title and description, wiki page content, comment text, SAML user information etc. + +**Note:** Passwords are not logged in plain text. + +The data listed above is generated upon entering the application. When actually processing the request within the application, events deemed noteworthy by the developers might be logged additionally. An example of this are failed login attempts. + +#### Retention period + +Logfiles are automatically removed based on a first-in-first-out mechanism. This is done to limit the disk space which ensures the server's operation and at the same time serves as a means to erase the log entries once they have served their purpose of supporting operations. By default the retention period is determined by the size of the logfile. Once the logfile reaches its storage limit, the oldest entries are removed. + +As such, the log entries are not kept for a fixed period of time. If there are a lot of requests, old entries are removed faster then if there are less requests. Administrators of an OpenProject installation might decide to configure a different behaviour that factors in the age of the log entries. + +#### Technical documentation + +Detailed technical information about the logging mechanism can be found in the operations documentation: + +* [Monitoring your OpenProject installation](../../installation-and-operations/operation/monitoring/) + +> **Note:** Additional logfiles might be generated by systems that are part of the used network infrastructure (e.g., load balancers, proxying servers, or other network components). These are out of scope for this documentation but they often contain additional information such as the IP address. On the other hand, since TLS is employed for all connections by default, those intermediary systems do not have access to the full request body so they are not able to see for example the request parameters. + +## Flows of personal data + +### A: System overview + +The following diagram provides an overview of the flows of personal data in OpenProject. This applies to the different installation methods. + +```mermaid +%%{init: {'theme':'neutral'}}%% + +flowchart TD + browser[Web browser] -->|"HTTP(s) requests"| loadbalancer(Load balancer / proxy) + A1[Native client] -->|"HTTP(s) requests"| loadbalancer + A2[SVN or Git client] -->|"HTTP(s) requests"| loadbalancer + loadbalancer -->|Proxy| openproject + + subgraph openproject[OpenProject Core Application] + openprojectrailsapp[Rails application] + C[Puma app server] + D[Background worker] + end + + + subgraph integrations[External Integrations] + direction TB + idp["Identity provider (idp)"] + nex["Nextcloud (nex)"] + gih["GitHub (gih)"] + cal["Calendar (cal)"] + O["API integrations (api)"] + +end + + subgraph services[Internal Services] + direction TB + M[Memcached] + P[PostgreSQL] + S[Object storage or NFS] + email["Email gateways (eml)"] + end + + + openproject <--> services + openproject --> integrations + loadbalancer <--> integrations + + subgraph localclients[Local Client / User device] + direction TB + browser + A1 + A2 + + + + +end + + + + +``` + +As a web application, the primary data flow is between the user's web browser (or attached API clients) through an external proxying web server (this might be a load balancer or proxying server). Depending on the individual setup the proxying server is responsible for terminating TLS connections for the course of this document - although encrypted connections between Load balancer and Puma server are possible. In case of packaged or Kubernetes installations, this proxying server might be part of the OpenProject stack (e.g., an Apache2 packaged installation server or nginx ingress). + +The external web server acts as a proxy/reverse-proxy for the OpenProject Puma app server, relaying requests for it to handle and respond. In the course of the request, access to external services such as the PostgreSQL database, a caching server, or attached storages might be performed. In case of S3-compatible object storage set ups, OpenProject performs calls to the object storage to put or request files from it. Likewise, for network-attached storages linked into the application, underlying network requests are performed. These are out of scope for this evaluation, as they are provided and maintained by the operator of the system. + +In the course of using the application, background tasks are enqueued in the database such as outgoing emails, cleanup tasks, or notification processing. These tasks are performed in a separate process, the background worker queue. This process accesses the same services as the application server process to access or modify data. It might connect to external integrations such as a [Nextcloud](../../user-guide/nextcloud-integration/) instance to set up file sharings depending on actions performed by the users. + +**Exemplary request flow** + +- **User request**: An end-user sends an HTTPS request to the load balancer or proxying server. +- **Load balancer**: The external load balancer or proxying server receives the request, terminates TLS, and forwards the HTTP request to the Puma application server. +- **Puma app server**: Processes the request and invokes the appropriate Rails middlewares and controller. +- **Rails application**: + - Authenticates the user according to the mechanisms outlined in the [secure coding guidelines](../../development/concepts/secure-coding) + - Validates session and input data + - Responsible for error handling, logging, and auditing aggregation + + - Retrieves or updates resources to the PostgreSQL database via models + - Calls or interacts with external services for requests, such as retrieving files or attachments from object storage + + - Renders the appropriate views + - **Response**: Sends the HTTP response back through the Puma server and load balancer to the end-user. + +- **Background worker:** Operates on periodical background data, or performs actions requested by the web request of user (sending emails, exporting data, communicating with external services) + +### B: Identity provider (idp) + +#### Overview + +```mermaid +%%{init: {'theme':'neutral'}}%% +flowchart LR + Browser <-->|idp-01| IDP + IDP <-->|idp-02| openproject[OpenProject] + Browser <-->|idp-03| openproject + + subgraph IDP[Identity Provider] + direction LR + ssoprovider[SSO provider] + LDAP + + end + + subgraph openproject["Relying Party (OpenProject) "] + direction LR + ssoclient[SSO client] + ldapauthentication[LDAP authentication] + ldapgroupsync[LDAP group sync] + + end + + subgraph localclients[Local clients] + direction LR + Browser + end + +``` + +#### Purpose + +* Centralized identity and access management +* Single sign on and single sign out ([OIDC](../../system-admin-guide/authentication/openid-providers/), [SAML](../../system-admin-guide/authentication/saml/)) +* [Syncing LDAP groups with OpenProject groups](../../system-admin-guide/authentication/ldap-authentication/ldap-group-synchronization/) + +#### Processed data + +* `bu-01` +* `bu-02` +* `bu-03` +* `bu-05` (group memberships trough LDAP groups) + +#### Security measures + +* `idp-01` TLS +* `idp-02` TLS +* `idp-03` TLS + +### C: Email (eml) + +#### Overview + + +```mermaid +%%{init: {'theme':'neutral'}}%% + +flowchart LR + A[User's email client] <-->|eml-01| B[User's email hoster] + B <-->|eml-02| C[Email gateway] + C <-->|eml-03| D[Email notification service] + + + subgraph localclients[Local clients] + direction TB + A + end + + subgraph internal[Internal services] + direction TB + C + + end + + subgraph external[External services] + direction TB + A + B + end + + subgraph OpenProject + direction TB + D + end + + + + +``` + +#### Purpose + +* Create a new work package by sending an email to a configured email adress. +* Adding a comment to an existing work package by answering to an email notification. +* Sending email notifications about updates in OpenProject (e.g [email reminder](../../system-admin-guide/emails-and-notifications/), meeting updates, project invitation, wiki notifications) + +#### Processed data + +* `bu-01` +* `bu-04` +* `bu-05` +* `cc-01` +* `cm-01` +* `cp-01` +* `cw-02` + +#### Security measures + +* `eml-01` TLS (not controlled by the OpenProject system) + +* `eml-02` TLS (not controlled by the OpenProject system) + +* `eml-03` TLS (encryption can be activated in the email settings in the OpenProject Administration) + + **Note**: OpenProject does not support end-to-end encryption using GPG or S/MIME. + +### D: Calendar (cal) + +#### Overview + +```mermaid +%%{init: {'theme':'neutral'}}%% +flowchart LR + opicalapi[OpenProject's iCal API] --> |cal-01|B + B[Calendar web application] -->|cal-03| localcalendarapp[Local calendar application] + opicalapi -->|cal-02| localcalendarapp + + subgraph localclient[Local clients] + direction TB + localcalendarapp + end + + + subgraph external[External services] + direction TB + B + end + + subgraph OpenProject + direction TB + projectcalendar[Project calendar] --> opicalapi + end +``` + +#### Purpose + +* Users can import project calendars into their calendar application using the iCal format. + +#### Processed data + +* `bu-01` +* `bu-03 (iCalendar access tokens)` +* `cm-01` +* `cp-02` +* `ct-01` + +#### Security measures + +* `cal-01` TLS +* `cal-02` TLS (not controlled by the OpenProject system) +* `cal-03` TLS (not controlled by the OpenProject system) + +### E: Nextcloud (nex) + +#### Overview + +```mermaid +%%{init: {'theme':'neutral'}}%% +flowchart LR + Browser <--> |nex-01| openproject + Browser <-->|nex-02| nextcloud + nextclouddesktopclient[Nextcloud desktop client] <-->|nex-03| nextcloudapi + appopenprojectintegration <-->|nex-04| openprojectapi + + subgraph local[Local clients] + Browser + nextclouddesktopclient + end + +subgraph openproject[OpenProject] + + opnextcloudintegrattion[Nextcloud integration] + openprojectapi[API] + end + + subgraph nextcloud[Nextcloud] + groupfolder[Group folder app] + appopenprojectintegration[OpenProject integration app] + nextcloudapi[API] + end + +``` + +#### Purpose + +* Users can link files stored in Nextcloud with work package in OpenProject. +* Project folders in Nextcloud can be managed in OpenProject (create, delete, update, user permissions). + +#### Processed data + +* `bu-01` +* `bu-03 (iCalendar access tokens)` +* `cm-01` +* `cw-02` + +#### Security measures + +* `nex-01` TLS +* `nex-02` TLS +* `nex-03` TLS +* `nex-04` TLS + +### F: GitHub (gih) + +#### Overview + +```mermaid +%%{init: {'theme':'neutral'}}%% +flowchart LR + gitclient <-->|gih-01| githubapi + githubapi <-->|gih-02| opgithubintegration + githubwebhooks -->|gih-03| opgithubintegration + + subgraph GitHub + direction TB + githubapi[API] + githubwebhooks[Webhooks] + + end + + subgraph localclients[Local clients] + direction TB + gitclient[Git client] + end + + subgraph openproject[OpenProject] + direction TB + opgithubintegration[Github integration] --- workpackagesmodule[Work packages module] + end + + +``` + +#### Purpose + +- Connect pull requests in GitHub with work packages in OpenProject. +- Show the status of pull requests in related work packages. + +#### Processed data + +* cw-02 + +#### Security measure + +* `gih-01` TLS +* `gih-02` TLS +* `gih-03` TLS + +### G: API integrations (api) + +#### Overview + +```mermaid +%%{init: {'theme':'neutral'}}%% +flowchart LR + api <-->|api-01| apiintegration[API integration] + + subgraph externalintegreations[External integrations] + direction TB + apiintegration + end + + subgraph openproject[OpenProject] + direction TB + api[API] + end + + +``` + +#### Purpose + +- Create, read, update and delete data from OpenProject. + +#### Processed data + +* All data the user has permissions to. + +> **Note**: Please see the [API documentation](https://www.openproject.org/docs/api) for further information about all API endpoints. + +#### Security measure + +* `api-01` TLS + +## Use of technical cookies + +OpenProject makes use of technical cookies to identity the browser client and/or remember information such as 2FA login state. The core application makes use of these cookies: + +| **Cookie name** | **Description** | **Expiry** | **Security flags** | **Implementation** | +| ---------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ----------------------------------------------------- | ------------------------------------------------------------ | +| `_open_project_session` (name is configurable) | contains the information about the logged in user as well as information stored between requests on the user's choices (e.g. the filters for costs are in part stored there) | Session
+ configurable server-sideTTL | secure
httponly
Samesite=Lax
encrypted | [Code ref](https://github.com/opf/openproject/blob/release/13.0/config/initializers/session_store.rb#L34-L39) | +| `autologin` (name is configurable) | (Optional feature, requires opt-in under Administration > Authentication settings)
enables the user to automatically log in again after the session expired (e.g. because the browser was closed). It is set when the user checks the '*Stay logged in*' box in the login form.
| Cookie 1 year
+ server-side token N days (configurable) | secure
httponly
Samesite=Lax
encrypted | [Code ref](https://github.com/opf/openproject/blob/release/13.0/app/controllers/concerns/accounts/user_login.rb#L19C1-L29) | +| `op2fa_remember_token` | the presence of that cookie suppresses the need for the user to provide a second factor upon login for N days (configurable by administration) if the user selects to do so when entering the 2fa information. | N days (configurable) | secure
httponly
Samesite=Lax
encrypted | [Code ref](https://github.com/opf/openproject/blob/release/13.0/modules/two_factor_authentication/app/controllers/concerns/two_factor_authentication/remember_token.rb#L28-L34) | + +## Deletion of personal data + +Whenever a user in OpenProject is fully deleted, the system scrubs and removes all user master data, all functional assignments, and all references to a user in the change histories. All actions performed in the name of the user are being replaced with a singular "**Deleted user**" reference in order to maintain integrity of database references, such as being an author of a work package that remains. Finally, the user data itself will be deleted, removing all structural traces of PII in the system. + +**Note:** Due to the user references changing, respective cache keys for information such as work packages or projects are invalidated automatically. + +**Note:** Deleting a user account is a permanent action and cannot be reversed. + +For more information on user account deletion, please see [the user administration guide](../../system-admin-guide/users-permissions/users/#delete-users). + +**Note:** Input created by a user such as text or comments cannot be deleted or scrubbed in an automated fashion. The content stays but will be referenced to the non-personal "Deleted User". + +**Note:** Persons mentioned in text or shown in uploaded pictures cannot be deleted or scrubbed in an automated fashion. All references to persons in text or pictures need to be deleted either one by one or by deleting the project in total. Memory references in memcached might still refer to (invalidated) user data until it is being reassigned. + +**Note:** Logfiles might retain personal data for the configured retention period of the logfile. See "D: Logging" above. diff --git a/docs/development/security/README.md b/docs/security-and-privacy/statement-on-security/README.md similarity index 67% rename from docs/development/security/README.md rename to docs/security-and-privacy/statement-on-security/README.md index 27ec1066c6e0..4169b4cdeffb 100644 --- a/docs/development/security/README.md +++ b/docs/security-and-privacy/statement-on-security/README.md @@ -1,3 +1,11 @@ +--- +sidebar_navigation: + title: Statement on security + priority: 600 +description: Statement of data security in OpenProject +keywords: GDPR, data security, security, OpenProject security, security alerts, single sign-on, password security, mailing list +--- + # Statement on security At its core, OpenProject is an open-source software that is [developed and published on GitHub](https://github.com/opf/openproject). Every change to the OpenProject code base ends up in an open repository accessible to everyone. This results in a transparent software where every commit can be traced back to the contributor. @@ -6,6 +14,8 @@ Automated tests and manual code reviews ensure that these contributions are safe For more information on security and data privacy for OpenProject, please visit: [www.openproject.org/security-and-privacy](https://www.openproject.org/security-and-privacy/). + + ## Security announcements mailing list If you want to receive immediate security notifications via email as we publish them, please sign up to our security mailing list: https://www.openproject.org/security-and-privacy/#mailing-list. @@ -16,6 +26,29 @@ To unsubscribe, you will find a link at the end of every email. Any security related information will also be published on our [blog](https://www.openproject.org/blog/) and in the [release notes](../../release-notes/). + + +## Security advisory list + +OpenProject uses GitHub to manage and publish security advisory listings: https://github.com/opf/openproject/security/advisories + + + +## Security vulnerability processing + +When we receive vulnerability reports from researchers or through internal identification, the following process is taking place immediately: + +1. A security vulnerability is reported internally or through security@openproject.com (see below on how to disclose vulnerabilities responsibly). +2. A security engineer is receiving and validating the report. An internal tracking ticket is created with a checklist template on how to process the report. +3. The reporter receives a timely response with an acknowledgement of the report, further questions if present, and an estimated timeline and complexity of a potential fix. +4. The security engineer coordinates with the security and development team to prepare and test a fix for the report. +5. A GitHub advisory draft is created and a CVE is requested, if appropriate. Security researchers are invited to collaborate on the draft, if available. +6. A patch is returned to the reporter and awaited for confirmation unless fix is trivial +7. A patch release is created, published and distributed for all supported installations +8. The security vulnerability is publicly disclosed on GitHub and communicated through the mailing list + + + ## Reporting a vulnerability We take all facets of security seriously at OpenProject. If you want to report a security concerns, have remarks, or contributions regarding security at OpenProject, please reach out to us at [security@openproject.com](mailto:security@openproject.com). @@ -24,10 +57,13 @@ If you can, please send us a PGP-encrypted email using the following key: - Key ID: [0x7D669C6D47533958](https://keys.openpgp.org/vks/v1/by-fingerprint/BDCFE01EDE84EA199AE172CE7D669C6D47533958), - Fingerprint BDCF E01E DE84 EA19 9AE1 72CE 7D66 9C6D 4753 3958 -- You may also find the key [attached in our OpenProject repository.](https://github.com/opf/openproject/blob/dev/docs/development/security/security-at-openproject.com.asc) +- You may also find the key [attached in our OpenProject repository.](https://www.openproject.org/docs/security-and-privacy/statement-on-security/security-at-openproject.com.asc) Please include a description on how to reproduce the issue if possible. Our security team will get your email and will attempt to reproduce and fix the issue as soon as possible. +> **Please note:** OpenProject currently does not offer a bug bounty program. We will do our best to give you the appropriate credits for responsibly disclosing a security vulnerability to us. We will gladly reference your work, name, website on every publication we do related to the security update. + + ## OpenProject security features ### Authentication and password security diff --git a/docs/development/security/security-at-openproject.com.asc b/docs/security-and-privacy/statement-on-security/security-at-openproject.com.asc similarity index 100% rename from docs/development/security/security-at-openproject.com.asc rename to docs/security-and-privacy/statement-on-security/security-at-openproject.com.asc diff --git a/docs/user-guide/time-and-costs/progress-tracking/README.md b/docs/user-guide/time-and-costs/progress-tracking/README.md index ea1bb1d5238e..6b46c4e5bd6c 100644 --- a/docs/user-guide/time-and-costs/progress-tracking/README.md +++ b/docs/user-guide/time-and-costs/progress-tracking/README.md @@ -8,8 +8,8 @@ keywords: Progress tracking, cost reporting, earned value analysis, earned value # Progress tracking -You can track the completion of projects in OpenProject by assigning -a **Progress (%)** value to individual work packages. +You can track the completion of projects in OpenProject by assigning +a **Progress (%)** value to individual work packages. OpenProject will automatically roll-up progress to parent work packages. | Topic | Content | @@ -28,12 +28,12 @@ the default value of 0%. ![Work package progress field](progress-tracking-wp-field.png) -Clicking on the progress bar opens an in-place editor +Clicking on the progress bar opens an in-place editor that allows you to enter a percentage value between 0 and 100. ![Work package progress field with editor](progress-tracking-wp-field-editor.png) -Pressing enter saves the value and updates dependent work packages (see below). +Pressing enter saves the value and updates dependent work packages (see below). Progress is rounded to the next integer. ![Work package progress field with 50%](progress-tracking-wp-field-50perc.png) @@ -44,20 +44,20 @@ You can also bulk-modify the **Progress (%)** in the list of work packages. ## Progress tracking in the work package hierarchy -The progress of **work package with children** is calculated as the -weighted average of all direct children, using the field **Estimated time** -as the weight. -When adding the **Progress(%)** column to a work -package hierarchy view, please also add the **Estimated time** +The progress of **work package with children** is calculated as the +weighted average of all direct children, using the field **Estimated time** +as the weight. +When adding the **Progress(%)** column to a work +package hierarchy view, please also add the **Estimated time** column as well so that you can track the calculation. -The screenshot below shows an example hierarchy with aggregated +The screenshot below shows an example hierarchy with aggregated **Progress (%)**. -Please note the **Estimated time** column to the right. -Here, values in parenthesis (for example “(40h)” of Main Task) -indicate estimated time from children, while values without -parenthesis refer to estimated time directly assigned to a work -package. +Please note the **Estimated time** column to the right. +Here, values in parenthesis (for example “(40h)” of Main Task) +indicate estimated time from children, while values without +parenthesis refer to estimated time directly assigned to a work +package. ![Progress calculation in the WP hierarchy](progress-tracking-hierarchy-progress.png) @@ -68,28 +68,28 @@ Calculation examples: ## Status-based progress tracking -As an alternative to the manual progress tracking mode above, you can configure +As an alternative to the manual progress tracking mode above, you can configure your OpenProject system to associate work packages statuses . -In the Administration, please navigate to Work packages -> Settings and change “Calculate the work package done ratio” to +In the Administration, please navigate to Work packages -> Settings and change “Calculate the work package done ratio” to “Use the work package status”. ![Change calculate the work package done ration](image-20221102110738283.png) -In this mode, OpenProject does _not_ allow you to manually modify the +In this mode, OpenProject does _not_ allow you to manually modify the **Progress (%)** field in the work packages. -Instead, the **Progress (%)** value will be set automatically based on the the work package +Instead, the **Progress (%)** value will be set automatically based on the work package status configuration page. Within the Administration, navigate to Work package -> Status and select the status you want to edit regarding the progress tracking. Here you can select the desired progress percentage from the drop-down menu in the progress line and add it to the status. Please do not forget to save your changes. ![Progress calculation in the WP hierarchy](progress-tracking-admin-status-percentage.png) -The screenshot above shows a sample configuration of work package -statuses together with suitable “Progress (%)” values. -For example, setting the status of a work package to “In progress” +The screenshot above shows a sample configuration of work package +statuses together with suitable “Progress (%)” values. +For example, setting the status of a work package to “In progress” is equivalent to setting **Progress (%)** to 50% manually. -Note: The status and it’s associated progress value from the -administration screen also determines the **Progress (%)** of -work packages with children. So there is no roll-up of progress +Note: The status and it’s associated progress value from the +administration screen also determines the **Progress (%)** of +work packages with children. So there is no roll-up of progress in the work package table hierarchy in this configuration. diff --git a/docs/user-guide/wysiwyg/README.md b/docs/user-guide/wysiwyg/README.md index 8c5f61e618af..b42f7ae7b982 100644 --- a/docs/user-guide/wysiwyg/README.md +++ b/docs/user-guide/wysiwyg/README.md @@ -151,6 +151,8 @@ As with the textile formatting syntax, you can link to other resources within Op To avoid processing these items, preceding them with a bang `!` character such as `!#12` will prevent linking to a work package with ID 12. +> **Please note**: All these macros need to be written as a new word (i.e., with at least one space before it or at the beginning of a paragraph/sentence. Macros contained within a word such as `somethingmeeting#4` will not be parsed. + ### Autocompletion for work packages and users @@ -185,7 +187,7 @@ You can also embed attribute values and [their help texts](../../system-admin-gu The following lists show the supported attributes for work packages and projects. -> **Please note**: If you are using a different language than, English a translation of the commands can only be used in the text editor if all user languages (of all useres) of an instance are set to the same language (for example: German). In this case, only the attribute to which the command refers is translated, e.g. (`workPackageValue:1234:"translated attribute"`). +> **Please note**: If you are using a language different than English, a translation of the commands can only be used in the text editor if the language of all the users of an instance is set to the same language (for example German). In this case, only the attribute to which the command refers is translated, e.g. (`workPackageValue:1234:"translated attribute"`). We recommend against using translated attributes, as they might break in future versions due to fixes or changes to texts. ### Available attributes for work packages diff --git a/frontend/src/app/features/calendar/op-calendar.service.ts b/frontend/src/app/features/calendar/op-calendar.service.ts index 490f456139f4..a9f58521b61f 100644 --- a/frontend/src/app/features/calendar/op-calendar.service.ts +++ b/frontend/src/app/features/calendar/op-calendar.service.ts @@ -35,8 +35,9 @@ export class OpCalendarService extends UntilDestroyedMixin { } applyNonWorkingDay({ date }:{ date?:Date }, nonWorkingDays:IDay[]):string[] { - const formatted = moment(date).format('YYYY-MM-DD'); - if (date && (this.weekdayService.isNonWorkingDay(date) || nonWorkingDays.find((el) => el.date === formatted))) { + const utcDate = moment(date).utc(); + const formatted = utcDate.format('YYYY-MM-DD'); + if (date && (this.weekdayService.isNonWorkingDay(utcDate) || nonWorkingDays.find((el) => el.date === formatted))) { return ['fc-non-working-day']; } return []; diff --git a/frontend/src/app/features/calendar/te-calendar/te-calendar.component.ts b/frontend/src/app/features/calendar/te-calendar/te-calendar.component.ts index 6ea5a4779261..89ddff84c6a4 100644 --- a/frontend/src/app/features/calendar/te-calendar/te-calendar.component.ts +++ b/frontend/src/app/features/calendar/te-calendar/te-calendar.component.ts @@ -123,7 +123,7 @@ export class TimeEntryCalendarComponent { public scaleRatio = 1; - protected memoizedTimeEntries:{ start:Date, end:Date, entries:Promise> }; + protected memoizedTimeEntries:{ start:Moment, end:Moment, entries:Promise> }; public memoizedCreateAllowed = false; @@ -216,7 +216,9 @@ export class TimeEntryCalendarComponent { successCallback:(events:EventInput[]) => void, failureCallback:(error:Error) => void, ):void|PromiseLike { - void this.fetchTimeEntries(fetchInfo.start, fetchInfo.end) + const start = moment(fetchInfo.startStr); + const end = moment(fetchInfo.endStr); + void this.fetchTimeEntries(start, end) .then(async (collection) => { this.entries.emit(collection); @@ -225,10 +227,10 @@ export class TimeEntryCalendarComponent { .catch(failureCallback); } - protected fetchTimeEntries(start:Date, end:Date):Promise> { + protected fetchTimeEntries(start:Moment, end:Moment):Promise> { if (!this.memoizedTimeEntries - || this.memoizedTimeEntries.start.getTime() !== start.getTime() - || this.memoizedTimeEntries.end.getTime() !== end.getTime()) { + || this.memoizedTimeEntries.start.valueOf() !== start.valueOf() + || this.memoizedTimeEntries.end.valueOf() !== end.valueOf()) { const promise = firstValueFrom( this .apiV3Service @@ -388,9 +390,9 @@ export class TimeEntryCalendarComponent { }; } - protected dmFilters(start:Date, end:Date):Array<[string, FilterOperator, string[]]> { - const startDate = moment(start).format('YYYY-MM-DD'); - const endDate = moment(end).subtract(1, 'd').format('YYYY-MM-DD'); + protected dmFilters(start:Moment, end:Moment):Array<[string, FilterOperator, string[]]> { + const startDate = start.format('YYYY-MM-DD'); + const endDate = end.subtract(1, 'd').format('YYYY-MM-DD'); return [['spentOn', '<>d', [startDate, endDate]] as [string, FilterOperator, string[]], ['user_id', '=', ['me']] as [string, FilterOperator, [string]]]; } @@ -399,7 +401,7 @@ export class TimeEntryCalendarComponent { if (event.event.extendedProps.entry) { this.editEvent(event.event.extendedProps.entry); } else if (event.el.classList.contains(ADD_ENTRY_CLASS_NAME) && !event.el.classList.contains(ADD_ENTRY_PROHIBITED_CLASS_NAME)) { - this.addEvent(moment(event.event.start)); + this.addEvent(moment(event.event.startStr)); } } @@ -420,7 +422,7 @@ export class TimeEntryCalendarComponent { // Use end instead of start as when dragging, the event might be too long and would thus be start // on the day before by fullcalendar. - entry.spentOn = moment(event.event.end).format('YYYY-MM-DD'); + entry.spentOn = moment(event.event.endStr).format('YYYY-MM-DD'); void this .schemaCache diff --git a/frontend/src/app/features/work-packages/components/wp-card-view/wp-single-card/wp-single-card.component.sass b/frontend/src/app/features/work-packages/components/wp-card-view/wp-single-card/wp-single-card.component.sass index 01923709bd3f..698f601b2e14 100644 --- a/frontend/src/app/features/work-packages/components/wp-card-view/wp-single-card/wp-single-card.component.sass +++ b/frontend/src/app/features/work-packages/components/wp-card-view/wp-single-card/wp-single-card.component.sass @@ -121,6 +121,7 @@ &-cover-image grid-area: image max-height: 350px + justify-self: center @media screen and (max-width: $breakpoint-sm) max-height: 250px diff --git a/frontend/src/global_styles/layout/_toolbar.sass b/frontend/src/global_styles/layout/_toolbar.sass index a62f039a0ce9..429c7259c5af 100644 --- a/frontend/src/global_styles/layout/_toolbar.sass +++ b/frontend/src/global_styles/layout/_toolbar.sass @@ -87,6 +87,7 @@ $nm-color-success-background: #d8fdd1 flex-wrap: wrap margin: 0 -10px 0 0 padding: 0 + justify-content: space-between li list-style-type: none diff --git a/lib/open_project/version.rb b/lib/open_project/version.rb index 50e0f4b62947..ee0e9596b6d2 100644 --- a/lib/open_project/version.rb +++ b/lib/open_project/version.rb @@ -33,7 +33,7 @@ module OpenProject module VERSION # :nodoc: MAJOR = 13 MINOR = 0 - PATCH = 7 + PATCH = 8 class << self # Used by semver to define the special version (if any). diff --git a/modules/avatars/config/locales/crowdin/js-sr.yml b/modules/avatars/config/locales/crowdin/js-sr.yml index ed64bba3a0cf..c3c03636c6eb 100644 --- a/modules/avatars/config/locales/crowdin/js-sr.yml +++ b/modules/avatars/config/locales/crowdin/js-sr.yml @@ -1,15 +1,15 @@ #English strings go here sr: js: - label_preview: 'Pregled' - button_update: 'Ažuriranje' + label_preview: 'Prikaži' + button_update: 'Ažuriraj' avatars: - label_choose_avatar: "Choose Avatar from file" - uploading_avatar: "Uploading your avatar." + label_choose_avatar: "Izaberi avatar kao datoteku" + uploading_avatar: "Postavite avatar." text_upload_instructions: | - Upload your own custom avatar of 128 by 128 pixels. Larger files will be resized and cropped to match. - A preview of your avatar will be shown before uploading, once you selected an image. - error_image_too_large: "Image is too large." - wrong_file_format: "Allowed formats are jpg, png, gif" - empty_file_error: "Please upload a valid image (jpg, png, gif)" + Postavite svoj lični avatar, dimenzije: 128x128 piksela. Veće datoteke će biti isečene na traženu dimenziju. + Avatar će vam biti prikazan, pre postavljanja, onda kada budete izabrali željenu sliku. + error_image_too_large: "Slika je prevelika." + wrong_file_format: "Dozvoljeni formati su: jpg, png, gif" + empty_file_error: "Postavite ispravnu sliku (jpg, png, gif)" diff --git a/modules/avatars/config/locales/crowdin/sr.yml b/modules/avatars/config/locales/crowdin/sr.yml index f0196f2375fa..1b34333da5d9 100644 --- a/modules/avatars/config/locales/crowdin/sr.yml +++ b/modules/avatars/config/locales/crowdin/sr.yml @@ -5,37 +5,37 @@ sr: description: >- This plugin allows OpenProject users to upload a picture to be used as an avatar or use registered images from Gravatar. label_avatar: "Avatar" - label_avatar_plural: "Avatars" - label_current_avatar: "Current Avatar" - label_choose_avatar: "Choose Avatar from file" - message_avatar_uploaded: "Avatar changed successfully." - error_image_upload: "Error saving the image." - error_image_size: "The image is too large." - button_change_avatar: "Change avatar" - are_you_sure_delete_avatar: "Are you sure you want to delete your avatar?" - avatar_deleted: "Avatar deleted successfully." - unable_to_delete_avatar: "Avatar could not be deleted." - wrong_file_format: "Allowed formats are jpg, png, gif" - empty_file_error: "Please upload a valid image (jpg, png, gif)" + label_avatar_plural: "Avatari" + label_current_avatar: "Trenutni Avatar" + label_choose_avatar: "Izaberite Avatar iz sopstvene datoteke" + message_avatar_uploaded: "Avatar je uspešno promenjen." + error_image_upload: "Greška prilikom čuvanja slike." + error_image_size: "Slika je prevelika." + button_change_avatar: "Promenite avatar" + are_you_sure_delete_avatar: "Da li ste sigurni da želite da obrišete svoj avatar?" + avatar_deleted: "Avatar je uspešno obrisan." + unable_to_delete_avatar: "Avatar nije moguće obrisati." + wrong_file_format: "Dozvoljeni formati su: jpg, png, gif" + empty_file_error: "Molim vas postavite sliku u ispravnom formatu (jpg, png, gif)" avatars: label_avatar: "Avatar" label_gravatar: 'Gravatar' - label_current_avatar: 'Current avatar' - label_local_avatar: 'Custom avatar' + label_current_avatar: 'Trenutni avatar' + label_local_avatar: 'Prilagođeni avatar' text_current_avatar: | - The following image shows the current avatar. + Sledeća slika prikazuje tekući avatar. text_upload_instructions: | - Upload your own custom avatar of 128 by 128 pixels. Larger files will be resized and cropped to match. - A preview of your avatar will be shown before uploading, once you selected an image. - text_change_gravatar_html: 'To change or add the Gravatar for your mail address, go to %{gravatar_url}.' + Postavite svoj lični avatar, dimenzije: 128x128 piksela. Veće datoteke će biti isečene na traženu dimenziju. + Avatar će vam biti prikazan, pre postavljanja, onda kada budete izabrali željenu sliku. + text_change_gravatar_html: 'Za dodavanje Gravatar-a adrese vaše elektronske pošte idite na %{gravatar_url}.' text_your_local_avatar: | - OpenProject allows you to upload your own custom avatar. + OpenProject ti dozvoljava da postaviš lični avatar prilagođen sebi. text_local_avatar_over_gravatar: | - If you set one, this custom avatar is used in precedence over the gravatar above. + Ukoliko postavite jedan, prilagođeni avatar ima prednost u odnosu na ponuđeni gravatar iznad. text_your_current_gravatar: | - OpenProject uses your gravatar if you registered one, or a default image or icon if one exists. - The current gravatar is as follows: + OpenProject koristi tvoj gravatar, ukoliko ste registrovali jedna, ili podrazumevanu sliku ili ikonu ako ona postoji. + Trenutni gravatar je: settings: - enable_gravatars: 'Enable user gravatars' - gravatar_default: "Default Gravatar image" - enable_local_avatars: 'Enable user custom avatars' + enable_gravatars: 'Omogućite gravatare korisnika' + gravatar_default: "Podrazumevana Gravatar slika" + enable_local_avatars: 'Omogući prilagođene avatare za korisnike' diff --git a/modules/avatars/config/locales/crowdin/uk.yml b/modules/avatars/config/locales/crowdin/uk.yml index 3bea9fe758fb..0b722fc2bfb0 100644 --- a/modules/avatars/config/locales/crowdin/uk.yml +++ b/modules/avatars/config/locales/crowdin/uk.yml @@ -3,7 +3,7 @@ uk: plugin_openproject_avatars: name: "Аватари" description: >- - This plugin allows OpenProject users to upload a picture to be used as an avatar or use registered images from Gravatar. + Цей плагін дозволяє користувачам OpenProject завантажувати зображення для використання як аватара або використовувати наявні зображення з Gravatar. label_avatar: "Аватар" label_avatar_plural: "Аватари" label_current_avatar: "Поточний аватар" diff --git a/modules/backlogs/config/locales/crowdin/js-ka.yml b/modules/backlogs/config/locales/crowdin/js-ka.yml index 39c062e831c1..e2a3bcd451e3 100644 --- a/modules/backlogs/config/locales/crowdin/js-ka.yml +++ b/modules/backlogs/config/locales/crowdin/js-ka.yml @@ -23,5 +23,5 @@ ka: js: work_packages: properties: - storyPoints: "Story Points" - remainingTime: "Remaining hours" + storyPoints: "ისტორიული წერტილები" + remainingTime: "დარჩენილია საათები" diff --git a/modules/backlogs/config/locales/crowdin/js-sr.yml b/modules/backlogs/config/locales/crowdin/js-sr.yml index 4694282f916d..5c8758342da5 100644 --- a/modules/backlogs/config/locales/crowdin/js-sr.yml +++ b/modules/backlogs/config/locales/crowdin/js-sr.yml @@ -23,5 +23,5 @@ sr: js: work_packages: properties: - storyPoints: "Story Points" - remainingTime: "Remaining hours" + storyPoints: "Poeni Priče" + remainingTime: "Preostalo časova" diff --git a/modules/backlogs/config/locales/crowdin/sr.yml b/modules/backlogs/config/locales/crowdin/sr.yml index 2078b321d724..126f336fe6fa 100644 --- a/modules/backlogs/config/locales/crowdin/sr.yml +++ b/modules/backlogs/config/locales/crowdin/sr.yml @@ -26,66 +26,66 @@ sr: activerecord: attributes: work_package: - position: "Position" - remaining_hours: "Remaining hours" - remaining_time: "Remaining hours" + position: "Pozicija" + remaining_hours: "Preostalo časova" + remaining_time: "Preostalo časova" derived_remaining_hours: "Derived remaining hours" derived_remaining_time: "Derived remaining hours" - story_points: "Story Points" - backlogs_work_package_type: "Backlog type" + story_points: "Poeni Priče" + backlogs_work_package_type: "Tip backlog-a" 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." - must_block_at_least_one_work_package: "must contain the ID of at least one ticket." + can_only_contain_work_packages_of_current_sprint: "Može sadržati samo ID radnog paketa iz tekućeg sprint-a." + must_block_at_least_one_work_package: "mora sadržati ID bar jednog tiketa." version_id: - task_version_must_be_the_same_as_story_version: "must be the same as the parent story's version." + task_version_must_be_the_same_as_story_version: "mora biti ista kao verzija priče roditelja." sprint: - cannot_end_before_it_starts: "Sprint cannot end before it starts." + cannot_end_before_it_starts: "Sprint se ne može završiti pre nego što počne." backlogs: - add_new_story: "New Story" - any: "any" - backlog_settings: "Backlogs settings" - burndown_graph: "Burndown Graph" - card_paper_size: "Paper size for card printing" - chart_options: "Chart options" - close: "Close" - column_width: "Column width:" - date: "Day" - definition_of_done: "Definition of Done" - generating_chart: "Generating Graph..." - hours: "Hours" - impediment: "Impediment" - label_versions_default_fold_state: "Show versions folded" - work_package_is_closed: "Work package is done, when" - label_is_done_status: "Status %{status_name} means done" - no_burndown_data: "No burndown data available. It is necessary to have the sprint start- and end dates set." - points: "Points" - positions_could_not_be_rebuilt: "Positions could not be rebuilt." - positions_rebuilt_successfully: "Positions rebuilt successfully." - properties: "Properties" - rebuild: "Rebuild" - rebuild_positions: "Rebuild positions" - remaining_hours: "Remaining hours" - remaining_hours_ideal: "Remaining hours (ideal)" - show_burndown_chart: "Burndown Chart" - story: "Story" - story_points: "Story Points" - story_points_ideal: "Story Points (ideal)" - task: "Task" - task_color: "Task color" - unassigned: "Unassigned" - x_more: "%{count} more..." - backlogs_active: "active" - backlogs_any: "any" - backlogs_inactive: "Project shows no activity" - backlogs_points_burn_direction: "Points burn up/down" - backlogs_product_backlog: "Product backlog" - backlogs_product_backlog_is_empty: "Product backlog is empty" - backlogs_product_backlog_unsized: "The top of the product backlog has unsized stories" - backlogs_sizing_inconsistent: "Story sizes vary against their estimates" + add_new_story: "Nova Priča" + any: "bilo koji" + backlog_settings: "Podešavanja backlog-a" + burndown_graph: "Burndown grafik" + card_paper_size: "Format papira za štampanje kartica" + chart_options: "Opcije grafikona" + close: "Zatvori" + column_width: "Širina kolone:" + date: "Dan" + definition_of_done: "Definicija završetka" + generating_chart: "Generisanje Grafika..." + hours: "Časovi" + impediment: "Smetnja" + label_versions_default_fold_state: "Prikaži verzije skupljene" + work_package_is_closed: "Radni paket je završen, kada" + label_is_done_status: "Status %{status_name} znači završen" + no_burndown_data: "Nema dostupnih burndown podataka. Potrebno je zadati datum početka i kraja sprint-a." + points: "Poeni" + positions_could_not_be_rebuilt: "Pozicije ne mogu biti rekonstruisane." + positions_rebuilt_successfully: "Rekonstrukcija pozicija je uspešna." + properties: "Svojstva" + rebuild: "Rekonstrukcija" + rebuild_positions: "Rekonstruiši pozicije" + remaining_hours: "Preostalo časova" + remaining_hours_ideal: "Preostalo časova (idealno)" + show_burndown_chart: "Burndown grafik" + story: "Priča" + story_points: "Poeni Priče" + story_points_ideal: "Poeni Priče (idealno)" + task: "Zadatak" + task_color: "Boja zadatka" + unassigned: "Nedodeljen" + x_more: "%{count} više..." + backlogs_active: "aktivno" + backlogs_any: "bilo koji" + backlogs_inactive: "Projekat ne pokazuje aktivnosti" + backlogs_points_burn_direction: "burn up/down poeni" + backlogs_product_backlog: "Backlog proizvoda" + backlogs_product_backlog_is_empty: "Backlog proizvoda je prazan" + backlogs_product_backlog_unsized: "Vrh backlog-a proizvoda ima nedefinisane priče" + backlogs_sizing_inconsistent: "Veličine priča variraju u odnosu na njihove procene" backlogs_sprint_notes_missing: "Closed sprints without retrospective/review notes" backlogs_sprint_unestimated: "Closed or active sprints with unestimated stories" backlogs_sprint_unsized: "Project has stories on active or recently closed sprints that were not sized" diff --git a/modules/bim/config/locales/crowdin/ar.yml b/modules/bim/config/locales/crowdin/ar.yml index 000d11506aae..ca14d5947ad0 100644 --- a/modules/bim/config/locales/crowdin/ar.yml +++ b/modules/bim/config/locales/crowdin/ar.yml @@ -17,6 +17,7 @@ ar: exceptions: file_invalid: "ملف BCF غير صالح" x_bcf_issues: + zero: 'لا توجد مشاكل BCF' one: 'One BCF issue' other: '%{count} BCF issues' bcf_xml: diff --git a/modules/bim/config/locales/crowdin/ca.seeders.yml b/modules/bim/config/locales/crowdin/ca.seeders.yml index c8925f33aaea..5ea8d781f254 100644 --- a/modules/bim/config/locales/crowdin/ca.seeders.yml +++ b/modules/bim/config/locales/crowdin/ca.seeders.yml @@ -410,11 +410,11 @@ ca: item_0: title: Benvingut al teu projecte de demostració summary: | - Estem contents que t'hagis unit. - En aquest mòdul pots comunicar notícies del projecte a nous membres de l'equip. + Estem contents que us hàgiu unit. + En aquest mòdul podeu comunicar notícies del projecte als nous membres de l'equip. description: Les notícies actuals categories: - item_0: Categoria 1 (per ser canviat en la configuració del projecte) + item_0: Categoria 1 (per ser canviada en la configuració del projecte) queries: item_0: name: Pla de projecte diff --git a/modules/bim/config/locales/crowdin/ka.seeders.yml b/modules/bim/config/locales/crowdin/ka.seeders.yml index 1aeace505916..c7b2d99d8a77 100644 --- a/modules/bim/config/locales/crowdin/ka.seeders.yml +++ b/modules/bim/config/locales/crowdin/ka.seeders.yml @@ -18,16 +18,16 @@ ka: item_0: name: ახალი item_1: - name: In progress + name: მიმდინარეობს item_2: name: შესრულებულია item_3: name: დახურულია time_entry_activities: item_0: - name: Management + name: მართვა item_1: - name: Specification + name: სპეციფიკაცია item_2: name: სხვა types: @@ -55,17 +55,17 @@ ka: group_name: შვილები groups: item_0: - name: Architects + name: არქიტექტორები item_1: name: BIM Coordinators item_2: - name: BIM Managers + name: BIM მმართველები item_3: name: BIM Modellers item_4: name: Lead BIM Coordinators item_5: - name: MEP Engineers + name: MEP ინჟინრები item_6: name: მგეგმავები item_7: @@ -101,13 +101,13 @@ ka: item_0: Category 1 (to be changed in Project settings) queries: item_0: - name: Project plan + name: პროექტის გეგმა item_1: - name: Milestones + name: ნიშანსვეტები item_2: name: ამოცანები item_3: - name: Team planner + name: გუნდის მგეგმავი boards: bcf: name: Simple drag'n drop workflow @@ -144,10 +144,10 @@ ka: name: წევრები item_5: options: - name: Work packages + name: სამუშაო პაკეტები item_6: options: - name: Milestones + name: ნიშანსვეტები demo-planning-constructing-project: name: "(Demo) Planning & constructing" status_explanation: All tasks are on schedule. The people involved know their tasks. The system is completely set up. @@ -163,13 +163,13 @@ ka: item_0: Category 1 (to be changed in Project settings) queries: item_0: - name: Project plan + name: პროექტის გეგმა item_1: - name: Milestones + name: ნიშანსვეტები item_2: name: ამოცანები item_3: - name: Team planner + name: გუნდის მგეგმავი project-overview: widgets: item_0: @@ -199,10 +199,10 @@ ka: name: წევრები item_5: options: - name: Work packages + name: სამუშაო პაკეტები item_6: options: - name: Milestones + name: ნიშანსვეტები work_packages: item_0: subject: Project kick off construction project @@ -321,7 +321,7 @@ ka: * Get the team together * ... item_1: - subject: Foundation + subject: საფუძველი description: |- ## Goal @@ -417,13 +417,13 @@ ka: item_0: Category 1 (to be changed in Project settings) queries: item_0: - name: Project plan + name: პროექტის გეგმა item_1: - name: Milestones + name: ნიშანსვეტები item_2: name: ამოცანები item_3: - name: Team planner + name: გუნდის მგეგმავი project-overview: widgets: item_0: @@ -456,10 +456,10 @@ ka: name: წევრები item_5: options: - name: Work packages + name: სამუშაო პაკეტები item_6: options: - name: Milestones + name: ნიშანსვეტები work_packages: item_0: subject: Project kick off creating BIM model @@ -690,16 +690,16 @@ ka: item_3: name: შენიშვნები item_4: - name: Project plan + name: პროექტის გეგმა item_5: - name: Milestones + name: ნიშანსვეტები item_6: name: ამოცანები item_7: - name: Team planner + name: გუნდის მგეგმავი boards: bcf: - name: BCF issues + name: BCF-ის პრობლემები project-overview: widgets: item_0: @@ -731,4 +731,4 @@ ka: name: წევრები item_5: options: - name: Work packages + name: სამუშაო პაკეტები diff --git a/modules/bim/config/locales/crowdin/tr.seeders.yml b/modules/bim/config/locales/crowdin/tr.seeders.yml index bae32d6aaab6..85734e3c2e88 100644 --- a/modules/bim/config/locales/crowdin/tr.seeders.yml +++ b/modules/bim/config/locales/crowdin/tr.seeders.yml @@ -13,14 +13,14 @@ tr: item_2: name: Yüksek item_3: - name: Critical + name: Kritik statuses: item_0: name: Yeni item_1: name: Devam eden item_2: - name: Resolved + name: Çözüldü item_3: name: Kapalı time_entry_activities: @@ -101,11 +101,11 @@ tr: item_0: Category 1 (to be changed in Project settings) queries: item_0: - name: Project plan + name: Proje planı item_1: name: Milestones item_2: - name: Tasks + name: Görevler item_3: name: Takım planlayıcısı boards: @@ -115,7 +115,7 @@ tr: widgets: item_0: options: - name: Welcome + name: Hoş geldiniz item_1: options: name: Başlarken diff --git a/modules/boards/config/locales/crowdin/el.yml b/modules/boards/config/locales/crowdin/el.yml index 46bb2956864d..8cf608a5f64c 100644 --- a/modules/boards/config/locales/crowdin/el.yml +++ b/modules/boards/config/locales/crowdin/el.yml @@ -9,8 +9,8 @@ el: boards: label_board: "Πίνακας" label_boards: "Πίνακες" - label_create_new_board: "Create new board" - label_board_type: "Board type" + label_create_new_board: "Δημιουργία νέου πίνακα" + label_board_type: "Τύπος πίνακα" board_types: free: Βασικό action: "Πίνακας ενεργειών (%{attribute})" @@ -23,9 +23,9 @@ el: basic: Βασικό board_type_descriptions: basic: > - Start from scratch with a blank board. Manually add cards and columns to this board. + Ξεκινήστε από την αρχή με έναν κενό πίνακα. Προσθέστε χειροκίνητα κάρτες και στήλες σε αυτόν τον πίνακα. status: > - Basic kanban style board with columns for status such as To Do, In Progress, Done. + Βασικός πίνακας τύπου kanban με στήλες για την κατάσταση, όπως To Do, In Progress, Done. assignee: > Board with automated columns based on assigned users. Ideal for dispatching work packages. version: > @@ -36,4 +36,4 @@ el: Board with automated columns for sub-elements. Dragging work packages to other lists updates the parent accordingly. 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.' - upgrade: 'Upgrade now' + upgrade: 'Αναβάθμιση τώρα' diff --git a/modules/boards/config/locales/crowdin/ja.yml b/modules/boards/config/locales/crowdin/ja.yml index 88ee03a3319e..49c3edd07f77 100644 --- a/modules/boards/config/locales/crowdin/ja.yml +++ b/modules/boards/config/locales/crowdin/ja.yml @@ -9,8 +9,8 @@ ja: boards: label_board: "ボード" label_boards: "ボード" - label_create_new_board: "Create new board" - label_board_type: "Board type" + label_create_new_board: "新しいボードを作成" + label_board_type: "ボードの種類" board_types: free: 基本 action: "アクションボード (%{attribute})" diff --git a/modules/boards/config/locales/crowdin/js-sr.yml b/modules/boards/config/locales/crowdin/js-sr.yml index c2d4f7e06550..16744793f0ba 100644 --- a/modules/boards/config/locales/crowdin/js-sr.yml +++ b/modules/boards/config/locales/crowdin/js-sr.yml @@ -2,85 +2,85 @@ sr: js: boards: - create_new: 'Create new board' - label_unnamed_board: 'Unnamed board' - label_unnamed_list: 'Unnamed list' - label_board_type: 'Board type' + create_new: 'Nova tabla' + label_unnamed_board: 'Neimenovana tabla' + label_unnamed_list: 'Neimenovana lista' + label_board_type: 'Tip table' 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.' - upgrade: 'Upgrade now' + upgrade: 'Nadogradite' lists: - delete: 'Delete list' + delete: 'Obriši listu' version: - is_locked: 'Version is locked. No items can be added to this version.' - is_closed: 'Version is closed. No items can be added to this version.' - close_version: 'Close version' - open_version: 'Open version' - lock_version: 'Lock version' - unlock_version: 'Unlock version' - edit_version: 'Edit version' - show_version: 'Show version' - locked: 'Locked' - closed: 'Closed' - new_board: 'New board' - add_list: 'Add list to board' - add_card: 'Add card' - error_attribute_not_writable: "Cannot move the work package, %{attribute} is not writable." - error_loading_the_list: "Error loading the list: %{error_message}" - error_permission_missing: "The permission to create public queries is missing" - error_cannot_move_into_self: "You can not move a work package into its own column." - text_hidden_list_warning: "Not all lists are displayed because you lack the permission. Contact your admin for more information." - click_to_remove_list: "Click to remove this list" + is_locked: 'Verzija je zaključana. U ovu verziju nije moguće dodavati stavke.' + is_closed: 'Verzija je zatvorena. U ovu verziju nije moguće dodavati stavke.' + close_version: 'Zatvori verziju' + open_version: 'Otvori verziju' + lock_version: 'Zaključaj verziju' + unlock_version: 'Otključaj verziju' + edit_version: 'Uredi verziju' + show_version: 'Prikaži verziju' + locked: 'Zaključano' + closed: 'Zatvoreno' + new_board: 'Nova tabla' + add_list: 'Dodaj listu na tablu' + add_card: 'Dodaj karticu' + error_attribute_not_writable: "Radni paket nije moguće premestiti, %{attribute} nije upisiv." + error_loading_the_list: "Greška pri učitavanju liste: %{error_message}" + error_permission_missing: "Nemate dozvolu za kreiranje javnih upita" + error_cannot_move_into_self: "Nemožeta premestiti radni paket u izdvojenu kolonu" + text_hidden_list_warning: "Nemate dovoljno privilegija za prikaz svih lista. Za više informacija kontaktirajte vašeg administratora." + click_to_remove_list: "Klikni da ukloniš ovu listu" board_type: - text: 'Board type' - free: 'basic' - select_board_type: 'Please choose the type of board you need.' + text: 'Tip table' + free: 'osnovno' + select_board_type: 'Izaberite tip table.' free_text: > - Start from scratch with a blank board. Manually add cards and columns to this board. - action: 'Action board' - action_by_attribute: 'Action board (%{attribute})' + Počnite ispočetka sa praznom tablom. Na tablu, ručno dodaj kartice i kolone. + action: 'Tabla sa zadacima' + action_by_attribute: 'Tabla sa zadacima (%{attribute})' action_text: > - A board with filtered lists on %{attribute} attribute. Moving work packages to other lists will update their attribute. + Tabla sa filtriranim listama po %{attribute}. Premeštanje radnog paketa na druge liste osvežava njihove atribute. action_text_subprojects: > - Board with automated columns for subprojects. Dragging work packages to other lists updates the (sub-)project accordingly. + Tabla sa automatizovanim kolonama za potprojekte. Prevlačenje radnog paketa na druge liste osvežava stanje potprojekta. action_text_subtasks: > - Board with automated columns for sub-elements. Dragging work packages to other lists updates the parent accordingly. + Tabla sa automatizovanim kolonama za podelemente. Prevlačenje radnog paketa na druge liste osvežava stanje izvornog elementa. action_text_status: > - Basic kanban style board with columns for status such as To Do, In Progress, Done. + Osnovna tabla u kanban stilu, sa kolonama koje prikazuju status, kao što su: Uraditi, Tekuće, Završeno. action_text_assignee: > - Board with automated columns based on assigned users. Ideal for dispatching work packages. + Tabla sa automatizovanim kolonama, po dodeljenim korisnicima. Idealna za otpremanje radnih paketa. action_text_version: > - Board with automated columns based on the version attribute. Ideal for planning product development. + Tabla sa automatizovanim kolonama, po atributima verzije. Idealna za planiranje razvoja proizvoda. action_type: - assignee: assignee + assignee: zadužen status: status - version: version - subproject: subproject - subtasks: parent-child + version: verzija + subproject: potprojekat + subtasks: roditelj-dete board_type_title: - assignee: Assignee + assignee: Zadužen status: Status - version: Version - subproject: Subproject + version: Verzija + subproject: Potprojekat subtasks: Parent-child - basic: Basic - select_attribute: "Action attribute" + basic: Osnovno + select_attribute: "Atribut akcije" add_list_modal: labels: - assignee: Select user to add as a new assignee list - status: Select status to add as a new list - version: Select version to add as a new list - subproject: Select subproject to add as a new list - subtasks: Select work package to add as a new list + assignee: Izaberi korisnika za dodavanje kao novu listu dodeljenih + status: Izaberi status za dodavanje kao novu listu + version: Izaberite verziju, za dodavanje kao novu list + subproject: Izaberite potprojekat, za dodavanje kao novu listu + subtasks: Izaberite radni paket, za dodavanje kao novu listu warning: status: | - There is currently no status available.
- Either there are none or they have all already been added to the board. - assignee: There isn't any member matched with your filter value.
- no_member: This project currently does not have any members that can be added.
- add_members: Add a new member to this project to select users again. + Trenutno nema dostupnih statusa.
+ Ili ne postoji ni jedan, ili su svi već dodati na tablu. + assignee: Nema članova koji odgovaraju traženom filteru. + no_member: Projekat trenutno nema članova dostupnih za dodavanje. + add_members: Dodaj novog člana ovom projektuda bi ste ponovo izabrali korisnike. configuration_modal: - title: 'Configure this board' + title: 'Konfigurišite ovu tablu' display_settings: - card_mode: "Display as cards" - table_mode: "Display as table" + card_mode: "Prikaži kao kartice" + table_mode: "Prikaži kao tablu" diff --git a/modules/boards/config/locales/crowdin/tr.yml b/modules/boards/config/locales/crowdin/tr.yml index 1523cb31b7c9..360234445a58 100644 --- a/modules/boards/config/locales/crowdin/tr.yml +++ b/modules/boards/config/locales/crowdin/tr.yml @@ -9,8 +9,8 @@ tr: boards: label_board: "Pano" label_boards: "Panolar" - label_create_new_board: "Create new board" - label_board_type: "Board type" + label_create_new_board: "Yeni pano oluştur" + label_board_type: "Pano türü" board_types: free: Temel action: "Eylem kurulu (%{attribute})" @@ -36,4 +36,4 @@ tr: Board with automated columns for sub-elements. Dragging work packages to other lists updates the parent accordingly. 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.' - upgrade: 'Upgrade now' + upgrade: 'Şimdi Yükselt' diff --git a/modules/budgets/config/locales/crowdin/bg.yml b/modules/budgets/config/locales/crowdin/bg.yml index 585ac6a52203..c92218a88170 100644 --- a/modules/budgets/config/locales/crowdin/bg.yml +++ b/modules/budgets/config/locales/crowdin/bg.yml @@ -56,7 +56,7 @@ bg: caption_material_costs: "Реални единични разходи" budgets_title: "Бюджети" events: - budget: "Budget edited" + budget: "Бюджетът е редактиран" help_click_to_edit: "Click here to edit." help_currency_format: "Format of displayed currency values. %n is replaced with the currency value, %u ist replaced with the currency unit." help_override_rate: "Enter a value here to override the default rate." diff --git a/modules/budgets/config/locales/crowdin/el.yml b/modules/budgets/config/locales/crowdin/el.yml index 0717900c34c3..dc7be11ac11d 100644 --- a/modules/budgets/config/locales/crowdin/el.yml +++ b/modules/budgets/config/locales/crowdin/el.yml @@ -74,5 +74,5 @@ el: permission_view_budgets: "Εμφάνιση προϋπολογισμών" project_module_budgets: "Προϋπολογισμοί" text_budget_reassign_to: "Reassign them to this budget:" - text_budget_delete: "Delete the budget from all work packages" - text_budget_destroy_assigned_wp: "There are %{count} work packages assigned to this budget. What do you want to do?" + text_budget_delete: "Διαγραφή του προϋπολογισμού από όλα τα πακέτα εργασίας" + text_budget_destroy_assigned_wp: "Υπάρχουν %{count} πακέτα εργασίας που έχουν συνδεθεί με αυτόν τον προϋπολογισμό. Τι θέλετε να κάνετε;" diff --git a/modules/calendar/config/locales/crowdin/el.yml b/modules/calendar/config/locales/crowdin/el.yml index 8c5a37a43cbf..fcd0822344be 100644 --- a/modules/calendar/config/locales/crowdin/el.yml +++ b/modules/calendar/config/locales/crowdin/el.yml @@ -5,8 +5,8 @@ el: description: "Provides calendar views." label_calendar: "Ημερολόγιο" label_calendar_plural: "Ημερολόγια" - label_new_calendar: "New calendar" + label_new_calendar: "Νέο ημερολόγιο" permission_view_calendar: "Προβολή ημερολογίων" permission_manage_calendars: "Διαχείριση ημερολογίων" - permission_share_calendars: "Subscribe to iCalendars" + permission_share_calendars: "Εγγραφή σε iCalendars" project_module_calendar_view: "Ημερολόγια" diff --git a/modules/calendar/config/locales/crowdin/ja.yml b/modules/calendar/config/locales/crowdin/ja.yml index 6b185725fb0c..9237726ff94b 100644 --- a/modules/calendar/config/locales/crowdin/ja.yml +++ b/modules/calendar/config/locales/crowdin/ja.yml @@ -5,7 +5,7 @@ ja: description: "Provides calendar views." label_calendar: "カレンダー" label_calendar_plural: "カレンダー" - label_new_calendar: "New calendar" + label_new_calendar: "新しいカレンダー" permission_view_calendar: "カレンダーを表示" permission_manage_calendars: "カレンダーを管理" permission_share_calendars: "iCalendarを購読" diff --git a/modules/calendar/config/locales/crowdin/uk.yml b/modules/calendar/config/locales/crowdin/uk.yml index 980bad7123cf..6e3e16d8fcde 100644 --- a/modules/calendar/config/locales/crowdin/uk.yml +++ b/modules/calendar/config/locales/crowdin/uk.yml @@ -1,8 +1,8 @@ #English strings go here uk: plugin_openproject_calendar: - name: "OpenProject Calendar" - description: "Provides calendar views." + name: "Календар OpenProject " + description: "Дозволяти перегляд календаря" label_calendar: "Календар" label_calendar_plural: "Календарі" label_new_calendar: "Новий календар" diff --git a/modules/costs/config/locales/crowdin/bg.yml b/modules/costs/config/locales/crowdin/bg.yml index 9f6ac461b7a6..5bfa62425fe6 100644 --- a/modules/costs/config/locales/crowdin/bg.yml +++ b/modules/costs/config/locales/crowdin/bg.yml @@ -60,7 +60,7 @@ bg: costs: "Разходи" current_rate: "Текуща ставка" hours: "Часове" - units: "Units" + units: "Единици" valid_from: "Валиден от" fixed_date: "Фиксирана дата" button_add_rate: "Добавете курс" @@ -69,39 +69,39 @@ bg: caption_default: "По подразбиране" caption_default_rate_history_for: "История на тарифите по подразбиране за %{user}" caption_locked_on: "Заключена" - caption_materials: "Units" + caption_materials: "Единици" caption_rate_history: "Оценете историята" caption_rate_history_for: "Оценете историята за %{user}" caption_rate_history_for_project: "Оценете историята за %{user} в проекта %{project}" caption_save_rate: "Съхраняване на ставката" caption_set_rate: "Задайте текуща ставка" caption_show_locked: "Показване на заключените типове" - description_date_for_new_rate: "Date for new rate" - group_by_others: "not in any group" + description_date_for_new_rate: "Дата за нова ставка" + group_by_others: "не е в нито една група" label_between: "между" - label_cost_filter_add: "Add cost entry filter" - label_costlog: "Logged unit costs" + label_cost_filter_add: "Добавете филтър за въвеждане на разходи" + label_costlog: "Регистрирани единични разходи" label_cost_plural: "Разходи" label_cost_type_plural: "Видове разходи" label_cost_type_specific: "Тип на разходите #%{id}: %{name}" - label_costs_per_page: "Costs per page" - label_currency: "Currency" - label_currency_format: "Format of currency" - label_current_default_rate: "Current default rate" + label_costs_per_page: "Разходи за страница" + label_currency: "Валута" + label_currency_format: "Формат на валутата" + label_current_default_rate: "Текуща ставка по подразбиране" label_date_on: "на" - label_deleted_cost_types: "Deleted cost types" - label_locked_cost_types: "Locked cost types" - label_display_cost_entries: "Display unit costs" - label_display_time_entries: "Display reported hours" - label_display_types: "Display types" + label_deleted_cost_types: "Изтрити видове разходи" + label_locked_cost_types: "Заключени видове разходи" + label_display_cost_entries: "Показване на единични разходи" + label_display_time_entries: "Показване на отчетените часове" + label_display_types: "Видове изобразяване" label_edit: "Редактиране" - label_generic_user: "Generic user" + label_generic_user: "Общ потребител" label_greater_or_equal: ">=" label_group_by: "Групиране по" - label_group_by_add: "Add grouping field" - label_hourly_rate: "Hourly rate" - label_include_deleted: "Include deleted" - label_work_package_filter_add: "Add work package filter" + label_group_by_add: "Добавете поле за групиране" + label_hourly_rate: "Часова ставка" + label_include_deleted: "Включете изтритите" + label_work_package_filter_add: "Добавете филтър за работен пакет" label_kind: "Тип" label_less_or_equal: "<=" label_log_costs: "Разходи за единична регистрация" @@ -109,26 +109,26 @@ bg: label_option_plural: "Опции" label_overall_costs: "Общи разходи" label_rate: "Ставка" - label_rate_plural: "Rates" - label_status_finished: "Finished" - label_units: "Cost units" + label_rate_plural: "Цени" + label_status_finished: "Завършено" + label_units: "Разходни единици" label_user: "Потребител" - label_until: "until" + label_until: "докато" label_valid_from: "Валиден от" label_yes: "Да" - notice_something_wrong: "Something went wrong. Please try again." - notice_successful_restore: "Successful restore." - notice_successful_lock: "Locked successfully." - notice_cost_logged_successfully: 'Unit cost logged successfully.' - permission_edit_cost_entries: "Edit booked unit costs" - permission_edit_own_cost_entries: "Edit own booked unit costs" - permission_edit_hourly_rates: "Edit hourly rates" - permission_edit_own_hourly_rate: "Edit own hourly rates" - permission_edit_rates: "Edit rates" - permission_log_costs: "Book unit costs" - permission_log_own_costs: "Book unit costs for oneself" - permission_view_cost_entries: "View booked costs" - permission_view_cost_rates: "View cost rates" + notice_something_wrong: "Нещо се обърка. Моля, опитайте отново." + notice_successful_restore: "Успешно възстановяване." + notice_successful_lock: "Заключено успешно." + notice_cost_logged_successfully: 'Единичната цена е регистрирана успешно.' + permission_edit_cost_entries: "Редактирайте резервираните единични разходи" + permission_edit_own_cost_entries: "Редактирайте собствените резервирани единични разходи" + permission_edit_hourly_rates: "Редактирайте почасовите ставки" + permission_edit_own_hourly_rate: "Редактирайте собствените си почасови ставки" + permission_edit_rates: "Редактиране на ставките" + permission_log_costs: "Резервирайте единични разходи" + permission_log_own_costs: "Резервирайте единичните разходи за себе си" + permission_view_cost_entries: "Вижте резервираните разходи" + permission_view_cost_rates: "Преглед на цените" permission_view_hourly_rates: "Вижте всички почасови тарифи" permission_view_own_cost_entries: "Вижте собствените резервирани разходи" permission_view_own_hourly_rate: "Вижте собствената почасова ставка" diff --git a/modules/costs/config/locales/crowdin/sk.yml b/modules/costs/config/locales/crowdin/sk.yml index b890dfc52d8d..355b73ad9fcb 100644 --- a/modules/costs/config/locales/crowdin/sk.yml +++ b/modules/costs/config/locales/crowdin/sk.yml @@ -85,7 +85,7 @@ sk: label_costlog: "Zaúčtované jednotkové náklady" label_cost_plural: "Náklady" label_cost_type_plural: "Typy nákladov" - label_cost_type_specific: "Cost type #%{id}: %{name}" + label_cost_type_specific: "Typ nákladu #%{id}: %{name}" label_costs_per_page: "Náklady na stranu" label_currency: "Mena" label_currency_format: "Formát meny" diff --git a/modules/costs/config/locales/crowdin/uk.yml b/modules/costs/config/locales/crowdin/uk.yml index 01d3728c54e9..e0bab2242fd0 100644 --- a/modules/costs/config/locales/crowdin/uk.yml +++ b/modules/costs/config/locales/crowdin/uk.yml @@ -22,7 +22,7 @@ uk: plugin_costs: name: "Час і витрати" - description: "This module adds features for planning and tracking costs of projects." + description: "Цей модуль додає функції планування і відстеження витрат на проєкти." activerecord: attributes: cost_entry: diff --git a/modules/documents/config/locales/crowdin/uk.yml b/modules/documents/config/locales/crowdin/uk.yml index 1e5cfd97ac32..bf73f2f8dc4e 100644 --- a/modules/documents/config/locales/crowdin/uk.yml +++ b/modules/documents/config/locales/crowdin/uk.yml @@ -21,8 +21,8 @@ #++ uk: plugin_openproject_documents: - name: "OpenProject Documents" - description: "An OpenProject plugin to allow creation of documents in projects." + name: "Документи OpenProject " + description: "Плагін OpenProject дозволяє створювати документи в проектах." activerecord: models: document: "Документ" diff --git a/modules/github_integration/config/locales/crowdin/js-ja.yml b/modules/github_integration/config/locales/crowdin/js-ja.yml index d00d48f427e1..fd259410d4be 100644 --- a/modules/github_integration/config/locales/crowdin/js-ja.yml +++ b/modules/github_integration/config/locales/crowdin/js-ja.yml @@ -44,8 +44,8 @@ ja: merged_message: "Pull request #%{pr_number} %{pr_link} for %{repository_link} has been %{pr_state} by %{github_user_link}." referenced_message: "Pull request #%{pr_number} %{pr_link} for %{repository_link} authored by %{github_user_link} referenced this work package." states: - opened: 'opened' + opened: 'オープン' closed: '完了' - draft: 'drafted' - merged: 'merged' - ready_for_review: 'marked ready for review' + draft: 'ドラフト' + merged: 'マージ済' + ready_for_review: 'レビュー準備完了' diff --git a/modules/github_integration/config/locales/crowdin/js-tr.yml b/modules/github_integration/config/locales/crowdin/js-tr.yml index b15c2cbd9a5a..5b5778b6680a 100644 --- a/modules/github_integration/config/locales/crowdin/js-tr.yml +++ b/modules/github_integration/config/locales/crowdin/js-tr.yml @@ -47,5 +47,5 @@ tr: opened: 'opened' closed: 'kapalı' draft: 'drafted' - merged: 'merged' - ready_for_review: 'marked ready for review' + merged: 'birleştirildi' + ready_for_review: 'incelemeye hazır olarak işaretlendi' diff --git a/modules/github_integration/config/locales/crowdin/tr.yml b/modules/github_integration/config/locales/crowdin/tr.yml index ec14e409c6ba..7da8f60de266 100644 --- a/modules/github_integration/config/locales/crowdin/tr.yml +++ b/modules/github_integration/config/locales/crowdin/tr.yml @@ -21,7 +21,7 @@ #++ tr: plugin_openproject_github_integration: - name: "OpenProject GitHub Integration" + name: "OpenProject GitHub Entegrasyonu" description: "Integrates OpenProject and GitHub for a better workflow" project_module_github: "GitHub" permission_show_github_content: "Github içeriğini göster" diff --git a/modules/grids/config/locales/crowdin/js-fr.yml b/modules/grids/config/locales/crowdin/js-fr.yml index 25f8a4109e98..6f07e68905f6 100644 --- a/modules/grids/config/locales/crowdin/js-fr.yml +++ b/modules/grids/config/locales/crowdin/js-fr.yml @@ -30,7 +30,7 @@ fr: title: 'Détails du projet' no_results: 'Aucun champ personnalisé n''a été défini pour les projets.' project_status: - title: 'État du projet' + title: 'Statut du projet' not_started: 'Non démarré' on_track: 'Sur la bonne voie' off_track: 'Sur la mauvaise voie' diff --git a/modules/ldap_groups/config/locales/crowdin/ar.yml b/modules/ldap_groups/config/locales/crowdin/ar.yml index 70984d111ffe..efd70df78934 100644 --- a/modules/ldap_groups/config/locales/crowdin/ar.yml +++ b/modules/ldap_groups/config/locales/crowdin/ar.yml @@ -35,6 +35,7 @@ ar: label_n_groups_found: one: "1 group found by the filter" other: "%{count} groups found by the filter" + zero: "No groups were found by the filter" destroy: title: 'Remove synchronized filter %{name}' confirmation: "If you continue, the synchronized filter %{name} and all groups %{groups_count} created through it will be removed." diff --git a/modules/ldap_groups/config/locales/crowdin/ja.yml b/modules/ldap_groups/config/locales/crowdin/ja.yml index f42f54d49548..a3c88e5d9652 100644 --- a/modules/ldap_groups/config/locales/crowdin/ja.yml +++ b/modules/ldap_groups/config/locales/crowdin/ja.yml @@ -6,11 +6,11 @@ ja: attributes: ldap_groups/synchronized_group: dn: 'DN' - ldap_auth_source: 'LDAP connection' + ldap_auth_source: 'LDAP 接続' sync_users: 'ユーザーを同期' ldap_groups/synchronized_filter: filter_string: 'LDAPフィルタ' - ldap_auth_source: 'LDAP connection' + ldap_auth_source: 'LDAP 接続' group_name_attribute: "グループ名属性" sync_users: 'ユーザーを同期' base_dn: "ベース DN を検索" diff --git a/modules/ldap_groups/config/locales/crowdin/uk.yml b/modules/ldap_groups/config/locales/crowdin/uk.yml index 4541b302e94f..140d8f4e99d7 100644 --- a/modules/ldap_groups/config/locales/crowdin/uk.yml +++ b/modules/ldap_groups/config/locales/crowdin/uk.yml @@ -1,7 +1,7 @@ uk: plugin_openproject_ldap_groups: - name: "OpenProject LDAP groups" - description: "Synchronization of LDAP group memberships." + name: "Групи LDAP OpenProject" + description: "Синхронізація членства в LDAP групах." activerecord: attributes: ldap_groups/synchronized_group: diff --git a/modules/meeting/config/locales/crowdin/ca.yml b/modules/meeting/config/locales/crowdin/ca.yml index 2358b33668ea..62f3eedcec0a 100644 --- a/modules/meeting/config/locales/crowdin/ca.yml +++ b/modules/meeting/config/locales/crowdin/ca.yml @@ -33,7 +33,7 @@ ca: participants: "Participants" participants_attended: "Assistents" participants_invited: "Convidats" - project: "Project" + project: "Projecte" start_time: "Hora" start_time_hour: "Hora d'inici" errors: @@ -66,13 +66,13 @@ ca: label_meeting_agenda_close: "Tanca l'agenda per començar l'acta" label_meeting_date_time: "Data/Hora" label_meeting_diff: "Diferència" - label_upcoming_meetings: "Upcoming meetings" - label_past_meetings: "Past meetings" - label_involvement: "Involvement" - label_upcoming_invitations: "Upcoming invitations" - label_past_invitations: "Past invitations" - label_attendee: "Attendee" - label_author: "Creator" + label_upcoming_meetings: "Pròximes reunions" + label_past_meetings: "Reunions passades" + label_involvement: "Implicació" + label_upcoming_invitations: "Pròximes invitacions" + label_past_invitations: "Invitacions passades" + label_attendee: "Assistent" + label_author: "Creador" label_notify: "Envia per revisar" label_icalendar: "Envia iCalendar" label_version: "Versió" @@ -97,7 +97,7 @@ ca: text_duration_in_hours: "Duració en hores" text_in_hours: "en hores" text_meeting_agenda_for_meeting: 'agenda per la reunió "%{meeting}"' - text_meeting_closing_are_you_sure: "Are you sure you want to close the meeting agenda?" + text_meeting_closing_are_you_sure: "Esteu segur que voleu tancar l'agenda de la reunió?" text_meeting_agenda_open_are_you_sure: "Això sobreescriurà tots els canvis a l'acte! Vols continuar?" text_meeting_minutes_for_meeting: 'actes per la reunió "%{meeting}"' text_review_meeting_agenda: "%{author} ha afegit el %{link} per a revisió." diff --git a/modules/meeting/config/locales/crowdin/cs.yml b/modules/meeting/config/locales/crowdin/cs.yml index 3de1a2771e8b..56425f12ceba 100644 --- a/modules/meeting/config/locales/crowdin/cs.yml +++ b/modules/meeting/config/locales/crowdin/cs.yml @@ -86,7 +86,7 @@ cs: permission_edit_meetings: "Upravit schůzku" permission_delete_meetings: "Odstranit schůzky" permission_view_meetings: "Zobrazit schůzky" - permission_create_meeting_agendas: "Správa agend" + permission_create_meeting_agendas: "Správa zápisů" permission_close_meeting_agendas: "uzavřít agendy" permission_send_meeting_agendas_notification: "Odeslat oznámení k revizi agendy" permission_create_meeting_minutes: "Spravovat zápisy" diff --git a/modules/meeting/config/locales/crowdin/de.yml b/modules/meeting/config/locales/crowdin/de.yml index ff57cc733abe..23ecd87e2a9f 100644 --- a/modules/meeting/config/locales/crowdin/de.yml +++ b/modules/meeting/config/locales/crowdin/de.yml @@ -100,6 +100,6 @@ de: text_meeting_closing_are_you_sure: "Sind Sie sicher, dass Sie die Agenda schließen wollen?" text_meeting_agenda_open_are_you_sure: "Es werden alle Änderungen im Protokoll überschrieben! Wollen Sie fortfahren?" text_meeting_minutes_for_meeting: 'das Protokoll für die Besprechung "%{meeting}"' - text_review_meeting_agenda: "%{author} hat %{link} zur Einsicht freigegeben." - text_review_meeting_minutes: "%{author} hat %{link} zur Einsicht freigegeben." + text_review_meeting_agenda: "%{author} hat die %{link} zur Einsicht freigegeben." + text_review_meeting_minutes: "%{author} hat die %{link} zur Einsicht freigegeben." text_notificiation_invited: "Diese Email enthält einen ics Eintrag für die untenstehende Besprechung:" diff --git a/modules/meeting/config/locales/crowdin/es.yml b/modules/meeting/config/locales/crowdin/es.yml index 9aa9ea683d72..07efda041647 100644 --- a/modules/meeting/config/locales/crowdin/es.yml +++ b/modules/meeting/config/locales/crowdin/es.yml @@ -101,5 +101,5 @@ es: text_meeting_agenda_open_are_you_sure: "Se sobrescribirán todos los cambios en las minutas. ¿Quiere continuar?" text_meeting_minutes_for_meeting: 'minutas para la reunión "%{meeting}"' text_review_meeting_agenda: "%{author} ha puesto el %{link} para revisión." - text_review_meeting_minutes: "%{author} ha definido el %{link} para revisión." + text_review_meeting_minutes: "%{author} ha puesto el %{link} para revisión." text_notificiation_invited: "El correo electrónico contiene una entrada ics para la reunión siguiente:" diff --git a/modules/meeting/config/locales/crowdin/lt.yml b/modules/meeting/config/locales/crowdin/lt.yml index 50cdb8efbbad..90018b43bf10 100644 --- a/modules/meeting/config/locales/crowdin/lt.yml +++ b/modules/meeting/config/locales/crowdin/lt.yml @@ -101,5 +101,5 @@ lt: text_meeting_agenda_open_are_you_sure: "Tai perrašys visus pakeitimus minutėse! Ar norite tęsti?" text_meeting_minutes_for_meeting: 'pasitarimo „%{meeting}“ minutės' text_review_meeting_agenda: "%{author} įdėjo %{link} peržiūroje." - text_review_meeting_minutes: "%{author} įdėjo %{link} peržiūrai." + text_review_meeting_minutes: "%{author} įdėjo %{link} peržiūroje." text_notificiation_invited: "Šis laiškas turi ics įrašą žemiau nurodytam susitikimui:" diff --git a/modules/meeting/config/locales/crowdin/tr.yml b/modules/meeting/config/locales/crowdin/tr.yml index e0c561b1e668..6d6b6914b616 100644 --- a/modules/meeting/config/locales/crowdin/tr.yml +++ b/modules/meeting/config/locales/crowdin/tr.yml @@ -33,7 +33,7 @@ tr: participants: "Katılımcılar" participants_attended: "Katılımcılar" participants_invited: "Davetliler" - project: "Project" + project: "Proje" start_time: "Saat" start_time_hour: "Başlangıç saati" errors: @@ -66,11 +66,11 @@ tr: label_meeting_agenda_close: "Başlamak için gündemi dakikalar sonra kapatın" label_meeting_date_time: "Tarih/Saat" label_meeting_diff: "Fark" - label_upcoming_meetings: "Upcoming meetings" - label_past_meetings: "Past meetings" + label_upcoming_meetings: "Yaklaşan toplantılar" + label_past_meetings: "Geçmiş toplantılar" label_involvement: "Involvement" - label_upcoming_invitations: "Upcoming invitations" - label_past_invitations: "Past invitations" + label_upcoming_invitations: "Yaklaşan davetiyeler" + label_past_invitations: "Geçmiş davetiyeler" label_attendee: "Attendee" label_author: "Creator" label_notify: "Gözden geçirilmek üzere gönder" diff --git a/modules/meeting/config/locales/crowdin/uk.yml b/modules/meeting/config/locales/crowdin/uk.yml index aee1bac9ccca..683b90dca05c 100644 --- a/modules/meeting/config/locales/crowdin/uk.yml +++ b/modules/meeting/config/locales/crowdin/uk.yml @@ -22,9 +22,9 @@ #English strings go here for Rails i18n uk: plugin_openproject_meeting: - name: "OpenProject Meeting" + name: "Зустріч OpenProject" description: >- - This module adds functions to support project meetings to OpenProject. Meetings can be scheduled selecting invitees from the same project to take part in the meeting. An agenda can be created and sent to the invitees. After the meeting, attendees can be selected and minutes can be created based on the agenda. Finally, the minutes can be sent to all attendees and invitees. + Цей модуль додає до OpenProject функції для підтримки зустрічей проєкту. Зустрічі можна планувати, вибираючи запрошених з одного проекту для участі у зустрічі. Можна створити порядок денний і надіслати його запрошеним. Після зустрічі можна вибрати учасників і створити протокол на основі порядку денного. Наостанок, протокол можна надіслати всім учасникам і запрошеним. activerecord: attributes: meeting: diff --git a/modules/my_page/spec/features/my/my_spent_time_widget_with_a_negative_time_zone_spec.rb b/modules/my_page/spec/features/my/my_spent_time_widget_with_a_negative_time_zone_spec.rb new file mode 100644 index 000000000000..664477503f22 --- /dev/null +++ b/modules/my_page/spec/features/my/my_spent_time_widget_with_a_negative_time_zone_spec.rb @@ -0,0 +1,103 @@ +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 2012-2023 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_relative '../../support/pages/my/page' + +RSpec.describe 'My spent time widget with a negative time zone', :js, + with_settings: { start_of_week: 1 } do + let(:beginning_of_week) { monday } + let(:end_of_week) { sunday } + let(:monday) { Date.current.beginning_of_week(:monday) } + let(:tuesday) { beginning_of_week + 1.day } + let(:thursday) { beginning_of_week + 3.days } + let(:sunday) { beginning_of_week + 6.days } + let(:time_zone) { 'America/Phoenix' } + + let!(:type) { create(:type) } + let!(:project) { create(:project, types: [type]) } + let!(:activity) { create(:time_entry_activity, name: 'Development') } + let!(:work_package) do + create(:work_package, + project:, + type:, + author: user) + end + let!(:time_entry) do + create(:time_entry, + spent_on: monday, + work_package:, + project:, + activity:, + user:) + end + let(:user) do + create(:user, + preferences: { time_zone: }, + member_in_project: project, + member_with_permissions: %i[view_time_entries edit_time_entries view_work_packages log_own_time]) + end + let(:my_page) { Pages::My::Page.new } + let(:time_logging_modal) { Components::TimeLoggingModal.new } + let!(:week_days) { week_with_saturday_and_sunday_as_weekend } + let!(:non_working_day) { create(:non_working_day, date: tuesday) } + + # Configure the time zone of the browser + # @param [String] time_zone The time zone to set, for instance 'Europe/Paris' + def set_browser_time_zone(time_zone) + page.driver.browser.execute_cdp('Emulation.setTimezoneOverride', timezoneId: time_zone) + end + + before do + login_as user + set_browser_time_zone(time_zone) + my_page.visit! + end + + it 'correctly displays non-working days and prefills day when logging time [fix #49779]' do + my_page.add_widget(1, 1, :within, 'My spent time') + + my_page.expect_and_dismiss_toaster message: I18n.t(:notice_successful_update) + + aggregate_failures("non-working days are displayed properly") do + expect(page).not_to have_css('.fc-day-mon.fc-non-working-day', wait: 0) + expect(page).to have_css('.fc-day-tue.fc-non-working-day', wait: 0) + expect(page).not_to have_css('.fc-day-wed.fc-non-working-day', wait: 0) + expect(page).not_to have_css('.fc-day-thu.fc-non-working-day', wait: 0) + expect(page).not_to have_css('.fc-day-fri.fc-non-working-day', wait: 0) + expect(page).to have_css('.fc-day-sat.fc-non-working-day', wait: 0) + expect(page).to have_css('.fc-day-sun.fc-non-working-day', wait: 0) + end + + aggregate_failures("when clicking a day, time entry day is set to the day clicked (Thursday)") do + find(".fc-day-thu .te-calendar--add-entry", visible: false).click + time_logging_modal.has_field_with_value 'spentOn', thursday.iso8601 + end + end +end diff --git a/modules/openid_connect/app/views/openid_connect/providers/_azure_form.html.erb b/modules/openid_connect/app/views/openid_connect/providers/_azure_form.html.erb index 09c208f6744e..2003de5d5cde 100644 --- a/modules/openid_connect/app/views/openid_connect/providers/_azure_form.html.erb +++ b/modules/openid_connect/app/views/openid_connect/providers/_azure_form.html.erb @@ -5,13 +5,13 @@ 'admin--openid-connect-providers-target': 'azureForm', }, hidden: @provider.name.present? && @provider.name != 'azure' do %> -
+
<%= f.text_field :tenant, required: true, container_class: '-middle' %>
<%= t('openid_connect.setting_instructions.azure_tenant_html') %>
-
+
<%= f.check_box :use_graph_api, container_class: '-middle' %>
<%= t('openid_connect.setting_instructions.azure_graph_api') %> diff --git a/modules/openid_connect/app/views/openid_connect/providers/_form.html.erb b/modules/openid_connect/app/views/openid_connect/providers/_form.html.erb index 7361267e0183..046a0bbfefa2 100644 --- a/modules/openid_connect/app/views/openid_connect/providers/_form.html.erb +++ b/modules/openid_connect/app/views/openid_connect/providers/_form.html.erb @@ -1,3 +1,11 @@ +<% if @provider.persisted? && @provider.name == 'azure' && @provider.tenant.empty? %> +
+
+

<%= I18n.t('openid_connect.setting_instructions.azure_deprecation_warning') %>

+
+
+<% end %> +
<% unless @provider.persisted? -%>
diff --git a/modules/openid_connect/config/locales/crowdin/af.yml b/modules/openid_connect/config/locales/crowdin/af.yml index d951b66d269e..0d53f3916fbd 100644 --- a/modules/openid_connect/config/locales/crowdin/af.yml +++ b/modules/openid_connect/config/locales/crowdin/af.yml @@ -22,6 +22,8 @@ af: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/ar.yml b/modules/openid_connect/config/locales/crowdin/ar.yml index 02b35693d0af..327286f1d071 100644 --- a/modules/openid_connect/config/locales/crowdin/ar.yml +++ b/modules/openid_connect/config/locales/crowdin/ar.yml @@ -22,6 +22,8 @@ ar: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/az.yml b/modules/openid_connect/config/locales/crowdin/az.yml index b59bac21ee14..e42a9e7dab40 100644 --- a/modules/openid_connect/config/locales/crowdin/az.yml +++ b/modules/openid_connect/config/locales/crowdin/az.yml @@ -22,6 +22,8 @@ az: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/be.yml b/modules/openid_connect/config/locales/crowdin/be.yml index a3775e2583f8..fa94f6effa4e 100644 --- a/modules/openid_connect/config/locales/crowdin/be.yml +++ b/modules/openid_connect/config/locales/crowdin/be.yml @@ -22,6 +22,8 @@ be: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/bg.yml b/modules/openid_connect/config/locales/crowdin/bg.yml index 800e7833e9ab..c296a6f5eecd 100644 --- a/modules/openid_connect/config/locales/crowdin/bg.yml +++ b/modules/openid_connect/config/locales/crowdin/bg.yml @@ -22,6 +22,8 @@ bg: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/ca.yml b/modules/openid_connect/config/locales/crowdin/ca.yml index 62648e61b32d..88a7e6a38dc6 100644 --- a/modules/openid_connect/config/locales/crowdin/ca.yml +++ b/modules/openid_connect/config/locales/crowdin/ca.yml @@ -22,6 +22,8 @@ ca: plural: Proveïdors d’OpenID singular: Proveïdor d’OpenID setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/ckb-IR.yml b/modules/openid_connect/config/locales/crowdin/ckb-IR.yml index 9a426a0b3e86..3b8d913fd8a1 100644 --- a/modules/openid_connect/config/locales/crowdin/ckb-IR.yml +++ b/modules/openid_connect/config/locales/crowdin/ckb-IR.yml @@ -22,6 +22,8 @@ ckb-IR: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/cs.yml b/modules/openid_connect/config/locales/crowdin/cs.yml index 23961a68f955..2364ae9be3b0 100644 --- a/modules/openid_connect/config/locales/crowdin/cs.yml +++ b/modules/openid_connect/config/locales/crowdin/cs.yml @@ -22,6 +22,8 @@ cs: plural: Poskytovatelé OpenID singular: Poskytovatel OpenID setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/da.yml b/modules/openid_connect/config/locales/crowdin/da.yml index 73eda37f9cb9..e8aa06cc24c5 100644 --- a/modules/openid_connect/config/locales/crowdin/da.yml +++ b/modules/openid_connect/config/locales/crowdin/da.yml @@ -22,6 +22,8 @@ da: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/de.yml b/modules/openid_connect/config/locales/crowdin/de.yml index bc8cd8646869..0696064407eb 100644 --- a/modules/openid_connect/config/locales/crowdin/de.yml +++ b/modules/openid_connect/config/locales/crowdin/de.yml @@ -22,6 +22,8 @@ de: plural: OpenID-Anbieter singular: OpenID-Anbieter setting_instructions: + azure_deprecation_warning: > + Die konfigurierte Azure App verwendet eine veraltete API von Azure. Bitte erstellen Sie eine neue Azure App, um die Funktionalität in Zukunft sicherzustellen. azure_graph_api: > Endpunkt graph.microsoft.com für OpenID Connect userinfo Anfragen, um Benutzerdaten anzufordern. Dies sollte die Standardeinstellung sein, es sei denn, Sie haben eine ältere azure Anwendung. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/el.yml b/modules/openid_connect/config/locales/crowdin/el.yml index 64f917d9041a..ab24b24f28d5 100644 --- a/modules/openid_connect/config/locales/crowdin/el.yml +++ b/modules/openid_connect/config/locales/crowdin/el.yml @@ -22,6 +22,8 @@ el: plural: Πάροχοι OpenID singular: Πάροχος OpenID setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/eo.yml b/modules/openid_connect/config/locales/crowdin/eo.yml index 2d489e5bdd59..abf1e3dff2ab 100644 --- a/modules/openid_connect/config/locales/crowdin/eo.yml +++ b/modules/openid_connect/config/locales/crowdin/eo.yml @@ -22,6 +22,8 @@ eo: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/es.yml b/modules/openid_connect/config/locales/crowdin/es.yml index a8a2fdc86e1b..b75f8b898773 100644 --- a/modules/openid_connect/config/locales/crowdin/es.yml +++ b/modules/openid_connect/config/locales/crowdin/es.yml @@ -22,6 +22,8 @@ es: plural: Proveedores de OpenID singular: Proveedor de OpenID setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Utilice el terminal graph.microsoft.com userinfo para solicitar los datos de usuario. Este debería ser el predeterminado a menos que tenga una aplicación azure más antigua. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/et.yml b/modules/openid_connect/config/locales/crowdin/et.yml index 2c503df2d752..41c1632f7572 100644 --- a/modules/openid_connect/config/locales/crowdin/et.yml +++ b/modules/openid_connect/config/locales/crowdin/et.yml @@ -22,6 +22,8 @@ et: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/eu.yml b/modules/openid_connect/config/locales/crowdin/eu.yml index 05f659404238..f1006e960a13 100644 --- a/modules/openid_connect/config/locales/crowdin/eu.yml +++ b/modules/openid_connect/config/locales/crowdin/eu.yml @@ -22,6 +22,8 @@ eu: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/fa.yml b/modules/openid_connect/config/locales/crowdin/fa.yml index f4dbc5ad85e0..ad03bf626a2a 100644 --- a/modules/openid_connect/config/locales/crowdin/fa.yml +++ b/modules/openid_connect/config/locales/crowdin/fa.yml @@ -22,6 +22,8 @@ fa: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/fi.yml b/modules/openid_connect/config/locales/crowdin/fi.yml index 803e3dce10ed..56d6bd605992 100644 --- a/modules/openid_connect/config/locales/crowdin/fi.yml +++ b/modules/openid_connect/config/locales/crowdin/fi.yml @@ -22,6 +22,8 @@ fi: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/fil.yml b/modules/openid_connect/config/locales/crowdin/fil.yml index 93ce786ff6a3..29f023994dd9 100644 --- a/modules/openid_connect/config/locales/crowdin/fil.yml +++ b/modules/openid_connect/config/locales/crowdin/fil.yml @@ -22,6 +22,8 @@ fil: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/fr.yml b/modules/openid_connect/config/locales/crowdin/fr.yml index db16b613cf52..bb881c512f7f 100644 --- a/modules/openid_connect/config/locales/crowdin/fr.yml +++ b/modules/openid_connect/config/locales/crowdin/fr.yml @@ -22,6 +22,8 @@ fr: plural: Fournisseurs OpenID singular: Fournisseur OpenID setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Utilisez le point de terminaison graph.microsoft.com userinfo pour demander des données d'utilisateur. Cela devrait être la valeur par défaut, sauf si vous avez une application Azure plus ancienne. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/he.yml b/modules/openid_connect/config/locales/crowdin/he.yml index 2ac3e7e742c1..fc3fa0969463 100644 --- a/modules/openid_connect/config/locales/crowdin/he.yml +++ b/modules/openid_connect/config/locales/crowdin/he.yml @@ -22,6 +22,8 @@ he: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/hi.yml b/modules/openid_connect/config/locales/crowdin/hi.yml index 77674ff1f00a..fa8d1422d68e 100644 --- a/modules/openid_connect/config/locales/crowdin/hi.yml +++ b/modules/openid_connect/config/locales/crowdin/hi.yml @@ -22,6 +22,8 @@ hi: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/hr.yml b/modules/openid_connect/config/locales/crowdin/hr.yml index 48a7c6789a30..a09f226dc7e9 100644 --- a/modules/openid_connect/config/locales/crowdin/hr.yml +++ b/modules/openid_connect/config/locales/crowdin/hr.yml @@ -22,6 +22,8 @@ hr: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/hu.yml b/modules/openid_connect/config/locales/crowdin/hu.yml index 13a9b8512c14..05d3d8760841 100644 --- a/modules/openid_connect/config/locales/crowdin/hu.yml +++ b/modules/openid_connect/config/locales/crowdin/hu.yml @@ -22,6 +22,8 @@ hu: plural: OpenID szolgáltatók singular: OpenID szolgáltató setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/id.yml b/modules/openid_connect/config/locales/crowdin/id.yml index f8717bf6ba0f..b72c30cff0ac 100644 --- a/modules/openid_connect/config/locales/crowdin/id.yml +++ b/modules/openid_connect/config/locales/crowdin/id.yml @@ -22,6 +22,8 @@ id: plural: penyedia OpenID singular: penyedia OpenID setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/it.yml b/modules/openid_connect/config/locales/crowdin/it.yml index b67d46777ac3..6b5aab6c47d8 100644 --- a/modules/openid_connect/config/locales/crowdin/it.yml +++ b/modules/openid_connect/config/locales/crowdin/it.yml @@ -22,6 +22,8 @@ it: plural: OpenID provider singular: Provider OpenID setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Usa l'endpoint userinfo di graph.microsoft.com per richiedere i dati utente. Questa dovrebbe essere l'impostazione predefinita, a meno che non si disponga di un'applicazione Azure precedente. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/ja.yml b/modules/openid_connect/config/locales/crowdin/ja.yml index 4db20b0c378e..37f0399346f1 100644 --- a/modules/openid_connect/config/locales/crowdin/ja.yml +++ b/modules/openid_connect/config/locales/crowdin/ja.yml @@ -22,6 +22,8 @@ ja: plural: OpenID プロバイダー singular: OpenID プロバイダー setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/ka.yml b/modules/openid_connect/config/locales/crowdin/ka.yml index 786d647e4b32..afba4b168687 100644 --- a/modules/openid_connect/config/locales/crowdin/ka.yml +++ b/modules/openid_connect/config/locales/crowdin/ka.yml @@ -22,6 +22,8 @@ ka: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/ko.yml b/modules/openid_connect/config/locales/crowdin/ko.yml index c12e26d41255..5dee7e2c0c97 100644 --- a/modules/openid_connect/config/locales/crowdin/ko.yml +++ b/modules/openid_connect/config/locales/crowdin/ko.yml @@ -22,6 +22,8 @@ ko: plural: OpenID 공급자 singular: OpenID 공급자 setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > graph.microsoft.com userinfo 엔드포인트를 사용하여 사용자 데이터를 요청합니다. 이전 Azure 애플리케이션이 없는 경우 이것이 기본값이어야 합니다. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/lt.yml b/modules/openid_connect/config/locales/crowdin/lt.yml index b878ffc7230c..d6eae7d9a0f3 100644 --- a/modules/openid_connect/config/locales/crowdin/lt.yml +++ b/modules/openid_connect/config/locales/crowdin/lt.yml @@ -22,6 +22,8 @@ lt: plural: OpenID tiekėjai singular: OpenID tiekėjas setting_instructions: + azure_deprecation_warning: > + Sukonfigūruota Azure aplikacija rodo į pasenusį Azure API. Prašome sukurti naują Azure aplikaciją, kad užtikrintumėte veikimą ateityje. azure_graph_api: > Naudotojo duomenų atsiuntimui naudoti graph.microsoft.com. Tai turėtų būti numatyta parinktis, nebent jūs turite senesnę azure aplikaciją. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/lv.yml b/modules/openid_connect/config/locales/crowdin/lv.yml index 0e6a4c7ce935..f1adab4fb798 100644 --- a/modules/openid_connect/config/locales/crowdin/lv.yml +++ b/modules/openid_connect/config/locales/crowdin/lv.yml @@ -22,6 +22,8 @@ lv: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/mn.yml b/modules/openid_connect/config/locales/crowdin/mn.yml index 411467b8dab0..ae939d52e6f4 100644 --- a/modules/openid_connect/config/locales/crowdin/mn.yml +++ b/modules/openid_connect/config/locales/crowdin/mn.yml @@ -22,6 +22,8 @@ mn: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/ne.yml b/modules/openid_connect/config/locales/crowdin/ne.yml index 815c72c65be1..580d012c98ce 100644 --- a/modules/openid_connect/config/locales/crowdin/ne.yml +++ b/modules/openid_connect/config/locales/crowdin/ne.yml @@ -22,6 +22,8 @@ ne: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/nl.yml b/modules/openid_connect/config/locales/crowdin/nl.yml index d3b09da0e2c9..2844afad39db 100644 --- a/modules/openid_connect/config/locales/crowdin/nl.yml +++ b/modules/openid_connect/config/locales/crowdin/nl.yml @@ -22,6 +22,8 @@ nl: plural: OpenID aanbieders singular: OpenID aanbieders setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/no.yml b/modules/openid_connect/config/locales/crowdin/no.yml index 4ad5d086116b..a2cd898b208c 100644 --- a/modules/openid_connect/config/locales/crowdin/no.yml +++ b/modules/openid_connect/config/locales/crowdin/no.yml @@ -22,6 +22,8 @@ plural: OpenID leverandører singular: OpenID-leverandør setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/pl.yml b/modules/openid_connect/config/locales/crowdin/pl.yml index a17dd6fe0df9..06bcd7de65b3 100644 --- a/modules/openid_connect/config/locales/crowdin/pl.yml +++ b/modules/openid_connect/config/locales/crowdin/pl.yml @@ -22,6 +22,8 @@ pl: plural: Dostawcy OpenID singular: Dostawca OpenID setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Użyj punktu końcowego graph.microsoft.com userinfo, aby zażądać danych użytkownika. Powinno to być ustawienie domyślne, chyba że masz starszą aplikację Azure. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/pt.yml b/modules/openid_connect/config/locales/crowdin/pt.yml index 1098a8db40d5..4a7b81f08c74 100644 --- a/modules/openid_connect/config/locales/crowdin/pt.yml +++ b/modules/openid_connect/config/locales/crowdin/pt.yml @@ -22,6 +22,8 @@ pt: plural: Provedores OpenID singular: Provedor OpenID setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use o ponto de extremidade de userinfo graph.microsoft.com para solicitar dados de usuário. Este deve ser o padrão, a menos que você tenha um aplicativo Azure mais antigo. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/ro.yml b/modules/openid_connect/config/locales/crowdin/ro.yml index b4812ab18f24..b1405d150ca5 100644 --- a/modules/openid_connect/config/locales/crowdin/ro.yml +++ b/modules/openid_connect/config/locales/crowdin/ro.yml @@ -22,6 +22,8 @@ ro: plural: Furnizori OpenID singular: Furnizor de autentificare setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/ru.yml b/modules/openid_connect/config/locales/crowdin/ru.yml index 89ecc270e7e6..35e69a9920cd 100644 --- a/modules/openid_connect/config/locales/crowdin/ru.yml +++ b/modules/openid_connect/config/locales/crowdin/ru.yml @@ -22,6 +22,8 @@ ru: plural: Провайдеры OpenID singular: Провайдер OpenID setting_instructions: + azure_deprecation_warning: > + azure_graph_api: > Используйте endpoint userinfo graph.microsoft.com для запроса пользовательских данных. Это должно быть по умолчанию, если у вас нет более старого azure. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/rw.yml b/modules/openid_connect/config/locales/crowdin/rw.yml index d7e0586dbe7f..72987f6a0411 100644 --- a/modules/openid_connect/config/locales/crowdin/rw.yml +++ b/modules/openid_connect/config/locales/crowdin/rw.yml @@ -22,6 +22,8 @@ rw: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/si.yml b/modules/openid_connect/config/locales/crowdin/si.yml index bf870d38d0b7..6a266b981812 100644 --- a/modules/openid_connect/config/locales/crowdin/si.yml +++ b/modules/openid_connect/config/locales/crowdin/si.yml @@ -22,6 +22,8 @@ si: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/sk.yml b/modules/openid_connect/config/locales/crowdin/sk.yml index b21b18ce0615..ef18447ae4a7 100644 --- a/modules/openid_connect/config/locales/crowdin/sk.yml +++ b/modules/openid_connect/config/locales/crowdin/sk.yml @@ -22,6 +22,8 @@ sk: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/sl.yml b/modules/openid_connect/config/locales/crowdin/sl.yml index 519811b0df40..e04a12b56d65 100644 --- a/modules/openid_connect/config/locales/crowdin/sl.yml +++ b/modules/openid_connect/config/locales/crowdin/sl.yml @@ -22,6 +22,8 @@ sl: plural: OpenID ponudniki singular: OpenID ponudnik setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/sr.yml b/modules/openid_connect/config/locales/crowdin/sr.yml index e78211d4a5b6..ed1c2895c77a 100644 --- a/modules/openid_connect/config/locales/crowdin/sr.yml +++ b/modules/openid_connect/config/locales/crowdin/sr.yml @@ -22,6 +22,8 @@ sr: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/sv.yml b/modules/openid_connect/config/locales/crowdin/sv.yml index 6c3332572b7c..cc3bfed34d3c 100644 --- a/modules/openid_connect/config/locales/crowdin/sv.yml +++ b/modules/openid_connect/config/locales/crowdin/sv.yml @@ -22,6 +22,8 @@ sv: plural: OpenID leverantörer singular: OpenID leverantör setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Använd graph.microsoft.com "userinfo"-endpointen för att be om användardata. Det här bör vara standard om du inte har en äldre version av azure. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/th.yml b/modules/openid_connect/config/locales/crowdin/th.yml index 0268326862e1..9f6b6e51e95c 100644 --- a/modules/openid_connect/config/locales/crowdin/th.yml +++ b/modules/openid_connect/config/locales/crowdin/th.yml @@ -22,6 +22,8 @@ th: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/tr.yml b/modules/openid_connect/config/locales/crowdin/tr.yml index e2cff2f65260..0546fac1f41b 100644 --- a/modules/openid_connect/config/locales/crowdin/tr.yml +++ b/modules/openid_connect/config/locales/crowdin/tr.yml @@ -22,6 +22,8 @@ tr: plural: OpenID sağlayıcıları singular: OpenID sağlayıcı setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/uk.yml b/modules/openid_connect/config/locales/crowdin/uk.yml index fd1fb120ac27..470fcefe1d33 100644 --- a/modules/openid_connect/config/locales/crowdin/uk.yml +++ b/modules/openid_connect/config/locales/crowdin/uk.yml @@ -22,6 +22,8 @@ uk: plural: Постачальники OpenID singular: OpenID постачальник setting_instructions: + azure_deprecation_warning: > + Налаштована програма Azure вказує на застарілий API від Azure. Будь ласка, створіть новий додаток Azure, щоб забезпечити функціональність у майбутньому. azure_graph_api: > Надсилайте запити на дані користувачів за допомогою кінцевої точки graph.microsoft.com userinfo. Це налаштування має бути ввімкнено за замовчуванням в усіх версія Azure, крім старіших. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/vi.yml b/modules/openid_connect/config/locales/crowdin/vi.yml index 124905d5e0e7..2b21fe461371 100644 --- a/modules/openid_connect/config/locales/crowdin/vi.yml +++ b/modules/openid_connect/config/locales/crowdin/vi.yml @@ -22,6 +22,8 @@ vi: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/zh-CN.yml b/modules/openid_connect/config/locales/crowdin/zh-CN.yml index cad0d57b0e34..1c88a7908b92 100644 --- a/modules/openid_connect/config/locales/crowdin/zh-CN.yml +++ b/modules/openid_connect/config/locales/crowdin/zh-CN.yml @@ -22,6 +22,8 @@ zh-CN: plural: OpenID 提供商 singular: OpenID 提供商 setting_instructions: + azure_deprecation_warning: > + 配置的 Azure 应用程序指向 Azure 中已弃用的 API 。请创建一个新的 Azure 应用程序,以确保未来的功能性。 azure_graph_api: > 使用 graph.microsoft.com userinfo 端点请求用户数据。除非您有更低版本的 Azure 应用程序,否则这应该是默认设置。 azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/crowdin/zh-TW.yml b/modules/openid_connect/config/locales/crowdin/zh-TW.yml index 89baf09b2be4..27e972008cbe 100644 --- a/modules/openid_connect/config/locales/crowdin/zh-TW.yml +++ b/modules/openid_connect/config/locales/crowdin/zh-TW.yml @@ -22,6 +22,8 @@ zh-TW: plural: OpenID 提供者 singular: OpenID 提供者 setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/openid_connect/config/locales/en.yml b/modules/openid_connect/config/locales/en.yml index faada1e506c2..7c9185c3ef1d 100644 --- a/modules/openid_connect/config/locales/en.yml +++ b/modules/openid_connect/config/locales/en.yml @@ -23,6 +23,8 @@ en: plural: OpenID providers singular: OpenID provider setting_instructions: + azure_deprecation_warning: > + The configured Azure app points to a deprecated API from Azure. Please create a new Azure app to ensure the functionality in future. azure_graph_api: > Use the graph.microsoft.com userinfo endpoint to request userdata. This should be the default unless you have an older azure application. azure_tenant_html: > diff --git a/modules/reporting/config/locales/crowdin/ca.yml b/modules/reporting/config/locales/crowdin/ca.yml index 7da9fa022e6c..bcd2505bda76 100644 --- a/modules/reporting/config/locales/crowdin/ca.yml +++ b/modules/reporting/config/locales/crowdin/ca.yml @@ -86,7 +86,7 @@ ca: validation_failure_integer: "no és un enter vàlid" export: cost_reports: - title: "Your Cost Reports XLS export" + title: "La vostra exportació de l'informe de costos XLS" reporting: group_by: selected_columns: "Columnes seleccionades" diff --git a/modules/reporting/config/locales/crowdin/nl.yml b/modules/reporting/config/locales/crowdin/nl.yml index 1662658b15e1..90539570629b 100644 --- a/modules/reporting/config/locales/crowdin/nl.yml +++ b/modules/reporting/config/locales/crowdin/nl.yml @@ -86,7 +86,7 @@ nl: validation_failure_integer: "is geen geldig geheel getal" export: cost_reports: - title: "Your Cost Reports XLS export" + title: "Jouw kostenrapporten XLS export" reporting: group_by: selected_columns: "Geselecteerde kolommen" diff --git a/modules/reporting/config/locales/crowdin/sk.yml b/modules/reporting/config/locales/crowdin/sk.yml index ca273c506cba..29605795993b 100644 --- a/modules/reporting/config/locales/crowdin/sk.yml +++ b/modules/reporting/config/locales/crowdin/sk.yml @@ -72,7 +72,7 @@ sk: label_inactive: "«neaktívny»" label_no: "Nie" label_none: "(žiadne údaje)" - label_no_reports: "There are no cost reports yet." + label_no_reports: "Zatiaľ nie sú k dispozícii žiadne výkazy nákladov." label_report: "Report" label_yes: "Áno" load_query_question: "Výsledná tlačová zostava bude obsahovať %{size} buniek a jej vytvorenie môže trvať dlhšie. Želáte si ju aj napriek tomu vygenerovať?" @@ -86,7 +86,7 @@ sk: validation_failure_integer: "nie je platné celé číslo" export: cost_reports: - title: "Your Cost Reports XLS export" + title: "Váš XLS export správy o nákladoch" reporting: group_by: selected_columns: "Vybrané stĺpce" diff --git a/modules/reporting/config/locales/crowdin/tr.yml b/modules/reporting/config/locales/crowdin/tr.yml index 4f0c90a31f55..4402679d1ca8 100644 --- a/modules/reporting/config/locales/crowdin/tr.yml +++ b/modules/reporting/config/locales/crowdin/tr.yml @@ -86,7 +86,7 @@ tr: validation_failure_integer: "geçerli bir tamsayı değil" export: cost_reports: - title: "Your Cost Reports XLS export" + title: "Maliyet Raporlarınızın XLS çıktısı" reporting: group_by: selected_columns: "Seçilen sütunlar" diff --git a/modules/storages/app/models/storages/nextcloud_storage.rb b/modules/storages/app/models/storages/nextcloud_storage.rb index acd2d42025bc..31ab532ff987 100644 --- a/modules/storages/app/models/storages/nextcloud_storage.rb +++ b/modules/storages/app/models/storages/nextcloud_storage.rb @@ -45,9 +45,14 @@ def self.sync_all_group_folders timeout_seconds: 0, transaction: false) do where("provider_fields->>'automatically_managed' = 'true'") + .order(:created_at) .includes(:oauth_client) .each do |storage| Storages::GroupFolderPropertiesSyncService.new(storage).call + rescue StandardError => e + OpenProject.logger.error( + "Unexpected error during NextcloudStorage group folders sync for ##{storage.id} #{storage.host}: #{e.message}" + ) end true end diff --git a/modules/storages/config/locales/crowdin/cs.yml b/modules/storages/config/locales/crowdin/cs.yml index fe5716c52e0a..bf2982df29dc 100644 --- a/modules/storages/config/locales/crowdin/cs.yml +++ b/modules/storages/config/locales/crowdin/cs.yml @@ -1,7 +1,7 @@ #English strings go here cs: plugin_openproject_storages: - name: "OpenProject Storages" + name: "Úložiště OpenProject" description: "Allows linking work packages to files in external storages, such as Nextcloud." permission_view_file_links: "Zobrazit odkazy na soubor" permission_manage_file_links: "Správa odkazů souborů" @@ -35,7 +35,7 @@ cs: storages/project_storage: attributes: project_folder_mode: - mode_unavailable: "is not available for this storage." + mode_unavailable: "není k dispozici pro toto úložiště." storages/storage: attributes: host: @@ -138,7 +138,7 @@ cs: label_provider_type: "Typ poskytovatele" label_project_folder: "Složka projektu" label_new_storage: "Nové úložiště" - label_edit_storage: "Edit storage" + label_edit_storage: "" label_existing_manual_folder: "Existing folder with manually managed permissions" label_no_specific_folder: "Žádná specifická složka" label_automatic_folder: "New folder with automatically managed permissions" diff --git a/modules/storages/config/locales/crowdin/ka.yml b/modules/storages/config/locales/crowdin/ka.yml index fcfbd36a5d58..3f61cb14cb8b 100644 --- a/modules/storages/config/locales/crowdin/ka.yml +++ b/modules/storages/config/locales/crowdin/ka.yml @@ -64,7 +64,7 @@ ka: edit_automatically_managed_project_folders: "Edit automatically managed project folders" replace_openproject_oauth: "Replace OpenProject OAuth" replace_provider_type_oauth: "Replace %{provider_type} OAuth" - save: "Save" + save: "შენახვა" save_and_continue_setup: "Save and continue setup" save_and_complete_setup: "Save and complete setup" select_folder: "Select folder" diff --git a/modules/storages/config/locales/crowdin/ru.yml b/modules/storages/config/locales/crowdin/ru.yml index 6afad9cbe86d..39cf498b712f 100644 --- a/modules/storages/config/locales/crowdin/ru.yml +++ b/modules/storages/config/locales/crowdin/ru.yml @@ -35,7 +35,7 @@ ru: storages/project_storage: attributes: project_folder_mode: - mode_unavailable: "is not available for this storage." + mode_unavailable: "не доступен для этого хранилища." storages/storage: attributes: host: diff --git a/modules/storages/config/locales/crowdin/uk.yml b/modules/storages/config/locales/crowdin/uk.yml index 5b02a57526f3..a7f0bf4fcfcc 100644 --- a/modules/storages/config/locales/crowdin/uk.yml +++ b/modules/storages/config/locales/crowdin/uk.yml @@ -1,8 +1,8 @@ #English strings go here uk: plugin_openproject_storages: - name: "OpenProject Storages" - description: "Allows linking work packages to files in external storages, such as Nextcloud." + name: "Сховища OpenProject" + description: "" permission_view_file_links: "Перегляд посилань на файл" permission_manage_file_links: "Керування посиланнями на файл" permission_manage_storages_in_project: "Керування файловими сховищами в проєкті" @@ -64,7 +64,7 @@ uk: edit_automatically_managed_project_folders: "Редагувати папки проєкту з автоматичним керуванням" replace_openproject_oauth: "Замінити OpenProject OAuth" replace_provider_type_oauth: "Замінити %{provider_type} OAuth" - save: "Save" + save: "Зберегти" save_and_continue_setup: "Зберегти й продовжити налаштування" save_and_complete_setup: "Зберегти й завершити налаштування" select_folder: "Вибрати папку" diff --git a/modules/storages/spec/models/nextcloud_storage_spec.rb b/modules/storages/spec/models/nextcloud_storage_spec.rb index 6ac1574162e3..0fd80e8563e7 100644 --- a/modules/storages/spec/models/nextcloud_storage_spec.rb +++ b/modules/storages/spec/models/nextcloud_storage_spec.rb @@ -90,6 +90,26 @@ expect(Storages::GroupFolderPropertiesSyncService).to have_received(:new).with(storage1).once expect(Storages::GroupFolderPropertiesSyncService).not_to have_received(:new).with(storage2) end + + it 'continues synchronization for other storages if previous one raises an exception' do + storage1 = create(:nextcloud_storage, :as_automatically_managed) + storage3 = create(:nextcloud_storage, :as_automatically_managed) + + allow(OpenProject.logger).to receive(:error) + allow(Storages::GroupFolderPropertiesSyncService).to receive(:new).and_call_original + allow(Storages::GroupFolderPropertiesSyncService) + .to receive(:new) + .with(storage1) + .and_raise(RuntimeError.new("Unexpected Error")) + allow_any_instance_of(Storages::GroupFolderPropertiesSyncService).to receive(:call).and_return(nil) # rubocop:disable RSpec/AnyInstance + expect(subject).to be(true) + + expect(OpenProject.logger).to have_received(:error) do |msg, _| + expect(msg).to eq "Unexpected error during NextcloudStorage group folders sync for ##{storage1.id} #{storage1.host}: Unexpected Error" + end + expect(Storages::GroupFolderPropertiesSyncService).to have_received(:new).with(storage1).once + expect(Storages::GroupFolderPropertiesSyncService).to have_received(:new).with(storage3).once + end end context 'when lock is unfree' do diff --git a/modules/team_planner/config/locales/crowdin/bg.yml b/modules/team_planner/config/locales/crowdin/bg.yml index 015e7959de9f..509770de05de 100644 --- a/modules/team_planner/config/locales/crowdin/bg.yml +++ b/modules/team_planner/config/locales/crowdin/bg.yml @@ -3,15 +3,15 @@ bg: plugin_openproject_team_planner: name: "OpenProject Team Planner" description: "Provides team planner views." - permission_view_team_planner: "View team planner" - permission_manage_team_planner: "Manage team planner" - project_module_team_planner_view: "Team planners" + permission_view_team_planner: "Вижте екипния плановик" + permission_manage_team_planner: "Управлявайте екипния плановик" + project_module_team_planner_view: "Екипни плановици" team_planner: - label_team_planner: "Team planner" - label_new_team_planner: "New team planner" - label_create_new_team_planner: "Create new team planner" - label_team_planner_plural: "Team planners" - label_assignees: "Assignees" + label_team_planner: "Екипен плановик" + label_new_team_planner: "Нов екипен плановик" + label_create_new_team_planner: "Създайте нов екипен плановик" + label_team_planner_plural: "Екипни плановици" + label_assignees: "Правоприемници" upsale: - title: "Team planner" - description: "Get a complete overview of your team’s planning with Team Planner. Stretch, shorten and drag-and-drop work packages to modify dates, move them or change assignees." + title: "Екипен плановик" + description: "Получете пълен преглед на планирането на вашия екип с Team Planner. Разтягайте, съкращавайте и плъзгайте и пускайте работни пакети, за да промените датите, да ги преместите или да промените възложителите." diff --git a/modules/webhooks/config/locales/crowdin/bg.yml b/modules/webhooks/config/locales/crowdin/bg.yml index e0f508bcac23..dad255c375e8 100644 --- a/modules/webhooks/config/locales/crowdin/bg.yml +++ b/modules/webhooks/config/locales/crowdin/bg.yml @@ -1,7 +1,7 @@ bg: plugin_openproject_webhooks: - name: "OpenProject Webhooks" - description: "Provides a plug-in API to support OpenProject webhooks for better 3rd party integration." + name: "OpenProject уеб-куки" + description: "Осигурява приставка API, за поддръжка на OpenProject веб-куки, за по-добра интеграция на трети страни." activerecord: attributes: webhooks/webhook: diff --git a/modules/webhooks/config/locales/crowdin/cs.yml b/modules/webhooks/config/locales/crowdin/cs.yml index e104a2118c1c..2d3a7224622b 100644 --- a/modules/webhooks/config/locales/crowdin/cs.yml +++ b/modules/webhooks/config/locales/crowdin/cs.yml @@ -42,7 +42,7 @@ cs: deliveries: no_results_table: Pro tento webhook nebyly provedeny žádné dodávky. title: 'Nedávné dodávky' - time: 'Dodací doba' + time: 'Delivery time' form: introduction: > Pošlete POST požadavek na URL adresu payload pro jakoukoliv událost v projektu, ke kterému jste přihlášeni. Užitečné zatížení bude odpovídat reprezentaci modifikovaného objektu APIv3. diff --git a/modules/webhooks/config/locales/crowdin/uk.yml b/modules/webhooks/config/locales/crowdin/uk.yml index 50e835b4247b..c5e26f7a79c1 100644 --- a/modules/webhooks/config/locales/crowdin/uk.yml +++ b/modules/webhooks/config/locales/crowdin/uk.yml @@ -1,7 +1,7 @@ uk: plugin_openproject_webhooks: - name: "OpenProject Webhooks" - description: "Provides a plug-in API to support OpenProject webhooks for better 3rd party integration." + name: "Вебгуки OpenProject" + description: "Надає плагіну API для підтримки вебгуків OpenProject для кращої інтеграції сторонніх розробників." activerecord: attributes: webhooks/webhook: diff --git a/modules/xls_export/config/locales/crowdin/bg.yml b/modules/xls_export/config/locales/crowdin/bg.yml index bb5178414b89..a8370409dd4c 100644 --- a/modules/xls_export/config/locales/crowdin/bg.yml +++ b/modules/xls_export/config/locales/crowdin/bg.yml @@ -1,16 +1,16 @@ bg: plugin_openproject_xls_export: - name: "OpenProject XLS Export" - description: "Export issue lists as Excel spreadsheets (.xls)." + name: "Експортиране на OpenProject XLS" + description: "Експортирайте списъци с проблеми като електронни таблици на Excel (.xls)." export_to_excel: "Експорт XLS" print_with_description: "Преглед преди печат с описание" - sentence_separator_or: "or" + sentence_separator_or: "или" different_formats: Различни формати export: format: xls: "XLS" xls_with_descriptions: "XLS с описания" - xls_with_relations: "XLS with relations" + xls_with_relations: "XLS с отношения" xls_export: child_of: дете на parent_of: родител на diff --git a/modules/xls_export/config/locales/crowdin/cs.yml b/modules/xls_export/config/locales/crowdin/cs.yml index 62de048e6212..11c270d68a27 100644 --- a/modules/xls_export/config/locales/crowdin/cs.yml +++ b/modules/xls_export/config/locales/crowdin/cs.yml @@ -1,6 +1,6 @@ cs: plugin_openproject_xls_export: - name: "OpenProject XLS Export" + name: "Export OpenProject XLS" description: "Export issue lists as Excel spreadsheets (.xls)." export_to_excel: "Exportovat XLS" print_with_description: "Tisk náhledu s popisem" diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index c87edf1c96fc..8105d49acc47 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -29,7 +29,7 @@ require 'spec_helper' RSpec.describe ApplicationController do - let(:user) { create(:user, lastname: "Crazy! Name with \r\n Newline") } + let(:user) { create(:user, lastname: "Crazy name") } # Fake controller to test calling an action controller do @@ -41,8 +41,7 @@ def index describe 'logging requesting users' do let(:user_message) do - "OpenProject User: #{user.firstname} Crazy! Name with ## " + - "Newline (#{user.login} ID: #{user.id} <#{user.mail}>)" + "OpenProject User: #{user.firstname} Crazy name (#{user.login} ID: #{user.id} <#{user.mail}>)" end let(:anonymous_message) { 'OpenProject User: Anonymous' } diff --git a/spec/controllers/messages_controller_spec.rb b/spec/controllers/messages_controller_spec.rb index 785d4b4d7ed4..de52f693c778 100644 --- a/spec/controllers/messages_controller_spec.rb +++ b/spec/controllers/messages_controller_spec.rb @@ -173,7 +173,10 @@ end it 'escapes HTML in quoted message author' do - user.update!(firstname: 'Hello', lastname: 'world') + user.firstname = 'Hello' + user.lastname = 'world' + user.save! validate: false + message.update!(author: user) get :quote, params: { forum_id: forum.id, id: message.id }, format: :json diff --git a/spec/features/members/membership_spec.rb b/spec/features/members/membership_spec.rb index 12592acaa57d..8fabb0c73142 100644 --- a/spec/features/members/membership_spec.rb +++ b/spec/features/members/membership_spec.rb @@ -54,16 +54,11 @@ preferences: { hide_mail: true }) end let!(:developer_placeholder) { create(:placeholder_user, name: 'Developer 1') } - let!(:crash) do - create(:user, - firstname: "", - lastname: "") - end let!(:group) do create(:group, lastname: 'A-Team', members: [peter, hannibal]) end - let!(:manager) { create(:role, name: 'Manager', permissions: [:manage_members]) } + let!(:manager) { create(:role, name: 'Manager', permissions: [:manage_members]) } let!(:developer) { create(:role, name: 'Developer') } let(:member1) { create(:member, principal: peter, project:, roles: [manager]) } let(:member2) { create(:member, principal: hannibal, project:, roles: [developer]) } @@ -165,14 +160,4 @@ members_page.search_principal! 'Smith, H' expect(members_page).to have_search_result 'Hannibal Smith' end - - it 'Escaping should work properly when entering a name' do - members_page.open_new_member! - SeleniumHubWaiter.wait - - members_page.search_principal! 'script' - - expect(members_page).not_to have_alert_dialog - expect(members_page).to have_search_result "" - end end diff --git a/spec/features/work_packages/table/baseline/baseline_query_spec.rb b/spec/features/work_packages/table/baseline/baseline_query_spec.rb index e864b45e42d1..912d3e7bae76 100644 --- a/spec/features/work_packages/table/baseline/baseline_query_spec.rb +++ b/spec/features/work_packages/table/baseline/baseline_query_spec.rb @@ -48,12 +48,25 @@ member_with_permissions: %i[view_work_packages save_queries manage_public_queries]) end + # 1 or 2 depending on daylight saving time + shared_let(:berlin_hours_offset) { berlin_user.time_zone.tzinfo.observed_utc_offset / 3600 } + # "+01:00" or "+02:00" depending on daylight saving time + shared_let(:berlin_time_offset) { "+0#{berlin_hours_offset}:00" } + # "UTC+1" or "UTC+2" depending on daylight saving time + shared_let(:berlin_utc_offset) { "UTC+#{berlin_hours_offset}" } + shared_let(:tokyo_user) do create(:user, preferences: { time_zone: 'Asia/Tokyo' }, member_in_project: project, member_with_permissions: %i[view_work_packages save_queries manage_public_queries]) end + # always 9 as Japan does not observe daylight saving time + shared_let(:tokyo_hours_offset) { tokyo_user.time_zone.tzinfo.observed_utc_offset / 3600 } + # always "+09:00" + shared_let(:tokyo_time_offset) { "+0#{tokyo_hours_offset}:00" } + # always "UTC+9" + shared_let(:tokyo_utc_offset) { "UTC+#{tokyo_hours_offset}" } it 'shows a warning when an incompatible filter is used' do login_as berlin_user @@ -67,7 +80,7 @@ baseline_modal.select_filter 'yesterday' baseline_modal.set_time '09:00' - baseline_modal.expect_offset 'UTC+2' + baseline_modal.expect_offset berlin_utc_offset baseline_modal.apply loading_indicator_saveguard @@ -77,7 +90,7 @@ loading_indicator_saveguard - expect(page).to have_selector( + expect(page).to have_css( '.op-toast.-warning', text: 'Baseline mode is on but some of your active filters are not included in the comparison.' ) @@ -98,7 +111,7 @@ baseline_modal.select_filter 'yesterday' baseline_modal.set_time '09:00' - baseline_modal.expect_offset 'UTC+2' + baseline_modal.expect_offset berlin_utc_offset baseline_modal.apply loading_indicator_saveguard @@ -109,33 +122,35 @@ baseline_modal.toggle_drop_modal baseline_modal.expect_closed baseline.expect_legends - baseline.expect_legend_text "Changes since yesterday (#{Date.yesterday.iso8601} 9:00 AM UTC+2)" - expect(page).to have_selector(".op-baseline-legends--details-added", text: 'Now meets filter criteria (1)') - expect(page).to have_selector(".op-baseline-legends--details-removed", text: 'No longer meets filter criteria (0)') - expect(page).to have_selector(".op-baseline-legends--details-changed", text: 'Maintained with changes (0)') + baseline.expect_legend_text "Changes since yesterday (#{Date.yesterday.iso8601} 9:00 AM #{berlin_utc_offset})" + expect(page).to have_css(".op-baseline-legends--details-added", text: 'Now meets filter criteria (1)') + expect(page).to have_css(".op-baseline-legends--details-removed", text: 'No longer meets filter criteria (0)') + expect(page).to have_css(".op-baseline-legends--details-changed", text: 'Maintained with changes (0)') wp_table.save_as 'Baseline query' wp_table.expect_and_dismiss_toaster(message: 'Successful creation.') query = retry_block { Query.find_by! name: 'Baseline query' } - expect(query.timestamps.map(&:to_s)).to eq ['oneDayAgo@09:00+02:00', 'PT0S'] + expect(query.timestamps.map(&:to_s)).to eq ["oneDayAgo@09:00#{berlin_time_offset}", 'PT0S'] query.update! public: true login_as tokyo_user wp_table.visit_query query - baseline.expect_legend_text "Changes since yesterday (#{Date.yesterday.iso8601} 9:00 AM UTC+2)" - baseline.expect_legend_tooltip "In your local timezone: #{Date.yesterday.iso8601} 4:00 PM UTC+9" + baseline.expect_legend_text "Changes since yesterday (#{Date.yesterday.iso8601} 9:00 AM #{berlin_utc_offset})" + expected_tokyo_time = berlin_user.time_zone.tzinfo.dst? ? "4:00" : "5:00" + baseline.expect_legend_tooltip "In your local timezone: " \ + "#{Date.yesterday.iso8601} #{expected_tokyo_time} PM #{tokyo_utc_offset}" baseline_modal.expect_closed baseline_modal.toggle_drop_modal baseline_modal.expect_open baseline_modal.expect_selected 'yesterday' baseline_modal.expect_selected_time '09:00' - baseline_modal.expect_offset 'UTC+2' + baseline_modal.expect_offset berlin_utc_offset baseline_modal.select_filter '-' baseline_modal.select_filter 'yesterday' - baseline_modal.expect_offset 'UTC+9' + baseline_modal.expect_offset tokyo_utc_offset baseline_modal.select_filter '-' baseline_modal.apply @@ -152,7 +167,7 @@ baseline_modal.toggle_drop_modal baseline_modal.expect_open baseline_modal.select_filter 'a specific date' - baseline_modal.expect_offset 'UTC+9' + baseline_modal.expect_offset tokyo_utc_offset baseline_modal.set_time '06:00' baseline_modal.set_date '2023-05-20' baseline_modal.apply @@ -179,6 +194,12 @@ baseline_modal.expect_time_help_text "In your local time: 2023-05-19 11:00 PM" baseline_modal.select_filter 'between two specific dates' + # TODO: on the 2023-05-19, utc offset is +2 hours. But when current date is + # outside of DST (from November to February for instance), then on time + # selection input the displayed offset is UTC+1. While technically ok, it + # would be better to change the offset depending on the selected date: here + # UTC+2 offset should be used so that 8:00 is really 8:00 in Berlin on this + # date, and not 9:00 (because 8:00 UTC+1 is 9:00 UTC+2). baseline_modal.set_between_dates from: '2023-05-19', to: '2023-05-25', from_time: '08:00', @@ -192,12 +213,15 @@ wp_table.expect_and_dismiss_toaster(message: 'Successful update.') query.reload - expect(query.timestamps.map(&:to_s)).to eq ['2023-05-19T08:00+02:00', '2023-05-25T20:00+02:00'] + expect(query.timestamps.map(&:to_s)).to eq ["2023-05-19T08:00#{berlin_time_offset}", "2023-05-25T20:00#{berlin_time_offset}"] login_as tokyo_user wp_table.visit_query query - baseline.expect_legend_text "Changes between 2023-05-19 8:00 AM UTC+2 and 2023-05-25 8:00 PM UTC+2" - baseline.expect_legend_tooltip "In your local timezone: 2023-05-19 3:00 PM UTC+9 - 2023-05-26 3:00 AM UTC+9" + baseline.expect_legend_text "Changes between 2023-05-19 8:00 AM #{berlin_utc_offset} " \ + "and 2023-05-25 8:00 PM #{berlin_utc_offset}" + expected_tokyo_time = berlin_user.time_zone.tzinfo.dst? ? "3:00" : "4:00" + baseline.expect_legend_tooltip "In your local timezone: 2023-05-19 #{expected_tokyo_time} PM #{tokyo_utc_offset} " \ + "- 2023-05-26 #{expected_tokyo_time} AM #{tokyo_utc_offset}" baseline_modal.expect_closed baseline_modal.toggle_drop_modal @@ -208,6 +232,6 @@ from_time: '08:00', to_time: '20:00' - baseline_modal.expect_offset 'UTC+2', count: 2 + baseline_modal.expect_offset berlin_utc_offset, count: 2 end end diff --git a/spec/features/work_packages/tabs/watcher_tab_spec.rb b/spec/features/work_packages/tabs/watcher_tab_spec.rb index 593d20eeff23..74f2fc2343dd 100644 --- a/spec/features/work_packages/tabs/watcher_tab_spec.rb +++ b/spec/features/work_packages/tabs/watcher_tab_spec.rb @@ -86,6 +86,7 @@ def expect_button_is_not_watching context 'with a user with arbitrary characters' do let!(:html_user) do create(:user, + :skip_validations, firstname: 'foo', member_in_project: project, member_through_role: role) diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 3e92c93b8b4a..6c7eb49999bb 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -176,7 +176,8 @@ describe '.authoring_at' do it 'escapes html from author name' do created = '2023-06-02' - author = create(:user, firstname: 'Hello', lastname: 'world') + author = build(:user, firstname: 'Hello', lastname: 'world') + author.save! validate: false expect(authoring_at(created, author)) .to eq("Added by <b>Hello</b> world at 2023-06-02") end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 2f628a7b9ddb..2ee8f99a0adb 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -252,6 +252,44 @@ end end + describe 'name validation' do + let(:user) do + build(:user) + end + + it 'restricts some options', :aggregate_failures do + [ + 'http://foobar.com', + '', + 'https://hello.com' + ].each do |name| + user.firstname = name + user.lastname = name + expect(user).not_to be_valid + expect(user.errors.symbols_for(:firstname)).to eq [:invalid] + expect(user.errors.symbols_for(:lastname)).to eq [:invalid] + end + end + + it 'allows a lot of options', :aggregate_failures do + [ + "Tim O'Reilly", + "🔴Emojinames", + "山本由紀夫", + "Татьяна", + "Users with spaces", + "Müller, Phd.", + "@invited+user.com", + "Foo & Bar", + "T’Oole" + ].each do |name| + user.firstname = name + user.lastname = name + expect(user).to be_valid + end + end + end + describe '#name' do let(:user) do create(:user, diff --git a/spec/models/users/scopes/having_reminder_mail_to_send_spec.rb b/spec/models/users/scopes/having_reminder_mail_to_send_spec.rb index 850dde0744e0..1d8b9a4bbac8 100644 --- a/spec/models/users/scopes/having_reminder_mail_to_send_spec.rb +++ b/spec/models/users/scopes/having_reminder_mail_to_send_spec.rb @@ -48,7 +48,7 @@ let(:paris_user) do create( :user, - firstname: 'Europe/Paris', + firstname: 'Europe-Paris', preferences: { time_zone: "Europe/Paris", workdays: paris_user_workdays, @@ -154,7 +154,7 @@ let(:hawaii_user) do create( :user, - firstname: 'Pacific/Honolulu', + firstname: 'Pacific-Honolulu', preferences: { time_zone: "Pacific/Honolulu", workdays: hawaii_user_workdays, @@ -230,7 +230,7 @@ let(:samoa_user) do create( :user, - firstname: 'Pacific/Apia', + firstname: 'Pacific-Apia', preferences: { time_zone: "Pacific/Apia", workdays: samoa_user_workdays, @@ -266,7 +266,7 @@ let(:moscow_user) do create( :user, - firstname: 'Europe/Moscow', + firstname: 'Europe-Moscow', preferences: { time_zone: "Europe/Moscow", daily_reminders: { @@ -370,7 +370,7 @@ let(:paris_user) do create( :user, - firstname: 'Europe/Paris', + firstname: 'Europe-Paris', preferences: { time_zone: "Europe/Paris" } @@ -389,7 +389,7 @@ let(:paris_user) do create( :user, - firstname: 'Europe/Paris', + firstname: 'Europe-Paris', preferences: { time_zone: "Europe/Paris" } @@ -408,7 +408,7 @@ let(:kathmandu_user) do create( :user, - firstname: 'Asia/Kathmandu', + firstname: 'Asia-Kathmandu', preferences: { time_zone: "Asia/Kathmandu", daily_reminders: { @@ -436,7 +436,7 @@ let(:kathmandu_user) do create( :user, - firstname: 'Asia/Kathmandu', + firstname: 'Asia-Kathmandu', preferences: { time_zone: "Asia/Kathmandu", daily_reminders: { @@ -464,7 +464,7 @@ let(:kathmandu_user) do create( :user, - firstname: 'Asia/Kathmandu', + firstname: 'Asia-Kathmandu', preferences: { time_zone: "Asia/Kathmandu", daily_reminders: { @@ -557,7 +557,7 @@ let(:paris_user) do create( :user, - firstname: 'Europe/Paris', + firstname: 'Europe-Paris', preferences: { daily_reminders: { enabled: true, @@ -577,7 +577,7 @@ let(:paris_user) do create( :user, - firstname: 'Europe/Paris', + firstname: 'Europe-Paris', preferences: { time_zone: '', daily_reminders: { @@ -598,7 +598,7 @@ let(:paris_user) do create( :user, - firstname: 'Europe/Paris', + firstname: 'Europe-Paris', preferences: {} ) end @@ -614,7 +614,7 @@ let(:paris_user) do create( :user, - firstname: 'Europe/Paris', + firstname: 'Europe-Paris', preferences: {} ) end @@ -632,7 +632,7 @@ let(:moscow_user) do create( :user, - firstname: 'Europe/Moscow', + firstname: 'Europe-Moscow', preferences: { daily_reminders: { enabled: true,