/* * Copyright (C) 1998-2018 by Northwoods Software Corporation * All Rights Reserved. * * Go One Drive */ import * as go from "../../release/go"; import * as gcs from "./GoCloudStorage"; import {Promise} from "es6-promise"; /** *

Class for saving / loading GoJS Diagram models * to / from Microsoft One Drive. * As with all {@link GoCloudStorage} subclasses (with the exception of {@link GoLocalStorage}, any page using GoDropBox must be served on a web server.

*

Note: Makes use of OneDrive FilePicker for JavaScript v7.2. Any page * using GoOneDrive must include a script tag with src set to https://js.live.net/v7.2/OneDrive.js.

* @category Storage */ export class GoOneDrive extends gcs.GoCloudStorage { private _oneDriveFilepicker: any; private _oauthToken: string; /** * @constructor * @param {go.Diagram[]} managedDiagrams An array of GoJS Diagrams whose model(s) will be saved to * / loaded from OneDrive. Can also be a single Diagram. * @param {string} clientId The client ID of the application in use (given by Microsoft in Microsoft Dev Center) * @param {string} defaultModel String representation of the default model data for new diagrams. If this is null, default new diagrams * will be empty. Usually a value given by calling .toJson() on a GoJS Diagram's Model. * @param {string} iconsRelativeDirectory The directory path relative to the page in which this instance of GoOneDrive exists, in which * the storage service brand icons can be found. The default value is "../goCloudStorageIcons/". */ constructor(managedDiagrams: go.Diagram|go.Diagram[], clientId: string, defaultModel?: string, iconsRelativeDirectory?: string) { super(managedDiagrams, defaultModel, clientId); this._oauthToken = null; this.ui.id = "goOneDriveSavePrompt"; if (window['OneDrive']) { this._oneDriveFilepicker = window['OneDrive']; } this.authorize(false); // // on construction, check if there is an access_token in the window URI (there will be if redirected from a permissions grant page) this._serviceName = "Microsoft OneDrive"; } /** * Get / set the global oauthToken. Only used to authorize requests in {@link load}, {@link save}, and {@link remove} * when the {@link oneDriveFilepicker} property is not used. Not needed when the oneDriveFilePicker is used, as action-specific tokens (issued by the Microsoft-provided * OneDrive Filepicker) are issued then. oauthToken is null after construction, * but can be set or refreshed with calls to {@link authorize}. * @function. * @return {string} */ get oauthToken(): string { return this._oauthToken } set oauthToken(value: string) { this._oauthToken = value } /** * Get OneDrive Filepicker object. Used to display a Microsoft user's OneDrive files. * @function. * @return {any} */ get oneDriveFilepicker(): any { return this._oneDriveFilepicker } /** * Get OAuth 2.0 token for Microsoft OneDrive API requests with a specific Microsoft account. Sets {@link oauthToken}. * @param {Boolean} refreshToken Whether to get a new access token (triggers a page redirect) (true) or try to find / use the one in the browser * window URI (no redirect) (false) * @return {Promise} Returns a Promise that resolves with a boolean stating whether authorization was succesful (true) or failed (false). */ public authorize(refreshToken?: boolean) { const storage = this; return new Promise(function(resolve: Function, reject: Function){ if (!refreshToken && window.location.hash.indexOf("access_token") !== -1) { let accessToken: string = window.location.hash.substring(window.location.hash.indexOf('=') + 1, window.location.hash.indexOf('&')); storage.oauthToken = accessToken; resolve(true); } else if (refreshToken) { let authUrl: string = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=' + storage.clientId + '&scope=files.readwrite.all&response_type=token&redirect_uri=' + window.location.href + ''; window.location.href = authUrl; resolve(true); } }); } /** * Get information about the currently logged in Microsoft user. Some fields of particular note include: * *

Note: If {@link oauthToken} is not valid or has expired, a page redirect to the Microsoft Account sign in will occur.

* @return {Promise} Returns a Promise that resolves with information about the currently logged in Microsoft user */ public getUserInfo() { const storage = this; return new Promise(function(resolve: Function, reject: Function) { let xhr: XMLHttpRequest = new XMLHttpRequest(); if (!storage.oauthToken) { if(window.location.hash.indexOf("access_token") == -1) { reject("No acessToken in current uri"); storage.authorize(true); } else { reject("oauthToken not set"); storage.authorize(false); } } else { xhr.open('GET', 'https://graph.microsoft.com/v1.0/me'); xhr.setRequestHeader('Authorization', 'Bearer ' + storage.oauthToken); xhr.onreadystatechange = function() { if (xhr.readyState == 4 && xhr.status == 200) { resolve(JSON.parse(xhr.response)); } else if (xhr.status == 401) { // unauthorized request (expired token) storage.authorize(true); reject(xhr.response); } } xhr.send(); } }); } /** * Check whether a file exists at a given path. * @param {string} path A valid MS OneDrive filepath to save current diagram model to * Path must be of the form: /drive/root:/{item-path} * @return {Promise} Returns a Promise that resolves with a boolean stating whether a file exists at a given path */ public checkFileExists(path: string) { const storage = this; if (path.indexOf('.diagram') === -1) path += '.diagram'; return new Promise(function (resolve: Function, reject: Function) { let xhr: XMLHttpRequest = new XMLHttpRequest(); xhr.open('GET', 'https://graph.microsoft.com/v1.0' + path, true); xhr.setRequestHeader('Authorization', 'Bearer ' + storage.oauthToken); xhr.onreadystatechange = function () { let bool, err; if (xhr.readyState === 4) { if (xhr.status === 200) { bool = true } else if (xhr.status === 401) { storage.authorize(true); } else if (xhr.status === 404) { bool = false; } else { err = xhr.response; } resolve(bool); if (err) reject(err); } } xhr.send(); }); } /** *

Get the OneDrive file reference object at a given path. Properties of particular note include:

*