Merge branch 'develop' of git.znuny.com:zammad/zammad into develop

This commit is contained in:
Martin Edenhofer 2017-12-04 01:25:50 +01:00
commit 0d1d86511f
456 changed files with 3929 additions and 2621 deletions

View file

@ -45,29 +45,29 @@ Style/TrailingCommaInArguments:
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas'
Enabled: false
Style/SpaceInsideParens:
Layout/SpaceInsideParens:
Description: 'No spaces after ( or before ).'
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-spaces-braces'
Enabled: false
Style/SpaceAfterMethodName:
Layout/SpaceAfterMethodName:
Description: >-
Do not put a space between a method name and the opening
parenthesis in a method definition.
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parens-no-spaces'
Enabled: false
Style/LeadingCommentSpace:
Layout/LeadingCommentSpace:
Description: 'Comments should start with a space.'
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#hash-space'
Enabled: false
Style/MethodCallParentheses:
Style/MethodCallWithoutArgsParentheses:
Description: 'Do not use parentheses for method calls with no arguments.'
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-args-no-parens'
Enabled: false
Style/SpaceInsideBrackets:
Layout/SpaceInsideBrackets:
Description: 'No spaces after [ or before ].'
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-spaces-braces'
Enabled: false
@ -83,19 +83,19 @@ Style/MethodDefParentheses:
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#method-parens'
Enabled: false
Style/EmptyLinesAroundClassBody:
Layout/EmptyLinesAroundClassBody:
Description: "Keeps track of empty lines around class bodies."
Enabled: false
Style/EmptyLinesAroundMethodBody:
Layout/EmptyLinesAroundMethodBody:
Description: "Keeps track of empty lines around method bodies."
Enabled: false
Style/EmptyLinesAroundBlockBody:
Layout/EmptyLinesAroundBlockBody:
Description: "Keeps track of empty lines around block bodies."
Enabled: false
Style/EmptyLinesAroundModuleBody:
Layout/EmptyLinesAroundModuleBody:
Description: "Keeps track of empty lines around module bodies."
Enabled: false
@ -143,17 +143,29 @@ Rails/HasAndBelongsToMany:
# StyleGuide: 'https://github.com/bbatsov/rails-style-guide#has-many-through'
Enabled: false
Rails/SkipsModelValidations:
Description: >-
Use methods that skips model validations with caution.
See reference for more information.
Reference: 'http://guides.rubyonrails.org/active_record_validations.html#skipping-validations'
Enabled: true
Exclude:
- test/**/*
Style/ClassAndModuleChildren:
Description: 'Checks style of children classes and modules.'
Enabled: false
Style/FileName:
Naming/FileName:
Description: 'Use snake_case for source file names.'
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#snake-case-files'
Enabled: true
Exclude:
- 'script/websocket-server.rb'
Naming/VariableNumber:
Description: 'Use the configured style when numbering variables.'
Enabled: false
# 2.0
@ -184,8 +196,23 @@ Metrics/ModuleLength:
Description: 'Avoid modules longer than 100 lines of code.'
Enabled: false
Metrics/BlockLength:
Enabled: false
Lint/RescueWithoutErrorClass:
Enabled: false
Rails/ApplicationRecord:
Enabled: false
# TODO
Rails/HasManyOrHasOneDependent:
Enabled: false
Style/DateTime:
Enabled: false
Style/Documentation:
Description: 'Document classes and non-namespace modules.'
Enabled: false
@ -193,7 +220,7 @@ Style/Documentation:
Lint/UselessAssignment:
Enabled: false
Style/ExtraSpacing:
Layout/ExtraSpacing:
Description: 'Do not use unnecessary spacing.'
Enabled: false
@ -216,3 +243,13 @@ Style/NumericPredicate:
Enabled: true
Exclude:
- "**/*_spec.rb"
Lint/AmbiguousBlockAssociation:
Description: >-
Checks for ambiguous block association with method when param passed without
parentheses.
StyleGuide: '#syntax'
Enabled: true
Exclude:
- "**/*_spec.rb"
- "**/*_examples.rb"

128
Gemfile
View file

@ -1,112 +1,131 @@
source 'https://rubygems.org'
# core - base
ruby '2.4.1'
gem 'rails', '5.1.4'
gem 'rails-observers'
# core - rails additions
gem 'activerecord-session_store'
# Bundle edge Rails instead:
#gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'composite_primary_keys'
gem 'json'
gem 'rails-observers'
# Supported DBs
# core - application servers
gem 'puma', group: :puma
gem 'unicorn', group: :unicorn
# core - supported ORMs
gem 'activerecord-nulldb-adapter', group: :nulldb
gem 'mysql2', group: :mysql
gem 'pg', group: :postgres
# core - asynchrous task execution
gem 'daemons'
gem 'delayed_job_active_record'
# core - websocket
gem 'em-websocket'
gem 'eventmachine'
# core - password security
gem 'argon2'
# performance - Memcached
gem 'dalli'
# asset handling
group :assets do
gem 'sass-rails' #, github: 'rails/sass-rails'
# asset handling - coffee-script
gem 'coffee-rails'
gem 'coffee-script-source'
gem 'sprockets'
gem 'uglifier'
# asset handling - frontend templating
gem 'eco'
# asset handling - SASS
gem 'sass-rails'
# asset handling - pipeline
gem 'sprockets'
gem 'uglifier'
end
gem 'autoprefixer-rails'
# asset handling - javascript execution for e.g. linux
gem 'execjs'
gem 'libv8'
gem 'therubyracer'
# authentication - provider
gem 'doorkeeper'
gem 'oauth2'
# authentication - third party
gem 'omniauth'
gem 'omniauth-oauth2'
gem 'omniauth-facebook'
gem 'omniauth-github'
gem 'omniauth-gitlab'
gem 'omniauth-google-oauth2'
gem 'omniauth-linkedin-oauth2'
gem 'omniauth-twitter'
gem 'omniauth-microsoft-office365'
gem 'omniauth-oauth2'
gem 'omniauth-twitter'
gem 'omniauth-weibo-oauth2'
gem 'twitter'
gem 'telegramAPI'
# channels
gem 'koala'
gem 'mail'
gem 'valid_email2'
gem 'telegramAPI'
gem 'twitter'
# channels - email additions
gem 'htmlentities'
gem 'mail', '2.6.6'
gem 'mime-types'
gem 'valid_email2'
# feature - business hours
gem 'biz'
gem 'composite_primary_keys'
gem 'delayed_job_active_record'
gem 'daemons'
gem 'simple-rss'
# e. g. on linux we need a javascript execution
gem 'libv8'
gem 'execjs'
gem 'therubyracer'
require 'erb'
require 'yaml'
gem 'net-ldap'
# password security
gem 'argon2'
# feature - signature diffing
gem 'diffy'
# feature - excel output
gem 'writeexcel'
gem 'icalendar'
gem 'icalendar-recurrence'
# feature - device logging
gem 'browser'
# feature - iCal export
gem 'icalendar'
gem 'icalendar-recurrence'
# integrations
gem 'slack-notifier'
gem 'clearbit'
gem 'net-ldap'
gem 'slack-notifier'
gem 'zendesk_api'
gem 'viewpoint'
gem 'rubyntlm', git: 'https://github.com/wimm/rubyntlm.git'
# integrations - exchange
gem 'autodiscover', git: 'https://github.com/thorsteneckel/autodiscover.git'
# event machine
gem 'eventmachine'
gem 'em-websocket'
gem 'diffy'
gem 'dalli'
gem 'rubyntlm', git: 'https://github.com/wimm/rubyntlm.git'
gem 'viewpoint'
# Gems used only for develop/test and not required
# in production environments by default.
group :development, :test do
# test frameworks
gem 'rspec-rails'
gem 'test-unit'
gem 'spring'
gem 'spring-commands-rspec'
# test DB
gem 'sqlite3'
# code coverage
gem 'coveralls', require: false
gem 'simplecov'
gem 'simplecov-rcov'
gem 'coveralls', require: false
# UI tests w/ Selenium
gem 'selenium-webdriver', '2.53.4'
@ -121,9 +140,9 @@ group :development, :test do
gem 'guard-symlink', require: false
# code QA
gem 'coffeelint'
gem 'pre-commit'
gem 'rubocop'
gem 'coffeelint'
# changelog generation
gem 'github_changelog_generator'
@ -138,10 +157,7 @@ group :development, :test do
gem 'webmock'
end
gem 'puma', group: :puma
gem 'unicorn', group: :unicorn
# load onw gem's
# load onw gems for development and testing purposes
local_gemfile = File.join(File.dirname(__FILE__), 'Gemfile.local')
if File.exist?(local_gemfile)
eval_gemfile local_gemfile

View file

@ -217,13 +217,12 @@ GEM
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
lumberjack (1.0.12)
mail (2.7.0)
mini_mime (>= 0.1.1)
mail (2.6.6)
mime-types (>= 1.16, < 4)
memoizable (0.4.2)
thread_safe (~> 0.3, >= 0.3.1)
method_source (0.9.0)
mime-types (2.99.3)
mini_mime (1.0.0)
mini_portile2 (2.3.0)
minitest (5.10.3)
multi_json (1.12.2)
@ -389,7 +388,6 @@ GEM
rubyzip (~> 1.0)
websocket (~> 1.0)
shellany (0.0.1)
simple-rss (1.3.1)
simple_oauth (0.3.1)
simplecov (0.15.1)
docile (~> 1.1.0)
@ -399,10 +397,6 @@ GEM
simplecov-rcov (0.2.3)
simplecov (>= 0.4.1)
slack-notifier (2.3.1)
spring (2.0.2)
activesupport (>= 4.2)
spring-commands-rspec (1.0.4)
spring (>= 0.9.1)
sprockets (3.7.1)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
@ -508,7 +502,7 @@ DEPENDENCIES
json
koala
libv8
mail
mail (= 2.6.6)
mime-types
mysql2
net-ldap
@ -535,12 +529,9 @@ DEPENDENCIES
rubyntlm!
sass-rails
selenium-webdriver (= 2.53.4)
simple-rss
simplecov
simplecov-rcov
slack-notifier
spring
spring-commands-rspec
sprockets
sqlite3
telegramAPI

0
Rakefile Normal file → Executable file
View file

View file

@ -148,6 +148,8 @@ class App.ControllerGenericIndex extends App.Controller
return item
)
if !@table
# show description button, only if content exists
showDescription = false
if App[ @genericObject ].description && !_.isEmpty(objects)
@ -184,7 +186,10 @@ class App.ControllerGenericIndex extends App.Controller
},
@pageData.tableExtend
)
new App.ControllerTable(params)
if !@table
@table = new App.ControllerTable(params)
else
@table.update(objects: objects)
edit: (id, e) =>
e.preventDefault()
@ -1170,7 +1175,6 @@ class App.ObserverController extends App.Controller
if @globalRerender
@bind('ui:rerender', =>
@lastAttributres = undefined
console.log('aaaa', @model, @template)
@maybeRender(App[@model].fullLocal(@object_id))
)

View file

@ -1,7 +1,7 @@
class SidebarCustomer extends App.Controller
sidebarItem: =>
return if !@permissionCheck('ticket.agent')
return if !@params.customer_id
return if _.isEmpty(@params.customer_id)
{
head: 'Customer'
name: 'customer'
@ -18,6 +18,7 @@ class SidebarCustomer extends App.Controller
showCustomer: (el) =>
@el = el
return if _.isEmpty(@params.customer_id)
new App.WidgetUser(
el: @el
user_id: @params.customer_id

View file

@ -44,6 +44,8 @@ class App.IdoitObjectSelector extends App.ControllerModal
''
search: (filter) =>
if _.isEmpty(filter.type)
delete filter.type
if _.isEmpty(filter.title)
delete filter.title
else

View file

@ -23,17 +23,22 @@ class Index extends App.ControllerSubContent
]
container: @el.closest('.content')
large: true
dndCallback: =>
dndCallback: (e, item) =>
items = @el.find('table > tbody > tr')
order = []
prios = []
prio = 0
for item in items
prio += 1
id = $(item).data('id')
overview = App.Overview.find(id)
if overview.prio isnt prio
overview.prio = prio
overview.save()
prios.push [id, prio]
@ajax(
id: 'overview_prio'
type: 'POST'
url: "#{@apiPath}/overviews_prio"
processData: true
data: JSON.stringify(prios: prios)
)
)
App.Config.set('Overview', { prio: 2300, name: 'Overviews', parent: '#manage', target: '#manage/overviews', controller: Index, permission: ['admin.overview'] }, 'NavBarAdmin')

View file

@ -18,8 +18,19 @@ class App.TicketCustomer extends App.ControllerModal
onSubmit: (e) =>
params = @formParam(e.target)
@customer_id = params['customer_id']
ticket = App.Ticket.find(@ticket_id)
ticket.customer_id = params['customer_id']
errors = ticket.validate()
if !_.isEmpty(errors)
@log 'error', errors
@formValidate(
form: e.target
errors: errors
)
return
@customer_id = params['customer_id']
callback = =>
# close modal

View file

@ -71,7 +71,7 @@ class App.ObjectOrganizationAutocompletion extends App.Controller
@open()
focusInput: =>
@objectSelect.focus() if not @formControl.hasClass 'focus'
@objectSelect.focus() if not @formControl.hasClass('focus')
onBlur: =>
selectObject = @objectSelect.val()
@ -85,6 +85,9 @@ class App.ObjectOrganizationAutocompletion extends App.Controller
@objectId.val("guess:#{selectObject}")
@formControl.removeClass 'focus'
resetObjectSelection: =>
@objectId.val('').trigger('change')
onObjectClick: (e) =>
objectId = $(e.currentTarget).data('object-id')
@selectObject(objectId)
@ -103,14 +106,14 @@ class App.ObjectOrganizationAutocompletion extends App.Controller
# Only work with the last one since its the newest one
objectId = @objectId.val().split(',').pop()
return if !objectId
return if !App[@objectSingle].exists(objectId)
if objectId && App[@objectSingle].exists(objectId)
object = App[@objectSingle].find(objectId)
name = object.displayName()
if @attribute.multiple
# create token
@createToken name, objectId
@createToken(name, objectId)
else
if object.email
@ -321,12 +324,16 @@ class App.ObjectOrganizationAutocompletion extends App.Controller
@hideOrganizationMembers()
# hide dropdown
if !query
if _.isEmpty(query)
@emptyResultList()
if !@attribute.disableCreateObject
@recipientList.append(@buildObjectNew())
# reset object selection
@resetObjectSelection()
return
# show dropdown
if query && ( !@attribute.minLengt || @attribute.minLengt <= query.length )
@lazySearch(query)

View file

@ -387,15 +387,17 @@ set new attributes of model (remove already available attributes)
=>
return if _.isEmpty(@SUBSCRIPTION_COLLECTION)
App.Log.debug('Model', "server notify collection change #{@className}")
callback = =>
@fetchFull(
->
clear: true
)
App.Delay.set(callback, 200, "full-#{@className}")
"Collection::Subscribe::#{@className}"
)
key = @className + '-' + Math.floor( Math.random() * 99999 )
key = "#{@className}-#{Math.floor(Math.random() * 99999)}"
@SUBSCRIPTION_COLLECTION[key] = callback
# fetch init collection

View file

@ -1,5 +1,5 @@
class App.Overview extends App.Model
@configure 'Overview', 'name', 'prio', 'condition', 'order', 'group_by', 'view', 'user_ids', 'organization_shared', 'role_ids', 'order', 'group_by', 'active', 'updated_at'
@configure 'Overview', 'name', 'prio', 'condition', 'order', 'group_by', 'view', 'user_ids', 'organization_shared', 'role_ids', 'active'
@extend Spine.Model.Ajax
@url: @apiPath + '/overviews'
@configure_attributes = [

View file

@ -200,6 +200,26 @@ class App.Ticket extends App.Model
result = true if objectValue.toString().match(contains_regex)
else if condition.operator == 'contains not'
result = true if !objectValue.toString().match(contains_regex)
else if condition.operator == 'contains all'
result = true
for loopConditionValue in conditionValue
if !_.contains(objectValue, loopConditionValue)
result = false
else if condition.operator == 'contains one'
result = false
for loopConditionValue in conditionValue
if _.contains(objectValue, loopConditionValue)
result = true
else if condition.operator == 'contains all not'
result = true
for loopObjectValue in objectValue
if _.contains(conditionValue, loopObjectValue)
result = false
else if condition.operator == 'contains one not'
result = false
for loopObjectValue in objectValue
if !_.contains(conditionValue, loopObjectValue)
result = true
else if condition.operator == 'is'
result = true if objectValue.toString().trim().toLowerCase() is loopConditionValue.toString().trim().toLowerCase()
else if condition.operator == 'is not'

View file

@ -18,7 +18,7 @@ module ApplicationController::Authenticates
raise Exceptions::NotAuthorized, 'Not authorized (token)!'
end
return false if current_user && current_user.permissions?(key)
return false if current_user&.permissions?(key)
raise Exceptions::NotAuthorized, 'Not authorized (user)!'
end

View file

@ -26,8 +26,7 @@ module ApplicationController::HandlesDevices
if user_device_updated_at
# check if entry exists / only if write action
diff = Time.zone.now - 10.minutes
method = request.method
if method == 'GET' || method == 'OPTIONS' || method == 'HEAD'
if %w[GET OPTIONS HEAD].include?(request.method)
diff = Time.zone.now - 30.minutes
end

View file

@ -72,7 +72,7 @@ module ApplicationController::HandlesErrors
data[:error_human] = data[:error]
end
if Rails.env.production? && !data[:error_human].empty?
if Rails.env.production? && data[:error_human].present?
data[:error] = data.delete(:error_human)
end
data

View file

@ -146,7 +146,7 @@ module ApplicationController::RendersModels
def model_references_check(object, params)
generic_object = object.find(params[:id])
result = Models.references(object, generic_object.id)
return false if result.empty?
return false if result.blank?
raise Exceptions::UnprocessableEntity, 'Can\'t delete, object has references.'
rescue => e
raise Exceptions::UnprocessableEntity, e

View file

@ -226,7 +226,7 @@ class ChannelsEmailController < ApplicationController
Channel.where(area: 'Email::Notification').each do |channel|
active = false
if adapter =~ /^#{channel.options[:outbound][:adapter]}$/i
if adapter.match?(/^#{channel.options[:outbound][:adapter]}$/i)
active = true
channel.options = {
outbound: {

View file

@ -44,7 +44,7 @@ class FormController < ApplicationController
errors['email'] = 'required'
elsif params[:email] !~ /@/
errors['email'] = 'invalid'
elsif params[:email] =~ /(>|<|\||\!|"|§|'|\$|%|&|\(|\)|\?|\s|\.\.)/
elsif params[:email].match?(/(>|<|\||\!|"|§|'|\$|%|&|\(|\)|\?|\s|\.\.)/)
errors['email'] = 'invalid'
end
if params[:title].blank?
@ -126,9 +126,7 @@ class FormController < ApplicationController
internal: false,
)
if params[:file]
params[:file].each do |file|
params[:file]&.each do |file|
Store.add(
object: 'Ticket::Article',
o_id: article.id,
@ -139,7 +137,6 @@ class FormController < ApplicationController
}
)
end
end
UserInfo.current_user_id = 1

View file

@ -66,7 +66,7 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password}
# verify auto wizard file
auto_wizard_data = AutoWizard.data
if !auto_wizard_data || auto_wizard_data.empty?
if auto_wizard_data.blank?
render json: {
auto_wizard: true,
auto_wizard_success: false,
@ -132,7 +132,7 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password}
end
# validate organization
if !params[:organization] || params[:organization].empty?
if params[:organization].blank?
messages[:organization] = 'Invalid!'
else
settings[:organization] = params[:organization]
@ -146,7 +146,7 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password}
end
end
if !messages.empty?
if messages.present?
render json: {
result: 'invalid',
messages: messages,

View file

@ -26,7 +26,7 @@ class ImportOtrsController < ApplicationController
if !response.success? && response.code.to_s !~ /^40.$/
message_human = ''
translation_map.each do |key, message|
if response.error.to_s =~ /#{Regexp.escape(key)}/i
if response.error.to_s.match?(/#{Regexp.escape(key)}/i)
message_human = message
end
end
@ -39,7 +39,7 @@ class ImportOtrsController < ApplicationController
end
result = {}
if response.body =~ /zammad migrator/
if response.body.match?(/zammad migrator/)
migrator_response = JSON.parse(response.body)
@ -86,7 +86,7 @@ class ImportOtrsController < ApplicationController
message_human: migrator_response['Error']
}
end
elsif response.body =~ /(otrs\sag|otrs\.com|otrs\.org)/i
elsif response.body.match?(/(otrs\sag|otrs\.com|otrs\.org)/i)
result = {
result: 'invalid',
message_human: 'Host found, but no OTRS migrator is installed!'
@ -144,7 +144,7 @@ class ImportOtrsController < ApplicationController
end
result = 'ok'
if !issues.empty?
if issues.present?
result = 'failed'
end
render json: {

View file

@ -28,7 +28,7 @@ class ImportZendeskController < ApplicationController
if !response.success?
message_human = ''
translation_map.each do |key, message|
if response.error.to_s =~ /#{Regexp.escape(key)}/i
if response.error.to_s.match?(/#{Regexp.escape(key)}/i)
message_human = message
end
end

View file

@ -133,6 +133,8 @@ UserAgent: #{request.env['HTTP_USER_AGENT']}
if Setting.get('check_mk_token') != params[:token]
raise Exceptions::UnprocessableEntity, 'Invalid token!'
end
true
end
end

View file

@ -1,9 +1,9 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class Integration::IdoitController < ApplicationController
prepend_before_action -> { authentication_check(permission: ['agent.integration.idoit', 'admin.integration.idoit']) }, except: [:verify, :query, :update]
prepend_before_action -> { authentication_check(permission: ['agent.integration.idoit', 'admin.integration.idoit']) }, except: %i[verify query update]
prepend_before_action -> { authentication_check(permission: ['admin.integration.idoit']) }, only: [:verify]
prepend_before_action -> { authentication_check(permission: ['ticket.agent']) }, only: [:query, :update]
prepend_before_action -> { authentication_check(permission: ['ticket.agent']) }, only: %i[query update]
def verify
response = ::Idoit.verify(params[:api_token], params[:endpoint], params[:client_id])

View file

@ -93,6 +93,8 @@ class Integration::SipgateController < ApplicationController
xml_error('Feature not configured, please contact your admin!')
return
end
true
end
def config_integration

View file

@ -18,7 +18,7 @@ class LongPollingController < ApplicationController
params['data'] = {}
end
session_data = {}
if current_user && current_user.id
if current_user&.id
session_data = { 'id' => current_user.id }
end
@ -61,13 +61,12 @@ class LongPollingController < ApplicationController
# check queue to send
begin
# update last ping
4.times do
sleep 0.25
end
#sleep 1
Sessions.touch(client_id)
Sessions.touch(client_id) # rubocop:disable Rails/SkipsModelValidations
# set max loop time to 24 sec. because of 30 sec. timeout of mod_proxy
count = 3

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class MonitoringController < ApplicationController
prepend_before_action -> { authentication_check(permission: 'admin.monitoring') }, except: [:health_check, :status]
prepend_before_action -> { authentication_check(permission: 'admin.monitoring') }, except: %i[health_check status]
skip_before_action :verify_csrf_token
=begin
@ -39,7 +39,7 @@ curl http://localhost/api/v1/monitoring/health_check?token=XXX
# inbound channel
if channel.status_in == 'error'
message = "Channel: #{channel.area} in "
%w(host user uid).each do |key|
%w[host user uid].each do |key|
next if channel.options[key].blank?
message += "key:#{channel.options[key]};"
end
@ -52,7 +52,7 @@ curl http://localhost/api/v1/monitoring/health_check?token=XXX
# outbound channel
next if channel.status_out != 'error'
message = "Channel: #{channel.area} out "
%w(host user uid).each do |key|
%w[host user uid].each do |key|
next if channel.options[key].blank?
message += "key:#{channel.options[key]};"
end
@ -60,7 +60,7 @@ curl http://localhost/api/v1/monitoring/health_check?token=XXX
end
# unprocessable mail check
directory = "#{Rails.root}/tmp/unprocessable_mail"
directory = Rails.root.join('tmp', 'unprocessable_mail').to_s
if File.exist?(directory)
count = 0
Dir.glob("#{directory}/*.eml") do |_entry|
@ -161,9 +161,7 @@ curl http://localhost/api/v1/monitoring/status?token=XXX
map.each do |key, class_name|
status[:counts][key] = class_name.count
last = class_name.last
status[:last_created_at][key] = if last
last.created_at
end
status[:last_created_at][key] = last&.created_at
end
render json: status

View file

@ -98,20 +98,20 @@ class ObjectManagerAttributesController < ApplicationController
private
def check_params
if params[:data_type] =~ /^(boolean)$/
if params[:data_type].match?(/^(boolean)$/)
if params[:data_option][:options]
# rubocop:disable Lint/BooleanSymbol
if params[:data_option][:options][:false]
params[:data_option][:options][false] = params[:data_option][:options][:false]
params[:data_option][:options].delete(:false)
params[:data_option][:options][false] = params[:data_option][:options].delete(:false)
end
if params[:data_option][:options][:true]
params[:data_option][:options][true] = params[:data_option][:options][:true]
params[:data_option][:options].delete(:true)
params[:data_option][:options][true] = params[:data_option][:options].delete(:true)
end
# rubocop:enable Lint/BooleanSymbol
end
end
if params[:data_option] && !params[:data_option].key?(:default)
params[:data_option][:default] = if params[:data_type] =~ /^(input|select|tree_select)$/
params[:data_option][:default] = if params[:data_type].match?(/^(input|select|tree_select)$/)
''
end
end

View file

@ -237,12 +237,16 @@ curl http://localhost/api/v1/organization/{id} -v -u #{login}:#{password} -H "Co
params[:limit].to_i = 500
end
query = params[:query]
if query.respond_to?(:permit!)
query = query.permit!.to_h
end
query_params = {
query: params[:query],
query: query,
limit: params[:limit],
current_user: current_user,
}
if params[:role_ids] && !params[:role_ids].empty?
if params[:role_ids].present?
query_params[:role_ids] = params[:role_ids]
end

View file

@ -30,7 +30,7 @@ Example:
=begin
Resource:
GET /api/v1/overviews.json
GET /api/v1/overviews
Response:
[
@ -47,7 +47,7 @@ Response:
]
Test:
curl http://localhost/api/v1/overviews.json -v -u #{login}:#{password}
curl http://localhost/api/v1/overviews -v -u #{login}:#{password}
=end
@ -58,7 +58,7 @@ curl http://localhost/api/v1/overviews.json -v -u #{login}:#{password}
=begin
Resource:
GET /api/v1/overviews/#{id}.json
GET /api/v1/overviews/#{id}
Response:
{
@ -68,7 +68,7 @@ Response:
}
Test:
curl http://localhost/api/v1/overviews/#{id}.json -v -u #{login}:#{password}
curl http://localhost/api/v1/overviews/#{id} -v -u #{login}:#{password}
=end
@ -79,7 +79,7 @@ curl http://localhost/api/v1/overviews/#{id}.json -v -u #{login}:#{password}
=begin
Resource:
POST /api/v1/overviews.json
POST /api/v1/overviews
Payload:
{
@ -101,7 +101,7 @@ Response:
}
Test:
curl http://localhost/api/v1/overviews.json -v -u #{login}:#{password} -H "Content-Type: application/json" -X POST -d '{"name": "some_name","active": true, "note": "some note"}'
curl http://localhost/api/v1/overviews -v -u #{login}:#{password} -H "Content-Type: application/json" -X POST -d '{"name": "some_name","active": true, "note": "some note"}'
=end
@ -112,7 +112,7 @@ curl http://localhost/api/v1/overviews.json -v -u #{login}:#{password} -H "Conte
=begin
Resource:
PUT /api/v1/overviews/{id}.json
PUT /api/v1/overviews/{id}
Payload:
{
@ -134,7 +134,7 @@ Response:
}
Test:
curl http://localhost/api/v1/overviews.json -v -u #{login}:#{password} -H "Content-Type: application/json" -X PUT -d '{"name": "some_name","active": true, "note": "some note"}'
curl http://localhost/api/v1/overviews -v -u #{login}:#{password} -H "Content-Type: application/json" -X PUT -d '{"name": "some_name","active": true, "note": "some note"}'
=end
@ -145,17 +145,55 @@ curl http://localhost/api/v1/overviews.json -v -u #{login}:#{password} -H "Conte
=begin
Resource:
DELETE /api/v1/overviews/{id}.json
DELETE /api/v1/overviews/{id}
Response:
{}
Test:
curl http://localhost/api/v1/overviews/#{id}.json -v -u #{login}:#{password} -H "Content-Type: application/json" -X DELETE
curl http://localhost/api/v1/overviews/#{id} -v -u #{login}:#{password} -H "Content-Type: application/json" -X DELETE
=end
def destroy
model_destroy_render(Overview, params)
end
=begin
Resource:
POST /api/v1/overviews_prio
Payload:
{
"prios": [
[overview_id, prio],
[overview_id, prio],
[overview_id, prio],
[overview_id, prio],
[overview_id, prio]
]
}
Response:
{
"success": true,
}
Test:
curl http://localhost/api/v1/overviews_prio -v -u #{login}:#{password} -H "Content-Type: application/json" -X POST -d '{"prios": [ [1,1], [44,2] ]}'
=end
def prio
Overview.without_callback(:update, :before, :rearrangement) do
params[:prios].each do |overview_prio|
overview = Overview.find(overview_prio[0])
next if overview.prio == overview_prio[1]
overview.prio = overview_prio[1]
overview.save!
end
end
render json: { success: true }, status: :ok
end
end

View file

@ -16,6 +16,9 @@ class SearchController < ApplicationController
# get params
query = params[:query]
if query.respond_to?(:permit!)
query = query.permit!.to_h
end
limit = params[:limit] || 10
# convert objects string into array of class names

View file

@ -1,8 +1,8 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class SessionsController < ApplicationController
prepend_before_action :authentication_check, only: [:switch_to_user, :list, :delete]
skip_before_action :verify_csrf_token, only: [:create, :show, :destroy, :create_omniauth, :create_sso]
prepend_before_action :authentication_check, only: %i[switch_to_user list delete]
skip_before_action :verify_csrf_token, only: %i[create show destroy create_omniauth create_sso]
# "Create" a login, aka "log the user in"
def create

View file

@ -93,11 +93,11 @@ class SettingsController < ApplicationController
def keep_certain_attributes
setting = Setting.find(params[:id])
[:name, :area, :state_initial, :frontend, :options].each do |key|
%i[name area state_initial frontend options].each do |key|
params.delete(key)
end
if !params[:preferences].empty?
[:online_service_disable, :permission, :render].each do |key|
if params[:preferences].present?
%i[online_service_disable permission render].each do |key|
params[:preferences].delete(key)
end
params[:preferences].merge!(setting.preferences)

View file

@ -266,7 +266,7 @@ class TicketArticlesController < ApplicationController
def sanitized_disposition
disposition = params.fetch(:disposition, 'inline')
valid_disposition = %w(inline attachment)
valid_disposition = %w[inline attachment]
return disposition if valid_disposition.include?(disposition)
raise Exceptions::NotAuthorized, "Invalid disposition #{disposition} requested. Only #{valid_disposition.join(', ')} are valid."
end

View file

@ -80,7 +80,7 @@ class TicketsController < ApplicationController
# overwrite params
if !current_user.permissions?('ticket.agent')
[:owner, :owner_id, :customer, :customer_id, :organization, :organization_id, :preferences].each do |key|
%i[owner owner_id customer customer_id organization organization_id preferences].each do |key|
clean_params.delete(key)
end
clean_params[:customer_id] = current_user.id
@ -186,7 +186,7 @@ class TicketsController < ApplicationController
# overwrite params
if !current_user.permissions?('ticket.agent')
[:owner, :owner_id, :customer, :customer_id, :organization, :organization_id, :preferences].each do |key|
%i[owner owner_id customer customer_id organization organization_id preferences].each do |key|
clean_params.delete(key)
end
end
@ -270,7 +270,7 @@ class TicketsController < ApplicationController
.limit(6)
# if we do not have open related tickets, search for any tickets
if ticket_lists.empty?
if ticket_lists.blank?
ticket_lists = Ticket
.where(
customer_id: ticket.customer_id,
@ -389,11 +389,16 @@ class TicketsController < ApplicationController
params[:limit].to_i = 100
end
query = params[:query]
if query.respond_to?(:permit!)
query = query.permit!.to_h
end
# build result list
tickets = Ticket.search(
query: query,
condition: params[:condition].to_h,
limit: params[:limit],
query: params[:query],
condition: params[:condition],
current_user: current_user,
)
@ -435,12 +440,10 @@ class TicketsController < ApplicationController
assets = {}
ticket_ids = []
if tickets
tickets.each do |ticket|
tickets&.each do |ticket|
ticket_ids.push ticket.id
assets = ticket.assets(assets)
end
end
# return result
render json: {
@ -504,7 +507,7 @@ class TicketsController < ApplicationController
# lookup open org tickets
org_tickets = {}
if params[:organization_id] && !params[:organization_id].empty?
if params[:organization_id].present?
organization = Organization.lookup(id: params[:organization_id])
if !organization
raise "No such organization with id #{params[:organization_id]}"

View file

@ -164,7 +164,7 @@ class TimeAccountingsController < ApplicationController
]
result = []
results.each do |row|
row[:ticket].keys.each do |field|
row[:ticket].each_key do |field|
next if row[:ticket][field].blank?
next if !row[:ticket][field].is_a?(ActiveSupport::TimeWithZone)
@ -250,7 +250,7 @@ class TimeAccountingsController < ApplicationController
customers[ticket.customer_id][:time_unit] += local_time_unit[:time_unit]
end
results = []
customers.each do |_customer_id, content|
customers.each_value do |content|
results.push content
end
@ -326,7 +326,7 @@ class TimeAccountingsController < ApplicationController
organizations[ticket.organization_id][:time_unit] += local_time_unit[:time_unit]
end
results = []
organizations.each do |_customer_id, content|
organizations.each_value do |content|
results.push content
end

View file

@ -14,7 +14,7 @@ class UserAccessTokenController < ApplicationController
end
local_permissions = current_user.permissions
local_permissions_new = {}
local_permissions.each do |key, _value|
local_permissions.each_key do |key|
keys = Object.const_get('Permission').with_parents(key)
keys.each do |local_key|
next if local_permissions_new.key?([local_key])

View file

@ -8,7 +8,7 @@ class UserDevicesController < ApplicationController
devices_full = []
devices.each do |device|
attributes = device.attributes
if device.location_details['city_name'] && !device.location_details['city_name'].empty?
if device.location_details['city_name'].present?
attributes['location'] += ", #{device.location_details['city_name']}"
end
attributes.delete('created_at')

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class UsersController < ApplicationController
prepend_before_action :authentication_check, except: [:create, :password_reset_send, :password_reset_verify, :image]
prepend_before_action :authentication_check, except: %i[create password_reset_send password_reset_verify image]
prepend_before_action :authentication_check_only, only: [:create]
# @path [GET] /users
@ -145,7 +145,7 @@ class UsersController < ApplicationController
group_ids = []
role_ids = []
if count <= 2
Role.where(name: %w(Admin Agent)).each do |role|
Role.where(name: %w[Admin Agent]).each do |role|
role_ids.push role.id
end
Group.all().each do |group|
@ -363,12 +363,17 @@ class UsersController < ApplicationController
params[:limit].to_i = 500
end
query = params[:query]
if query.respond_to?(:permit!)
query = query.permit!.to_h
end
query_params = {
query: params[:query],
query: query,
limit: params[:limit],
current_user: current_user,
}
[:role_ids, :permissions].each do |key|
%i[role_ids permissions].each do |key|
next if params[key].blank?
query_params[key] = params[key]
end
@ -1046,7 +1051,7 @@ curl http://localhost/api/v1/users/avatar -v -u #{login}:#{password} -H "Content
def permission_check_by_permission(params)
return true if current_user.permissions?('admin.user')
%i(role_ids roles).each do |key|
%i[role_ids roles].each do |key|
next if !params[key]
if current_user.permissions?('ticket.agent')
params.delete(key)
@ -1059,7 +1064,7 @@ curl http://localhost/api/v1/users/avatar -v -u #{login}:#{password} -H "Content
params[:role_ids] = Role.signup_role_ids
end
%i(group_ids groups).each do |key|
%i[group_ids groups].each do |key|
next if !params[key]
if current_user.permissions?('ticket.agent')
params.delete(key)

View file

@ -99,7 +99,7 @@ return all activity entries of an user
permission_ids = user.permissions_with_child_ids
group_ids = user.group_ids_access('read')
stream = if group_ids.empty?
stream = if group_ids.blank?
ActivityStream.where('(permission_id IN (?) AND group_id is NULL)', permission_ids)
.order('created_at DESC, id DESC')
.limit(limit)

View file

@ -33,7 +33,7 @@ returns
return data if !self['created_by_id'] && !self['updated_by_id']
app_model_user = User.to_app_model
%w(created_by_id updated_by_id).each do |local_user_id|
%w[created_by_id updated_by_id].each do |local_user_id|
next if !self[ local_user_id ]
next if data[ app_model_user ] && data[ app_model_user ][ self[ local_user_id ] ]
user = User.lookup(id: self[ local_user_id ])
@ -75,12 +75,12 @@ get assets and record_ids of selector
attribute_ref_class = models[attribute_class][:reflections][reflection].klass
if content['value'].instance_of?(Array)
content['value'].each do |item_id|
attribute_object = attribute_ref_class.find_by(id: item_id)
if attribute_object
next if item_id.blank?
attribute_object = attribute_ref_class.lookup(id: item_id)
next if !attribute_object
assets = attribute_object.assets(assets)
end
end
else
elsif content['value'].present?
attribute_object = attribute_ref_class.find_by(id: content['value'])
if attribute_object
assets = attribute_object.assets(assets)
@ -138,11 +138,11 @@ get assets of object list
require item['object'].to_filename
record = Kernel.const_get(item['object']).find(item['o_id'])
assets = record.assets(assets)
if item['created_by_id']
if item['created_by_id'].present?
user = User.find(item['created_by_id'])
assets = user.assets(assets)
end
if item['updated_by_id']
if item['updated_by_id'].present?
user = User.find(item['updated_by_id'])
assets = user.assets(assets)
end

View file

@ -109,7 +109,7 @@ returns
return cache if cache
attributes = self.attributes
relevant = %i(has_and_belongs_to_many has_many)
relevant = %i[has_and_belongs_to_many has_many]
eager_load = []
pluck = []
keys = []
@ -180,7 +180,7 @@ returns
next if !item[:name]
attributes[assoc.name.to_s].push item[:name]
end
if ref.count.positive? && attributes[assoc.name.to_s].empty?
if ref.count.positive? && attributes[assoc.name.to_s].blank?
attributes.delete(assoc.name.to_s)
end
next
@ -216,7 +216,7 @@ returns
def filter_attributes(attributes)
# remove forbitten attributes
%w(password token tokens token_ids).each do |item|
%w[password token tokens token_ids].each do |item|
attributes.delete(item)
end
end
@ -237,7 +237,7 @@ returns
def association_id_validation(attribute_id, value)
return true if value.nil?
attributes.each do |key, _value|
attributes.each_key do |key|
next if key != attribute_id
# check if id is assigned
@ -339,16 +339,15 @@ returns
class_object = assoc.klass
lookup = nil
if class_object == User
if value.instance_of?(String)
if !value.instance_of?(String)
raise ArgumentError, "String is needed as ref value #{value.inspect} for '#{assoc_name}'"
end
if !lookup
lookup = class_object.lookup(login: value)
end
if !lookup
lookup = class_object.lookup(email: value)
end
else
raise ArgumentError, "String is needed as ref value #{value.inspect} for '#{assoc_name}'"
end
else
lookup = class_object.lookup(name: value)
end
@ -367,7 +366,7 @@ returns
end
next if !value.instance_of?(Array)
next if value.empty?
next if value.blank?
next if !value[0].instance_of?(String)
# handle _ids values
@ -383,16 +382,15 @@ returns
value.each do |item|
lookup = nil
if class_object == User
if item.instance_of?(String)
if !item.instance_of?(String)
raise ArgumentError, "String is needed in array ref as ref value #{value.inspect} for '#{assoc_name}'"
end
if !lookup
lookup = class_object.lookup(login: item)
end
if !lookup
lookup = class_object.lookup(email: item)
end
else
raise ArgumentError, "String is needed in array ref as ref value #{value.inspect} for '#{assoc_name}'"
end
else
lookup = class_object.lookup(name: item)
end

View file

@ -43,7 +43,7 @@ returns
# only use object attributes
clean_params = {}
new.attributes.each do |attribute, _value|
new.attributes.each_key do |attribute|
next if !data.key?(attribute.to_sym)
# check reference records, referenced by _id attributes
@ -80,7 +80,7 @@ returns
def filter_unused_params(data)
# we do want to set this via database
[:action, :controller, :updated_at, :created_at, :updated_by_id, :created_by_id, :updated_by, :created_by].each do |key|
%i[action controller updated_at created_at updated_by_id created_by_id updated_by created_by].each do |key|
data.delete(key)
end

View file

@ -123,8 +123,8 @@ returns
return record
end
record = new(data)
record.save
return record
record.save!
record
elsif data[:name]
# do lookup with == to handle case insensitive databases
@ -140,8 +140,8 @@ returns
end
end
record = new(data)
record.save
return record
record.save!
record
elsif data[:login]
# do lookup with == to handle case insensitive databases
@ -157,8 +157,8 @@ returns
end
end
record = new(data)
record.save
return record
record.save!
record
elsif data[:email]
# do lookup with == to handle case insensitive databases
@ -174,8 +174,8 @@ returns
end
end
record = new(data)
record.save
return record
record.save!
record
elsif data[:locale]
# do lookup with == to handle case insensitive databases
@ -191,8 +191,8 @@ returns
end
end
record = new(data)
record.save
return record
record.save!
record
else
raise ArgumentError, 'Need name, login, email or locale for create_or_update()'
end

View file

@ -21,7 +21,7 @@ touch references by params
object_class = Kernel.const_get(data[:object])
object = object_class.lookup(id: data[:o_id])
return if !object
object.touch
object.touch # rubocop:disable Rails/SkipsModelValidations
rescue => e
logger.error e
end

View file

@ -37,7 +37,7 @@ store attachments for this object
self.attachments_buffer = attachments
# update if object already exists
return if !(id && id.nonzero?)
return if !(id&.nonzero?)
attachments_buffer_check
end

View file

@ -90,7 +90,7 @@ class Authorization < ApplicationModel
def delete_user_cache
return if !user
user.touch
user.touch # rubocop:disable Rails/SkipsModelValidations
end
end

View file

@ -105,16 +105,16 @@ add avatar by url
# fetch image based on http url
if data[:url].present?
if data[:url] =~ /^http/
if data[:url].match?(/^http/)
# check if source ist already updated within last 2 minutes
if avatar_already_exists && avatar_already_exists.source_url == data[:url]
if avatar_already_exists&.source_url == data[:url]
return if avatar_already_exists.updated_at > 2.minutes.ago
end
# twitter workaround to get bigger avatar images
# see also https://dev.twitter.com/overview/general/user-profile-images-and-banners
if data[:url] =~ %r{//pbs.twimg.com/}i
if data[:url].match?(%r{//pbs.twimg.com/}i)
data[:url].sub!(/normal\.(png|jpg|gif)$/, 'bigger.\1')
end
@ -134,10 +134,10 @@ add avatar by url
end
logger.info "Fetchd image '#{data[:url]}', http code: #{response.code}"
mime_type = 'image'
if data[:url] =~ /\.png/i
if data[:url].match?(/\.png/i)
mime_type = 'image/png'
end
if data[:url] =~ /\.(jpg|jpeg)/i
if data[:url].match?(/\.(jpg|jpeg)/i)
mime_type = 'image/jpeg'
end
if !data[:resize]
@ -150,10 +150,10 @@ add avatar by url
data[:full][:mime_type] = mime_type
# try zammad backend to find image based on email
elsif data[:url] =~ /@/
elsif data[:url].match?(/@/)
# check if source ist already updated within last 3 minutes
if avatar_already_exists && avatar_already_exists.source_url == data[:url]
if avatar_already_exists&.source_url == data[:url]
return if avatar_already_exists.updated_at > 2.minutes.ago
end
@ -170,8 +170,8 @@ add avatar by url
# check if avatar need to be updated
if data[:resize].present? && data[:resize][:content].present?
record[:store_hash] = Digest::MD5.hexdigest(data[:resize][:content])
if avatar_already_exists && avatar_already_exists.store_hash == record[:store_hash]
avatar_already_exists.touch
if avatar_already_exists&.store_hash == record[:store_hash]
avatar_already_exists.touch # rubocop:disable Rails/SkipsModelValidations
return avatar_already_exists
end
end

View file

@ -83,11 +83,11 @@ returns
=end
def self.ical_feeds
data = YAML.load_file(Rails.root.join('config/holiday_calendars.yml'))
data = YAML.load_file(Rails.root.join('config', 'holiday_calendars.yml'))
url = data['url']
data['countries'].map do |country, domain|
[(url % { domain: domain }), country]
[format(url, domain: domain), country]
end.to_h
end
@ -210,7 +210,7 @@ returns
end
def self.fetch_parse(location)
if location =~ /^http/i
if location.match?(/^http/i)
result = UserAgent.get(location)
if !result.success?
raise result.error
@ -257,7 +257,7 @@ returns
end
# ignore daylight saving time entries
return if comment =~ /(daylight saving|sommerzeit|summertime)/i
return if comment.match?(/(daylight saving|sommerzeit|summertime)/i)
[day, comment]
end

View file

@ -50,7 +50,6 @@ fetch one account
end
begin
# we need to require each channel backend individually otherwise we get a
# 'warning: toplevel constant Twitter referenced by Channel::Driver::Twitter' error e.g.
# so we have to convert the channel name to the filename via Rails String.underscore
@ -94,7 +93,6 @@ stream instance of account
adapter = options[:adapter]
begin
# we need to require each channel backend individually otherwise we get a
# 'warning: toplevel constant Twitter referenced by Channel::Driver::Twitter' error e.g.
# so we have to convert the channel name to the filename via Rails String.underscore
@ -264,7 +262,6 @@ send via account
result = nil
begin
# we need to require each channel backend individually otherwise we get a
# 'warning: toplevel constant Twitter referenced by Channel::Driver::Twitter' error e.g.
# so we have to convert the channel name to the filename via Rails String.underscore

View file

@ -40,7 +40,7 @@ returns
end
end
if !access
%w(inbound outbound).each do |key|
%w[inbound outbound].each do |key|
if attributes['options'] && attributes['options'][key] && attributes['options'][key]['options']
attributes['options'][key]['options'].delete('password')
end
@ -51,7 +51,7 @@ returns
end
return data if !self['created_by_id'] && !self['updated_by_id']
%w(created_by_id updated_by_id).each do |local_user_id|
%w[created_by_id updated_by_id].each do |local_user_id|
next if !self[ local_user_id ]
next if data[ User.to_app_model ] && data[ User.to_app_model ][ self[ local_user_id ] ]
user = User.lookup(id: self[ local_user_id ])

View file

@ -60,8 +60,7 @@ class Channel::Driver::Facebook
true
end
def disconnect
end
def disconnect; end
=begin

View file

@ -104,7 +104,7 @@ example
# sort messages by date on server (if not supported), if not fetch messages via search (first in, first out)
filter = ['ALL']
if keep_on_server && check_type != 'check' && check_type != 'verify'
filter = %w(NOT SEEN)
filter = %w[NOT SEEN]
end
begin
message_ids = @imap.sort(['DATE'], filter, 'US-ASCII')
@ -254,7 +254,7 @@ returns
# verify if message is already imported via same channel, if not, import it again
ticket = article.ticket
if ticket && ticket.preferences && ticket.preferences[:channel_id].present? && channel.present?
if ticket&.preferences && ticket.preferences[:channel_id].present? && channel.present?
return false if ticket.preferences[:channel_id] != channel[:id]
end

View file

@ -27,7 +27,7 @@ class Channel::Driver::Smtp
return if Setting.get('import_mode')
# set smtp defaults
if !options.key?(:port) || options[:port].empty?
if !options.key?(:port) || options[:port].blank?
options[:port] = 25
end
if !options.key?(:ssl)

View file

@ -119,8 +119,8 @@ returns
end
def disconnect
@stream_client.disconnect if @stream_client
@rest_client.disconnect if @rest_client
@stream_client&.disconnect
@rest_client&.disconnect
end
=begin
@ -203,12 +203,11 @@ returns
stream_start
rescue Twitter::Error::Unauthorized => e
Rails.logger.info "Unable to stream, try #{loop_count}, error #{e.inspect}"
if loop_count < 2
Rails.logger.info "wait for #{sleep_on_unauthorized} sec. and try it again"
sleep sleep_on_unauthorized
else
if loop_count >= 2
raise "Unable to stream, try #{loop_count}, error #{e.inspect}"
end
Rails.logger.info "wait for #{sleep_on_unauthorized} sec. and try it again"
sleep sleep_on_unauthorized
end
end
end
@ -233,7 +232,7 @@ returns
filter[:replies] = 'all'
end
return if filter.empty?
return if filter.blank?
@stream_client.client.user(filter) do |tweet|
next if tweet.class != Twitter::Tweet && tweet.class != Twitter::DirectMessage
@ -258,13 +257,11 @@ returns
# check if it's mention
if sync['mentions'] && sync['mentions']['group_id'].present?
hit = false
if tweet.user_mentions
tweet.user_mentions.each do |user|
tweet.user_mentions&.each do |user|
if user.id.to_s == @channel.options['user']['id'].to_s
hit = true
end
end
end
if hit
@stream_client.to_group(tweet, sync['mentions']['group_id'], @channel)
next
@ -299,7 +296,7 @@ returns
next if item['term'].blank?
next if item['term'] == '#'
next if item['group_id'].blank?
if body =~ /#{item['term']}/
if body.match?(/#{item['term']}/)
hit = item
end
end

View file

@ -69,7 +69,7 @@ module Channel::EmailBuild
end
# build email without any attachments
if !html_alternative && ( !attr[:attachments] || attr[:attachments].empty? )
if !html_alternative && attr[:attachments].blank?
mail.content_type 'text/plain; charset=UTF-8'
mail.body attr[:body]
return mail
@ -84,10 +84,9 @@ module Channel::EmailBuild
html_container.add_part html_alternative
# place to add inline attachments related to html alternative
if attr[:attachments]
attr[:attachments].each do |attachment|
attr[:attachments]&.each do |attachment|
next if attachment.class == Hash
next if attachment.preferences['Content-ID'].empty?
next if attachment.preferences['Content-ID'].blank?
attachment = Mail::Part.new do
content_type attachment.preferences['Content-Type']
content_id "<#{attachment.preferences['Content-ID']}>"
@ -97,20 +96,18 @@ module Channel::EmailBuild
end
html_container.add_part attachment
end
end
alternative_bodies.add_part html_container
end
mail.add_part alternative_bodies
# add attachments
if attr[:attachments]
attr[:attachments].each do |attachment|
attr[:attachments]&.each do |attachment|
if attachment.class == Hash
attachment['content-id'] = nil
mail.attachments[ attachment[:filename] ] = attachment
else
next if !attachment.preferences['Content-ID'].empty?
next if attachment.preferences['Content-ID'].present?
filename = attachment.filename
encoded_filename = Mail::Encodings.decode_encode filename, :encode
disposition = attachment.preferences['Content-Disposition'] || 'attachment'
@ -122,7 +119,6 @@ module Channel::EmailBuild
}
end
end
end
mail
end
@ -137,7 +133,7 @@ returns
=end
def self.recipient_line(realname, email)
return "#{realname} <#{email}>" if realname =~ /^[A-z]+$/i
return "#{realname} <#{email}>" if realname.match?(/^[A-z]+$/i)
"\"#{realname.gsub('"', '\"')}\" <#{email}>"
end
@ -154,7 +150,7 @@ Check if string is a complete html document. If not, add head and css styles.
# apply mail client fixes
html = Channel::EmailBuild.html_mail_client_fixes(html)
return html if html =~ /<html>/i
return html if html.match?(/<html>/i)
# use block form because variable html could contain backslashes and e. g. '\1' that
# must not be handled as back-references for regular expressions

View file

@ -94,7 +94,7 @@ class Channel::EmailParser
# verify content, ignore recipients with non email address
['to', 'cc', 'delivered-to', 'x-original-to', 'envelope-to'].each do |field|
next if data[field.to_sym].blank?
next if data[field.to_sym] =~ /@/
next if data[field.to_sym].match?(/@/)
data[field.to_sym] = ''
end
@ -146,7 +146,7 @@ class Channel::EmailParser
if mail.multipart?
# html attachment/body may exists and will be converted to strict html
if mail.html_part && mail.html_part.body
if mail.html_part&.body
data[:body] = mail.html_part.body.to_s
data[:body] = Encode.conv(mail.html_part.charset.to_s, data[:body])
data[:body] = data[:body].html2html_strict.to_s.force_encoding('utf-8')
@ -196,8 +196,7 @@ class Channel::EmailParser
end
# get attachments
if mail.parts
mail.parts.each do |part|
mail.parts&.each do |part|
# protect process to work fine with spam emails, see test/fixtures/mail15.box
begin
@ -208,7 +207,6 @@ class Channel::EmailParser
data[:attachments].concat(attachs)
end
end
end
# not multipart email
@ -306,10 +304,10 @@ class Channel::EmailParser
end
# ignore text/plain attachments - already shown in view
return [] if mail.text_part && mail.text_part.body.to_s == file.body.to_s
return [] if mail.text_part&.body.to_s == file.body.to_s
# ignore text/html - html part, already shown in view
return [] if mail.html_part && mail.html_part.body.to_s == file.body.to_s
return [] if mail.html_part&.body.to_s == file.body.to_s
# get file preferences
headers_store = {}
@ -376,7 +374,7 @@ class Channel::EmailParser
# generate file name based on content type
if filename.blank? && headers_store['Content-Type'].present?
if headers_store['Content-Type'] =~ %r{^message/rfc822}i
if headers_store['Content-Type'].match?(%r{^message/rfc822}i)
begin
parser = Channel::EmailParser.new
mail_local = parser.parse(file.body.to_s)
@ -406,13 +404,13 @@ class Channel::EmailParser
if filename.blank?
map = {
'message/delivery-status': ['txt', 'delivery-status'],
'text/plain': %w(txt document),
'text/html': %w(html document),
'video/quicktime': %w(mov video),
'image/jpeg': %w(jpg image),
'image/jpg': %w(jpg image),
'image/png': %w(png image),
'image/gif': %w(gif image),
'text/plain': %w[txt document],
'text/html': %w[html document],
'video/quicktime': %w[mov video],
'image/jpeg': %w[jpg image],
'image/jpg': %w[jpg image],
'image/png': %w[png image],
'image/gif': %w[gif image],
}
map.each do |type, ext|
next if headers_store['Content-Type'] !~ /^#{Regexp.quote(type)}/i
@ -454,12 +452,12 @@ class Channel::EmailParser
end
# get mime type
if file.header[:content_type] && file.header[:content_type].string
if file.header[:content_type]&.string
headers_store['Mime-Type'] = file.header[:content_type].string
end
# get charset
if file.header && file.header.charset
if file.header&.charset
headers_store['Charset'] = file.header.charset
end
@ -503,9 +501,8 @@ returns
_process(channel, msg)
rescue => e
# store unprocessable email for bug reporting
path = "#{Rails.root}/tmp/unprocessable_mail/"
path = Rails.root.join('tmp', 'unprocessable_mail')
FileUtils.mkpath path
md5 = Digest::MD5.hexdigest(msg)
filename = "#{path}/#{md5}.eml"
@ -532,7 +529,7 @@ returns
Setting.where(area: 'Postmaster::PreFilter').order(:name).each do |setting|
filters[setting.name] = Kernel.const_get(Setting.get(setting.name))
end
filters.each do |_prio, backend|
filters.each_value do |backend|
Rails.logger.debug "run postmaster pre filter #{backend}"
begin
backend.run(channel, mail)
@ -663,8 +660,7 @@ returns
article.save_as_raw(msg)
# store attachments
if mail[:attachments]
mail[:attachments].each do |attachment|
mail[:attachments]&.each do |attachment|
Store.add(
object: 'Ticket::Article',
o_id: article.id,
@ -675,14 +671,13 @@ returns
end
end
end
end
# run postmaster post filter
filters = {}
Setting.where(area: 'Postmaster::PostFilter').order(:name).each do |setting|
filters[setting.name] = Kernel.const_get(Setting.get(setting.name))
end
filters.each do |_prio, backend|
filters.each_value do |backend|
Rails.logger.debug "run postmaster post filter #{backend}"
begin
backend.run(channel, mail, ticket, article, session_user)
@ -765,7 +760,7 @@ returns
def set_attributes_by_x_headers(item_object, header_name, mail, suffix = false)
# loop all x-zammad-header-* headers
item_object.attributes.each do |key, _value|
item_object.attributes.each_key do |key|
# ignore read only attributes
next if key == 'updated_by_id'
@ -862,9 +857,9 @@ module Mail
.+?(?=\=\?|$) # Plain String
)/xmi).map do |matches|
string, method = *matches
if method == 'b' || method == 'B'
if method == 'b' || method == 'B' # rubocop:disable Style/MultipleComparison
b_value_decode(string)
elsif method == 'q' || method == 'Q'
elsif method == 'q' || method == 'Q' # rubocop:disable Style/MultipleComparison
q_value_decode(string)
else
string

View file

@ -25,7 +25,7 @@ module Channel::Filter::AutoResponseCheck
message_id = mail[ 'message_id'.to_sym ]
if message_id
fqdn = Setting.get('fqdn')
return if message_id =~ /@#{Regexp.quote(fqdn)}/i
return if message_id.match?(/@#{Regexp.quote(fqdn)}/i)
end
mail[ 'x-zammad-send-auto-response'.to_sym ] = true

View file

@ -28,7 +28,7 @@ module Channel::Filter::BounceDeliveryPermanentFailed
# get recipient of origin article, if only one - mark this user to not sent notifications anymore
recipients = []
if article.sender.name == 'System' || article.sender.name == 'Agent'
%w(to cc).each do |line|
%w[to cc].each do |line|
next if article[line].blank?
recipients = []
begin

View file

@ -104,5 +104,6 @@ module Channel::Filter::FollowUpCheck
end
end
true
end
end

View file

@ -22,15 +22,15 @@ module Channel::Filter::IdentifySender
if !customer_user && mail[ 'x-zammad-customer-email'.to_sym ].present?
customer_user = User.find_by(email: mail[ 'x-zammad-customer-email'.to_sym ])
end
if !customer_user
# get correct customer
if !customer_user && Setting.get('postmaster_sender_is_agent_search_for_customer') == true
if mail[ 'x-zammad-ticket-create-article-sender'.to_sym ] == 'Agent'
# get first recipient and set customer
begin
to = 'raw-to'.to_sym
if mail[to] && mail[to].addrs
if mail[to]&.addrs
items = mail[to].addrs
items.each do |item|
@ -46,9 +46,12 @@ module Channel::Filter::IdentifySender
end
end
rescue => e
Rails.logger.error 'ERROR: SenderIsSystemAddress: ' + e.inspect
Rails.logger.error "SenderIsSystemAddress: ##{e.inspect}"
end
end
end
# take regular from as customer
if !customer_user
customer_user = user_create(
login: mail[ 'x-zammad-customer-login'.to_sym ] || mail[ 'x-zammad-customer-email'.to_sym ] || mail[:from_email],
@ -57,7 +60,7 @@ module Channel::Filter::IdentifySender
email: mail[ 'x-zammad-customer-email'.to_sym ] || mail[:from_email],
)
end
end
create_recipients(mail)
mail[ 'x-zammad-ticket-customer_id'.to_sym ] = customer_user.id
@ -83,6 +86,8 @@ module Channel::Filter::IdentifySender
if session_user
mail[ 'x-zammad-session-user-id'.to_sym ] = session_user.id
end
true
end
# create to and cc user
@ -159,7 +164,7 @@ module Channel::Filter::IdentifySender
role_ids = Role.signup_role_ids
# fillup
%w(firstname lastname).each do |item|
%w[firstname lastname].each do |item|
if data[item.to_sym].nil?
data[item.to_sym] = ''
end

View file

@ -9,12 +9,12 @@ module Channel::Filter::Match::EmailRegex
if regexp == false
match_rule_quoted = Regexp.quote(match_rule).gsub(/\\\*/, '.*')
return true if value =~ /#{match_rule_quoted}/i
return true if value.match?(/#{match_rule_quoted}/i)
return false
end
begin
return true if value =~ /#{match_rule}/i
return true if value.match?(/#{match_rule}/i)
return false
rescue => e
message = "Can't use regex '#{match_rule}' on '#{value}': #{e.message}"

View file

@ -36,9 +36,7 @@ class Channel::Filter::MonitoringBase
key = key.downcase
end
value = $2
if value
value.strip!
end
value&.strip!
result[key] = value
end
@ -70,9 +68,9 @@ class Channel::Filter::MonitoringBase
# possible event types https://mmonit.com/monit/documentation/#Setting-an-event-filter
if result['state'].blank?
result['state'] = if mail[:body] =~ /\s(done|recovery|succeeded|bytes\sok|packets\sok)\s/
result['state'] = if mail[:body].match?(/\s(done|recovery|succeeded|bytes\sok|packets\sok)\s/)
'OK'
elsif mail[:body] =~ /(instance\schanged\snot|Link\sup|Exists|Saturation\sok|Speed\sok)/
elsif mail[:body].match?(/(instance\schanged\snot|Link\sup|Exists|Saturation\sok|Speed\sok)/)
'OK'
else
'CRITICAL'
@ -132,5 +130,6 @@ class Channel::Filter::MonitoringBase
return true
end
true
end
end

View file

@ -18,12 +18,12 @@ module Channel::Filter::OutOfOfficeCheck
if mail[ 'auto-submitted'.to_sym ]
# check zimbra out of office characteristics
if mail[ 'auto-submitted'.to_sym ] =~ /vacation/i
if mail[ 'auto-submitted'.to_sym ].match?(/vacation/i)
mail[ 'x-zammad-out-of-office'.to_sym ] = true
end
# check cloud out of office characteristics
if mail[ 'auto-submitted'.to_sym ] =~ /auto-replied;\sowner-email=/i
if mail[ 'auto-submitted'.to_sym ].match?(/auto-replied;\sowner-email=/i)
mail[ 'x-zammad-out-of-office'.to_sym ] = true
end
@ -35,6 +35,7 @@ module Channel::Filter::OutOfOfficeCheck
return
end
true
end
end

View file

@ -7,7 +7,7 @@ module Channel::Filter::Trusted
# check if trust x-headers
if !channel[:trusted]
mail.each do |key, _value|
mail.each_key do |key|
next if key !~ /^x-zammad/i
mail.delete(key)
end

View file

@ -9,7 +9,7 @@ class Chat < ApplicationModel
# reconnect
if session_id
chat_session = Chat::Session.find_by(session_id: session_id, state: %w(waiting running))
chat_session = Chat::Session.find_by(session_id: session_id, state: %w[waiting running])
if chat_session
if chat_session.state == 'running'
@ -126,7 +126,7 @@ class Chat < ApplicationModel
end
def self.active_chat_count
Chat::Session.where(state: %w(waiting running)).count
Chat::Session.where(state: %w[waiting running]).count
end
def self.available_agents(diff = 2.minutes)
@ -153,7 +153,7 @@ class Chat < ApplicationModel
def self.seads_total(diff = 2.minutes)
total = 0
available_agents(diff).each do |_user_id, concurrent|
available_agents(diff).each_value do |concurrent|
total += concurrent
end
total

View file

@ -5,7 +5,7 @@ class Chat::Agent < ApplicationModel
end
def active_chat_count
Chat::Session.where(state: %w(waiting running), user_id: updated_by_id).count
Chat::Session.where(state: %w[waiting running], user_id: updated_by_id).count
end
def self.state(user_id, state = nil)

View file

@ -17,7 +17,7 @@ module CanSeed
end
def seedfile
"#{Rails.root}/db/seeds/#{name.pluralize.underscore.tr('/', '_')}.rb"
Rails.root.join('db', 'seeds', "#{name.pluralize.underscore.tr('/', '_')}.rb").to_s
end
end
end

View file

@ -35,12 +35,11 @@ log object update activity stream, if configured - will be executed automaticall
return true if !saved_changes?
ignored_attributes = self.class.instance_variable_get(:@activity_stream_attributes_ignored) || []
ignored_attributes += %i(created_at updated_at created_by_id updated_by_id)
ignored_attributes += %i[created_at updated_at created_by_id updated_by_id]
log = false
saved_changes.each do |key, _value|
saved_changes.each_key do |key|
next if ignored_attributes.include?(key.to_sym)
log = true
end
return true if !log

View file

@ -40,20 +40,18 @@ log object update history with all updated attributes, if configured - will be e
# new record also triggers update, so ignore new records
changes = saved_changes
if history_changes_last_done
history_changes_last_done.each do |key, value|
history_changes_last_done&.each do |key, value|
if changes.key?(key) && changes[key] == value
changes.delete(key)
end
end
end
self.history_changes_last_done = changes
#logger.info 'updated ' + self.changes.inspect
return if changes['id'] && !changes['id'][0]
ignored_attributes = self.class.instance_variable_get(:@history_attributes_ignored) || []
ignored_attributes += %i(created_at updated_at created_by_id updated_by_id)
ignored_attributes += %i[created_at updated_at created_by_id updated_by_id]
changes.each do |key, value|

View file

@ -84,7 +84,7 @@ returns
def search_index_data
attributes = {}
%w(name note).each do |key|
%w[name note].each do |key|
next if !self[key]
next if self[key].respond_to?('blank?') && self[key].blank?
attributes[key] = self[key]

View file

@ -108,11 +108,11 @@ returns
# get caller ids
caller_ids = []
attributes = record.attributes
attributes.each do |_attribute, value|
attributes.each_value do |value|
next if value.class != String
next if value.empty?
next if value.blank?
local_caller_ids = Cti::CallerId.extract_numbers(value)
next if local_caller_ids.empty?
next if local_caller_ids.blank?
caller_ids = caller_ids.concat(local_caller_ids)
end
@ -233,23 +233,23 @@ returns
if user
comment += user.fullname
end
elsif !record.comment.empty?
elsif record.comment.present?
comment += record.comment
end
if record.level == 'known'
if !from_comment_known.empty?
if from_comment_known.present?
from_comment_known += ','
end
from_comment_known += comment
else
if !from_comment_maybe.empty?
if from_comment_maybe.present?
from_comment_maybe += ','
end
from_comment_maybe += comment
end
end
return [from_comment_known, preferences_known] if !from_comment_known.empty?
return ["maybe #{from_comment_maybe}", preferences_maybe] if !from_comment_maybe.empty?
return [from_comment_known, preferences_known] if from_comment_known.present?
return ["maybe #{from_comment_maybe}", preferences_maybe] if from_comment_maybe.present?
nil
end

View file

@ -249,7 +249,7 @@ returns
assets = {}
list.each do |item|
next if !item.preferences
%w(from to).each do |direction|
%w[from to].each do |direction|
next if !item.preferences[direction]
item.preferences[direction].each do |caller_id|
next if !caller_id['user_id']

View file

@ -47,7 +47,7 @@ check and if channel not exists reset configured channels for email addresses
return true if email.blank?
self.email = email.downcase.strip
raise Exceptions::UnprocessableEntity, 'Invalid email' if email !~ /@/
raise Exceptions::UnprocessableEntity, 'Invalid email' if email =~ /\s/
raise Exceptions::UnprocessableEntity, 'Invalid email' if email.match?(/\s/)
true
end

View file

@ -68,7 +68,7 @@ class ExternalSync < ApplicationModel
break if !value
storable = value.class.ancestors.any? do |ancestor|
%w(String Integer Float Bool Array).include?(ancestor.to_s)
%w[String Integer Float Bool Array].include?(ancestor.to_s)
end
if storable

View file

@ -78,13 +78,11 @@ job.run(true)
self.running = true
save!
if tickets
tickets.each do |ticket|
tickets&.each do |ticket|
Transaction.execute(disable_notification: disable_notification, reset_user_id: true) do
ticket.perform_changes(perform, 'job')
end
end
end
self.running = false
self.last_run_at = Time.zone.now

View file

@ -36,7 +36,7 @@ returns
data = assets_of_selector('condition', data)
data = assets_of_selector('perform', data)
end
%w(created_by_id updated_by_id).each do |local_user_id|
%w[created_by_id updated_by_id].each do |local_user_id|
next if !self[ local_user_id ]
next if data[ User.to_app_model ][ self[ local_user_id ] ]
user = User.lookup(id: self[ local_user_id ])

View file

@ -71,7 +71,7 @@ all:
def self.load_from_file
version = Version.get
file = Rails.root.join("config/locales-#{version}.yml")
file = Rails.root.join('config', "locales-#{version}.yml")
return false if !File.exist?(file)
data = YAML.load_file(file)
to_database(data)
@ -107,7 +107,7 @@ all:
raise "Can't load locales from #{url}" if !result
raise "Can't load locales from #{url}: #{result.error}" if !result.success?
file = Rails.root.join("config/locales-#{version}.yml")
file = Rails.root.join('config', "locales-#{version}.yml")
File.open(file, 'w') do |out|
YAML.dump(result.data, out)
end

View file

@ -11,7 +11,7 @@ list all backend managed object
=end
def self.list_objects
%w(Ticket TicketArticle User Organization Group)
%w[Ticket TicketArticle User Organization Group]
end
=begin
@ -23,7 +23,7 @@ list all frontend managed object
=end
def self.list_frontend_objects
%w(Ticket User Organization Group)
%w[Ticket User Organization Group]
end
end

View file

@ -279,7 +279,7 @@ possible types
# if data_option has changed, store it for next migration
if !force
[:name, :display, :data_type, :position, :active].each do |key|
%i[name display data_type position active].each do |key|
next if record[key] == data[key]
data[:to_config] = true
break
@ -441,7 +441,7 @@ returns:
tag: item.data_type,
#:null => item.null,
}
if item.data_option[:permission] && item.data_option[:permission].any?
if item.data_option[:permission]&.any?
next if !user
hint = false
item.data_option[:permission].each do |permission|
@ -459,7 +459,7 @@ returns:
permission_options.each do |permission, options|
if permission == '-all-'
data[:screen][screen] = options
elsif user && user.permissions?(permission)
elsif user&.permissions?(permission)
data[:screen][screen] = options
end
end
@ -535,7 +535,7 @@ returns
=end
def self.pending_migration?
return false if migrations.empty?
return false if migrations.blank?
true
end
@ -601,21 +601,21 @@ to send no browser reload event, pass false
end
data_type = nil
if attribute.data_type =~ /^input|select|tree_select|richtext|textarea|checkbox$/
if attribute.data_type.match?(/^input|select|tree_select|richtext|textarea|checkbox$/)
data_type = :string
elsif attribute.data_type =~ /^integer|user_autocompletion$/
elsif attribute.data_type.match?(/^integer|user_autocompletion$/)
data_type = :integer
elsif attribute.data_type =~ /^boolean|active$/
elsif attribute.data_type.match?(/^boolean|active$/)
data_type = :boolean
elsif attribute.data_type =~ /^datetime$/
elsif attribute.data_type.match?(/^datetime$/)
data_type = :datetime
elsif attribute.data_type =~ /^date$/
elsif attribute.data_type.match?(/^date$/)
data_type = :date
end
# change field
if model.column_names.include?(attribute.name)
if attribute.data_type =~ /^input|select|tree_select|richtext|textarea|checkbox$/
if attribute.data_type.match?(/^input|select|tree_select|richtext|textarea|checkbox$/)
ActiveRecord::Migration.change_column(
model.table_name,
attribute.name,
@ -623,7 +623,7 @@ to send no browser reload event, pass false
limit: attribute.data_option[:maxlength],
null: true
)
elsif attribute.data_type =~ /^integer|user_autocompletion|datetime|date$/
elsif attribute.data_type.match?(/^integer|user_autocompletion|datetime|date$/)
ActiveRecord::Migration.change_column(
model.table_name,
attribute.name,
@ -631,7 +631,7 @@ to send no browser reload event, pass false
default: attribute.data_option[:default],
null: true
)
elsif attribute.data_type =~ /^boolean|active$/
elsif attribute.data_type.match?(/^boolean|active$/)
ActiveRecord::Migration.change_column(
model.table_name,
attribute.name,
@ -654,7 +654,7 @@ to send no browser reload event, pass false
end
# create field
if attribute.data_type =~ /^input|select|tree_select|richtext|textarea|checkbox$/
if attribute.data_type.match?(/^input|select|tree_select|richtext|textarea|checkbox$/)
ActiveRecord::Migration.add_column(
model.table_name,
attribute.name,
@ -662,7 +662,7 @@ to send no browser reload event, pass false
limit: attribute.data_option[:maxlength],
null: true
)
elsif attribute.data_type =~ /^integer|user_autocompletion$/
elsif attribute.data_type.match?(/^integer|user_autocompletion$/)
ActiveRecord::Migration.add_column(
model.table_name,
attribute.name,
@ -670,7 +670,7 @@ to send no browser reload event, pass false
default: attribute.data_option[:default],
null: true
)
elsif attribute.data_type =~ /^boolean|active$/
elsif attribute.data_type.match?(/^boolean|active$/)
ActiveRecord::Migration.add_column(
model.table_name,
attribute.name,
@ -678,7 +678,7 @@ to send no browser reload event, pass false
default: attribute.data_option[:default],
null: true
)
elsif attribute.data_type =~ /^datetime|date$/
elsif attribute.data_type.match?(/^datetime|date$/)
ActiveRecord::Migration.add_column(
model.table_name,
attribute.name,
@ -727,27 +727,21 @@ to send no browser reload event, pass false
def check_name
return if !name
if name =~ /_(id|ids)$/i || name =~ /^id$/i
raise 'Name can\'t get used, *_id and *_ids are not allowed'
elsif name =~ /\s/
raise 'Spaces in name are not allowed'
elsif name !~ /^[a-z0-9_]+$/
raise 'Only letters from a-z, numbers from 0-9, and _ are allowed'
elsif name !~ /[a-z]/
raise 'At least one letters is needed'
elsif name =~ /^(destroy|true|false|integer|select|drop|create|alter|index|table|varchar|blob|date|datetime|timestamp)$/
raise "#{name} is a reserved word, please choose a different one"
raise 'Name can\'t get used, *_id and *_ids are not allowed' if name.match?(/_(id|ids)$/i) || name.match?(/^id$/i)
raise 'Spaces in name are not allowed' if name.match?(/\s/)
raise 'Only letters from a-z, numbers from 0-9, and _ are allowed' if !name.match?(/^[a-z0-9_]+$/)
raise 'At least one letters is needed' if !name.match?(/[a-z]/)
# do not allow model method names as attributes
else
model = Kernel.const_get(object_lookup.name)
record = model.new
if record.respond_to?(name.to_sym) && !record.attributes.key?(name)
reserved_words = %w[destroy true false integer select drop create alter index table varchar blob date datetime timestamp]
raise "#{name} is a reserved word, please choose a different one" if name.match?(/^(#{reserved_words.join('|')})$/)
record = object_lookup.name.constantize.new
return true if !record.respond_to?(name.to_sym)
return true if record.attributes.key?(name)
raise "#{name} is a reserved word, please choose a different one"
end
end
true
end
def check_editable
return if editable
@ -783,7 +777,7 @@ to send no browser reload event, pass false
end
if data_type == 'integer'
[:min, :max].each do |item|
%i[min max].each do |item|
raise "Need data_option[#{item.inspect}] param" if !data_option[item]
raise "Invalid data_option[#{item.inspect}] param #{data_option[item]}" if data_option[item].to_s !~ /^\d+?$/
end
@ -817,6 +811,7 @@ to send no browser reload event, pass false
raise 'Need data_option[:diff] param in days' if data_option[:diff].nil?
end
true
end
end

View file

@ -1,5 +1,3 @@
# encoding: utf-8
class Observer::Chat::Leave::BackgroundJob
def initialize(chat_session_id, client_id, session)
@chat_session_id = chat_session_id

View file

@ -27,7 +27,7 @@ class Observer::Organization::RefObjectTouch < ActiveRecord::Observer
Ticket.select('id').where(organization_id: record.id).pluck(:id).each do |ticket_id|
ticket = Ticket.find(ticket_id)
ticket.with_lock do
ticket.touch
ticket.touch # rubocop:disable Rails/SkipsModelValidations
end
end
@ -35,7 +35,7 @@ class Observer::Organization::RefObjectTouch < ActiveRecord::Observer
User.select('id').where(organization_id: record.id).pluck(:id).each do |user_id|
user = User.find(user_id)
user.with_lock do
user.touch
user.touch # rubocop:disable Rails/SkipsModelValidations
end
end
true

View file

@ -33,9 +33,9 @@ class Observer::Sla::TicketRebuildEscalation < ActiveRecord::Observer
changed = false
fields_to_check = nil
fields_to_check = if record.class == Sla
%w(condition calendar_id first_response_time update_time solution_time)
%w[condition calendar_id first_response_time update_time solution_time]
else
%w(timezone business_hours default ical_url public_holidays)
%w[timezone business_hours default ical_url public_holidays]
end
fields_to_check.each do |item|
next if !record.saved_change_to_attribute(item)

View file

@ -1,6 +1,5 @@
class Observer::Sla::TicketRebuildEscalation::BackgroundJob
def initialize(_sla_id)
end
def initialize(_sla_id); end
def perform
Cache.delete('SLA::List::Active')

View file

@ -10,7 +10,7 @@ class Observer::Ticket::Article::CommunicateEmail < ActiveRecord::Observer
# only do send email if article got created via application_server (e. g. not
# if article and sender type is set via *.postmaster)
return if ApplicationHandleInfo.current.split('.')[1] == 'postmaster'
return if ApplicationHandleInfo.postmaster?
# if sender is customer, do not communicate
return if !record.sender_id

View file

@ -90,7 +90,7 @@ class Observer::Ticket::Article::CommunicateEmail::BackgroundJob
# add history record
recipient_list = ''
[:to, :cc].each do |key|
%i[to cc].each do |key|
next if !record[key]
next if record[key] == ''
@ -130,7 +130,7 @@ class Observer::Ticket::Article::CommunicateEmail::BackgroundJob
if local_record.preferences['delivery_retry'] > 3
recipient_list = ''
[:to, :cc].each do |key|
%i[to cc].each do |key|
next if !local_record[key]
next if local_record[key] == ''

View file

@ -12,7 +12,7 @@ class Observer::Ticket::Article::CommunicateFacebook < ActiveRecord::Observer
# only do send email if article got created via application_server (e. g. not
# if article and sender type is set via *.postmaster)
return if ApplicationHandleInfo.current.split('.')[1] == 'postmaster'
return if ApplicationHandleInfo.postmaster?
# if sender is customer, do not communicate
return if !record.sender_id

View file

@ -10,7 +10,7 @@ class Observer::Ticket::Article::CommunicateTwitter < ActiveRecord::Observer
# only do send email if article got created via application_server (e. g. not
# if article and sender type is set via *.postmaster)
return if ApplicationHandleInfo.current.split('.')[1] == 'postmaster'
return if ApplicationHandleInfo.postmaster?
# if sender is customer, do not communicate
return if !record.sender_id

View file

@ -10,7 +10,7 @@ class Observer::Ticket::Article::FillupFromEmail < ActiveRecord::Observer
# only do fill of email from if article got created via application_server (e. g. not
# if article and sender type is set via *.postmaster)
return true if ApplicationHandleInfo.current.split('.')[1] == 'postmaster'
return if ApplicationHandleInfo.postmaster?
# if sender is customer, do not change anything
return true if !record.sender_id

View file

@ -10,7 +10,7 @@ class Observer::Ticket::Article::FillupFromGeneral < ActiveRecord::Observer
# only do fill of from if article got created via application_server (e. g. not
# if article and sender type is set via *.postmaster)
return true if ApplicationHandleInfo.current.split('.')[1] == 'postmaster'
return if ApplicationHandleInfo.postmaster?
# set from on all article types excluding email|twitter status|twitter direct-message|facebook feed post|facebook feed comment
return true if !record.type_id

View file

@ -10,7 +10,7 @@ class Observer::Ticket::Article::FillupFromOriginById < ActiveRecord::Observer
# only do fill of from if article got created via application_server (e. g. not
# if article and sender type is set via *.postmaster)
return if ApplicationHandleInfo.current.split('.')[1] == 'postmaster'
return if ApplicationHandleInfo.postmaster?
# check if origin_by_id exists
return if record.origin_by_id.present?

View file

@ -24,7 +24,7 @@ class Observer::Ticket::ArticleChanges < ActiveRecord::Observer
# save ticket
if !changed
record.ticket.touch
record.ticket.touch # rubocop:disable Rails/SkipsModelValidations
return
end
record.ticket.save
@ -38,7 +38,7 @@ class Observer::Ticket::ArticleChanges < ActiveRecord::Observer
# save ticket
if !changed
record.ticket.touch
record.ticket.touch # rubocop:disable Rails/SkipsModelValidations
return
end
record.ticket.save!

View file

@ -24,26 +24,24 @@ class Observer::Ticket::RefObjectTouch < ActiveRecord::Observer
cutomer_id_changed = record.saved_changes['customer_id']
if cutomer_id_changed && cutomer_id_changed[0] != cutomer_id_changed[1]
if cutomer_id_changed[0]
User.find(cutomer_id_changed[0]).touch
User.find(cutomer_id_changed[0]).touch # rubocop:disable Rails/SkipsModelValidations
end
end
# touch new/current customer
if record.customer
record.customer.touch
end
record.customer&.touch
# touch old organization if changed
organization_id_changed = record.saved_changes['organization_id']
if organization_id_changed && organization_id_changed[0] != organization_id_changed[1]
if organization_id_changed[0]
Organization.find(organization_id_changed[0]).touch
Organization.find(organization_id_changed[0]).touch # rubocop:disable Rails/SkipsModelValidations
end
end
# touch new/current organization
return true if !record.organization
record.organization.touch
record.organization.touch # rubocop:disable Rails/SkipsModelValidations
end
end

View file

@ -9,7 +9,7 @@ class Observer::Ticket::ResetNewState < ActiveRecord::Observer
return if Setting.get('import_mode')
# only change state if not processed via postmaster
return if ApplicationHandleInfo.current.split('.')[1] == 'postmaster'
return if ApplicationHandleInfo.postmaster?
# if article in internal
return true if record.internal

View file

@ -33,14 +33,14 @@ class Observer::Transaction < ActiveRecord::Observer
sync_backends = []
Setting.where(area: 'Transaction::Backend::Sync').order(:name).each do |setting|
backend = Setting.get(setting.name)
next if params[:disable] && params[:disable].include?(backend)
next if params[:disable]&.include?(backend)
sync_backends.push Kernel.const_get(backend)
end
# get uniq objects
list_objects = get_uniq_changes(list)
list_objects.each do |_object, objects|
objects.each do |_id, item|
list_objects.each_value do |objects|
objects.each_value do |item|
# execute sync backends
sync_backends.each do |backend|
@ -215,7 +215,7 @@ class Observer::Transaction < ActiveRecord::Observer
end
# do not send anything if nothing has changed
return true if real_changes.empty?
return true if real_changes.blank?
changed_by_id = nil
changed_by_id = if record.respond_to?('updated_by_id')

View file

@ -16,7 +16,7 @@ class Observer::User::Geo < ActiveRecord::Observer
# check if geo need to be updated
def check_geo(record)
location = %w(address street zip city country)
location = %w[address street zip city country]
# check if geo update is needed based on old/new location
if record.id
@ -45,7 +45,7 @@ class Observer::User::Geo < ActiveRecord::Observer
# update geo data of user
def geo_update(record)
address = ''
location = %w(address street zip city country)
location = %w[address street zip city country]
location.each do |item|
next if record[item].blank?
if address.present?

View file

@ -29,7 +29,7 @@ class Observer::User::RefObjectTouch < ActiveRecord::Observer
# featrue used for different propose, do not touch references
if User.where(organization_id: organization_id_changed[0]).count < 100
organization = Organization.find(organization_id_changed[0])
organization.touch
organization.touch # rubocop:disable Rails/SkipsModelValidations
member_ids = organization.member_ids
end
end
@ -40,7 +40,7 @@ class Observer::User::RefObjectTouch < ActiveRecord::Observer
# featrue used for different propose, do not touch references
if User.where(organization_id: record.organization_id).count < 100
record.organization.touch
record.organization.touch # rubocop:disable Rails/SkipsModelValidations
member_ids += record.organization.member_ids
end
end
@ -48,7 +48,7 @@ class Observer::User::RefObjectTouch < ActiveRecord::Observer
# touch old/current customer
member_ids.uniq.each do |user_id|
next if user_id == record.id
User.find(user_id).touch
User.find(user_id).touch # rubocop:disable Rails/SkipsModelValidations
end
true
end

View file

@ -55,7 +55,7 @@ returns
data[ app_model_organization ][ id ] = local_attributes
end
%w(created_by_id updated_by_id).each do |local_user_id|
%w[created_by_id updated_by_id].each do |local_user_id|
next if !self[ local_user_id ]
next if data[ app_model_user ][ self[ local_user_id ] ]
user = User.lookup(id: self[ local_user_id ])

View file

@ -17,26 +17,47 @@ class Overview < ApplicationModel
validates :name, presence: true
before_create :fill_link_on_create, :fill_prio
before_update :fill_link_on_update
before_update :fill_link_on_update, :rearrangement
private
def rearrangement
return true if !changes['prio']
prio = 0
Overview.all.order(prio: :asc, updated_at: :desc).pluck(:id).each do |overview_id|
prio += 1
next if id == overview_id
Overview.without_callback(:update, :before, :rearrangement) do
overview = Overview.find(overview_id)
next if overview.prio == prio
overview.prio = prio
overview.save!
end
end
end
def fill_prio
return true if prio
self.prio = 9999
return true if prio.present?
self.prio = Overview.count + 1
true
end
def fill_link_on_create
return true if link.present?
self.link = link_name(name)
self.link = if link.present?
link_name(link)
else
link_name(name)
end
true
end
def fill_link_on_update
return true if !changes['name']
return true if changes['link']
self.link = link_name(name)
return true if !changes['name'] && !changes['link']
self.link = if link.present?
link_name(link)
else
link_name(name)
end
true
end
@ -45,17 +66,21 @@ class Overview < ApplicationModel
local_link = local_link.parameterize(separator: '_')
local_link.gsub!(/\s/, '_')
local_link.gsub!(/_+/, '_')
local_link = URI.escape(local_link)
local_link = CGI.escape(local_link)
if local_link.blank?
local_link = id || rand(999)
end
check = true
count = 0
local_lookup_link = local_link
while check
exists = Overview.find_by(link: local_link)
if exists && exists.id != id
local_link = "#{local_link}_#{rand(999)}"
count += 1
exists = Overview.find_by(link: local_lookup_link)
if exists && exists.id != id # rubocop:disable Style/SafeNavigation
local_lookup_link = "#{local_link}_#{count}"
else
check = false
local_link = local_lookup_link
end
end
local_link

View file

@ -34,19 +34,15 @@ returns
end
if !data[ app_model_overview ][ id ]
data[ app_model_overview ][ id ] = attributes_with_association_ids
if user_ids
user_ids.each do |local_user_id|
user_ids&.each do |local_user_id|
next if data[ app_model_user ][ local_user_id ]
user = User.lookup(id: local_user_id)
next if !user
data = user.assets(data)
end
end
data = assets_of_selector('condition', data)
end
%w(created_by_id updated_by_id).each do |local_user_id|
%w[created_by_id updated_by_id].each do |local_user_id|
next if !self[ local_user_id ]
next if data[ app_model_user ][ self[ local_user_id ] ]
user = User.lookup(id: self[ local_user_id ])

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