WIP
parent
6ff597c106
commit
63f02b047e
20
demo.html
20
demo.html
|
@ -5,14 +5,7 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<link rel="stylesheet" href="css/ln.vue.css"/>
|
<link rel="stylesheet" href="css/ln.vue.css"/>
|
||||||
|
|
||||||
<script type="text/javascript" src="js/vue.js"></script>
|
<script type="text/javascript" src="js"></script>
|
||||||
<script type="text/javascript" src="js/vue-router.js"></script>
|
|
||||||
|
|
||||||
<script type="text/javascript" src="js/ln.vue.js"></script>
|
|
||||||
<script type="text/javascript" src="js/ln.vue.components.js"></script>
|
|
||||||
<script type="text/javascript" src="js/ln.vue.table.js"></script>
|
|
||||||
<script type="text/javascript" src="js/ln.vue.webauthn.js"></script>
|
|
||||||
<script type="text/javascript" src="js/ln.identities.js"></script>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
table#controls > tbody > tr > td:nth-child(3) {
|
table#controls > tbody > tr > td:nth-child(3) {
|
||||||
|
@ -59,7 +52,14 @@
|
||||||
},
|
},
|
||||||
routes: {
|
routes: {
|
||||||
'/': {
|
'/': {
|
||||||
template: `<div>This is the ln.vue demo application. Feel free to test all the features, you can find.<br>Here should be a message:<br><i>{{ message.value }}</i></div>`,
|
template: `<div>This is the ln.vue demo application.<br>
|
||||||
|
Feel free to test all the features, you can find.<br>
|
||||||
|
Here should be a message:<br>
|
||||||
|
<i>{{ message.value }}</i><br>
|
||||||
|
<br>
|
||||||
|
<div v-if="LN.Vue.$_.identity.hasRole(LN.Identity.VIEW,'demo')">You are allowed to see this!</div>
|
||||||
|
<div v-if="!LN.Vue.$_.identity.hasRole(LN.Identity.VIEW,'demo')">Login using demo/demopass to see the hidden message!</div>
|
||||||
|
</div>`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -91,7 +91,7 @@
|
||||||
|
|
||||||
let message = { value: "" };
|
let message = { value: "" };
|
||||||
|
|
||||||
app = new LNVue("#frame",{
|
app = new LN.Vue("#frame",{
|
||||||
data: {
|
data: {
|
||||||
message: message,
|
message: message,
|
||||||
columns: {
|
columns: {
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
(function(){
|
||||||
|
/*\
|
||||||
|
|*|
|
||||||
|
|*| Base64 / binary data / UTF-8 strings utilities (#1)
|
||||||
|
|*|
|
||||||
|
|*| https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding
|
||||||
|
|*|
|
||||||
|
|*| Author: madmurphy
|
||||||
|
|*|
|
||||||
|
|*| Harald Wolff-Thobaben: Small adaptions to create a static class
|
||||||
|
|*|
|
||||||
|
\*/
|
||||||
|
class Base64
|
||||||
|
{
|
||||||
|
constructor(){
|
||||||
|
}
|
||||||
|
|
||||||
|
static b64ToUint6(nChr){
|
||||||
|
return nChr > 64 && nChr < 91 ?
|
||||||
|
nChr - 65
|
||||||
|
: nChr > 96 && nChr < 123 ?
|
||||||
|
nChr - 71
|
||||||
|
: nChr > 47 && nChr < 58 ?
|
||||||
|
nChr + 4
|
||||||
|
: nChr === 43 ?
|
||||||
|
62
|
||||||
|
: nChr === 47 ?
|
||||||
|
63
|
||||||
|
:
|
||||||
|
0;
|
||||||
|
}
|
||||||
|
static uint6ToB64(nUint6){
|
||||||
|
return nUint6 < 26 ?
|
||||||
|
nUint6 + 65
|
||||||
|
: nUint6 < 52 ?
|
||||||
|
nUint6 + 71
|
||||||
|
: nUint6 < 62 ?
|
||||||
|
nUint6 - 4
|
||||||
|
: nUint6 === 62 ?
|
||||||
|
43
|
||||||
|
: nUint6 === 63 ?
|
||||||
|
47
|
||||||
|
:
|
||||||
|
65;
|
||||||
|
}
|
||||||
|
|
||||||
|
static encode(aBytes){
|
||||||
|
var eqLen = (3 - (aBytes.length % 3)) % 3, sB64Enc = "";
|
||||||
|
|
||||||
|
for (var nMod3, nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) {
|
||||||
|
nMod3 = nIdx % 3;
|
||||||
|
nUint24 |= aBytes[nIdx] << (16 >>> nMod3 & 24);
|
||||||
|
if (nMod3 === 2 || aBytes.length - nIdx === 1) {
|
||||||
|
sB64Enc += String.fromCharCode(Base64.uint6ToB64(nUint24 >>> 18 & 63), Base64.uint6ToB64(nUint24 >>> 12 & 63), Base64.uint6ToB64(nUint24 >>> 6 & 63), Base64.uint6ToB64(nUint24 & 63));
|
||||||
|
nUint24 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return eqLen === 0 ?
|
||||||
|
sB64Enc
|
||||||
|
:
|
||||||
|
sB64Enc.substring(0, sB64Enc.length - eqLen) + (eqLen === 1 ? "=" : "==");
|
||||||
|
}
|
||||||
|
|
||||||
|
static decode(sBase64, nBlockSize) {
|
||||||
|
var
|
||||||
|
sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""), nInLen = sB64Enc.length,
|
||||||
|
nOutLen = nBlockSize ? Math.ceil((nInLen * 3 + 1 >>> 2) / nBlockSize) * nBlockSize : nInLen * 3 + 1 >>> 2, aBytes = new Uint8Array(nOutLen);
|
||||||
|
|
||||||
|
for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) {
|
||||||
|
nMod4 = nInIdx & 3;
|
||||||
|
nUint24 |= Base64.b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4;
|
||||||
|
if (nMod4 === 3 || nInLen - nInIdx === 1) {
|
||||||
|
for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {
|
||||||
|
aBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;
|
||||||
|
}
|
||||||
|
nUint24 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return aBytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LN.$add("LN.Base64",Base64);
|
||||||
|
})();
|
|
@ -11,18 +11,20 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
findRolesByName(identityName){
|
findRolesByName(identityName){
|
||||||
|
let roleMask = 0;
|
||||||
this.Roles.forEach(role => {
|
this.Roles.forEach(role => {
|
||||||
if (role.IdentityName == identityName)
|
if (role.IdentityName == identityName)
|
||||||
return role.Roles;
|
roleMask = role.Roles;
|
||||||
});
|
});
|
||||||
return 0;
|
return roleMask;
|
||||||
}
|
}
|
||||||
findRolesByID(identityUniqueID){
|
findRolesByID(identityUniqueID){
|
||||||
|
let roleMask = 0;
|
||||||
this.Roles.forEach(role => {
|
this.Roles.forEach(role => {
|
||||||
if (role.UniqueID == identityUniqueID)
|
if (role.UniqueID == identityUniqueID)
|
||||||
return role.Roles;
|
roleMask = role.Roles;
|
||||||
});
|
});
|
||||||
return 0;
|
return roleMask;;
|
||||||
}
|
}
|
||||||
|
|
||||||
hasRole(role,identityName){
|
hasRole(role,identityName){
|
|
@ -0,0 +1,59 @@
|
||||||
|
(function(){
|
||||||
|
class LNPromise
|
||||||
|
{
|
||||||
|
constructor(executor, label){
|
||||||
|
this.promise = new Promise(
|
||||||
|
(resolve,reject) => {
|
||||||
|
this.resolve = (v) => {
|
||||||
|
this._s.state = "ready";
|
||||||
|
resolve(v);
|
||||||
|
this.release();
|
||||||
|
},
|
||||||
|
this.reject = (e) => {
|
||||||
|
this._s.state = "failed";
|
||||||
|
reject(e);
|
||||||
|
this.release();
|
||||||
|
}
|
||||||
|
executor && executor(
|
||||||
|
this.resolve,
|
||||||
|
this.reject
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!label)
|
||||||
|
label = "N.D.";
|
||||||
|
|
||||||
|
this._s = {
|
||||||
|
label,
|
||||||
|
state: "waiting"
|
||||||
|
};
|
||||||
|
|
||||||
|
this.idx = LN.$unique();
|
||||||
|
LNPromise.$current[this.idx] = this._s;
|
||||||
|
}
|
||||||
|
|
||||||
|
label(){
|
||||||
|
return this._s.label;
|
||||||
|
}
|
||||||
|
|
||||||
|
state(){
|
||||||
|
return this._s.state;
|
||||||
|
}
|
||||||
|
|
||||||
|
release(){
|
||||||
|
setTimeout(()=>{
|
||||||
|
Vue.delete(LNPromise.$current, this.idx);
|
||||||
|
},1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
then(){
|
||||||
|
return this.promise.then.apply(this.promise, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
static getCurrentPromises(){ return LNPromise.$current; }
|
||||||
|
}
|
||||||
|
LNPromise.$current = {};
|
||||||
|
|
||||||
|
LN.$add("LN.Promise",LNPromise);
|
||||||
|
})();
|
|
@ -4,7 +4,7 @@ let nextTooltipKey = 0;
|
||||||
var tooltipData = {};
|
var tooltipData = {};
|
||||||
|
|
||||||
var tootlipVisible = false;
|
var tootlipVisible = false;
|
||||||
var tooltipEl = LNVue.$(`<div class="ln-tooltip"></div>`);
|
var tooltipEl = LN.$(`<div class="ln-tooltip"></div>`);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -572,6 +572,44 @@ Vue.component('ln-identity',{
|
||||||
</div>`,
|
</div>`,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Vue.component('ln-popup',{
|
||||||
|
props: {
|
||||||
|
title: String,
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
show: function(){
|
||||||
|
this.visible = true;
|
||||||
|
},
|
||||||
|
hide: function(){
|
||||||
|
this.visible = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `<div class="ln-popup">
|
||||||
|
<div
|
||||||
|
class="ln-popup-frame"
|
||||||
|
><div
|
||||||
|
class="ln-popup-title"
|
||||||
|
v-if="title"
|
||||||
|
>{{ title }}</div>
|
||||||
|
<div class="ln-popup-content">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="ln-popup-footer"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
@click="hide()"
|
||||||
|
>schliessen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
|
||||||
Vue.component('ln-login-pane',{
|
Vue.component('ln-login-pane',{
|
||||||
props: {
|
props: {
|
||||||
},
|
},
|
|
@ -0,0 +1,274 @@
|
||||||
|
(function (){
|
||||||
|
|
||||||
|
let exModule = {
|
||||||
|
label: 'Example Module',
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
path: '/about',
|
||||||
|
template: `This is about this example!`,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
navigation: {
|
||||||
|
'99': {
|
||||||
|
label: 'About',
|
||||||
|
href: '/about'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
let defaultOptions = {
|
||||||
|
element: 'body',
|
||||||
|
modules: [ exModule, ],
|
||||||
|
};
|
||||||
|
|
||||||
|
class LNVue
|
||||||
|
{
|
||||||
|
constructor(el,options = {}){
|
||||||
|
this.options = Object.assign({
|
||||||
|
routes: [],
|
||||||
|
data: {},
|
||||||
|
}, options );
|
||||||
|
|
||||||
|
this._el = el;
|
||||||
|
this.data = Object.assign({}, options.data, { LNVue: this, msg: "Hello World" });
|
||||||
|
this.promises = [];
|
||||||
|
|
||||||
|
this.statusText = "LNVue preparing";
|
||||||
|
|
||||||
|
Vue.prototype.$LNVue = this;
|
||||||
|
LNVue.$_ = this;
|
||||||
|
|
||||||
|
this.navigation = {};
|
||||||
|
this.identity = new LN.Identity();
|
||||||
|
|
||||||
|
Promise
|
||||||
|
.all(LNVue.promises)
|
||||||
|
.then(()=>{
|
||||||
|
this.status("LNVue: starting");
|
||||||
|
|
||||||
|
LNVue.vueRouter.addRoutes([{
|
||||||
|
path: "*",
|
||||||
|
component: {
|
||||||
|
template: `<h2>404 Not Found</h2>The URL you tried to reach is not existing.`,
|
||||||
|
},
|
||||||
|
}]);
|
||||||
|
},
|
||||||
|
(cause)=>{
|
||||||
|
this.status("LNVue: start failed: " + cause);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.vue = null;
|
||||||
|
|
||||||
|
LNVue.$instance.resolve(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Start(){
|
||||||
|
Promise
|
||||||
|
.all(this.promises)
|
||||||
|
.then(()=>{
|
||||||
|
LN.$idle(()=>{
|
||||||
|
this.vue = new Vue({
|
||||||
|
el: this._el,
|
||||||
|
data: this.data,
|
||||||
|
router: LNVue.vueRouter,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
LN.$idle(()=>{
|
||||||
|
this.socket = new LN.Vue.WebSocket(this);
|
||||||
|
this.socket.open();
|
||||||
|
});
|
||||||
|
LN.$idle(()=>{
|
||||||
|
LNVue.$start.resolve(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
storage(){
|
||||||
|
return window.localStorage;
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionID(){
|
||||||
|
if (arguments.length == 1){
|
||||||
|
this.storage().setItem("LNVueSessionID",arguments[0]);
|
||||||
|
console.log("LNVue.SID <= " + arguments[0]);
|
||||||
|
return this;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
let sid = this.storage().getItem("LNVueSessionID");
|
||||||
|
console.log("LNVue.SID == " + sid);
|
||||||
|
if (!sid)
|
||||||
|
{
|
||||||
|
sid = "00000000-0000-0000-0000-000000000000";
|
||||||
|
}
|
||||||
|
return sid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Version(){ return "0.2alpha"; };
|
||||||
|
getCurrentPromises() {
|
||||||
|
return LN.Promise.getCurrentPromises();
|
||||||
|
}
|
||||||
|
|
||||||
|
status(){
|
||||||
|
if (arguments.length == 1){
|
||||||
|
this.statusText = arguments[0];
|
||||||
|
return this;
|
||||||
|
} else if (arguments.length == 0){
|
||||||
|
return this.statusText;
|
||||||
|
} else
|
||||||
|
throw "LNVue.status(): too many arguments";
|
||||||
|
}
|
||||||
|
|
||||||
|
addModule(modSpec){
|
||||||
|
if (modSpec.navigation instanceof Object){
|
||||||
|
LNVue.deepAssign(modSpec.navigation,this.navigation);
|
||||||
|
}
|
||||||
|
|
||||||
|
LN.$each(modSpec.routes,(key,route)=>{
|
||||||
|
if ((route instanceof Object) && route.url)
|
||||||
|
{
|
||||||
|
let p = new LN.Promise((resolve,reject)=>{
|
||||||
|
LN.$fetch(route.url)
|
||||||
|
.then((src)=>{
|
||||||
|
this.addRoute(key,{ template: src, data: ()=>{ return this.data; }, });
|
||||||
|
resolve();
|
||||||
|
},
|
||||||
|
(cause)=>{
|
||||||
|
console.log("loading route.url failed: ",cause);
|
||||||
|
});
|
||||||
|
},`addModule(${route.url})`);
|
||||||
|
this.promises.push(p);
|
||||||
|
} else if (route instanceof Object){
|
||||||
|
this.addRoute(key,{ template: route.template, data: ()=>{ return this.data; }, } );
|
||||||
|
} else {
|
||||||
|
this.addRoute(key,{ template: route, data: ()=>{ return this.data; }, } );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addRoute(path,component){
|
||||||
|
LNVue.vueRouter.addRoutes([
|
||||||
|
{ path, component, },
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (this.vue){
|
||||||
|
let route = this.vue.$route;
|
||||||
|
LNVue.vueRouter.replace("/");
|
||||||
|
LNVue.vueRouter.replace(route);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Authentication API */
|
||||||
|
|
||||||
|
requestChallenges(identityName,secureAttributeTypeName){
|
||||||
|
return new Promise((resolve,reject)=>{
|
||||||
|
this.socket.request("AuthenticationRequest",{
|
||||||
|
IdentityName: identityName,
|
||||||
|
SecureAttributeTypeName: secureAttributeTypeName,
|
||||||
|
})
|
||||||
|
.then((challenges)=>{
|
||||||
|
resolve(challenges);
|
||||||
|
},
|
||||||
|
(error)=>{
|
||||||
|
console.log("Login challenges could not be retrieved", error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticate(identityName,secureAttributeID,challenge,prove){
|
||||||
|
let authenticationProve = {
|
||||||
|
IdentityName: identityName,
|
||||||
|
SecureAttributeUniqueID: secureAttributeID,
|
||||||
|
Challenge: challenge,
|
||||||
|
Prove: prove,
|
||||||
|
};
|
||||||
|
this.socket.request("AuthenticationProve", authenticationProve)
|
||||||
|
.then((identity)=>{
|
||||||
|
this.identity = new LN.Identity(identity.message);
|
||||||
|
},
|
||||||
|
(error)=>{
|
||||||
|
this.identity = new LN.Identity();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
rpc(moduleName,methodName,parameters){
|
||||||
|
return new Promise((resolve,reject)=>{
|
||||||
|
let rpcCall = {
|
||||||
|
module: moduleName,
|
||||||
|
method: methodName,
|
||||||
|
parameters: parameters
|
||||||
|
};
|
||||||
|
this.socket.request("RPCCall",rpcCall)
|
||||||
|
.then(
|
||||||
|
(result)=>{
|
||||||
|
if (result.message.error)
|
||||||
|
{
|
||||||
|
console.log("rpc call failed", result.message.error);
|
||||||
|
reject(result.message.error);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
resolve(result.message.Result);
|
||||||
|
},
|
||||||
|
(error)=>{
|
||||||
|
console.log("rpc failed", error);
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static $LNVue(){
|
||||||
|
return LNVue.$_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LNVue.$instance = new LN.Promise(()=>{},'LN.Vue Instance Promise');
|
||||||
|
LNVue.$start = new LN.Promise(()=>{},'LN Vue Startup Promise');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
LNVue.vueRouter = new VueRouter({
|
||||||
|
mode: 'history',
|
||||||
|
routes: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
LNVue.deepAssign = function(source,target){
|
||||||
|
LN.$each(source,function(key){
|
||||||
|
if (target[key] instanceof Object){
|
||||||
|
LNVue.deepAssign(src[key],target[key]);
|
||||||
|
} else {
|
||||||
|
target[key] = source[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
LNVue.routes = [];
|
||||||
|
LNVue.promises = [];
|
||||||
|
|
||||||
|
LNVue.encodeHex = (bytes) => bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '');
|
||||||
|
LNVue.decodeHex = (hexString) => new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
|
||||||
|
|
||||||
|
ArrayBuffer.combine = function(...args){
|
||||||
|
let byteLength = 0;
|
||||||
|
args.forEach((arg,index)=>{
|
||||||
|
byteLength = byteLength + arg.byteLength;
|
||||||
|
});
|
||||||
|
|
||||||
|
let result = new Uint8Array(byteLength);
|
||||||
|
let p = 0;
|
||||||
|
args.forEach((arg,index)=>{
|
||||||
|
for (let n=0;n<arg.byteLength;n++)
|
||||||
|
{
|
||||||
|
result[p++] = arg[n];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log("combine",new Uint8Array(result));
|
||||||
|
return result.buffer
|
||||||
|
};
|
||||||
|
|
||||||
|
LN.$add("LN.Vue",LNVue);
|
||||||
|
LN.$add("LNVue",LNVue);
|
||||||
|
})();
|
|
@ -0,0 +1,45 @@
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
// LNVue.prototype.createCredentials = function(_challenge,rp,userId,crossplatform,attestation){
|
||||||
|
// crossplatform = crossplatform ? true : false;
|
||||||
|
// if (!attestation)
|
||||||
|
// attestation = "none";
|
||||||
|
|
||||||
|
// let credCreateOptions = {
|
||||||
|
// challenge: Uint8Array.from(_challenge, c => c.charCodeAt(0)),
|
||||||
|
// rp: {
|
||||||
|
// id: rp,
|
||||||
|
// name: 'LN.Vue Demo Application',
|
||||||
|
// },
|
||||||
|
// user: {
|
||||||
|
// id: Int8Array.from(userId, c => c.charCodeAt(0)),
|
||||||
|
// name: 'SomeUser',
|
||||||
|
// displayName: "Some user for now...",
|
||||||
|
// },
|
||||||
|
// pubKeyCredParams: [
|
||||||
|
// {
|
||||||
|
// type: 'public-key',
|
||||||
|
// alg: -7,
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
|
// authenticatorSelection: {
|
||||||
|
// authenticatorAttachment: crossplatform ? 'cross-platform' : 'platform',
|
||||||
|
// },
|
||||||
|
// timeout: 60000,
|
||||||
|
// attestation: attestation,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// console.log(credCreateOptions);
|
||||||
|
// navigator.credentials.create({
|
||||||
|
// publicKey: credCreateOptions
|
||||||
|
// });
|
||||||
|
|
||||||
|
// };
|
||||||
|
|
||||||
|
// LNVue.prototype.createAuthToken = function(){
|
||||||
|
|
||||||
|
// };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
})();
|
|
@ -0,0 +1,137 @@
|
||||||
|
(function(){
|
||||||
|
class LNVueWebSocket
|
||||||
|
{
|
||||||
|
constructor(lnvue,o){
|
||||||
|
this.LNVue = lnvue;
|
||||||
|
this.options = Object.assign({},o);
|
||||||
|
|
||||||
|
if (!this.options.url)
|
||||||
|
this.options.url = this.constructURL();
|
||||||
|
|
||||||
|
this._id = 1;
|
||||||
|
this.defaultTimeout = 30000;
|
||||||
|
this.websocket = null;
|
||||||
|
this.callbacks = {};
|
||||||
|
|
||||||
|
this._state = "initialized";
|
||||||
|
this._retry = null;
|
||||||
|
|
||||||
|
this.closing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructURL(){
|
||||||
|
var pageURI = window.location;
|
||||||
|
|
||||||
|
var scheme = pageURI.scheme == "https" ? "wss:" : "ws:";
|
||||||
|
var host = pageURI.host;
|
||||||
|
|
||||||
|
return scheme + "//" + host + "/socket";
|
||||||
|
}
|
||||||
|
|
||||||
|
open(){
|
||||||
|
if (this._retry){
|
||||||
|
clearTimeout(this._retry);
|
||||||
|
}
|
||||||
|
this.closing = false;
|
||||||
|
|
||||||
|
this.websocket = new WebSocket(this.options.url);
|
||||||
|
this.websocket.onopen = (e) =>{
|
||||||
|
console.log("WebSocket connected");
|
||||||
|
this._state = "ONLINE";
|
||||||
|
|
||||||
|
let WSHello = {
|
||||||
|
ApplicationSessionID: this.LNVue.sessionID(),
|
||||||
|
};
|
||||||
|
console.log("WSHello request",WSHello);
|
||||||
|
|
||||||
|
this.request("WSHello",WSHello)
|
||||||
|
.then((wsh)=>{
|
||||||
|
console.log("WSHello response",wsh);
|
||||||
|
this.LNVue.sessionID(wsh.message.ApplicationSessionID);
|
||||||
|
this.LNVue.identity = new LN.Identity(wsh.message.SessionIdentity);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
this.websocket.onclose = (e)=>{ this._onclose(e); this._state = "OFFLINE"; };
|
||||||
|
this.websocket.onerror = (e)=>{ this._onerror(e); this._state = "ERROR"; };
|
||||||
|
this.websocket.onmessage = (e)=>{ this._onmessage(e); };
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(){
|
||||||
|
if (this.websocket){
|
||||||
|
this.closing = true;
|
||||||
|
this.websocket.close(200,"close() called");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request(msgtype,msg,timeout){
|
||||||
|
let message = {
|
||||||
|
id: this._id++,
|
||||||
|
type: msgtype,
|
||||||
|
message: msg,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!timeout)
|
||||||
|
timeout = this.defaultTimeout;
|
||||||
|
|
||||||
|
if (timeout != -1){
|
||||||
|
return new Promise((resolve,reject)=>{
|
||||||
|
let to = setTimeout(()=>{
|
||||||
|
delete this.callbacks[message.id];
|
||||||
|
reject("timed out");
|
||||||
|
},timeout);
|
||||||
|
|
||||||
|
this.callbacks[message.id] = (msgtype,msg)=>{
|
||||||
|
clearTimeout(to);
|
||||||
|
delete this.callbacks[message.id];
|
||||||
|
if (msgtype == "error")
|
||||||
|
reject(msg);
|
||||||
|
else
|
||||||
|
resolve({type: msgtype,message: msg});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.websocket.send(
|
||||||
|
JSON.stringify(message)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
new Promise((resolve,reject)=>{
|
||||||
|
this.websocket.send(
|
||||||
|
JSON.stringify(message)
|
||||||
|
);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_onclose(evt){
|
||||||
|
this.websocket = null;
|
||||||
|
this.options.onclose && this.options.onclose(evt);
|
||||||
|
if (!this.closing)
|
||||||
|
{
|
||||||
|
this._retry = setTimeout(() => {
|
||||||
|
this._retry = null;
|
||||||
|
console.log("reconnect...")
|
||||||
|
this.open();
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_onerror(evt){
|
||||||
|
this.options.onerror && this.options.onerror(evt);
|
||||||
|
}
|
||||||
|
_onmessage(evt){
|
||||||
|
try
|
||||||
|
{
|
||||||
|
let j = JSON.parse(evt.data);
|
||||||
|
let cb = this.callbacks[ j.id ];
|
||||||
|
cb && cb(j.type,j.message);
|
||||||
|
} catch(exc){
|
||||||
|
console.log(exc,evt.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LN.$add("LN.Vue.WebSocket",LNVueWebSocket);
|
||||||
|
})();
|
|
@ -0,0 +1,107 @@
|
||||||
|
(function(globals){
|
||||||
|
let _unique = new Date().getTime();
|
||||||
|
let __idles__ = [];
|
||||||
|
|
||||||
|
class LN
|
||||||
|
{
|
||||||
|
constructor(opts){
|
||||||
|
}
|
||||||
|
|
||||||
|
static $each(oa,cb){
|
||||||
|
if (oa instanceof Array){
|
||||||
|
let result = [];
|
||||||
|
oa.forEach((value,index)=>{
|
||||||
|
result.push(cb.call(value,index,value));
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
} else if (oa instanceof Object){
|
||||||
|
let result = {};
|
||||||
|
Object.keys(oa).forEach((key)=>{
|
||||||
|
if (oa.hasOwnProperty(key)){
|
||||||
|
result[key] = cb.call(oa[key],key,oa[key]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static $idle(cb,thisval = null){
|
||||||
|
let scheduled = __idles__.length > 0;
|
||||||
|
let n=0;
|
||||||
|
|
||||||
|
for (;n<__idles__.length;n++){
|
||||||
|
let idle = __idles__[n];
|
||||||
|
if ((idle[0] == cb) && (idle[1] == thisval))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (n == __idles__.length)
|
||||||
|
__idles__.push([cb,thisval]);
|
||||||
|
|
||||||
|
if (!scheduled)
|
||||||
|
setTimeout(()=>{
|
||||||
|
while (__idles__.length > 0){
|
||||||
|
let idle = __idles__.pop();
|
||||||
|
idle[0].call(idle[1]);
|
||||||
|
}
|
||||||
|
},0);
|
||||||
|
}
|
||||||
|
static $unique(){
|
||||||
|
return _unique++;
|
||||||
|
}
|
||||||
|
static $fetch(url,cb){
|
||||||
|
return new LN.Promise((resolve,reject)=>{
|
||||||
|
fetch(url)
|
||||||
|
.then((response => {
|
||||||
|
if (response.status.toString().startsWith("2"))
|
||||||
|
{
|
||||||
|
let t = response.text();
|
||||||
|
cb && cb(t,null);
|
||||||
|
resolve(t);
|
||||||
|
} else {
|
||||||
|
cb && cb(null, response.statusText);
|
||||||
|
reject(response.statusText);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}, `fetch(${url})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
static $resolve(v){
|
||||||
|
if (v instanceof Function)
|
||||||
|
return v();
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static $add(classpath,c){
|
||||||
|
let p = classpath.split(".");
|
||||||
|
if (p.length < 1)
|
||||||
|
throw "invalid classpath";
|
||||||
|
|
||||||
|
let container = globals;
|
||||||
|
while (p.length > 1){
|
||||||
|
let next = p.shift();
|
||||||
|
if (!container[next])
|
||||||
|
container[next] = {}
|
||||||
|
container = container[next];
|
||||||
|
}
|
||||||
|
|
||||||
|
let prev = container[p[0]];
|
||||||
|
container[p[0]] = c;
|
||||||
|
|
||||||
|
if (prev)
|
||||||
|
{
|
||||||
|
LN.$each(prev,(key,value)=>{
|
||||||
|
c[key] = value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static $(selector){
|
||||||
|
let el = document.createElement("parse");
|
||||||
|
el.innerHTML = selector;
|
||||||
|
return el.firstChild;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LN.prototypes = {};
|
||||||
|
|
||||||
|
LN.$add("LN", LN);
|
||||||
|
})(window);
|
634
js/ln.vue.js
634
js/ln.vue.js
|
@ -1,634 +0,0 @@
|
||||||
(function(globals){
|
|
||||||
let _unique = new Date().getTime();
|
|
||||||
let __idles__ = [];
|
|
||||||
|
|
||||||
class LN
|
|
||||||
{
|
|
||||||
constructor(opts){
|
|
||||||
}
|
|
||||||
|
|
||||||
static $each(oa,cb){
|
|
||||||
if (oa instanceof Array){
|
|
||||||
let result = [];
|
|
||||||
oa.forEach((value,index)=>{
|
|
||||||
result.push(cb.call(value,index,value));
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
} else if (oa instanceof Object){
|
|
||||||
let result = {};
|
|
||||||
Object.keys(oa).forEach((key)=>{
|
|
||||||
if (oa.hasOwnProperty(key)){
|
|
||||||
result[key] = cb.call(oa[key],key,oa[key]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static $idle(cb,thisval = null){
|
|
||||||
let scheduled = __idles__.length > 0;
|
|
||||||
let n=0;
|
|
||||||
|
|
||||||
for (;n<__idles__.length;n++){
|
|
||||||
let idle = __idles__[n];
|
|
||||||
if ((idle[0] == cb) && (idle[1] == thisval))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (n == __idles__.length)
|
|
||||||
__idles__.push([cb,thisval]);
|
|
||||||
|
|
||||||
if (!scheduled)
|
|
||||||
setTimeout(()=>{
|
|
||||||
while (__idles__.length > 0){
|
|
||||||
let idle = __idles__.pop();
|
|
||||||
idle[0].call(idle[1]);
|
|
||||||
}
|
|
||||||
},0);
|
|
||||||
}
|
|
||||||
static $unique(){
|
|
||||||
return _unique++;
|
|
||||||
}
|
|
||||||
static $fetch(url,cb){
|
|
||||||
return new LN.Promise((resolve,reject)=>{
|
|
||||||
fetch(url)
|
|
||||||
.then((response => {
|
|
||||||
if (response.status.toString().startsWith("2"))
|
|
||||||
{
|
|
||||||
let t = response.text();
|
|
||||||
cb && cb(t,null);
|
|
||||||
resolve(t);
|
|
||||||
} else {
|
|
||||||
cb && cb(null, response.statusText);
|
|
||||||
reject(response.statusText);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}, `fetch(${url})`);
|
|
||||||
}
|
|
||||||
|
|
||||||
static $add(classpath,c){
|
|
||||||
let p = classpath.split(".");
|
|
||||||
if (p.length < 1)
|
|
||||||
throw "invalid classpath";
|
|
||||||
|
|
||||||
let container = globals;
|
|
||||||
while (p.length > 1){
|
|
||||||
let next = p.shift();
|
|
||||||
if (!container[next])
|
|
||||||
container[next] = {}
|
|
||||||
container = container[next];
|
|
||||||
}
|
|
||||||
|
|
||||||
let prev = container[p[0]];
|
|
||||||
container[p[0]] = c;
|
|
||||||
|
|
||||||
if (prev)
|
|
||||||
{
|
|
||||||
LN.$each(prev,(key,value)=>{
|
|
||||||
c[key] = value;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
LN.prototypes = {};
|
|
||||||
|
|
||||||
LN.$add("LN", LN);
|
|
||||||
})(window);
|
|
||||||
|
|
||||||
(function(){
|
|
||||||
/*\
|
|
||||||
|*|
|
|
||||||
|*| Base64 / binary data / UTF-8 strings utilities (#1)
|
|
||||||
|*|
|
|
||||||
|*| https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding
|
|
||||||
|*|
|
|
||||||
|*| Author: madmurphy
|
|
||||||
|*|
|
|
||||||
|*| Harald Wolff-Thobaben: Small adaptions to create a static class
|
|
||||||
|*|
|
|
||||||
\*/
|
|
||||||
class Base64
|
|
||||||
{
|
|
||||||
constructor(){
|
|
||||||
}
|
|
||||||
|
|
||||||
static b64ToUint6(nChr){
|
|
||||||
return nChr > 64 && nChr < 91 ?
|
|
||||||
nChr - 65
|
|
||||||
: nChr > 96 && nChr < 123 ?
|
|
||||||
nChr - 71
|
|
||||||
: nChr > 47 && nChr < 58 ?
|
|
||||||
nChr + 4
|
|
||||||
: nChr === 43 ?
|
|
||||||
62
|
|
||||||
: nChr === 47 ?
|
|
||||||
63
|
|
||||||
:
|
|
||||||
0;
|
|
||||||
}
|
|
||||||
static uint6ToB64(nUint6){
|
|
||||||
return nUint6 < 26 ?
|
|
||||||
nUint6 + 65
|
|
||||||
: nUint6 < 52 ?
|
|
||||||
nUint6 + 71
|
|
||||||
: nUint6 < 62 ?
|
|
||||||
nUint6 - 4
|
|
||||||
: nUint6 === 62 ?
|
|
||||||
43
|
|
||||||
: nUint6 === 63 ?
|
|
||||||
47
|
|
||||||
:
|
|
||||||
65;
|
|
||||||
}
|
|
||||||
|
|
||||||
static encode(aBytes){
|
|
||||||
var eqLen = (3 - (aBytes.length % 3)) % 3, sB64Enc = "";
|
|
||||||
|
|
||||||
for (var nMod3, nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) {
|
|
||||||
nMod3 = nIdx % 3;
|
|
||||||
nUint24 |= aBytes[nIdx] << (16 >>> nMod3 & 24);
|
|
||||||
if (nMod3 === 2 || aBytes.length - nIdx === 1) {
|
|
||||||
sB64Enc += String.fromCharCode(Base64.uint6ToB64(nUint24 >>> 18 & 63), Base64.uint6ToB64(nUint24 >>> 12 & 63), Base64.uint6ToB64(nUint24 >>> 6 & 63), Base64.uint6ToB64(nUint24 & 63));
|
|
||||||
nUint24 = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return eqLen === 0 ?
|
|
||||||
sB64Enc
|
|
||||||
:
|
|
||||||
sB64Enc.substring(0, sB64Enc.length - eqLen) + (eqLen === 1 ? "=" : "==");
|
|
||||||
}
|
|
||||||
|
|
||||||
static decode(sBase64, nBlockSize) {
|
|
||||||
var
|
|
||||||
sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""), nInLen = sB64Enc.length,
|
|
||||||
nOutLen = nBlockSize ? Math.ceil((nInLen * 3 + 1 >>> 2) / nBlockSize) * nBlockSize : nInLen * 3 + 1 >>> 2, aBytes = new Uint8Array(nOutLen);
|
|
||||||
|
|
||||||
for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) {
|
|
||||||
nMod4 = nInIdx & 3;
|
|
||||||
nUint24 |= Base64.b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4;
|
|
||||||
if (nMod4 === 3 || nInLen - nInIdx === 1) {
|
|
||||||
for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {
|
|
||||||
aBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;
|
|
||||||
}
|
|
||||||
nUint24 = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return aBytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LN.$add("LN.Base64",Base64);
|
|
||||||
})();
|
|
||||||
|
|
||||||
(function(){
|
|
||||||
class LNPromise
|
|
||||||
{
|
|
||||||
constructor(executor, label){
|
|
||||||
this.promise = new Promise(
|
|
||||||
(resolve,reject) => {
|
|
||||||
this.resolve = (v) => {
|
|
||||||
this._s.state = "ready";
|
|
||||||
resolve(v);
|
|
||||||
this.release();
|
|
||||||
},
|
|
||||||
this.reject = (e) => {
|
|
||||||
this._s.state = "failed";
|
|
||||||
reject(e);
|
|
||||||
this.release();
|
|
||||||
}
|
|
||||||
executor && executor(
|
|
||||||
this.resolve,
|
|
||||||
this.reject
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!label)
|
|
||||||
label = "N.D.";
|
|
||||||
|
|
||||||
this._s = {
|
|
||||||
label,
|
|
||||||
state: "waiting"
|
|
||||||
};
|
|
||||||
|
|
||||||
this.idx = LN.$unique();
|
|
||||||
LNPromise.$current[this.idx] = this._s;
|
|
||||||
}
|
|
||||||
|
|
||||||
label(){
|
|
||||||
return this._s.label;
|
|
||||||
}
|
|
||||||
|
|
||||||
state(){
|
|
||||||
return this._s.state;
|
|
||||||
}
|
|
||||||
|
|
||||||
release(){
|
|
||||||
setTimeout(()=>{
|
|
||||||
Vue.delete(LNPromise.$current, this.idx);
|
|
||||||
},1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
then(){
|
|
||||||
return this.promise.then.apply(this.promise, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getCurrentPromises(){ return LNPromise.$current; }
|
|
||||||
}
|
|
||||||
LNPromise.$current = {};
|
|
||||||
|
|
||||||
LN.$add("LN.Promise",LNPromise);
|
|
||||||
})();
|
|
||||||
|
|
||||||
(function(){
|
|
||||||
class LNVueWebSocket
|
|
||||||
{
|
|
||||||
constructor(lnvue,o){
|
|
||||||
this.LNVue = lnvue;
|
|
||||||
this.options = Object.assign({},o);
|
|
||||||
|
|
||||||
if (!this.options.url)
|
|
||||||
this.options.url = this.constructURL();
|
|
||||||
|
|
||||||
this._id = 1;
|
|
||||||
this.defaultTimeout = 30000;
|
|
||||||
this.websocket = null;
|
|
||||||
this.callbacks = {};
|
|
||||||
|
|
||||||
this._state = "initialized";
|
|
||||||
this._retry = null;
|
|
||||||
|
|
||||||
this.closing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructURL(){
|
|
||||||
var pageURI = window.location;
|
|
||||||
|
|
||||||
var scheme = pageURI.scheme == "https" ? "wss:" : "ws:";
|
|
||||||
var host = pageURI.host;
|
|
||||||
|
|
||||||
return scheme + "//" + host + "/socket";
|
|
||||||
}
|
|
||||||
|
|
||||||
open(){
|
|
||||||
if (this._retry){
|
|
||||||
clearTimeout(this._retry);
|
|
||||||
}
|
|
||||||
this.closing = false;
|
|
||||||
|
|
||||||
this.websocket = new WebSocket(this.options.url);
|
|
||||||
this.websocket.onopen = (e) =>{
|
|
||||||
console.log("WebSocket connected");
|
|
||||||
this._state = "ONLINE";
|
|
||||||
|
|
||||||
let WSHello = {
|
|
||||||
ApplicationSessionID: this.LNVue.sessionID(),
|
|
||||||
};
|
|
||||||
console.log("WSHello request",WSHello);
|
|
||||||
|
|
||||||
this.request("WSHello",WSHello)
|
|
||||||
.then((wsh)=>{
|
|
||||||
console.log("WSHello response",wsh);
|
|
||||||
this.LNVue.sessionID(wsh.message.ApplicationSessionID);
|
|
||||||
this.LNVue.identity = new LN.Identity(wsh.message.SessionIdentity);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
this.websocket.onclose = (e)=>{ this._onclose(e); this._state = "OFFLINE"; };
|
|
||||||
this.websocket.onerror = (e)=>{ this._onerror(e); this._state = "ERROR"; };
|
|
||||||
this.websocket.onmessage = (e)=>{ this._onmessage(e); };
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
close(){
|
|
||||||
if (this.websocket){
|
|
||||||
this.closing = true;
|
|
||||||
this.websocket.close(200,"close() called");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
request(msgtype,msg,timeout){
|
|
||||||
let message = {
|
|
||||||
id: this._id++,
|
|
||||||
type: msgtype,
|
|
||||||
message: msg,
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!timeout)
|
|
||||||
timeout = this.defaultTimeout;
|
|
||||||
|
|
||||||
if (timeout != -1){
|
|
||||||
return new Promise((resolve,reject)=>{
|
|
||||||
let to = setTimeout(()=>{
|
|
||||||
delete this.callbacks[message.id];
|
|
||||||
reject("timed out");
|
|
||||||
},timeout);
|
|
||||||
|
|
||||||
this.callbacks[message.id] = (msgtype,msg)=>{
|
|
||||||
clearTimeout(to);
|
|
||||||
delete this.callbacks[message.id];
|
|
||||||
if (msgtype == "error")
|
|
||||||
reject(msg);
|
|
||||||
else
|
|
||||||
resolve({type: msgtype,message: msg});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.websocket.send(
|
|
||||||
JSON.stringify(message)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
new Promise((resolve,reject)=>{
|
|
||||||
this.websocket.send(
|
|
||||||
JSON.stringify(message)
|
|
||||||
);
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
_onclose(evt){
|
|
||||||
this.websocket = null;
|
|
||||||
this.options.onclose && this.options.onclose(evt);
|
|
||||||
if (!this.closing)
|
|
||||||
{
|
|
||||||
this._retry = setTimeout(() => {
|
|
||||||
this._retry = null;
|
|
||||||
console.log("reconnect...")
|
|
||||||
this.open();
|
|
||||||
}, 5000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_onerror(evt){
|
|
||||||
this.options.onerror && this.options.onerror(evt);
|
|
||||||
}
|
|
||||||
_onmessage(evt){
|
|
||||||
try
|
|
||||||
{
|
|
||||||
let j = JSON.parse(evt.data);
|
|
||||||
let cb = this.callbacks[ j.id ];
|
|
||||||
cb && cb(j.type,j.message);
|
|
||||||
} catch(exc){
|
|
||||||
console.log(exc,evt.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LN.$add("LN.Vue.WebSocket",LNVueWebSocket);
|
|
||||||
})();
|
|
||||||
|
|
||||||
(function (){
|
|
||||||
class LNVue
|
|
||||||
{
|
|
||||||
constructor(el,options = {}){
|
|
||||||
this.options = Object.assign({
|
|
||||||
routes: [],
|
|
||||||
data: {},
|
|
||||||
}, options );
|
|
||||||
|
|
||||||
this._el = el;
|
|
||||||
this.data = Object.assign({}, options.data, { LNVue: this, msg: "Hello World" });
|
|
||||||
this.promises = [];
|
|
||||||
|
|
||||||
this.statusText = "LNVue preparing";
|
|
||||||
|
|
||||||
Vue.prototype.$LNVue = this;
|
|
||||||
LNVue.$_ = this;
|
|
||||||
|
|
||||||
this.navigation = {};
|
|
||||||
this.identity = new LN.Identity();
|
|
||||||
|
|
||||||
Promise
|
|
||||||
.all(LNVue.promises)
|
|
||||||
.then(()=>{
|
|
||||||
this.status("LNVue: starting");
|
|
||||||
|
|
||||||
LNVue.vueRouter.addRoutes([{
|
|
||||||
path: "*",
|
|
||||||
component: {
|
|
||||||
template: `<h2>404 Not Found</h2>The URL you tried to reach is not existing.`,
|
|
||||||
},
|
|
||||||
}]);
|
|
||||||
},
|
|
||||||
(cause)=>{
|
|
||||||
this.status("LNVue: start failed: " + cause);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.vue = null;
|
|
||||||
|
|
||||||
LNVue.$instance.resolve(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Start(){
|
|
||||||
Promise
|
|
||||||
.all(this.promises)
|
|
||||||
.then(()=>{
|
|
||||||
LN.$idle(()=>{
|
|
||||||
this.vue = new Vue({
|
|
||||||
el: this._el,
|
|
||||||
data: this.data,
|
|
||||||
router: LNVue.vueRouter,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
LN.$idle(()=>{
|
|
||||||
this.socket = new LN.Vue.WebSocket(this);
|
|
||||||
this.socket.open();
|
|
||||||
});
|
|
||||||
LN.$idle(()=>{
|
|
||||||
LNVue.$start.resolve(this);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
storage(){
|
|
||||||
return window.localStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
sessionID(){
|
|
||||||
if (arguments.length == 1){
|
|
||||||
this.storage().setItem("LNVueSessionID",arguments[0]);
|
|
||||||
console.log("LNVue.SID <= " + arguments[0]);
|
|
||||||
return this;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
let sid = this.storage().getItem("LNVueSessionID");
|
|
||||||
console.log("LNVue.SID == " + sid);
|
|
||||||
if (!sid)
|
|
||||||
{
|
|
||||||
sid = "00000000-0000-0000-0000-000000000000";
|
|
||||||
}
|
|
||||||
return sid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Version(){ return "0.2alpha"; };
|
|
||||||
getCurrentPromises() {
|
|
||||||
return LN.Promise.getCurrentPromises();
|
|
||||||
}
|
|
||||||
|
|
||||||
status(){
|
|
||||||
if (arguments.length == 1){
|
|
||||||
this.statusText = arguments[0];
|
|
||||||
return this;
|
|
||||||
} else if (arguments.length == 0){
|
|
||||||
return this.statusText;
|
|
||||||
} else
|
|
||||||
throw "LNVue.status(): too many arguments";
|
|
||||||
}
|
|
||||||
|
|
||||||
addModule(modSpec){
|
|
||||||
if (modSpec.navigation instanceof Object){
|
|
||||||
LNVue.deepAssign(modSpec.navigation,this.navigation);
|
|
||||||
}
|
|
||||||
|
|
||||||
LN.$each(modSpec.routes,(key,route)=>{
|
|
||||||
if ((route instanceof Object) && route.url)
|
|
||||||
{
|
|
||||||
let p = new LN.Promise((resolve,reject)=>{
|
|
||||||
LN.$fetch(route.url)
|
|
||||||
.then((src)=>{
|
|
||||||
this.addRoute(key,{ template: src, data: ()=>{ return this.data; }, });
|
|
||||||
resolve();
|
|
||||||
},
|
|
||||||
(cause)=>{
|
|
||||||
console.log("loading route.url failed: ",cause);
|
|
||||||
});
|
|
||||||
},`addModule(${route.url})`);
|
|
||||||
this.promises.push(p);
|
|
||||||
} else if (route instanceof Object){
|
|
||||||
this.addRoute(key,{ template: route.template, data: ()=>{ return this.data; }, } );
|
|
||||||
} else {
|
|
||||||
this.addRoute(key,{ template: route, data: ()=>{ return this.data; }, } );
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
addRoute(path,component){
|
|
||||||
LNVue.vueRouter.addRoutes([
|
|
||||||
{ path, component, },
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (this.vue){
|
|
||||||
let route = this.vue.$route;
|
|
||||||
LNVue.vueRouter.replace("/");
|
|
||||||
LNVue.vueRouter.replace(route);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Authentication API */
|
|
||||||
|
|
||||||
requestChallenges(identityName,secureAttributeTypeName){
|
|
||||||
return new Promise((resolve,reject)=>{
|
|
||||||
this.socket.request("AuthenticationRequest",{
|
|
||||||
IdentityName: identityName,
|
|
||||||
SecureAttributeTypeName: secureAttributeTypeName,
|
|
||||||
})
|
|
||||||
.then((challenges)=>{
|
|
||||||
resolve(challenges);
|
|
||||||
},
|
|
||||||
(error)=>{
|
|
||||||
console.log("Login challenges could not be retrieved", error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
authenticate(identityName,secureAttributeID,challenge,prove){
|
|
||||||
let authenticationProve = {
|
|
||||||
IdentityName: identityName,
|
|
||||||
SecureAttributeUniqueID: secureAttributeID,
|
|
||||||
Challenge: challenge,
|
|
||||||
Prove: prove,
|
|
||||||
};
|
|
||||||
this.socket.request("AuthenticationProve", authenticationProve)
|
|
||||||
.then((identity)=>{
|
|
||||||
this.identity = new LN.Identity(identity.message);
|
|
||||||
},
|
|
||||||
(error)=>{
|
|
||||||
this.identity = new LN.Identity();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
rpc(moduleName,methodName,parameters){
|
|
||||||
return new Promise((resolve,reject)=>{
|
|
||||||
let rpcCall = {
|
|
||||||
module: moduleName,
|
|
||||||
method: methodName,
|
|
||||||
parameters: parameters
|
|
||||||
};
|
|
||||||
this.socket.request("RPCCall",rpcCall)
|
|
||||||
.then(
|
|
||||||
(result)=>{
|
|
||||||
if (result.message.error)
|
|
||||||
{
|
|
||||||
console.log("rpc call failed", result.message.error);
|
|
||||||
reject(result.message.error);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
resolve(result.message.Result);
|
|
||||||
},
|
|
||||||
(error)=>{
|
|
||||||
console.log("rpc failed", error);
|
|
||||||
reject(error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static $LNVue(){
|
|
||||||
return LNVue.$_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LNVue.$instance = new LN.Promise(()=>{},'LN.Vue Instance Promise');
|
|
||||||
LNVue.$start = new LN.Promise(()=>{},'LN Vue Startup Promise');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LNVue.vueRouter = new VueRouter({
|
|
||||||
mode: 'history',
|
|
||||||
routes: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
LNVue.deepAssign = function(source,target){
|
|
||||||
LN.$each(source,function(key){
|
|
||||||
if (target[key] instanceof Object){
|
|
||||||
LNVue.deepAssign(src[key],target[key]);
|
|
||||||
} else {
|
|
||||||
target[key] = source[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
LNVue.$ = function(src){
|
|
||||||
let el = document.createElement("parse");
|
|
||||||
el.innerHTML = src;
|
|
||||||
return el.firstChild;
|
|
||||||
}
|
|
||||||
|
|
||||||
LNVue.routes = [];
|
|
||||||
LNVue.promises = [];
|
|
||||||
|
|
||||||
LNVue.encodeHex = (bytes) => bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '');
|
|
||||||
LNVue.decodeHex = (hexString) => new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
|
|
||||||
|
|
||||||
ArrayBuffer.combine = function(...args){
|
|
||||||
let byteLength = 0;
|
|
||||||
args.forEach((arg,index)=>{
|
|
||||||
byteLength = byteLength + arg.byteLength;
|
|
||||||
});
|
|
||||||
|
|
||||||
let result = new Uint8Array(byteLength);
|
|
||||||
let p = 0;
|
|
||||||
args.forEach((arg,index)=>{
|
|
||||||
for (let n=0;n<arg.byteLength;n++)
|
|
||||||
{
|
|
||||||
result[p++] = arg[n];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
console.log("combine",new Uint8Array(result));
|
|
||||||
return result.buffer
|
|
||||||
};
|
|
||||||
|
|
||||||
LN.$add("LN.Vue",LNVue);
|
|
||||||
LN.$add("LNVue",LNVue);
|
|
||||||
})();
|
|
|
@ -1,45 +0,0 @@
|
||||||
(function(){
|
|
||||||
|
|
||||||
LNVue.prototype.createCredentials = function(_challenge,rp,userId,crossplatform,attestation){
|
|
||||||
crossplatform = crossplatform ? true : false;
|
|
||||||
if (!attestation)
|
|
||||||
attestation = "none";
|
|
||||||
|
|
||||||
let credCreateOptions = {
|
|
||||||
challenge: Uint8Array.from(_challenge, c => c.charCodeAt(0)),
|
|
||||||
rp: {
|
|
||||||
id: rp,
|
|
||||||
name: 'LN.Vue Demo Application',
|
|
||||||
},
|
|
||||||
user: {
|
|
||||||
id: Int8Array.from(userId, c => c.charCodeAt(0)),
|
|
||||||
name: 'SomeUser',
|
|
||||||
displayName: "Some user for now...",
|
|
||||||
},
|
|
||||||
pubKeyCredParams: [
|
|
||||||
{
|
|
||||||
type: 'public-key',
|
|
||||||
alg: -7,
|
|
||||||
}
|
|
||||||
],
|
|
||||||
authenticatorSelection: {
|
|
||||||
authenticatorAttachment: crossplatform ? 'cross-platform' : 'platform',
|
|
||||||
},
|
|
||||||
timeout: 60000,
|
|
||||||
attestation: attestation,
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log(credCreateOptions);
|
|
||||||
navigator.credentials.create({
|
|
||||||
publicKey: credCreateOptions
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
LNVue.prototype.createAuthToken = function(){
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
})();
|
|
Loading…
Reference in New Issue