Updated rubocop to latest version (0.59.2) and applied required changes.

This commit is contained in:
Thorsten Eckel 2018-10-09 08:17:41 +02:00
parent 3d4d5414f1
commit 9af50f2a4e
536 changed files with 1327 additions and 340 deletions

View file

@ -1,5 +1,5 @@
# Default enabled cops # Default enabled cops
# https://github.com/bbatsov/rubocop/blob/master/config/enabled.yml # https://github.com/rubocop-hq/rubocop/blob/master/config/default.yml
inherit_from: .rubocop_todo.yml inherit_from: .rubocop_todo.yml
@ -144,6 +144,10 @@ Style/BracesAroundHashParameters:
Description: 'Enforce braces style around hash parameters.' Description: 'Enforce braces style around hash parameters.'
Enabled: false Enabled: false
Rails/BulkChangeTable:
Description: 'Check whether alter queries are combinable.'
Enabled: false
Rails/FindEach: Rails/FindEach:
Description: 'Prefer all.find_each over all.find.' Description: 'Prefer all.find_each over all.find.'
Enabled: false Enabled: false

View file

@ -40,6 +40,14 @@ Rails/ApplicationRecord:
Description: 'Check that models subclass ApplicationRecord.' Description: 'Check that models subclass ApplicationRecord.'
Enabled: false Enabled: false
# Browser-Tests inherit from TestCase < Test::Unit::TestCase
# which does not provide assert_not
Rails/AssertNot:
Description: 'Use `assert_not` instead of `assert !`.'
Enabled: true
Exclude:
- "test/browser/*"
Rails/CreateTableWithTimestamps: Rails/CreateTableWithTimestamps:
Description: >- Description: >-
Checks the migration for which timestamps are not included Checks the migration for which timestamps are not included

View file

@ -203,6 +203,7 @@ GEM
ice_cube (0.16.2) ice_cube (0.16.2)
inflection (1.0.0) inflection (1.0.0)
interception (0.5) interception (0.5)
jaro_winkler (1.5.1)
json (2.1.0) json (2.1.0)
jwt (1.5.6) jwt (1.5.6)
kgio (2.11.0) kgio (2.11.0)
@ -293,12 +294,12 @@ GEM
omniauth (~> 1.5) omniauth (~> 1.5)
omniauth-oauth2 (>= 1.4.0) omniauth-oauth2 (>= 1.4.0)
parallel (1.12.1) parallel (1.12.1)
parser (2.5.0.5) parser (2.5.1.2)
ast (~> 2.4.0) ast (~> 2.4.0)
pg (0.21.0) pg (0.21.0)
pluginator (1.5.0) pluginator (1.5.0)
power_assert (1.1.1) power_assert (1.1.1)
powerpack (0.1.1) powerpack (0.1.2)
pre-commit (0.37.0) pre-commit (0.37.0)
pluginator (~> 1.5) pluginator (~> 1.5)
pry (0.11.3) pry (0.11.3)
@ -377,14 +378,15 @@ GEM
rspec-mocks (~> 3.8.0) rspec-mocks (~> 3.8.0)
rspec-support (~> 3.8.0) rspec-support (~> 3.8.0)
rspec-support (3.8.0) rspec-support (3.8.0)
rubocop (0.54.0) rubocop (0.59.2)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10) parallel (~> 1.10)
parser (>= 2.5) parser (>= 2.5, != 2.5.1.1)
powerpack (~> 0.1) powerpack (~> 0.1)
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1) unicode-display_width (~> 1.0, >= 1.0.1)
ruby-progressbar (1.9.0) ruby-progressbar (1.10.0)
ruby_dep (1.5.0) ruby_dep (1.5.0)
rubyzip (1.2.2) rubyzip (1.2.2)
safe_yaml (1.0.4) safe_yaml (1.0.4)
@ -463,7 +465,7 @@ GEM
unf (0.1.4) unf (0.1.4)
unf_ext unf_ext
unf_ext (0.0.7.5) unf_ext (0.0.7.5)
unicode-display_width (1.3.0) unicode-display_width (1.4.0)
unicorn (5.3.1) unicorn (5.3.1)
kgio (~> 2.6) kgio (~> 2.6)
raindrops (~> 0.7) raindrops (~> 0.7)

View file

@ -15,10 +15,12 @@ module ApplicationController::Authenticates
permission: key, permission: key,
) )
return false if user return false if user
raise Exceptions::NotAuthorized, 'Not authorized (token)!' raise Exceptions::NotAuthorized, 'Not authorized (token)!'
end end
return false if current_user&.permissions?(key) return false if current_user&.permissions?(key)
raise Exceptions::NotAuthorized, 'Not authorized (user)!' raise Exceptions::NotAuthorized, 'Not authorized (user)!'
end end
@ -68,6 +70,7 @@ module ApplicationController::Authenticates
if Setting.get('api_password_access') == false if Setting.get('api_password_access') == false
raise Exceptions::NotAuthorized, 'API password access disabled!' raise Exceptions::NotAuthorized, 'API password access disabled!'
end end
user = User.authenticate(username, password) user = User.authenticate(username, password)
return authentication_check_prerequesits(user, 'basic_auth', auth_param) if user return authentication_check_prerequesits(user, 'basic_auth', auth_param) if user
end end
@ -79,6 +82,7 @@ module ApplicationController::Authenticates
if Setting.get('api_token_access') == false if Setting.get('api_token_access') == false
raise Exceptions::NotAuthorized, 'API token access disabled!' raise Exceptions::NotAuthorized, 'API token access disabled!'
end end
user = Token.check( user = Token.check(
action: 'api', action: 'api',
name: token_string, name: token_string,

View file

@ -5,6 +5,7 @@ module ApplicationController::ChecksMaintainance
def check_maintenance(user) def check_maintenance(user)
return false if !check_maintenance_only(user) return false if !check_maintenance_only(user)
raise Exceptions::NotAuthorized, 'Maintenance mode enabled!' raise Exceptions::NotAuthorized, 'Maintenance mode enabled!'
end end
@ -12,6 +13,7 @@ module ApplicationController::ChecksMaintainance
def check_maintenance_only(user) def check_maintenance_only(user)
return false if Setting.get('maintenance_mode') != true return false if Setting.get('maintenance_mode') != true
return false if user.permissions?('admin.maintenance') return false if user.permissions?('admin.maintenance')
Rails.logger.info "Maintenance mode enabled, denied login for user #{user.login}, it's no admin user." Rails.logger.info "Maintenance mode enabled, denied login for user #{user.login}, it's no admin user."
true true
end end

View file

@ -7,6 +7,7 @@ module ApplicationController::HandlesDevices
def user_device_check def user_device_check
return false if !user_device_log(current_user, 'session') return false if !user_device_log(current_user, 'session')
true true
end end
@ -39,6 +40,7 @@ module ApplicationController::HandlesDevices
# if ip has not changed and ttl in still valid # if ip has not changed and ttl in still valid
remote_ip = ENV['TEST_REMOTE_IP'] || request.remote_ip remote_ip = ENV['TEST_REMOTE_IP'] || request.remote_ip
return true if time_to_check == false && session[:user_device_remote_ip] == remote_ip return true if time_to_check == false && session[:user_device_remote_ip] == remote_ip
session[:user_device_remote_ip] = remote_ip session[:user_device_remote_ip] = remote_ip
# for sessions we need the fingperprint # for sessions we need the fingperprint
@ -46,6 +48,7 @@ module ApplicationController::HandlesDevices
if !session[:user_device_updated_at] && !params[:fingerprint] && !session[:user_device_fingerprint] if !session[:user_device_updated_at] && !params[:fingerprint] && !session[:user_device_fingerprint]
raise Exceptions::UnprocessableEntity, 'Need fingerprint param!' raise Exceptions::UnprocessableEntity, 'Need fingerprint param!'
end end
if params[:fingerprint] if params[:fingerprint]
UserDevice.fingerprint_validation(params[:fingerprint]) UserDevice.fingerprint_validation(params[:fingerprint])
session[:user_device_fingerprint] = params[:fingerprint] session[:user_device_fingerprint] = params[:fingerprint]

View file

@ -17,6 +17,7 @@ module ApplicationController::HasResponseExtentions
return true if params[:full] == 'true' return true if params[:full] == 'true'
return true if params[:full] == 1 return true if params[:full] == 1
return true if params[:full] == '1' return true if params[:full] == '1'
false false
end end
@ -25,6 +26,7 @@ module ApplicationController::HasResponseExtentions
return true if params[:all] == 'true' return true if params[:all] == 'true'
return true if params[:all] == 1 return true if params[:all] == 1
return true if params[:all] == '1' return true if params[:all] == '1'
false false
end end

View file

@ -10,6 +10,7 @@ module ApplicationController::HasUser
def current_user def current_user
user_on_behalf = current_user_on_behalf user_on_behalf = current_user_on_behalf
return user_on_behalf if user_on_behalf return user_on_behalf if user_on_behalf
current_user_real current_user_real
end end
@ -20,6 +21,7 @@ module ApplicationController::HasUser
def current_user_real def current_user_real
return @_current_user if @_current_user return @_current_user if @_current_user
return if !session[:user_id] return if !session[:user_id]
@_current_user = User.lookup(id: session[:user_id]) @_current_user = User.lookup(id: session[:user_id])
end end
@ -49,6 +51,7 @@ module ApplicationController::HasUser
search_attributes[field] = request.headers['X-On-Behalf-Of'] search_attributes[field] = request.headers['X-On-Behalf-Of']
@_user_on_behalf = User.find_by(search_attributes) @_user_on_behalf = User.find_by(search_attributes)
next if !@_user_on_behalf next if !@_user_on_behalf
return @_user_on_behalf return @_user_on_behalf
end end
@ -89,11 +92,13 @@ module ApplicationController::HasUser
# fill user agent # fill user agent
return if session[:user_agent] return if session[:user_agent]
session[:user_agent] = request.env['HTTP_USER_AGENT'] session[:user_agent] = request.env['HTTP_USER_AGENT']
end end
def valid_session_with_user def valid_session_with_user
return true if current_user return true if current_user
raise Exceptions::UnprocessableEntity, 'No session user!' raise Exceptions::UnprocessableEntity, 'No session user!'
end end
end end

View file

@ -24,6 +24,7 @@ module ApplicationController::LogsHttpAccess
} }
request.headers.each do |key, value| request.headers.each do |key, value|
next if key[0, 5] != 'HTTP_' next if key[0, 5] != 'HTTP_'
request_data[:content] += if key == 'HTTP_COOKIE' request_data[:content] += if key == 'HTTP_COOKIE'
"#{key}: xxxxx\n" "#{key}: xxxxx\n"
else else

View file

@ -10,6 +10,7 @@ module ApplicationController::PreventsCsrf
def set_csrf_token_headers def set_csrf_token_headers
return true if @_auth_type.present? && @_auth_type != 'session' return true if @_auth_type.present? && @_auth_type != 'session'
headers['CSRF-TOKEN'] = form_authenticity_token headers['CSRF-TOKEN'] = form_authenticity_token
end end
@ -19,6 +20,7 @@ module ApplicationController::PreventsCsrf
return true if request.head? return true if request.head?
return true if %w[token_auth basic_auth].include?(@_auth_type) return true if %w[token_auth basic_auth].include?(@_auth_type)
return true if valid_authenticity_token?(session, params[:authenticity_token] || request.headers['X-CSRF-Token']) return true if valid_authenticity_token?(session, params[:authenticity_token] || request.headers['X-CSRF-Token'])
logger.info 'CSRF token verification failed' logger.info 'CSRF token verification failed'
raise Exceptions::NotAuthorized, 'CSRF token verification failed!' raise Exceptions::NotAuthorized, 'CSRF token verification failed!'
end end

View file

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

View file

@ -11,6 +11,7 @@ module ApplicationController::SetsHeaders
# For all responses in this controller, return the CORS access control headers. # For all responses in this controller, return the CORS access control headers.
def set_access_control_headers def set_access_control_headers
return if @_auth_type != 'token_auth' && @_auth_type != 'basic_auth' return if @_auth_type != 'token_auth' && @_auth_type != 'basic_auth'
set_access_control_headers_execute set_access_control_headers_execute
end end
@ -26,11 +27,13 @@ module ApplicationController::SetsHeaders
# text/plain. # text/plain.
def cors_preflight_check def cors_preflight_check
return true if @_auth_type != 'token_auth' && @_auth_type != 'basic_auth' return true if @_auth_type != 'token_auth' && @_auth_type != 'basic_auth'
cors_preflight_check_execute cors_preflight_check_execute
end end
def cors_preflight_check_execute def cors_preflight_check_execute
return true if request.method != 'OPTIONS' return true if request.method != 'OPTIONS'
headers['Access-Control-Allow-Origin'] = '*' headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, GET, PUT, DELETE, PATCH, OPTIONS' headers['Access-Control-Allow-Methods'] = 'POST, GET, PUT, DELETE, PATCH, OPTIONS'
headers['Access-Control-Allow-Headers'] = 'Content-Type, Depth, User-Agent, X-File-Size, X-Requested-With, If-Modified-Since, X-File-Name, Cache-Control, Accept-Language' headers['Access-Control-Allow-Headers'] = 'Content-Type, Depth, User-Agent, X-File-Size, X-Requested-With, If-Modified-Since, X-File-Name, Cache-Control, Accept-Language'

View file

@ -29,6 +29,7 @@ class ChannelsEmailController < ApplicationController
end end
EmailAddress.all.each do |email_address| EmailAddress.all.each do |email_address|
next if system_online_service && email_address.preferences && email_address.preferences['online_service_disable'] next if system_online_service && email_address.preferences && email_address.preferences['online_service_disable']
email_address_ids.push email_address.id email_address_ids.push email_address.id
assets = email_address.assets(assets) assets = email_address.assets(assets)
if !email_address.channel_id || !email_address.active || !Channel.find_by(id: email_address.channel_id) if !email_address.channel_id || !email_address.active || !Channel.find_by(id: email_address.channel_id)
@ -256,6 +257,7 @@ class ChannelsEmailController < ApplicationController
next if channel.options[:inbound][:options][:user] != result[:setting][:inbound][:options][:user] next if channel.options[:inbound][:options][:user] != result[:setting][:inbound][:options][:user]
next if channel.options[:inbound][:options][:folder].to_s != result[:setting][:inbound][:options][:folder].to_s next if channel.options[:inbound][:options][:folder].to_s != result[:setting][:inbound][:options][:folder].to_s
next if channel.id.to_s == channel_id.to_s next if channel.id.to_s == channel_id.to_s
render json: { render json: {
result: 'duplicate', result: 'duplicate',
message: 'Account already exists!', message: 'Account already exists!',
@ -267,6 +269,7 @@ class ChannelsEmailController < ApplicationController
def check_online_service def check_online_service
return true if !Setting.get('system_online_service') return true if !Setting.get('system_online_service')
raise Exceptions::NotAuthorized raise Exceptions::NotAuthorized
end end

View file

@ -29,6 +29,7 @@ module ChecksUserAttributesByCurrentUserPermission
return true if params[:id].present? return true if params[:id].present?
return true if params[:role_ids] return true if params[:role_ids]
return true if params[:roles] return true if params[:roles]
params[:role_ids] = Role.signup_role_ids params[:role_ids] = Role.signup_role_ids
true true
end end

View file

@ -13,8 +13,10 @@ module ClonesTicketArticleAttachments
attachments = [] attachments = []
article.attachments.each do |new_attachment| article.attachments.each do |new_attachment|
next if new_attachment.preferences['content-alternative'] == true next if new_attachment.preferences['content-alternative'] == true
if article.content_type.present? && article.content_type =~ %r{text/html}i if article.content_type.present? && article.content_type =~ %r{text/html}i
next if new_attachment.preferences['content_disposition'].present? && new_attachment.preferences['content_disposition'] !~ /inline/ next if new_attachment.preferences['content_disposition'].present? && new_attachment.preferences['content_disposition'] !~ /inline/
if new_attachment.preferences['Content-ID'].present? && article.body.present? if new_attachment.preferences['Content-ID'].present? && article.body.present?
next if article.body.match?(/#{Regexp.quote(new_attachment.preferences['Content-ID'])}/i) next if article.body.match?(/#{Regexp.quote(new_attachment.preferences['Content-ID'])}/i)
end end
@ -22,10 +24,12 @@ module ClonesTicketArticleAttachments
already_added = false already_added = false
existing_attachments.each do |existing_attachment| existing_attachments.each do |existing_attachment|
next if existing_attachment.filename != new_attachment.filename || existing_attachment.size != new_attachment.size next if existing_attachment.filename != new_attachment.filename || existing_attachment.size != new_attachment.size
already_added = true already_added = true
break break
end end
next if already_added == true next if already_added == true
file = Store.add( file = Store.add(
object: 'UploadCache', object: 'UploadCache',
o_id: params[:form_id], o_id: params[:form_id],

View file

@ -84,12 +84,14 @@ module CreatesTicketArticles
# validation # validation
['mime-type', 'filename', 'data'].each do |key| ['mime-type', 'filename', 'data'].each do |key|
next if attachment[key] next if attachment[key]
raise Exceptions::UnprocessableEntity, "Attachment needs '#{key}' param for attachment with index '#{index}'" raise Exceptions::UnprocessableEntity, "Attachment needs '#{key}' param for attachment with index '#{index}'"
end end
preferences = {} preferences = {}
['charset', 'mime-type'].each do |key| ['charset', 'mime-type'].each do |key|
next if !attachment[key] next if !attachment[key]
store_key = key.tr('-', '_').camelize.gsub(/(.+)([A-Z])/, '\1_\2').tr('_', '-') store_key = key.tr('-', '_').camelize.gsub(/(.+)([A-Z])/, '\1_\2').tr('_', '-')
preferences[store_key] = attachment[key] preferences[store_key] = attachment[key]
end end

View file

@ -58,6 +58,7 @@ class ExternalCredentialsController < ApplicationController
if params[:id].present? && ExternalCredential.exists?(params[:id]) if params[:id].present? && ExternalCredential.exists?(params[:id])
external_credential = ExternalCredential.find(params[:id]) external_credential = ExternalCredential.find(params[:id])
raise 'No such ExternalCredential!' if !external_credential raise 'No such ExternalCredential!' if !external_credential
authentication_check(permission: ["admin.channel_#{external_credential.name}"]) authentication_check(permission: ["admin.channel_#{external_credential.name}"])
return return
end end

View file

@ -223,6 +223,7 @@ class FirstStepsController < ApplicationController
def access? def access?
return true if current_user.permissions?(['admin', 'ticket.agent']) return true if current_user.permissions?(['admin', 'ticket.agent'])
render json: [] render json: []
false false
end end
@ -243,10 +244,12 @@ class FirstStepsController < ApplicationController
test_ticket_active = false test_ticket_active = false
end end
return result if test_ticket_active return result if test_ticket_active
result.each do |item| result.each do |item|
items = [] items = []
item[:items].each do |local_item| item[:items].each do |local_item|
next if local_item[:name] == 'Create a Test Ticket' next if local_item[:name] == 'Create a Test Ticket'
items.push local_item items.push local_item
end end
item[:items] = items item[:items] = items

View file

@ -230,6 +230,7 @@ class FormController < ApplicationController
def fingerprint_exists? def fingerprint_exists?
return true if params[:fingerprint].present? && params[:fingerprint].length > 30 return true if params[:fingerprint].present? && params[:fingerprint].length > 30
Rails.logger.info 'No fingerprint given!' Rails.logger.info 'No fingerprint given!'
response_access_deny response_access_deny
false false
@ -238,6 +239,7 @@ class FormController < ApplicationController
def enabled? def enabled?
return true if params[:test] && current_user && current_user.permissions?('admin.channel_formular') return true if params[:test] && current_user && current_user.permissions?('admin.channel_formular')
return true if Setting.get('form_ticket_create') return true if Setting.get('form_ticket_create')
response_access_deny response_access_deny
false false
end end

View file

@ -103,6 +103,7 @@ class ImportOtrsController < ApplicationController
def import_start def import_start
return if setup_done_response return if setup_done_response
Setting.set('import_mode', true) Setting.set('import_mode', true)
welcome = Import::OTRS.connection_test welcome = Import::OTRS.connection_test
if !welcome if !welcome
@ -130,6 +131,7 @@ class ImportOtrsController < ApplicationController
dynamic_fields = Import::OTRS::Requester.load('DynamicField') dynamic_fields = Import::OTRS::Requester.load('DynamicField')
dynamic_fields.each do |dynamic_field| dynamic_fields.each do |dynamic_field|
next if dynamic_field['ValidID'].to_i != 1 next if dynamic_field['ValidID'].to_i != 1
dynamic_field_count += 1 dynamic_field_count += 1
end end
if dynamic_field_count > 20 if dynamic_field_count > 20
@ -140,6 +142,7 @@ class ImportOtrsController < ApplicationController
sys_configs = Import::OTRS::Requester.load('SysConfig') sys_configs = Import::OTRS::Requester.load('SysConfig')
sys_configs.each do |sys_config| sys_configs.each do |sys_config|
next if sys_config['Key'] != 'Process' next if sys_config['Key'] != 'Process'
issues.push 'otrsProcesses' issues.push 'otrsProcesses'
end end
@ -176,6 +179,7 @@ class ImportOtrsController < ApplicationController
if !setup_done if !setup_done
return false return false
end end
render json: { render json: {
setup_done: true, setup_done: true,
} }

View file

@ -93,6 +93,7 @@ class ImportZendeskController < ApplicationController
def import_start def import_start
return if setup_done_response return if setup_done_response
Setting.set('import_mode', true) Setting.set('import_mode', true)
Setting.set('import_backend', 'zendesk') Setting.set('import_backend', 'zendesk')
@ -129,6 +130,7 @@ class ImportZendeskController < ApplicationController
if !setup_done if !setup_done
return false return false
end end
render json: { render json: {
setup_done: true, setup_done: true,
} }

View file

@ -54,6 +54,7 @@ UserAgent: #{request.env['HTTP_USER_AGENT']}
ticket_ids_found.each do |ticket_id| ticket_ids_found.each do |ticket_id|
ticket = Ticket.find_by(id: ticket_id) ticket = Ticket.find_by(id: ticket_id)
next if !ticket next if !ticket
article = Ticket::Article.create!( article = Ticket::Article.create!(
ticket_id: ticket_id, ticket_id: ticket_id,
type_id: Ticket::Article::Type.find_by(name: 'web').id, type_id: Ticket::Article::Type.find_by(name: 'web').id,
@ -84,6 +85,7 @@ UserAgent: #{request.env['HTTP_USER_AGENT']}
ticket_ids_found.each do |ticket_id| ticket_ids_found.each do |ticket_id|
ticket = Ticket.find_by(id: ticket_id) ticket = Ticket.find_by(id: ticket_id)
next if !ticket next if !ticket
ticket.state_id = auto_close_state_id ticket.state_id = auto_close_state_id
ticket.save! ticket.save!
end end

View file

@ -48,6 +48,7 @@ class Integration::CtiController < ApplicationController
routing_table.each do |row| routing_table.each do |row|
dest = row[:dest].gsub(/\*/, '.+?') dest = row[:dest].gsub(/\*/, '.+?')
next if to !~ /^#{dest}$/ next if to !~ /^#{dest}$/
from = row[:caller_id] from = row[:caller_id]
data = { data = {
action: 'dial', action: 'dial',

View file

@ -19,6 +19,7 @@ class Integration::LdapController < ApplicationController
rescue => e rescue => e
# workaround for issue #1114 # workaround for issue #1114
raise if !e.message.end_with?(', 48, Inappropriate Authentication') raise if !e.message.end_with?(', 48, Inappropriate Authentication')
# return empty result # return empty result
{} {}
end end

View file

@ -14,6 +14,7 @@ class Integration::SipgateController < ApplicationController
# check if call need to be blocked # check if call need to be blocked
block_caller_ids.each do |item| block_caller_ids.each do |item|
next if item[:caller_id] != params['from'] next if item[:caller_id] != params['from']
xml = Builder::XmlMarkup.new(indent: 2) xml = Builder::XmlMarkup.new(indent: 2)
xml.instruct! xml.instruct!
content = xml.Response(onHangup: url, onAnswer: url) do content = xml.Response(onHangup: url, onAnswer: url) do
@ -61,6 +62,7 @@ class Integration::SipgateController < ApplicationController
routing_table.each do |row| routing_table.each do |row|
dest = row[:dest].gsub(/\*/, '.+?') dest = row[:dest].gsub(/\*/, '.+?')
next if to !~ /^#{dest}$/ next if to !~ /^#{dest}$/
from = row[:caller_id] from = row[:caller_id]
content = xml.Response(onHangup: url, onAnswer: url) do content = xml.Response(onHangup: url, onAnswer: url) do
xml.Dial(callerId: from) { xml.Number(params[:to]) } xml.Dial(callerId: from) { xml.Number(params[:to]) }

View file

@ -103,8 +103,10 @@ class LongPollingController < ApplicationController
def client_id_verify def client_id_verify
return if !params[:client_id] return if !params[:client_id]
sessions = Sessions.sessions sessions = Sessions.sessions
return if !sessions.include?(params[:client_id].to_s) return if !sessions.include?(params[:client_id].to_s)
params[:client_id].to_s params[:client_id].to_s
end end

View file

@ -41,6 +41,7 @@ curl http://localhost/api/v1/monitoring/health_check?token=XXX
message = "Channel: #{channel.area} in " 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? next if channel.options[key].blank?
message += "key:#{channel.options[key]};" message += "key:#{channel.options[key]};"
end end
issues.push "#{message} #{channel.last_log_in}" issues.push "#{message} #{channel.last_log_in}"
@ -52,9 +53,11 @@ curl http://localhost/api/v1/monitoring/health_check?token=XXX
# outbound channel # outbound channel
next if channel.status_out != 'error' next if channel.status_out != 'error'
message = "Channel: #{channel.area} out " 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? next if channel.options[key].blank?
message += "key:#{channel.options[key]};" message += "key:#{channel.options[key]};"
end end
issues.push "#{message} #{channel.last_log_out}" issues.push "#{message} #{channel.last_log_out}"
@ -76,6 +79,7 @@ curl http://localhost/api/v1/monitoring/health_check?token=XXX
Scheduler.where('active = ? AND period > 300', true).where.not(last_run: nil).order(last_run: :asc, period: :asc).each do |scheduler| Scheduler.where('active = ? AND period > 300', true).where.not(last_run: nil).order(last_run: :asc, period: :asc).each do |scheduler|
diff = Time.zone.now - (scheduler.last_run + scheduler.period.seconds) diff = Time.zone.now - (scheduler.last_run + scheduler.period.seconds)
next if diff < 8.minutes next if diff < 8.minutes
issues.push "scheduler may not run (last execution of #{scheduler.method} #{helpers.time_ago_in_words(Time.zone.now - diff.seconds)} over) - please contact your system administrator" issues.push "scheduler may not run (last execution of #{scheduler.method} #{helpers.time_ago_in_words(Time.zone.now - diff.seconds)} over) - please contact your system administrator"
break break
end end
@ -259,11 +263,13 @@ curl http://localhost/api/v1/monitoring/status?token=XXX
user = authentication_check_only(permission: 'admin.monitoring') user = authentication_check_only(permission: 'admin.monitoring')
return if user return if user
return if Setting.get('monitoring_token') == params[:token] return if Setting.get('monitoring_token') == params[:token]
raise Exceptions::NotAuthorized raise Exceptions::NotAuthorized
end end
def access_check def access_check
return if Permission.find_by(name: 'admin.monitoring', active: true) return if Permission.find_by(name: 'admin.monitoring', active: true)
raise Exceptions::NotAuthorized raise Exceptions::NotAuthorized
end end

View file

@ -103,6 +103,7 @@ curl http://localhost/api/v1/online_notifications/#{id} -v -u #{login}:#{passwor
def show def show
return if !access? return if !access?
model_show_render(OnlineNotification, params) model_show_render(OnlineNotification, params)
end end
@ -131,6 +132,7 @@ curl http://localhost/api/v1/online_notifications -v -u #{login}:#{password} -H
def update def update
return if !access? return if !access?
model_update_render(OnlineNotification, params) model_update_render(OnlineNotification, params)
end end
@ -149,6 +151,7 @@ curl http://localhost/api/v1/online_notifications/{id}.json -v -u #{login}:#{pas
def destroy def destroy
return if !access? return if !access?
model_destroy_render(OnlineNotification, params) model_destroy_render(OnlineNotification, params)
end end

View file

@ -190,6 +190,7 @@ curl http://localhost/api/v1/overviews_prio -v -u #{login}:#{password} -H "Conte
params[:prios].each do |overview_prio| params[:prios].each do |overview_prio|
overview = Overview.find(overview_prio[0]) overview = Overview.find(overview_prio[0])
next if overview.prio == overview_prio[1] next if overview.prio == overview_prio[1]
overview.prio = overview_prio[1] overview.prio = overview_prio[1]
overview.save! overview.save!
end end

View file

@ -30,6 +30,7 @@ class ReportsController < ApplicationController
backend[:condition] = condition backend[:condition] = condition
end end
next if !backend[:adapter] next if !backend[:adapter]
result[backend[:name]] = backend[:adapter].aggs( result[backend[:name]] = backend[:adapter].aggs(
range_start: get_params[:start], range_start: get_params[:start],
range_end: get_params[:stop], range_end: get_params[:stop],
@ -75,6 +76,7 @@ class ReportsController < ApplicationController
result = {} result = {}
get_params[:metric][:backend].each do |backend| get_params[:metric][:backend].each do |backend|
next if params[:downloadBackendSelected] != backend[:name] next if params[:downloadBackendSelected] != backend[:name]
condition = get_params[:profile].condition condition = get_params[:profile].condition
if backend[:condition] if backend[:condition]
backend[:condition].merge(condition) backend[:condition].merge(condition)
@ -82,6 +84,7 @@ class ReportsController < ApplicationController
backend[:condition] = condition backend[:condition] = condition
end end
next if !backend[:adapter] next if !backend[:adapter]
result = backend[:adapter].items( result = backend[:adapter].items(
range_start: get_params[:start], range_start: get_params[:start],
range_end: get_params[:stop], range_end: get_params[:stop],
@ -95,6 +98,7 @@ class ReportsController < ApplicationController
# generate sheet # generate sheet
next if !params[:sheet] next if !params[:sheet]
content = sheet(get_params[:profile], backend[:display], result) content = sheet(get_params[:profile], backend[:display], result)
send_data( send_data(
content, content,
@ -113,11 +117,13 @@ class ReportsController < ApplicationController
if !params[:profiles] && !params[:profile_id] if !params[:profiles] && !params[:profile_id]
raise Exceptions::UnprocessableEntity, 'No such profiles param' raise Exceptions::UnprocessableEntity, 'No such profiles param'
end end
if params[:profile_id] if params[:profile_id]
profile = Report::Profile.find(params[:profile_id]) profile = Report::Profile.find(params[:profile_id])
else else
params[:profiles].each do |profile_id, active| params[:profiles].each do |profile_id, active|
next if !active next if !active
profile = Report::Profile.find(profile_id) profile = Report::Profile.find(profile_id)
end end
end end
@ -129,6 +135,7 @@ class ReportsController < ApplicationController
if !local_config || !local_config[:metric] || !local_config[:metric][params[:metric].to_sym] if !local_config || !local_config[:metric] || !local_config[:metric][params[:metric].to_sym]
raise Exceptions::UnprocessableEntity, "No such metric #{params[:metric]}" raise Exceptions::UnprocessableEntity, "No such metric #{params[:metric]}"
end end
metric = local_config[:metric][params[:metric].to_sym] metric = local_config[:metric][params[:metric].to_sym]
#{"metric"=>"count", "year"=>2015, "month"=>10, "week"=>43, "day"=>20, "timeSlot"=>"year", "report"=>{"metric"=>"count", "year"=>2015, "month"=>10, "week"=>43, "day"=>20, "timeSlot"=>"year"}} #{"metric"=>"count", "year"=>2015, "month"=>10, "week"=>43, "day"=>20, "timeSlot"=>"year", "report"=>{"metric"=>"count", "year"=>2015, "month"=>10, "week"=>43, "day"=>20, "timeSlot"=>"year"}}

View file

@ -36,6 +36,7 @@ class SearchController < ApplicationController
local_class = object.constantize local_class = object.constantize
preferences = local_class.search_preferences(current_user) preferences = local_class.search_preferences(current_user)
next if !preferences next if !preferences
objects_in_order_hash[preferences[:prio]] = local_class objects_in_order_hash[preferences[:prio]] = local_class
end end
objects_in_order_hash.keys.sort.reverse_each do |prio| objects_in_order_hash.keys.sort.reverse_each do |prio|
@ -53,6 +54,7 @@ class SearchController < ApplicationController
objects.each do |object| objects.each do |object|
preferences = object.constantize.search_preferences(current_user) preferences = object.constantize.search_preferences(current_user)
next if !preferences next if !preferences
if preferences[:direct_search_index] if preferences[:direct_search_index]
objects_with_direct_search_index.push object objects_with_direct_search_index.push object
else else
@ -68,6 +70,7 @@ class SearchController < ApplicationController
local_class = Kernel.const_get(item[:type]) local_class = Kernel.const_get(item[:type])
record = local_class.lookup(id: item[:id]) record = local_class.lookup(id: item[:id])
next if !record next if !record
assets = record.assets(assets) assets = record.assets(assets)
item[:type] = local_class.to_app_model.to_s item[:type] = local_class.to_app_model.to_s
result.push item result.push item
@ -87,6 +90,7 @@ class SearchController < ApplicationController
objects_in_order.each do |object| objects_in_order.each do |object|
result.each do |item| result.each do |item|
next if item[:type] != object.to_app_model.to_s next if item[:type] != object.to_app_model.to_s
item[:id] = item[:id].to_i item[:id] = item[:id].to_i
result_in_order.push item result_in_order.push item
end end

View file

@ -45,5 +45,5 @@ module ExtraCollection
[collections, assets] [collections, assets]
end end
module_function :session module_function :session # rubocop:disable Style/AccessModifierDeclarations
end end

View file

@ -10,9 +10,10 @@ module ExtraCollection
key: 'dashboard', key: 'dashboard',
) )
return [collections, assets] if !item return [collections, assets] if !item
collections['StatsStore'] = [item] collections['StatsStore'] = [item]
[collections, assets] [collections, assets]
end end
module_function :session module_function :session # rubocop:disable Style/AccessModifierDeclarations
end end

View file

@ -44,5 +44,5 @@ module ExtraCollection
end end
[collections, assets] [collections, assets]
end end
module_function :session module_function :session # rubocop:disable Style/AccessModifierDeclarations
end end

View file

@ -288,10 +288,13 @@ class SessionsController < ApplicationController
sessions_clean = [] sessions_clean = []
SessionHelper.list.each do |session| SessionHelper.list.each do |session|
next if session.data['user_id'].blank? next if session.data['user_id'].blank?
sessions_clean.push session sessions_clean.push session
next if session.data['user_id'] next if session.data['user_id']
user = User.lookup(id: session.data['user_id']) user = User.lookup(id: session.data['user_id'])
next if !user next if !user
assets = user.assets(assets) assets = user.assets(assets)
end end
render json: { render json: {
@ -314,8 +317,10 @@ class SessionsController < ApplicationController
config = {} config = {}
Setting.select('name, preferences').where(frontend: true).each do |setting| Setting.select('name, preferences').where(frontend: true).each do |setting|
next if setting.preferences[:authentication] == true && !current_user next if setting.preferences[:authentication] == true && !current_user
value = Setting.get(setting.name) value = Setting.get(setting.name)
next if !current_user && (value == false || value.nil?) next if !current_user && (value == false || value.nil?)
config[setting.name] = value config[setting.name] = value
end end

View file

@ -8,6 +8,7 @@ class SettingsController < ApplicationController
list = [] list = []
Setting.all.each do |setting| Setting.all.each do |setting|
next if setting.preferences[:permission] && !current_user.permissions?(setting.preferences[:permission]) next if setting.preferences[:permission] && !current_user.permissions?(setting.preferences[:permission])
list.push setting list.push setting
end end
render json: list, status: :ok render json: list, status: :ok

View file

@ -44,6 +44,7 @@ class TicketArticlesController < ApplicationController
# ignore internal article if customer is requesting # ignore internal article if customer is requesting
next if article.internal == true && current_user.permissions?('ticket.customer') next if article.internal == true && current_user.permissions?('ticket.customer')
result = article.attributes_with_association_names result = article.attributes_with_association_names
articles.push result articles.push result
end end
@ -74,6 +75,7 @@ class TicketArticlesController < ApplicationController
# ignore internal article if customer is requesting # ignore internal article if customer is requesting
next if article.internal == true && current_user.permissions?('ticket.customer') next if article.internal == true && current_user.permissions?('ticket.customer')
articles.push article.attributes_with_association_names articles.push article.attributes_with_association_names
end end
render json: articles, status: :ok render json: articles, status: :ok
@ -315,6 +317,7 @@ class TicketArticlesController < ApplicationController
if Setting.get('import_mode') != true if Setting.get('import_mode') != true
raise 'Only can import tickets if system is in import mode.' raise 'Only can import tickets if system is in import mode.'
end end
result = Ticket::Article.csv_import( result = Ticket::Article.csv_import(
string: params[:file].read.force_encoding('utf-8'), string: params[:file].read.force_encoding('utf-8'),
parse_params: { parse_params: {
@ -331,6 +334,7 @@ class TicketArticlesController < ApplicationController
disposition = params.fetch(:disposition, 'inline') disposition = params.fetch(:disposition, 'inline')
valid_disposition = %w[inline attachment] valid_disposition = %w[inline attachment]
return disposition if valid_disposition.include?(disposition) return disposition if valid_disposition.include?(disposition)
raise Exceptions::NotAuthorized, "Invalid disposition #{disposition} requested. Only #{valid_disposition.join(', ')} are valid." raise Exceptions::NotAuthorized, "Invalid disposition #{disposition} requested. Only #{valid_disposition.join(', ')} are valid."
end end
end end

View file

@ -31,6 +31,7 @@ class TicketStatesController < ApplicationController
def destroy def destroy
permission_check('admin.object') permission_check('admin.object')
return if model_references_check(Ticket::State, params) return if model_references_check(Ticket::State, params)
model_destroy_render(Ticket::State, params) model_destroy_render(Ticket::State, params)
end end
end end

View file

@ -177,10 +177,13 @@ class TicketsController < ApplicationController
if params[:links].present? if params[:links].present?
link = params[:links].permit!.to_h link = params[:links].permit!.to_h
raise Exceptions::UnprocessableEntity, 'Invalid link structure' if !link.is_a? Hash raise Exceptions::UnprocessableEntity, 'Invalid link structure' if !link.is_a? Hash
link.each do |target_object, link_types_with_object_ids| link.each do |target_object, link_types_with_object_ids|
raise Exceptions::UnprocessableEntity, 'Invalid link structure (Object)' if !link_types_with_object_ids.is_a? Hash raise Exceptions::UnprocessableEntity, 'Invalid link structure (Object)' if !link_types_with_object_ids.is_a? Hash
link_types_with_object_ids.each do |link_type, object_ids| link_types_with_object_ids.each do |link_type, object_ids|
raise Exceptions::UnprocessableEntity, 'Invalid link structure (Object->LinkType)' if !object_ids.is_a? Array raise Exceptions::UnprocessableEntity, 'Invalid link structure (Object->LinkType)' if !object_ids.is_a? Array
object_ids.each do |local_object_id| object_ids.each do |local_object_id|
link = Link.add( link = Link.add(
link_type: link_type, link_type: link_type,
@ -342,6 +345,7 @@ class TicketsController < ApplicationController
recent_views.each do |recent_view| recent_views.each do |recent_view|
next if recent_view.object.name != 'Ticket' next if recent_view.object.name != 'Ticket'
next if recent_view.o_id == ticket.id next if recent_view.o_id == ticket.id
ticket_ids_recent_viewed.push recent_view.o_id ticket_ids_recent_viewed.push recent_view.o_id
recent_view_ticket = Ticket.find(recent_view.o_id) recent_view_ticket = Ticket.find(recent_view.o_id)
assets = recent_view_ticket.assets(assets) assets = recent_view_ticket.assets(assets)
@ -516,6 +520,7 @@ class TicketsController < ApplicationController
if !user if !user
raise "No such user with id #{params[:user_id]}" raise "No such user with id #{params[:user_id]}"
end end
conditions = { conditions = {
closed_ids: { closed_ids: {
'ticket.state_id' => { 'ticket.state_id' => {
@ -557,6 +562,7 @@ class TicketsController < ApplicationController
if !organization if !organization
raise "No such organization with id #{params[:organization_id]}" raise "No such organization with id #{params[:organization_id]}"
end end
conditions = { conditions = {
closed_ids: { closed_ids: {
'ticket.state_id' => { 'ticket.state_id' => {
@ -634,6 +640,7 @@ class TicketsController < ApplicationController
if Setting.get('import_mode') != true if Setting.get('import_mode') != true
raise 'Only can import tickets if system is in import mode.' raise 'Only can import tickets if system is in import mode.'
end end
string = params[:data] || params[:file].read.force_encoding('utf-8') string = params[:data] || params[:file].read.force_encoding('utf-8')
result = Ticket.csv_import( result = Ticket.csv_import(
string: string, string: string,
@ -652,6 +659,7 @@ class TicketsController < ApplicationController
return true if ticket.group.follow_up_possible != 'new_ticket' # check if the setting for follow_up_possible is disabled return true if ticket.group.follow_up_possible != 'new_ticket' # check if the setting for follow_up_possible is disabled
return true if ticket.state.name != 'closed' # check if the ticket state is already closed return true if ticket.state.name != 'closed' # check if the ticket state is already closed
raise Exceptions::UnprocessableEntity, 'Cannot follow up on a closed ticket. Please create a new ticket.' raise Exceptions::UnprocessableEntity, 'Cannot follow up on a closed ticket. Please create a new ticket.'
end end

View file

@ -28,6 +28,7 @@ class TimeAccountingsController < ApplicationController
time_unit.each do |ticket_id, local_time_unit| time_unit.each do |ticket_id, local_time_unit|
ticket = Ticket.lookup(id: ticket_id) ticket = Ticket.lookup(id: ticket_id)
next if !ticket next if !ticket
if !customers[ticket.customer_id] if !customers[ticket.customer_id]
customers[ticket.customer_id] = '-' customers[ticket.customer_id] = '-'
if ticket.customer_id if ticket.customer_id
@ -264,6 +265,7 @@ class TimeAccountingsController < ApplicationController
time_unit.each do |ticket_id, local_time_unit| time_unit.each do |ticket_id, local_time_unit|
ticket = Ticket.lookup(id: ticket_id) ticket = Ticket.lookup(id: ticket_id)
next if !ticket next if !ticket
if !customers[ticket.customer_id] if !customers[ticket.customer_id]
organization = nil organization = nil
if ticket.organization_id if ticket.organization_id
@ -345,6 +347,7 @@ class TimeAccountingsController < ApplicationController
ticket = Ticket.lookup(id: ticket_id) ticket = Ticket.lookup(id: ticket_id)
next if !ticket next if !ticket
next if !ticket.organization_id next if !ticket.organization_id
if !organizations[ticket.organization_id] if !organizations[ticket.organization_id]
organizations[ticket.organization_id] = { organizations[ticket.organization_id] = {
organization: Organization.lookup(id: ticket.organization_id).attributes, organization: Organization.lookup(id: ticket.organization_id).attributes,

View file

@ -41,6 +41,7 @@ curl http://localhost/api/v1/user_access_token -v -u #{login}:#{password}
keys = Object.const_get('Permission').with_parents(key) keys = Object.const_get('Permission').with_parents(key)
keys.each do |local_key| keys.each do |local_key|
next if local_permissions_new.key?([local_key]) next if local_permissions_new.key?([local_key])
if local_permissions[local_key] == true if local_permissions[local_key] == true
local_permissions_new[local_key] = true local_permissions_new[local_key] = true
next next
@ -51,6 +52,7 @@ curl http://localhost/api/v1/user_access_token -v -u #{login}:#{password}
permissions = [] permissions = []
Permission.all.where(active: true).order(:name).each do |permission| Permission.all.where(active: true).order(:name).each do |permission|
next if !local_permissions_new.key?(permission.name) && !current_user.permissions?(permission.name) next if !local_permissions_new.key?(permission.name) && !current_user.permissions?(permission.name)
permission_attributes = permission.attributes permission_attributes = permission.attributes
if local_permissions_new[permission.name] == false if local_permissions_new[permission.name] == false
permission_attributes['preferences']['disabled'] = true permission_attributes['preferences']['disabled'] = true
@ -93,6 +95,7 @@ curl http://localhost/api/v1/user_access_token -v -u #{login}:#{password} -H "Co
if params[:label].blank? if params[:label].blank?
raise Exceptions::UnprocessableEntity, 'Need label!' raise Exceptions::UnprocessableEntity, 'Need label!'
end end
token = Token.create!( token = Token.create!(
action: 'api', action: 'api',
label: params[:label], label: params[:label],
@ -124,6 +127,7 @@ curl http://localhost/api/v1/user_access_token/{id} -v -u #{login}:#{password} -
def destroy def destroy
token = Token.find_by(action: 'api', user_id: current_user.id, id: params[:id]) token = Token.find_by(action: 'api', user_id: current_user.id, id: params[:id])
raise Exceptions::UnprocessableEntity, 'Unable to find api token!' if !token raise Exceptions::UnprocessableEntity, 'Unable to find api token!' if !token
token.destroy! token.destroy!
render json: {}, status: :ok render json: {}, status: :ok
end end

View file

@ -36,6 +36,7 @@ class UserDevicesController < ApplicationController
next if !session.data['user_id'] next if !session.data['user_id']
next if !session.data['user_device_id'] next if !session.data['user_device_id']
next if session.data['user_device_id'] != user_device.id next if session.data['user_device_id'] != user_device.id
SessionHelper.destroy( session.id ) SessionHelper.destroy( session.id )
end end
user_device.destroy user_device.destroy

View file

@ -411,6 +411,7 @@ class UsersController < ApplicationController
} }
%i[role_ids permissions].each do |key| %i[role_ids permissions].each do |key|
next if params[key].blank? next if params[key].blank?
query_params[key] = params[key] query_params[key] = params[key]
end end
@ -827,6 +828,7 @@ curl http://localhost/api/v1/users/out_of_office -v -u #{login}:#{password} -H "
def out_of_office def out_of_office
raise Exceptions::UnprocessableEntity, 'No current user!' if !current_user raise Exceptions::UnprocessableEntity, 'No current user!' if !current_user
user = User.find(current_user.id) user = User.find(current_user.id)
user.with_lock do user.with_lock do
user.assign_attributes( user.assign_attributes(
@ -1065,6 +1067,7 @@ curl http://localhost/api/v1/users/avatar -v -u #{login}:#{password} -H "Content
if Setting.get('password_min_2_lower_2_upper_characters').to_i == 1 && ( password !~ /[A-Z].*[A-Z]/ || password !~ /[a-z].*[a-z]/ ) if Setting.get('password_min_2_lower_2_upper_characters').to_i == 1 && ( password !~ /[A-Z].*[A-Z]/ || password !~ /[a-z].*[a-z]/ )
return ["Can't update password, it must contain at least 2 lowercase and 2 uppercase characters!"] return ["Can't update password, it must contain at least 2 lowercase and 2 uppercase characters!"]
end end
true true
end end
end end

View file

@ -45,6 +45,7 @@ add a new activity entry for an object
if !permission if !permission
raise "No such Permission #{data[:permission]}" raise "No such Permission #{data[:permission]}"
end end
permission_id = permission.id permission_id = permission.id
end end

View file

@ -43,12 +43,15 @@ returns
end end
return data if !self['created_by_id'] return data if !self['created_by_id']
app_model_user = User.to_app_model app_model_user = User.to_app_model
%w[created_by_id].each do |local_user_id| %w[created_by_id].each do |local_user_id|
next if !self[ local_user_id ] next if !self[ local_user_id ]
next if data[ app_model_user ] && data[ app_model_user ][ 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 ]) user = User.lookup(id: self[ local_user_id ])
next if !user next if !user
data = user.assets(data) data = user.assets(data)
end end
data data

View file

@ -32,12 +32,15 @@ returns
end end
return data if !self['created_by_id'] && !self['updated_by_id'] return data if !self['created_by_id'] && !self['updated_by_id']
app_model_user = User.to_app_model 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 !self[ local_user_id ]
next if data[ app_model_user ] && data[ app_model_user ][ 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 ]) user = User.lookup(id: self[ local_user_id ])
next if !user next if !user
data = user.assets(data) data = user.assets(data)
end end
data data
@ -60,10 +63,12 @@ get assets and record_ids of selector
send(selector).each do |item, content| send(selector).each do |item, content|
attribute = item.split(/\./) attribute = item.split(/\./)
next if !attribute[1] next if !attribute[1]
begin begin
attribute_class = attribute[0].to_classname.constantize attribute_class = attribute[0].to_classname.constantize
rescue => e rescue => e
next if attribute[0] == 'article' next if attribute[0] == 'article'
logger.error "Unable to get asset for '#{attribute[0]}': #{e.inspect}" logger.error "Unable to get asset for '#{attribute[0]}': #{e.inspect}"
next next
end end
@ -73,12 +78,15 @@ get assets and record_ids of selector
next if !models[attribute_class][:reflections] next if !models[attribute_class][:reflections]
next if !models[attribute_class][:reflections][reflection] next if !models[attribute_class][:reflections][reflection]
next if !models[attribute_class][:reflections][reflection].klass next if !models[attribute_class][:reflections][reflection].klass
attribute_ref_class = models[attribute_class][:reflections][reflection].klass attribute_ref_class = models[attribute_class][:reflections][reflection].klass
if content['value'].instance_of?(Array) if content['value'].instance_of?(Array)
content['value'].each do |item_id| content['value'].each do |item_id|
next if item_id.blank? next if item_id.blank?
attribute_object = attribute_ref_class.lookup(id: item_id) attribute_object = attribute_ref_class.lookup(id: item_id)
next if !attribute_object next if !attribute_object
assets = attribute_object.assets(assets) assets = attribute_object.assets(assets)
end end
elsif content['value'].present? elsif content['value'].present?

View file

@ -23,8 +23,10 @@ returns
group_ids: :group_ids_access_map= group_ids: :group_ids_access_map=
}.each do |param, setter| }.each do |param, setter|
next if !params.key?(param) next if !params.key?(param)
map = params[param] map = params[param]
next if !respond_to?(setter) next if !respond_to?(setter)
send(setter, map) send(setter, map)
end end
@ -32,9 +34,11 @@ returns
self.class.reflect_on_all_associations.map do |assoc| self.class.reflect_on_all_associations.map do |assoc|
assoc_name = assoc.name assoc_name = assoc.name
next if association_attributes_ignored.include?(assoc_name) next if association_attributes_ignored.include?(assoc_name)
real_ids = assoc_name[0, assoc_name.length - 1] + '_ids' real_ids = assoc_name[0, assoc_name.length - 1] + '_ids'
real_ids = real_ids.to_sym real_ids = real_ids.to_sym
next if !params.key?(real_ids) next if !params.key?(real_ids)
list_of_items = params[real_ids] list_of_items = params[real_ids]
if !params[real_ids].instance_of?(Array) if !params[real_ids].instance_of?(Array)
list_of_items = [ params[real_ids] ] list_of_items = [ params[real_ids] ]
@ -42,12 +46,14 @@ returns
list = [] list = []
list_of_items.each do |item_id| list_of_items.each do |item_id|
next if !item_id next if !item_id
lookup = assoc.klass.lookup(id: item_id) lookup = assoc.klass.lookup(id: item_id)
# complain if we found no reference # complain if we found no reference
if !lookup if !lookup
raise ArgumentError, "No value found for '#{assoc_name}' with id #{item_id.inspect}" raise ArgumentError, "No value found for '#{assoc_name}' with id #{item_id.inspect}"
end end
list.push item_id list.push item_id
end end
send("#{real_ids}=", list) send("#{real_ids}=", list)
@ -57,16 +63,20 @@ returns
self.class.reflect_on_all_associations.map do |assoc| self.class.reflect_on_all_associations.map do |assoc|
assoc_name = assoc.name assoc_name = assoc.name
next if association_attributes_ignored.include?(assoc_name) next if association_attributes_ignored.include?(assoc_name)
real_ids = assoc_name[0, assoc_name.length - 1] + '_ids' real_ids = assoc_name[0, assoc_name.length - 1] + '_ids'
next if !respond_to?(real_ids) next if !respond_to?(real_ids)
real_values = assoc_name[0, assoc_name.length - 1] + 's' real_values = assoc_name[0, assoc_name.length - 1] + 's'
real_values = real_values.to_sym real_values = real_values.to_sym
next if !respond_to?(real_values) next if !respond_to?(real_values)
next if !params[real_values] next if !params[real_values]
if params[real_values].instance_of?(String) || params[real_values].instance_of?(Integer) || params[real_values].instance_of?(Float) if params[real_values].instance_of?(String) || params[real_values].instance_of?(Integer) || params[real_values].instance_of?(Float)
params[real_values] = [params[real_values]] params[real_values] = [params[real_values]]
end end
next if !params[real_values].instance_of?(Array) next if !params[real_values].instance_of?(Array)
list = [] list = []
class_object = assoc.klass class_object = assoc.klass
params[real_values].each do |value| params[real_values].each do |value|
@ -86,6 +96,7 @@ returns
if !lookup if !lookup
raise ArgumentError, "No lookup value found for '#{assoc_name}': #{value.inspect}" raise ArgumentError, "No lookup value found for '#{assoc_name}': #{value.inspect}"
end end
list.push lookup.id list.push lookup.id
end end
send("#{real_ids}=", list) send("#{real_ids}=", list)
@ -171,8 +182,10 @@ returns
self.class.reflect_on_all_associations.map do |assoc| self.class.reflect_on_all_associations.map do |assoc|
next if !respond_to?(assoc.name) next if !respond_to?(assoc.name)
next if association_attributes_ignored.include?(assoc.name) next if association_attributes_ignored.include?(assoc.name)
ref = send(assoc.name) ref = send(assoc.name)
next if !ref next if !ref
if ref.respond_to?(:first) if ref.respond_to?(:first)
attributes[assoc.name.to_s] = [] attributes[assoc.name.to_s] = []
ref.each do |item| ref.each do |item|
@ -181,6 +194,7 @@ returns
next next
end end
next if !item[:name] next if !item[:name]
attributes[assoc.name.to_s].push item[:name] attributes[assoc.name.to_s].push item[:name]
end end
if ref.count.positive? && attributes[assoc.name.to_s].blank? if ref.count.positive? && attributes[assoc.name.to_s].blank?
@ -193,6 +207,7 @@ returns
next next
end end
next if !ref[:name] next if !ref[:name]
attributes[assoc.name.to_s] = ref[:name] attributes[assoc.name.to_s] = ref[:name]
end end
@ -207,8 +222,10 @@ returns
'updated_by_id' => 'updated_by', 'updated_by_id' => 'updated_by',
}.each do |source, destination| }.each do |source, destination|
next if !attributes[source] next if !attributes[source]
user = User.lookup(id: attributes[source]) user = User.lookup(id: attributes[source])
next if !user next if !user
attributes[destination] = user.login attributes[destination] = user.login
end end
@ -245,14 +262,18 @@ returns
# check if id is assigned # check if id is assigned
next if !key.end_with?('_id') next if !key.end_with?('_id')
key_short = key.chomp('_id') key_short = key.chomp('_id')
self.class.reflect_on_all_associations.map do |assoc| self.class.reflect_on_all_associations.map do |assoc|
next if assoc.name.to_s != key_short next if assoc.name.to_s != key_short
item = assoc.class_name.constantize item = assoc.class_name.constantize
return false if !item.respond_to?(:find_by) return false if !item.respond_to?(:find_by)
ref_object = item.find_by(id: value) ref_object = item.find_by(id: value)
return false if !ref_object return false if !ref_object
return true return true
end end
end end
@ -332,6 +353,7 @@ returns
assoc_name = assoc.name assoc_name = assoc.name
value = data[assoc_name] value = data[assoc_name]
next if !value # next if we do not have a value next if !value # next if we do not have a value
ref_name = "#{assoc_name}_id" ref_name = "#{assoc_name}_id"
# handle _id values # handle _id values
@ -345,6 +367,7 @@ returns
if !value.instance_of?(String) if !value.instance_of?(String)
raise ArgumentError, "String is needed as ref value #{value.inspect} for '#{assoc_name}'" raise ArgumentError, "String is needed as ref value #{value.inspect} for '#{assoc_name}'"
end end
if !lookup if !lookup
lookup = class_object.lookup(login: value) lookup = class_object.lookup(login: value)
end end
@ -374,6 +397,7 @@ returns
# handle _ids values # handle _ids values
next if !assoc_name.to_s.end_with?('s') next if !assoc_name.to_s.end_with?('s')
ref_names = "#{assoc_name.to_s.chomp('s')}_ids" ref_names = "#{assoc_name.to_s.chomp('s')}_ids"
generic_object_tmp = new generic_object_tmp = new
next if !generic_object_tmp.respond_to?(ref_names) # if we do have an _ids attribute next if !generic_object_tmp.respond_to?(ref_names) # if we do have an _ids attribute
@ -388,6 +412,7 @@ returns
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}'" raise ArgumentError, "String is needed in array ref as ref value #{value.inspect} for '#{assoc_name}'"
end end
if !lookup if !lookup
lookup = class_object.lookup(login: item) lookup = class_object.lookup(login: item)
end end
@ -402,6 +427,7 @@ returns
if !lookup if !lookup
raise ArgumentError, "No lookup value found for '#{assoc_name}': #{item.inspect}" raise ArgumentError, "No lookup value found for '#{assoc_name}': #{item.inspect}"
end end
lookup_ids.push lookup.id lookup_ids.push lookup.id
end end

View file

@ -50,10 +50,12 @@ returns
reflect_on_all_associations.map do |assoc| reflect_on_all_associations.map do |assoc|
class_name = assoc.options[:class_name] class_name = assoc.options[:class_name]
next if !class_name next if !class_name
name = "#{assoc.name}_id" name = "#{assoc.name}_id"
next if !data.key?(name) next if !data.key?(name)
next if data[name].blank? next if data[name].blank?
next if assoc.klass.lookup(id: data[name]) next if assoc.klass.lookup(id: data[name])
raise ArgumentError, "Invalid value for param '#{name}': #{data[name].inspect}" raise ArgumentError, "Invalid value for param '#{name}': #{data[name].inspect}"
end end
clean_params[attribute] = data[attribute] clean_params[attribute] = data[attribute]
@ -105,6 +107,7 @@ merge preferences param
def param_preferences_merge(new_params) def param_preferences_merge(new_params)
return new_params if new_params.blank? return new_params if new_params.blank?
return new_params if preferences.blank? return new_params if preferences.blank?
new_params[:preferences] = preferences.merge(new_params[:preferences] || {}) new_params[:preferences] = preferences.merge(new_params[:preferences] || {})
new_params new_params
end end

View file

@ -27,6 +27,7 @@ returns
updated_at = order(updated_at: :desc, id: :desc).limit(1).pluck(:updated_at).first updated_at = order(updated_at: :desc, id: :desc).limit(1).pluck(:updated_at).first
return if !updated_at return if !updated_at
latest_change_set(updated_at) latest_change_set(updated_at)
updated_at updated_at
end end

View file

@ -25,6 +25,7 @@ returns
attribute_name_with_id = key.to_s attribute_name_with_id = key.to_s
attribute_name = key.to_s attribute_name = key.to_s
next if attribute_name[-3, 3] != '_id' next if attribute_name[-3, 3] != '_id'
attribute_name = attribute_name[ 0, attribute_name.length - 3 ] attribute_name = attribute_name[ 0, attribute_name.length - 3 ]
# check if attribute method exists # check if attribute method exists

View file

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

View file

@ -19,6 +19,7 @@ module ApplicationModel::ChecksAttributeValuesAndLength
columns = self.class.columns_hash columns = self.class.columns_hash
attributes.each do |name, value| attributes.each do |name, value|
next if !value.instance_of?(String) next if !value.instance_of?(String)
column = columns[name] column = columns[name]
next if !column next if !column
@ -52,6 +53,7 @@ module ApplicationModel::ChecksAttributeValuesAndLength
# strip 4 bytes utf8 chars if needed (mysql/mariadb will complain it) # strip 4 bytes utf8 chars if needed (mysql/mariadb will complain it)
next if self[name].blank? next if self[name].blank?
self[name] = self[name].utf8_to_3bytesutf8 self[name] = self[name].utf8_to_3bytesutf8
end end
true true

View file

@ -14,6 +14,7 @@ module ApplicationModel::ChecksImport
return if !Setting.get('system_init_done') return if !Setting.get('system_init_done')
return if Setting.get('import_mode') && import_class_list.include?(self.class.to_s) return if Setting.get('import_mode') && import_class_list.include?(self.class.to_s)
return if !has_attribute?(:id) return if !has_attribute?(:id)
self[:id] = nil self[:id] = nil
true true
end end

View file

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

View file

@ -179,6 +179,7 @@ add avatar by url
# fetch image # fetch image
image = Service::Image.user(url) image = Service::Image.user(url)
return if !image return if !image
data[:resize] = image data[:resize] = image
data[:full] = image data[:full] = image
end end
@ -358,6 +359,7 @@ returns:
store_hash: hash, store_hash: hash,
) )
return if !avatar return if !avatar
Store.find(avatar.store_resize_id) Store.find(avatar.store_resize_id)
end end
@ -389,6 +391,7 @@ returns:
).order('created_at ASC, id DESC') ).order('created_at ASC, id DESC')
avatars.each do |avatar| avatars.each do |avatar|
next if avatar.id == avatar_id next if avatar.id == avatar_id
avatar.default = false avatar.default = false
avatar.save! avatar.save!
end end

View file

@ -33,6 +33,7 @@ returns calendar object
# prevent multible setups for same ip # prevent multible setups for same ip
cache = Cache.get('Calendar.init_setup.done') cache = Cache.get('Calendar.init_setup.done')
return if cache && cache[:ip] == ip return if cache && cache[:ip] == ip
Cache.write('Calendar.init_setup.done', { ip: ip }, { expires_in: 1.hour }) Cache.write('Calendar.init_setup.done', { ip: ip }, { expires_in: 1.hour })
# call for calendar suggestion # call for calendar suggestion
@ -171,6 +172,7 @@ returns
public_holidays.each do |day, meta| public_holidays.each do |day, meta|
next if !public_holidays[day]['feed'] next if !public_holidays[day]['feed']
next if meta['feed'] == Digest::MD5.hexdigest(ical_url) next if meta['feed'] == Digest::MD5.hexdigest(ical_url)
public_holidays.delete(day) public_holidays.delete(day)
end end
@ -215,6 +217,7 @@ returns
if !result.success? if !result.success?
raise result.error raise result.error
end end
cal_file = result.body cal_file = result.body
else else
cal_file = File.open(location) cal_file = File.open(location)
@ -234,14 +237,17 @@ returns
occurrences.each do |occurrence| occurrences.each do |occurrence|
result = Calendar.day_and_comment_by_event(event, occurrence.start_time) result = Calendar.day_and_comment_by_event(event, occurrence.start_time)
next if !result next if !result
events[result[0]] = result[1] events[result[0]] = result[1]
end end
end end
end end
next if event.dtstart < Time.zone.now - 1.year next if event.dtstart < Time.zone.now - 1.year
next if event.dtstart > Time.zone.now + 3.years next if event.dtstart > Time.zone.now + 3.years
result = Calendar.day_and_comment_by_event(event, event.dtstart) result = Calendar.day_and_comment_by_event(event, event.dtstart)
next if !result next if !result
events[result[0]] = result[1] events[result[0]] = result[1]
end end
events.sort.to_h events.sort.to_h
@ -255,6 +261,7 @@ returns
# ignore daylight saving time entries # ignore daylight saving time entries
return if comment.match?(/(daylight saving|sommerzeit|summertime)/i) return if comment.match?(/(daylight saving|sommerzeit|summertime)/i)
[day, comment] [day, comment]
end end
@ -263,9 +270,11 @@ returns
# if changed calendar is default, set all others default to false # if changed calendar is default, set all others default to false
def sync_default def sync_default
return true if !default return true if !default
Calendar.find_each do |calendar| Calendar.find_each do |calendar|
next if calendar.id == id next if calendar.id == id
next if !calendar.default next if !calendar.default
calendar.default = false calendar.default = false
calendar.save calendar.save
end end
@ -277,6 +286,7 @@ returns
if !Calendar.find_by(default: true) if !Calendar.find_by(default: true)
first = Calendar.order(:created_at, :id).limit(1).first first = Calendar.order(:created_at, :id).limit(1).first
return true if !first return true if !first
first.default = true first.default = true
first.save first.save
end end

View file

@ -58,6 +58,7 @@ fetch one account
driver_class = Object.const_get("Channel::Driver::#{adapter.to_classname}") driver_class = Object.const_get("Channel::Driver::#{adapter.to_classname}")
driver_instance = driver_class.new driver_instance = driver_class.new
return if !force && !driver_instance.fetchable?(self) return if !force && !driver_instance.fetchable?(self)
result = driver_instance.fetch(adapter_options, self) result = driver_instance.fetch(adapter_options, self)
self.status_in = result[:result] self.status_in = result[:result]
self.last_log_in = result[:notice] self.last_log_in = result[:notice]
@ -103,6 +104,7 @@ stream instance of account
# check is stream exists # check is stream exists
return if !driver_instance.respond_to?(:stream_instance) return if !driver_instance.respond_to?(:stream_instance)
driver_instance.stream_instance(self) driver_instance.stream_instance(self)
# set scheduler job to active # set scheduler job to active
@ -142,9 +144,11 @@ stream all accounts
channels.each do |channel| channels.each do |channel|
adapter = channel.options[:adapter] adapter = channel.options[:adapter]
next if adapter.blank? next if adapter.blank?
driver_class = Object.const_get("Channel::Driver::#{adapter.to_classname}") driver_class = Object.const_get("Channel::Driver::#{adapter.to_classname}")
next if !driver_class.respond_to?(:streamable?) next if !driver_class.respond_to?(:streamable?)
next if !driver_class.streamable? next if !driver_class.streamable?
channel_id = channel.id.to_s channel_id = channel.id.to_s
current_channels.push channel_id current_channels.push channel_id
@ -225,6 +229,7 @@ stream all accounts
last_channels.each do |channel_id| last_channels.each do |channel_id|
next if @@channel_stream[channel_id].blank? next if @@channel_stream[channel_id].blank?
next if current_channels.include?(channel_id) next if current_channels.include?(channel_id)
logger.info "channel (#{channel_id}) not longer active, stop stream thread" logger.info "channel (#{channel_id}) not longer active, stop stream thread"
@@channel_stream[channel_id][:thread].exit @@channel_stream[channel_id][:thread].exit
@@channel_stream[channel_id][:thread].join @@channel_stream[channel_id][:thread].join

View file

@ -52,11 +52,14 @@ returns
end end
return data if !self['created_by_id'] && !self['updated_by_id'] 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 !self[ local_user_id ]
next if data[ User.to_app_model ] && data[ User.to_app_model ][ 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 ]) user = User.lookup(id: self[ local_user_id ])
next if !user next if !user
data = user.assets(data) data = user.assets(data)
end end
data data

View file

@ -30,11 +30,13 @@ class Channel::Driver::Facebook
access_token = nil access_token = nil
options['pages'].each do |page| options['pages'].each do |page|
next if page['id'].to_s != fb_object_id.to_s next if page['id'].to_s != fb_object_id.to_s
access_token = page['access_token'] access_token = page['access_token']
end end
if !access_token if !access_token
raise "No access_token found for fb_object_id: #{fb_object_id}" raise "No access_token found for fb_object_id: #{fb_object_id}"
end end
client = ::Facebook.new(access_token) client = ::Facebook.new(access_token)
client.from_article(article) client.from_article(article)
end end
@ -54,6 +56,7 @@ class Channel::Driver::Facebook
return true if !channel.preferences return true if !channel.preferences
return true if !channel.preferences[:last_fetch] return true if !channel.preferences[:last_fetch]
return false if channel.preferences[:last_fetch] > Time.zone.now - 5.minutes return false if channel.preferences[:last_fetch] > Time.zone.now - 5.minutes
true true
end end
@ -93,6 +96,7 @@ returns
page = get_page(page_to_sync_id) page = get_page(page_to_sync_id)
next if !page next if !page
next if page_to_sync_params['group_id'].blank? next if page_to_sync_params['group_id'].blank?
page_client = ::Facebook.new(page['access_token']) page_client = ::Facebook.new(page['access_token'])
posts = page_client.client.get_connection('me', 'feed', fields: 'id,from,to,message,created_time,permalink_url,comments{id,from,to,message,created_time}') posts = page_client.client.get_connection('me', 'feed', fields: 'id,from,to,message,created_time,permalink_url,comments{id,from,to,message,created_time}')

View file

@ -164,6 +164,7 @@ example
subject = message_meta['ENVELOPE'].subject subject = message_meta['ENVELOPE'].subject
next if !subject next if !subject
next if subject !~ /#{verify_string}/ next if subject !~ /#{verify_string}/
Rails.logger.info " - verify email #{verify_string} found" Rails.logger.info " - verify email #{verify_string} found"
@imap.store(message_id, '+FLAGS', [:Deleted]) @imap.store(message_id, '+FLAGS', [:Deleted])
@imap.expunge() @imap.expunge()
@ -206,6 +207,7 @@ example
# delete email from server after article was created # delete email from server after article was created
msg = @imap.fetch(message_id, 'RFC822')[0].attr['RFC822'] msg = @imap.fetch(message_id, 'RFC822')[0].attr['RFC822']
next if !msg next if !msg
process(channel, msg, false) process(channel, msg, false)
if !keep_on_server if !keep_on_server
@imap.store(message_id, '+FLAGS', [:Deleted]) @imap.store(message_id, '+FLAGS', [:Deleted])
@ -231,6 +233,7 @@ example
def disconnect def disconnect
return if !@imap return if !@imap
@imap.disconnect() @imap.disconnect()
end end
@ -256,8 +259,10 @@ returns
return false if !keep_on_server return false if !keep_on_server
return false if !message_meta.attr return false if !message_meta.attr
return false if !message_meta.attr['ENVELOPE'] return false if !message_meta.attr['ENVELOPE']
local_message_id = message_meta.attr['ENVELOPE'].message_id local_message_id = message_meta.attr['ENVELOPE'].message_id
return false if local_message_id.blank? return false if local_message_id.blank?
local_message_id_md5 = Digest::MD5.hexdigest(local_message_id) local_message_id_md5 = Digest::MD5.hexdigest(local_message_id)
article = Ticket::Article.where(message_id_md5: local_message_id_md5).order('created_at DESC, id DESC').limit(1).first article = Ticket::Article.where(message_id_md5: local_message_id_md5).order('created_at DESC, id DESC').limit(1).first
return false if !article return false if !article
@ -275,6 +280,7 @@ returns
def deleted?(message_meta, count, count_all) def deleted?(message_meta, count, count_all)
return false if !message_meta.attr['FLAGS'].include?(:Deleted) return false if !message_meta.attr['FLAGS'].include?(:Deleted)
Rails.logger.info " - ignore message #{count}/#{count_all} - because message has already delete flag" Rails.logger.info " - ignore message #{count}/#{count_all} - because message has already delete flag"
true true
end end

View file

@ -118,6 +118,7 @@ returns
# check if verify message exists # check if verify message exists
next if mail !~ /#{verify_string}/ next if mail !~ /#{verify_string}/
Rails.logger.info " - verify email #{verify_string} found" Rails.logger.info " - verify email #{verify_string} found"
m.delete m.delete
disconnect disconnect
@ -196,6 +197,7 @@ returns
def disconnect def disconnect
return if !@pop return if !@pop
@pop.finish @pop.finish
end end

View file

@ -23,6 +23,7 @@ class Channel::Driver::Sendmail
def delivery_method def delivery_method
return :test if Rails.env.test? return :test if Rails.env.test?
:sendmail :sendmail
end end
end end

View file

@ -50,6 +50,7 @@ returns
if options[:auth] && options[:auth][:external_credential_id] if options[:auth] && options[:auth][:external_credential_id]
external_credential = ExternalCredential.find_by(id: options[:auth][:external_credential_id]) external_credential = ExternalCredential.find_by(id: options[:auth][:external_credential_id])
raise "No such ExternalCredential.find(#{options[:auth][:external_credential_id]})" if !external_credential raise "No such ExternalCredential.find(#{options[:auth][:external_credential_id]})" if !external_credential
options[:auth][:api_key] = external_credential.credentials['api_key'] options[:auth][:api_key] = external_credential.credentials['api_key']
end end
options options

View file

@ -83,6 +83,7 @@ returns
return true if !channel.preferences return true if !channel.preferences
return true if !channel.preferences[:last_fetch] return true if !channel.preferences[:last_fetch]
return false if channel.preferences[:last_fetch] > Time.zone.now - 20.minutes return false if channel.preferences[:last_fetch] > Time.zone.now - 20.minutes
true true
end end
@ -206,6 +207,7 @@ returns
if loop_count >= 2 if loop_count >= 2
raise "Unable to stream, try #{loop_count}, error #{e.inspect}" raise "Unable to stream, try #{loop_count}, error #{e.inspect}"
end end
Rails.logger.info "wait for #{sleep_on_unauthorized} sec. and try it again" Rails.logger.info "wait for #{sleep_on_unauthorized} sec. and try it again"
sleep sleep_on_unauthorized sleep sleep_on_unauthorized
end end
@ -224,6 +226,7 @@ returns
next if item['term'].blank? next if item['term'].blank?
next if item['term'] == '#' next if item['term'] == '#'
next if item['group_id'].blank? next if item['group_id'].blank?
hashtags.push item['term'] hashtags.push item['term']
end end
filter[:track] = hashtags.join(',') filter[:track] = hashtags.join(',')
@ -246,6 +249,7 @@ returns
if tweet.class == Twitter::DirectMessage if tweet.class == Twitter::DirectMessage
if sync['direct_messages'] && sync['direct_messages']['group_id'] != '' if sync['direct_messages'] && sync['direct_messages']['group_id'] != ''
next if @stream_client.direct_message_limit_reached(tweet, 2) next if @stream_client.direct_message_limit_reached(tweet, 2)
@stream_client.to_group(tweet, sync['direct_messages']['group_id'], @channel) @stream_client.to_group(tweet, sync['direct_messages']['group_id'], @channel)
end end
next next
@ -275,8 +279,10 @@ returns
next if item['term'].blank? next if item['term'].blank?
next if item['term'] == '#' next if item['term'] == '#'
next if item['group_id'].blank? next if item['group_id'].blank?
tweet.hashtags.each do |hashtag| tweet.hashtags.each do |hashtag|
next if item['term'] !~ /^#/ next if item['term'] !~ /^#/
if item['term'].sub(/^#/, '') == hashtag.text if item['term'].sub(/^#/, '') == hashtag.text
hit = item hit = item
end end
@ -296,6 +302,7 @@ returns
next if item['term'].blank? next if item['term'].blank?
next if item['term'] == '#' next if item['term'] == '#'
next if item['group_id'].blank? next if item['group_id'].blank?
if body.match?(/#{item['term']}/) if body.match?(/#{item['term']}/)
hit = item hit = item
end end
@ -312,10 +319,12 @@ returns
def fetch_search def fetch_search
return if @sync[:search].blank? return if @sync[:search].blank?
@sync[:search].each do |search| @sync[:search].each do |search|
next if search[:term].blank? next if search[:term].blank?
next if search[:term] == '#' next if search[:term] == '#'
next if search[:group_id].blank? next if search[:group_id].blank?
result_type = search[:type] || 'mixed' result_type = search[:type] || 'mixed'
Rails.logger.debug { " - searching for '#{search[:term]}'" } Rails.logger.debug { " - searching for '#{search[:term]}'" }
older_import = 0 older_import = 0
@ -333,6 +342,7 @@ returns
next if @rest_client.locale_sender?(tweet) && own_tweet_already_imported?(tweet) next if @rest_client.locale_sender?(tweet) && own_tweet_already_imported?(tweet)
next if Ticket::Article.find_by(message_id: tweet.id) next if Ticket::Article.find_by(message_id: tweet.id)
break if @rest_client.tweet_limit_reached(tweet) break if @rest_client.tweet_limit_reached(tweet)
@rest_client.to_group(tweet, search[:group_id], @channel) @rest_client.to_group(tweet, search[:group_id], @channel)
end end
end end
@ -341,6 +351,7 @@ returns
def fetch_mentions def fetch_mentions
return if @sync[:mentions].blank? return if @sync[:mentions].blank?
return if @sync[:mentions][:group_id].blank? return if @sync[:mentions][:group_id].blank?
Rails.logger.debug { ' - searching for mentions' } Rails.logger.debug { ' - searching for mentions' }
older_import = 0 older_import = 0
older_import_max = 20 older_import_max = 20
@ -355,6 +366,7 @@ returns
end end
next if Ticket::Article.find_by(message_id: tweet.id) next if Ticket::Article.find_by(message_id: tweet.id)
break if @rest_client.tweet_limit_reached(tweet) break if @rest_client.tweet_limit_reached(tweet)
@rest_client.to_group(tweet, @sync[:mentions][:group_id], @channel) @rest_client.to_group(tweet, @sync[:mentions][:group_id], @channel)
end end
end end
@ -362,6 +374,7 @@ returns
def fetch_direct_messages def fetch_direct_messages
return if @sync[:direct_messages].blank? return if @sync[:direct_messages].blank?
return if @sync[:direct_messages][:group_id].blank? return if @sync[:direct_messages][:group_id].blank?
Rails.logger.debug { ' - searching for direct_messages' } Rails.logger.debug { ' - searching for direct_messages' }
older_import = 0 older_import = 0
older_import_max = 20 older_import_max = 20
@ -375,6 +388,7 @@ returns
end end
next if Ticket::Article.find_by(message_id: tweet.id) next if Ticket::Article.find_by(message_id: tweet.id)
break if @rest_client.direct_message_limit_reached(tweet) break if @rest_client.direct_message_limit_reached(tweet)
@rest_client.to_group(tweet, @sync[:direct_messages][:group_id], @channel) @rest_client.to_group(tweet, @sync[:direct_messages][:group_id], @channel)
end end
end end
@ -383,6 +397,7 @@ returns
if options[:auth] && options[:auth][:external_credential_id] if options[:auth] && options[:auth][:external_credential_id]
external_credential = ExternalCredential.find_by(id: options[:auth][:external_credential_id]) external_credential = ExternalCredential.find_by(id: options[:auth][:external_credential_id])
raise "No such ExternalCredential.find(#{options[:auth][:external_credential_id]})" if !external_credential raise "No such ExternalCredential.find(#{options[:auth][:external_credential_id]})" if !external_credential
options[:auth][:consumer_key] = external_credential.credentials['consumer_key'] options[:auth][:consumer_key] = external_credential.credentials['consumer_key']
options[:auth][:consumer_secret] = external_credential.credentials['consumer_secret'] options[:auth][:consumer_secret] = external_credential.credentials['consumer_secret']
end end
@ -403,6 +418,7 @@ returns
end end
count = Delayed::Job.where('created_at < ?', event_time).count count = Delayed::Job.where('created_at < ?', event_time).count
break if count.zero? break if count.zero?
sleep_time = 2 * count sleep_time = 2 * count
sleep_time = 5 if sleep_time > 5 sleep_time = 5 if sleep_time > 5
Rails.logger.debug { "Delay importing own tweets - sleep #{sleep_time} (loop #{loop_count})" } Rails.logger.debug { "Delay importing own tweets - sleep #{sleep_time} (loop #{loop_count})" }

View file

@ -37,6 +37,7 @@ module Channel::EmailBuild
next if key.to_s == 'attachments' next if key.to_s == 'attachments'
next if key.to_s == 'body' next if key.to_s == 'body'
next if key.to_s == 'content_type' next if key.to_s == 'content_type'
mail[key.to_s] = if value && value.class != Array mail[key.to_s] = if value && value.class != Array
value.to_s value.to_s
else else
@ -84,6 +85,7 @@ module Channel::EmailBuild
attr[:attachments]&.each do |attachment| attr[:attachments]&.each do |attachment|
next if attachment.class == Hash next if attachment.class == Hash
next if attachment.preferences['Content-ID'].blank? next if attachment.preferences['Content-ID'].blank?
attachment = Mail::Part.new do attachment = Mail::Part.new do
content_type attachment.preferences['Content-Type'] content_type attachment.preferences['Content-Type']
content_id "<#{attachment.preferences['Content-ID']}>" content_id "<#{attachment.preferences['Content-ID']}>"
@ -105,6 +107,7 @@ module Channel::EmailBuild
mail.attachments[attachment[:filename]] = attachment mail.attachments[attachment[:filename]] = attachment
else else
next if attachment.preferences['Content-ID'].present? next if attachment.preferences['Content-ID'].present?
filename = attachment.filename filename = attachment.filename
encoded_filename = Mail::Encodings.decode_encode filename, :encode encoded_filename = Mail::Encodings.decode_encode filename, :encode
disposition = attachment.preferences['Content-Disposition'] || 'attachment' disposition = attachment.preferences['Content-Disposition'] || 'attachment'
@ -131,6 +134,7 @@ returns
def self.recipient_line(realname, email) def self.recipient_line(realname, email)
return "#{realname} <#{email}>" if realname.match?(/^[A-z]+$/i) return "#{realname} <#{email}>" if realname.match?(/^[A-z]+$/i)
"\"#{realname.gsub('"', '\"')}\" <#{email}>" "\"#{realname.gsub('"', '\"')}\" <#{email}>"
end end

View file

@ -121,6 +121,7 @@ returns
file.write msg file.write msg
end end
return false if exception == false return false if exception == false
raise e.inspect + "\n" + e.backtrace.join("\n") raise e.inspect + "\n" + e.backtrace.join("\n")
end end
@ -169,6 +170,7 @@ returns
if !session_user_id if !session_user_id
raise 'No x-zammad-session-user-id, no sender set!' raise 'No x-zammad-session-user-id, no sender set!'
end end
session_user = User.lookup(id: session_user_id) session_user = User.lookup(id: session_user_id)
if !session_user if !session_user
raise "No user found for x-zammad-session-user-id: #{session_user_id}!" raise "No user found for x-zammad-session-user-id: #{session_user_id}!"
@ -320,23 +322,28 @@ returns
attribute = nil attribute = nil
# skip check attributes if it is tags # skip check attributes if it is tags
return true if header_name == 'x-zammad-ticket-tags' return true if header_name == 'x-zammad-ticket-tags'
if header_name =~ /^x-zammad-(.+?)-(followup-|)(.*)$/i if header_name =~ /^x-zammad-(.+?)-(followup-|)(.*)$/i
class_name = $1 class_name = $1
attribute = $3 attribute = $3
end end
return true if !class_name return true if !class_name
if class_name.downcase == 'article' if class_name.downcase == 'article'
class_name = 'Ticket::Article' class_name = 'Ticket::Article'
end end
return true if !attribute return true if !attribute
key_short = attribute[ attribute.length - 3, attribute.length ] key_short = attribute[ attribute.length - 3, attribute.length ]
return true if key_short != '_id' return true if key_short != '_id'
class_object = Object.const_get(class_name.to_classname) class_object = Object.const_get(class_name.to_classname)
return if !class_object return if !class_object
class_instance = class_object.new class_instance = class_object.new
return false if !class_instance.association_id_validation(attribute, value) return false if !class_instance.association_id_validation(attribute, value)
true true
end end
@ -467,6 +474,7 @@ process unprocessable_mails (tmp/unprocessable_mail/*.eml) again
Dir.glob("#{path}/*.eml") do |entry| Dir.glob("#{path}/*.eml") do |entry|
ticket, article, user, mail = Channel::EmailParser.new.process(params, IO.binread(entry)) ticket, article, user, mail = Channel::EmailParser.new.process(params, IO.binread(entry))
next if ticket.blank? next if ticket.blank?
files.push entry files.push entry
File.delete(entry) File.delete(entry)
end end
@ -535,6 +543,7 @@ process unprocessable_mails (tmp/unprocessable_mail/*.eml) again
body_text = Mail::Utilities.to_lf(body_text) body_text = Mail::Utilities.to_lf(body_text)
return body_text.html2html_strict if options[:strict_html] return body_text.html2html_strict if options[:strict_html]
body_text body_text
end end
@ -567,6 +576,7 @@ process unprocessable_mails (tmp/unprocessable_mail/*.eml) again
attachments.push(*new_attachments) attachments.push(*new_attachments)
rescue => e # Protect process to work with spam emails (see test/fixtures/mail15.box) rescue => e # Protect process to work with spam emails (see test/fixtures/mail15.box)
raise e if (fail_count ||= 0).positive? raise e if (fail_count ||= 0).positive?
(fail_count += 1) && retry (fail_count += 1) && retry
end end
end end
@ -694,6 +704,7 @@ process unprocessable_mails (tmp/unprocessable_mail/*.eml) again
} }
map.each do |type, ext| map.each do |type, ext|
next if headers_store['Content-Type'] !~ /^#{Regexp.quote(type)}/i next if headers_store['Content-Type'] !~ /^#{Regexp.quote(type)}/i
filename = if headers_store['Content-Description'].present? filename = if headers_store['Content-Description'].present?
"#{headers_store['Content-Description']}.#{ext[0]}".to_s.force_encoding('utf-8') "#{headers_store['Content-Description']}.#{ext[0]}".to_s.force_encoding('utf-8')
else else
@ -723,6 +734,7 @@ process unprocessable_mails (tmp/unprocessable_mail/*.eml) again
end end
end end
break if filename_exists == false break if filename_exists == false
filename = if local_extention.present? filename = if local_extention.present?
"#{local_filename}#{i}.#{local_extention}" "#{local_filename}#{i}.#{local_extention}"
else else
@ -769,6 +781,7 @@ module Mail
value = @raw_value.utf8_encode(fallback: :read_as_sanitized_binary) value = @raw_value.utf8_encode(fallback: :read_as_sanitized_binary)
end end
return value if value.blank? return value if value.blank?
value.sub(/^.+?:(\s|)/, '') value.sub(/^.+?:(\s|)/, '')
end end
end end

View file

@ -16,6 +16,7 @@ module Channel::Filter::BounceDeliveryPermanentFailed
result = Channel::EmailParser.new.parse(attachment[:data]) result = Channel::EmailParser.new.parse(attachment[:data])
next if !result[:message_id] next if !result[:message_id]
message_id_md5 = Digest::MD5.hexdigest(result[:message_id]) message_id_md5 = Digest::MD5.hexdigest(result[:message_id])
article = Ticket::Article.where(message_id_md5: message_id_md5).order('created_at DESC, id DESC').limit(1).first article = Ticket::Article.where(message_id_md5: message_id_md5).order('created_at DESC, id DESC').limit(1).first
next if !article next if !article
@ -30,11 +31,13 @@ module Channel::Filter::BounceDeliveryPermanentFailed
if article.sender.name == 'System' || article.sender.name == 'Agent' 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? next if article[line].blank?
recipients = [] recipients = []
begin begin
list = Mail::AddressList.new(article[line]) list = Mail::AddressList.new(article[line])
list.addresses.each do |address| list.addresses.each do |address|
next if address.address.blank? next if address.address.blank?
recipients.push address.address.downcase recipients.push address.address.downcase
end end
rescue rescue
@ -60,6 +63,7 @@ module Channel::Filter::BounceDeliveryPermanentFailed
users = User.where(email: recipient) users = User.where(email: recipient)
users.each do |user| users.each do |user|
next if !user next if !user
user.preferences[:mail_delivery_failed] = true user.preferences[:mail_delivery_failed] = true
user.preferences[:mail_delivery_failed_data] = Time.zone.now user.preferences[:mail_delivery_failed_data] = Time.zone.now
user.save! user.save!

View file

@ -16,6 +16,7 @@ module Channel::Filter::BounceFollowUpCheck
result = Channel::EmailParser.new.parse(attachment[:data]) result = Channel::EmailParser.new.parse(attachment[:data])
next if !result[:message_id] next if !result[:message_id]
message_id_md5 = Digest::MD5.hexdigest(result[:message_id]) message_id_md5 = Digest::MD5.hexdigest(result[:message_id])
article = Ticket::Article.where(message_id_md5: message_id_md5).order('created_at DESC, id DESC').limit(1).first article = Ticket::Article.where(message_id_md5: message_id_md5).order('created_at DESC, id DESC').limit(1).first
next if !article next if !article

View file

@ -14,6 +14,7 @@ module Channel::Filter::Database
filter[:match].each do |key, meta| filter[:match].each do |key, meta|
begin begin
next if meta.blank? || meta['value'].blank? next if meta.blank? || meta['value'].blank?
value = mail[ key.downcase.to_sym ] value = mail[ key.downcase.to_sym ]
match_rule = meta['value'] match_rule = meta['value']
min_one_rule_exists = true min_one_rule_exists = true
@ -44,6 +45,7 @@ module Channel::Filter::Database
filter[:perform].each do |key, meta| filter[:perform].each do |key, meta|
next if !Channel::EmailParser.check_attributes_by_x_headers(key, meta['value']) next if !Channel::EmailParser.check_attributes_by_x_headers(key, meta['value'])
Rails.logger.info " perform '#{key.downcase}' = '#{meta.inspect}'" Rails.logger.info " perform '#{key.downcase}' = '#{meta.inspect}'"
if key.downcase == 'x-zammad-ticket-tags' && meta['value'].present? && meta['operator'].present? if key.downcase == 'x-zammad-ticket-tags' && meta['value'].present? && meta['operator'].present?
@ -54,13 +56,16 @@ module Channel::Filter::Database
when 'add' when 'add'
tags.each do |tag| tags.each do |tag|
next if tag.blank? next if tag.blank?
tag.strip! tag.strip!
next if mail[ 'x-zammad-ticket-tags'.downcase.to_sym ].include?(tag) next if mail[ 'x-zammad-ticket-tags'.downcase.to_sym ].include?(tag)
mail[ 'x-zammad-ticket-tags'.downcase.to_sym ].push tag mail[ 'x-zammad-ticket-tags'.downcase.to_sym ].push tag
end end
when 'remove' when 'remove'
tags.each do |tag| tags.each do |tag|
next if tag.blank? next if tag.blank?
tag.strip! tag.strip!
mail[ 'x-zammad-ticket-tags'.downcase.to_sym ] -= [tag] mail[ 'x-zammad-ticket-tags'.downcase.to_sym ] -= [tag]
end end

View file

@ -30,8 +30,10 @@ module Channel::Filter::FollowUpCheck
if setting.include?('attachment') && mail[:attachments] if setting.include?('attachment') && mail[:attachments]
mail[:attachments].each do |attachment| mail[:attachments].each do |attachment|
next if !attachment[:data] next if !attachment[:data]
ticket = Ticket::Number.check(attachment[:data].html2text) ticket = Ticket::Number.check(attachment[:data].html2text)
next if !ticket next if !ticket
Rails.logger.debug { "Follow up for '##{ticket.number}' in attachment." } Rails.logger.debug { "Follow up for '##{ticket.number}' in attachment." }
mail['x-zammad-ticket-id'.to_sym] = ticket.id mail['x-zammad-ticket-id'.to_sym] = ticket.id
return true return true
@ -58,6 +60,7 @@ module Channel::Filter::FollowUpCheck
message_id_md5 = Digest::MD5.hexdigest(message_id) message_id_md5 = Digest::MD5.hexdigest(message_id)
article = Ticket::Article.where(message_id_md5: message_id_md5).order('created_at DESC, id DESC').limit(1).first article = Ticket::Article.where(message_id_md5: message_id_md5).order('created_at DESC, id DESC').limit(1).first
next if !article next if !article
Rails.logger.debug { "Follow up for '##{article.ticket.number}' in references." } Rails.logger.debug { "Follow up for '##{article.ticket.number}' in references." }
mail['x-zammad-ticket-id'.to_sym] = article.ticket_id mail['x-zammad-ticket-id'.to_sym] = article.ticket_id
return true return true
@ -85,8 +88,10 @@ module Channel::Filter::FollowUpCheck
message_id_md5 = Digest::MD5.hexdigest(message_id) message_id_md5 = Digest::MD5.hexdigest(message_id)
article = Ticket::Article.where(message_id_md5: message_id_md5).order('created_at DESC, id DESC').limit(1).first article = Ticket::Article.where(message_id_md5: message_id_md5).order('created_at DESC, id DESC').limit(1).first
next if !article next if !article
ticket = article.ticket ticket = article.ticket
next if !ticket next if !ticket
article_first = ticket.articles.first article_first = ticket.articles.first
next if !article_first next if !article_first

View file

@ -5,6 +5,7 @@ module Channel::Filter::FollowUpPossibleCheck
def self.run(_channel, mail) def self.run(_channel, mail)
ticket_id = mail['x-zammad-ticket-id'.to_sym] ticket_id = mail['x-zammad-ticket-id'.to_sym]
return true if !ticket_id return true if !ticket_id
ticket = Ticket.lookup(id: ticket_id) ticket = Ticket.lookup(id: ticket_id)
return true if !ticket return true if !ticket
return true if ticket.state.state_type.name !~ /^(closed|merged|removed)/i return true if ticket.state.state_type.name !~ /^(closed|merged|removed)/i

View file

@ -96,14 +96,17 @@ module Channel::Filter::IdentifySender
current_count = 0 current_count = 0
['raw-to', 'raw-cc'].each do |item| ['raw-to', 'raw-cc'].each do |item|
next if mail[item.to_sym].blank? next if mail[item.to_sym].blank?
begin begin
items = mail[item.to_sym].addrs items = mail[item.to_sym].addrs
next if items.blank? next if items.blank?
items.each do |address_data| items.each do |address_data|
email_address = address_data.address email_address = address_data.address
next if email_address.blank? next if email_address.blank?
next if email_address !~ /@/ next if email_address !~ /@/
next if email_address.match?(/\s/) next if email_address.match?(/\s/)
user_create( user_create(
firstname: address_data.display_name, firstname: address_data.display_name,
lastname: '', lastname: '',
@ -131,6 +134,7 @@ module Channel::Filter::IdentifySender
next if address.blank? next if address.blank?
next if address !~ /@/ next if address !~ /@/
next if address.match?(/\s/) next if address.match?(/\s/)
user_create( user_create(
firstname: display_name, firstname: display_name,
lastname: '', lastname: '',

View file

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

View file

@ -14,6 +14,7 @@ class Channel::Filter::MonitoringBase
def self.run(_channel, mail) def self.run(_channel, mail)
integration = integration_name integration = integration_name
return if !Setting.get("#{integration}_integration") return if !Setting.get("#{integration}_integration")
sender = Setting.get("#{integration}_sender") sender = Setting.get("#{integration}_sender")
auto_close = Setting.get("#{integration}_auto_close") auto_close = Setting.get("#{integration}_auto_close")
auto_close_state_id = Setting.get("#{integration}_auto_close_state_id") auto_close_state_id = Setting.get("#{integration}_auto_close_state_id")
@ -22,6 +23,7 @@ class Channel::Filter::MonitoringBase
return if mail[:from].blank? return if mail[:from].blank?
return if mail[:body].blank? return if mail[:body].blank?
session_user_id = mail[ 'x-zammad-session-user-id'.to_sym ] session_user_id = mail[ 'x-zammad-session-user-id'.to_sym ]
return if !session_user_id return if !session_user_id

View file

@ -6,6 +6,7 @@ module Channel::Filter::OwnNotificationLoopDetection
message_id = mail['message-id'.to_sym] message_id = mail['message-id'.to_sym]
return if !message_id return if !message_id
recedence = mail['precedence'.to_sym] recedence = mail['precedence'.to_sym]
return if !recedence return if !recedence
return if recedence !~ /bulk/i return if recedence !~ /bulk/i

View file

@ -16,9 +16,11 @@ module Channel::Filter::SenderIsSystemAddress
# in case, set sender # in case, set sender
begin begin
return if !mail[form].addrs return if !mail[form].addrs
items = mail[form].addrs items = mail[form].addrs
items.each do |item| items.each do |item|
next if !EmailAddress.find_by(email: item.address.downcase) next if !EmailAddress.find_by(email: item.address.downcase)
mail['x-zammad-ticket-create-article-sender'.to_sym] = 'Agent' mail['x-zammad-ticket-create-article-sender'.to_sym] = 'Agent'
mail['x-zammad-article-sender'.to_sym] = 'Agent' mail['x-zammad-article-sender'.to_sym] = 'Agent'
return true return true
@ -29,10 +31,12 @@ module Channel::Filter::SenderIsSystemAddress
# check if sender is agent # check if sender is agent
return if mail[:from_email].blank? return if mail[:from_email].blank?
begin begin
user = User.find_by(email: mail[:from_email].downcase) user = User.find_by(email: mail[:from_email].downcase)
return if !user return if !user
return if !user.permissions?('ticket.agent') return if !user.permissions?('ticket.agent')
mail['x-zammad-ticket-create-article-sender'.to_sym] = 'Agent' mail['x-zammad-ticket-create-article-sender'.to_sym] = 'Agent'
mail['x-zammad-article-sender'.to_sym] = 'Agent' mail['x-zammad-article-sender'.to_sym] = 'Agent'
return true return true

View file

@ -9,6 +9,7 @@ module Channel::Filter::Trusted
if !channel[:trusted] if !channel[:trusted]
mail.each_key do |key| mail.each_key do |key|
next if key !~ /^x-zammad/i next if key !~ /^x-zammad/i
mail.delete(key) mail.delete(key)
end end
return return
@ -20,6 +21,7 @@ module Channel::Filter::Trusted
# no assoc exists, remove header # no assoc exists, remove header
next if Channel::EmailParser.check_attributes_by_x_headers(key, value) next if Channel::EmailParser.check_attributes_by_x_headers(key, value)
mail.delete(key.to_sym) mail.delete(key.to_sym)
end end

View file

@ -64,6 +64,7 @@ class Chat < ApplicationModel
def self.agent_state(user_id) def self.agent_state(user_id)
return { state: 'chat_disabled' } if !Setting.get('chat') return { state: 'chat_disabled' } if !Setting.get('chat')
assets = {} assets = {}
Chat.where(active: true).each do |chat| Chat.where(active: true).each do |chat|
assets = chat.assets(assets) assets = chat.assets(assets)
@ -76,8 +77,10 @@ class Chat < ApplicationModel
runningchat_session_list_local = running_chat_session_list runningchat_session_list_local = running_chat_session_list
runningchat_session_list_local.each do |session| runningchat_session_list_local.each do |session|
next if !session['user_id'] next if !session['user_id']
user = User.lookup(id: session['user_id']) user = User.lookup(id: session['user_id'])
next if !user next if !user
assets = user.assets(assets) assets = user.assets(assets)
end end
{ {
@ -96,6 +99,7 @@ class Chat < ApplicationModel
def self.agent_state_with_sessions(user_id) def self.agent_state_with_sessions(user_id)
return { state: 'chat_disabled' } if !Setting.get('chat') return { state: 'chat_disabled' } if !Setting.get('chat')
result = agent_state(user_id) result = agent_state(user_id)
result[:active_sessions] = Chat::Session.active_chats_by_user_id(user_id) result[:active_sessions] = Chat::Session.active_chats_by_user_id(user_id)
result result
@ -146,6 +150,7 @@ class Chat < ApplicationModel
Chat::Agent.where(active: true).where('updated_at > ?', Time.zone.now - diff).each do |record| Chat::Agent.where(active: true).where('updated_at > ?', Time.zone.now - diff).each do |record|
user = User.lookup(id: record.updated_by_id) user = User.lookup(id: record.updated_by_id)
next if !user next if !user
users.push user users.push user
end end
users users
@ -180,6 +185,7 @@ optional you can ignore it for dedecated user
# send broadcast to agents # send broadcast to agents
Chat::Agent.where('active = ? OR updated_at > ?', true, Time.zone.now - 8.hours).each do |item| Chat::Agent.where('active = ? OR updated_at > ?', true, Time.zone.now - 8.hours).each do |item|
next if item.updated_by_id == ignore_user_id next if item.updated_by_id == ignore_user_id
data = { data = {
event: 'chat_status_agent', event: 'chat_status_agent',
data: Chat.agent_state(item.updated_by_id), data: Chat.agent_state(item.updated_by_id),
@ -250,6 +256,7 @@ optional you can put the max oldest chat sessions as argument
def self.cleanup_close(diff = 5.minutes) def self.cleanup_close(diff = 5.minutes)
Chat::Session.where.not(state: 'closed').where('updated_at < ?', Time.zone.now - diff).each do |chat_session| Chat::Session.where.not(state: 'closed').where('updated_at < ?', Time.zone.now - diff).each do |chat_session|
next if chat_session.recipients_active? next if chat_session.recipients_active?
chat_session.state = 'closed' chat_session.state = 'closed'
chat_session.save chat_session.save
message = { message = {
@ -276,6 +283,7 @@ check if ip address is blocked for chat
def blocked_ip?(ip) def blocked_ip?(ip)
return false if ip.blank? return false if ip.blank?
return false if block_ip.blank? return false if block_ip.blank?
ips = block_ip.split(';') ips = block_ip.split(';')
ips.each do |local_ip| ips.each do |local_ip|
return true if ip == local_ip.strip return true if ip == local_ip.strip
@ -296,9 +304,11 @@ check if country is blocked for chat
def blocked_country?(ip) def blocked_country?(ip)
return false if ip.blank? return false if ip.blank?
return false if block_country.blank? return false if block_country.blank?
geo_ip = Service::GeoIp.location(ip) geo_ip = Service::GeoIp.location(ip)
return false if geo_ip.blank? return false if geo_ip.blank?
return false if geo_ip['country_code'].blank? return false if geo_ip['country_code'].blank?
countries = block_country.split(';') countries = block_country.split(';')
countries.each do |local_country| countries.each do |local_country|
return true if geo_ip['country_code'] == local_country return true if geo_ip['country_code'] == local_country

View file

@ -14,6 +14,7 @@ class Chat::Agent < ApplicationModel
) )
if state.nil? if state.nil?
return false if !chat_agent return false if !chat_agent
return chat_agent.active return chat_agent.active
end end
if chat_agent if chat_agent

View file

@ -23,6 +23,7 @@ class Chat::Session < ApplicationModel
preferences[:participants] = [] preferences[:participants] = []
end end
return preferences[:participants] if preferences[:participants].include?(client_id) return preferences[:participants] if preferences[:participants].include?(client_id)
preferences[:participants].push client_id preferences[:participants].push client_id
if store if store
save save
@ -33,18 +34,22 @@ class Chat::Session < ApplicationModel
def recipients_active? def recipients_active?
return true if !preferences return true if !preferences
return true if !preferences[:participants] return true if !preferences[:participants]
count = 0 count = 0
preferences[:participants].each do |client_id| preferences[:participants].each do |client_id|
next if !Sessions.session_exists?(client_id) next if !Sessions.session_exists?(client_id)
count += 1 count += 1
end end
return true if count >= 2 return true if count >= 2
false false
end end
def send_to_recipients(message, ignore_client_id = nil) def send_to_recipients(message, ignore_client_id = nil)
preferences[:participants].each do |local_client_id| preferences[:participants].each do |local_client_id|
next if local_client_id == ignore_client_id next if local_client_id == ignore_client_id
Sessions.send(local_client_id, message) Sessions.send(local_client_id, message)
end end
true true
@ -52,6 +57,7 @@ class Chat::Session < ApplicationModel
def position def position
return if state != 'waiting' return if state != 'waiting'
position = 0 position = 0
Chat::Session.where(state: 'waiting').order(created_at: :asc).each do |chat_session| Chat::Session.where(state: 'waiting').order(created_at: :asc).each do |chat_session|
position += 1 position += 1
@ -63,6 +69,7 @@ class Chat::Session < ApplicationModel
def self.messages_by_session_id(session_id) def self.messages_by_session_id(session_id)
chat_session = Chat::Session.find_by(session_id: session_id) chat_session = Chat::Session.find_by(session_id: session_id)
return if !chat_session return if !chat_session
session_attributes = [] session_attributes = []
Chat::Message.where(chat_session_id: chat_session.id).order(created_at: :asc).each do |message| Chat::Message.where(chat_session_id: chat_session.id).order(created_at: :asc).each do |message|
session_attributes.push message.attributes session_attributes.push message.attributes

View file

@ -48,8 +48,10 @@ returns
%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 !self[ local_user_id ]
next if data[ app_model_user ] && data[ app_model_user ][ 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 ]) user = User.lookup(id: self[ local_user_id ])
next if !user next if !user
data = user.assets(data) data = user.assets(data)
end end
data data

View file

@ -27,6 +27,7 @@ returns if user has no permissions to search
def search_preferences(current_user) def search_preferences(current_user)
return false if Setting.get('chat') != true || !current_user.permissions?('chat.agent') return false if Setting.get('chat') != true || !current_user.permissions?('chat.agent')
{ {
prio: 900, prio: 900,
direct_search_index: true, direct_search_index: true,
@ -68,6 +69,7 @@ returns
items.each do |item| items.each do |item|
chat_session = Chat::Session.lookup(id: item[:id]) chat_session = Chat::Session.lookup(id: item[:id])
next if !chat_session next if !chat_session
chat_sessions.push chat_session chat_sessions.push chat_session
end end
return chat_sessions return chat_sessions

View file

@ -70,6 +70,7 @@ returns
if data[:file].present? if data[:file].present?
raise Exceptions::UnprocessableEntity, "No such file '#{data[:file]}'" if !File.exist?(data[:file]) raise Exceptions::UnprocessableEntity, "No such file '#{data[:file]}'" if !File.exist?(data[:file])
begin begin
file = File.open(data[:file], 'r:UTF-8') file = File.open(data[:file], 'r:UTF-8')
data[:string] = file.read data[:string] = file.read
@ -103,6 +104,7 @@ returns
item.strip! item.strip!
end end
next if !item.respond_to?(:downcase!) next if !item.respond_to?(:downcase!)
item.downcase! item.downcase!
end end
@ -124,6 +126,7 @@ returns
row.each_with_index do |item, count| row.each_with_index do |item, count|
next if item.blank? next if item.blank?
next if header[count].nil? next if header[count].nil?
if payload_last[header[count].to_sym].class != Array if payload_last[header[count].to_sym].class != Array
payload_last[header[count].to_sym] = [payload_last[header[count].to_sym]] payload_last[header[count].to_sym] = [payload_last[header[count].to_sym]]
end end
@ -136,6 +139,7 @@ returns
next if !item next if !item
next if header[count].blank? next if header[count].blank?
next if @csv_attributes_ignored&.include?(header[count].to_sym) next if @csv_attributes_ignored&.include?(header[count].to_sym)
attributes[header[count].to_sym] = if item.respond_to?(:strip) attributes[header[count].to_sym] = if item.respond_to?(:strip)
item.strip item.strip
else else
@ -170,6 +174,7 @@ returns
record = nil record = nil
%i[id number name login email].each do |lookup_by| %i[id number name login email].each do |lookup_by|
next if !attributes[lookup_by] next if !attributes[lookup_by]
params = {} params = {}
params[lookup_by] = attributes[lookup_by] params[lookup_by] = attributes[lookup_by]
record = lookup(params) record = lookup(params)
@ -208,6 +213,7 @@ returns
end end
record = new(clean_params) record = new(clean_params)
next if try == true next if try == true
record.associations_from_param(attributes) record.associations_from_param(attributes)
record.save! record.save!
rescue => e rescue => e
@ -217,6 +223,7 @@ returns
else else
stats[:updated] += 1 stats[:updated] += 1
next if try == true next if try == true
begin begin
csv_verify_attributes(clean_params) csv_verify_attributes(clean_params)
clean_params = param_cleanup(clean_params) clean_params = param_cleanup(clean_params)
@ -278,6 +285,7 @@ verify if attributes are valid, will raise an ArgumentError with "unknown attrib
end end
clean_params.each_key do |key| clean_params.each_key do |key|
next if all_clean_attributes.key?(key.to_sym) next if all_clean_attributes.key?(key.to_sym)
raise ArgumentError, "unknown attribute '#{key}' for #{new.class}." raise ArgumentError, "unknown attribute '#{key}' for #{new.class}."
end end
true true
@ -319,6 +327,7 @@ returns
next if key == 'created_at' next if key == 'created_at'
next if key == 'updated_at' next if key == 'updated_at'
next if header.include?(key) next if header.include?(key)
header.push key header.push key
end end
end end
@ -339,6 +348,7 @@ returns
record[key].each do |entry| record[key].each do |entry|
entry_count += 1 entry_count += 1
next if entry_count == -1 next if entry_count == -1
if !rows_to_add[entry_count] if !rows_to_add[entry_count]
rows_to_add[entry_count] = Array.new(header.count + 1) { '' } rows_to_add[entry_count] = Array.new(header.count + 1) { '' }
end end
@ -350,6 +360,7 @@ returns
end end
rows.push row rows.push row
next if rows_to_add.count.zero? next if rows_to_add.count.zero?
rows_to_add.each do |item| rows_to_add.each do |item|
rows.push item rows.push item
end end

View file

@ -21,6 +21,7 @@ returns
def generate_uniq_name(name) def generate_uniq_name(name)
return name if !exists?(name: name) return name if !exists?(name: name)
(1..100).each do |counter| (1..100).each do |counter|
name = "#{name}_#{counter}" name = "#{name}_#{counter}"
break if !exists?(name: name) break if !exists?(name: name)

View file

@ -29,6 +29,7 @@ class OwnModel < ApplicationModel
# return if we run import mode # return if we run import mode
return if Setting.get('import_mode') return if Setting.get('import_mode')
logger.debug { "#{self.class.name}.find(#{id}) notify created #{created_at}" } logger.debug { "#{self.class.name}.find(#{id}) notify created #{created_at}" }
class_name = self.class.name class_name = self.class.name
class_name.gsub!(/::/, '') class_name.gsub!(/::/, '')
@ -61,6 +62,7 @@ class OwnModel < ApplicationModel
# return if we run import mode # return if we run import mode
return if Setting.get('import_mode') return if Setting.get('import_mode')
logger.debug { "#{self.class.name}.find(#{id}) notify UPDATED #{updated_at}" } logger.debug { "#{self.class.name}.find(#{id}) notify UPDATED #{updated_at}" }
class_name = self.class.name class_name = self.class.name
class_name.gsub!(/::/, '') class_name.gsub!(/::/, '')
@ -93,6 +95,7 @@ class OwnModel < ApplicationModel
# return if we run import mode # return if we run import mode
return if Setting.get('import_mode') return if Setting.get('import_mode')
logger.debug { "#{self.class.name}.find(#{id}) notify TOUCH #{updated_at}" } logger.debug { "#{self.class.name}.find(#{id}) notify TOUCH #{updated_at}" }
class_name = self.class.name class_name = self.class.name
class_name.gsub!(/::/, '') class_name.gsub!(/::/, '')
@ -124,6 +127,7 @@ class OwnModel < ApplicationModel
# return if we run import mode # return if we run import mode
return if Setting.get('import_mode') return if Setting.get('import_mode')
logger.debug { "#{self.class.name}.find(#{id}) notify DESTOY #{updated_at}" } logger.debug { "#{self.class.name}.find(#{id}) notify DESTOY #{updated_at}" }
class_name = self.class.name class_name = self.class.name
class_name.gsub!(/::/, '') class_name.gsub!(/::/, '')

View file

@ -28,6 +28,7 @@ module ChecksConditionValidation
ticket_count, tickets = Ticket.selectors(validate_condition, 1, User.find(1)) ticket_count, tickets = Ticket.selectors(validate_condition, 1, User.find(1))
return true if ticket_count.present? return true if ticket_count.present?
raise Exceptions::UnprocessableEntity, 'Invalid ticket selector conditions' raise Exceptions::UnprocessableEntity, 'Invalid ticket selector conditions'
end end
end end

View file

@ -40,9 +40,11 @@ log object update activity stream, if configured - will be executed automaticall
log = false log = false
saved_changes.each_key do |key| saved_changes.each_key do |key|
next if ignored_attributes.include?(key.to_sym) next if ignored_attributes.include?(key.to_sym)
log = true log = true
end end
return true if !log return true if !log
activity_stream_log('update', self['updated_by_id']) activity_stream_log('update', self['updated_by_id'])
true true
end end

View file

@ -47,6 +47,7 @@ module HasGroupRelationDefinition
end end
return if !query.exists? return if !query.exists?
errors.add(:access, "#{group_relation_model_identifier.to_s.capitalize} can have full or granular access to group") errors.add(:access, "#{group_relation_model_identifier.to_s.capitalize} can have full or granular access to group")
end end

View file

@ -83,6 +83,7 @@ module HasGroups
# check indirect access through Roles if possible # check indirect access through Roles if possible
return false if !respond_to?(:role_access?) return false if !respond_to?(:role_access?)
role_access?(group_id, access) role_access?(group_id, access)
end end
@ -197,6 +198,7 @@ module HasGroups
# @return [Boolean] # @return [Boolean]
def groups_access_permission? def groups_access_permission?
return true if !respond_to?(:permissions?) return true if !respond_to?(:permissions?)
permissions?('ticket.agent') permissions?('ticket.agent')
end end
@ -244,6 +246,7 @@ module HasGroups
# if changes to the map were performed # if changes to the map were performed
# otherwise it's just an update of other attributes # otherwise it's just an update of other attributes
return if group_access_buffer.nil? return if group_access_buffer.nil?
yield yield
group_access_buffer = nil group_access_buffer = nil
cache_delete cache_delete
@ -356,6 +359,7 @@ module HasGroups
def ensure_group_id_parameter(group_or_id) def ensure_group_id_parameter(group_or_id)
return group_or_id if group_or_id.is_a?(Integer) return group_or_id if group_or_id.is_a?(Integer)
group_or_id.id group_or_id.id
end end

View file

@ -84,6 +84,7 @@ module HasRoles
def ensure_group_id_parameter(group_or_id) def ensure_group_id_parameter(group_or_id)
return group_or_id if group_or_id.is_a?(Integer) return group_or_id if group_or_id.is_a?(Integer)
group_or_id.id group_or_id.id
end end

View file

@ -23,6 +23,7 @@ update search index, if configured - will be executed automatically
# start background job to transfer data to search index # start background job to transfer data to search index
return true if !SearchIndexBackend.enabled? return true if !SearchIndexBackend.enabled?
Delayed::Job.enqueue(BackgroundJobSearchIndex.new(self.class.to_s, id)) Delayed::Job.enqueue(BackgroundJobSearchIndex.new(self.class.to_s, id))
true true
end end
@ -38,6 +39,7 @@ delete search index object, will be executed automatically
def search_index_destroy def search_index_destroy
return true if ignore_search_indexing?(:destroy) return true if ignore_search_indexing?(:destroy)
SearchIndexBackend.remove(self.class.to_s, id) SearchIndexBackend.remove(self.class.to_s, id)
true true
end end
@ -87,9 +89,11 @@ returns
%w[name note].each do |key| %w[name note].each do |key|
next if !self[key] next if !self[key]
next if self[key].respond_to?('blank?') && self[key].blank? next if self[key].respond_to?('blank?') && self[key].blank?
attributes[key] = self[key] attributes[key] = self[key]
end end
return true if attributes.blank? return true if attributes.blank?
attributes attributes
end end
@ -130,6 +134,7 @@ reload search index with full data
ids.each do |item_id| ids.each do |item_id|
item = find(item_id) item = find(item_id)
next if item.ignore_search_indexing?(:destroy) next if item.ignore_search_indexing?(:destroy)
begin begin
item.search_index_update_backend item.search_index_update_backend
rescue => e rescue => e

View file

@ -72,6 +72,7 @@ returns
# check order # check order
params[:order_by].each do |value| params[:order_by].each do |value|
raise "Found invalid order by value #{value}. Please use 'asc' or 'desc'." if value !~ /\A(asc|desc)\z/i raise "Found invalid order by value #{value}. Please use 'asc' or 'desc'." if value !~ /\A(asc|desc)\z/i
order_by.push(value.downcase) order_by.push(value.downcase)
end end

View file

@ -32,6 +32,7 @@ module Cti
) )
return record if !record.new_record? return record if !record.new_record?
record.comment = data[:comment] record.comment = data[:comment]
record.save! record.save!
end end
@ -72,10 +73,12 @@ returns
model = nil model = nil
map.each do |item| map.each do |item|
next if item[:model] != record.class next if item[:model] != record.class
level = item[:level] level = item[:level]
model = item[:model] model = item[:model]
end end
return if !level || !model return if !level || !model
build_item(record, model, level) build_item(record, model, level)
end end
@ -92,6 +95,7 @@ returns
article = record.articles.first article = record.articles.first
return if !article return if !article
return if article.sender.name != 'Customer' return if article.sender.name != 'Customer'
record = article record = article
end end
@ -112,8 +116,10 @@ returns
attributes.each_value do |value| attributes.each_value do |value|
next if value.class != String next if value.class != String
next if value.blank? next if value.blank?
local_caller_ids = Cti::CallerId.extract_numbers(value) local_caller_ids = Cti::CallerId.extract_numbers(value)
next if local_caller_ids.blank? next if local_caller_ids.blank?
caller_ids = caller_ids.concat(local_caller_ids) caller_ids = caller_ids.concat(local_caller_ids)
end end
@ -217,6 +223,7 @@ returns
def self.extract_numbers(text) def self.extract_numbers(text)
# see specs for example # see specs for example
return [] if !text.is_a?(String) return [] if !text.is_a?(String)
text.scan(/([\d|\s|\-|\(|\)]{6,26})/).map do |match| text.scan(/([\d|\s|\-|\(|\)]{6,26})/).map do |match|
normalize_number(match[0]) normalize_number(match[0])
end end
@ -273,17 +280,20 @@ returns
end end
return [from_comment_known, preferences_known] if from_comment_known.present? return [from_comment_known, preferences_known] if from_comment_known.present?
return ["maybe #{from_comment_maybe}", preferences_maybe] if from_comment_maybe.present? return ["maybe #{from_comment_maybe}", preferences_maybe] if from_comment_maybe.present?
nil nil
end end
def update_cti_logs def update_cti_logs
return if object != 'User' return if object != 'User'
UpdateCtiLogsByCallerJob.perform_later(caller_id) UpdateCtiLogsByCallerJob.perform_later(caller_id)
end end
def update_cti_logs_with_fg_optimization def update_cti_logs_with_fg_optimization
return if object != 'User' return if object != 'User'
return if level != 'known' return if level != 'known'
UpdateCtiLogsByCallerJob.perform_now(caller_id, limit: 20) UpdateCtiLogsByCallerJob.perform_now(caller_id, limit: 20)
UpdateCtiLogsByCallerJob.perform_later(caller_id, limit: 40, offset: 20) UpdateCtiLogsByCallerJob.perform_later(caller_id, limit: 40, offset: 20)
end end

View file

@ -320,6 +320,7 @@ Cti::Log.process(
done = false done = false
end end
raise "call_id #{call_id} already exists!" if log raise "call_id #{call_id} already exists!" if log
create( create(
direction: params['direction'], direction: params['direction'],
from: params['from'], from: params['from'],
@ -336,6 +337,7 @@ Cti::Log.process(
when 'answer' when 'answer'
raise "No such call_id #{call_id}" if !log raise "No such call_id #{call_id}" if !log
return if log.state == 'hangup' # call is already hangup, ignore answer return if log.state == 'hangup' # call is already hangup, ignore answer
log.with_lock do log.with_lock do
log.state = 'answer' log.state = 'answer'
log.start_at = Time.zone.now log.start_at = Time.zone.now
@ -349,6 +351,7 @@ Cti::Log.process(
end end
when 'hangup' when 'hangup'
raise "No such call_id #{call_id}" if !log raise "No such call_id #{call_id}" if !log
log.with_lock do log.with_lock do
log.done = done log.done = done
if params['direction'] == 'in' if params['direction'] == 'in'
@ -395,6 +398,7 @@ Cti::Log.process(
def self.push_caller_list_update?(record) def self.push_caller_list_update?(record)
list_ids = Cti::Log.log_records.pluck(:id) list_ids = Cti::Log.log_records.pluck(:id)
return true if list_ids.include?(record.id) return true if list_ids.include?(record.id)
false false
end end

View file

@ -36,6 +36,7 @@ check and if channel not exists reset configured channels for email addresses
# set in inactive if channel not longer exists # set in inactive if channel not longer exists
next if !email_address.active next if !email_address.active
email_address.save! email_address.save!
end end
end end
@ -45,9 +46,11 @@ check and if channel not exists reset configured channels for email addresses
def check_email def check_email
return true if Setting.get('import_mode') return true if Setting.get('import_mode')
return true if email.blank? return true if email.blank?
self.email = email.downcase.strip self.email = email.downcase.strip
raise Exceptions::UnprocessableEntity, 'Invalid email' if email !~ /@/ raise Exceptions::UnprocessableEntity, 'Invalid email' if email !~ /@/
raise Exceptions::UnprocessableEntity, 'Invalid email' if email.match?(/\s/) raise Exceptions::UnprocessableEntity, 'Invalid email' if email.match?(/\s/)
true true
end end
@ -79,6 +82,7 @@ check and if channel not exists reset configured channels for email addresses
total = Group.count total = Group.count
return if not_configured.zero? return if not_configured.zero?
return if total != 1 return if total != 1
group = Group.find_by(email_address_id: nil) group = Group.find_by(email_address_id: nil)
group.email_address_id = id group.email_address_id = id
group.updated_by_id = updated_by_id group.updated_by_id = updated_by_id

View file

@ -37,8 +37,10 @@ class ExternalSync < ApplicationModel
local_key_sym = local_key.to_sym local_key_sym = local_key.to_sym
next if result[local_key_sym].present? next if result[local_key_sym].present?
value = extract(remote_key, information_source) value = extract(remote_key, information_source)
next if value.blank? next if value.blank?
result[local_key_sym] = value result[local_key_sym] = value
end end
result result

View file

@ -5,11 +5,9 @@ class History < ApplicationModel
self.table_name = 'histories' self.table_name = 'histories'
# rubocop:disable Rails/InverseOf
belongs_to :history_type, class_name: 'History::Type' belongs_to :history_type, class_name: 'History::Type'
belongs_to :history_object, class_name: 'History::Object' belongs_to :history_object, class_name: 'History::Object'
belongs_to :history_attribute, class_name: 'History::Attribute' belongs_to :history_attribute, class_name: 'History::Attribute'
# rubocop:enable Rails/InverseOf
# the noop is needed since Layout/EmptyLines detects # the noop is needed since Layout/EmptyLines detects
# the block commend below wrongly as the measurement of # the block commend below wrongly as the measurement of
@ -101,6 +99,7 @@ remove whole history entries of an object
def self.remove(requested_object, requested_object_id) def self.remove(requested_object, requested_object_id)
history_object = History::Object.find_by(name: requested_object) history_object = History::Object.find_by(name: requested_object)
return if !history_object return if !history_object
History.where( History.where(
history_object_id: history_object.id, history_object_id: history_object.id,
o_id: requested_object_id, o_id: requested_object_id,

View file

@ -51,8 +51,10 @@ class ImportJob < ApplicationModel
# return [Boolean] whether the ImportJob should get rescheduled (true) or destroyed (false) # return [Boolean] whether the ImportJob should get rescheduled (true) or destroyed (false)
def reschedule?(delayed_job) def reschedule?(delayed_job)
return false if finished_at.present? return false if finished_at.present?
instance = name.constantize.new(self) instance = name.constantize.new(self)
return false if !instance.respond_to?(:reschedule?) return false if !instance.respond_to?(:reschedule?)
instance.reschedule?(delayed_job) instance.reschedule?(delayed_job)
end end

View file

@ -27,6 +27,7 @@ Job.run
jobs = Job.where(active: true) jobs = Job.where(active: true)
jobs.each do |job| jobs.each do |job|
next if !job.executable? next if !job.executable?
job.run(false, start_at) job.run(false, start_at)
end end
true true
@ -199,10 +200,12 @@ job.run(true)
(0..5).each do |minute_counter| (0..5).each do |minute_counter|
if minute_counter.nonzero? if minute_counter.nonzero?
break if day_to_check.min.zero? break if day_to_check.min.zero?
day_to_check = day_to_check + 10.minutes day_to_check = day_to_check + 10.minutes
end end
next if !timeplan['hours'][day_to_check.hour] && !timeplan['hours'][day_to_check.hour.to_s] next if !timeplan['hours'][day_to_check.hour] && !timeplan['hours'][day_to_check.hour.to_s]
next if !timeplan['minutes'][match_minutes(day_to_check.min)] && !timeplan['minutes'][match_minutes(day_to_check.min).to_s] next if !timeplan['minutes'][match_minutes(day_to_check.min)] && !timeplan['minutes'][match_minutes(day_to_check.min).to_s]
return day_to_check return day_to_check
end end
end end
@ -227,10 +230,12 @@ job.run(true)
(0..5).each do |minute_counter| (0..5).each do |minute_counter|
minute_to_check = hour_to_check + minute_counter.minutes * 10 minute_to_check = hour_to_check + minute_counter.minutes * 10
next if !timeplan['minutes'][match_minutes(minute_to_check.min)] && !timeplan['minutes'][match_minutes(minute_to_check.min).to_s] next if !timeplan['minutes'][match_minutes(minute_to_check.min)] && !timeplan['minutes'][match_minutes(minute_to_check.min).to_s]
time_to_check = minute_to_check time_to_check = minute_to_check
break break
end end
next if !minute_to_check next if !minute_to_check
return time_to_check return time_to_check
end end
@ -252,6 +257,7 @@ job.run(true)
def match_minutes(minutes) def match_minutes(minutes)
return 0 if minutes < 10 return 0 if minutes < 10
"#{minutes.to_s.gsub(/(\d)\d/, '\\1')}0".to_i "#{minutes.to_s.gsub(/(\d)\d/, '\\1')}0".to_i
end end

View file

@ -40,8 +40,10 @@ returns
%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 !self[ local_user_id ]
next if data[ User.to_app_model ][ self[ local_user_id ] ] next if data[ User.to_app_model ][ self[ local_user_id ] ]
user = User.lookup(id: self[ local_user_id ]) user = User.lookup(id: self[ local_user_id ])
next if !user next if !user
data = user.assets(data) data = user.assets(data)
end end
data data

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