MXS-1583 Treat independent 'users' line in OR-fashion

If there are several 'users' lines in a rule file, for a particular
user, the rules each matching line will be checked independently
until a rule match is found.

That is, the rules of each 'users' line are treated in an OR-fashion
with respect to each other.
This commit is contained in:
Johan Wikman
2018-01-29 11:48:13 +02:00
parent cf0d745c14
commit 0db538db9a
4 changed files with 76 additions and 47 deletions

View File

@ -1029,7 +1029,7 @@ static bool process_user_templates(UserMap& users, const TemplateList& templates
if (newrules.size() > 0)
{
user->append_rules(ut->type, newrules);
user->add_rules(ut->type, newrules);
}
}

View File

@ -31,20 +31,20 @@ const char* User::name() const
return m_name.c_str();
}
void User::append_rules(match_type mode, const RuleList& rules)
void User::add_rules(match_type mode, const RuleList& rules)
{
switch (mode)
{
case FWTOK_MATCH_ANY:
rules_or.insert(rules_or.end(), rules.begin(), rules.end());
rules_or_vector.push_back(rules);
break;
case FWTOK_MATCH_ALL:
rules_and.insert(rules_and.end(), rules.begin(), rules.end());
rules_and_vector.push_back(rules);
break;
case FWTOK_MATCH_STRICT_ALL:
rules_strict_and.insert(rules_strict_and.end(), rules.begin(), rules.end());
rules_strict_and_vector.push_back(rules);
break;
default:
@ -73,28 +73,39 @@ bool User::match_any(Dbfw* my_instance, DbfwSession* my_session,
bool rval = false;
if (rules_or.size() > 0 && should_match(queue))
for (RuleListVector::iterator i = rules_or_vector.begin(); i != rules_or_vector.end(); ++i)
{
char *fullquery = modutil_get_SQL(queue);
RuleList& rules_or = *i;
if (fullquery)
if (rules_or.size() > 0 && should_match(queue))
{
for (RuleList::iterator it = rules_or.begin(); it != rules_or.end(); it++)
char *fullquery = modutil_get_SQL(queue);
if (fullquery)
{
if (rule_is_active(*it))
for (RuleList::iterator j = rules_or.begin(); j != rules_or.end(); j++)
{
if (rule_matches(my_instance, my_session, queue, *it, fullquery))
if (rule_is_active(*j))
{
*rulename = MXS_STRDUP_A((*it)->name().c_str());
rval = true;
break;
if (rule_matches(my_instance, my_session, queue, *j, fullquery))
{
*rulename = MXS_STRDUP_A((*j)->name().c_str());
rval = true;
break;
}
}
}
}
MXS_FREE(fullquery);
MXS_FREE(fullquery);
}
}
if (rval)
{
break;
}
}
return rval;
}
@ -116,44 +127,54 @@ bool User::do_match(Dbfw* my_instance, DbfwSession* my_session,
bool rval = false;
bool have_active_rule = false;
std::string matching_rules;
RuleList& rules = mode == User::ALL ? rules_and : rules_strict_and;
RuleListVector& rules_vector = (mode == User::ALL ? rules_and_vector : rules_strict_and_vector);
if (rules.size() > 0 && should_match(queue))
for (RuleListVector::iterator i = rules_vector.begin(); i != rules_vector.end(); ++i)
{
char *fullquery = modutil_get_SQL(queue);
RuleList& rules = *i;
if (fullquery)
if (rules.size() > 0 && should_match(queue))
{
rval = true;
for (RuleList::iterator it = rules.begin(); it != rules.end(); it++)
char *fullquery = modutil_get_SQL(queue);
if (fullquery)
{
if (rule_is_active(*it))
rval = true;
for (RuleList::iterator j = rules.begin(); j != rules.end(); j++)
{
have_active_rule = true;
if (rule_matches(my_instance, my_session, queue, *it, fullquery))
if (rule_is_active(*j))
{
matching_rules += (*it)->name();
matching_rules += " ";
}
else
{
rval = false;
have_active_rule = true;
if (mode == User::STRICT)
if (rule_matches(my_instance, my_session, queue, *j, fullquery))
{
break;
matching_rules += (*j)->name();
matching_rules += " ";
}
else
{
rval = false;
if (mode == User::STRICT)
{
break;
}
}
}
}
}
if (!have_active_rule)
{
/** No active rules */
rval = false;
if (!have_active_rule)
{
/** No active rules */
rval = false;
}
MXS_FREE(fullquery);
}
MXS_FREE(fullquery);
}
if (rval)
{
break;
}
}

View File

@ -57,12 +57,12 @@ public:
const char* name() const;
/**
* Append new rules to existing rules
* Add new rules to existing rules
*
* @param mode Matching mode for the rule
* @param rules Rules to append
*/
void append_rules(match_type mode, const RuleList& rules);
void add_rules(match_type mode, const RuleList& rules);
/**
* Check if a query matches some rule
@ -84,11 +84,13 @@ private:
STRICT
};
RuleList rules_or; /*< If any of these rules match the action is triggered */
RuleList rules_and; /*< All of these rules must match for the action to trigger */
RuleList rules_strict_and; /*< rules that skip the rest of the rules if one of them
* fails. This is only for rules paired with 'match strict_all'. */
std::string m_name; /*< Name of the user */
typedef std::vector<RuleList> RuleListVector;
RuleListVector rules_or_vector; /*< If any of these rules match the action is triggered */
RuleListVector rules_and_vector; /*< All of these rules must match for the action to trigger */
RuleListVector rules_strict_and_vector;/*< rules that skip the rest of the rules if one of them
* fails. This is only for rules paired with 'match strict_all'. */
std::string m_name; /*< Name of the user */
/**
* Functions for matching rules