diff --git a/r2/r2/controllers/api.py b/r2/r2/controllers/api.py index 64c3581b9..072a11799 100755 --- a/r2/r2/controllers/api.py +++ b/r2/r2/controllers/api.py @@ -677,7 +677,7 @@ class ApiController(RedditController, OAuth2ResourceController): @validatedForm(VSrModerator(), VModhash(), target=VExistingUname('name'), type_and_permissions=VPermissions('type', 'permissions')) - @api_doc(api_section.users) + @api_doc(api_section.users, uses_site=True) def POST_setpermissions(self, form, jquery, target, type_and_permissions): if form.has_errors('name', errors.USER_DOESNT_EXIST, errors.NO_USER): return @@ -870,7 +870,7 @@ class ApiController(RedditController, OAuth2ResourceController): @validatedForm(VUser(), VModhash(), ip=ValidIP()) - @api_doc(api_section.subreddits) + @api_doc(api_section.subreddits, uses_site=True) def POST_accept_moderator_invite(self, form, jquery, ip): rel = c.site.get_moderator_invite(c.user) if not c.site.remove_moderator_invite(c.user): @@ -1550,7 +1550,7 @@ class ApiController(RedditController, OAuth2ResourceController): stylesheet_contents = nop('stylesheet_contents'), prevstyle = VLength('prevstyle', max_length=36), op = VOneOf('op',['save','preview'])) - @api_doc(api_section.subreddits) + @api_doc(api_section.subreddits, uses_site=True) def POST_subreddit_stylesheet(self, form, jquery, stylesheet_contents = '', prevstyle='', op='save'): @@ -1648,7 +1648,7 @@ class ApiController(RedditController, OAuth2ResourceController): @validatedForm(VSrModerator(perms='config'), VModhash(), name = VCssName('img_name')) - @api_doc(api_section.subreddits) + @api_doc(api_section.subreddits, uses_site=True) def POST_delete_sr_img(self, form, jquery, name): """ Called upon requested delete on /about/stylesheet. @@ -1669,7 +1669,7 @@ class ApiController(RedditController, OAuth2ResourceController): @require_oauth2_scope("modconfig") @validatedForm(VSrModerator(perms='config'), VModhash()) - @api_doc(api_section.subreddits) + @api_doc(api_section.subreddits, uses_site=True) def POST_delete_sr_header(self, form, jquery): """ Called when the user request that the header on a sr be reset. @@ -1711,7 +1711,7 @@ class ApiController(RedditController, OAuth2ResourceController): img_type = VImageType('img_type'), form_id = VLength('formid', max_length = 100), header = VInt('header', max=1, min=0)) - @api_doc(api_section.subreddits) + @api_doc(api_section.subreddits, uses_site=True) def POST_upload_sr_img(self, file, header, name, form_id, img_type): """ Called on /about/stylesheet when an image needs to be replaced @@ -2668,7 +2668,7 @@ class ApiController(RedditController, OAuth2ResourceController): link = VFlairLink('link'), text = VFlairText("text"), css_class = VFlairCss("css_class")) - @api_doc(api_section.flair) + @api_doc(api_section.flair, uses_site=True) def POST_flair(self, form, jquery, user, link, text, css_class): if link: flair_type = LINK_FLAIR @@ -2740,7 +2740,7 @@ class ApiController(RedditController, OAuth2ResourceController): @validatedForm(VSrModerator(perms='flair'), VModhash(), user = VFlairAccount("name")) - @api_doc(api_section.flair) + @api_doc(api_section.flair, uses_site=True) def POST_deleteflair(self, form, jquery, user): # Check validation. if form.has_errors('name', errors.USER_DOESNT_EXIST, errors.NO_USER): @@ -2762,7 +2762,7 @@ class ApiController(RedditController, OAuth2ResourceController): @validate(VSrModerator(perms='flair'), VModhash(), flair_csv = nop('flair_csv')) - @api_doc(api_section.flair) + @api_doc(api_section.flair, uses_site=True) def POST_flaircsv(self, flair_csv): limit = 100 # max of 100 flair settings per call results = FlairCsv() @@ -2829,7 +2829,7 @@ class ApiController(RedditController, OAuth2ResourceController): @validatedForm(VUser(), VModhash(), flair_enabled = VBoolean("flair_enabled")) - @api_doc(api_section.flair) + @api_doc(api_section.flair, uses_site=True) def POST_setflairenabled(self, form, jquery, flair_enabled): setattr(c.user, 'flair_%s_enabled' % c.site._id, flair_enabled) c.user._commit() @@ -2846,7 +2846,7 @@ class ApiController(RedditController, OAuth2ResourceController): flair_self_assign_enabled = VBoolean("flair_self_assign_enabled"), link_flair_self_assign_enabled = VBoolean("link_flair_self_assign_enabled")) - @api_doc(api_section.flair) + @api_doc(api_section.flair, uses_site=True) def POST_flairconfig(self, form, jquery, flair_enabled, flair_position, link_flair_position, flair_self_assign_enabled, link_flair_self_assign_enabled): @@ -2878,7 +2878,7 @@ class ApiController(RedditController, OAuth2ResourceController): @require_oauth2_scope("modflair") @paginated_listing(max_page_size=1000) @validate(user = VFlairAccount('name')) - @api_doc(api_section.flair) + @api_doc(api_section.flair, uses_site=True) def GET_flairlist(self, num, after, reverse, count, user): flair = FlairList(num, after, reverse, '', user) return BoringPage(_("API"), content = flair).render() @@ -2892,7 +2892,7 @@ class ApiController(RedditController, OAuth2ResourceController): text_editable = VBoolean('text_editable'), flair_type = VOneOf('flair_type', (USER_FLAIR, LINK_FLAIR), default=USER_FLAIR)) - @api_doc(api_section.flair) + @api_doc(api_section.flair, uses_site=True) def POST_flairtemplate(self, form, jquery, flair_template, text, css_class, text_editable, flair_type): if text is None: @@ -2957,7 +2957,7 @@ class ApiController(RedditController, OAuth2ResourceController): @validatedForm(VSrModerator(perms='flair'), VModhash(), flair_template = VFlairTemplateByID('flair_template_id')) - @api_doc(api_section.flair) + @api_doc(api_section.flair, uses_site=True) def POST_deleteflairtemplate(self, form, jquery, flair_template): idx = FlairTemplateBySubredditIndex.by_sr(c.site._id) if idx.delete_by_id(flair_template._id): @@ -2969,7 +2969,7 @@ class ApiController(RedditController, OAuth2ResourceController): @validatedForm(VSrModerator(perms='flair'), VModhash(), flair_type = VOneOf('flair_type', (USER_FLAIR, LINK_FLAIR), default=USER_FLAIR)) - @api_doc(api_section.flair) + @api_doc(api_section.flair, uses_site=True) def POST_clearflairtemplates(self, form, jquery, flair_type): FlairTemplateBySubredditIndex.clear(c.site._id, flair_type=flair_type) jquery.refresh() @@ -2998,7 +2998,7 @@ class ApiController(RedditController, OAuth2ResourceController): link = VFlairLink('link'), flair_template_id = nop('flair_template_id'), text = VFlairText('text')) - @api_doc(api_section.flair) + @api_doc(api_section.flair, uses_site=True) def POST_selectflair(self, form, jquery, user, link, flair_template_id, text): if link: diff --git a/r2/r2/controllers/api_docs.py b/r2/r2/controllers/api_docs.py index 20456d948..72e71a2bc 100644 --- a/r2/r2/controllers/api_docs.py +++ b/r2/r2/controllers/api_docs.py @@ -82,7 +82,7 @@ section_info = { api_section = Storage((k, k) for k in section_info) -def api_doc(section, **kwargs): +def api_doc(section, uses_site=False, **kwargs): """ Add documentation annotations to the decorated function. @@ -93,6 +93,7 @@ def api_doc(section, **kwargs): if 'extends' in kwargs: kwargs['extends'] = kwargs['extends']._api_doc doc.update(kwargs) + doc['uses_site'] = uses_site doc['section'] = section doc['lineno'] = api_function.func_code.co_firstlineno @@ -148,6 +149,9 @@ class ApidocsController(RedditController): del docs['extensions'] docs['uri'] = uri + if api_doc['uses_site']: + docs["in-subreddit"] = True + oauth_perms = getattr(func, 'oauth2_perms', {}) docs['oauth_scopes'] = oauth_perms.get('allowed_scopes', []) diff --git a/r2/r2/controllers/front.py b/r2/r2/controllers/front.py index d997deda7..01a119efd 100755 --- a/r2/r2/controllers/front.py +++ b/r2/r2/controllers/front.py @@ -103,7 +103,7 @@ class FrontController(RedditController, OAuth2ResourceController): # redirect should be smarter and handle extensions, etc. return self.redirect(new_url, code=301) - @api_doc(api_section.listings) + @api_doc(api_section.listings, uses_site=True) def GET_random(self): """The Serendipity button""" sort = rand.choice(('new','hot')) @@ -222,6 +222,7 @@ class FrontController(RedditController, OAuth2ResourceController): depth=VInt('depth')) @api_doc(api_section.listings, uri='/comments/{article}', + uses_site=True, extensions=['json', 'xml']) def GET_comments(self, article, comment, context, sort, limit, depth): """Comment page for a given 'article'.""" @@ -395,7 +396,7 @@ class FrontController(RedditController, OAuth2ResourceController): @pagecache_policy(PAGECACHE_POLICY.LOGGEDIN_AND_LOGGEDOUT) @require_oauth2_scope("modconfig") - @api_doc(api_section.moderation) + @api_doc(api_section.moderation, uses_site=True) def GET_stylesheet(self): """Fetches a subreddit's current stylesheet.""" if g.css_killswitch: @@ -453,7 +454,7 @@ class FrontController(RedditController, OAuth2ResourceController): @paginated_listing(max_page_size=500, backend='cassandra') @validate(mod=nop('mod'), action=VOneOf('type', ModAction.actions)) - @api_doc(api_section.moderation) + @api_doc(api_section.moderation, uses_site=True) def GET_moderationlog(self, num, after, reverse, count, mod, action): if not c.user_is_loggedin or not (c.user_is_admin or c.site.is_moderator(c.user)): @@ -816,7 +817,7 @@ class FrontController(RedditController, OAuth2ResourceController): recent=VMenu('t', TimeMenu, remember=False), restrict_sr=VBoolean('restrict_sr', default=False), syntax=VOneOf('syntax', options=SearchQuery.known_syntaxes)) - @api_doc(api_section.search, extensions=['json', 'xml']) + @api_doc(api_section.search, extensions=['json', 'xml'], uses_site=True) def GET_search(self, query, num, reverse, after, count, sort, recent, restrict_sr, syntax): """Search links page.""" diff --git a/r2/r2/controllers/listingcontroller.py b/r2/r2/controllers/listingcontroller.py index 9f5182c21..e0ae1159c 100755 --- a/r2/r2/controllers/listingcontroller.py +++ b/r2/r2/controllers/listingcontroller.py @@ -380,7 +380,7 @@ class HotController(FixListing, ListingController): return c.site.title @require_oauth2_scope("read") - @listing_api_doc(uri='/hot') + @listing_api_doc(uri='/hot', uses_site=True) def GET_listing(self, **env): self.requested_ad = request.get.get('ad') self.infotext = request.get.get('deleted') and strings.user_deleted @@ -422,7 +422,7 @@ class NewController(ListingController): return self.redirect(request.fullpath) @require_oauth2_scope("read") - @listing_api_doc(uri='/new') + @listing_api_doc(uri='/new', uses_site=True) def GET_listing(self, **env): if request.params.get('sort') == 'rising': return self.redirect(add_sr('/rising')) @@ -468,7 +468,8 @@ class BrowseController(ListingController): @require_oauth2_scope("read") @validate(t = VMenu('sort', ControversyTimeMenu)) - @listing_api_doc(uri='/{sort}', uri_variants=['/top', '/controversial']) + @listing_api_doc(uri='/{sort}', uri_variants=['/top', '/controversial'], + uses_site=True) def GET_listing(self, sort, t, **env): self.sort = sort if sort == 'top': diff --git a/r2/r2/controllers/wiki.py b/r2/r2/controllers/wiki.py index e62dbc738..a8761667a 100644 --- a/r2/r2/controllers/wiki.py +++ b/r2/r2/controllers/wiki.py @@ -300,7 +300,7 @@ class WikiApiController(WikiController): content=nop(('content')), page_name=VWikiPageName('page'), reason=VPrintable('reason', 256, empty_error=None)) - @api_doc(api_section.wiki, uri='/api/wiki/edit') + @api_doc(api_section.wiki, uri='/api/wiki/edit', uses_site=True) def POST_wiki_edit(self, pageandprevious, content, page_name, reason): page, previous = pageandprevious @@ -358,6 +358,7 @@ class WikiApiController(WikiController): act=VOneOf('act', ('del', 'add')), user=VExistingUname('username')) @api_doc(api_section.wiki, uri='/api/wiki/alloweditor/{act}', + uses_site=True, uri_variants=['/api/wiki/alloweditor/%s' % act for act in ('del', 'add')]) def POST_wiki_allow_editor(self, act, page, user): if not user: @@ -373,7 +374,7 @@ class WikiApiController(WikiController): @validate(VModhash(), VWikiModerator(), pv=VWikiPageAndVersion(('page', 'revision'))) - @api_doc(api_section.wiki, uri='/api/wiki/hide') + @api_doc(api_section.wiki, uri='/api/wiki/hide', uses_site=True) def POST_wiki_revision_hide(self, pv): page, revision = pv if not revision: @@ -383,7 +384,7 @@ class WikiApiController(WikiController): @validate(VModhash(), VWikiModerator(), pv=VWikiPageAndVersion(('page', 'revision'))) - @api_doc(api_section.wiki, uri='/api/wiki/revert') + @api_doc(api_section.wiki, uri='/api/wiki/revert', uses_site=True) def POST_wiki_revision_revert(self, pv): page, revision = pv if not revision: diff --git a/r2/r2/templates/apihelp.html b/r2/r2/templates/apihelp.html index a3718ee52..2d2b8a530 100644 --- a/r2/r2/templates/apihelp.html +++ b/r2/r2/templates/apihelp.html @@ -30,6 +30,7 @@ <%def name="api_method_id(uri, method)">${method}_${uri.replace('/', '_').strip('_')} <%def name="api_uri(uri)">${unsafe(re.sub(r'{(\w+)}', r'\1', uri))} +<%def name="api_uri_with_sr_maybe(uri, in_sr)">${api_uri(("[/r/{subreddit}]" if in_sr else "") + uri)} <%def name="mode_selector(current_mode)"> @@ -181,6 +182,8 @@ if docs['uri'] != uri: continue + in_subreddit = 'in-subreddit' in docs + extends = docs.get('extends') %>
@@ -192,7 +195,7 @@

${method}  - ${api_uri(uri)} + ${api_uri_with_sr_maybe(uri, in_subreddit)} %if 'extensions' in docs: [ ${' | '.join('.'+extension for extension in docs['extensions'])} ] @@ -209,7 +212,7 @@ %if 'uri_variants' in docs:
    %for variant in docs['uri_variants']: -
  • → ${api_uri(variant)}
  • +
  • → ${api_uri_with_sr_maybe(variant, in_subreddit)}
  • %endfor
%endif