Merged pull request #1483 - Working on issue #1439: Refactoring - moved out the regex matching code to better readability. Huge thanks to @muhammadn .

This commit is contained in:
Thorsten Eckel 2017-10-24 16:58:03 +02:00
parent 7e3b63a7ba
commit 378d19c691
5 changed files with 148 additions and 37 deletions

View file

@ -18,12 +18,12 @@ module Channel::Filter::Database
match_rule = meta['value'] match_rule = meta['value']
min_one_rule_exists = true min_one_rule_exists = true
if meta[:operator] == 'contains not' if meta[:operator] == 'contains not'
if value.present? && match(value, match_rule, false) if value.present? && Channel::Filter::Match::EmailRegex.match(value: value, match_rule: match_rule)
all_matches_ok = false all_matches_ok = false
Rails.logger.info " matching #{key.downcase}:'#{value}' on #{match_rule}, but shoud not" Rails.logger.info " matching #{key.downcase}:'#{value}' on #{match_rule}, but shoud not"
end end
elsif meta[:operator] == 'contains' elsif meta[:operator] == 'contains'
if value.blank? || !match(value, match_rule, true) if value.blank? || !Channel::Filter::Match::EmailRegex.match(value: value, match_rule: match_rule)
all_matches_ok = false all_matches_ok = false
Rails.logger.info " not matching #{key.downcase}:'#{value}' on #{match_rule}, but should" Rails.logger.info " not matching #{key.downcase}:'#{value}' on #{match_rule}, but should"
end end
@ -51,32 +51,4 @@ module Channel::Filter::Database
end end
def self.match(value, match_rule, _should_match, check_mode = false)
regexp = false
if match_rule =~ /^(regex:)(.+?)$/
regexp = true
match_rule = $2
end
value ||= ''
if regexp == false
match_rule_quoted = Regexp.quote(match_rule).gsub(/\\\*/, '.*')
return true if value =~ /#{match_rule_quoted}/i
return false
end
begin
return true if value =~ /#{match_rule}/i
return false
rescue => e
message = "Can't use regex '#{match_rule}' on '#{value}': #{e.message}"
Rails.logger.error message
raise message if check_mode == true
end
false
end
end end

View file

@ -0,0 +1,27 @@
module Channel::Filter::Match::EmailRegex
def self.match(value:, match_rule:, check_mode: false)
regexp = false
if match_rule =~ /^(regex:)(.+?)$/
regexp = true
match_rule = $2
end
if regexp == false
match_rule_quoted = Regexp.quote(match_rule).gsub(/\\\*/, '.*')
return true if value =~ /#{match_rule_quoted}/i
return false
end
begin
return true if value =~ /#{match_rule}/i
return false
rescue => e
message = "Can't use regex '#{match_rule}' on '#{value}': #{e.message}"
Rails.logger.error message
raise message if check_mode == true
end
false
end
end

View file

@ -1,7 +1,6 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/ # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class Channel::Filter::MonitoringBase class Channel::Filter::MonitoringBase
# according # according
# Icinga # Icinga
@ -27,7 +26,7 @@ class Channel::Filter::MonitoringBase
return if !session_user_id return if !session_user_id
# check if sender is monitoring # check if sender is monitoring
return if !Channel::Filter::Database.match(mail[:from], sender, true, true) return if !Channel::Filter::Match::EmailRegex.match(value: mail[:from], match_rule: sender, check_mode: true)
# get mail attibutes like host and state # get mail attibutes like host and state
result = {} result = {}

View file

@ -14,11 +14,7 @@ class PostmasterFilter < ApplicationModel
raise Exceptions::UnprocessableEntity, 'operator invalid, ony "contains" and "contains not" is supported' if meta['operator'].blank? || meta['operator'] !~ /^(contains|contains not)$/ raise Exceptions::UnprocessableEntity, 'operator invalid, ony "contains" and "contains not" is supported' if meta['operator'].blank? || meta['operator'] !~ /^(contains|contains not)$/
raise Exceptions::UnprocessableEntity, 'value invalid/empty' if meta['value'].blank? raise Exceptions::UnprocessableEntity, 'value invalid/empty' if meta['value'].blank?
begin begin
if meta['operator'] == 'contains not' Channel::Filter::Match::EmailRegex.match(value: 'test content', match_rule: meta['value'], check_mode: true)
Channel::Filter::Database.match('test content', meta['value'], false, true)
else
Channel::Filter::Database.match('test content', meta['value'], true, true)
end
rescue => e rescue => e
raise Exceptions::UnprocessableEntity, e.message raise Exceptions::UnprocessableEntity, e.message
end end

View file

@ -0,0 +1,117 @@
# encoding: utf-8
require 'test_helper'
class EmailRegexTest < ActiveSupport::TestCase
test 'should be able to detect valid/invalid the regex filter' do
# check with exact email, check_mode = true
sender = 'foobar@foo.bar'
from = 'foobar@foo.bar'
regex = Channel::Filter::Match::EmailRegex.match(value: from, match_rule: sender, check_mode: true)
assert_equal(true, regex)
# check with exact email
sender = 'foobar@foo.bar'
from = 'foobar@foo.bar'
regex = Channel::Filter::Match::EmailRegex.match(value: from, match_rule: sender, check_mode: false)
assert_equal(true, regex)
# check with regex: filter check_mode = true
sender = 'regex:foobar@.*'
from = 'foobar@foo.bar'
regex = Channel::Filter::Match::EmailRegex.match(value: from, match_rule: sender, check_mode: true)
assert_equal(true, regex)
# check with regex: filter
sender = 'regex:foobar@.*'
from = 'foobar@foo.bar'
regex = Channel::Filter::Match::EmailRegex.match(value: from, match_rule: sender, check_mode: false)
assert_equal(true, regex)
# check regex with regex: filter
sender = 'regex:??'
from = 'foobar@foo.bar'
regex = Channel::Filter::Match::EmailRegex.match(value: from, match_rule: sender, check_mode: false)
assert_equal(false, regex)
# check regex with raise error (check_mode = true)
assert_raises("Can't use regex '??' on 'foobar@foo.bar'") do
sender = 'regex:??'
from = 'foobar@foo.bar'
regex = Channel::Filter::Match::EmailRegex.match(value: from, match_rule: sender, check_mode: true)
end
sender = 'regex:[]'
from = 'foobar@foo.bar'
regex = Channel::Filter::Match::EmailRegex.match(value: from, match_rule: sender, check_mode: false)
assert_equal(false, regex)
# check regex with raise error, (check_mode = true)
assert_raises("Can't use regex '[]' on 'foobar@foo.bar'") do
sender = 'regex:[]'
from = 'foobar@foo.bar'
regex = Channel::Filter::Match::EmailRegex.match(value: from, match_rule: sender, check_mode: true)
end
# check regex with empty field
sender = '{}'
from = 'foobar@foo.bar'
regex = Channel::Filter::Match::EmailRegex.match(value: from, match_rule: sender, check_mode: false)
assert_equal(false, regex)
# check regex with empty field and raise error (check_mode = true)
sender = '{}'
from = 'foobar@foo.bar'
regex = Channel::Filter::Match::EmailRegex.match(value: from, match_rule: sender, check_mode: true)
assert_equal(false, regex)
# check regex with empty field
sender = ''
from = 'foobar@foo.bar'
regex = Channel::Filter::Match::EmailRegex.match(value: from, match_rule: sender, check_mode: false)
assert_equal(true, regex)
# check regex with empty field
sender = ''
from = 'foobar@foo.bar'
regex = Channel::Filter::Match::EmailRegex.match(value: from, match_rule: sender, check_mode: true)
assert_equal(true, regex)
# check regex with regex: wildcard
sender = 'regex:*'
from = 'foobar@foo.bar'
regex = Channel::Filter::Match::EmailRegex.match(value: from, match_rule: sender, check_mode: false)
assert_equal(false, regex)
# check regex with regex: wildcard and raise error (check_mode = true)
assert_raises("Can't use regex '*' on 'foobar@foo.bar'") do
sender = 'regex:*'
from = 'foobar@foo.bar'
regex = Channel::Filter::Match::EmailRegex.match(value: from, match_rule: sender, check_mode: true)
end
# check email with wildcard
sender = '*'
from = 'foobar@foo.bar'
regex = Channel::Filter::Match::EmailRegex.match(value: from, match_rule: sender, check_mode: false)
assert_equal(true, regex)
# check email with wildcard (check_mode = true)
sender = '*'
from = 'foobar@foo.bar'
regex = Channel::Filter::Match::EmailRegex.match(value: from, match_rule: sender, check_mode: true)
assert_equal(true, regex)
# check email with a different sender
sender = 'regex:nagios@.*'
from = 'foobar@foo.bar'
regex = Channel::Filter::Match::EmailRegex.match(value: from, match_rule: sender, check_mode: false)
assert_equal(false, regex)
# check email with a different sender with checkmode = true
sender = 'regex:nagios@.*'
from = 'foobar@foo.bar'
regex = Channel::Filter::Match::EmailRegex.match(value: from, match_rule: sender, check_mode: true)
assert_equal(false, regex)
end
end