Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e91a7cae53 | ||
|
|
22cd7ccf3e | ||
|
|
e7b06654fd | ||
|
|
ccff1354ba | ||
|
|
0c1d519c5a | ||
|
|
0a0f22ec94 | ||
|
|
2628fee273 | ||
|
|
68c3bcad6c | ||
|
|
6e4a52b9d2 | ||
|
|
6a1a5fc02e | ||
|
|
215d1a42bc | ||
|
|
caec9d4328 | ||
|
|
045c5145ad | ||
|
|
743b98213e | ||
|
|
960910fef7 | ||
|
|
fb1ac41210 | ||
|
|
b62c81e55a | ||
|
|
e6eb44170b | ||
|
|
efab6b06f4 | ||
|
|
205433de6c | ||
|
|
ac194df03c | ||
|
|
80bf57c1b2 | ||
|
|
ea2eb62872 | ||
|
|
bf8b71d851 | ||
|
|
446f51f5e3 | ||
|
|
2f1bf5c5cf | ||
|
|
f76a83364f | ||
|
|
56c5f3a0c7 | ||
|
|
29bf395d54 |
@@ -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']
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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]
|
||||
@@ -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'
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
browser:build:
|
||||
stage: test
|
||||
extends:
|
||||
- .services_postgresql
|
||||
services:
|
||||
- !reference [.services, postgresql]
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
paths:
|
||||
|
||||
@@ -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
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
108
CHANGELOG.md
108
CHANGELOG.md
@@ -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)]
|
||||
|
||||
4
Gemfile
4
Gemfile
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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'
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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) =>
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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|
|
||||
|
||||
41
app/policies/controllers/attachments_controller_policy.rb
Normal file
41
app/policies/controllers/attachments_controller_policy.rb
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -24,6 +24,10 @@ class KnowledgeBase::AnswerPolicy < ApplicationPolicy
|
||||
access_editor?
|
||||
end
|
||||
|
||||
def user_required?
|
||||
false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def access
|
||||
|
||||
18
config/initializers/email_address_validator.rb
Normal file
18
config/initializers/email_address_validator.rb
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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."
|
||||
|
||||
@@ -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"
|
||||
|
||||
1157
i18n/zammad.th.po
1157
i18n/zammad.th.po
File diff suppressed because it is too large
Load Diff
17
lib/auth.rb
17
lib/auth.rb
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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' => [
|
||||
|
||||
@@ -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) }
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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'))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
[
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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') +
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'])
|
||||
|
||||
@@ -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']) }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)`.
|
||||
|
||||
@@ -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) }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user