From 22b49edc3ce51f45a69a467202ac0470b9f29bc3 Mon Sep 17 00:00:00 2001 From: Logan Hanks Date: Tue, 25 Sep 2012 16:00:42 -0700 Subject: [PATCH] Add oauth-only view of api docs. --- r2/r2/config/routing.py | 2 + r2/r2/controllers/api_docs.py | 32 +++++++-- r2/r2/public/static/css/reddit.css | 42 ++++++++++++ r2/r2/templates/apihelp.html | 106 ++++++++++++++++++++++------- 4 files changed, 151 insertions(+), 31 deletions(-) diff --git a/r2/r2/config/routing.py b/r2/r2/config/routing.py index 8b259ba4d..0825e822a 100644 --- a/r2/r2/config/routing.py +++ b/r2/r2/config/routing.py @@ -260,6 +260,8 @@ def make_map(): mc('/dev', controller='redirect', action='redirect', dest='/dev/api') mc('/dev/api', controller='apidocs', action='docs') + mc('/dev/api/:mode', controller='apidocs', action='docs', + requirements=dict(mode="oauth")) mc("/button_info", controller="api", action="info", limit=1) diff --git a/r2/r2/controllers/api_docs.py b/r2/r2/controllers/api_docs.py index e4560c7f9..8f16e52b9 100644 --- a/r2/r2/controllers/api_docs.py +++ b/r2/r2/controllers/api_docs.py @@ -31,6 +31,7 @@ from pylons.i18n import _ from reddit_base import RedditController from r2.lib.utils import Storage from r2.lib.pages import BoringPage, ApiHelp +from r2.controllers.validator import validate, VOneOf # API sections displayed in the documentation page. # Each section can have a title and a markdown-formatted description. @@ -96,7 +97,7 @@ def api_doc(section, **kwargs): class ApidocsController(RedditController): @staticmethod - def docs_from_controller(controller, url_prefix='/api'): + def docs_from_controller(controller, url_prefix='/api', oauth_only=False): """ Examines a controller for documentation. A dictionary index of sections containing dictionaries of URLs is returned. For each URL, a @@ -142,12 +143,22 @@ class ApidocsController(RedditController): # add every variant to the index -- the templates will filter # out variants in the long-form documentation - for variant in chain([uri], docs.get('uri_variants', [])): - api_docs[docs['section']][variant][method] = docs + if oauth_only: + if not docs['oauth_scopes']: + continue + for scope in docs['oauth_scopes']: + for variant in chain([uri], + docs.get('uri_variants', [])): + api_docs[scope][variant][method] = docs + else: + for variant in chain([uri], docs.get('uri_variants', [])): + api_docs[docs['section']][variant][method] = docs return api_docs - def GET_docs(self): + @validate( + mode=VOneOf('mode', options=('methods', 'oauth'), default='methods')) + def GET_docs(self, mode): # controllers to gather docs from. from r2.controllers.api import ApiController, ApiminimalController from r2.controllers.apiv1 import APIv1Controller @@ -166,14 +177,23 @@ class ApidocsController(RedditController): # merge documentation info together. api_docs = defaultdict(dict) + oauth_index = defaultdict(set) for controller, url_prefix in api_controllers: - for section, contents in self.docs_from_controller(controller, url_prefix).iteritems(): + controller_docs = self.docs_from_controller(controller, url_prefix, + mode == 'oauth') + for section, contents in controller_docs.iteritems(): api_docs[section].update(contents) + for variant, method_dict in contents.iteritems(): + for method, docs in method_dict.iteritems(): + for scope in docs['oauth_scopes']: + oauth_index[scope].add((section, variant, method)) return BoringPage( _('api documentation'), content=ApiHelp( - api_docs=api_docs + api_docs=api_docs, + oauth_index=oauth_index, + mode=mode, ), css_class="api-help", show_sidebar=False, diff --git a/r2/r2/public/static/css/reddit.css b/r2/r2/public/static/css/reddit.css index 00cdfef86..ee70a0d20 100755 --- a/r2/r2/public/static/css/reddit.css +++ b/r2/r2/public/static/css/reddit.css @@ -5828,6 +5828,41 @@ tr.gold-accent + tr > td { text-decoration: underline; } +.api-help .toc .mode-selector { + display: inline-block; + font-size: x-small; + border-radius: 5px; + border: 1px solid #888; + margin-top: 6px; + vertical-align: middle; +} + +.api-help .toc .mode-selector .mode { + display: inline-block; + margin: 2px; + padding-top: 2px; + padding-bottom: 3px; + border-radius: 3px; + text-align: center; + width: 107px; + color: #ddd; +} + +.api-help .toc .mode-selector .mode:hover { + background-color: #ccc; + color: black; + text-decoration: none; +} + +.api-help .toc .mode-selector .mode-current { + color: black; + background-color: #eee; +} + +.api-help .toc .mode-selector .mode-current:hover { + background-color: #ddd; +} + .api-help em.placeholder { font-style: italic; font-weight: normal; @@ -5882,6 +5917,13 @@ tr.gold-accent + tr > td { border-bottom: 1px solid #aaa; } +.api-help .methods h2 .scope-id { + margin-left: 1em; + font-size: small; + font-weight: normal; + font-style: italic; +} + .api-help .endpoint .info { padding-left: 1em; border-left: 1px solid #ddd; diff --git a/r2/r2/templates/apihelp.html b/r2/r2/templates/apihelp.html index 89fd07fa5..062eb0143 100644 --- a/r2/r2/templates/apihelp.html +++ b/r2/r2/templates/apihelp.html @@ -24,11 +24,83 @@ import re from r2.lib.filters import safemarkdown from r2.controllers.api_docs import section_info + from r2.models.token import OAuth2Scope %> <%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="mode_selector(current_mode)"> + + by section + by oauth scope + + + +<%def name="api_method_toc(api)"> + API methods + ${mode_selector('section')} + + + +<%def name="oauth_toc(api, oauth_index)"> + API methods + ${mode_selector('oauth')} + + + +<%def name="section_header(section)"> +

${section_info[section]['title']}

+ %if 'description' in section_info[section]: +
+ ${unsafe(safemarkdown(section_info[section]['description']))} +
+ %endif + + +<%def name="scope_header(scope)"> +

+ ${OAuth2Scope.scope_info[scope]['name']} + ${scope} +

+
+ ${unsafe(safemarkdown(OAuth2Scope.scope_info[scope]['description']))} +
+ + <% api = thing.api_docs %> @@ -38,26 +110,11 @@
@@ -73,11 +130,10 @@
%for section in sorted(api): -

${section_info[section]['title']}

- %if 'description' in section_info[section]: -
- ${unsafe(safemarkdown(section_info[section]['description']))} -
+ %if thing.mode == 'oauth': + ${scope_header(section)} + %else: + ${section_header(section)} %endif %for uri in sorted(api[section]): %for method in sorted(api[section][uri]):