feat: init; from commit c3adcb2e6bc94b46f4f34c03bc62abcce6c7e1a0 of BDContract

This commit is contained in:
Frank.R.Wu 2021-06-15 19:55:10 +08:00
commit 4379b1745e
14 changed files with 28424 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/.idea

7
README.md Normal file
View File

@ -0,0 +1,7 @@
#文件说明
1) 最小可直接使用:./js目录下的createWS.jscryptico.jssm2.js 三个脚本 。
2直接打开bdwareclinet.html在地址中填入单节点运行的地址如127.0.0.1:18000。可在界面中试调合约。
3参考bdwareclient.js的写法并配合说明文档中的ContractAPI.html进行使用。

173
bdwareclient.html Normal file
View File

@ -0,0 +1,173 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Cache-Control" content="no-cache" />
<title>数瑞客户端</title>
<script src="./js/createWS.js"></script>
<script src="./js/cryptico.js"></script>
<script src="./js/jquery-2.1.4.js"></script>
<script src="./js/bootstrap.min.js"></script>
<script src="./js/commonutil.js"></script>
<link href="./css/common.css" rel="stylesheet">
<link href="./css/bootstrap.min.css" rel="stylesheet">
<script src="./js/vue.js"></script>
<script src="./js/bdwareclient.js"></script>
<script src="./js/sm2.js"></script>
</head>
<body>
<header
class="headerFooter navbar navbar-default navbar-fixed-top navColor ">
<div class="col-10">
<div class="input-group">
<a class="navbar-brand" href="#"> <img alt="Brand"
src="./img/logo-1.png" style="height: 30px">
</a><a class="navbar-brand">数瑞浏览器&nbsp;&nbsp; </a> <input id="urlInput"
type="text" class="form-control" placeholder="输入地址">
<button class="btn btn-outline-secondary" type="button"
onclick="connectNode()">GO</button>
<button class="btn btn-outline-secondary" id="switchRenderBtn" type="button"
onclick="changeRender()">不加载界面</button>
<span>&nbsp;&nbsp;&nbsp;</span>
<div class="input-group-append">
<select id="selectContract" class="custom-select"
style="-webkit-appearance: none" onchange="changeApp()">
<option selected>选择合约</option>
</select>
</div>
</div>
</div>
<div class=" nav navbar-right userName" data-toggle="modal"
data-target="#pubkeyDialog">欢迎, {{shortName}}</div>
</header>
<div id="main">
<div class="row h-100" id="mainDiv"></div>
</div>
<!-- 用于配置sm2密钥的对话框 -->
<div class="modal fade" id="pubkeyDialog" tabindex="-1" role="dialog"
aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">用户信息</h5>
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="row" style="padding-left: 16px; padding-right: 16px">
<div class="input-group mb-3">
<div class="input-group-prepend">
<label class="input-group-text" for="localKeyList">本地公钥</label>
</div>
<select class="custom-select"
aria-label="Example select with button addon"
style="appearance: none" v-model="selectedSM2Key"
@change="changeSM2Key($event)">
<option v-for="(item,index) in sm2KeyList" :key="index"
:value='item.id'>{{item.title}}</option>
</select>
<div class="input-group-append">
<button class="btn btn-outline-primary" for="localKeyList"
v-on:click="exportPubkey">导出公钥</button>
</div>
<div class="input-group-append">
<button class="btn btn-outline-danger" for="localKeyList"
v-on:click="deletePubkey">删除公钥</button>
</div>
</div>
</div>
<div class="row" style="padding-left: 16px; padding-right: 16px">
<div class="input-group mb-1">
<div class="input-group-prepend">
<label class="input-group-text" for="localKeyList">当前SM2密钥</label>
</div>
<input type="text" class="form-control" placeholder="(请复制并妥善保存)"
disabled="disabled" aria-label=""
aria-describedby="basic-addon1">
<div class="input-group-append">
<button type="button" class="btn btn-outline-primary"
id="generatePubkeyBtn" v-on:click="generatePubkey">生成新公钥</button>
<button type="button" class="btn btn-outline-primary"
data-dismiss="modal" id="importPubkeyBtn"
v-on:click="importPubkey">导入公钥</button>
</div>
</div>
</div>
<textarea class="form-control mb-3" title="复制密钥,并妥善保存"
id="sm2KeyTextarea" v-model="sm2KeyStr"
style="width: 100%; min-height: 150px" rows="" cols="">
</textarea>
<div class="row" style="padding-left: 16px; padding-right: 16px;">
</div>
<div class="row" style="padding-left: 16px; padding-right: 16px">
<span>我的权限:{{myRole}}</span>
</div>
<div class="input-group">
<select id="inputGroupSelect04" v-model="test"
class="custom-select" style="appearance: none"
@change="changeProduct($event)">
<option v-for="(item,index) in productList" :key="index"
:value='item.id'>{{item.title}}</option>
</select>
<div class="input-group-append">
<button class="btn btn-outline-primary" type="button"
v-on:click="applyRole">角色认证</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" id="dialog" tabindex="-1" role="dialog"
aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="dialogTitleH5">Modal title</h5>
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body" id="dialogBodyDiv">...</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary"
data-dismiss="modal">关闭
</button>
<button type="button" id="dialogConfimBtn"
class="btn btn-outline-primary" data-dismiss="modal">确定
</button>
</div>
</div>
</div>
</div>
<script>
var h = document.body.clientHeight
- $("header").css("height").replace("px", "")
$("#main").css("height", h + "px");
init();
//initWSocket();
</script>
</body>
</html>

1
css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

128
css/common.css Normal file
View File

@ -0,0 +1,128 @@
.navColor {
background: #882929;
color: white;
}
.userName {
padding-left: 10px;
padding-right: 10px;
border: 1px solid rgba(0, 0, 0, .125);
border-radius: 5px;
background: white;
color: #2E324C;
}
.userName:hover {
cursor: pointer;
background: rgb(68, 110, 155);
color: white;
border-radius: 5px;
}
#horiNav {
padding-top: 10px;
border: 1px solid rgba(0, 0, 0, .05);
background: #f8f9fa;
}
#outputNav {
padding-top: 10px;
border: 1px solid rgba(0, 0, 0, .05);
background: #f8f9fa;
}
div .card {
background: #f8f9fa;
}
#main {
background: white;
color: black;
}
.active>.iconimg {
height: 25px;
width: 25px;
margin-right: 10px;
filter: invert(100%);
}
.iconimg {
height: 25px;
width: 25px;
margin-right: 10px;
filter: invert(15%) sepia(11%) saturate(2467%) hue-rotate(194deg)
brightness(94%) contrast(84%);
}
.buttonimg {
height: 24px;
width: 24px;
filter: invert(15%) sepia(11%) saturate(2467%) hue-rotate(194deg)
brightness(94%) contrast(84%);
}
.closeimg {
height: 12px;
width: 12px;
filter: invert(15%) sepia(11%) saturate(2467%) hue-rotate(194deg)
brightness(94%) contrast(84%);
}
.closeimg:hover {
cursor:pointer;
}
.active>.closeimg {
filter: invert(100%);
}
.trigimg {
height: 20px;
width: 20px;
}
.projectLine.collapsed {
background: #D5D6DB;
color: #2E324C;
}
.projectLine {
background: #2E324C;
color: white;
}
.projectLine.collapsed:hover {
background: #2E324C;
color: white;
}
button:hover>.trigimg {
filter: invert(100%);
}
button[aria-expanded="true"]>.trigimg {
filter: invert(100%);
}
button:hover>.buttonimg {
height: 24px;
width: 24x;
filter: invert(100%);
}
.headerFooter {
background: #2E324C;
color: white;
}
.outline-btn {
border: 1px solid #999;
border-radius: 3px;
}
div.filter-option {
border: 1px solid #999;
border-radius: 3px;
}

BIN
img/logo-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

786
js/bdwareclient.js Normal file
View File

@ -0,0 +1,786 @@
var dtLang = {
"sProcessing": "处理中...",
"lengthMenu": '显示 <select>' + '<option value="5">5</option>'
+ '<option value="20">20</option>'
+ '<option value="100">100</option>'
+ '<option value="-1">全部</option>' + '</select> 项结果',
"sZeroRecords": "没有匹配结果",
"sInfo": "显示第 _START_ 至 _END_ 项结果,共 _TOTAL_ 项",
"sInfoEmpty": "显示第 0 至 0 项结果,共 0 项",
"sInfoFiltered": "(由 _MAX_ 项结果过滤)",
"sInfoPostFix": "",
"sSearch": "搜索:",
"sUrl": "",
"sEmptyTable": "表中数据为空",
"sLoadingRecords": "载入中...",
"sInfoThousands": ",",
"oPaginate": {
"sFirst": "首页",
"sPrevious": "上页",
"sNext": "下页",
"sLast": "末页"
},
"oAria": {
"sSortAscending": ": 以升序排列此列",
"sSortDescending": ": 以降序排列此列"
}
};
function applyRole(role) {
global.wssocket.send("{\"action\":\"applyNodeRole\",\"role\":\"" + role
+ "\",\"pubKey\":\"" + global.sm2Key.publicKey + "\"}");
}
function WSHandler(event) {
console.log(event);
data = event.data;
// console.log(" -->" + data);
try {
var obj = JSON.parse(data);
switch (obj.action) {
case 'onTransferTo':
onTransferTo(obj);
break;
case 'onHashResult':
onHashResult(obj);
break;
case 'onListMemoryFiles':
onListMemoryFiles(obj);
break;
case 'onDumpContract':
onDumpContract(obj);
break;
case 'onChangeDumpPeriod':
onChangeDumpPeriod(obj);
break;
case 'onGetDumpPeriod':
onGetDumpPeriod(obj);
break;
case 'onStaticVerifyResult':
onStaticVerifyResult(obj);
break;
case "onListContractProcess":
onListContractProcess(obj);
break;
case "onDeleteFile":
onDeleteFile(obj);
break;
case "onCancelAuth":
onCancelAuth(obj);
break;
case "onDownloadContract":
onDownloadFile(obj);
break;
case "onChangePublic":
onChangePublic(obj);
break;
case "onListProjects":
onListProjects(obj);
break;
case "onListProject":
onListProject(obj);
break;
case "onListLocalNodeLog":
onListLocalNodeLog(obj);
break;
case "onListLocalNodeLogPie":
onListLocalNodeLogPie(obj);
break;
case "onListLocalNodeLogLine":
onListLocalNodeLogLine(obj);
break;
case "onListTheContractProcess":
onListTheContractProcess(obj);
break;
case "onListLocalContractLog":
onListLocalContractLog(obj);
break;
case "onListLocalContractLogPie":
onListLocalContractLogPie(obj);
break;
case "onListLocalContractLogLine":
onListLocalContractLogLine(obj);
break;
case "onGetNodeSessionID":
case "onSessionID":
onGetNodeSessionID(obj);
break;
case "onLogin":
onNodeLogin(obj);
break;
case "onGetNodeRole":
case "onGetRole":
onGetNodeRole(obj);
break;
case "onApplyRole":
onApplyRole(obj);
break;
case "onListAllAuthRole":
onListAllAuthRole(obj);
break;
case "onListUnAuthRole":
onListUnAuthRole(obj);
break;
case "onDeleteRole":
onDeleteRole(obj);
break;
case "onCountRole":
onCountRole(obj);
break;
case "onAuthNodeRole":
onAuthNodeRole(obj);
break;
case "onApplyNet":
onApplyNet(obj);
break;
case "onLoadNodeConfig":
onLoadNodeConfig(obj);
break;
case "onChangeNodeName":
onChangeNodeName(obj);
break;
case "onChangeYJSPath":
onChangeYJSPath(obj);
break;
case "onChangeIpPort":
onChangeIpPort(obj);
break;
case "onGetLicenceExpiredDate":
$("#expiredDate").html(convertDate(data.data));
break;
case "onGetPeerID":
global.peerID = obj.data;
// getNodeTrustUnits();//still connecting to centerportalws
break;
case "onViewContractInstance":
onViewContractInstance(obj);
break;
case 'onExecuteResult':
onExecuteResult(obj);
break;
case 'onExecuteContractTrustfully':
onExecuteContractTrustfully(obj);
break;
case 'onUploadFile':
onUploadFile(obj);
break;
case 'onStartContract':
onStartContract(obj);
break;
case 'onStartContractConfig':
onStartContractConfig(obj);
break;
case 'onKillContractProcess':
onStopContract(obj);
break;
case 'onKillAllContract':
onKillAllContract(obj);
break;
case 'onSetPermission':
onSetPermission(obj);
break;
case 'onOutputStream':
displayOutput(obj);
break;
case 'onChangeNodeCenter':
console.log("onChangeNodeCenter");
onChangeNodeCenter(obj);
break;
case 'onException':
onException(obj);
break;
// logException(obj);
// break;
default:
displayOutput(obj);
break;
}
} catch (err) {
console.log(err);
}
}
function onException(obj) {
if (obj.data.startsWith("unauthorised action")) {
const action = obj.data.replace("unauthorised action ", "");
switch (action) {
case "listContractProcess":
mainVue.contracts = [];
if (global.urlparam["contract"]) {
appendTargetContract(global.urlparam["contract"]);
} else
alertNoPermission("listContractProcess无授权请申请ContractUser权限", "提示");
break;
default:
alertNoPermission(action + "无权限", "提示");
}
}
}
function alertNoPermission(message, title) {
const npSpan = $("#nopermissionSpan");
if (npSpan.length > 0) {
console.log(message + " status:" + $("#dialog")[0].getAttribute("class"));
npSpan.append("<br/>" + message);
} else {
let body = "<div class='row'><div class='col-sm-12'><span id='nopermissionSpan'>";
body += message;
body += "</span></div></div>";
$("#dialogBodyDiv").html(body);
showDialog("提示", function () {
$("#dialogBodyDiv").html("");
});
}
}
function onExecuteResult(obj) {
console.log(obj);
global.executeResult = obj;
if (global.executeResult.size) {
onExecuteContractTrustfully(obj);
}
onExecuteResultInternal(obj);
}
function showContractResult(requestID) {
var data = global.responseCollector[requestID][0];
result = data;
$("#statusSpan")[0].innerHTML = result.status;
$("#timeSpan")[0].innerHTML = "调用耗时:" + data.executeTime + "(ms)";
if (result.result instanceof Object){
$("#responseArea")[0].value = JSON.stringify(result.result);
$("#timeSpan")[0].innerHTML +="<br> JSON格式";
}else{
$("#timeSpan")[0].innerHTML +="<br> 字符串格式";
$("#responseArea")[0].value = result.result;
}
if (global.responseCollector[requestID].hashCode!=undefined)
$("#hashDisplayDiv").html("溯源指纹:" + global.responseCollector[requestID].hashCode);
}
function switchContractResult() {
const requestID = reqIDSpan.value;
showContractResult(requestID);
}
function showInconsistentResult(list) {
global.resultList = list;
let html = "<table class='table table-striped'><thead><tr><td>status</td><td>executeTime</td><td>result</td></tr></thead><tbody>";
for (const r of list) {
html += "<tr><td>";
const data = JSON.parse(r.data);
html += data.status;
html += "</td><td>";
html += r.executeTime;
html += "</td><td><textarea class='form-control'>";
html += data.result;
html += "</textarea></td></tr>";
}
html += "</tbody></table>";
const consistencyResult = $("#consistencyResult");
if (consistencyResult.length > 0) {
consistencyResult.html(html);
} else {
$("#dialogBodyDiv").html(html);
showDialog("调用结果不一致", function () {
}, () => {
});
}
}
function showDialog(title, cb, cancelcb) {
$("#dialogTitleH5").html(title);
$("#dialogConfimBtn").off("click").on("click", cb);
$("#dialogCloseBtn").off("click").on("click", cancelcb);
$("#dialog").modal("show");
}
function onHashResult(obj) {
$("#hashDisplayDiv").html("溯源指纹:" + obj.data);
global.responseCollector[obj.responseID].hashCode = obj.data;
}
function displayOutput(obj) {
console.log(obj);
}
function initWSocket() {
let host = $("#urlInput")[0].value;
if (!host.startsWith("ws")) {
host = "ws://" + host;
}
if (host.endsWith("/SCIDE")) {
host += "/SCExecutor";
} else if (host.endsWith("/SCIDE/")) {
host += "SCExecutor";
} else if (host.endsWith("NodeCenterWS")) {
//..
} else if (!host.endsWith("/SCIDE/SCExecutor")) {
host += "/SCIDE/SCExecutor";
}
console.log("connect ws:" + host);
global.wssocket = createWssocket(host, () => {
getSession();
}, WSHandler);
global.responseCollector = {};
global.commited = {};
}
function getSession() {
global.wssocket.send("{\"action\":\"getSessionID\"}");
}
function exportSMKeyPair() {
const dialog = $("#dialog");
dialog.html("Save Your key:<br/>" + JSON.stringify(global.sm2Key));
dialog.dialog("open");
}
// ====== wsHandler
function onGetNodeSessionID(data) {
console.log("onGetNodeSessionID");
global.session = data.session;
const loginParam = {
pubKey: global.sm2Key.publicKey,
signature: sm2.doSignature(global.session, global.sm2Key.privateKey,{hash:true,der:true}),
action: "login"
};
global.wssocket.send(JSON.stringify(loginParam));
}
function onNodeLogin(data) {
pubkeyDialogVue.myRole = data.data;
global.myRole = data.data;
listContracts();
}
function listContracts() {
global.wssocket.send(JSON.stringify({action: "listContractProcess"}));
}
function changeApp() {
global.currentContract = global.contracts[$("#selectContract")[0].value];
if (!global.currentContract) {
return;
}
console.log(global.currentContract);
changeAppInternal(needRender(global.currentContract));
}
function changeAppInternal(requireRendering) {
if ((global.urlparam["noRender"] !== "true") && requireRendering) {
$("#mainDiv")[0].innerHTML = "";
executeCurrentContract("getMainFrame", "", parseMainFrame);
} else {
let title = "只包含计算逻辑";
if (requireRendering) {
title = "包含界面";
}
title += getContractDesp();
const html = " <div class='container'> <div class=\"card mt-3 \">\n"
+ " <div class=\"card-body\">\n"
+ " <h5 class=\"card-title\">"
+ title
+ "</h5>\n"
+ " <div class=\"card-body\" >\n"
+ " <div class=\"row\">\n"
+ " <div class=\"col-sm-12 d-flex justify-content-center\">\n"
+ " <div class=\"input-group mb-2\">\n"
+ " <div class=\"input-group-prepend\">\n"
+ " <select id=\"selectAction\" onchange=\"showDescription()\" class=\"custom-select\" style=\"-webkit-appearance: none;\"><option value=\"-1\">选择方法</option></select> \n"
+ " </div>\n"
+ " <input type=\"text\" class=\"form-control\" id=\"argInput\" placeholder=\"填写参数\" >\n"
+ " <div class=\"input-group-append\">\n"
+ " <button class=\"btn btn-outline-secondary\" type=\"button\" \n"
+ " onclick=\"triggerExecuteCurrentContract()\">\n"
+ " 调用\n"
+ " </button>\n"
+ " </div>\n"
+ " </div>\n"
+ " </div>\n"
+ " </div>"
+ "<div class='row mb-2'><div class='col-sm-12 d-flex '>"
+ "<div class=\"input-group\" ><div class=\"input-group-prepend\" > <span class=\"input-group-text\" >方法描述</span></div><input class=\"input-group-text form-control\" id=\"descriptionSpan\" placeholder=\"暂无\"></input></div>"
+ "</div></div>"
+ "<div class='row mb-4'><div class='col-sm-12 d-flex'>"
+ "<div class=\"input-group \" ><div class=\"input-group-prepend\" > <span class=\"input-group-text\" >http接口</span></div><input class=\"input-group-text form-control\" id=\"sigOutput\"></input></div></div></div>\n"
+ " <h5 class=\"card-title\">调用结果</h5>\n"
+ " <div class=\"input-group mb-3\">\n"
+ " <div class=\"input-group-prepend\">\n"
+ " <select class=\"custom-select form-control\" onchange='switchContractResult()' style=\"-webkit-appearance:none; appearance:none; height:100%\" id=\"reqIDSpan\"><option>请求ID</option></select>\n"
+ " </div>\n"
+ " <div class=\"input-group-append\"><span class=\"input-group-text\" id=\"statusSpan\">调用状态</span></div>\n"
+ " <div class=\"input-group-append\"><span class=\"input-group-text\" id=\"timeSpan\">调用耗时</span></div>\n"
+ " <textarea id=\"responseArea\" class=\"form-control\"></textarea>\n"
+ " </div><div class='row mb-3'><div class='col-sm-12 d-flex' id='consistencyResult'> </div></div>"
+ " <div class='row'><div class='col-sm-12 d-flex' id='hashDisplayDiv'> </div></div>"
+ " </div>\n"
+ " </div>\n"
+ " </div></div>\n" + "";
$("#mainDiv")[0].innerHTML = html;
for (const f of global.currentContract.exportedFunctions) {
$('#selectAction')
.append(`<option value="${f.functionName}">${f.functionName}</option>`);
}
}
}
function getContractDesp() {
try {
const annos = global.currentContract.annotations;
for (const anno of annos) {
if (anno.type === "Description") {
return ", " + JSON.parse(anno.args[0]);
}
}
} catch (e) {
console.log(e);
}
return "";
}
function triggerExecuteCurrentContract() {
const funPos = $("#selectAction")[0].value;
console.log(funPos);
if (funPos < 0) {
$("#dialogBodyDiv").html("请选择方法。");
showDialog("提示");
return;
}
var funNode;
for(var i = 0;i < global.currentContract.exportedFunctions.length;i++){
if(global.currentContract.exportedFunctions[i].functionName == funPos){
funNode = global.currentContract.exportedFunctions[i];
break;
}
}
console.log(funNode);
const argInput = $("#argInput");
executeCurrentContract(funNode.functionName, argInput[0].value,
fillResultInternal);
const iHtml = "/SCIDE/SCManager?action=executeContract&contractID="
+ global.currentContract.name + "&operation="
+ funNode.functionName + "&arg=" + argInput[0].value
+ "&pubkey=" + global.sm2Key.publicKey + "&signature=";
const toSign = global.currentContract.name + "|" + funNode.functionName + "|"
+ argInput[0].value + "|" + global.sm2Key.publicKey;
const signature = sm2.doSignature(toSign, global.sm2Key.privateKey,{hash:true,der:true});
let urlPre = $("#urlInput")[0].value;
if (urlPre.startsWith("ws")) {
urlPre = urlPre.replace("ws", "http");
}
$("#sigOutput")[0].value = (urlPre + iHtml + signature);
}
function showDescription() {
const funPos = $("#selectAction")[0].value;
console.log($("#selectAction")[0]);
console.log(funPos);
console.log(global.currentContract.exportedFunctions);
var funNode;
for(var i = 0;i < global.currentContract.exportedFunctions.length;i++){
if(global.currentContract.exportedFunctions[i].functionName == funPos){
funNode = global.currentContract.exportedFunctions[i];
break;
}
}
console.log(funNode);
for (const anno of funNode.annotations) {
if (anno.type === "Description") {
descriptionSpan.value = JSON.parse(anno.args[0]);
}
}
}
function fillResultInternal(result, data) {
if (global.responseCollector[data.responseID]==undefined){
global.responseCollector[data.responseID]=[];
const reqIDSpan = $("#reqIDSpan");
reqIDSpan.append("<option value='" + data.responseID + "'>" + data.responseID + "</option>");
reqIDSpan[0].value = data.responseID;
}
global.responseCollector[data.responseID].push(data);
$("#statusSpan")[0].innerHTML = result.status;
$("#timeSpan")[0].innerHTML = "调用耗时:" + data.executeTime + "(ms)";
if (result.result instanceof Object){
$("#responseArea")[0].value = JSON.stringify(result.result);
$("#timeSpan")[0].innerHTML +="<br> JSON格式";
}else{
$("#timeSpan")[0].innerHTML +="<br> 字符串格式";
$("#responseArea")[0].value = result.result;
}
}
function parseMainFrame(data) {
console.log("parseMainFrame");
console.log(data);
const mainHtml = data.result;
executeCurrentContract("loadResource", mainHtml, loadMain);
}
function loadMain(data) {
const html = data.result;
$("#mainDiv").append(html);
setTimeout(function () {
console.log("listSize:");
const scriptList = $("#mainDiv script");
global.scriptList = [];
global.scriptOrder = 0;
console.log("listSize:" + scriptList.length);
for (var i=0;i<scriptList.length;i++) {
const script = scriptList[i];
const re = script.getAttribute("fromContract");
if (!re) {
continue;
}
global.scriptList.push(re);
}
if (global.scriptList.length > 0) {
executeCurrentContract("loadResource", global.scriptList[0], loadScript);
}
const linkList = $("#mainDiv link");
for (var i=0; i<linkList.length;i++) {
const link = linkList[i];
const re = link.getAttribute("fromContract");
executeCurrentContract("loadResource", re, loadCss);
}
}, 100);
}
function loadScript(data) {
console.log("loadScript");
global.lastScript = data;
setTimeout(eval, 1, global.lastScript.result);
global.scriptOrder++;
if (global.scriptOrder < global.scriptList.length) {
executeCurrentContract("loadResource", global.scriptList[global.scriptOrder], loadScript);
}
}
function loadCss(data) {
console.log("loadScript");
global.lastCss = data;
const ele = document.createElement("style");
ele.setAttribute("type", "text/css");
ele.innerHTML = data.result;
document.body.append(ele);
}
function needRender(con) {
for (const fun of con.exportedFunctions) {
console.log(fun);
if (fun.functionName === "needRender") {
return true;
}
}
return false;
}
function onListContractProcess(data) {
console.log(data);
console.log(data.data);
global.contracts = JSON.parse(data.data);
if (global.urlparam["contract"]) {
appendTargetContract(global.urlparam["contract"]);
} else {
renewList();
}
}
function renewList() {
const selectedContract = $("#selectContract");
selectedContract.html("");
selectedContract.append("<option value='-1'>选择合约</option>");
let selectValue = -1;
console.log(global.contracts);
console.log(global.contracts.length);
for (let i = 0; i < global.contracts.length; ++i) {
const c = global.contracts[i];
console.log(c);
if (!c.id) {
c.id = c.contractID;
}
if (!c.name) {
c.name = c.contractName;
}
selectedContract.append(`<option value='${i}'>${c.name}</option>`);
if (global.urlparam["contract"]) {
if (global.urlparam["contract"] === c.name
|| global.urlparam["contract"] === c.id) {
selectValue = i;
}
}
}
console.log(selectValue);
selectedContract[0].value = selectValue;
if (global.urlparam["contract"]) {
changeApp();
}
}
function appendTargetContract(target) {
global.wssocket.send(JSON.stringify({
action: "listTheContractProcess",
contractID: target
}));
}
function onListTheContractProcess(target) {
console.log(target);
const c = JSON.parse(target.data);
let hasTheSame = false;
if (!global.contracts) {
global.contracts = [];
}
for (const con of global.contracts) {
if (con.id === c.id) {
hasTheSame = true;
}
}
if (!hasTheSame) {
global.contracts.push(c);
}
renewList();
//"884422533"
}
function onListLocalNodeLog(data) {
const userManTab = $("#v-pills-userManager-tab")[0];
if (userManTab.getAttribute("aria-selected") === "true") {
drawUserActivityGraph(data);
} else {
drawLocalLogGraphs(data);
}
}
function onListAllAuthRole(data) {
console.log("onListAllAuthRole");
fillAuthRoleData(data.data);
}
function onListUnAuthRole(data) {
console.log("onListUnAuthRole");
fillUnAuthRoleData(data.data);
}
function onApplyNet(data) {
console.log("onApplyNet");
}
function onCountRole(data) {
console.log("onCountRole");
setUserTypeDistribution(data.data);
}
function onAuthNodeRole(data) {
myToast("授权/忽略操作", data.data);
if (data.data === "success") {
global.wssocket.send(JSON.stringify({action: "listAllAuthRole"}));
global.wssocket.send(JSON.stringify({action: "listUnAuthRole"}));
}
}
function onApplyRole(data) {
console.log(data.data);
myToast("申请操作", data.data);
}
function onDeleteRole(data) {
myToast("删除操作", data.data);
global.wssocket.send(JSON.stringify({action: "listAllAuthRole"}));
}
// ====== wsHandler done!
function myToast(title, msg) {
toastVue.toastTitle = title;
toastVue.toastMessage = msg;
$("#alertDiv").toast("show");
}
function countChar(str, c) {
let ret = 0;
for (const ch of str) {
if (ch === c) {
ret++;
}
}
return ret;
}
function generate() {
const key = sm2.generateKeyPairHex();
global.sm2Key = key;
localStorage.setItem("PrivKey", JSON.stringify(key));
}
function killAllContract() {
global.wssocket.send(JSON.stringify({action: "killAllContract"}));
}
function init() {
initVue();
initGlobal();
global.urlparam = getRequestParameters();
if (global.urlparam["noRender"] === "true") {
switchRenderBtn.innerHTML = "加载界面";
}
global.cbs = {};
const urlInput = $("#urlInput");
if (global.urlparam["self"] === "true") {
if (document.location.href.startsWith("http")) {
let path = document.location.origin + document.location.pathname;
path = path.replace("/client/bdwareclient.html", "");
urlInput[0].value = path.replace("http",
"ws");
if (global.urlparam["withNodeCenterWS"] === "true") {
urlInput[0].value += "/NodeCenterWS";
}
connectNode();
}
} else if (global.urlparam["nodeAddr"]) {
urlInput[0].value = global.urlparam["nodeAddr"];
connectNode();
} else {
const lastNode = localStorage.getItem("lastNode");
if (lastNode) {
urlInput[0].value = lastNode;
connectNode();
}
}
}
function connectNode() {
localStorage.setItem("lastNode", $("#urlInput")[0].value);
initWSocket();
}
function getRequestParameters() {
const arr = (location.search || "").replace(/^\?/, '').split("&");
const params = {};
for (const a of arr) {
const data = a.split("=");
if (data.length === 2) {
params[data[0]] = data[1];
}
}
return params;
}
function changeRender() {
if (global.urlparam["noRender"] === "true") {
global.urlparam["noRender"] = undefined;
switchRenderBtn.innerHTML = "不加载界面";
} else {
global.urlparam["noRender"] = "true";
switchRenderBtn.innerHTML = "加载界面";
}
changeApp();
}

7
js/bootstrap.min.js vendored Normal file

File diff suppressed because one or more lines are too long

229
js/commonutil.js Normal file
View File

@ -0,0 +1,229 @@
var getDateDaysBefore = function(daysAgo) {
var dateStr = new Date().toISOString().substring(0, 10);
var ret = new Date(dateStr).getTime() - daysAgo * 24 * 3600 * 1000;
return ret;
};
var primaryColor = "#2E324C";
// ======Vue start
var headerVue = "";
var pubkeyDialogVue = "";
var mainVue = "";
var select = "";
var initVue = function() {
console.log("[nodePortal.js] initVue : ");
headerVue = new Vue({
el : 'header',
data : {
shortName : "00000"
}
});
pubkeyDialogVue = new Vue({
el : '#pubkeyDialog',
data : {
sm2KeyStr : "00000",
myRole : "匿名用户",
test:"0",
selectedSM2Key:"0",
productList:[{id:0,title:"ContractProvider"},{id:1,title:"ContractUser"},{id:2,title:"ContractInstanceManager"}],
sm2KeyList:[]
},
methods : {
importPubkey : function() {
console.log("importkey trigged");
try {
var sm2Key = JSON.parse(this.sm2KeyStr);
if (sm2Key.publicKey == undefined
|| sm2Key.privateKey == undefined) {
this.sm2KeyStr = (JSON.stringify(global.sm2Key));
} else {
global.sm2Key = sm2Key;
localStorage.setItem("PrivKey", JSON
.stringify(sm2Key));
headerVue.shortName = global.sm2Key.publicKey
.substr(0, 5);
var newKey = {};
newKey.id = this.sm2KeyList.length;
newKey.title = headerVue.shortName;
newKey.sm2Key = this.sm2KeyStr;
this.sm2KeyList.push(newKey);
localStorage.setItem("PrivKeyList",JSON.stringify(this.sm2KeyList));
getSession();
listProjects("priv");
}
} catch (e) {
console.log(e);
this.sm2KeyStr = (JSON.stringify(global.sm2Key));
}
},
generatePubkey : function() {
console.log("generate pubkey trigged");
var sm2Key = sm2.generateKeyPairHex();
this.sm2KeyStr = JSON.stringify(sm2Key);
global.sm2Key = sm2Key;
localStorage.setItem("PrivKey", JSON
.stringify(sm2Key));
headerVue.shortName = global.sm2Key.publicKey
.substr(0, 5);
var newKey = {};
newKey.id = this.sm2KeyList.length;
newKey.title = headerVue.shortName;
newKey.sm2Key = this.sm2KeyStr;
this.sm2KeyList.push(newKey);
this.selectedSM2Key = newKey.id;
localStorage.setItem("PrivKeyList",JSON.stringify(this.sm2KeyList));
getSession();
},
changeProduct(event) {
this.test = event.target.value; // 获取option对应的value值
this.role = this.productList[this.test].title;
console.log("选了",this.role);
global.role=this.role;
},
apply : function() {
console.log("apply");
global.wssocket
.send("{\"action\":\"applyNet\",\"role\":\"NodeManager\"}");
},
applyRole : function() {
var role=this.productList[this.test];
console.log("applyRole, "+role);
applyRole(role.title);
},changeSM2Key:function(event){
var order = event.target.value; // 获取option对应的value值
if (order == undefined)
return;
console.log("changeSM2Key, -->"+order);
headerVue.shortName = this.sm2KeyList[order].title;
this.selectedSM2Key = order;
this.sm2KeyStr = this.sm2KeyList[order].sm2Key;
global.sm2Key = JSON.parse(this.sm2KeyStr);
localStorage.setItem("PrivKey", this.sm2KeyStr);
getSession();
},deletePubkey:function(event){
var order = this.selectedSM2Key;
var obj = this.sm2KeyList[order];
if (this.sm2KeyList.length==1){
alert("最后一对密钥不可以删除");
return;
}
var newList = [];
for (var i=0;i<order;i++){
newList.push(this.sm2KeyList[i]);
};
for (var i=order/1 +1;i<this.sm2KeyList.length;i++){
newList.push(this.sm2KeyList[i]);
};
this.sm2KeyList = newList;
for (var i=0;i<newList.length;i++){
newList[i].id = i;
}
if (order>=newList.length){
order --;
}
console.log("after delete, size:"+newList.length+" order:"+order);
localStorage.setItem("PrivKeyList", JSON.stringify(newList));
headerVue.shortName = this.sm2KeyList[order].title;
this.selectedSM2Key = order + "";
this.sm2KeyStr = this.sm2KeyList[order].sm2Key;
global.sm2Key = JSON.parse(this.sm2KeyStr);
localStorage.setItem("PrivKey", this.sm2KeyStr);
getSession();
},exportPubkey : function(event){
var uri = "data:text/html,";
uri+=localStorage.getItem("PrivKeyList");
var link = document.createElement("a");
link.download = "sm2keyList.json";
link.href = uri;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
}
}
});
mainVue = new Vue({
el : "#main",
data : {
licenceDueDate : "已过期",
licenceNodes : 0,
offlineLicence : undefined,
licenceRemark : undefined,
userCount:".",
contractCount:".",
nodeCount:".",
eventCount:".",
unitCount:".",
pubDialogVue:{},
projects:[],
contracts:[],
contractFunctions:[],
openedFiles:[{
isDir: false,
val: "Please Checkout code from left side!",
path: "Hello",
name: "Hello"
}]
}
});
};
// ======Vue done
var initGlobal = function() {
if (window.global==undefined){
window.global = {};
}
global.sm2Key = localStorage.getItem("PrivKey");
global.result = "";
if (global.sm2Key == undefined || global.sm2Key == null
|| global.sm2Key.length < 100) {
generate();
} else {
global.sm2Key = JSON.parse(global.sm2Key);
}
headerVue.shortName = global.sm2Key.publicKey.substr(0, 5);
pubkeyDialogVue.sm2KeyStr = JSON.stringify(global.sm2Key);
mainVue.pubDialogVue = pubkeyDialogVue;
var keyListStr = localStorage.getItem("PrivKeyList");
if (keyListStr==undefined){
var keyObj = {};
keyObj.id = 0;
keyObj.title = headerVue.shortName;
keyObj.sm2Key = pubkeyDialogVue.sm2KeyStr;
pubkeyDialogVue.sm2KeyList = [];
pubkeyDialogVue.sm2KeyList.push(keyObj);
pubkeyDialogVue.selectedSM2Key = 0;
// mainVue.sm2KeyList = pubkeyDialogVue.sm2KeyList;
// mainVue.selectedSM2Key = 0;
} else{
pubkeyDialogVue.sm2KeyList = JSON.parse(keyListStr);
pubkeyDialogVue.selectedSM2Key = -1;
for (var i=0;i<pubkeyDialogVue.sm2KeyList.length;i++){
var obj = pubkeyDialogVue.sm2KeyList[i];
if (obj.sm2Key==pubkeyDialogVue.sm2KeyStr){
pubkeyDialogVue.selectedSM2Key = i;
// mainVue.sm2KeyList = pubkeyDialogVue.sm2KeyList;
// mainVue.selectedSM2Key = pubkeyDialogVue.selectedSM2Key;
return;
}
}
var keyObj = {};
keyObj.id = pubkeyDialogVue.sm2KeyList.length;
keyObj.title = headerVue.shortName;
keyObj.sm2Key = pubkeyDialogVue.sm2KeyStr;
pubkeyDialogVue.sm2KeyList.push(keyObj);
pubkeyDialogVue.selectedSM2Key = keyObj.id;
// mainVue.sm2KeyList = pubkeyDialogVue.sm2KeyList;
// mainVue.selectedSM2Key = pubkeyDialogVue.selectedSM2Key;
}
}

256
js/createWS.js Normal file
View File

@ -0,0 +1,256 @@
var createWssocket = function(wsurl, onopen, handler) {
console.log("[createWS.js] createWssocket : " + wsurl);
var retsocket = {};
retsocket.handlerList = [];
if (handler != undefined)
retsocket.handlerList.push(handler);
var wssocket = new WebSocket(wsurl);
wssocket.onerror = function(error) {
console.log(error);
};
wssocket.onopen = onopen;
var onmessage = function(event) {
var obj = JSON.parse(event.data);
switch (obj.action) {
case 'sendNextSegment':
retsocket.sendNextSegment();
break;
case 'sendSeg':
retsocket.receiveSeg(obj);
break;
default:
for (var i = 0; i < retsocket.handlerList.length; i++) {
var h = retsocket.handlerList[i];
h(event, wssocket);
}
}
};
var reconnect = function(error) {
setTimeout(function() {
console.log("[createWS.js] try to reconnect");
wssocket = new WebSocket(wsurl);
wssocket.onclose = reconnect;
wssocket.onmessage = onmessage;
wssocket.onopen = onopen;
}, 1000);
};
wssocket.onclose = reconnect;
retsocket.receiveSeg = function(obj) {
if (obj.cid == 'start') {
retsocket.toReceive = "";
}
retsocket.toReceive += obj.data;
if (obj.cid == 'done') {
console.log("[receiveSeg] Received AllData:" + retsocket.toReceive);
var event = {};
event.data = retsocket.toReceive;
retsocket.toReceive = "";
handler(event);
}
};
wssocket.onmessage = onmessage;
retsocket.isSending = false;
retsocket.sendList = [];
retsocket.monitor = function() {
if (!retsocket.isSending) {
if (retsocket.sendList.length > 0) {
retsocket.send(retsocket.sendList.pop());
}
}
setTimeout(retsocket.monitor, 1000);
};
// TODO: we don't need monitor at all?
retsocket.monitor();
retsocket.send = function(str) {
if (retsocket.isSending) {
retsocket.sendList.push(str);
return;
}
if (str.length > 1024) {
retsocket.isSending = true;
retsocket.toSend = str.substr(1024);
var obj = {};
obj.isSegment = true;
obj.data = str.substr(0, 1024);
wssocket.send(JSON.stringify(obj));
} else
wssocket.send(str);
};
retsocket.sendNextSegment = function() {
var str = retsocket.toSend;
if (str.length > 1024) {
retsocket.toSend = str.substr(1024);
var obj = {};
obj.isSegment = true;
obj.data = str.substr(0, 1024);
wssocket.send(JSON.stringify(obj));
} else {
retsocket.toSend = "";
var obj = {};
obj.isSegment = false;
obj.data = str;
wssocket.send(JSON.stringify(obj));
retsocket.isSending = false;
if (retsocket.sendList.length > 0) {
retsocket.send(retsocket.sendList.pop());
}
}
};
retsocket.isOpen = function() {
return wssocket.readyState;
}
retsocket.addHandler = function(handler) {
retsocket.handlerList.push(handler);
}
return retsocket;
};
var aesDecrypt = function(data) {
data = cryptico.b64to256(data);
var encryptedBlocks = cryptico.string2bytes(data);
var exkey = global.aesKey.slice(0);
aes.ExpandKey(exkey);
aes.Decrypt(encryptedBlocks, exkey);
return cryptico.bytes2string(encryptedBlocks);
};
var aesEncrypt = function(data, aesKey) {
var key = aesKey;
var exkey = key.slice(0);
aes.ExpandKey(exkey);
var blocks = my.string2bytes(data);
blocks = my.pad16(blocks);
aes.Encrypt(blocks, exkey);
ciphertext = cryptico.bytes2string(blocks);
ciphertext = cryptico.b256to64(ciphertext);
return ciphertext;
};
var rsaEncrypt = function(data, rsaKey) {
var rsa = new RSAKey();
rsa.setPublic(rsaKey.n, rsaKey.e1);
var result = rsa.encrypt(data);
return result;
};
var loadRSAKey = function(rsaKey) {
var str = cryptico.b64to256(rsaKey);
str = str.split(",");
var ret = {};
ret.n = str[0];
ret.e1 = str[1];
ret.e2 = str[2];
return ret;
};
var testRSA = function() {
pubKey = loadRSAKey(global.privKey);
reqContent = {};
reqContent.action = "main";
reqContent.arg = "[{\"score\":20},{\"score\":20}]";
reqContent.contractID = "abc";
eReq = encryptReq(reqContent, pubKey);
url = "http://localhost:8080/SCIDE/SCManager?action=executeContractEncrypted&contractRequest="
+ encodeURIComponent(JSON.stringify(eReq));
};
var encryptReq = function(reqContent, pubKey) {
// global.pubKey = loadRSAKey(global.privKey);
var aes = {};
aes.key = cryptico.generateAESKey();
var aesObj = JSON.stringify(aes);
var rsa = new RSAKey();
rsa.setPrivate(pubKey.n, pubKey.e1, pubKey.e2);
var encrypedReq = {};
encrypedReq.action = rsa.decrypt(aesObj);
encrypedReq.contractID = reqContent.contractID;
reqContent.contractID = undefined;
encrypedReq.arg = JSON.stringify(reqContent);
encrypedReq.arg = aesEncrypt(encrypedReq.arg, aes.key);
encrypedReq.requester = pubKey.n + "," + pubKey.e1 + "," + "0";
encrypedReq.requester = cryptico.b256to64(encrypedReq.requester);
return encrypedReq;
};
var onExecuteResultInternal = function(data) {
console.log(data);
global.executeResult = data;
var reqId = data.responseID;
var callback = global.cbs[data.responseID];
if (callback != undefined) {
callback(global.executeResult, data);
}
};
window.executeContract = function(contractID, method, strarg, cb) {
var sm2Key = global.sm2Key;
var request = {};
request.action = "executeContract";
request.requestID = new Date().getTime() + "_"
+ Math.floor(Math.random() * 10000);
global.cbs[request.requestID] = cb;
request.contractID = contractID;
request.operation=method;
request.arg = strarg;
if (sm2Key != undefined) {
request.pubkey = sm2Key.publicKey;
request.signature = sm2.doSignature(request.contractID + "|"
+ method + "|" + strarg + "|" + sm2Key.publicKey,
sm2Key.privateKey,{hash:true,der:true});
}
global.wssocket.send(JSON.stringify(request));
};
window.executeCurrentContract = function(method, strarg, cb) {
console.log("executeCurrentContract");
var contract = global.currentContract;
executeContract(contract.id, method, strarg, cb);
};
window.loadBDWareWebSDK = function(url, onopen, handler) {
if (window.global == undefined) {
window.global = {};
}
if (global.sm2Key == undefined) {
if (sm2 != undefined)
global.sm2Key = sm2.generateKeyPairHex();
}
if (global.cbs == undefined) {
global.cbs = {};
}
if (global.wssocket == undefined) {
global.wssocket = createWssocket(url, onopen, function(event, wss) {
var data = event.data;
var obj = JSON.parse(data);
switch (obj.action) {
case 'onExecuteResult':
onExecuteResultInternal(obj);
default:
}
handler(event, global.wssocket);
});
} else {
if (onopen != undefined)
onopen();
global.wssocket.addHandler(handler);
}
};
// Usage:
// Approach 1:
// var url = "ws://" +
// document.location.host+(document.location.pathname.replace("scide.html",
// "SCExecutor"));
// global.wssocket = createWssocket(url, WSHandler);
// Approach 2:
// loadBDWareWebSDK(url,function(){},WSHandler);
// global.currentContract = {'id':'DataAnalysisSample'};
// executeContract("contractID","methodName","arg",function(data){
// });
// executeCurrentContract("methodName","arg",function(data){
// });
// the bdware client won't call this method

3560
js/cryptico.js Normal file

File diff suppressed because it is too large Load Diff

9210
js/jquery-2.1.4.js vendored Normal file

File diff suppressed because it is too large Load Diff

2101
js/sm2.js Normal file

File diff suppressed because it is too large Load Diff

11965
js/vue.js Normal file

File diff suppressed because it is too large Load Diff