Просмотр исходного кода

Do not show non whitelisted extensions

Eric Charles 5 лет назад
Родитель
Сommit
adedbe557d

+ 0 - 101
docs/source/admin/listings.rst

@@ -1,101 +0,0 @@
-.. _listings:
-
-Listings
----------
-
-When searching extensions, JupyterLab can check the extensions against ``blacklists`` 
-and ``whitelists``. Only one mode at a time is allowed.
-
-List modes
-~~~~~~~~~~
-
-.. _blacklist_mode:
-
-Blacklist
-^^^^^^^^^
-
-Extensions can be freely downloaded without going through a vetting process.
-However, users can add malicious extensions to a blacklist.
-
-The extension manager will show all extensions except for those that have 
-been explicitly added to the blacklist. Therfore, the extension manager 
-does not allow you to install blacklisted extensions.
-
-.. _whitelist_mode:
-
-Whitelist
-^^^^^^^^^
-
-A whitelist maintains a set of approved extensions that users can freely 
-search and download.
-
-Extensions need to go through some sort of vetting process before they are 
-added to the whitelist. When using a whitelist, the extension manager 
-will highlight extensions that have been explicitly added to the whitelist.
-
-List URI
-~~~~~~~~
-
-By default, JupyterLab ships with blacklist mode enabled. The blacklist can 
-be found on https://github.com/jupyterlab/listings/blacklist.json
-
-Please open a `pull request <https://github.com/jupyterlab/jupyterlab/pulls>`__
-if you think that some extensions should be blacklisted.
-
-Open also a `pull request <https://github.com/jupyterlab/jupyterlab/pulls>`__
-if your extensions is blacklistd and you think it should not.
-
-List format
-~~~~~~~~~~~
-
-This is an example of a blacklist.
-
-.. code:: json
-
-   {
-   "blacklist": [
-      {
-         "name": "@jupyterlab-examples/launcher",
-         "type": "jupyterlab",
-         "reason": "@jupyterlab-examples/launcher is blacklisted for test purpose - Do NOT take this for granted!!!",
-         "creation_date": "2020-03-11T03:28:56.782Z",
-         "last_update_date":  "2020-03-11T03:28:56.782Z"
-      }
-   ]
-   }
-
-The ``name`` attribute support regular expressions.
-
-In the following example a ``@jupyterlab/*`` will whitelist
-all jupyterlab organization extensions.
-
-.. code:: json
-
-   {
-   "whitelistlist": [
-      {
-         "name": "@jupyterlab/*",
-         "type": "jupyterlab",
-         "reason": "@jupyterlab-examples/launcher is blacklisted for test purpose - Do NOT take this for granted!!!",
-         "creation_date": "2020-03-11T03:28:56.782Z",
-         "last_update_date":  "2020-03-11T03:28:56.782Z"
-      }
-   ]
-   }
-
-
-Server Traits
-~~~~~~~~~~~~~
-
-The administrator can use the following Traits to define the listings loading.
-
-- ``blacklist_uris``: A list of comma-separated URIs to get the blacklist
-- ``whitelist_uris``: A list of comma-separated URIs to get the whitelist
-- ``listings_refresh_ms``: The interval delay in milliseconds to refresh the lists
-- ``listings_request_options``: The optional kwargs to use for the listings HTTP requests
-
-Launch the server with e.g. ``--LabServerApp.blacklist_uris``.
-
-The details for the listings_request_options are listed
-on the `this page <https://2.python-requests.org/en/v2.7.0/api/#requests.request>`__  
-(for example, you could pass ``{'timeout': 10}`` to change the HTTP request timeout value).

+ 0 - 8
docs/source/index.rst

@@ -44,14 +44,6 @@ JupyterLab is the next-generation web-based user interface for Project Jupyter.
    user/jupyterhub
    user/export
 
-
-.. toctree::
-   :maxdepth: 1
-   :caption: Admin Guide
-
-   admin/listings
-
-
 .. toctree::
    :maxdepth: 1
    :caption: Developer Guide

+ 117 - 17
docs/source/user/extensions.rst

@@ -155,16 +155,43 @@ performs a free-text search of JupyterLab extensions on the NPM registry.
    :alt: Screenshot showing an example search result
 
 
-Blacklist
-^^^^^^^^^
+.. _listings:
 
-If you, or your administrator, has enabled the :ref:`blacklist_mode`,
-JupyterLab will first use the blacklist and remove all blacklisted
+Listings
+^^^^^^^^
+
+When searching extensions, JupyterLab displays the complete search result and 
+the user if free to install any extension.
+
+To bring more security, you or your adminstrator can enable ``blacklists`` or ``whitelists``
+mode. JupyterLab will check the extensions against the defined listings.
+
+Only one mode at a time is allowed. The details to enable configure the listings
+can be read :ref:`listings_conf`. The following details the behavior in the different
+modes.
+
+Default mode
+^^^^^^^^^^^^
+
+In the ``default`` mode, no listing is enabled and the search behavior is unchanged and
+is the one described previously.
+
+Blacklist mode
+^^^^^^^^^^^^^^
+
+Extensions can be freely downloaded without going through a vetting process.
+However, users can add malicious extensions to a blacklist. The extension manager 
+will show all extensions except for those that have 
+been explicitly added to the blacklist. Therfore, the extension manager 
+does not allow you to install blacklisted extensions.
+
+If you, or your administrator, has enabled the blacklist mode,
+JupyterLab will use the blacklist and remove all blacklisted
 extensions from your search result.
 
-You will be informed of the number of non listed extensions, but will
-not be able to see them. You can also click on that information
-message to be driven to this documentation page.
+You will be informed of the number of blacklisted extensions, but will
+not be able to see them. You can click on that message to be driven to 
+this documentation page.
 
 .. figure:: images/listings/searchresult_blacklisted.png
    :align: center
@@ -173,8 +200,8 @@ message to be driven to this documentation page.
    **Figure:** Search result in blacklist mode
 
 
-If you have installed an extension before it is blacklisted,
-the extension entry in the installed list will be highlightd
+If you have installed an extension before it has been blacklisted,
+the extension entry in the installed list will be highlighted
 in red. It is recommended that you uninstall it. You can move
 your mouse on the red cross to know more about the reason it
 is blacklisted.
@@ -186,15 +213,21 @@ is blacklisted.
    **Figure:** Blacklisted installed extension
 
 
-Whitelist
-^^^^^^^^^
+Whitelist mode
+^^^^^^^^^^^^^^
 
-If you, or your administrator, has enabled the :ref:`whitelist_mode`
-JupyterLab will first use the whitelist and only show "Install" 
-action for whitelisted extensions. The withelisted extensions
+A whitelist maintains a set of approved extensions that users can freely 
+search and install. Extensions need to go through some sort of vetting process 
+before they are added to the whitelist. When using a whitelist, the extension manager 
+will highlight extensions that have been explicitly added to the whitelist.
 
-The other extensions will be show in the search result but you
-will not be able to install them.
+If you, or your administrator, has enabled the whitelist mode
+JupyterLab will use the whitelist and only show extensions present
+in the withelist. The other extensions will not be show in the search result.
+
+You will be informed of the number of non whitelisted extensions, but will
+not be able to see them. You can click on that message to be driven to 
+this documentation page.
 
 .. figure:: images/listings/searchresult_whitelisted.png
    :align: center
@@ -203,7 +236,11 @@ will not be able to install them.
    **Figure:** Search result in whitelist mode
 
 
-The installed extensions being whitelisted are highlited in green.
+If you have installed an whitelisted extension and at some point
+in time that extension is removed from the whitelist, the extension entry 
+in the installed list will be highlighted in red. It is recommended that 
+you uninstall it. You can move your mouse on the red cross to get
+an explanation message.
 
 .. figure:: images/listings/installed_whitelisted.png
    :align: center
@@ -637,3 +674,66 @@ because these files are typically shared across Python environments.
 The location can be modified using the ``JUPYTERLAB_WORKSPACES_DIR`` environment variable. These files can be imported and exported to create default "profiles",
 using the :ref:`workspace command line tool <url-workspaces-cli>`.
 
+
+.. _listings_conf:
+
+Listing Configuration
+~~~~~~~~~~~~~~~~~~~~~
+
+By default, JupyterLab ships with blacklist mode enabled. The blacklist can 
+be found on https://github.com/jupyterlab/listings/blacklist.json
+
+Please open a `pull request <https://github.com/jupyterlab/jupyterlab/pulls>`__
+if you think that some extensions should be blacklisted.
+
+Open also a `pull request <https://github.com/jupyterlab/jupyterlab/pulls>`__
+if your extensions is blacklistd and you think it should not.
+
+This is an example of a blacklist.
+
+.. code:: json
+
+   {
+   "blacklist": [
+      {
+         "name": "@jupyterlab-examples/launcher",
+         "type": "jupyterlab",
+         "reason": "@jupyterlab-examples/launcher is blacklisted for test purpose - Do NOT take this for granted!!!",
+         "creation_date": "2020-03-11T03:28:56.782Z",
+         "last_update_date":  "2020-03-11T03:28:56.782Z"
+      }
+   ]
+   }
+
+The ``name`` attribute support regular expressions.
+
+In the following example a ``@jupyterlab/*`` will whitelist
+all jupyterlab organization extensions.
+
+.. code:: json
+
+   {
+   "whitelistlist": [
+      {
+         "name": "@jupyterlab/*",
+         "type": "jupyterlab",
+         "reason": "@jupyterlab-examples/launcher is blacklisted for test purpose - Do NOT take this for granted!!!",
+         "creation_date": "2020-03-11T03:28:56.782Z",
+         "last_update_date":  "2020-03-11T03:28:56.782Z"
+      }
+   ]
+   }
+
+
+The administrator can use the following Traits to define the listings loading.
+
+- ``blacklist_uris``: A list of comma-separated URIs to get the blacklist
+- ``whitelist_uris``: A list of comma-separated URIs to get the whitelist
+- ``listings_refresh_ms``: The interval delay in milliseconds to refresh the lists
+- ``listings_request_options``: The optional kwargs to use for the listings HTTP requests
+
+Launch the server with e.g. ``--LabServerApp.blacklist_uris``.
+
+The details for the listings_request_options are listed
+on the `this page <https://2.python-requests.org/en/v2.7.0/api/#requests.request>`__  
+(for example, you could pass ``{'timeout': 10}`` to change the HTTP request timeout value).

BIN
docs/source/user/images/listings/installed_whitelisted.png


BIN
docs/source/user/images/listings/searchresult_whitelisted.png


+ 4 - 4
packages/extensionmanager-extension/examples/listings/Makefile

@@ -1,7 +1,7 @@
-export BLACK_LIST_URIS="https://raw.githubusercontent.com/datalayer-jupyterlab/jupyterlab-listings-example/master/blacklist_simple.json"
-# export BLACK_LIST_URIS=""
-# export WHITE_LIST_URIS="https://raw.githubusercontent.com/datalayer-jupyterlab/jupyterlab-listings-example/master/whitelist_simple.json"
-export WHITE_LIST_URIS=""
+# export BLACK_LIST_URIS="https://raw.githubusercontent.com/datalayer-jupyterlab/jupyterlab-listings-example/master/blacklist_simple.json"
+export BLACK_LIST_URIS=""
+export WHITE_LIST_URIS="https://raw.githubusercontent.com/datalayer-jupyterlab/jupyterlab-listings-example/master/whitelist_simple.json"
+# export WHITE_LIST_URIS=""
 export LISTINGS_REFRESH_MS=30000
 export LISTINGS_REQUEST_OPTS="{'timeout': 10}"
 

+ 2 - 4
packages/extensionmanager-extension/listing/listings.json

@@ -1,10 +1,8 @@
 {
   "listings": {
-    "blacklist_uris": [
-      "https://raw.githubusercontent.com/jupyterlab/listings/master/blacklist.json"
-    ],
+    "blacklist_uris": [""],
     "whitelist_uris": [""],
     "blacklist": [],
-    "whitelist": ["@jupyterlab/*"]
+    "whitelist": []
   }
 }

+ 57 - 15
packages/extensionmanager/src/widget.tsx

@@ -179,24 +179,35 @@ namespace BuildPrompt {
  * VDOM for visualizing an extension entry.
  */
 function ListEntry(props: ListEntry.IProperties): React.ReactElement<any> {
-  const { entry, listMode } = props;
+  const { entry, listMode, viewType } = props;
   const flagClasses = [];
   if (entry.status && ['ok', 'warning', 'error'].indexOf(entry.status) !== -1) {
     flagClasses.push(`jp-extensionmanager-entry-${entry.status}`);
   }
   let title = entry.name;
   if (isJupyterOrg(entry.name)) {
-    flagClasses.push(`jp-extensionmanager-entry-mod-whitelisted`);
+    flagClasses.push(`jp-extensionmanager-entry-mod-jupyterlab-org`);
   }
-  if (entry.whitelistEntry) {
-    flagClasses.push(`jp-extensionmanager-entry-is-whitelisted`);
-  }
-  if (entry.blacklistEntry) {
-    flagClasses.push(`jp-extensionmanager-entry-is-blacklisted`);
+  if (
+    listMode === 'black' &&
+    entry.blacklistEntry &&
+    viewType === 'searchResult'
+  ) {
+    return <li></li>;
   }
-  if (entry.blacklistEntry?.name && listMode === 'black') {
+  if (
+    listMode === 'white' &&
+    !entry.whitelistEntry &&
+    viewType === 'searchResult'
+  ) {
     return <li></li>;
   }
+  if (listMode === 'black' && entry.blacklistEntry?.name) {
+    flagClasses.push(`jp-extensionmanager-entry-should-be-uninstalled`);
+  }
+  if (listMode === 'white' && !entry.whitelistEntry) {
+    flagClasses.push(`jp-extensionmanager-entry-should-be-uninstalled`);
+  }
   return (
     <li
       className={`jp-extensionmanager-entry ${flagClasses.join(' ')}`}
@@ -218,14 +229,26 @@ function ListEntry(props: ListEntry.IProperties): React.ReactElement<any> {
           <ToolbarButtonComponent
             icon={blacklistedIcon}
             iconLabel={`${entry.name} is blacklisted since ${entry.blacklistEntry?.creation_date} - Reason: [${entry.blacklistEntry?.reason}]`}
+            onClick={() =>
+              window.open(
+                'https://jupyterlab.readthedocs.io/en/stable/user/extensions.html'
+              )
+            }
           />
         )}
-        {entry.whitelistEntry && (
-          <ToolbarButtonComponent
-            icon={whitelistedIcon}
-            iconLabel={`${entry.name} is whitelisted since ${entry.whitelistEntry?.creation_date} - Reason: [${entry.whitelistEntry?.reason}]`}
-          />
-        )}
+        {!entry.whitelistEntry &&
+          viewType === 'installed' &&
+          listMode === 'white' && (
+            <ToolbarButtonComponent
+              icon={whitelistedIcon}
+              iconLabel={`${entry.name} is not whitelisted, please contact your administrator.`}
+              onClick={() =>
+                window.open(
+                  'https://jupyterlab.readthedocs.io/en/stable/user/extensions.html'
+                )
+              }
+            />
+          )}
       </div>
       <div className="jp-extensionmanager-entry-content">
         <div className="jp-extensionmanager-entry-description">
@@ -299,8 +322,16 @@ export namespace ListEntry {
      */
     entry: IEntry;
 
+    /**
+     * The list mode to apply.
+     */
     listMode: 'black' | 'white' | null;
 
+    /**
+     * The requested view type.
+     */
+    viewType: 'installed' | 'searchResult';
+
     /**
      * Callback to use for performing an action on the entry.
      */
@@ -318,6 +349,7 @@ export function ListView(props: ListView.IProperties): React.ReactElement<any> {
       <ListEntry
         entry={entry}
         listMode={props.listMode}
+        viewType={props.viewType}
         key={entry.name}
         performAction={props.performAction}
       />
@@ -376,8 +408,16 @@ export namespace ListView {
      */
     numPages: number;
 
+    /**
+     * The list mode to apply.
+     */
     listMode: 'black' | 'white' | null;
 
+    /**
+     * The requested view type.
+     */
+    viewType: 'installed' | 'searchResult';
+
     /**
      * The callback to use for changing the page
      */
@@ -623,7 +663,8 @@ export class ExtensionView extends VDomRenderer<ListModel> {
         installedContent.push(
           <ListView
             key="installed-items"
-            listMode={null}
+            listMode={model.listMode}
+            viewType={'installed'}
             entries={model.installed}
             numPages={1}
             onPage={value => {
@@ -694,6 +735,7 @@ export class ExtensionView extends VDomRenderer<ListModel> {
             <ListView
               key="search-items"
               listMode={model.listMode}
+              viewType={'searchResult'}
               // Filter out installed extensions:
               entries={model.searchResult.filter(
                 entry => model.installed.indexOf(entry) === -1

+ 2 - 6
packages/extensionmanager/style/base.css

@@ -174,19 +174,15 @@
   display: none;
 }
 
-.jp-extensionmanager-entry.jp-extensionmanager-entry-mod-whitelisted
+.jp-extensionmanager-entry.jp-extensionmanager-entry-mod-jupyterlab-org
   .jp-extensionmanager-entry-jupyter-org {
   display: inline;
 }
 
-.jp-extensionmanager-entry.jp-extensionmanager-entry-is-blacklisted {
+.jp-extensionmanager-entry.jp-extensionmanager-entry-should-be-uninstalled {
   background-color: var(--jp-error-color3);
 }
 
-.jp-extensionmanager-entry.jp-extensionmanager-entry-is-whitelisted {
-  background-color: var(--jp-success-color3);
-}
-
 /* Precedence order update/error/warning matters! */
 .jp-extensionmanager-entry.jp-extensionmanager-entry-update {
   border-left: solid 8px var(--jp-brand-color2);