Browse Source

Fetch the listings uri from the listings handler

Eric Charles 5 years ago
parent
commit
c7bfec9831

+ 4 - 0
examples/listings/README.md

@@ -1,3 +1,7 @@
+# JupyterLab Listings Example
+
 ```bash
 make dev
+# or...
+make dev-watch
 ```

+ 0 - 3
packages/extensionmanager-extension/listing/builtin_blacklist.json

@@ -1,3 +0,0 @@
-{
-  "blacklist": []
-}

+ 0 - 3
packages/extensionmanager-extension/listing/builtin_whitelist.json

@@ -1,3 +0,0 @@
-{
-  "whitelist": []
-}

+ 3 - 1
packages/extensionmanager-extension/listing/listings.json

@@ -1,6 +1,8 @@
 {
   "listings": {
     "blacklist_uri": "",
-    "whitelist_uri": ""
+    "builtin_blacklist": [],
+    "whitelist_uri": "",
+    "builtin_whitelist": ["@jupyterlab/*"]
   }
 }

+ 50 - 23
packages/extensionmanager/src/listings.ts

@@ -1,6 +1,10 @@
 // Copyright (c) Jupyter Development Team.
 // Distributed under the terms of the Modified BSD License.
 
+import { URLExt } from '@jupyterlab/coreutils';
+
+import { ServerConnection } from '@jupyterlab/services';
+
 /**
  * Listing search result structure (subset).
  *
@@ -22,6 +26,13 @@ export interface IListResult {
   time: string;
 }
 
+export interface IListingApi {
+  listings: {
+    blacklist_uri: string;
+    whitelist_uri: string;
+  };
+}
+
 /**
  * An object for searching an List registry.
  *
@@ -29,16 +40,18 @@ export interface IListResult {
 export class Lister {
   /**
    * Create a Lister object.
-   *
-   * @param blackListUri The URI of the list registry to use.
-   * @param whiteListUri The URI of the CDN to use for fetching full package data.
    */
-  constructor(
-    blackListUri = 'http://localhost:8888/listings/blacklist.json',
-    whiteListUri = 'http://localhost:8888/listings/whitelist.json'
-  ) {
-    this.blackListUri = blackListUri;
-    this.whiteListUri = whiteListUri;
+  constructor() {
+    requestAPI<IListingApi>(
+      '@jupyterlab/extensionmanager-extension/listings.json'
+    )
+      .then(data => {
+        this.blackListUri = data.listings.blacklist_uri;
+        this.whiteListUri = data.listings.whitelist_uri;
+      })
+      .catch(error => {
+        console.error(error);
+      });
   }
 
   /**
@@ -48,7 +61,7 @@ export class Lister {
    * @param pageination The pagination size to use. See registry API documentation for acceptable values.
    */
   getBlackList(): Promise<IListResult> {
-    const uri = new URL('', this.blackListUri);
+    const uri = new URL(this.blackListUri);
     return fetch(uri.toString()).then((response: Response) => {
       if (response.ok) {
         return response.json();
@@ -64,7 +77,7 @@ export class Lister {
    * @param pageination The pagination size to use. See registry API documentation for acceptable values.
    */
   getWhiteList(): Promise<IListResult> {
-    const uri = new URL('', this.whiteListUri);
+    const uri = new URL(this.whiteListUri);
     return fetch(uri.toString()).then((response: Response) => {
       if (response.ok) {
         return response.json();
@@ -85,19 +98,33 @@ export class Lister {
 }
 
 /**
+ * Call the API extension
  *
+ * @param endPoint API REST end point for the extension
+ * @param init Initial values for the request
+ * @returns The response body interpreted as JSON
  */
-export function isWhiteListed(name: string): boolean {
-  /**
-   * A list of whitelisted NPM orgs.
-   */
-  const whitelist = ['jupyterlab', 'jupyter-widgets'];
-  const parts = name.split('/');
-  const first = parts[0];
-  return (
-    parts.length > 1 && // Has a first part
-    !!first && // with a finite length
-    first[0] === '@' && // corresponding to an org name
-    whitelist.indexOf(first.slice(1)) !== -1 // in the org whitelist.
+async function requestAPI<T>(
+  endPoint: string = '',
+  init: RequestInit = {}
+): Promise<T> {
+  // Make request to Jupyter API
+  const settings = ServerConnection.makeSettings();
+  const requestUrl = URLExt.join(
+    settings.baseUrl,
+    settings.appUrl,
+    'api/listings/',
+    endPoint
   );
+  let response: Response;
+  try {
+    response = await ServerConnection.makeRequest(requestUrl, init, settings);
+  } catch (error) {
+    throw new ServerConnection.NetworkError(error);
+  }
+  const data = await response.json();
+  if (!response.ok) {
+    throw new ServerConnection.ResponseError(response, data.message);
+  }
+  return data;
 }

+ 8 - 7
packages/extensionmanager/src/model.ts

@@ -647,19 +647,18 @@ export class ListModel extends VDomModel {
     // Start both queries before awaiting:
 
     const blacklistingPromise = this.performGetBlacklist();
-    const blacklistingMap = await blacklistingPromise;
-
+    this._blacklistingMap = await blacklistingPromise;
     const whitelistingPromise = this.performGetWhitelist();
-    const whitelistingMap = await whitelistingPromise;
+    this._whitelistingMap = await whitelistingPromise;
 
     const searchMapPromise = this.performSearch(
-      blacklistingMap,
-      whitelistingMap
+      this._blacklistingMap,
+      this._whitelistingMap
     );
     const installedMapPromise = this.queryInstalled(
       refreshInstalled,
-      blacklistingMap,
-      whitelistingMap
+      this._blacklistingMap,
+      this._whitelistingMap
     );
 
     // Await results:
@@ -812,6 +811,8 @@ export class ListModel extends VDomModel {
   private _searchResult: IEntry[];
   private _pendingActions: Promise<any>[] = [];
   private _debouncedUpdate: Debouncer<void, void>;
+  private _blacklistingMap: Map<string, IListEntry>;
+  private _whitelistingMap: Map<string, IListEntry>;
 }
 
 /**

+ 0 - 5
packages/extensionmanager/src/widget.tsx

@@ -10,7 +10,6 @@ import {
   Collapse,
   InputGroup,
   Checkbox,
-  Switch,
   blacklistedIcon,
   jupyterIcon,
   refreshIcon,
@@ -67,10 +66,6 @@ export class SearchBar extends React.Component<
           rightIcon="search"
         />
         <br />
-        <Switch
-          checked={false}
-          label="I understand that extensions managed through this interface run arbitrary code that may be dangerous."
-        />
         <Checkbox label="I understand that extensions managed through this interface run arbitrary code that may be dangerous." />
       </div>
     );

+ 0 - 8
packages/ui-components/src/blueprint.tsx

@@ -26,10 +26,6 @@ import {
   Checkbox as BPCheckbox,
   ICheckboxProps
 } from '@blueprintjs/core/lib/cjs/components/forms/controls';
-import {
-  Switch as BPSwitch,
-  ISwitchProps
-} from '@blueprintjs/core/lib/cjs/components/forms/controls';
 export { Intent } from '@blueprintjs/core/lib/cjs/common/intent';
 
 import { classes } from './utils';
@@ -89,7 +85,3 @@ export const Select = (props: ISelectProps<any> & CommonProps<any>) => (
 export const Checkbox = (props: ICheckboxProps & CommonProps<any>) => (
   <BPCheckbox {...props} className={classes(props.className, 'jp-Checkbox')} />
 );
-
-export const Switch = (props: ISwitchProps & CommonProps<any>) => (
-  <BPSwitch {...props} className={classes(props.className, 'jp-Switch')} />
-);