diff --git a/r2/r2/controllers/api.py b/r2/r2/controllers/api.py index 20f78cc73..995c7f32b 100644 --- a/r2/r2/controllers/api.py +++ b/r2/r2/controllers/api.py @@ -2122,8 +2122,7 @@ class ApiController(RedditController): @validatedForm(VFlairManager(), VModhash(), - user = VExistingUname("name", allow_deleted=True, - prefer_existing=True), + user = VFlairAccount("name"), text = VFlairText("text"), css_class = VFlairCss("css_class")) @api_doc(api_section.flair) @@ -2173,8 +2172,7 @@ class ApiController(RedditController): @validatedForm(VFlairManager(), VModhash(), - user = VExistingUname("name", allow_deleted=True, - prefer_existing=True)) + user = VFlairAccount("name")) @api_doc(api_section.flair) def POST_deleteflair(self, form, jquery, user): # Check validation. @@ -2216,8 +2214,7 @@ class ApiController(RedditController): line_result.error('row', 'improperly formatted row, ignoring') continue - user = VExistingUname('name', allow_deleted=True, - prefer_existing=True).run(name) + user = VFlairAccount('name').run(name) if not user: line_result.error('user', "unable to resolve user `%s', ignoring" @@ -2296,8 +2293,7 @@ class ApiController(RedditController): @paginated_listing(max_page_size=1000) @validate(VFlairManager(), - user = VOptionalExistingUname('name', allow_deleted=True, - prefer_existing=True)) + user = VFlairAccount('name')) @api_doc(api_section.flair) def GET_flairlist(self, num, after, reverse, count, user): flair = FlairList(num, after, reverse, '', user) @@ -2381,7 +2377,7 @@ class ApiController(RedditController): details='flair_clear_template') @validate(VUser(), - user = VOptionalExistingUname('name')) + user = VFlairAccount('name')) def POST_flairselector(self, user): if user and not (c.user_is_admin or c.site.is_moderator(c.user)): # ignore user parameter if c.user is not mod/admin @@ -2390,9 +2386,9 @@ class ApiController(RedditController): @validatedForm(VUser(), VModhash(), - user = VOptionalExistingUname('name'), + user = VFlairAccount('name'), flair_template = VFlairTemplateByID('flair_template_id'), - text = VFlairText("text")) + text = VFlairText('text')) @api_doc(api_section.flair) def POST_selectflair(self, form, jquery, user, flair_template, text): if not flair_template: diff --git a/r2/r2/controllers/errors.py b/r2/r2/controllers/errors.py index 4daaa864d..7fec8eb48 100644 --- a/r2/r2/controllers/errors.py +++ b/r2/r2/controllers/errors.py @@ -88,6 +88,7 @@ error_list = dict(( ('TOO_OLD', _("that's a piece of history now; it's too late to reply to it")), ('BAD_CSS_NAME', _('invalid css name')), ('TOO_MUCH_FLAIR_CSS', _('too many flair css classes')), + ('BAD_FLAIR_TARGET', _('not a valid flair target')), ('OAUTH2_INVALID_CLIENT', _('invalid client id')), ('OAUTH2_ACCESS_DENIED', _('access denied by the user')), ('CONFIRM', _("please confirm the form")), diff --git a/r2/r2/controllers/validator/validator.py b/r2/r2/controllers/validator/validator.py index 32b3b2618..c2f593c6e 100644 --- a/r2/r2/controllers/validator/validator.py +++ b/r2/r2/controllers/validator/validator.py @@ -1028,45 +1028,27 @@ class VUrl(VRequired): pass return params -class VOptionalExistingUname(VRequired): - def __init__(self, item, allow_deleted=False, prefer_existing=False, - *a, **kw): - self.allow_deleted = allow_deleted - self.prefer_existing = prefer_existing +class VExistingUname(VRequired): + def __init__(self, item, *a, **kw): VRequired.__init__(self, item, errors.NO_USER, *a, **kw) def run(self, name): - if self.prefer_existing: - result = self._lookup(name, False) - if not result and self.allow_deleted: - result = self._lookup(name, True) - else: - result = self._lookup(name, self.allow_deleted) - return result or self.error(errors.USER_DOESNT_EXIST) - - def _lookup(self, name, allow_deleted): if name and name.startswith('~') and c.user_is_admin: try: user_id = int(name[1:]) return Account._byID(user_id, True) except (NotFound, ValueError): - return None + self.error(errors.USER_DOESNT_EXIST) # make sure the name satisfies our user name regexp before # bothering to look it up. name = chkuser(name) if name: try: - return Account._by_name(name, allow_deleted=allow_deleted) + return Account._by_name(name) except NotFound: - return None - -class VExistingUname(VOptionalExistingUname): - def run(self, name): - user = VOptionalExistingUname.run(self, name) - if not user: - self.error() - return user + self.error(errors.USER_DOESNT_EXIST) + self.error() def param_docs(self): return { @@ -1667,6 +1649,22 @@ class VTarget(Validator): if name and self.target_re.match(name): return name +class VFlairAccount(VRequired): + def __init__(self, item, *a, **kw): + VRequired.__init__(self, item, errors.BAD_FLAIR_TARGET, *a, **kw) + + def _lookup(self, name, allow_deleted): + try: + return Account._by_name(name, allow_deleted=allow_deleted) + except NotFound: + return None + + def run(self, name): + return ( + self._lookup(name, False) + or self._lookup(name, True) + or self.error()) + class VFlairCss(VCssName): def __init__(self, param, max_css_classes=10, **kw): self.max_css_classes = max_css_classes @@ -1688,7 +1686,6 @@ class VFlairCss(VCssName): return css - class VFlairText(VLength): def __init__(self, param, max_length=64, **kw): VLength.__init__(self, param, max_length, **kw)