1"""Tornado handlers for listing extensions."""
2
3# Copyright (c) Jupyter Development Team.
4# Distributed under the terms of the Modified BSD License.
5
6import json
7
8import requests
9import tornado
10
11from .server import APIHandler
12
13LISTINGS_URL_SUFFIX='@jupyterlab/extensionmanager-extension/listings.json'
14
15
16def fetch_listings(logger):
17    """Fetch the listings for the extension manager."""
18    if not logger:
19        from traitlets import log
20        logger = log.get_logger()
21    if len(ListingsHandler.blocked_extensions_uris) > 0:
22        blocked_extensions = []
23        for blocked_extensions_uri in ListingsHandler.blocked_extensions_uris:
24            logger.info('Fetching blocked_extensions from {}'.format(ListingsHandler.blocked_extensions_uris))
25            r = requests.request('GET', blocked_extensions_uri, **ListingsHandler.listings_request_opts)
26            j = json.loads(r.text)
27            for b in j['blocked_extensions']:
28                blocked_extensions.append(b)
29            ListingsHandler.blocked_extensions = blocked_extensions
30    if len(ListingsHandler.allowed_extensions_uris) > 0:
31        allowed_extensions = []
32        for allowed_extensions_uri in ListingsHandler.allowed_extensions_uris:
33            logger.info('Fetching allowed_extensions from {}'.format(ListingsHandler.allowed_extensions_uris))
34            r = requests.request('GET', allowed_extensions_uri, **ListingsHandler.listings_request_opts)
35            j = json.loads(r.text)
36            for w in j['allowed_extensions']:
37                allowed_extensions.append(w)
38        ListingsHandler.allowed_extensions = allowed_extensions
39    ListingsHandler.listings = json.dumps({
40        'blocked_extensions_uris': list(ListingsHandler.blocked_extensions_uris),
41        'allowed_extensions_uris': list(ListingsHandler.allowed_extensions_uris),
42        'blocked_extensions': ListingsHandler.blocked_extensions,
43        'allowed_extensions': ListingsHandler.allowed_extensions,
44    })
45
46
47class ListingsHandler(APIHandler):
48    """An handler that returns the listings specs."""
49
50    """Below fields are class level fields that are accessed and populated
51    by the initialization and the fetch_listings methods.
52    Some fields are initialized before the handler creation in the
53    handlers.py#add_handlers method.
54    Having those fields predefined reduces the guards in the methods using
55    them.
56    """
57    # The list of blocked_extensions URIS.
58    blocked_extensions_uris = set()
59    # The list of allowed_extensions URIS.
60    allowed_extensions_uris = set()
61    # The blocked extensions extensions.
62    blocked_extensions = []
63    # The allowed extensions extensions.
64    allowed_extensions = []
65    # The provider request options to be used for the request library.
66    listings_request_opts = {}
67    # The PeriodicCallback that schedule the call to fetch_listings method.
68    pc = None
69
70
71    def get(self, path):
72        """Get the listings for the extension manager."""
73        self.set_header('Content-Type', 'application/json')
74        if path == LISTINGS_URL_SUFFIX:
75            self.write(ListingsHandler.listings)
76        else:
77            raise tornado.web.HTTPError(400)
78