const utils = require("./utils");
/**
* @memberOf Services
* @type {doPost}
*/
const doPost = utils.getPostHandlerFor("dsu-wizard");
if (utils.getEnv() === 'nodejs')
FormData = require('form-data'); // needed because nodejs does not have FormData. his makes sure we can use it in tests
/**
* Class responsible for Authenticated DSU transactions between the client and the API Hub
* @class DSUService
* @memberOf Services
*/
class DSUService {
constructor() {
let openDSU = require('opendsu');
let crypto = openDSU.loadApi("crypto");
let http = openDSU.loadApi("http");
this.keyssiSpace = openDSU.loadApi('keyssi');
// http.registerInterceptor((data, callback)=>{
// let {url, headers} = data;
// let scope = "";
//
// if(typeof this.holderInfo != "undefined"){
// crypto.createPresentationToken(this.holderInfo.ssi, scope, this.credential, (err, presentationToken)=>{
// if(err){
// return callback(err);
// }
//
// headers["Authorization"] = presentationToken;
// return callback(undefined, {url, headers});
// });
// }else {
// console.log("Unexpected case");
// return callback(undefined, {url, headers});
// }
//
// });
}
// ensureHolderInfo(callback) {
// function getJSON(pth, callback){
// scriptUtils.fetch(pth).then((response) => {
// return response.json();
// }).then((json) => {
// return callback(undefined, json)
// }).catch(callback);
// }
//
// if (typeof this.holderInfo === "undefined" || typeof this.credential === "undefined") {
// getJSON("/download/myKeys/holder.json", (err, holderInfo) => {
// if (err) {
// return callback(Error("No holder info available!"));
// }
// this.holderInfo = holderInfo;
//
// getJSON("/download/myKeys/credential.json", (err, result) => {
// if (err) {
// return callback(Error("No credentials available!"));
// }
// this.credential = result.credential;
// return callback(undefined, holderInfo);
// });
// });
// } else {
// callback(undefined, this.holderInfo);
// }
// }
/**
* This callback is displayed as part of the DSUService class.
* @callback DSUService~callback
* @param {string|object|undefined} error
* @param {string|undefined} [keySSI]: not in human readable form
*/
/**
* This function is called by DSUService class to initialize/update DSU Structure.
* @callback DSUService~modifier
* @param {DSUBuilder} dsuBuilder
* @param {DSUService~callback} callback
*/
/**
* Creates a DSU and initializes it via the provided initializer
* @param {string} domain: the domain where the DSU is meant to be stored
* @param {string|object} keySSIOrEndpoint: the keySSI string or endpoint object {endpoint: 'gtin', data: 'data'}
* @param {DSUService~modifier} initializer: a method with arguments (dsuBuilder, callback)
* <ul><li>the dsuBuilder provides the api to all operations on the DSU</li></ul>
* @param {DSUService~callback} callback: the callback function
*/
create(domain, keySSIOrEndpoint, initializer, callback){
let self = this;
let simpleKeySSI = typeof keySSIOrEndpoint === 'string';
self.getTransactionId(domain, (err, transactionId) => {
if (err)
return callback(err);
let afterKeyCb = function(err){
if (err)
return callback(err);
initializer(self.bindToTransaction(domain, transactionId), err => {
if (err)
return callback(err);
self.buildDossier(transactionId, domain, (err, keySSI) => {
if (err)
return callback(err);
callback(undefined, self.keyssiSpace.parse(keySSI));
});
});
};
if (simpleKeySSI){
self.setKeySSI(transactionId, domain, keySSIOrEndpoint, afterKeyCb);
} else {
self.setCustomSSI(transactionId, domain, keySSIOrEndpoint.endpoint, keySSIOrEndpoint.data, afterKeyCb);
}
});
}
/**
* Creates a DSU and initializes it via the provided initializer
* @param {string} domain: the domain where the DSU is meant to be stored
* @param {keySSI} keySSI:
* @param {DSUService~modifier} modifier: a method with arguments (dsuBuilder, callback)
* <ul><li>the dsuBuilder provides the api to all operations on the DSU</li></ul>
* @param {DSUService~callback} callback: the callback function
*/
update(domain, keySSI, modifier, callback){
let self = this;
self.getTransactionId(domain, (err, transactionId) => {
if (err)
return callback(err);
self.setKeySSI(transactionId, domain, keySSI, err =>{
if (err)
return callback(err);
modifier(self.bindToTransaction(domain, transactionId), (err, keySSI) => {
if (err)
return callback(err);
callback(undefined, keySSI);
});
});
});
}
/**
* Binds the DSU<service to the transaction and outputs a DSUBuilder
* @param {string} domain
* @param {string} transactionId
* @returns {DSUBuilder} the dsu builder
*/
bindToTransaction(domain, transactionId){
let self = this;
/**
* Wrapper class around DSUService with binded transactionId and domain
*/
return new class DSUBuilder {
/**
* @see {@link DSUService#addFileDataToDossier} with already filled transactionId and domain
* @memberOf Services
*/
addFileDataToDossier(fileName, fileData, callback){
self.addFileDataToDossier(transactionId, domain, fileName, fileData, callback);
};
/**
* @see {@link DSUService#mount} with already filled transactionId and domain
* @memberOf Services
*/
mount(path, seed, callback){
self.mount(transactionId, domain, path, seed, callback);
};
}
}
getTransactionId(domain, callback) {
let obtainTransaction = ()=>{
doPost(`/${domain}/begin`, '',(err, transactionId) => {
if (err)
return callback(err);
return callback(undefined, transactionId);
});
}
// this.ensureHolderInfo( (err)=>{
// if(err){
// return OpenDSUSafeCallback(callback)(createOpenDSUErrorWrapper("Holder missconfiguration in the wallet", err));
// }
obtainTransaction();
// });
}
setKeySSI(transactionId, domain, keyssi, callback) {
const url = `/${domain}/setKeySSI/${transactionId}`;
doPost(url, keyssi, callback);
}
setCustomSSI(transactionId, domain, endpoint, data, callback){
const url = `/${domain}/${endpoint}/${transactionId}`;
doPost(url, JSON.stringify(data), callback);
}
addFileDataToDossier(transactionId, domain, fileName, fileData, callback) {
const url = `/${domain}/addFile/${transactionId}`;
if (fileData instanceof ArrayBuffer) {
fileData = new Blob([new Uint8Array(fileData)], {type: "application/octet-stream"});
}
let body = new FormData();
let inputType = "file";
body.append(inputType, fileData);
doPost(url, body, {headers: {"x-dossier-path": fileName}}, callback);
}
mount(transactionId, domain, path, seed, callback) {
const url = `/${domain}/mount/${transactionId}`;
doPost(url, "", {
headers: {
'x-mount-path': path,
'x-mounted-dossier-seed': seed
}
}, callback);
}
buildDossier(transactionId, domain, callback) {
const url = `/${domain}/build/${transactionId}`;
doPost(url, "", callback);
}
}
module.exports = DSUService;
Source