Compare commits

...

29 Commits

Author SHA1 Message Date
Martin Gruner
e91a7cae53 Release Zammad 5.2.1. 🚀 2022-07-05 09:25:50 +02:00
Martin Gruner
22cd7ccf3e Maintenance: Refactored handling of login_failed counter. 2022-07-04 18:20:12 +00:00
Mantas Masalskis
e7b06654fd Maintenance: Refactored attachment handling
(cherry picked from commit 26f7a45e9b6457985bed2157447977801923d29e)
2022-07-04 18:20:12 +00:00
Martin Gruner
ccff1354ba Maintenance: Improve configuration of rack_attack.
(cherry picked from commit a41170308a8ba0c66465c74ca53217a3bbd68537)
2022-07-04 18:20:12 +00:00
Rolf Schmidt
0c1d519c5a Maintenance: Improve search controller for customer organization search. 2022-07-04 18:20:12 +00:00
Mantas
0a0f22ec94 Fixes #4159 - Allow very long email address 2022-07-04 19:51:05 +03:00
Martin Gruner
2628fee273 Fixes: #4158 - Elasticsearch 8 incompatible with Zammad 5.2.
(cherry picked from commit c29751907a)
2022-07-04 13:01:45 +02:00
Weblate
68c3bcad6c Maintenance: Translations update from translations.zammad.org.
Special thanks to the amazing translation team. You rock! 💪

Co-authored-by: Ivan Perovic <ip@zammad.com>
Co-authored-by: JPB <jeffreypeerboom@eijsden-margraten.nl>
Co-authored-by: LAO <sumonchai@gmail.com>
Translate-URL: https://translations.zammad.org/projects/zammad/zammad-stable/hr/
Translate-URL: https://translations.zammad.org/projects/zammad/zammad-stable/nl/
Translate-URL: https://translations.zammad.org/projects/zammad/zammad-stable/th/
Translation: Zammad/Zammad (stable version)
2022-07-04 10:42:23 +02:00
Martin Gruner
6e4a52b9d2 Maintenance: Improve CI service container configuration.
(cherry picked from commit 488f5c027b)
2022-07-01 10:49:06 +02:00
Rolf Schmidt
6a1a5fc02e Performance: Readd authorizations caching (0b6010c390). 2022-06-30 17:51:17 +02:00
Rolf Schmidt
215d1a42bc Performance: Faster updates because core workflow assets are not needed to be generated on validation. 2022-06-30 17:50:56 +02:00
Florian Liebe
caec9d4328 Fixes #4100 - Selecting group permission "full" behaves differently in user- and role-management. 2022-06-30 16:52:00 +02:00
Weblate
045c5145ad Maintenance: Translations update from translations.zammad.org.
Special thanks to the amazing translation team. You rock! 💪

Co-authored-by: Ivan Perovic <ip@zammad.com>
Co-authored-by: Wim Deprez <wim@tamale.nl>
Translate-URL: https://translations.zammad.org/projects/zammad/zammad-stable/hr/
Translate-URL: https://translations.zammad.org/projects/zammad/zammad-stable/nl/
Translation: Zammad/Zammad (stable version)
2022-06-30 11:21:00 +02:00
Rolf Schmidt
743b98213e Fixes #4153 - Trigger Attribute "action > is > updated" is not working after Zammad 5.2 update. 2022-06-30 10:01:04 +02:00
Rolf Schmidt
960910fef7 Performance: Rollback old attributes_with_association_ids caching logic and... 2022-06-30 08:34:16 +02:00
Mantas Masalskis
fb1ac41210 Fixes #4151 - cannot process emails with special characters in local part 2022-06-29 22:03:59 +03:00
Florian Liebe
b62c81e55a Fixes #4140 - No error message is shown if the mandatory role field is missing during creating/updating overviews. 2022-06-29 15:55:05 +02:00
Martin Gruner
e6eb44170b Maintenance: Bump selenium-webdriver from 4.2.1 to 4.3.0
Bumps [selenium-webdriver](https://github.com/SeleniumHQ/selenium) from 4.2.1 to 4.3.0.
- [Release notes](https://github.com/SeleniumHQ/selenium/releases)
- [Changelog](https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES)
- [Commits](https://github.com/SeleniumHQ/selenium/commits/selenium-4.3.0)


(cherry picked from commit 3e31d4d654)
2022-06-29 13:17:06 +02:00
Florian Liebe
efab6b06f4 Fixes #4129 - Tooltips are not displayed correctly for all fields while creating a new group. 2022-06-29 10:56:55 +02:00
Mantas
205433de6c Maintenance: Chrome browser in CI uses same timestamp format as Firefox 2022-06-28 22:09:35 +03:00
Weblate
ac194df03c Maintenance: Translations update from translations.zammad.org.
Special thanks to the amazing translation team. You rock! 💪

Co-authored-by: DjMagicFingers <amir@srvit.co.il>
Co-authored-by: Ivan Perovic <ip@zammad.com>
Co-authored-by: LAO <sumonchai@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Zhilin Ruslan <x-th-unicorn@hotmail.com>
Translate-URL: https://translations.zammad.org/projects/zammad/zammad-stable/he_IL/
Translate-URL: https://translations.zammad.org/projects/zammad/zammad-stable/hr/
Translate-URL: https://translations.zammad.org/projects/zammad/zammad-stable/ru/
Translate-URL: https://translations.zammad.org/projects/zammad/zammad-stable/th/
Translation: Zammad/Zammad (stable version)
2022-06-28 07:33:21 +02:00
Rolf Schmidt
80bf57c1b2 Fixes #4143 - LDAP import job no longer starts automatically. 2022-06-23 21:13:22 +02:00
Mantas Masalskis
ea2eb62872 Fixes #4141 - background_services will stop immediately after starting 2022-06-23 17:38:23 +03:00
Mantas
bf8b71d851 Fixes #4031 - The use of shared drafts for response ends with the saving of an internal note 2022-06-22 19:47:22 +03:00
Rolf Schmidt
446f51f5e3 Maintenance: Ignore exists db strategy check in support dir to exclude custom development support files as well. 2022-06-22 15:14:01 +01:00
Martin Gruner
2f1bf5c5cf Maintenance: Correct the filtering of (non-)integration tests in RSpec. 2022-06-22 12:10:16 +02:00
Florian Liebe
f76a83364f Maintenance: Enable RSpec/AlignLeftLetBrace cop 2022-06-22 07:46:52 +02:00
Rolf Schmidt
56c5f3a0c7 Maintenance: Improve custom gemfile loading to support multiple gem files. 2022-06-21 16:53:38 +02:00
Martin Gruner
29bf395d54 Release Zammad 5.2.0. 🚀 2022-06-21 11:22:21 +02:00
295 changed files with 2969 additions and 2207 deletions

View File

@@ -1,14 +1,3 @@
.variables_es: &variables_es
variables:
ES_INDEX_RAND: 'true'
ES_URL: 'http://elasticsearch:9200'
ELASTICSEARCH_TAG: '7.16'
.variables_redis_memcached: &variables_redis_memcached
variables:
REDIS_URL: 'redis://redis:6379'
MEMCACHE_SERVERS: 'memcached'
.variables_selenium_firefox: &variables_selenium_firefox
variables:
REMOTE_URL: 'http://selenium-firefox:4444/wd/hub'
@@ -30,157 +19,36 @@
SE_OPTS: '--log /builds/selenium.log'
CHROME_LOG_FILE: '/builds/chrome.log'
# DB Docker
.docker_mysql: &docker_mysql
name: $CI_REGISTRY/docker/zammad-mysql:stable
alias: mysql
.services:
mysql:
name: $CI_REGISTRY/docker/zammad-mysql:stable
alias: mysql
.docker_postgresql: &docker_postgresql
name: $CI_REGISTRY/docker/zammad-postgresql:stable
alias: postgresql
postgresql:
name: $CI_REGISTRY/docker/zammad-postgresql:stable
alias: postgresql
.docker_elasticsearch: &docker_elasticsearch
name: $CI_REGISTRY/docker/zammad-elasticsearch:$ELASTICSEARCH_TAG
alias: elasticsearch
elasticsearch:
name: $CI_REGISTRY/docker/zammad-elasticsearch:$ELASTICSEARCH_TAG
alias: elasticsearch
.docker_selenium_chrome: &docker_selenium_chrome
name: $CI_REGISTRY/docker/zammad-selenium-chrome:stable
alias: selenium-chrome
selenium-chrome:
name: $CI_REGISTRY/docker/zammad-selenium-chrome:stable
alias: selenium-chrome
.docker_selenium_firefox: &docker_selenium_firefox
name: $CI_REGISTRY/docker/zammad-selenium-firefox:stable
alias: selenium-firefox
selenium-firefox:
name: $CI_REGISTRY/docker/zammad-selenium-firefox:stable
alias: selenium-firefox
.docker_imap: &docker_imap
name: $CI_REGISTRY/docker/zammad-imap:stable
alias: mail
imap:
name: $CI_REGISTRY/docker/zammad-imap:stable
alias: mail
.docker_redis: &docker_redis
name: $CI_REGISTRY/docker/zammad-redis:stable
alias: redis
redis:
name: $CI_REGISTRY/docker/zammad-redis:stable
alias: redis
.docker_memcached: &docker_memcached
name: $CI_REGISTRY/docker/zammad-memcached:stable
alias: memcached
command: ['memcached', '-m', '256M']
# service templates
.services_mysql:
services:
- <<: *docker_mysql
.services_mysql_redis_memcached:
extends:
- .variables_redis_memcached
services:
- <<: *docker_mysql
- <<: *docker_redis
- <<: *docker_memcached
.services_postgresql:
services:
- <<: *docker_postgresql
.services_postgresql_redis_memcached:
extends:
- .variables_redis_memcached
services:
- <<: *docker_postgresql
- <<: *docker_redis
- <<: *docker_memcached
.services_mysql_postgresql_redis_memcached:
extends:
- .variables_redis_memcached
services:
- <<: *docker_mysql
- <<: *docker_postgresql
- <<: *docker_redis
- <<: *docker_memcached
.services_postgresql_selenium_chrome:
extends:
- .variables_selenium_chrome
services:
- <<: *docker_postgresql
- <<: *docker_selenium_chrome
.services_postgresql_selenium_firefox:
extends:
- .variables_selenium_firefox
services:
- <<: *docker_postgresql
- <<: *docker_selenium_firefox
.services_mysql_postgresql_imap_redis_memcached:
extends:
- .variables_redis_memcached
services:
- <<: *docker_mysql
- <<: *docker_postgresql
- <<: *docker_imap
- <<: *docker_redis
- <<: *docker_memcached
.services_mysql_postgresql_elasticsearch:
services:
- <<: *docker_mysql
- <<: *docker_postgresql
- <<: *docker_elasticsearch
.services_mysql_postgresql_redis_memcached_elasticsearch:
extends:
- .variables_redis_memcached
services:
- <<: *docker_mysql
- <<: *docker_postgresql
- <<: *docker_redis
- <<: *docker_memcached
- <<: *docker_elasticsearch
.services_mysql_postgresql_elasticsearch_selenium_chrome_imap:
extends:
- .variables_selenium_chrome
services:
- <<: *docker_mysql
- <<: *docker_postgresql
- <<: *docker_elasticsearch
- <<: *docker_selenium_chrome
- <<: *docker_imap
.services_mysql_postgresql_elasticsearch_selenium_firefox_imap:
extends:
- .variables_selenium_firefox
services:
- <<: *docker_mysql
- <<: *docker_postgresql
- <<: *docker_elasticsearch
- <<: *docker_selenium_firefox
- <<: *docker_imap
.services_mysql_postgresql_elasticsearch_selenium_chrome_imap_redis_memcached:
extends:
- .variables_selenium_chrome
- .variables_redis_memcached
services:
- <<: *docker_mysql
- <<: *docker_postgresql
- <<: *docker_elasticsearch
- <<: *docker_selenium_chrome
- <<: *docker_imap
- <<: *docker_redis
- <<: *docker_memcached
.services_mysql_postgresql_elasticsearch_selenium_firefox_imap_redis_memcached:
extends:
- .variables_selenium_firefox
- .variables_redis_memcached
services:
- <<: *docker_mysql
- <<: *docker_postgresql
- <<: *docker_elasticsearch
- <<: *docker_selenium_firefox
- <<: *docker_imap
- <<: *docker_redis
- <<: *docker_memcached
memcached:
name: $CI_REGISTRY/docker/zammad-memcached:stable
alias: memcached
command: ['memcached', '-m', '256M']

View File

@@ -17,6 +17,11 @@ variables:
MAIL_SERVER_EMAIL: "zammad@mail.test.dc.zammad.com"
KEEP_ON_MAIL_SERVER: "mail"
KEEP_ON_MAIL_SERVER_ACCOUNT: "zammad@mail.test.dc.zammad.com:zammad"
# Settings for elasticsearch, if active
ES_INDEX_RAND: 'true'
ELASTICSEARCH_TAG: '7.16'
# Temporary switch to enable the mobile front end for testing.
ENABLE_EXPERIMENTAL_MOBILE_FRONTEND: 'true'
# Compile assets only once.

View File

@@ -4,7 +4,6 @@
- browser:build
extends:
- .job_rules_default
- .variables_es
- .tags_docker_low_concurrency
variables:
RAILS_ENV: "production"
@@ -20,12 +19,28 @@
.template_browser-core_chrome: &template_browser-core_chrome
extends:
- .template_browser-core
- .services_mysql_postgresql_elasticsearch_selenium_chrome_imap_redis_memcached
- .variables_selenium_chrome
services:
- !reference [.services, mysql]
- !reference [.services, postgresql]
- !reference [.services, elasticsearch]
- !reference [.services, selenium-chrome]
- !reference [.services, imap]
- !reference [.services, redis]
- !reference [.services, memcached]
.template_browser-core_firefox: &template_browser-core_firefox
extends:
- .template_browser-core
- .services_mysql_postgresql_elasticsearch_selenium_firefox_imap_redis_memcached
- .variables_selenium_firefox
services:
- !reference [.services, mysql]
- !reference [.services, postgresql]
- !reference [.services, elasticsearch]
- !reference [.services, selenium-firefox]
- !reference [.services, imap]
- !reference [.services, redis]
- !reference [.services, memcached]
.template_browser-core_autowizard: &template_browser-core_autowizard
stage: browser
@@ -50,12 +65,18 @@
.template_browser-core_autowizard_chrome: &template_browser-core_autowizard_chrome
extends:
- .template_browser-core_autowizard
- .services_postgresql_selenium_chrome
- .variables_selenium_chrome
services:
- !reference [.services, postgresql]
- !reference [.services, selenium-chrome]
.template_browser-core_autowizard_firefox: &template_browser-core_autowizard_firefox
extends:
- .template_browser-core_autowizard
- .services_postgresql_selenium_firefox
- .variables_selenium_firefox
services:
- !reference [.services, postgresql]
- !reference [.services, selenium-firefox]
.template_browser-core_capybara: &template_browser-core_capybara
stage: browser
@@ -63,7 +84,6 @@
- browser:build
extends:
- .job_rules_default
- .variables_es
- .tags_docker_low_concurrency
script:
- echo -e "\\e[0Ksection_start:`date +%s`:zammad_ci_test_prepare[collapsed=true]\\r\\e[0Kbundle exec rake zammad:ci:test:prepare"
@@ -75,9 +95,25 @@
.template_browser-core_capybara_chrome: &template_browser-core_capybara_chrome
extends:
- .template_browser-core_capybara
- .services_mysql_postgresql_elasticsearch_selenium_chrome_imap_redis_memcached
- .variables_selenium_chrome
services:
- !reference [.services, mysql]
- !reference [.services, postgresql]
- !reference [.services, elasticsearch]
- !reference [.services, selenium-chrome]
- !reference [.services, imap]
- !reference [.services, redis]
- !reference [.services, memcached]
.template_browser-core_capybara_firefox: &template_browser-core_capybara_firefox
extends:
- .template_browser-core_capybara
- .services_mysql_postgresql_elasticsearch_selenium_firefox_imap_redis_memcached
- .variables_selenium_firefox
services:
- !reference [.services, mysql]
- !reference [.services, postgresql]
- !reference [.services, elasticsearch]
- !reference [.services, selenium-firefox]
- !reference [.services, imap]
- !reference [.services, redis]
- !reference [.services, memcached]

View File

@@ -4,7 +4,6 @@
- browser:build
extends:
- .job_rules_default
- .variables_es
- .tags_docker_low_concurrency
script:
- echo -e "\\e[0Ksection_start:`date +%s`:zammad_ci_test_prepare[collapsed=true]\\r\\e[0Kbundle exec rake zammad:ci:test:prepare"
@@ -15,12 +14,28 @@
.template_browser-integration_capybara_chrome: &template_browser-integration_capybara_chrome
extends:
- .template_browser-integration_capybara
- .services_mysql_postgresql_elasticsearch_selenium_chrome_imap_redis_memcached
- .variables_selenium_chrome
services:
- !reference [.services, mysql]
- !reference [.services, postgresql]
- !reference [.services, elasticsearch]
- !reference [.services, selenium-chrome]
- !reference [.services, imap]
- !reference [.services, redis]
- !reference [.services, memcached]
.template_browser-integration_capybara_firefox: &template_browser-integration_capybara_firefox
extends:
- .template_browser-integration_capybara
- .services_mysql_postgresql_elasticsearch_selenium_firefox_imap_redis_memcached
- .variables_selenium_firefox
services:
- !reference [.services, mysql]
- !reference [.services, postgresql]
- !reference [.services, elasticsearch]
- !reference [.services, selenium-firefox]
- !reference [.services, imap]
- !reference [.services, redis]
- !reference [.services, memcached]
.template_browser-integration_chrome: &template_browser-integration_chrome
stage: browser
@@ -28,8 +43,11 @@
- browser:build
extends:
- .job_rules_default
- .services_postgresql_selenium_chrome
- .tags_docker_low_concurrency
- .variables_selenium_chrome
services:
- !reference [.services, postgresql]
- !reference [.services, selenium-chrome]
variables:
RAILS_ENV: "production"
APP_RESTART_CMD: 'bundle exec rake environment zammad:ci:app:restart'
@@ -48,8 +66,11 @@
- browser:build
extends:
- .job_rules_default
- .services_postgresql_selenium_chrome
- .tags_docker_low_concurrency
- .variables_selenium_chrome
services:
- !reference [.services, postgresql]
- !reference [.services, selenium-chrome]
variables:
RAILS_ENV: "production"
APP_RESTART_CMD: 'bundle exec rake environment zammad:ci:app:restart'

View File

@@ -7,7 +7,8 @@
.template_lint_rails: &template_lint_rails
extends:
- .template_lint
- .services_postgresql
services:
- !reference [.services, postgresql]
before_script:
- !reference [.scripts, source_rvm]
- !reference [.scripts, bundle_install]

View File

@@ -32,8 +32,8 @@
- script/build/sync_repo.sh git@github.com:zammad/zammad.git
'refresh global envs':
extends:
- .services_postgresql
services:
- !reference [.services, postgresql]
stage: pre
needs:
- 'write runner cache: ruby'

View File

@@ -4,8 +4,12 @@
- browser:build
extends:
- .job_rules_default
- .services_mysql_postgresql_redis_memcached
- .tags_docker_low_concurrency
services:
- !reference [.services, mysql]
- !reference [.services, postgresql]
- !reference [.services, redis]
- !reference [.services, memcached]
variables:
RAILS_ENV: "production"
APP_RESTART_CMD: 'bundle exec rake environment zammad:ci:app:restart'

View File

@@ -1,7 +1,7 @@
browser:build:
stage: test
extends:
- .services_postgresql
services:
- !reference [.services, postgresql]
artifacts:
expire_in: 1 week
paths:

View File

@@ -4,6 +4,11 @@ include:
.template_integration: &template_integration
extends:
- .job_rules_default
- .services_mysql_postgresql_imap_redis_memcached
- .job_rules_integration_manual_start
services:
- !reference [.services, mysql]
- !reference [.services, postgresql]
- !reference [.services, imap]
- !reference [.services, redis]
- !reference [.services, memcached]
stage: test

View File

@@ -1,8 +1,12 @@
.template_integration_es: &template_integration_es
extends:
- .job_rules_default
- .services_mysql_postgresql_redis_memcached_elasticsearch
- .variables_es
services:
- !reference [.services, mysql]
- !reference [.services, postgresql]
- !reference [.services, redis]
- !reference [.services, memcached]
- !reference [.services, elasticsearch]
stage: test
script:
- !reference [.scripts, zammad_db_unseeded]

View File

@@ -2,6 +2,7 @@ include:
- '.gitlab/ci/test/rspec/*.yml'
.template_rspec: &template_rspec
stage: test
extends:
- .job_rules_default
script:
@@ -9,7 +10,7 @@ include:
- bundle exec rake zammad:db:init
- echo -e "\\e[0Ksection_end:`date +%s`:zammad_db_init\\r\\e[0K"
- echo "RSpec filter:" "$RSPEC_EXAMPLE_MATCHES"
- bundle exec rspec --require ./spec/rspec_extensions.rb --exclude-pattern "spec/{system,integration}/**/*_spec.rb" -t ~searchindex --profile 10
- bundle exec rspec --require ./spec/rspec_extensions.rb --exclude-pattern "spec/system/**/*_spec.rb" -t ~searchindex -t ~integration --profile 10
# RSpec 3rd party integration tests are independent of the database
# therefore we need only one job and choose a random database for each run
@@ -19,8 +20,13 @@ rspec:integration:
stage: test
extends:
- .job_rules_default
- .services_mysql_postgresql_imap_redis_memcached
- .job_rules_integration_manual_start
services:
- !reference [.services, mysql]
- !reference [.services, postgresql]
- !reference [.services, imap]
- !reference [.services, redis]
- !reference [.services, memcached]
script:
- !reference [.scripts, zammad_db_init]
- bundle exec rspec -t type:integration --profile 10
- bundle exec rspec --exclude-pattern "spec/system/**/*_spec.rb" -t integration --profile 10

View File

@@ -1,53 +1,49 @@
.template_rspec_mysql:
extends:
- .template_rspec
services:
- !reference [.services, mysql]
- !reference [.services, redis]
- !reference [.services, memcached]
rspec:mysql:1:
stage: test
variables:
RSPEC_SLICES: 6
RSPEC_CURRENT_SLICE: 1
extends:
- .services_mysql_redis_memcached
- .template_rspec
- .template_rspec_mysql
rspec:mysql:2:
stage: test
variables:
RSPEC_SLICES: 6
RSPEC_CURRENT_SLICE: 2
extends:
- .services_mysql_redis_memcached
- .template_rspec
- .template_rspec_mysql
rspec:mysql:3:
stage: test
variables:
RSPEC_SLICES: 6
RSPEC_CURRENT_SLICE: 3
extends:
- .services_mysql_redis_memcached
- .template_rspec
- .template_rspec_mysql
rspec:mysql:4:
stage: test
variables:
RSPEC_SLICES: 6
RSPEC_CURRENT_SLICE: 4
extends:
- .services_mysql_redis_memcached
- .template_rspec
- .template_rspec_mysql
rspec:mysql:5:
stage: test
variables:
RSPEC_SLICES: 6
RSPEC_CURRENT_SLICE: 5
extends:
- .services_mysql_redis_memcached
- .template_rspec
- .template_rspec_mysql
rspec:mysql:6:
stage: test
variables:
RSPEC_SLICES: 6
RSPEC_CURRENT_SLICE: 6
extends:
- .services_mysql_redis_memcached
- .template_rspec
- .template_rspec_mysql

View File

@@ -1,53 +1,49 @@
.template_rspec_postgresql:
extends:
- .template_rspec
services:
- !reference [.services, postgresql]
- !reference [.services, redis]
- !reference [.services, memcached]
rspec:postgresql:1:
stage: test
variables:
RSPEC_SLICES: 6
RSPEC_CURRENT_SLICE: 1
extends:
- .services_postgresql_redis_memcached
- .template_rspec
- .template_rspec_postgresql
rspec:postgresql:2:
stage: test
variables:
RSPEC_SLICES: 6
RSPEC_CURRENT_SLICE: 2
extends:
- .services_postgresql_redis_memcached
- .template_rspec
- .template_rspec_postgresql
rspec:postgresql:3:
stage: test
variables:
RSPEC_SLICES: 6
RSPEC_CURRENT_SLICE: 3
extends:
- .services_postgresql_redis_memcached
- .template_rspec
- .template_rspec_postgresql
rspec:postgresql:4:
stage: test
variables:
RSPEC_SLICES: 6
RSPEC_CURRENT_SLICE: 4
extends:
- .services_postgresql_redis_memcached
- .template_rspec
- .template_rspec_postgresql
rspec:postgresql:5:
stage: test
variables:
RSPEC_SLICES: 6
RSPEC_CURRENT_SLICE: 5
extends:
- .services_postgresql_redis_memcached
- .template_rspec
- .template_rspec_postgresql
rspec:postgresql:6:
stage: test
variables:
RSPEC_SLICES: 6
RSPEC_CURRENT_SLICE: 6
extends:
- .services_postgresql_redis_memcached
- .template_rspec
- .template_rspec_postgresql

View File

@@ -10,11 +10,17 @@
unit:mysql:
stage: test
extends:
- .services_mysql_redis_memcached
- .template_unit
services:
- !reference [.services, mysql]
- !reference [.services, redis]
- !reference [.services, memcached]
unit:postgresql:
stage: test
extends:
- .services_postgresql_redis_memcached
- .template_unit
- .template_unit
services:
- !reference [.services, postgresql]
- !reference [.services, redis]
- !reference [.services, memcached]

View File

@@ -7,8 +7,10 @@ require 'fileutils'
#
# Configures the CI system
# - either (randomly) mysql or postgresql, if it is available
# - (randomly) mysql or postgresql, if available
# - (randomly) Redis or File as web socket session back end, if Redis is available
# - (randomly) Memcached or File as Rails cache store, if Memcached is available
# - Elasticsearch support, if available
#
# Database config happens directly in config/database.yml, other settings are written to
# .gitlab/environment.env which must be sourced in the CI configuration.
@@ -22,7 +24,35 @@ class ConfigureEnvironment
true
ENV_FILE_CONTENT
def self.configure_database # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
DB_SETTINGS_MAP = {
'postgresql' => {
'adapter' => 'postgresql',
'username' => 'zammad',
'password' => 'zammad',
'host' => 'postgresql', # db alias from gitlab-ci.yml
},
'mysql' => {
'adapter' => 'mysql2',
'username' => 'root',
'password' => 'zammad',
'host' => 'mysql', # db alias from gitlab-ci.yml
}
}.freeze
# Detect service availability based on host presence in network.
def self.network_host_exists?(hostname)
if %w[1 true].include?(ENV['FF_NETWORK_PER_BUILD'])
begin
!!Resolv::DNS.new.tap { |dns| dns.timeouts = 3 }.getaddress(hostname)
rescue Resolv::ResolvError
false
end
else
File.foreach('/etc/hosts').any? { |l| l[hostname] }
end
end
def self.configure_database # rubocop:disable Metrics/AbcSize
if File.exist? File.join(__dir__, '../config/database.yml')
puts "'config/database.yml' already exists and will not be changed."
@@ -32,51 +62,16 @@ class ConfigureEnvironment
cnf = YAML.load_file(File.join(__dir__, '../config/database/database.yml'))
cnf.delete('default')
database = ENV['ENFORCE_DB_SERVICE']
# Lookup in /etc/hosts first: gitlab uses that if FF_NETWORK_PER_BUILD is not set.
if !database
hostsfile = '/etc/hosts'
database = %w[postgresql mysql].shuffle.find do |possible_database|
File.foreach(hostsfile).any? { |l| l[possible_database] }
end
end
# Lookup via DNS if needed: gitlab uses that if FF_NETWORK_PER_BUILD is enabled.
if !database
dns = Resolv::DNS.new
dns.timeouts = 3
database = %w[postgresql mysql].shuffle.find do |possible_database|
# Perform a lookup of the database host to check if it is configured as a service.
if dns.getaddress possible_database
next possible_database
end
rescue Resolv::ResolvError
# Ignore DNS lookup errors
end
database = ENV['ENFORCE_DB_SERVICE'] || %w[postgresql mysql].shuffle.find do |db|
network_host_exists?(db)
end
raise "Can't find any supported database." if database.nil?
puts "Using #{database} as database service."
db_settings_map = {
'postgresql' => {
'adapter' => 'postgresql',
'username' => 'zammad',
'password' => 'zammad',
'host' => 'postgresql', # db alias from gitlab-ci.yml
},
'mysql' => {
'adapter' => 'mysql2',
'username' => 'root',
'password' => 'zammad',
'host' => 'mysql', # db alias from gitlab-ci.yml
}
}
# fetch DB settings from settings map and fallback to postgresql
db_settings = db_settings_map.fetch(database) { db_settings_map['postgresql'] }
db_settings = DB_SETTINGS_MAP.fetch(database) { DB_SETTINGS_MAP['postgresql'] }
%w[development test production].each do |environment|
cnf[environment].merge!(db_settings)
@@ -85,40 +80,46 @@ class ConfigureEnvironment
File.write(File.join(__dir__, '../config/database.yml'), Psych.dump(cnf))
end
def self.configure_redis # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
puts 'ENABLING THE NEW EXPERIMENTAL MOBILE FRONTEND.' if ENV['ENABLE_EXPERIMENTAL_MOBILE_FRONTEND'] == 'true'
if ENV['ENABLE_EXPERIMENTAL_MOBILE_FRONTEND'] == 'true' && (ENV['REDIS_URL'].nil? || ENV['REDIS_URL'].empty?) # rubocop:disable Rails/Blank
if database_type == 'mysql'
raise 'Redis was not found, but is required for ActionCable on MySQL based systems.'
end
def self.configure_redis
has_redis = network_host_exists?('redis')
needs_redis = database_type == 'mysql' && ENV['ENABLE_EXPERIMENTAL_MOBILE_FRONTEND'] == 'true'
puts 'Redis is not available, using File as web socket session store.'
puts 'Redis is not available, using the PostgreSQL adapter for ActionCable.'
if needs_redis && !has_redis
raise 'Redis was not found, but is required for ActionCable on MySQL based systems.'
end
if has_redis && [true, needs_redis].sample
puts 'Using Redis as web socket session store and as adapter for ActionCable.'
@env_file_content += "export REDIS_URL='redis://redis:6379'\n"
return
end
if database_type == 'mysql' || [true, false].sample
puts 'Using Redis as web socket session store.'
puts 'Using the Redis adapter for ActionCable.'
return
end
puts 'Using File as web socket session store.'
puts 'Using the PostgreSQL adapter for ActionCable.'
puts 'Using File as web socket session store and the PostgreSQL adapter for ActionCable.'
@env_file_content += "unset REDIS_URL\n"
end
def self.configure_memcached
if ENV['MEMCACHE_SERVERS'].nil? || ENV['MEMCACHE_SERVERS'].empty? # rubocop:disable Rails/Blank
puts 'Memcached is not available, using File as Rails cache store.'
return
end
if [true, false].sample
if network_host_exists?('memcached') && [true, false].sample
puts 'Using memcached as Rails cache store.'
@env_file_content += "export MEMCACHE_SERVERS='memcached'\n"
return
end
puts "Using Zammad's file store as Rails cache store."
@env_file_content += "unset MEMCACHE_SERVERS\n"
end
def self.configure_elasticsearch
if network_host_exists?('elasticsearch')
puts 'Activating support for Elasticsearch.'
@env_file_content += "export ES_URL='http://elasticsearch:9200'\n"
return
end
puts 'Not using Elasticsearch.'
@env_file_content += "unset ES_URL\n"
end
# Since configure_database skips if database.yml already exists, check the
# content of that file to reliably determine the database type in all cases.
def self.database_type
@@ -135,9 +136,11 @@ class ConfigureEnvironment
end
def self.run
puts 'ENABLING THE NEW EXPERIMENTAL MOBILE FRONTEND.' if ENV['ENABLE_EXPERIMENTAL_MOBILE_FRONTEND'] == 'true'
configure_database
configure_redis
configure_memcached
configure_elasticsearch
write_env_file
end
end

View File

@@ -339,6 +339,10 @@ RSpec/Rails/AvoidSetupHook:
Exclude:
- "test/**/*"
RSpec/AlignLeftLetBrace:
Description: 'Checks that left braces for adjacent single line lets are aligned.'
Enabled: true
Zammad/PreferNegatedIfOverUnless:
Exclude:
- 'bin/rspec'
@@ -379,4 +383,4 @@ Zammad/ExistsDbStrategy:
Include:
- "spec/**/*.rb"
Exclude:
- spec/support/capybara/common_actions.rb
- "spec/support/capybara/*.rb"

View File

@@ -1,11 +1,113 @@
# Change Log
## [5.2.0](https://github.com/zammad/zammad/tree/5.2.0) (2022-xx-xx)
## [5.2.1](https://github.com/zammad/zammad/tree/5.2.1) (2022-07-05)
[Full Changelog](https://github.com/zammad/zammad/compare/5.2.0...5.2.1)
**Fixed bugs:**
- Allow very long email address [4159](https://github.com/zammad/zammad/issues/4159) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Elasticsearch 8 incompatible with Zammad 5.2 [4158](https://github.com/zammad/zammad/issues/4158)
- Selecting group permission "full" behaves differently in user- and role-management [4100](https://github.com/zammad/zammad/issues/4100) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Trigger Attribute "action > is > updated" is not working after Zammad 5.2 update [4153](https://github.com/zammad/zammad/issues/4153) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- cannot process emails with special characters in local part [4151](https://github.com/zammad/zammad/issues/4151) [[bug](https://github.com/zammad/zammad/labels/bug)]
- No error message is shown if the mandatory role field is missing during creating/updating overviews [4140](https://github.com/zammad/zammad/issues/4140) [[bug](https://github.com/zammad/zammad/labels/bug)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)] [[overviews](https://github.com/zammad/zammad/labels/overviews)]
- Tooltips are not displayed correctly for all fields while creating a new group [4129](https://github.com/zammad/zammad/issues/4129) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- LDAP import job no longer starts automatically [4143](https://github.com/zammad/zammad/issues/4143) [[bug](https://github.com/zammad/zammad/labels/bug)] [[blocker](https://github.com/zammad/zammad/labels/blocker)] [[LDAP](https://github.com/zammad/zammad/labels/LDAP)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- background_services will stop immediately after starting [4141](https://github.com/zammad/zammad/issues/4141) [[bug](https://github.com/zammad/zammad/labels/bug)]
- The use of shared drafts for response ends with the saving of an internal note [4031](https://github.com/zammad/zammad/issues/4031) [[bug](https://github.com/zammad/zammad/labels/bug)]
## [5.2.0](https://github.com/zammad/zammad/tree/5.2.0) (2022-06-21)
[Full Changelog](https://github.com/zammad/zammad/compare/5.1.0...5.2.0)
**Implemented enhancements:**
- Time accounting "Overviews" is misleading [4119](https://github.com/zammad/zammad/issues/4119) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)] [[time accounting](https://github.com/zammad/zammad/labels/time%20accounting)]
- Translate Slack templates in French [4101](https://github.com/zammad/zammad/pull/4101) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[translation](https://github.com/zammad/zammad/labels/translation)] [[integration](https://github.com/zammad/zammad/labels/integration)]
- Translate ticket merge email templates in French [4099](https://github.com/zammad/zammad/pull/4099) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[translation](https://github.com/zammad/zammad/labels/translation)]
- Multi LDAP: Httplog should include source where data was synced from [4106](https://github.com/zammad/zammad/issues/4106) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)] [[LDAP](https://github.com/zammad/zammad/labels/LDAP)]
- Multiple LDAP server configurations [3141](https://github.com/zammad/zammad/issues/3141) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)] [[LDAP](https://github.com/zammad/zammad/labels/LDAP)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- implemented time accounting export by activity [3976](https://github.com/zammad/zammad/pull/3976) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)] [[time accounting](https://github.com/zammad/zammad/labels/time%20accounting)]
- no test e-mail [1471](https://github.com/zammad/zammad/issues/1471) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)]
- Multi tree select object manager attribute [4062](https://github.com/zammad/zammad/issues/4062) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- parsing incoming mails breaks on this line "Reply-To: <>" [3867](https://github.com/zammad/zammad/issues/3867) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[mail processing](https://github.com/zammad/zammad/labels/mail%20processing)]
- Prefix the contact form css with 'zammad' for a better selection [4048](https://github.com/zammad/zammad/issues/4048) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[theming / skinning](https://github.com/zammad/zammad/labels/theming%20%2F%20skinning)]
- Show age (indicator) for public KB Answers [2848](https://github.com/zammad/zammad/issues/2848) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge%20base)]
- Allow reauthentication of Google / Microsoft 365 accounts [3240](https://github.com/zammad/zammad/issues/3240) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[channel](https://github.com/zammad/zammad/labels/channel)]
- Avatar lookup during user creation can cause significant delays [3542](https://github.com/zammad/zammad/issues/3542) [[enhancement](https://github.com/zammad/zammad/labels/enhancement)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
**Fixed bugs:**
- Zendesk import ignores active flag for user during the import [4135](https://github.com/zammad/zammad/issues/4135) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Zammad shows "<![if !supportLists]>- <![endif]>" instead of list icon [4112](https://github.com/zammad/zammad/issues/4112) [[bug](https://github.com/zammad/zammad/labels/bug)] [[mail processing](https://github.com/zammad/zammad/labels/mail%20processing)]
- Zendesk import for users and organizations works not correctly when custom fields are created with a sanitized name [4128](https://github.com/zammad/zammad/issues/4128) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Popovers will not disappear [4122](https://github.com/zammad/zammad/issues/4122) [[bug](https://github.com/zammad/zammad/labels/bug)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- Pop-Up Warning for missing attachments with text containing "attached" or related only appears on english terms (not translated) [4096](https://github.com/zammad/zammad/issues/4096) [[bug](https://github.com/zammad/zammad/labels/bug)]
- 'Sender Format' set to 'Agent Name' causes empty display names in triggers [3890](https://github.com/zammad/zammad/issues/3890) [[bug](https://github.com/zammad/zammad/labels/bug)] [[trigger](https://github.com/zammad/zammad/labels/trigger)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Changing the category of a Knowledge Base answer leads to alternative translation loop [3931](https://github.com/zammad/zammad/issues/3931) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge%20base)]
- Switching the photos displayed in the preview does not work with the arrow keys [4030](https://github.com/zammad/zammad/issues/4030) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Webhhok transfers "accounted_time" of an article as integer instead of float/double [4127](https://github.com/zammad/zammad/issues/4127) [[bug](https://github.com/zammad/zammad/labels/bug)]
- User popover shows secondary organizations label if user has no organizations [4125](https://github.com/zammad/zammad/issues/4125) [[bug](https://github.com/zammad/zammad/labels/bug)]
- OS detection crashes if OS name cannot be parsed [4124](https://github.com/zammad/zammad/issues/4124) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Upgrade to Zammad 5.2 not possible (undefined method `view' for nil:NilClass) [4126](https://github.com/zammad/zammad/issues/4126) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Notifications are sent for all tickets when an organization of a customer is updated [3952](https://github.com/zammad/zammad/issues/3952) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Single tree select no longer allows displaying child values [4118](https://github.com/zammad/zammad/issues/4118) [[bug](https://github.com/zammad/zammad/labels/bug)] [[blocker](https://github.com/zammad/zammad/labels/blocker)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[ticket](https://github.com/zammad/zammad/labels/ticket)]
- users customer name is displayed as id [4040](https://github.com/zammad/zammad/issues/4040) [[bug](https://github.com/zammad/zammad/labels/bug)] [[overviews](https://github.com/zammad/zammad/labels/overviews)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Follow-up detection does not work for the body of plain text mails [3894](https://github.com/zammad/zammad/issues/3894) [[bug](https://github.com/zammad/zammad/labels/bug)] [[mail processing](https://github.com/zammad/zammad/labels/mail%20processing)]
- DataPrivacy Tasks fail if Zammad has to solve references on users with invalid email addresses [3935](https://github.com/zammad/zammad/issues/3935) [[bug](https://github.com/zammad/zammad/labels/bug)] [[data privacy](https://github.com/zammad/zammad/labels/data%20privacy)]
- Parents will always be selected when going through the tree in multiple treeselect field [4080](https://github.com/zammad/zammad/issues/4080) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[frontend / JS app](https://github.com/zammad/zammad/labels/frontend%20%2F%20JS%20app)] [[object manager attribute](https://github.com/zammad/zammad/labels/object%20manager%20attribute)] [[form](https://github.com/zammad/zammad/labels/form)]
- Title column is missing if ticket number is disabled in overview options [3943](https://github.com/zammad/zammad/issues/3943) [[bug](https://github.com/zammad/zammad/labels/bug)]
- script/background-services.rb crashes on startup [4113](https://github.com/zammad/zammad/issues/4113) [[bug](https://github.com/zammad/zammad/labels/bug)] [[blocker](https://github.com/zammad/zammad/labels/blocker)]
- Monitoring endpoint is complaing about not executed scheduler job "CacheClearJob.perform_now" [4079](https://github.com/zammad/zammad/issues/4079) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Searches display all groups and owners on bulk selections [4054](https://github.com/zammad/zammad/issues/4054) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[core workflows](https://github.com/zammad/zammad/labels/core%20workflows)]
- Wrong default values in ticket create when creating from user profile [4088](https://github.com/zammad/zammad/issues/4088) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[ticket](https://github.com/zammad/zammad/labels/ticket)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Reporting export file shows empty fields in selected columns when "custom sort option" is enabled [4103](https://github.com/zammad/zammad/issues/4103) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Wrongly creation of "session started" activity stream log entry for session check [4105](https://github.com/zammad/zammad/issues/4105) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Latest upgrade to 5.1 is not possible [4097](https://github.com/zammad/zammad/issues/4097) [[bug](https://github.com/zammad/zammad/labels/bug)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- Trigger autocomplete when clicking the "Tags" field also without a search term [4095](https://github.com/zammad/zammad/issues/4095) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- Shared draft attribute in object manage not disabled for onclick [4089](https://github.com/zammad/zammad/issues/4089) [[bug](https://github.com/zammad/zammad/labels/bug)] [[object manager attribute](https://github.com/zammad/zammad/labels/object%20manager%20attribute)]
- Assign user to multiple organizations [1573](https://github.com/zammad/zammad/issues/1573) [[feature backlog](https://github.com/zammad/zammad/labels/feature%20backlog)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Preview of *.ics files in ticket zoom attachments [4091](https://github.com/zammad/zammad/issues/4091) [[feature backlog](https://github.com/zammad/zammad/labels/feature%20backlog)] [[ticket](https://github.com/zammad/zammad/labels/ticket)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[productivity](https://github.com/zammad/zammad/labels/productivity)]
- Tab behaviour does not show properly when doing a ticket update at the same time [4094](https://github.com/zammad/zammad/issues/4094) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Custom sort on select returns "undefined method `merge' " for older objects [4086](https://github.com/zammad/zammad/issues/4086) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[object manager attribute](https://github.com/zammad/zammad/labels/object%20manager%20attribute)]
- Tree Select Trigger changes the conditions on its own [4090](https://github.com/zammad/zammad/issues/4090) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Zammad email display broken [4053](https://github.com/zammad/zammad/issues/4053) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Linked ticket state won't be updated [476](https://github.com/zammad/zammad/issues/476) [[bug](https://github.com/zammad/zammad/labels/bug)] [[frontend / JS app](https://github.com/zammad/zammad/labels/frontend%20%2F%20JS%20app)]
- OTRS migration currently do not support custom dropdown multi-select fields [4057](https://github.com/zammad/zammad/issues/4057) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)]
- OTRS import fails for DynamicFields of Type Dropdown without possible values [2375](https://github.com/zammad/zammad/issues/2375) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)]
- Boolean shows wrong default value if not set to shown by default [4065](https://github.com/zammad/zammad/issues/4065) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[core workflows](https://github.com/zammad/zammad/labels/core%20workflows)]
- Zammad notification emails have a broken 'reason' footer line [4066](https://github.com/zammad/zammad/issues/4066) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Javascript error undefined multiple while opening core workflow with tree selects [4067](https://github.com/zammad/zammad/issues/4067) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Popovers will not disappear anymore [4058](https://github.com/zammad/zammad/issues/4058) [[bug](https://github.com/zammad/zammad/labels/bug)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- Freshdesk import currently doesn't handle the ticket type field [4064](https://github.com/zammad/zammad/issues/4064) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)]
- Core Workflow: Does show wrong field list if you only have admin permissions and not ticket.agent permissions [4035](https://github.com/zammad/zammad/issues/4035) [[bug](https://github.com/zammad/zammad/labels/bug)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Migrations (Zendesk, Kayako) currently do not support custom dropdown multi-select fields [4055](https://github.com/zammad/zammad/issues/4055) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Ticket in the ticket creation screen tags are shown after 2 characters, in the ticket zoom after 1 character [3748](https://github.com/zammad/zammad/issues/3748) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Clicking the button in a mail opens the link as a photo [4044](https://github.com/zammad/zammad/issues/4044) [[bug](https://github.com/zammad/zammad/labels/bug)] [[ticket](https://github.com/zammad/zammad/labels/ticket)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Tree select widget closes unexpectedly [4041](https://github.com/zammad/zammad/issues/4041) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- pre-code tags cause Zammad to swallow content [4039](https://github.com/zammad/zammad/issues/4039) [[bug](https://github.com/zammad/zammad/labels/bug)] [[mail processing](https://github.com/zammad/zammad/labels/mail%20processing)]
- Error on second migration of an microsoft365 channel undefined method `options' for nil:NilClass [4060](https://github.com/zammad/zammad/issues/4060) [[bug](https://github.com/zammad/zammad/labels/bug)] [[channel](https://github.com/zammad/zammad/labels/channel)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Freshdesk migration which doesn't support time entries runs in unwanted behaviour [4052](https://github.com/zammad/zammad/issues/4052) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)]
- Freshdesk-Migration does not like no Companies / Organisations within the source [4051](https://github.com/zammad/zammad/issues/4051) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)]
- Cannot encrypt if multiple S/MIME certificates exist and one is expired [4029](https://github.com/zammad/zammad/issues/4029) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Can't delete smime certificate - ERROR: duplicate key value violates unique constraint [4049](https://github.com/zammad/zammad/issues/4049) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Core Workflow - Unable to select "has changed" logic when creating new workflow. It is also replaced with "is" in previously created workflows. [4046](https://github.com/zammad/zammad/issues/4046) [[bug](https://github.com/zammad/zammad/labels/bug)]
- undefined method `to_hash` on editing select fields in the admin interface after migration to 5.1 [4027](https://github.com/zammad/zammad/issues/4027) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Knowledge Base on-the-fly updating does not work [4026](https://github.com/zammad/zammad/issues/4026) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Default time diff for date and datetime objects don't function [3763](https://github.com/zammad/zammad/issues/3763) [[bug](https://github.com/zammad/zammad/labels/bug)] [[object manager attribute](https://github.com/zammad/zammad/labels/object%20manager%20attribute)]
- Problems with duplicate records in Translations table [4020](https://github.com/zammad/zammad/issues/4020) [[bug](https://github.com/zammad/zammad/labels/bug)] [[translation](https://github.com/zammad/zammad/labels/translation)]
- Tree select value cannot be set to "-" (empty) with Trigger/Scheduler/Core workflow [4024](https://github.com/zammad/zammad/issues/4024) [[bug](https://github.com/zammad/zammad/labels/bug)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Admin macros are not usable with admin permissions only [4032](https://github.com/zammad/zammad/issues/4032) [[bug](https://github.com/zammad/zammad/labels/bug)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Admin SLA index view does not show update time if "for agent respond" is selected [4033](https://github.com/zammad/zammad/issues/4033) [[bug](https://github.com/zammad/zammad/labels/bug)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Core Workflow: Stop after match is not saved [4034](https://github.com/zammad/zammad/issues/4034) [[bug](https://github.com/zammad/zammad/labels/bug)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)] [[core workflows](https://github.com/zammad/zammad/labels/core%20workflows)]
- KB Public menus scroll bar positioning incorrect [4008](https://github.com/zammad/zammad/issues/4008) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[knowledge base](https://github.com/zammad/zammad/labels/knowledge%20base)]
- Freshdesk import error when a inline image source attribute contains no clean url [4028](https://github.com/zammad/zammad/issues/4028) [[bug](https://github.com/zammad/zammad/labels/bug)] [[import](https://github.com/zammad/zammad/labels/import)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- Mention history does not show properly who got added [3984](https://github.com/zammad/zammad/issues/3984) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[history](https://github.com/zammad/zammad/labels/history)]
- Translation introduction text shows wrong keyboard shortcut [2885](https://github.com/zammad/zammad/issues/2885) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[translation](https://github.com/zammad/zammad/labels/translation)]
- Translation introduction text shows wrong keyboard shortcut [3990](https://github.com/zammad/zammad/pull/3990) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Obsolete notice field in admin calendar view [4023](https://github.com/zammad/zammad/issues/4023) [[bug](https://github.com/zammad/zammad/labels/bug)] [[admin area](https://github.com/zammad/zammad/labels/admin%20area)]
- Error “customer_id required” on Macro execution [4022](https://github.com/zammad/zammad/issues/4022) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[macros](https://github.com/zammad/zammad/labels/macros)]
- Translations are not available in API after syncing [4016](https://github.com/zammad/zammad/issues/4016) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Upgraded to 5.1.0: pending time doesn’t show a date [4018](https://github.com/zammad/zammad/issues/4018) [[bug](https://github.com/zammad/zammad/labels/bug)] [[translation](https://github.com/zammad/zammad/labels/translation)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]
- UI is not updated right after importing users csv file [3919](https://github.com/zammad/zammad/issues/3919) [[bug](https://github.com/zammad/zammad/labels/bug)]
- Pending closed/reminder date selector shows current date black on dark gray [2316](https://github.com/zammad/zammad/issues/2316) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[regression](https://github.com/zammad/zammad/labels/regression)]
- LDAP with many groups (<5k) and group role relation (>50) will crash in frontend [3994](https://github.com/zammad/zammad/issues/3994) [[bug](https://github.com/zammad/zammad/labels/bug)] [[UX/UI](https://github.com/zammad/zammad/labels/UX%2FUI)] [[LDAP](https://github.com/zammad/zammad/labels/LDAP)] [[prioritised by payment](https://github.com/zammad/zammad/labels/prioritised%20by%20payment)]

View File

@@ -233,4 +233,6 @@ end
# ZAMMAD DEVS: Consult the internal wiki
# (or else risk pushing unwanted changes to Gemfile.lock!)
# https://git.zammad.com/zammad/zammad/wikis/Tips#user-content-customizing-the-gemfile
eval_gemfile 'Gemfile.local' if File.exist?('Gemfile.local')
Dir['Gemfile.local*'].each do |file|
eval_gemfile file
end

View File

@@ -496,7 +496,7 @@ GEM
sprockets (> 3.0)
sprockets-rails
tilt
selenium-webdriver (4.2.1)
selenium-webdriver (4.3.0)
childprocess (>= 0.5, < 5.0)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)

View File

@@ -784,7 +784,8 @@ class App.ControllerForm extends App.Controller
# set autofocus by delay to make validation testable
App.Delay.set(
->
lookupForm.find('.has-error').find('input, textarea, select').first().trigger('focus')
# make sure to work for all field types (e.g. column_select which is an hidden select)
lookupForm.find('.has-error').get(0)?.scrollIntoView(true)
200
'validate'
)

View File

@@ -106,6 +106,8 @@ class App.UiElement.ApplicationSelector
config.expanding = false
if config.type is 'email' || config.type is 'tel'
config.type = 'text'
if config.tag is 'select'
config.multiple = true
for operatorRegEx, operator of operators_type
myRegExp = new RegExp(operatorRegEx, 'i')
if config.tag && config.tag.match(myRegExp)

View File

@@ -30,6 +30,12 @@ class App.UiElement.permission extends App.UiElement.ApplicationUiElement
@checkUncheck($(e.currentTarget), permissions, item)
)
item.find('[name=permission_ids]').trigger('change')
# check/uncheck group permissions (particular permissions vs. full)
item.on('click', '.checkbox-replacement', (event) ->
App.PermissionHelper.switchGroupPermission(event)
)
item
@checkUncheck: (element, permissions, item) ->
@@ -54,4 +60,3 @@ class App.UiElement.permission extends App.UiElement.ApplicationUiElement
lookupPermission = App.Permission.findByAttribute('name', localPermission)
if lookupPermission
item.find("[name=permission_ids][value=#{lookupPermission.id}]").prop('checked', false)

View File

@@ -4,7 +4,10 @@ class App.UiElement.select_search extends App.UiElement.ApplicationUiElement
attribute = $.extend(true, {}, attributeConfig)
# set multiple option
attribute.multiple = 'multiple'
if attribute.multiple
attribute.multiple = 'multiple'
else
attribute.multiple = ''
delete attribute.filter

View File

@@ -74,18 +74,10 @@ class App.UiElement.user_permission
groupAccesses: App.Group.accesses()
) )
throttled = _.throttle( (e) ->
input = $(@).find('input')
upcoming_state = if $(e.target).is(':checkbox') then input.prop('checked') else !input.prop('checked')
value = input.val()
if value is 'full' and upcoming_state is true
$(@).closest('tr').find('input:not([value=full])').prop('checked', false)
else if value isnt 'full' and upcoming_state is true
$(@).closest('tr').find('input[value=full]').prop('checked', false)
, 300, { trailing: false })
item.on('click', '.checkbox-replacement', throttled)
# check/uncheck group permissions (particular permissions vs. full)
item.on('click', '.checkbox-replacement', (event) ->
App.PermissionHelper.switchGroupPermission(event)
)
# if customer, remove admin and agent
item.find('[name=role_ids]').on('change', (e) =>

View File

@@ -55,11 +55,13 @@ class App.TicketZoomArticleNew extends App.Controller
@openTextarea(null, true, !data.nofocus)
for key, value of data.article
if key is 'body'
@$("[data-name=\"#{key}\"]").html(value)
else
@$("[name=\"#{key}\"]").val(value).trigger('change')
switch key
when 'body'
@$("[data-name=\"#{key}\"]").html(value)
when 'internal'
@setArticleInternal(value)
else
@$("[name=\"#{key}\"]").val(value).trigger('change')
@$('[name=shared_draft_id]').val(data.shared_draft_id)
@@ -363,19 +365,13 @@ class App.TicketZoomArticleNew extends App.Controller
@el.find('.js-articleTypes').addClass('is-hidden')
setArticleInternal: (internal) =>
if internal is true
@articleNewEdit
.removeClass('is-public')
.addClass('is-internal')
@$('[name=internal]').val('true')
return
@articleNewEdit
.addClass('is-public')
.removeClass('is-internal')
.toggleClass('is-public', !internal)
.toggleClass('is-internal', internal)
@$('[name=internal]').val('')
value = if internal then 'true' else ''
@$('[name=internal]').val(value)
setArticleTypePre: (type, signaturePosition = 'bottom') =>
wasScrolledToBottom = @isScrolledToBottom()

View File

@@ -175,6 +175,7 @@ class App.FormHandlerCoreWorkflow
)
form.find('[name="' + field + '"]').closest('.form-group').replaceWith(newElement)
form.find('[name="' + field + '"]').closest('.form-group').find('.js-helpMessage').tooltip()
if shown
ui.show(field, form)

View File

@@ -0,0 +1,17 @@
App.PermissionHelper =
switchGroupPermission: (event) ->
throttled = _.throttle( (e) ->
input = $(e.target)
upcoming_state = input.prop('checked')
if !$(e.target).is(':checkbox')
upcoming_state = !upcoming_state
selector = 'input[value=full]'
if input.val() is 'full' and upcoming_state is true
selector = 'input[value!=full]'
$(e.target).closest('tr').find(selector).prop('checked', false)
, 300, { trailing: false })
throttled(event)

View File

@@ -9,6 +9,7 @@
<%= @attribute.autofocus %>
value="<%= @attribute.value %>"
multiple
disabled
>
<% for option in @allOptions: %>
<option value="<%= option.value %>" <%= ' selected' if option.selected %>><%= option.name %></option>

View File

@@ -56,8 +56,14 @@ module ApplicationController::HandlesErrors
# check if a special authorization_error should be shown in the result payload
# which was raised in one of the policies. Fall back to a simple "Not authorized"
# error to hide actual cause for security reasons.
exeption = e.policy&.custom_exception || Exceptions::Forbidden.new(__('Not authorized'))
forbidden(exeption)
exception = e.policy&.custom_exception || Exceptions::Forbidden.new(__('Not authorized'))
case exception
when ActiveRecord::RecordNotFound
not_found(exception)
else
forbidden(exception)
end
end
private

View File

@@ -82,10 +82,7 @@ class AttachmentsController < ApplicationController
render json: { error: e.message }, status: :unprocessable_entity
end
def authorize!
record = download_file&.store_object&.name&.safe_constantize&.find(download_file.o_id)
authorize(record) if record
rescue Pundit::NotAuthorizedError
raise ActiveRecord::RecordNotFound
def user_not_authorized(e)
not_found(e)
end
end

View File

@@ -5,6 +5,8 @@ class ApplicationJob < ActiveJob::Base
include ApplicationJob::HasQueuingPriority
include ApplicationJob::HasCustomLogging
discard_on HasActiveJobLock::LockKeyNotGeneratable
ActiveJob::LogSubscriber.detach_from :active_job
# See config/initializers/delayed_jobs_timeout_per_job.rb for details.

View File

@@ -1,6 +1,8 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
module HasActiveJobLock
class LockKeyNotGeneratable < StandardError; end
extend ActiveSupport::Concern
included do
@@ -9,6 +11,9 @@ module HasActiveJobLock
end
around_perform do |job, block|
# do not perform job if lock key cannot be generated anymore
raise LockKeyNotGeneratable if job.safe_lock_key.nil?
job.mark_active_job_lock_as_started
block.call
@@ -40,6 +45,16 @@ module HasActiveJobLock
self.class.name
end
# Caches lock key for the duration of the job'
# Silences errors thrown when generating lock key
#
# return [String]
def safe_lock_key
@safe_lock_key ||= lock_key
rescue
nil
end
def mark_active_job_lock_as_started
release_active_job_lock_cache
@@ -56,28 +71,33 @@ module HasActiveJobLock
def ensure_active_job_lock_for_enqueue!
release_active_job_lock_cache
throw :abort if safe_lock_key.nil?
in_active_job_lock_transaction do
return if active_job_lock_for_enqueue!.present?
ActiveJobLock.create!(
lock_key: lock_key,
lock_key: safe_lock_key,
active_job_id: job_id,
)
end
end
def release_active_job_lock!
# nothing to release if lock key cannot be generated anymore
return if safe_lock_key.nil?
# only delete lock if the current job is the one holding the lock
# perform_now jobs or perform_later jobs for which follow-up jobs were enqueued
# don't need to remove any locks
lock = ActiveJobLock.lock.find_by(lock_key: lock_key, active_job_id: job_id)
lock = ActiveJobLock.lock.find_by(lock_key: safe_lock_key, active_job_id: job_id)
if !lock
logger.debug { "Found no ActiveJobLock for #{self.class.name} (Job ID: #{job_id}) with key '#{lock_key}'." }
logger.debug { "Found no ActiveJobLock for #{self.class.name} (Job ID: #{job_id}) with key '#{safe_lock_key}'." }
return
end
logger.debug { "Deleting ActiveJobLock for #{self.class.name} (Job ID: #{job_id}) with key '#{lock_key}'." }
logger.debug { "Deleting ActiveJobLock for #{self.class.name} (Job ID: #{job_id}) with key '#{safe_lock_key}'." }
lock.destroy!
end
@@ -114,7 +134,7 @@ module HasActiveJobLock
end
def active_job_lock
@active_job_lock ||= ActiveJobLock.lock.find_by(lock_key: lock_key)
@active_job_lock ||= ActiveJobLock.lock.find_by(lock_key: safe_lock_key)
end
def release_active_job_lock_cache

View File

@@ -128,6 +128,10 @@ returns
=end
def attributes_with_association_ids
key = "#{self.class}::aws::#{id}"
cache = Rails.cache.read(key)
return filter_unauthorized_attributes(cache) if cache && cache['updated_at'] == try(:updated_at)
attributes = self.attributes
relevant = %i[has_and_belongs_to_many has_many]
eager_load = []
@@ -163,6 +167,8 @@ returns
end
filter_attributes(attributes)
Rails.cache.write(key, attributes)
filter_unauthorized_attributes(attributes)
end

View File

@@ -3,8 +3,19 @@
module ApplicationModel::HasCache
extend ActiveSupport::Concern
def cache_update(_other)
included do
before_create :cache_delete
after_commit :cache_delete
end
def cache_update(other)
cache_delete if respond_to?(:cache_delete)
other.cache_delete if other.respond_to?(:cache_delete)
ActiveSupport::CurrentAttributes.clear_all
true
end
def cache_delete
Rails.cache.delete("#{self.class}::aws::#{id}")
end
end

View File

@@ -22,7 +22,7 @@ module ChecksCoreWorkflow
'class_name' => self.class.to_s,
'screen' => screen,
'params' => attributes
}, user: User.find(UserInfo.current_user_id))
}, user: User.find(UserInfo.current_user_id), assets: false)
check_restrict_values(perform_result)
check_mandatory(perform_result)

View File

@@ -44,6 +44,7 @@ class CoreWorkflow::Attributes::Group < CoreWorkflow::Attributes::Base
end
def assets(group)
return if @attributes.assets == false
return if @attributes.assets[Group.to_app_model] && @attributes.assets[Group.to_app_model][group.id]
@attributes.assets = group.assets(@attributes.assets)

View File

@@ -4,9 +4,16 @@ class CoreWorkflow::Attributes::TicketPriority < CoreWorkflow::Attributes::Base
def values
@values ||= begin
Ticket::Priority.where(active: true).each_with_object([]) do |priority, priority_ids|
@attributes.assets = priority.assets(@attributes.assets)
priority_ids.push priority.id
assets(priority)
end
end
end
def assets(priority)
return if @attributes.assets == false
return if @attributes.assets[Ticket::Priority.to_app_model] && @attributes.assets[Ticket::Priority.to_app_model][priority.id]
@attributes.assets = priority.assets(@attributes.assets)
end
end

View File

@@ -29,6 +29,7 @@ class CoreWorkflow::Attributes::TicketState < CoreWorkflow::Attributes::Base
end
def assets(state)
return if @attributes.assets == false
return if @attributes.assets[Ticket::State.to_app_model] && @attributes.assets[Ticket::State.to_app_model][state.id]
@attributes.assets = state.assets(@attributes.assets)

View File

@@ -100,6 +100,7 @@ class CoreWorkflow::Attributes::User < CoreWorkflow::Attributes::Base
end
def assets(user)
return if @attributes.assets == false
return if @attributes.assets[User.to_app_model] && @attributes.assets[User.to_app_model][user.id]
@attributes.assets = user.assets(@attributes.assets)

View File

@@ -116,6 +116,7 @@ class CoreWorkflow::Result
end
def assets_in_result?
return false if assets == false
return false if !@assets_in_result
@result[:assets] = assets

View File

@@ -31,7 +31,7 @@ returns if user has no permissions to search
{
prio: 1500,
direct_search_index: true,
direct_search_index: !customer_only?(current_user),
}
end
@@ -82,7 +82,7 @@ returns
# check order - positions related to sort by
order_by = sql_helper.get_order_by(params, %w[desc desc])
# enable search only for agents and admins
# enable search only for permitted users
return [] if !search_preferences(current_user)
# make sure customers always only can search their own organizations

View File

@@ -42,14 +42,17 @@ returns
data[ app_model ][ id ] = local_attributes
# get linked accounts
local_accounts = {}
authorizations.each do |authorization|
local_accounts[authorization.provider] = {
uid: authorization[:uid],
username: authorization[:username]
}
local_attributes['accounts'] = Rails.cache.fetch("User/authorizations/#{cache_key_with_version}") do
local_accounts = {}
authorizations = self.authorizations()
authorizations.each do |authorization|
local_accounts[authorization.provider] = {
uid: authorization[:uid],
username: authorization[:username]
}
end
local_accounts
end
local_attributes['accounts'] = local_accounts
# get roles
local_attributes['role_ids']&.each do |role_id|

View File

@@ -0,0 +1,41 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
class Controllers::AttachmentsControllerPolicy < Controllers::ApplicationControllerPolicy
def show?
store_object_policy(store_object_owner)&.show?
end
def destroy?
store_object_policy(store_object_owner)&.destroy?
end
def user_required?
false
end
def custom_exception
ActiveRecord::RecordNotFound.new
end
private
def download_file
record.send(:download_file)
end
def store_object_class
download_file
&.store_object
&.name
&.safe_constantize
end
def store_object_policy(target)
Pundit.policy user, target
end
def store_object_owner
store_object_class
&.find download_file.o_id
end
end

View File

@@ -1,14 +1,20 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
class KnowledgeBase::Answer::Translation::ContentPolicy < ApplicationPolicy
def show?
return true if user&.permissions?(%w[knowledge_base.editor])
delegate :show?, to: :parent_answer_policy
delegate :destroy?, to: :parent_answer_policy
record.translation.answer.visible? ||
(user&.permissions?(%w[knowledge_base.reader]) && record.translation.answer.visible_internally?)
def user_required?
false
end
def destroy?
user&.permissions?(%w[knowledge_base.editor])
private
def parent_answer_policy
Pundit.policy user, parent_answer
end
def parent_answer
record.translation.answer
end
end

View File

@@ -24,6 +24,10 @@ class KnowledgeBase::AnswerPolicy < ApplicationPolicy
access_editor?
end
def user_required?
false
end
private
def access

View File

@@ -0,0 +1,18 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
Rails.application.config.after_initialize do
EmailAddressValidator::Config.configure(
local_format: :standard,
local_encoding: :unicode,
host_local: true,
host_fqdn: false,
address_size: 3..250, # EmailAdress#email database field is limited to 250 characters, User#email is 255
host_auto_append: false
)
# Allow emails with very long local part. For example Google Docs notifications emails
EmailAddressValidator::Local.send(:remove_const, :STANDARD_MAX_SIZE)
EmailAddressValidator::Local.const_set(:STANDARD_MAX_SIZE, 200)
EmailAddressValidator::Config.providers.clear
end

View File

@@ -5,13 +5,13 @@
#
API_V1_USERS__PASSWORD_RESET_PATH = '/api/v1/users/password_reset'.freeze
Rack::Attack.throttle('limit password reset requests per username', limit: 3, period: 1.minute.to_i) do |req|
if req.path == API_V1_USERS__PASSWORD_RESET_PATH && req.post?
if req.path.start_with?(API_V1_USERS__PASSWORD_RESET_PATH) && req.post?
# Normalize to protect against rate limit bypasses.
req.params['username'].to_s.downcase.gsub(%r{\s+}, '')
end
end
Rack::Attack.throttle('limit password reset requests per source IP address', limit: 3, period: 1.minute.to_i) do |req|
if req.path == API_V1_USERS__PASSWORD_RESET_PATH && req.post?
if req.path.start_with?(API_V1_USERS__PASSWORD_RESET_PATH) && req.post?
req.ip
end
end
@@ -22,19 +22,19 @@ end
API_V1_FORM_SUBMIT_PATH = '/api/v1/form_submit'.freeze
form_limit_by_ip_per_hour_proc = proc { Setting.get('form_ticket_create_by_ip_per_hour') || 20 }
Rack::Attack.throttle('form submits per IP and hour', limit: form_limit_by_ip_per_hour_proc, period: 1.hour.to_i) do |req|
if req.path == API_V1_FORM_SUBMIT_PATH
if req.path.start_with?(API_V1_FORM_SUBMIT_PATH)
req.ip
end
end
form_limit_by_ip_per_day_proc = proc { Setting.get('form_ticket_create_by_ip_per_day') || 240 }
Rack::Attack.throttle('form submits per IP and day', limit: form_limit_by_ip_per_day_proc, period: 1.day.to_i) do |req|
if req.path == API_V1_FORM_SUBMIT_PATH
if req.path.start_with?(API_V1_FORM_SUBMIT_PATH)
req.ip
end
end
form_limit_per_day_proc = proc { Setting.get('form_ticket_create_per_day') || 5000 }
Rack::Attack.throttle('form submits per day', limit: form_limit_per_day_proc, period: 1.day.to_i) do |req|
if req.path == API_V1_FORM_SUBMIT_PATH
if req.path.start_with?(API_V1_FORM_SUBMIT_PATH)
req.path
end
end

View File

@@ -2,13 +2,17 @@ msgid ""
msgstr ""
"Project-Id-Version: zammad\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"PO-Revision-Date: 2022-06-28 05:33+0000\n"
"Last-Translator: DjMagicFingers <amir@srvit.co.il>\n"
"Language-Team: Hebrew (Israel) <https://translations.zammad.org/projects/"
"zammad/zammad-stable/he_IL/>\n"
"Language: he-il\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n == 1) ? 0 : ((n == 2) ? 1 : ((n > 10 && "
"n % 10 == 0) ? 2 : 3));\n"
"X-Generator: Weblate 4.13\n"
#. Default date format to use for the current locale.
#. These placeholders are supported:
@@ -44,7 +48,7 @@ msgstr "dd/mm/yyyy HH:MM"
#: app/frontend/shared/components/Form/fields/FieldDate/FieldDateTimeInput.vue
msgid " to "
msgstr ""
msgstr " אל "
#: db/seeds/settings.rb
msgid ""

File diff suppressed because it is too large Load Diff

View File

@@ -2,16 +2,16 @@ msgid ""
msgstr ""
"Project-Id-Version: zammad\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2022-06-17 15:08+0000\n"
"Last-Translator: francois littel <flittel@rentcompany.nl>\n"
"Language-Team: Dutch <https://translations.zammad.org/projects/zammad/zammad-"
"development/nl/>\n"
"PO-Revision-Date: 2022-07-04 08:42+0000\n"
"Last-Translator: JPB <jeffreypeerboom@eijsden-margraten.nl>\n"
"Language-Team: Dutch <https://translations.zammad.org/projects/zammad/"
"zammad-stable/nl/>\n"
"Language: nl-nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.12.1\n"
"X-Generator: Weblate 4.13\n"
#. Default date format to use for the current locale.
#. These placeholders are supported:
@@ -103,7 +103,7 @@ msgstr ""
#: app/assets/javascripts/app/models/ticket_article.coffee
msgid "%s created article for |%s|"
msgstr "%s maakte nototie voor |%s|"
msgstr "%s maakte notitie voor |%s|"
#: app/assets/javascripts/app/models/data_privacy_task.coffee
msgid "%s created data privacy task to delete user ID |%s|"
@@ -137,10 +137,8 @@ msgid "%s credentials"
msgstr "%s credentials"
#: app/frontend/shared/i18n/dates.ts
#, fuzzy
#| msgid "%s ago"
msgid "%s days ago"
msgstr "%s geleden"
msgstr "%s dagen geleden"
#: app/assets/javascripts/app/models/user.coffee
msgid "%s ended switch to |%s|!"
@@ -748,19 +746,17 @@ msgstr "Voeg bijlage-optie toe om te uploaden."
#: app/frontend/shared/components/Form/fields/FieldEditor/useEditorActions.ts
msgid "Add bullet list"
msgstr ""
msgstr "Voeg opsommingslijst toe"
#: app/frontend/shared/components/Form/fields/FieldEditor/useEditorActions.ts
msgid "Add first level heading"
msgstr ""
msgstr "Voeg hoofdniveau koptekst toe"
#: app/frontend/shared/components/Form/fields/FieldEditor/useEditorActions.ts
msgid "Add image"
msgstr "Afbeelding toevoegen"
#: app/frontend/shared/components/Form/fields/FieldEditor/useEditorActions.ts
#, fuzzy
#| msgid "Add Link"
msgid "Add link"
msgstr "Link toevoegen"
@@ -770,7 +766,7 @@ msgstr "Voeg toe als geordende lijst"
#: app/frontend/shared/components/Form/fields/FieldEditor/useEditorActions.ts
msgid "Add second level heading"
msgstr ""
msgstr "Voeg tweede niveau koptekst toe"
#: db/seeds/settings.rb
msgid "Add sender initials to end of a tweet."
@@ -778,7 +774,7 @@ msgstr "Voeg initialen toe van de behandelaar aan het eind van de tweet."
#: app/frontend/shared/components/Form/fields/FieldEditor/useEditorActions.ts
msgid "Add third level heading"
msgstr ""
msgstr "Voeg derde niveau koptekst toe"
#: app/assets/javascripts/app/controllers/_channel/chat.coffee
msgid "Add this class to a button on your page that should open the chat."
@@ -1186,10 +1182,8 @@ msgid "At least one user needs to have admin permissions."
msgstr "Minimaal één gebruiker moet administrator rechten hebben."
#: app/assets/javascripts/app/lib/app_post/utils.coffee
#, fuzzy
#| msgid "Attachments"
msgid "Attached"
msgstr "Bijlagen"
msgstr "Bijgevoegd"
#: app/assets/javascripts/app/views/generic/attachments.jst.eco
#: app/views/knowledge_base/public/answers/show.html.erb
@@ -1197,10 +1191,8 @@ msgid "Attached Files"
msgstr "Bijgevoegde bestanden"
#: app/assets/javascripts/app/lib/app_post/utils.coffee
#, fuzzy
#| msgid "Attachments"
msgid "Attachment"
msgstr "Bijlagen"
msgstr "Bijlage"
#: db/seeds/settings.rb
msgid "Attachment - Search for follow-up also in attachments."
@@ -1644,8 +1636,6 @@ msgstr "Ook de Caller ID van uitgaande gesprekken kan worden gewijzigd."
#: app/assets/javascripts/app/views/integration/cti.jst.eco
#: app/assets/javascripts/app/views/integration/placetel.jst.eco
#: app/assets/javascripts/app/views/integration/sipgate.jst.eco
#, fuzzy
#| msgid "Caller id to block"
msgid "Caller ID to block"
msgstr "Caller ID om te blokkeren"
@@ -2021,8 +2011,6 @@ msgid "Clean up expired sessions."
msgstr "Schoon verlopen sessies op."
#: app/frontend/shared/components/Form/fields/FieldDate/FieldDateTimeInput.vue
#, fuzzy
#| msgid "clear"
msgid "Clear"
msgstr "Wissen"
@@ -2204,10 +2192,8 @@ msgid "Configure App"
msgstr "Configureer App"
#: app/assets/javascripts/app/controllers/getting_started/base.coffee
#, fuzzy
#| msgid "Basic Settings"
msgid "Configure Basic Settings"
msgstr "Basisinstellingen"
msgstr "Configureer Basisinstellingen"
#: app/assets/javascripts/app/controllers/_plugin/keyboard_shortcuts.coffee
msgid "Confirm/submit dialog"
@@ -2596,10 +2582,8 @@ msgid "Created by"
msgstr "Aangemaakt door"
#: app/models/report.rb
#, fuzzy
#| msgid "Create Channels"
msgid "Creation Channels"
msgstr "Kanalen aanmaken"
msgstr "Aanmaakkanaal"
#: app/assets/javascripts/app/controllers/core_workflow.coffee
msgid "Creation mask"
@@ -4347,16 +4331,12 @@ msgid "Enables users to create their own account via web interface."
msgstr "Hiermee kunnen gebruikers hun eigen account aanmaken via webinterface."
#: app/assets/javascripts/app/lib/app_post/utils.coffee
#, fuzzy
#| msgid "closed"
msgid "Enclosed"
msgstr "gesloten"
msgstr "Bijgevoegd"
#: app/assets/javascripts/app/lib/app_post/utils.coffee
#, fuzzy
#| msgid "close"
msgid "Enclosure"
msgstr "sluiten"
msgstr "Omsluiting"
#: app/assets/javascripts/app/views/agent_ticket_create.jst.eco
#: app/assets/javascripts/app/views/ticket_zoom/article_new.jst.eco
@@ -4428,7 +4408,7 @@ msgstr "Invoergegevens invoeren"
#: app/frontend/shared/components/Form/fields/FieldEditor/useEditorActions.ts
msgid "Enter link URL"
msgstr ""
msgstr "Voer URL in"
#: app/assets/javascripts/app/views/import/freshdesk.jst.eco
#: app/assets/javascripts/app/views/import/kayako.jst.eco
@@ -4595,8 +4575,6 @@ msgid "Examples"
msgstr "Voorbeelden"
#: app/assets/javascripts/app/controllers/_manage/ticket_auto_assignment.coffee
#, fuzzy
#| msgid "Exception users"
msgid "Excepted users"
msgstr "Uitgezonderde gebruikers"
@@ -5210,8 +5188,6 @@ msgstr "Groepsselectie voor het maken van tickets"
#: app/assets/javascripts/app/controllers/ticket_overview.coffee
#: app/assets/javascripts/app/models/overview.coffee
#, fuzzy
#| msgid "Group by"
msgid "Grouping by"
msgstr "Groeperen op"
@@ -5539,6 +5515,8 @@ msgid ""
"If a user is found in two (or more) configured LDAP sources, the last "
"synchronisation will win."
msgstr ""
"Als een gebruiker wordt gevonden in twee (of meer) geconfigureerde LDAP "
"bronnen, dan zal de laatst gesynchroniseerde worden gebruikt."
#: app/assets/javascripts/app/controllers/_channel/chat.coffee
msgid ""
@@ -5776,6 +5754,8 @@ msgid ""
"In order to be able to influence the desired behaviour in this regard, you "
"can influence the order of the LDAP sources via drag & drop."
msgstr ""
"Om dit gedrag te beïnvloeden kun je de volgorde van LDAP bronnen aanpassen "
"via drag en drop."
#: app/assets/javascripts/app/views/channel/email_account_overview.jst.eco
#: app/assets/javascripts/app/views/channel/sms_account_overview.jst.eco
@@ -6827,7 +6807,7 @@ msgstr "Stemming"
#: app/models/user.rb
msgid "More than 250 secondary organizations are not allowed."
msgstr ""
msgstr "Meer dan 250 secundaire organisaties zijn niet toegestaan."
#: app/assets/javascripts/app/views/profile/devices.jst.eco
msgid "Most recent activity"
@@ -7091,10 +7071,8 @@ msgid "New Scheduler"
msgstr "Nieuwe taak"
#: app/assets/javascripts/app/controllers/_integration/ldap.coffee
#, fuzzy
#| msgid "Source"
msgid "New Source"
msgstr "Bron"
msgstr "Nieuwe bron"
#: app/assets/javascripts/app/views/tag/index.jst.eco db/seeds/settings.rb
msgid "New Tags"
@@ -7715,10 +7693,8 @@ msgstr ""
"…) en klanten."
#: app/assets/javascripts/app/views/generic/calender_preview.jst.eco
#, fuzzy
#| msgid "Organization"
msgid "Organizer"
msgstr "Organisatie"
msgstr "Organisator"
#: app/assets/javascripts/app/models/ticket_article.coffee
msgid "Origin By"
@@ -7941,7 +7917,7 @@ msgstr "Overschreden Tickets"
#: app/assets/javascripts/app/models/ticket.coffee
msgid "Pending reminder reached for ticket |%s|"
msgstr "Herinnering voor Ticket |% s |"
msgstr "Herinnering voor Ticket |%s|"
#: app/assets/javascripts/app/models/ticket.coffee
#: db/seeds/object_manager_attributes.rb
@@ -8300,7 +8276,7 @@ msgstr "Ruwe data"
#: app/assets/javascripts/app/models/group.coffee
msgid "Read"
msgstr ""
msgstr "Lezen"
#: app/assets/javascripts/app/views/report/time_range_picker.jst.eco
msgid "Real-time"
@@ -8851,6 +8827,8 @@ msgid ""
"Secondary organizations are only allowed when the primary organization is "
"given."
msgstr ""
"Secundaire organisaties zijn alleen toegestaan als de primaire organisatie "
"is opgegeven."
#: app/assets/javascripts/app/controllers/_manage/security.coffee
#: app/assets/javascripts/app/views/agent_ticket_create.jst.eco
@@ -9213,13 +9191,11 @@ msgstr "Minder tonen"
#: app/assets/javascripts/app/controllers/_plugin/keyboard_shortcuts.coffee
msgid "Show next tab"
msgstr ""
msgstr "Toon volgende tab"
#: app/assets/javascripts/app/controllers/_plugin/keyboard_shortcuts.coffee
#, fuzzy
#| msgid "Previous tab"
msgid "Show previous tab"
msgstr "Vorige tab"
msgstr "Toon vorige tab"
#: app/assets/javascripts/app/controllers/_channel/chat.coffee
msgid "Show the chat when ready."
@@ -9864,7 +9840,7 @@ msgid ""
"hackers to steal your credentials. If you are sure that you are using a self-"
"signed certificate, you can press \"Proceed\". Otherwise, please \"Cancel\"."
msgstr ""
"Het certificaat van het domein |% s | kan niet worden geverifieerd. Hierdoor "
"Het certificaat van het domein |%s| kan niet worden geverifieerd. Hierdoor "
"kunnen hackers uw inloggegevens stelen. Als u zeker weet dat u een "
"zelfondertekend certificaat gebruikt, kunt u op \"Doorgaan\" drukken. Anders "
"\"Annuleren\"."
@@ -10074,6 +10050,8 @@ msgstr ""
msgid ""
"The preview cannot be generated. The format is corrupted or not supported."
msgstr ""
"Het voorbeeld kan niet worden gegenereerd. Het formaat is beschadigd of "
"wordt niet ondersteund."
#: app/controllers/import_freshdesk_controller.rb
#: app/controllers/import_kayako_controller.rb
@@ -10127,7 +10105,7 @@ msgstr "Het verzoek kon niet worden verwerkt."
#: app/controllers/channels_twitter_controller.rb
msgid "The required 'ExternalCredential' 'twitter' could not be found."
msgstr ""
msgstr "De vereiste 'ExternalCredential' 'twitter' kon niet worden gevonden."
#: lib/idoit.rb
msgid "The required field 'api_token' is missing from the config."
@@ -10255,6 +10233,7 @@ msgstr "De vereiste parameter 'group_id' ontbreekt."
#: app/controllers/channels_twitter_controller.rb
msgid "The required value external_credential could not be found in the cache."
msgstr ""
"De vereiste waarde external_credential kan niet worden gevonden in de cache."
#: app/controllers/users_controller.rb
msgid "The resized image is invalid."
@@ -10451,10 +10430,8 @@ msgid "This field doesn't contain an allowed value."
msgstr "Dit veld bevat geen toegestane waarde."
#: app/frontend/shared/form/i18n/locales.ts
#, fuzzy
#| msgid "The file does not belong to the specified article."
msgid "This field doesn't correspond to the expected value."
msgstr "Het bestand behoort niet tot de opgegeven notitie."
msgstr "Dit veld komt niet overeen met de verwachte waarde."
#: app/frontend/shared/form/i18n/locales.ts
msgid "This field doesn't end with \"%s\"."
@@ -11369,7 +11346,7 @@ msgstr "Gebruik de tijd van de allerlaatste klantnotitie."
#: app/assets/javascripts/app/controllers/_integration/ldap.coffee
msgid "Use this switch to start synchronization of your ldap sources. "
msgstr ""
"Gebruik deze schakelaar om de synchronisatie van je ldap bronnen te starten. "
"Gebruik deze schakelaar om de synchronisatie van je LDAP bronnen te starten. "
#: app/assets/javascripts/app/controllers/_plugin/keyboard_shortcuts.coffee
msgid "Used anywhere"
@@ -11474,8 +11451,6 @@ msgstr "Gebruikersnaam"
#: app/frontend/apps/mobile/modules/login/views/Login.vue
#: app/models/form_schema/form/mobile/login.rb
#, fuzzy
#| msgid "Username / email"
msgid "Username / Email"
msgstr "Gebruikersnaam / e-mailadres"
@@ -12489,7 +12464,7 @@ msgstr "Postcode"
#: db/seeds/settings.rb
msgid "absolute - e. g. \"Monday 09:30\" or \"Tuesday 23. Feb 14:20\""
msgstr ""
msgstr "absoluut - \"Maandag 09:30\" of \"Dinsdag 23. Feb 14:20\""
#: app/assets/javascripts/app/controllers/_ui_element/active.coffee
msgid "active"
@@ -12537,16 +12512,12 @@ msgid "at"
msgstr "om"
#: app/assets/javascripts/app/lib/app_post/utils.coffee
#, fuzzy
#| msgid "reached"
msgid "attached"
msgstr "bereikt"
msgstr "bijgevoegd"
#: app/assets/javascripts/app/lib/app_post/utils.coffee
#, fuzzy
#| msgid "Attachments"
msgid "attachment"
msgstr "Bijlagen"
msgstr "bijlage"
#: app/assets/javascripts/app/controllers/_ui_element/core_workflow_perform.coffee
msgid "auto select"
@@ -12687,8 +12658,6 @@ msgid "disconnect"
msgstr "verbreken"
#: app/assets/javascripts/app/controllers/cti.coffee
#, fuzzy
#| msgid "not exist"
msgid "does not exist"
msgstr "bestaat niet"
@@ -12727,7 +12696,7 @@ msgstr "wijzig %s"
#: app/frontend/apps/mobile/composables/useEditedBy.ts
msgid "edited %s by %s"
msgstr ""
msgstr "Aangepast %s door %s"
#: db/seeds/ticket_article_types.rb
msgid "email"
@@ -12738,16 +12707,12 @@ msgid "email sent to '%s'"
msgstr "E-mail verzonden naar '%s'"
#: app/assets/javascripts/app/lib/app_post/utils.coffee
#, fuzzy
#| msgid "closed"
msgid "enclosed"
msgstr "gesloten"
msgstr "bijgevoegd"
#: app/assets/javascripts/app/lib/app_post/utils.coffee
#, fuzzy
#| msgid "close"
msgid "enclosure"
msgstr "sluiten"
msgstr "omsluiting"
#: app/assets/javascripts/app/models/ticket.coffee
msgid "escalated"
@@ -12968,7 +12933,7 @@ msgstr "vorige week"
#: db/seeds/settings.rb
msgid "left"
msgstr ""
msgstr "links"
#: app/assets/javascripts/app/lib/app_post/pretty_date.coffee
msgid "m"
@@ -13315,7 +13280,7 @@ msgstr "tot (relatief)"
#: db/seeds/settings.rb
msgid "timestamp - e. g. \"2018-08-30 14:30\""
msgstr ""
msgstr "timestamp - \"2018-08-30 14:30\""
#: app/views/knowledge_base/public/not_found.html.erb
msgid "to go to the homepage."

View File

@@ -2,17 +2,17 @@ msgid ""
msgstr ""
"Project-Id-Version: zammad\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2022-05-29 03:30+0000\n"
"PO-Revision-Date: 2022-06-28 05:33+0000\n"
"Last-Translator: Zhilin Ruslan <x-th-unicorn@hotmail.com>\n"
"Language-Team: Russian <https://translations.zammad.org/projects/zammad/"
"zammad-development/ru/>\n"
"zammad-stable/ru/>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 4.12.1\n"
"X-Generator: Weblate 4.13\n"
#. Default date format to use for the current locale.
#. These placeholders are supported:
@@ -239,10 +239,8 @@ msgstr "%s переключился на |%s|!"
#: app/frontend/apps/mobile/components/Organization/OrganizationItem.vue
#: app/frontend/apps/mobile/components/User/UserItem.vue
#, fuzzy
#| msgid "assign tickets"
msgid "%s tickets"
msgstr "назначить заявки"
msgstr "%s заявки"
#: app/assets/javascripts/app/models/ticket_article.coffee
msgid "%s updated article for |%s|"
@@ -529,7 +527,7 @@ msgstr "Ключ программного интерфейса приложен
#: app/frontend/apps/mobile/modules/account/views/AccountOverview.vue
msgid "About"
msgstr ""
msgstr "Об"
#: db/seeds/permissions.rb
msgid "Access to %s"
@@ -1199,10 +1197,8 @@ msgid "At least one user needs to have admin permissions."
msgstr "По крайней мере, один пользователь должен иметь права администратора."
#: app/assets/javascripts/app/lib/app_post/utils.coffee
#, fuzzy
#| msgid "Attachments"
msgid "Attached"
msgstr "Вложения"
msgstr "Вложенный"
#: app/assets/javascripts/app/views/generic/attachments.jst.eco
#: app/views/knowledge_base/public/answers/show.html.erb
@@ -1210,10 +1206,8 @@ msgid "Attached Files"
msgstr "Прикрепленные файлы"
#: app/assets/javascripts/app/lib/app_post/utils.coffee
#, fuzzy
#| msgid "Attachments"
msgid "Attachment"
msgstr "Вложения"
msgstr "Вложение"
#: db/seeds/settings.rb
msgid "Attachment - Search for follow-up also in attachments."
@@ -1396,10 +1390,8 @@ msgid "Back to my view"
msgstr "Вернуться к моему виду"
#: app/assets/javascripts/app/views/integration/ldap.jst.eco
#, fuzzy
#| msgid "Back to my view"
msgid "Back to overview"
msgstr "Вернуться к моему виду"
msgstr "Назад к обзору"
#: app/assets/javascripts/app/views/knowledge_base/reader.jst.eco
msgid "Back to search results"
@@ -4395,16 +4387,12 @@ msgstr ""
"интерфейс."
#: app/assets/javascripts/app/lib/app_post/utils.coffee
#, fuzzy
#| msgid "closed"
msgid "Enclosed"
msgstr "Закрыта"
msgstr "Приложенный"
#: app/assets/javascripts/app/lib/app_post/utils.coffee
#, fuzzy
#| msgid "close"
msgid "Enclosure"
msgstr "закрыть"
msgstr "Вложение"
#: app/assets/javascripts/app/views/agent_ticket_create.jst.eco
#: app/assets/javascripts/app/views/ticket_zoom/article_new.jst.eco
@@ -5589,6 +5577,8 @@ msgid ""
"If a user is found in two (or more) configured LDAP sources, the last "
"synchronisation will win."
msgstr ""
"Если пользователь найден в двух (или более) настроенных источниках LDAP, "
"последняя синхронизация будет иметь преимущество."
#: app/assets/javascripts/app/controllers/_channel/chat.coffee
msgid ""
@@ -5837,6 +5827,8 @@ msgid ""
"In order to be able to influence the desired behaviour in this regard, you "
"can influence the order of the LDAP sources via drag & drop."
msgstr ""
"Чтобы влиять на поведение в этом отношении, вы можете изменить порядок "
"источников LDAP, перетаскивая их мышью."
#: app/assets/javascripts/app/views/channel/email_account_overview.jst.eco
#: app/assets/javascripts/app/views/channel/sms_account_overview.jst.eco
@@ -6007,16 +5999,12 @@ msgid "Internal"
msgstr "Внутренний"
#: app/models/import_job.rb
#, fuzzy
#| msgid ""
#| "Interrupted by scheduler restart. Please restart manually or wait till "
#| "next execution time."
msgid ""
"Interrupted by a restart of the background worker process. Please restart "
"manually or wait until the next execution time."
msgstr ""
"Прервано перезапуском планировщика. Пожалуйста, перезапустите вручную или "
"дождитесь следующего времени выполнения."
"Прервано перезапуском фонового рабочего процесса. Пожалуйста, перезапустите "
"вручную или дождитесь следующего времени выполнения."
#: app/controllers/first_steps_controller.rb
msgid "Intro"
@@ -6360,10 +6348,8 @@ msgid "Last run"
msgstr "Последний запуск"
#: app/frontend/apps/mobile/modules/search/views/SearchOverview.vue
#, fuzzy
#| msgid "Last sync"
msgid "Last searches"
msgstr "Последняя синхронизация"
msgstr "Последние запросы"
#: app/assets/javascripts/app/views/integration/exchange_last_import.jst.eco
#: app/assets/javascripts/app/views/integration/ldap_last_import.jst.eco
@@ -6388,7 +6374,7 @@ msgstr "Макет"
#: app/frontend/apps/mobile/modules/account/views/AccountAvatar.vue
msgid "Library"
msgstr ""
msgstr "Библиотека"
#: app/assets/javascripts/app/views/profile/notification.jst.eco
msgid "Limit Groups"
@@ -7167,10 +7153,8 @@ msgid "New Scheduler"
msgstr "Новое Расписание"
#: app/assets/javascripts/app/controllers/_integration/ldap.coffee
#, fuzzy
#| msgid "Source"
msgid "New Source"
msgstr "Оригинал"
msgstr "Новый источник"
#: app/assets/javascripts/app/views/tag/index.jst.eco db/seeds/settings.rb
msgid "New Tags"
@@ -7316,10 +7300,8 @@ msgid "No code for session found!"
msgstr "Код сеанса не найден!"
#: app/assets/javascripts/app/views/integration/ldap.jst.eco
#, fuzzy
#| msgid "Save configuration"
msgid "No configuration set."
msgstr "Сохранить конфигурацию"
msgstr "Не задана конфигурация."
#: app/models/calendar.rb
msgid "No configured business hours found!"
@@ -7359,10 +7341,8 @@ msgid "No linked issues"
msgstr "Нет связанных проблем"
#: app/frontend/apps/mobile/modules/search/views/SearchOverview.vue
#, fuzzy
#| msgid "Show previous tab"
msgid "No previous searches"
msgstr "Показать предыдущую вкладку"
msgstr "Нет предыдущих запросов"
#: db/seeds/settings.rb
msgid "No proxy for the following hosts."
@@ -9226,10 +9206,8 @@ msgid "Settings"
msgstr "Параметры"
#: app/assets/javascripts/app/views/integration/ldap.jst.eco
#, fuzzy
#| msgid "Settings"
msgid "Settings %s"
msgstr "Параметры"
msgstr "Параметры %s"
#: app/assets/javascripts/app/controllers/getting_started/finish.coffee
#: app/assets/javascripts/app/views/getting_started/finish.jst.eco
@@ -9496,10 +9474,8 @@ msgid "Source"
msgstr "Оригинал"
#: app/assets/javascripts/app/controllers/_integration/ldap.coffee
#, fuzzy
#| msgid "Source"
msgid "Sources"
msgstr "Оригинал"
msgstr "Источники"
#: db/seeds/settings.rb
msgid "Special character required"
@@ -10866,10 +10842,8 @@ msgid "Ticket failed to save: %s"
msgstr "Заявку не удалось сохранить: %s"
#: app/frontend/apps/mobile/modules/account/views/AccountOverview.vue
#, fuzzy
#| msgid "Block Notifications"
msgid "Ticket notifications"
msgstr "Блокировка уведомлений"
msgstr "Уведомления о заявках"
#: app/assets/javascripts/app/controllers/_profile/notification.coffee
msgid "Ticket reminder reached"
@@ -11488,6 +11462,8 @@ msgstr "Использовать время самой последней ста
#: app/assets/javascripts/app/controllers/_integration/ldap.coffee
msgid "Use this switch to start synchronization of your ldap sources. "
msgstr ""
"Используйте этот переключатель, чтобы начать синхронизацию ваших источников "
"LDAP. "
#: app/assets/javascripts/app/controllers/_plugin/keyboard_shortcuts.coffee
msgid "Used anywhere"
@@ -12659,16 +12635,12 @@ msgid "at"
msgstr "в"
#: app/assets/javascripts/app/lib/app_post/utils.coffee
#, fuzzy
#| msgid "reached"
msgid "attached"
msgstr "достигнуто"
msgstr "прикрепленный"
#: app/assets/javascripts/app/lib/app_post/utils.coffee
#, fuzzy
#| msgid "Attachments"
msgid "attachment"
msgstr "Вложения"
msgstr "вложение"
#: app/assets/javascripts/app/controllers/_ui_element/core_workflow_perform.coffee
msgid "auto select"
@@ -12842,14 +12814,12 @@ msgid "edit"
msgstr "редактировать"
#: app/frontend/apps/mobile/composables/useEditedBy.ts
#, fuzzy
#| msgid "edit"
msgid "edited %s"
msgstr "редактировать"
msgstr "отредактировано %s"
#: app/frontend/apps/mobile/composables/useEditedBy.ts
msgid "edited %s by %s"
msgstr ""
msgstr "отредактировано %s пользователем %s"
#: db/seeds/ticket_article_types.rb
msgid "email"
@@ -12860,16 +12830,12 @@ msgid "email sent to '%s'"
msgstr "письмо отправлено на '%s'"
#: app/assets/javascripts/app/lib/app_post/utils.coffee
#, fuzzy
#| msgid "closed"
msgid "enclosed"
msgstr "Закрыта"
msgstr "приложенный"
#: app/assets/javascripts/app/lib/app_post/utils.coffee
#, fuzzy
#| msgid "close"
msgid "enclosure"
msgstr "закрыть"
msgstr "приложение"
#: app/assets/javascripts/app/models/ticket.coffee
msgid "escalated"
@@ -13120,10 +13086,8 @@ msgid "maybe"
msgstr "может быть"
#: app/frontend/apps/mobile/composables/useEditedBy.ts
#, fuzzy
#| msgid "m"
msgid "me"
msgstr "м"
msgstr "мне"
#: db/seeds/ticket_state_types.rb db/seeds/ticket_states.rb
msgid "merged"

File diff suppressed because it is too large Load Diff

View File

@@ -8,6 +8,8 @@ class Auth
attr_accessor :increase_login_failed_attempts
BRUTE_FORCE_SLEEP = 1.second
# Initializes a Auth object for the given user.
#
# @param username [String] the user name for the user object which needs an authentication.
@@ -28,20 +30,21 @@ class Auth
#
# @return [Boolean] true if the user was authenticated, otherwise false.
def valid?
if !auth_user || !auth_user.can_login?
avoid_brute_force_attack
# Wrap in a lock to synchronize concurrent requests.
validated = auth_user&.user&.with_lock do
next false if !auth_user.can_login?
next true if backends.valid?
return false
auth_user.increase_login_failed if increase_login_failed_attempts
false
end
if backends.valid?
if validated
auth_user.update_last_login
return true
end
avoid_brute_force_attack
auth_user.increase_login_failed if increase_login_failed_attempts
false
end
@@ -49,7 +52,7 @@ class Auth
# Sleep for a second to avoid brute force attacks.
def avoid_brute_force_attack
sleep 1
sleep BRUTE_FORCE_SLEEP
end
def backends

View File

@@ -23,11 +23,8 @@ class EmailAddressValidation
# @return [true] if email address has valid format
# @return [false] if email address has no valid format
def valid?(check_mx: false)
EmailAddressValidator.valid? email_address,
host_validation: (check_mx ? :mx : :syntax),
local_encoding: :unicode,
host_local: true,
host_fqdn: false,
host_auto_append: false
host_validation_type = check_mx ? :mx : :syntax
EmailAddressValidator.valid? email_address, host_validation: host_validation_type
end
end

View File

@@ -55,10 +55,6 @@ module Import
# Provides the integration configuration.
#
# @example
# Import::Ldap.config
# #=> {"ssl_verify"=>true, "host_url"=>"ldaps://192...", ...}
#
# return [Hash] the configuration
def self.config
Setting.get("#{identifier.downcase}_config") || {}
@@ -66,9 +62,6 @@ module Import
# Stores the integration configuration.
#
# @example
# Import::Ldap.config = {"ssl_verify"=>true, "host_url"=>"ldaps://192...", ...}
#
# return [nil]
def self.config=(value)
Setting.set("#{identifier.downcase}_config", value)
@@ -79,7 +72,7 @@ module Import
# an error which is confusing and wrong.
#
# @example
# Import::Ldap.queueable?
# Import::Exchange.queueable?
# #=> true
#
# return [Boolean]

View File

@@ -4,6 +4,10 @@ module Import
class Ldap < Import::IntegrationBase
include Import::Mixin::Sequence
def self.queueable?
active? && LdapSource.count.positive?
end
private
def sequence_name

View File

@@ -2,8 +2,8 @@
class SearchIndexBackend
SUPPORTED_ES_VERSION_MINIMUM = '7.8'.freeze
SUPPORTED_ES_VERSION_MAXIMUM = '8'.freeze
SUPPORTED_ES_VERSION_MINIMUM = '7.8'.freeze
SUPPORTED_ES_VERSION_LESS_THAN = '9'.freeze
=begin
@@ -25,7 +25,7 @@ info about used search index machine
installed_version_parsed = Gem::Version.new(installed_version)
if (installed_version_parsed > Gem::Version.new(SUPPORTED_ES_VERSION_MAXIMUM)) ||
if (installed_version_parsed >= Gem::Version.new(SUPPORTED_ES_VERSION_LESS_THAN)) ||
(installed_version_parsed < Gem::Version.new(SUPPORTED_ES_VERSION_MINIMUM))
raise "Version #{installed_version} of configured elasticsearch is not supported."
end

View File

@@ -1018,4 +1018,33 @@ QUnit.test('form checks', assert => {
},
}
assert.deepEqual(params, test_params, 'form param condition check for multiple users and organisation')
// https://github.com/zammad/zammad/issues/4153
$('#forms').append('<hr><h1>Trigger Attribute "action > is > updated" is not working after Zammad 5.2 update #4153</h1><form id="form7"></form>')
var el = $('#form7')
var defaults = {
condition: {
'ticket.action': {
operator: 'is',
value: 'update',
},
'ticket.state_id': {
operator: 'is',
pre_condition: 'specific',
value: [1],
},
},
}
new App.ControllerForm({
el: el,
model: {
configure_attributes: [
{ name: 'condition', display: 'Conditions', tag: 'ticket_selector', null: true, action: true },
]
},
params: defaults,
autofocus: true
})
assert.equal(undefined, $("#form7 select[name='condition::ticket.action::value']").attr('multiple'), 'ticket action is not multiple')
assert.equal('multiple', $("#form7 select[name='condition::ticket.state_id::value']").attr('multiple'), 'state id is multiple')
});

View File

@@ -6,8 +6,8 @@ RSpec.describe ApplicationController::HasDownload::DownloadFile do
subject(:download_file) { described_class.new(stored_file.id, disposition: 'inline') }
let(:file_content_type) { 'application/pdf' }
let(:file_data) { 'A example file.' }
let(:file_name) { 'example.pdf' }
let(:file_data) { 'A example file.' }
let(:file_name) { 'example.pdf' }
let(:stored_file) do
create(:store,

View File

@@ -28,11 +28,11 @@ RSpec.describe FixedStoreUpgradeRor45, type: :db_migration do
SQL
end
let(:mysql?) { ActiveRecord::Base.connection_db_config.configuration_hash[:adapter] == 'mysql2' }
let(:user) { User.last }
let(:mysql?) { ActiveRecord::Base.connection_db_config.configuration_hash[:adapter] == 'mysql2' }
let(:user) { User.last }
let(:last_contact) { '2017-09-01 10:10:00' }
let(:state) { ActionController::Parameters.new('ticket' => {}, 'article' => {}) }
let(:params) { ActionController::Parameters.new('ticket_id' => 1234, 'shown' => true) }
let(:state) { ActionController::Parameters.new('ticket' => {}, 'article' => {}) }
let(:params) { ActionController::Parameters.new('ticket_id' => 1234, 'shown' => true) }
let(:preferences) do
ActionController::Parameters.new(
'tasks' => [

View File

@@ -4,7 +4,7 @@ require 'rails_helper'
RSpec.describe Issue3123ExternalSyncTicketMerge, type: :db_migration do
let(:user) { create(:agent) }
let(:user) { create(:agent) }
let(:source_ticket) { create(:ticket) }
let(:target_ticket) { create(:ticket) }

View File

@@ -5,8 +5,8 @@ require 'rails_helper'
RSpec.describe Issue2460FixCorruptedTwitterIds, type: :db_migration do
before { allow(Twitter::REST::Client).to receive(:new).and_return(client) }
let(:client) { double('Twitter::REST::Client', user: twitter_api_user) }
let(:twitter_api_user) { double('Twitter::User', id: twitter_api_user_id) }
let(:client) { double('Twitter::REST::Client', user: twitter_api_user) }
let(:twitter_api_user) { double('Twitter::User', id: twitter_api_user_id) }
let(:twitter_api_user_id) { 1234567890 } # rubocop:disable Style/NumericLiterals
context 'with existing, corrupted Twitter channel' do

View File

@@ -3,7 +3,7 @@
require 'rails_helper'
RSpec.describe Issue2671PendingTillCanBeChangedByCustomer, type: :db_migration do
let(:attr) { ObjectManager::Attribute.find_by name: :pending_time }
let(:attr) { ObjectManager::Attribute.find_by name: :pending_time }
let(:initial_data_option) { { future: true, past: true, diff: 0 } }
before do

View File

@@ -4,7 +4,7 @@ require 'rails_helper'
RSpec.describe Issue3851, type: :db_migration do
let(:follow_up_assignment) { ObjectManager::Attribute.for_object('Group').find_by(name: 'follow_up_assignment') }
let(:follow_up_possible) { ObjectManager::Attribute.for_object('Group').find_by(name: 'follow_up_possible') }
let(:follow_up_possible) { ObjectManager::Attribute.for_object('Group').find_by(name: 'follow_up_possible') }
before do
migrate

View File

@@ -9,8 +9,8 @@ RSpec.describe RemoveDuplicateTranslations, type: :db_migration do
end
context 'when having unsynchronized entries with duplicates' do
let!(:unrelated_entry_one) { create_translation({ source: 'unknown entry', target: 'unknown translation', is_synchronized_from_codebase: false }) }
let!(:unrelated_entry_two) { create_translation({ source: 'unknown entry', target: 'unknown translation', is_synchronized_from_codebase: false }) }
let!(:unrelated_entry_one) { create_translation({ source: 'unknown entry', target: 'unknown translation', is_synchronized_from_codebase: false }) }
let!(:unrelated_entry_two) { create_translation({ source: 'unknown entry', target: 'unknown translation', is_synchronized_from_codebase: false }) }
let!(:unrelated_entry_three) { create_translation({ source: 'unknown entry', target: 'unknown translation', is_synchronized_from_codebase: false }) }
before do

View File

@@ -3,7 +3,7 @@
require 'rails_helper'
RSpec.describe SetUserSourceLdapFromExternalSync, type: :db_migration, db_strategy: :reset do
let(:users) { create_list(:user, 2) }
let(:users) { create_list(:user, 2) }
let(:other_user) { create(:user) }
before do

View File

@@ -5,11 +5,11 @@ require 'rails_helper'
RSpec.describe Gql::Mutations::Form::UploadCache::Add, type: :graphql do
context 'when uploading files for a form', authenticated_as: :agent do
let(:agent) { create(:agent) }
let(:query) { read_graphql_file('shared/components/Form/fields/FieldFile/graphql/mutations/uploadCache/add.graphql') }
let(:form_id) { 12_345 }
let(:file_name) { 'my_testfile.pdf' }
let(:file_type) { 'application/pdf' }
let(:agent) { create(:agent) }
let(:query) { read_graphql_file('shared/components/Form/fields/FieldFile/graphql/mutations/uploadCache/add.graphql') }
let(:form_id) { 12_345 }
let(:file_name) { 'my_testfile.pdf' }
let(:file_type) { 'application/pdf' }
let(:file_content) { 'some test content' }
let(:variables) do
{

View File

@@ -5,14 +5,14 @@ require 'rails_helper'
RSpec.describe Gql::Mutations::Form::UploadCache::Remove, type: :graphql do
context 'when uploading files for a form', authenticated_as: :agent do
let(:agent) { create(:agent) }
let(:query) { read_graphql_file('shared/components/Form/fields/FieldFile/graphql/mutations/uploadCache/remove.graphql') }
let(:form_id) { 12_345 }
let(:agent) { create(:agent) }
let(:query) { read_graphql_file('shared/components/Form/fields/FieldFile/graphql/mutations/uploadCache/remove.graphql') }
let(:form_id) { 12_345 }
let(:upload_cache_file) { UploadCache.new(form_id).add(filename: file_name, data: file_content, created_by_id: 1) }
let(:file_name) { 'my_testfile.pdf' }
let(:file_type) { 'application/pdf' }
let(:file_content) { 'some test content' }
let(:variables) { { formId: form_id, fileIds: [ Gql::ZammadSchema.id_from_object(upload_cache_file) ] } }
let(:file_name) { 'my_testfile.pdf' }
let(:file_type) { 'application/pdf' }
let(:file_content) { 'some test content' }
let(:variables) { { formId: form_id, fileIds: [ Gql::ZammadSchema.id_from_object(upload_cache_file) ] } }
before do
graphql_execute(query, variables: variables)

View File

@@ -13,7 +13,7 @@ RSpec.describe Gql::Mutations::Login, type: :request do
context 'when logging on' do
let(:agent_password) { 'some_test_password' }
let(:agent) { create(:agent, password: agent_password) }
let(:agent) { create(:agent, password: agent_password) }
let(:query) do
File.read(Rails.root.join('app/frontend/shared/graphql/mutations/login.graphql')) +
File.read(Rails.root.join('app/frontend/shared/graphql/fragments/errors.graphql'))

View File

@@ -5,12 +5,12 @@ require 'rails_helper'
RSpec.describe Gql::Queries::AutocompleteSearch::User, type: :graphql, authenticated_as: :agent do
context 'when searching for users' do
let(:agent) { create(:agent) }
let(:users) { create_list(:agent, 3, lastname: 'AutocompleteSearch') }
let(:query) { read_graphql_file('shared/graphql/queries/autocompleteSearch/user.graphql') }
let(:variables) { { query: query_string, limit: limit } }
let(:agent) { create(:agent) }
let(:users) { create_list(:agent, 3, lastname: 'AutocompleteSearch') }
let(:query) { read_graphql_file('shared/graphql/queries/autocompleteSearch/user.graphql') }
let(:variables) { { query: query_string, limit: limit } }
let(:query_string) { users.last.lastname }
let(:limit) { nil }
let(:limit) { nil }
before do
graphql_execute(query, variables: variables)

View File

@@ -6,7 +6,7 @@ RSpec.describe Gql::Queries::CurrentUser, type: :graphql do
context 'when fetching user information' do
let(:organization) { create(:organization) }
let(:agent) { create(:agent, department: 'TestDepartment', organization: organization) }
let(:agent) { create(:agent, department: 'TestDepartment', organization: organization) }
let(:query) do
read_graphql_file('shared/graphql/queries/currentUser.graphql') +
read_graphql_file('shared/graphql/fragments/objectAttributeValues.graphql')

View File

@@ -5,7 +5,7 @@ require 'rails_helper'
RSpec.describe Gql::Queries::FormSchema, type: :graphql do
context 'when fetching form schema data' do
let(:query) { read_graphql_file('shared/components/Form/graphql/queries/formSchema.graphql') }
let(:query) { read_graphql_file('shared/components/Form/graphql/queries/formSchema.graphql') }
let(:variables) { { formSchemaId: 'FormSchema__Form__Mobile__Login' } }
let(:expected) do
[

View File

@@ -5,8 +5,8 @@ require 'rails_helper'
RSpec.describe Gql::Queries::Overviews, type: :graphql do
context 'when fetching locales' do
let(:agent) { create(:agent) }
let(:query) { read_graphql_file('shared/entities/ticket/graphql/queries/overviews.graphql') }
let(:agent) { create(:agent) }
let(:query) { read_graphql_file('shared/entities/ticket/graphql/queries/overviews.graphql') }
let(:variables) { { withTicketCount: false } }
before do

View File

@@ -5,8 +5,8 @@ require 'rails_helper'
RSpec.describe Gql::Queries::Translations, type: :graphql do
context 'when fetching translations' do
let(:query) { read_graphql_file('shared/graphql/queries/translations.graphql') }
let(:variables) { { locale: locale, cacheKey: cache_key } }
let(:query) { read_graphql_file('shared/graphql/queries/translations.graphql') }
let(:variables) { { locale: locale, cacheKey: cache_key } }
let(:expected_cache_key) { Translation.where(locale: locale).order(updated_at: :desc).take.updated_at.to_s }
before do
@@ -43,7 +43,7 @@ RSpec.describe Gql::Queries::Translations, type: :graphql do
end
context 'with an invalid locale' do
let(:locale) { 'invalid-locale' }
let(:locale) { 'invalid-locale' }
let(:cache_key) { nil }
it 'returns error type' do

View File

@@ -54,7 +54,7 @@ RSpec.describe Gql::RecordLoader, type: :graphql do
context 'when querying multiple tickets' do
let(:loops) { 5 }
let(:tickets_per_loop) { 5 }
let(:tickets_per_loop) { 5 }
let(:articles_per_ticket) { 1 }
let(:overview_id) do
condition = {
@@ -120,9 +120,9 @@ RSpec.describe Gql::RecordLoader, type: :graphql do
context 'when querying one ticket with many articles' do
let(:loops) { 1 }
let(:tickets_per_loop) { 1 }
let(:tickets_per_loop) { 1 }
let(:articles_per_ticket) { 100 }
let(:ticket_id) { Gql::ZammadSchema.id_from_object(Ticket.last) }
let(:ticket_id) { Gql::ZammadSchema.id_from_object(Ticket.last) }
it 'performs only the expected amount of DB queries', authenticated_as: :agent do # rubocop:disable RSpec/ExampleLength, RSpec/MultipleExpectations
query = read_graphql_file('shared/graphql/fragments/objectAttributeValues.graphql') +

View File

@@ -4,7 +4,7 @@ require 'rails_helper'
RSpec.describe Gql::Types::BinaryString do
context 'when receiving a Base64 string' do
let(:input) { Base64.strict_encode64(result) }
let(:input) { Base64.strict_encode64(result) }
let(:result) { 'my unicode string ø' }
context 'without prefix' do
@@ -39,7 +39,7 @@ RSpec.describe Gql::Types::BinaryString do
end
context 'when sending a string' do
let(:input) { 'my unicode string ø' }
let(:input) { 'my unicode string ø' }
let(:result) { Base64.strict_encode64(input) }
it 'transforms input correctly' do

View File

@@ -7,7 +7,7 @@ require 'rails_helper'
# Individual import steps are tested in spec/lib/sequencer.
#
RSpec.describe 'Freshdesk import', type: :integration, use_vcr: true, db_strategy: :reset, required_envs: %w[IMPORT_FRESHDESK_ENDPOINT IMPORT_FRESHDESK_ENDPOINT_KEY IMPORT_FRESHDESK_ENDPOINT_SUBDOMAIN] do # rubocop:disable RSpec/DescribeClass
RSpec.describe 'Freshdesk import', integration: true, use_vcr: true, db_strategy: :reset, required_envs: %w[IMPORT_FRESHDESK_ENDPOINT IMPORT_FRESHDESK_ENDPOINT_KEY IMPORT_FRESHDESK_ENDPOINT_SUBDOMAIN] do # rubocop:disable RSpec/DescribeClass
before do
Setting.set('import_freshdesk_endpoint', ENV['IMPORT_FRESHDESK_ENDPOINT'])

View File

@@ -2,7 +2,7 @@
require 'rails_helper'
# rubocop:disable RSpec/FilePath
RSpec.describe GitHub, type: :integration, required_envs: %w[GITHUB_ENDPOINT GITHUB_APITOKEN] do
RSpec.describe GitHub, integration: true, required_envs: %w[GITHUB_ENDPOINT GITHUB_APITOKEN] do
# rubocop:enable RSpec/FilePath
let(:instance) { described_class.new(ENV['GITHUB_ENDPOINT'], ENV['GITHUB_APITOKEN']) }

View File

@@ -2,7 +2,7 @@
require 'rails_helper'
# rubocop:disable RSpec/FilePath
RSpec.describe GitLab, type: :integration, required_envs: %w[GITLAB_ENDPOINT GITLAB_APITOKEN] do
RSpec.describe GitLab, integration: true, required_envs: %w[GITLAB_ENDPOINT GITLAB_APITOKEN] do
# rubocop:enable RSpec/FilePath
let(:instance) { described_class.new(ENV['GITLAB_ENDPOINT'], ENV['GITLAB_APITOKEN']) }
@@ -82,9 +82,9 @@ RSpec.describe GitLab, type: :integration, required_envs: %w[GITLAB_ENDPOINT GIT
describe '#variables' do
describe 'Zammad ignores relative GitLab URLs #3830' do
let(:endpoint) { ENV['GITLAB_ENDPOINT'].sub('api/graphql', 'subfolder/api/graphql') }
let(:instance) { described_class.new(endpoint, ENV['GITLAB_APITOKEN']) }
let(:issue_url) { "https://#{URI.parse(ENV['GITLAB_ISSUE_LINK']).host}/subfolder/group/project/-/issues/1" }
let(:endpoint) { ENV['GITLAB_ENDPOINT'].sub('api/graphql', 'subfolder/api/graphql') }
let(:instance) { described_class.new(endpoint, ENV['GITLAB_APITOKEN']) }
let(:issue_url) { "https://#{URI.parse(ENV['GITLAB_ISSUE_LINK']).host}/subfolder/group/project/-/issues/1" }
let(:linked_issue) { GitLab::LinkedIssue.new(instance.client) }
it 'does remove the subfolder from the fullpath to get the issue correctly' do

View File

@@ -1,7 +1,7 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
require 'rails_helper'
RSpec.describe 'Gmail XOAUTH2', type: :integration, required_envs: %w[GMAIL_REFRESH_TOKEN GMAIL_CLIENT_ID GMAIL_CLIENT_SECRET GMAIL_USER] do # rubocop:disable RSpec/DescribeClass
RSpec.describe 'Gmail XOAUTH2', integration: true, required_envs: %w[GMAIL_REFRESH_TOKEN GMAIL_CLIENT_ID GMAIL_CLIENT_SECRET GMAIL_USER] do # rubocop:disable RSpec/DescribeClass
let(:channel) do
create(:google_channel).tap(&:refresh_xoauth2!)
end

View File

@@ -2,7 +2,7 @@
require 'rails_helper'
RSpec.describe 'Kayako import', type: :integration, use_vcr: true, db_strategy: :reset, required_envs: %w[IMPORT_KAYAKO_ENDPOINT IMPORT_KAYAKO_ENDPOINT_PASSWORD IMPORT_KAYAKO_ENDPOINT_USERNAME] do # rubocop:disable RSpec/DescribeClass
RSpec.describe 'Kayako import', integration: true, use_vcr: true, db_strategy: :reset, required_envs: %w[IMPORT_KAYAKO_ENDPOINT IMPORT_KAYAKO_ENDPOINT_PASSWORD IMPORT_KAYAKO_ENDPOINT_USERNAME] do # rubocop:disable RSpec/DescribeClass
let(:job) { ImportJob.last }
before do

View File

@@ -2,9 +2,8 @@
require 'rails_helper'
RSpec.describe 'Ldap import', use_vcr: false, type: :integration, required_envs: %w[IMPORT_LDAP_ENDPOINT IMPORT_LDAP_USER IMPORT_LDAP_PASSWORD] do # rubocop:disable RSpec/DescribeClass
RSpec.describe 'Ldap import', use_vcr: false, integration: true, required_envs: %w[IMPORT_LDAP_ENDPOINT IMPORT_LDAP_USER IMPORT_LDAP_PASSWORD] do # rubocop:disable RSpec/DescribeClass
let(:ldap_source) { create(:ldap_source, :with_config) }
let(:import_job) { create(:import_job, name: 'Import::Ldap') }
let(:expected_result) do
{ 'skipped' => 0,
@@ -50,12 +49,12 @@ RSpec.describe 'Ldap import', use_vcr: false, type: :integration, required_envs:
Setting.set('ldap_integration', true)
TCR.turned_off do
ldap_source
import_job.start
ImportJob.start_registered
end
end
it 'does import users and roles' do
expect(import_job.result).to eq(expected_result)
expect(ImportJob.last.result).to eq(expected_result)
user_ab = User.find_by(login: 'ab')
expect(user_ab.firstname).to eq('Albert')

View File

@@ -1,7 +1,7 @@
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
require 'rails_helper'
RSpec.describe 'Microsoft365 XOAUTH2', type: :integration, required_envs: %w[MICROSOFT365_REFRESH_TOKEN MICROSOFT365_CLIENT_ID MICROSOFT365_CLIENT_SECRET MICROSOFT365_USER] do # rubocop:disable RSpec/DescribeClass
RSpec.describe 'Microsoft365 XOAUTH2', integration: true, required_envs: %w[MICROSOFT365_REFRESH_TOKEN MICROSOFT365_CLIENT_ID MICROSOFT365_CLIENT_SECRET MICROSOFT365_USER] do # rubocop:disable RSpec/DescribeClass
let(:channel) do
create(:microsoft365_channel).tap(&:refresh_xoauth2!)
end

View File

@@ -2,7 +2,7 @@
require 'rails_helper'
RSpec.describe 'Zendesk import', type: :integration, use_vcr: true, db_strategy: :reset, required_envs: %w[IMPORT_ZENDESK_ENDPOINT IMPORT_ZENDESK_ENDPOINT_KEY IMPORT_ZENDESK_ENDPOINT_USERNAME] do # rubocop:disable RSpec/DescribeClass
RSpec.describe 'Zendesk import', integration: true, use_vcr: true, db_strategy: :reset, required_envs: %w[IMPORT_ZENDESK_ENDPOINT IMPORT_ZENDESK_ENDPOINT_KEY IMPORT_ZENDESK_ENDPOINT_USERNAME] do # rubocop:disable RSpec/DescribeClass
let(:job) { ImportJob.last }
before do

View File

@@ -6,8 +6,8 @@ RSpec.describe ChecksKbClientNotificationJob, type: :job, performs_jobs: true do
include_context 'basic Knowledge Base'
describe 'pushes to users who have access' do
let(:admin) { create(:admin) }
let(:agent) { create(:agent) }
let(:admin) { create(:admin) }
let(:agent) { create(:agent) }
let(:customer) { create(:customer) }
before do

View File

@@ -70,7 +70,7 @@ RSpec.describe CommunicateTwitterJob, type: :job, required_envs: %w[TWITTER_CONS
end
context 'for DMs' do
let(:article) { create(:twitter_dm_article, :pending_delivery, recipient: recipient, body: 'Please ignore this message.') }
let(:article) { create(:twitter_dm_article, :pending_delivery, recipient: recipient, body: 'Please ignore this message.') }
let(:recipient) { create(:twitter_authorization, uid: ENV.fetch('TWITTER_DM_RECIPIENT', '1234567890')) }
let(:dm_attributes) do
@@ -139,7 +139,7 @@ RSpec.describe CommunicateTwitterJob, type: :job, required_envs: %w[TWITTER_CONS
context 'if article.ticket.preferences["channel_id"] has been removed' do
before { channel.destroy }
let(:channel) { Channel.find(article.ticket.preferences[:channel_id]) }
let(:channel) { Channel.find(article.ticket.preferences[:channel_id]) }
let(:error_message) { "No such channel id #{article.ticket.preferences['channel_id']}" }
include_examples 'for failure cases'

View File

@@ -165,7 +165,7 @@ RSpec.describe HasActiveJobLock, type: :job do
include_examples 'handle locking of jobs'
context 'custom lock key' do
context 'when has custom lock key' do
let(:job_class) do
Class.new(super()) do
@@ -178,4 +178,48 @@ RSpec.describe HasActiveJobLock, type: :job do
include_examples 'handle locking of jobs'
end
context 'when has invalid custom lock key' do
let(:job_class) do
Class.new(super()) do
def lock_key
raise 'Cannot generate lock key anymore'
end
end
end
it 'does not allow enqueueing of perform_later jobs' do
expect { job_class.perform_later }.not_to have_enqueued_job(job_class)
end
it 'does not allow execution of perform_now jobs' do
expect { job_class.perform_now }.not_to change(job_class, :perform_counter)
end
end
# https://github.com/zammad/zammad/issues/4141
context 'when key becomes invalid after enqueueing' do
let(:job_class) do
Class.new(super()) do
cattr_accessor :allow_lock_key, default: true
def lock_key
raise 'Cannot generate lock key anymore' if !allow_lock_key
'lock key'
end
end
end
it 'safely handles error in generating lock key', performs_jobs: true do
job_class.perform_later
job_class.allow_lock_key = false
expect { perform_enqueued_jobs(only: job_class) }
.not_to raise_error
end
end
end

View File

@@ -11,8 +11,8 @@ RSpec.describe DataPrivacyTaskJob, type: :job do
end
let!(:organization) { create(:organization, name: 'test') }
let!(:admin) { create(:admin) }
let!(:user) { create(:customer, organization: organization) }
let!(:admin) { create(:admin) }
let!(:user) { create(:customer, organization: organization) }
it 'checks if the user is deleted' do
create(:data_privacy_task, deletable: user)

View File

@@ -6,7 +6,7 @@ require_dependency 'issue_2715_fix_broken_twitter_urls_job' # Rails autoloading
RSpec.describe Issue2715FixBrokenTwitterUrlsJob, type: :job do
context 'with existing Twitter articles' do
let!(:tweet) { create(:twitter_article, preferences: tweet_preferences) }
let!(:dm) { create(:twitter_dm_article, preferences: dm_preferences) }
let!(:dm) { create(:twitter_dm_article, preferences: dm_preferences) }
let(:tweet_preferences) do
# NOTE: Faker 2.0+ has deprecated the `#number(20)` syntax in favor of `#number(digits: 20)`.

View File

@@ -5,7 +5,7 @@ require 'rails_helper'
RSpec.describe TicketArticleCommunicateEmailJob, type: :job do
describe '#perform' do
context 'for an email article' do
let(:article) { create(:ticket_article, type_name: 'email') }
let(:article) { create(:ticket_article, type_name: 'email') }
let(:recipient_list) { [article.to, article.cc].compact_blank.join(',') }
before { allow(Rails.logger).to receive(:info) }

View File

@@ -3,9 +3,9 @@
require 'rails_helper'
RSpec.describe TicketOnlineNotificationSeenJob, type: :job do
let!(:user) { create(:user) }
let!(:user) { create(:user) }
let!(:other_user) { create(:user) }
let!(:ticket) { create(:ticket, owner: user, created_by_id: user.id) }
let!(:ticket) { create(:ticket, owner: user, created_by_id: user.id) }
let!(:online_notification) do
create(:online_notification, o_id: ticket.id, user_id: user.id)
end

View File

@@ -15,7 +15,7 @@ RSpec.shared_examples 'TriggerWebhookJob::RecordPayload backend' do |factory|
subject(:generate) { described_class.new(record).generate }
let(:resolved_associations) { described_class.const_get(:ASSOCIATIONS).map(&:to_s) }
let(:record) { build(factory) }
let(:record) { build(factory) }
it 'includes attributes with association names' do
expect(generate).to include(record.attributes_with_association_names.except(*resolved_associations))

View File

@@ -10,7 +10,7 @@ RSpec.describe TriggerWebhookJob::RecordPayload::Ticket::Article do
subject(:generate) { described_class.new(record).generate }
let(:resolved_associations) { described_class.const_get(:ASSOCIATIONS).map(&:to_s) }
let(:record) { create(:'ticket/article') }
let(:record) { create(:'ticket/article') }
it "adds 'accounted_time' key" do
expect(generate['accounted_time']).to be_zero

View File

@@ -10,7 +10,7 @@ RSpec.describe TriggerWebhookJob::RecordPayload do
context 'when generator backend exists' do
let(:record) { build(:ticket) }
let(:record) { build(:ticket) }
let(:backend) { TriggerWebhookJob::RecordPayload::Ticket }
it 'initializes backend instance and sends generate' do

View File

@@ -5,8 +5,8 @@ require 'rails_helper'
RSpec.describe TriggerWebhookJob, type: :job do
let(:endpoint) { 'http://api.example.com/webhook' }
let(:token) { 's3cr3t-t0k3n' }
let(:webhook) { create(:webhook, endpoint: endpoint, signature_token: token) }
let(:token) { 's3cr3t-t0k3n' }
let(:webhook) { create(:webhook, endpoint: endpoint, signature_token: token) }
let(:trigger) do
create(:trigger,
perform: {

View File

@@ -5,8 +5,8 @@ require 'lib/auth/backend/backend_examples'
RSpec.describe Auth::Backend::Base do
let(:user) { create(:user) }
let(:auth) { Auth.new(user.login, 'not_used') }
let(:user) { create(:user) }
let(:auth) { Auth.new(user.login, 'not_used') }
let(:instance) { described_class.new({ adapter: described_class.name }, auth) }
describe '#valid?' do

View File

@@ -5,9 +5,9 @@ require 'lib/auth/backend/backend_examples'
RSpec.describe Auth::Backend::Developer do
let(:user) { create(:user) }
let(:user) { create(:user) }
let(:password) { 'not_used' }
let(:auth) { Auth.new(user.login, password) }
let(:auth) { Auth.new(user.login, password) }
let(:instance) { described_class.new({ adapter: described_class.name }, auth) }
describe '#valid?' do
@@ -30,7 +30,7 @@ RSpec.describe Auth::Backend::Developer do
context 'when password matches actual User password' do
let(:user) { create(:user, password: 'secure') }
let(:user) { create(:user, password: 'secure') }
let(:password) { user.password_plain }
it "doesn't authenticate" do
@@ -56,7 +56,7 @@ RSpec.describe Auth::Backend::Developer do
context 'when password matches actual User password' do
let(:user) { create(:user, password: 'secure') }
let(:user) { create(:user, password: 'secure') }
let(:password) { user.password_plain }
it "doesn't authenticate" do
@@ -82,7 +82,7 @@ RSpec.describe Auth::Backend::Developer do
context 'when password matches actual User password' do
let(:user) { create(:user, password: 'secure') }
let(:user) { create(:user, password: 'secure') }
let(:password) { user.password_plain }
it "doesn't authenticate" do

View File

@@ -5,9 +5,9 @@ require 'lib/auth/backend/backend_examples'
RSpec.describe Auth::Backend::Internal do
let(:user) { create(:user) }
let(:user) { create(:user) }
let(:password) { 'secure' }
let(:auth) { Auth.new(user.login, password) }
let(:auth) { Auth.new(user.login, password) }
let(:instance) { described_class.new({ adapter: described_class.name }, auth) }
describe '#valid?' do
@@ -94,7 +94,7 @@ RSpec.describe Auth::Backend::Internal do
context 'when authentication fails' do
let(:password) { 'wrong' }
let(:user) { create(:user, password: 'secure') }
let(:user) { create(:user, password: 'secure') }
it 'sets Auth#increase_login_failed_attempts flag to true' do
expect { instance.valid? }.to change(auth, :increase_login_failed_attempts).from(false).to(true)

View File

@@ -6,9 +6,9 @@ require 'lib/auth/backend/backend_examples'
RSpec.describe ::Auth::Backend::Ldap do
let(:ldap_source) { create(:ldap_source) }
let(:user) { create(:user, source: "Ldap::#{ldap_source.id}") }
let(:password) { 'secure' }
let(:auth) { Auth.new(user.login, password) }
let(:user) { create(:user, source: "Ldap::#{ldap_source.id}") }
let(:password) { 'secure' }
let(:auth) { Auth.new(user.login, password) }
let(:config) do
{
adapter: described_class.name

View File

@@ -4,9 +4,9 @@ require 'rails_helper'
RSpec.describe Auth::Backend do
let(:user) { create(:user) }
let(:user) { create(:user) }
let(:password) { 'secure' }
let(:auth) { Auth.new(user.login, password) }
let(:auth) { Auth.new(user.login, password) }
let(:instance) { described_class.new(auth) }
describe '#valid?' do

Some files were not shown because too many files have changed in this diff Show More