diff --git a/api-data-store-server-javascript/src/js/api/server-data-store-facade.js b/api-data-store-server-javascript/src/js/api/server-data-store-facade.js index 9bfd200b354f6181bac67a8b679ea7517db7ed41..52be1744c59f570b61d5783f86240738ef3c2cd0 100644 --- a/api-data-store-server-javascript/src/js/api/server-data-store-facade.js +++ b/api-data-store-server-javascript/src/js/api/server-data-store-facade.js @@ -45,30 +45,52 @@ _DataStoreServerInternal.prototype.jsonRequestData = function(params) { return JSON.stringify(params); } -_DataStoreServerInternal.prototype.sendHttpRequest = function(httpMethod, contentType, url, data, callback) { +_DataStoreServerInternal.prototype.sendHttpRequest = function(httpMethod, contentType, url, data) { const xhr = new XMLHttpRequest(); xhr.open(httpMethod, url); - xhr.setRequestHeader("content-type", contentType); - xhr.onreadystatechange = function() { - if (xhr.readyState === XMLHttpRequest.DONE) { - const status = xhr.status; - if (status >= 200 && status < 300) { - callback(xhr.responseText); - } else if(status >= 400 && status < 500) { - let response = JSON.parse(xhr.responseText); - alert(response.error[1].message); - } else if(status >= 500 && status < 600) { - let response = JSON.parse(xhr.responseText); - alert(response.error[1].message); - } else { - alert("ERROR: " + xhr.responseText); + xhr.responseType = "blob"; + + return new Promise((resolve, reject) => { + xhr.onreadystatechange = function() { + if (xhr.readyState === XMLHttpRequest.DONE) { + const status = xhr.status; + const response = xhr.response; + + if (status >= 200 && status < 300) { + const contentType = this.getResponseHeader('content-type'); + + switch (contentType) { + case 'text/plain': + // Fall through. + case'application/json': { + response.text().then((blobResponse) => resolve(blobResponse)) + .catch((error) => reject(error)); + break; + } + case 'application/octet-stream': { + resolve(response); + break; + } + default: { + reject("Client error HTTP response. Unsupported content-type received."); + break; + } + } + } else if (status >= 400 && status < 600) { + if (response.size > 0) { + response.text().then((blobResponse) => reject(JSON.parse(blobResponse).error[1].message)) + .catch((error) => reject(error)); + } else { + reject(xhr.statusText); + } + } else { + reject("ERROR: " + xhr.responseText); + } } - - - } - }; - xhr.send(data); - } + }; + xhr.send(data); + }); +} @@ -141,13 +163,15 @@ _DataStoreServerInternal.prototype.parseUri = function(str) { /** Helper method for checking response from DSS server */ -function parseJsonResponse(rawResponse, action) { - let response = JSON.parse(rawResponse); - if(response.error){ - alert(response.error[1].message); - }else{ - action(response); - } +function parseJsonResponse(rawResponse) { + return new Promise((resolve, reject) => { + let response = JSON.parse(rawResponse); + if (response.error) { + reject(response.error[1].message); + } else { + resolve(response); + } + }); } @@ -272,25 +296,25 @@ const encodeParams = p => Object.entries(p).map(kv => kv.map(encodeURIComponent * * @method */ -DataStoreServer.prototype.login = function(userId, userPassword, action) { +DataStoreServer.prototype.login = function(userId, userPassword) { var datastoreObj = this const data = this.fillCommonParameters({ "method": "login", "userId": userId, "password": userPassword }); - this._internal.sendHttpRequest( + return this._internal.sendHttpRequest( "POST", - "text/plain", + "application/octet-stream", this._internal.datastoreUrl, - encodeParams(data), - function(loginResponse) { + encodeParams(data) + ).then((loginResponse) => { + return new Promise((resolve, reject) => { datastoreObj._internal.sessionToken = loginResponse; datastoreObj.rememberSession(); - action(loginResponse); - } - ); - + resolve(loginResponse); + }) + }); } @@ -298,32 +322,33 @@ DataStoreServer.prototype.login = function(userId, userPassword, action) { * Checks whether the current session is still active. * */ -DataStoreServer.prototype.isSessionValid = function(action) { - if(this.getSession()){ - const data = this.fillCommonParameters({"method":"isSessionValid"}); - this._internal.sendHttpRequest( - "GET", - "text/plain", - this._internal.datastoreUrl, - encodeParams(data), - (response) => parseJsonResponse(response, action) - ); - }else{ - action({ result : false }) - } +DataStoreServer.prototype.isSessionValid = function() { + return new Promise((resolve, reject) => { + if (this.getSession()) { + const data = this.fillCommonParameters({"method":"isSessionValid"}); + this._internal.sendHttpRequest( + "GET", + "application/octet-stream", + this._internal.datastoreUrl, + encodeParams(data) + ).then((response) => parseJsonResponse(response).then((value) => resolve(value)) + .catch((reason) => reject(reason))); + } else { + resolve({ result : false }) + } + }); } /** - * Restores the current session from a cookie and executes - * the specified action if the session is still active. + * Restores the current session from a cookie. * * @see restoreSession() * @see isSessionActive() * @method */ -DataStoreServer.prototype.ifRestoredSessionActive = function(action) { +DataStoreServer.prototype.ifRestoredSessionActive = function() { this.restoreSession(); - this.isSessionValid(function(data) { if (data.result) action(data) }); + return this.isSessionValid(); } /** @@ -331,21 +356,23 @@ DataStoreServer.prototype.ifRestoredSessionActive = function(action) { * * @method */ -DataStoreServer.prototype.logout = function(action) { - this.forgetSession(); - - if(this.getSession()){ - const data = this.fillCommonParameters({"method":"logout"}); - this._internal.sendHttpRequest( - "POST", - "text/plain", - this._internal.datastoreUrl, - encodeParams(data), - (response) => parseJsonResponse(response, action) - ); - }else if(action){ - action({ result : null }); - } +DataStoreServer.prototype.logout = function() { + return new Promise((resolve, reject) => { + this.forgetSession(); + + if (this.getSession()) { + const data = this.fillCommonParameters({"method": "logout"}); + this._internal.sendHttpRequest( + "POST", + "application/octet-stream", + this._internal.datastoreUrl, + encodeParams(data) + ).then((response) => parseJsonResponse(response).then((value) => resolve(value)) + .catch((reason) => reject(reason))); + } else { + resolve({result: null}); + } + }); } @@ -358,20 +385,19 @@ DataStoreServer.prototype.logout = function(action) { /** * List files in the DSS for given owner and source */ -DataStoreServer.prototype.list = function(owner, source, recursively, action){ +DataStoreServer.prototype.list = function(owner, source, recursively){ const data = this.fillCommonParameters({ "method": "list", "owner" : owner, "source": source, "recursively": recursively }); - this._internal.sendHttpRequest( + return this._internal.sendHttpRequest( "GET", - "text/plain", + "application/octet-stream", this._internal.buildGetUrl(data), - {}, - (response) => parseJsonResponse(response, action) - ); + {} + ).then((response) => parseJsonResponse(response)); } /** @@ -380,9 +406,8 @@ DataStoreServer.prototype.list = function(owner, source, recursively, action){ * @param {str} source path to file * @param {int} offset offset from whoch to start reading * @param {int} limit how many characters to read - * @param {*} action post-processing action */ -DataStoreServer.prototype.read = function(owner, source, offset, limit, action){ +DataStoreServer.prototype.read = function(owner, source, offset, limit){ const data = this.fillCommonParameters({ "method": "read", "owner" : owner, @@ -390,12 +415,11 @@ DataStoreServer.prototype.read = function(owner, source, offset, limit, action){ "offset": offset, "limit": limit }); - this._internal.sendHttpRequest( + return this._internal.sendHttpRequest( "GET", - "text", + "application/octet-stream", this._internal.buildGetUrl(data), - {}, - (response) => action(response) + {} ); } @@ -414,9 +438,8 @@ function hex2a(hexx) { * @param {str} source path to file * @param {int} offset offset from which to start writing * @param {str} data data to write - * @param {*} action post-processing action */ -DataStoreServer.prototype.write = function(owner, source, offset, data, action){ +DataStoreServer.prototype.write = function(owner, source, offset, data){ const params = this.fillCommonParameters({ "method": "write", "owner" : owner, @@ -426,12 +449,11 @@ DataStoreServer.prototype.write = function(owner, source, offset, data, action){ "md5Hash": btoa(hex2a(md5(data))), }); - this._internal.sendHttpRequest( + return this._internal.sendHttpRequest( "POST", - "text/plain", + "application/octet-stream", this._internal.datastoreUrl, - encodeParams(params), - (response) => action(response) + encodeParams(params) ); } @@ -439,27 +461,25 @@ DataStoreServer.prototype.write = function(owner, source, offset, data, action){ * Delete file from the DSS * @param {str} owner owner of the file * @param {str} source path to file - * @param {*} action post-processing action */ -DataStoreServer.prototype.delete = function(owner, source, action){ +DataStoreServer.prototype.delete = function(owner, source){ const data = this.fillCommonParameters({ "method": "delete", "owner" : owner, "source": source }); - this._internal.sendHttpRequest( + return this._internal.sendHttpRequest( "DELETE", - "text/plain", + "application/octet-stream", this._internal.datastoreUrl, - encodeParams(data), - (response) => action(response) + encodeParams(data) ); } /** * Copy file within DSS */ -DataStoreServer.prototype.copy = function(sourceOwner, source, targetOwner, target, action){ +DataStoreServer.prototype.copy = function(sourceOwner, source, targetOwner, target){ const data = this.fillCommonParameters({ "method": "copy", "sourceOwner" : sourceOwner, @@ -467,19 +487,18 @@ DataStoreServer.prototype.copy = function(sourceOwner, source, targetOwner, targ "targetOwner": targetOwner, "target" : target }); - this._internal.sendHttpRequest( + return this._internal.sendHttpRequest( "POST", - "text/plain", + "application/octet-stream", this._internal.datastoreUrl, - encodeParams(data), - (response) => action(response) + encodeParams(data) ); } /** * Move file within DSS */ -DataStoreServer.prototype.move = function(sourceOwner, source, targetOwner, target, action){ +DataStoreServer.prototype.move = function(sourceOwner, source, targetOwner, target){ const data = this.fillCommonParameters({ "method": "move", "sourceOwner" : sourceOwner, @@ -487,32 +506,29 @@ DataStoreServer.prototype.move = function(sourceOwner, source, targetOwner, targ "targetOwner": targetOwner, "target" : target }); - this._internal.sendHttpRequest( + return this._internal.sendHttpRequest( "POST", - "text/plain", + "application/octet-stream", this._internal.datastoreUrl, - encodeParams(data), - (response) => action(response) + encodeParams(data) ); - } /** * Create a file/directory within DSS */ -DataStoreServer.prototype.create = function(owner, source, directory, action){ +DataStoreServer.prototype.create = function(owner, source, directory){ const data = this.fillCommonParameters({ "method": "create", "owner" : owner, "source": source, "directory": directory }); - this._internal.sendHttpRequest( + return this._internal.sendHttpRequest( "POST", - "text/plain", + "application/octet-stream", this._internal.datastoreUrl, - encodeParams(data), - (response) => action(response) + encodeParams(data) ); } @@ -523,74 +539,65 @@ DataStoreServer.prototype.create = function(owner, source, directory, action){ * ================================================================================== */ -DataStoreServer.prototype.begin = function(transactionId, action){ +DataStoreServer.prototype.begin = function(transactionId){ const data = this.fillCommonParameters({ "method": "begin", "transactionId" : transactionId }); - this._internal.sendHttpRequest( + return this._internal.sendHttpRequest( "POST", - "text/plain", + "application/octet-stream", this._internal.datastoreUrl, - encodeParams(data), - (response) => action(response) + encodeParams(data) ); - } -DataStoreServer.prototype.prepare = function(action){ +DataStoreServer.prototype.prepare = function(){ const data = this.fillCommonParameters({ "method": "prepare" }); - this._internal.sendHttpRequest( + return this._internal.sendHttpRequest( "POST", - "text/plain", + "application/octet-stream", this._internal.datastoreUrl, - encodeParams(data), - (response) => action(response) + encodeParams(data) ); - } -DataStoreServer.prototype.commit = function(action){ +DataStoreServer.prototype.commit = function(){ const data = this.fillCommonParameters({ "method": "commit" }); - this._internal.sendHttpRequest( + return this._internal.sendHttpRequest( "POST", - "text/plain", + "application/octet-stream", this._internal.datastoreUrl, - encodeParams(data), - (response) => action(response) + encodeParams(data) ); - } -DataStoreServer.prototype.rollback = function(action){ +DataStoreServer.prototype.rollback = function(){ const data = this.fillCommonParameters({ "method": "rollback" }); - this._internal.sendHttpRequest( + return this._internal.sendHttpRequest( "POST", - "text/plain", + "application/octet-stream", this._internal.datastoreUrl, - encodeParams(data), - (response) => action(response) + encodeParams(data) ); } -DataStoreServer.prototype.recover = function(action){ +DataStoreServer.prototype.recover = function(){ const data = this.fillCommonParameters({ "method": "recover" }); - this._internal.sendHttpRequest( + return this._internal.sendHttpRequest( "POST", - "text/plain", + "application/octet-stream", this._internal.datastoreUrl, - encodeParams(data), - (response) => action(response) + encodeParams(data) ); - } diff --git a/api-data-store-server-javascript/src/js/demo/server-data-store-client.js b/api-data-store-server-javascript/src/js/demo/server-data-store-client.js index b9cc58fb9a1e237edb0ae5dea68a344078208b55..8528af8c83a03683698d36d1f8703b02ced69250 100644 --- a/api-data-store-server-javascript/src/js/demo/server-data-store-client.js +++ b/api-data-store-server-javascript/src/js/demo/server-data-store-client.js @@ -12,19 +12,19 @@ datastoreServer = new DataStoreServer('http://localhost:8085', HTTP_SERVER_URI); /** Creates open button for reading the file from dss */ function createOpenButton(row, filePath, fileSize) { readButton = document.createElement("button"); - readButton.innerText = "open"; - readButton.dataset.filepath = filePath; - readButton.dataset.filesize = fileSize; - readButton.onclick = (function() { - datastoreServer.read(owner, this.dataset.filepath, 0, this.dataset.filesize, (responseData => { - var win = window.open("", "_blank"); - var doc = win.document; - doc.open("text/html"); - doc.write(responseData); - doc.close(); - })); - }); - row.appendChild(readButton); + readButton.innerText = "open"; + readButton.dataset.filepath = filePath; + readButton.dataset.filesize = fileSize; + readButton.onclick = (function() { + datastoreServer.read(owner, this.dataset.filepath, 0, this.dataset.filesize).then((responseData) => { + const blob = responseData + const link = document.createElement('a') + link.href = window.URL.createObjectURL(blob) + link.download = filePath.substring(filePath.lastIndexOf('/') + 1) + link.click() + }); + }); + row.appendChild(readButton); } /** creates button for deleteing a file from the dss */ @@ -33,10 +33,8 @@ function createDeleteButton(row, filePath) { deleteButton.innerText = "delete"; deleteButton.dataset.filepath = filePath; deleteButton.onclick = (function() { - if (confirm("Do you want to delete "+filePath+" ?") == true) { - datastoreServer.delete(owner, this.dataset.filepath, (responseData => { - showEntries(); - })); + if (confirm("Do you want to delete " + filePath + "?")) { + datastoreServer.delete(owner, this.dataset.filepath).then(() => showEntries()); } }); row.appendChild(deleteButton); @@ -80,7 +78,7 @@ function generateTable(files) { files = dfs(tree, map, '', []); files.forEach(file => { file.owner = owner; - file.path = file.path.slice(owner.length + 1); + // file.path = file.path.slice(1); }); @@ -147,7 +145,7 @@ function showEntries() while (table.firstChild) { table.firstChild.remove() } - datastoreServer.list(owner, source, "true", displayReturnedFiles); + datastoreServer.list(owner, source, "true").then(displayReturnedFiles); } @@ -193,43 +191,36 @@ window.onload = function() { document.getElementById("write-submit").onclick = function() { if(isWriteValid()) { datastoreServer.write(owner, - document.getElementById("fpath").value.trim(), - parseInt(document.getElementById("foffset").value.trim()), - document.getElementById("write-text").value.trim(), - (_ => { - showEntries(); - })); + document.getElementById("fpath").value.trim(), + parseInt(document.getElementById("foffset").value.trim()), + document.getElementById("write-text").value.trim()) + .then(() => showEntries()); } }; document.getElementById("copy-submit").onclick = function() { - if(isCopyValid()) { - datastoreServer.copy(owner, document.getElementById("copy-from-path").value.trim(), owner, document.getElementById("copy-to-path").value.trim(), - (_ => { - showEntries(); - })); + if (isCopyValid()) { + datastoreServer.copy(owner, document.getElementById("copy-from-path").value.trim(), owner, + document.getElementById("copy-to-path").value.trim()) + .then(() => showEntries()); } }; document.getElementById("move-submit").onclick = function() { - if(isMoveValid()) { + if (isMoveValid()) { datastoreServer.move(owner, - document.getElementById("move-from-path").value.trim(), - owner, - document.getElementById("move-to-path").value.trim(), - (_ => { - showEntries(); - })); + document.getElementById("move-from-path").value.trim(), + owner, + document.getElementById("move-to-path").value.trim()) + .then(() => showEntries()); } }; document.getElementById("create-submit").onclick = function() { datastoreServer.create(owner, document.getElementById("create-path").value.trim(), - document.getElementById("create-directory").checked, - (_ => { - showEntries(); - })); + document.getElementById("create-directory").checked) + .then(() => showEntries()); }; } diff --git a/api-data-store-server-javascript/src/js/demo/server-data-store-login.js b/api-data-store-server-javascript/src/js/demo/server-data-store-login.js index ee6039ac7bb63447be43f3c207e870da528fe684..148bd45512e4c465b4aa0fcfd7ad3df9a9b87ceb 100644 --- a/api-data-store-server-javascript/src/js/demo/server-data-store-login.js +++ b/api-data-store-server-javascript/src/js/demo/server-data-store-login.js @@ -51,27 +51,26 @@ dssClientLoginPage.prototype.configure = function(){ } document.getElementById("logout-button").onclick = function() { - loginPage.datastore.logout(function(data) { + loginPage.datastore.logout().then(() => { document.getElementById("login-form-div").style.display = "block"; document.getElementById("main").style.display = "none"; document.getElementById("openbis-logo").style.height = "100px"; document.getElementById("username").focus(); }); - }; document.getElementById("login-form").onsubmit = function() { - loginPage.datastore.login(document.getElementById("username").value.trim(), - document.getElementById("password").value.trim(), - function(data) { - document.getElementById("username").value = ''; - document.getElementById("password").value = ''; - loginPage.onLogin(data); - }) + loginPage.datastore.login(document.getElementById("username").value.trim(), + document.getElementById("password").value.trim()) + .then((data) => { + document.getElementById("username").value = ''; + document.getElementById("password").value = ''; + loginPage.onLogin(data); + }) }; - loginPage.datastore.ifRestoredSessionActive(function(data) { loginPage.onLogin(data) }); + loginPage.datastore.ifRestoredSessionActive().then((data) => loginPage.onLogin(data)); document.onkeydown=function(evt){ diff --git a/server-data-store/src/main/resources/server-data-store-config.properties b/server-data-store/src/main/resources/server-data-store-config.properties index 850f4ccd20ba0a4e0b757b8b9d41bb324ed2a2dc..cf70d73c76e43206cd6ebc26dd13db0fe9adc45c 100755 --- a/server-data-store/src/main/resources/server-data-store-config.properties +++ b/server-data-store/src/main/resources/server-data-store-config.properties @@ -8,11 +8,11 @@ writeAheadLogRoot=./target/tests/transactions storageRoot=./target/tests/storage httpServerClass=ch.ethz.sis.afsserver.http.impl.NettyHttpServer -httpServerUri=/fileserver +httpServerUri=/data-store-server httpServerPort=8085 httpMaxContentLength=1024 -maxReadSizeInBytes=1024 +maxReadSizeInBytes=1048576 authenticationInfoProviderClass=ch.ethz.sis.afsserver.worker.providers.impl.DummyAuthenticationInfoProvider authorizationInfoProviderClass=ch.ethz.sis.afsserver.worker.providers.impl.DummyAuthorizationInfoProvider poolSize=50 diff --git a/server-data-store/src/test/resources/test-server-config.properties b/server-data-store/src/test/resources/test-server-config.properties index 430d16f423d418c474557cf5231498484c5a20a6..ae2c6d308127bd2ef5629d40e666f53c3addcdb7 100644 --- a/server-data-store/src/test/resources/test-server-config.properties +++ b/server-data-store/src/test/resources/test-server-config.properties @@ -29,7 +29,7 @@ httpServerPort=8085 httpServerUri=/fileserver httpMaxContentLength=1024 -maxReadSizeInBytes=1024 +maxReadSizeInBytes=1048576 authenticationInfoProviderClass=ch.ethz.sis.afsserver.worker.providers.impl.DummyAuthenticationInfoProvider authorizationInfoProviderClass=ch.ethz.sis.afsserver.worker.providers.impl.DummyAuthorizationInfoProvider poolSize=50 diff --git a/server-data-store/src/test/resources/test-server-with-auth-config.properties b/server-data-store/src/test/resources/test-server-with-auth-config.properties index cd2e462ccfc3ab3131efe26e436d9b92b930d864..1ee88621d7027ed0ebe33e6e60aa3882fa75d79f 100644 --- a/server-data-store/src/test/resources/test-server-with-auth-config.properties +++ b/server-data-store/src/test/resources/test-server-with-auth-config.properties @@ -29,7 +29,7 @@ httpServerPort=8085 httpServerUri=/fileserver httpMaxContentLength=1024 -maxReadSizeInBytes=1024 +maxReadSizeInBytes=1048576 authenticationInfoProviderClass=ch.ethz.sis.afsserver.worker.providers.impl.OpenBISAuthenticationInfoProvider authorizationInfoProviderClass=ch.ethz.sis.afsserver.worker.providers.impl.OpenBISAuthorizationInfoProvider poolSize=50