diff --git a/r2/r2/controllers/api.py b/r2/r2/controllers/api.py index 2d40df705..13d83389b 100755 --- a/r2/r2/controllers/api.py +++ b/r2/r2/controllers/api.py @@ -375,7 +375,7 @@ class ApiController(RedditController, OAuth2ResourceController): rate_user = True, prefix = 'fetchtitle_'), VUser(), - url = VSanitizedUrl(['url'])) + url = VSanitizedUrl('url')) def POST_fetch_title(self, form, jquery, url): if form.has_errors('ratelimit', errors.RATELIMIT): form.set_html(".title-status", ""); @@ -2824,16 +2824,19 @@ class ApiController(RedditController, OAuth2ResourceController): @noresponse(VUser(), VModhash(), client=VOAuth2ClientID()) + @api_doc(api_section.apps) def POST_revokeapp(self, client): if client: client.revoke(c.user) @validatedForm(VUser(), VModhash(), - name=VRequired('name', errors.NO_TEXT), + name=VRequired('name', errors.NO_TEXT, + docs=dict(name=_("a name for the app"))), about_url=VSanitizedUrl('about_url'), icon_url=VSanitizedUrl('icon_url'), redirect_uri=VUrl('redirect_uri', allow_self=False)) + @api_doc(api_section.apps) def POST_updateapp(self, form, jquery, name, about_url, icon_url, redirect_uri): if (form.has_errors('name', errors.NO_TEXT) | form.has_errors('redirect_uri', errors.BAD_URL, errors.NO_URL)): @@ -2877,6 +2880,7 @@ class ApiController(RedditController, OAuth2ResourceController): VModhash(), client=VOAuth2ClientDeveloper(), account=VExistingUnameNotSelf('name')) + @api_doc(api_section.apps) def POST_adddeveloper(self, form, jquery, client, account): if not client: form.set_html('.status', _('error')) @@ -2894,6 +2898,7 @@ class ApiController(RedditController, OAuth2ResourceController): VModhash(), client=VOAuth2ClientDeveloper(), account=VExistingUnameNotSelf('name')) + @api_doc(api_section.apps) def POST_removedeveloper(self, form, jquery, client, account): if client and account and not form.has_errors('name'): g.log.debug('removing developer: %s', account.name) @@ -2903,6 +2908,7 @@ class ApiController(RedditController, OAuth2ResourceController): @noresponse(VUser(), VModhash(), client=VOAuth2ClientDeveloper()) + @api_doc(api_section.apps) def POST_deleteapp(self, client): if client: client.deleted = True @@ -2911,7 +2917,9 @@ class ApiController(RedditController, OAuth2ResourceController): @validatedForm(VUser(), VModhash(), client=VOAuth2ClientDeveloper(), - icon_file=VLength('file', max_length=1024*32)) + icon_file=VLength('file', max_length=1024*32, + docs=dict(file=_("an icon (72x72)")))) + @api_doc(api_section.apps) def POST_setappicon(self, form, jquery, client, icon_file): if client and icon_file: filename = 'icon-%s' % client._id diff --git a/r2/r2/controllers/api_docs.py b/r2/r2/controllers/api_docs.py index 942422de8..a6596c3ca 100644 --- a/r2/r2/controllers/api_docs.py +++ b/r2/r2/controllers/api_docs.py @@ -38,6 +38,9 @@ section_info = { 'account': { 'title': _('account'), }, + 'apps': { + 'title': _('apps'), + }, 'flair': { 'title': _('flair'), }, diff --git a/r2/r2/controllers/validator/validator.py b/r2/r2/controllers/validator/validator.py index 8c8582507..b2ab481ec 100644 --- a/r2/r2/controllers/validator/validator.py +++ b/r2/r2/controllers/validator/validator.py @@ -74,14 +74,15 @@ def can_comment_link(article): class Validator(object): default_param = None - def __init__(self, param=None, default=None, post=True, get=True, url=True): + def __init__(self, param=None, default=None, post=True, get=True, url=True, + docs=None): if param: self.param = param else: self.param = self.default_param self.default = default - self.post, self.get, self.url = post, get, url + self.post, self.get, self.url, self.docs = post, get, url, docs self.has_errors = False def set_error(self, error, msg_params = {}, field = False): @@ -99,6 +100,8 @@ class Validator(object): param_info = {} for param in filter(None, tup(self.param)): param_info[param] = None + if self.docs: + param_info.update(self.docs) return param_info def __call__(self, url): @@ -992,6 +995,9 @@ class VSanitizedUrl(Validator): def run(self, url): return utils.sanitize_url(url) + def param_docs(self): + return {self.param: _("a valid URL")} + class VUrl(VRequired): def __init__(self, item, allow_self = True, lookup = True, *a, **kw): self.allow_self = allow_self @@ -1031,11 +1037,15 @@ class VUrl(VRequired): return self.error(errors.BAD_URL) def param_docs(self): + if isinstance(self.param, (list, tuple)): + param_names = self.param + else: + param_names = [self.param] params = {} try: - params[self.param[0]] = _('a valid URL') - params[self.param[1]] = _('a subreddit') - params[self.param[2]] = _('boolean value') + params[param_names[0]] = _('a valid URL') + params[param_names[1]] = _('a subreddit') + params[param_names[2]] = _('boolean value') except IndexError: pass return params @@ -1837,6 +1847,7 @@ class VOneTimePassword(Validator): class VOAuth2ClientID(VRequired): default_param = "client_id" + default_param_doc = _("an app") def __init__(self, param=None, *a, **kw): VRequired.__init__(self, param, errors.OAUTH2_INVALID_CLIENT, *a, **kw) @@ -1849,7 +1860,12 @@ class VOAuth2ClientID(VRequired): else: self.error() + def param_docs(self): + return {self.default_param: self.default_param_doc} + class VOAuth2ClientDeveloper(VOAuth2ClientID): + default_param_doc = _("an app developed by the user") + def run(self, client_id): client = super(VOAuth2ClientDeveloper, self).run(client_id) if not client or not client.has_developer(c.user):