Skip to content

Commit

Permalink
Requested Changes
Browse files Browse the repository at this point in the history
Changing rrule validation to allow for multuipe BYMONTH, BYMONTHDAY, BYYEARDAY and BYYEARDAY

Modified validation to inspect for SECONDLY at the rule level and now returning a list of all errors instead of the first encounterd

Fixed some linting in the rruleset test modules
  • Loading branch information
john-westcott-iv committed Apr 19, 2022
1 parent 098eff9 commit 990f4f4
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 663 deletions.
44 changes: 18 additions & 26 deletions awx/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4647,65 +4647,57 @@ class Meta:
# - Multiple DTSTART
# - At least one of RRULE is not included
# - EXDATE or RDATE is included
# - SECONDLY is used
# - BYYEARDAY
# - BYWEEKNO
# For any rule in the ruleset:
# - INTERVAL is not included
# - multiple BYMONTH
# - multiple BYMONTHDAY
# - SECONDLY is used
# - BYDAY prefixed with a number (MO is good but not 20MO)
# - Can't contain both COUNT and UNTIL
# - COUNT > 999
def validate_rrule(self, value):
rrule_value = value
multi_by_month_day = r".*?BYMONTHDAY[\:\=][0-9]+,-*[0-9]+"
multi_by_month = r".*?BYMONTH[\:\=][0-9]+,[0-9]+"
by_day_with_numeric_prefix = r".*?BYDAY[\:\=][0-9]+[a-zA-Z]{2}"
match_multiple_dtstart = re.findall(r".*?(DTSTART(;[^:]+)?\:[0-9]+T[0-9]+Z?)", rrule_value)
match_native_dtstart = re.findall(r".*?(DTSTART:[0-9]+T[0-9]+) ", rrule_value)
match_multiple_rrule = re.findall(r".*?(RULE\:[^\s]*)", rrule_value)
errors = []
if not len(match_multiple_dtstart):
raise serializers.ValidationError(_('Valid DTSTART required in rrule. Value should start with: DTSTART:YYYYMMDDTHHMMSSZ'))
errors.append(_('Valid DTSTART required in rrule. Value should start with: DTSTART:YYYYMMDDTHHMMSSZ'))
if len(match_native_dtstart):
raise serializers.ValidationError(_('DTSTART cannot be a naive datetime. Specify ;TZINFO= or YYYYMMDDTHHMMSSZZ.'))
errors.append(_('DTSTART cannot be a naive datetime. Specify ;TZINFO= or YYYYMMDDTHHMMSSZZ.'))
if len(match_multiple_dtstart) > 1:
raise serializers.ValidationError(_('Multiple DTSTART is not supported.'))
errors.append(_('Multiple DTSTART is not supported.'))
if "rrule:" not in rrule_value.lower():
raise serializers.ValidationError(_('One or more rule required in rrule.'))
errors.append(_('One or more rule required in rrule.'))
if "exdate:" in rrule_value.lower():
raise serializers.ValidationError(_('EXDATE not allowed in rrule.'))
if "rdate:" in rrule_value.lower():
raise serializers.ValidationError(_('RDATE not allowed in rrule.'))
if 'secondly' in rrule_value.lower():
raise serializers.ValidationError(_('SECONDLY is not supported.'))
if 'byyearday' in rrule_value.lower():
raise serializers.ValidationError(_("BYYEARDAY not supported."))
if 'byweekno' in rrule_value.lower():
raise serializers.ValidationError(_("BYWEEKNO not supported."))
for a_rule in match_multiple_rrule:
if 'interval' not in a_rule.lower():
raise serializers.ValidationError(_('INTERVAL required in rrule.'))
if re.match(multi_by_month_day, a_rule):
raise serializers.ValidationError(_('Multiple BYMONTHDAYs not supported.'))
if re.match(multi_by_month, a_rule):
raise serializers.ValidationError(_('Multiple BYMONTHs not supported.'))
errors.append("{0}: {1}".format(_('INTERVAL required in rrule'), a_rule))
elif 'secondly' in a_rule.lower():
errors.append("{0}: {1}".format(_('SECONDLY is not supported'), a_rule))
if re.match(by_day_with_numeric_prefix, a_rule):
raise serializers.ValidationError(_("BYDAY with numeric prefix not supported."))
errors.append("{0}: {1}".format(_("BYDAY with numeric prefix not supported"), a_rule))
if 'COUNT' in a_rule and 'UNTIL' in a_rule:
raise serializers.ValidationError(_("RRULE may not contain both COUNT and UNTIL"))
errors.append("{0}: {1}".format(_("RRULE may not contain both COUNT and UNTIL"), a_rule))
match_count = re.match(r".*?(COUNT\=[0-9]+)", a_rule)
if match_count:
count_val = match_count.groups()[0].strip().split("=")
if int(count_val[1]) > 999:
raise serializers.ValidationError(_("COUNT > 999 is unsupported."))
errors.append("{0}: {1}".format(_("COUNT > 999 is unsupported"), a_rule))

try:
Schedule.rrulestr(rrule_value)
except Exception as e:
import traceback

logger.error(traceback.format_exc())
raise serializers.ValidationError(_("rrule parsing failed validation: {}").format(e))
errors.append(_("rrule parsing failed validation: {}").format(e))

if errors:
raise serializers.ValidationError(errors)

return value


Expand Down

This file was deleted.

Loading

0 comments on commit 990f4f4

Please sign in to comment.