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>
<%def name="api_uri(uri)">${unsafe(re.sub(r'{(\w+)}', r'\1', uri))}%def>
+<%def name="api_uri_with_sr_maybe(uri, in_sr)">${api_uri(("[/r/{subreddit}]" if in_sr else "") + uri)}%def>
<%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