b081763f0b
Former-commit-id: e9ea0e8c1e
721 lines
16 KiB
JavaScript
721 lines
16 KiB
JavaScript
/**
|
|
* Copyright (c) 2006-2017, JGraph Ltd
|
|
* Copyright (c) 2006-2017, Gaudenz Alder
|
|
*/
|
|
OneDriveClient = function(editorUi)
|
|
{
|
|
DrawioClient.call(this, editorUi, 'odauth');
|
|
|
|
this.token = this.token;
|
|
};
|
|
|
|
// Extends DrawioClient
|
|
mxUtils.extend(OneDriveClient, DrawioClient);
|
|
|
|
/**
|
|
* Specifies if thumbnails should be enabled. Default is true.
|
|
* LATER: If thumbnails are disabled, make sure to replace the
|
|
* existing thumbnail with the placeholder only once.
|
|
*/
|
|
OneDriveClient.prototype.clientId = (window.location.hostname == 'test.draw.io') ? '0000000048148130' :
|
|
((window.location.hostname == 'drive.draw.io') ? '000000004413EC37' : '0000000040145A19');
|
|
|
|
/**
|
|
* Specifies if thumbnails should be enabled. Default is true.
|
|
* LATER: If thumbnails are disabled, make sure to replace the
|
|
* existing thumbnail with the placeholder only once.
|
|
*/
|
|
OneDriveClient.prototype.clientId2 = (window.location.hostname == 'test.draw.io') ?
|
|
'2e598409-107f-4b59-89ca-d7723c8e00a4' : '45c10911-200f-4e27-a666-9e9fca147395';
|
|
|
|
/**
|
|
* OAuth 2.0 scopes for installing Drive Apps.
|
|
*/
|
|
OneDriveClient.prototype.scopes = 'wl.skydrive_update wl.signin';
|
|
|
|
/**
|
|
* OAuth 2.0 scopes for installing Drive Apps.
|
|
*/
|
|
OneDriveClient.prototype.redirectUri = 'https://' + window.location.hostname + '/onedrive.html';
|
|
|
|
/**
|
|
* OAuth 2.0 scopes for installing Drive Apps.
|
|
*/
|
|
OneDriveClient.prototype.redirectUri2 = 'https://' + window.location.hostname + '/onedrive2.html';
|
|
|
|
/**
|
|
* Executes the first step for connecting to Google Drive.
|
|
*/
|
|
OneDriveClient.prototype.extension = '.html';
|
|
|
|
/**
|
|
* Executes the first step for connecting to Google Drive.
|
|
*/
|
|
OneDriveClient.prototype.baseUrl = 'https://api.onedrive.com/v1.0';
|
|
|
|
/**
|
|
* Checks if the client is authorized and calls the next step.
|
|
*/
|
|
OneDriveClient.prototype.updateUser = function(success, error, failOnAuth)
|
|
{
|
|
var acceptResponse = true;
|
|
|
|
var timeoutThread = window.setTimeout(mxUtils.bind(this, function()
|
|
{
|
|
acceptResponse = false;
|
|
error({code: App.ERROR_TIMEOUT});
|
|
}), this.ui.timeout);
|
|
|
|
mxUtils.get(this.baseUrl + '/drive?access_token=' + this.token, mxUtils.bind(this, function(req)
|
|
{
|
|
window.clearTimeout(timeoutThread);
|
|
|
|
if (acceptResponse)
|
|
{
|
|
if (req.getStatus() < 200 || req.getStatus() >= 300)
|
|
{
|
|
if (!failOnAuth)
|
|
{
|
|
this.logout();
|
|
|
|
this.authenticate(mxUtils.bind(this, function()
|
|
{
|
|
this.updateUser(success, error, true);
|
|
}), error);
|
|
}
|
|
else
|
|
{
|
|
error({message: mxResources.get('accessDenied')});
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var data = JSON.parse(req.getText());
|
|
this.setUser(new DrawioUser(data.owner.user.id, null, data.owner.user.displayName));
|
|
success();
|
|
}
|
|
}
|
|
}), error);
|
|
};
|
|
|
|
/**
|
|
* Authorizes the client, gets the userId and calls <open>.
|
|
*/
|
|
OneDriveClient.prototype.authenticate = function(success, error)
|
|
{
|
|
if (window.onOneDriveCallback == null)
|
|
{
|
|
var auth = mxUtils.bind(this, function()
|
|
{
|
|
var acceptAuthResponse = true;
|
|
|
|
this.ui.showAuthDialog(this, true, mxUtils.bind(this, function(remember, authSuccess)
|
|
{
|
|
var url = 'https://login.live.com/oauth20_authorize.srf?client_id=' + this.clientId +
|
|
'&scope=' + encodeURIComponent(this.scopes) + '&response_type=token' +
|
|
'&redirect_uri=' + encodeURIComponent(this.redirectUri);
|
|
|
|
var width = 525,
|
|
height = 525,
|
|
screenX = window.screenX,
|
|
screenY = window.screenY,
|
|
outerWidth = window.outerWidth,
|
|
outerHeight = window.outerHeight;
|
|
|
|
var left = screenX + Math.max(outerWidth - width, 0) / 2;
|
|
var top = screenY + Math.max(outerHeight - height, 0) / 2;
|
|
|
|
var features = ['width=' + width, 'height=' + height,
|
|
'top=' + top, 'left=' + left,
|
|
'status=no', 'resizable=yes',
|
|
'toolbar=no', 'menubar=no',
|
|
'scrollbars=yes'];
|
|
var popup = window.open(url, 'odauth', features.join(','));
|
|
|
|
if (popup != null)
|
|
{
|
|
window.onOneDriveCallback = mxUtils.bind(this, function(token, authWindow)
|
|
{
|
|
if (acceptAuthResponse)
|
|
{
|
|
window.onOneDriveCallback = null;
|
|
acceptAuthResponse = false;
|
|
|
|
try
|
|
{
|
|
if (token == null)
|
|
{
|
|
error({message: mxResources.get('accessDenied'), retry: auth});
|
|
}
|
|
else
|
|
{
|
|
if (authSuccess != null)
|
|
{
|
|
authSuccess();
|
|
}
|
|
|
|
this.setUser(null);
|
|
this.token = token;
|
|
|
|
if (remember)
|
|
{
|
|
this.setPersistentToken(token);
|
|
}
|
|
|
|
success();
|
|
}
|
|
}
|
|
catch (e)
|
|
{
|
|
error(e);
|
|
}
|
|
finally
|
|
{
|
|
if (authWindow != null)
|
|
{
|
|
authWindow.close();
|
|
}
|
|
}
|
|
}
|
|
else if (authWindow != null)
|
|
{
|
|
authWindow.close();
|
|
}
|
|
});
|
|
|
|
popup.focus();
|
|
}
|
|
}), mxUtils.bind(this, function()
|
|
{
|
|
if (acceptAuthResponse)
|
|
{
|
|
window.onOneDriveCallback = null;
|
|
acceptAuthResponse = false;
|
|
error({message: mxResources.get('accessDenied'), retry: auth});
|
|
}
|
|
}));
|
|
});
|
|
|
|
auth();
|
|
}
|
|
else
|
|
{
|
|
error({code: App.ERROR_BUSY});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Checks if the client is authorized and calls the next step.
|
|
*/
|
|
OneDriveClient.prototype.executeRequest = function(url, success, error)
|
|
{
|
|
var doExecute = mxUtils.bind(this, function(failOnAuth)
|
|
{
|
|
var acceptResponse = true;
|
|
|
|
var timeoutThread = window.setTimeout(mxUtils.bind(this, function()
|
|
{
|
|
acceptResponse = false;
|
|
error({code: App.ERROR_TIMEOUT, retry: fn});
|
|
}), this.ui.timeout);
|
|
|
|
mxUtils.get(url + '?access_token=' + this.token, mxUtils.bind(this, function(req)
|
|
{
|
|
window.clearTimeout(timeoutThread);
|
|
|
|
if (acceptResponse)
|
|
{
|
|
// 404 (file not found) is a valid response for checkExists
|
|
if ((req.getStatus() >= 200 && req.getStatus() <= 299) || req.getStatus() == 404)
|
|
{
|
|
success(req);
|
|
}
|
|
else if (req.getStatus() === 401)
|
|
{
|
|
this.clearPersistentToken();
|
|
this.setUser(null);
|
|
this.token = null;
|
|
|
|
if (!failOnAuth)
|
|
{
|
|
this.authenticate(function()
|
|
{
|
|
doExecute(true);
|
|
}, error);
|
|
}
|
|
else
|
|
{
|
|
error({message: mxResources.get('accessDenied'), retry: mxUtils.bind(this, function()
|
|
{
|
|
this.authenticate(function()
|
|
{
|
|
fn(true);
|
|
}, error);
|
|
})});
|
|
}
|
|
}
|
|
else
|
|
{
|
|
error(this.parseRequestText(req));
|
|
}
|
|
}
|
|
}), error);
|
|
});
|
|
|
|
var fn = mxUtils.bind(this, function(failOnAuth)
|
|
{
|
|
if (this.user == null)
|
|
{
|
|
this.updateUser(function()
|
|
{
|
|
fn(true);
|
|
}, error, failOnAuth);
|
|
}
|
|
else
|
|
{
|
|
doExecute(failOnAuth);
|
|
}
|
|
});
|
|
|
|
if (this.token == null)
|
|
{
|
|
this.authenticate(function()
|
|
{
|
|
fn(true);
|
|
}, error);
|
|
}
|
|
else
|
|
{
|
|
fn(false);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Checks if the client is authorized and calls the next step.
|
|
*/
|
|
OneDriveClient.prototype.getLibrary = function(id, success, error)
|
|
{
|
|
this.getFile(id, success, error, false, true);
|
|
};
|
|
|
|
/**
|
|
* Checks if the client is authorized and calls the next step.
|
|
*/
|
|
OneDriveClient.prototype.getFile = function(id, success, error, denyConvert, asLibrary)
|
|
{
|
|
asLibrary = (asLibrary != null) ? asLibrary : false;
|
|
|
|
this.executeRequest(this.baseUrl + '/drive/items/' + id, mxUtils.bind(this, function(req)
|
|
{
|
|
if (req.getStatus() >= 200 && req.getStatus() <= 299)
|
|
{
|
|
var meta = JSON.parse(req.getText());
|
|
|
|
// Handles .vsdx, Gliffy and PNG+XML files by creating a temporary file
|
|
if ((/\.vsdx$/i.test(meta.name) || /\.gliffy$/i.test(meta.name) || /\.png$/i.test(meta.name)))
|
|
{
|
|
var mimeType = (meta.file != null) ? meta.file.mimeType : null;
|
|
this.ui.convertFile(meta['@content.downloadUrl'], meta.name, mimeType,
|
|
this.extension, success, error);
|
|
}
|
|
else
|
|
{
|
|
var acceptResponse = true;
|
|
|
|
var timeoutThread = window.setTimeout(mxUtils.bind(this, function()
|
|
{
|
|
acceptResponse = false;
|
|
error({code: App.ERROR_TIMEOUT})
|
|
}), this.ui.timeout);
|
|
|
|
this.ui.loadUrl(meta['@content.downloadUrl'], mxUtils.bind(this, function(data)
|
|
{
|
|
window.clearTimeout(timeoutThread);
|
|
|
|
if (acceptResponse)
|
|
{
|
|
if (asLibrary)
|
|
{
|
|
success(new OneDriveLibrary(this.ui, data, meta));
|
|
}
|
|
else
|
|
{
|
|
success(new OneDriveFile(this.ui, data, meta));
|
|
}
|
|
}
|
|
}), mxUtils.bind(this, function(req)
|
|
{
|
|
window.clearTimeout(timeoutThread);
|
|
|
|
if (acceptResponse)
|
|
{
|
|
error(this.parseRequestText(req));
|
|
}
|
|
}), meta.file != null && meta.file.mimeType != null &&
|
|
meta.file.mimeType.substring(0, 6) == 'image/');
|
|
}
|
|
}
|
|
else
|
|
{
|
|
error(this.parseRequestText(req));
|
|
}
|
|
}), error);
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
OneDriveClient.prototype.renameFile = function(file, filename, success, error)
|
|
{
|
|
if (file != null && filename != null)
|
|
{
|
|
// TODO: How to force overwrite file with same name?
|
|
this.checkExists(file.meta.parentReference.id, filename, false, mxUtils.bind(this, function(checked)
|
|
{
|
|
if (checked)
|
|
{
|
|
var url = this.baseUrl + '/drive/items/' + file.meta.id;
|
|
this.writeFile(url, JSON.stringify({name: filename}), 'PATCH', 'application/json', success, error);
|
|
}
|
|
else
|
|
{
|
|
error();
|
|
}
|
|
}));
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
OneDriveClient.prototype.moveFile = function(id, folderId, success, error)
|
|
{
|
|
var url = this.baseUrl + '/drive/items/' + id;
|
|
this.writeFile(url, JSON.stringify({parentReference: {id: folderId}}), 'PATCH', 'application/json', success, error);
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
OneDriveClient.prototype.insertLibrary = function(filename, data, success, error, folderId)
|
|
{
|
|
this.insertFile(filename, data, success, error, true, folderId);
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
OneDriveClient.prototype.insertFile = function(filename, data, success, error, asLibrary, folderId)
|
|
{
|
|
asLibrary = (asLibrary != null) ? asLibrary : false;
|
|
|
|
this.checkExists(folderId, filename, true, mxUtils.bind(this, function(checked)
|
|
{
|
|
if (checked)
|
|
{
|
|
var folder = (folderId != null) ? 'items/' + folderId : 'special/documents';
|
|
var url = this.baseUrl + '/drive/' + folder + '/children/' + filename + '/content';
|
|
|
|
this.writeFile(url, data, 'PUT', null, mxUtils.bind(this, function(meta)
|
|
{
|
|
if (asLibrary)
|
|
{
|
|
success(new OneDriveLibrary(this.ui, data, meta));
|
|
}
|
|
else
|
|
{
|
|
success(new OneDriveFile(this.ui, data, meta));
|
|
}
|
|
}), error);
|
|
}
|
|
else
|
|
{
|
|
error();
|
|
}
|
|
}))
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
OneDriveClient.prototype.checkExists = function(parentId, filename, askReplace, fn)
|
|
{
|
|
var path = (parentId != null) ? 'items/' + parentId : 'special/documents';
|
|
|
|
this.executeRequest(this.baseUrl + '/drive/' + path + '/children/' + filename, mxUtils.bind(this, function(req)
|
|
{
|
|
if (req.getStatus() == 404)
|
|
{
|
|
fn(true);
|
|
}
|
|
else
|
|
{
|
|
if (askReplace)
|
|
{
|
|
this.ui.spinner.stop();
|
|
|
|
this.ui.confirm(mxResources.get('replaceIt', [filename]), function()
|
|
{
|
|
fn(true);
|
|
}, function()
|
|
{
|
|
fn(false);
|
|
});
|
|
}
|
|
else
|
|
{
|
|
this.ui.spinner.stop();
|
|
|
|
this.ui.showError(mxResources.get('error'), mxResources.get('fileExists'), mxResources.get('ok'), function()
|
|
{
|
|
fn(false);
|
|
});
|
|
}
|
|
}
|
|
}), function(req)
|
|
{
|
|
fn(false);
|
|
}, true);
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
OneDriveClient.prototype.saveFile = function(file, success, error)
|
|
{
|
|
var url = this.baseUrl + '/drive/items/' + file.meta.id + '/content/';
|
|
this.writeFile(url, file.getData(), 'PUT', null, success, error);
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
OneDriveClient.prototype.writeFile = function(url, data, method, contentType, success, error)
|
|
{
|
|
if (url != null && data != null)
|
|
{
|
|
var doExecute = mxUtils.bind(this, function(failOnAuth)
|
|
{
|
|
var acceptResponse = true;
|
|
|
|
var timeoutThread = window.setTimeout(mxUtils.bind(this, function()
|
|
{
|
|
acceptResponse = false;
|
|
error({code: App.ERROR_TIMEOUT, retry: fn});
|
|
}), this.ui.timeout);
|
|
|
|
var req = new mxXmlRequest(url + '?access_token=' + this.token, data, method);
|
|
|
|
req.setRequestHeaders = function(request, params)
|
|
{
|
|
// Space deletes content type header. Specification says "text/plain"
|
|
// should work but returns an 415 Unsupported Media Type error
|
|
request.setRequestHeader('Content-Type', contentType || ' ');
|
|
};
|
|
|
|
req.send(mxUtils.bind(this, function(req)
|
|
{
|
|
window.clearTimeout(timeoutThread);
|
|
|
|
if (acceptResponse)
|
|
{
|
|
if (req.getStatus() >= 200 && req.getStatus() <= 299)
|
|
{
|
|
success(JSON.parse(req.getText()));
|
|
}
|
|
else if (req.getStatus() === 401)
|
|
{
|
|
this.clearPersistentToken();
|
|
this.setUser(null);
|
|
this.token = null;
|
|
|
|
if (!failOnAuth)
|
|
{
|
|
this.authenticate(function()
|
|
{
|
|
doExecute(true);
|
|
}, error);
|
|
}
|
|
else
|
|
{
|
|
error({message: mxResources.get('accessDenied'), retry: mxUtils.bind(this, function()
|
|
{
|
|
this.authenticate(function()
|
|
{
|
|
fn(true);
|
|
}, error);
|
|
})});
|
|
}
|
|
}
|
|
else
|
|
{
|
|
error(this.parseRequestText(req));
|
|
}
|
|
}
|
|
}), mxUtils.bind(this, function(req)
|
|
{
|
|
window.clearTimeout(timeoutThread);
|
|
|
|
if (acceptResponse)
|
|
{
|
|
error(this.parseRequestText(req));
|
|
}
|
|
}));
|
|
});
|
|
|
|
var fn = mxUtils.bind(this, function(failOnAuth)
|
|
{
|
|
if (this.user == null)
|
|
{
|
|
this.updateUser(function()
|
|
{
|
|
fn(true);
|
|
}, error, failOnAuth);
|
|
}
|
|
else
|
|
{
|
|
doExecute(failOnAuth);
|
|
}
|
|
});
|
|
|
|
if (this.token == null)
|
|
{
|
|
this.authenticate(function()
|
|
{
|
|
fn(true);
|
|
}, error);
|
|
}
|
|
else
|
|
{
|
|
fn(false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
error({message: mxResources.get('unknownError')});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Checks if the client is authorized and calls the next step.
|
|
*/
|
|
OneDriveClient.prototype.parseRequestText = function(req)
|
|
{
|
|
var result = {message: mxResources.get('unknownError')};
|
|
|
|
try
|
|
{
|
|
result = JSON.parse(req.getText());
|
|
}
|
|
catch (e)
|
|
{
|
|
// ignore
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* Checks if the client is authorized and calls the next step.
|
|
*/
|
|
OneDriveClient.prototype.pickLibrary = function(fn)
|
|
{
|
|
this.pickFile(fn);
|
|
};
|
|
|
|
/**
|
|
* Checks if the client is authorized and calls the next step.
|
|
*/
|
|
OneDriveClient.prototype.pickFolder = function(fn)
|
|
{
|
|
OneDrive.save(
|
|
{
|
|
clientId: this.clientId2,
|
|
action: 'query',
|
|
openInNewWindow: true,
|
|
advanced:
|
|
{
|
|
'redirectUri': this.redirectUri2
|
|
},
|
|
success: function(files)
|
|
{
|
|
fn(files);
|
|
},
|
|
cancel: function()
|
|
{
|
|
// do nothing
|
|
},
|
|
error: mxUtils.bind(this, function(e)
|
|
{
|
|
this.ui.showError(mxResources.get('error'), e);
|
|
})
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Checks if the client is authorized and calls the next step.
|
|
*/
|
|
OneDriveClient.prototype.pickFile = function(fn)
|
|
{
|
|
fn = (fn != null) ? fn : mxUtils.bind(this, function(id)
|
|
{
|
|
this.ui.loadFile('W' + encodeURIComponent(id));
|
|
});
|
|
|
|
OneDrive.open(
|
|
{
|
|
clientId: this.clientId2,
|
|
action: 'query',
|
|
multiSelect: false,
|
|
advanced:
|
|
{
|
|
'redirectUri': this.redirectUri2
|
|
},
|
|
success: function(files)
|
|
{
|
|
if (files != null && files.value != null && files.value.length > 0)
|
|
{
|
|
fn(files.value[0].id);
|
|
}
|
|
},
|
|
cancel: function()
|
|
{
|
|
// do nothing
|
|
},
|
|
error: mxUtils.bind(this, function(e)
|
|
{
|
|
this.ui.showError(mxResources.get('error'), e);
|
|
})
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Checks if the client is authorized and calls the next step.
|
|
*/
|
|
OneDriveClient.prototype.logout = function()
|
|
{
|
|
this.clearPersistentToken();
|
|
this.setUser(null);
|
|
this.token = null;
|
|
};
|