modif towns

This commit is contained in:
2023-04-29 06:32:56 +00:00
parent 53589f7d19
commit b5cd6c8395
143 changed files with 12057 additions and 25 deletions

View File

@@ -0,0 +1,157 @@
/*eslint no-undef:0*/
/*eslint-env browser*/
"use strict";
var app = app || {};
app.createIdentity=(alias,passphrase="")=>{
if (alias.length<3 || apx.data.object['index_pagans_alias_all'].includes(alias) ){
alert('Please chose another alias')
return;
}
const keys = apx.generateKey(alias,passphrase)
for(let tag of ['inputalias','inputpassphrase']){
document.getElementById(tag).classList.add('disabled')
}
document.getElementById('privatekey').setAttribute("key",keys.privateKey);
document.getElementById('publickey').setAttribute("key",keys.publicKey);
document.getElementById('generatekeys').classList.add('d-none');
document.getElementById('downloadkeys').classList.remove('d-none');
document.getElementById('createId').classList.remove('d-none');
}
app.registerIdentity=()=>{
const data={
alias:document.getElementById('inputalias').value,
privateKey:document.getElementById('privatekey').getAttribute('key'),
publicKey:document.getElementById('publickey').getAttribute('key'),
passphrase:document.getElementById('inputpassphrase').value
}
axios.post('api/pagans',data,apx.data.headers)
.then(rep=>{
// genere authentification headers.xalias, xhash store object.pagans_alias={privateKey, passphrase}; console.log(rep)})
// if check trust add data email recovery axios.post('api/persons,data, apx.data.headers)
})
.catch(err=>{
console.log('sorry',err);
})
}
app.search = (elt) => {
//@todo get search string from input then return tpldata.listofarticles={"search":[]}
console.log("A FAIRE");
};
app.downloadlink = (keys, object, prefix) => {
/**
*
* @param {string} split(.) to naviagte in object until a subobject
* @param {object} a json object
*
* Create a link that download subobject as a textfile
* example:
* const obj={pagans:{privateKey:"123", publicKey:"AZE"}}
* const prefix = "appname"
* const keys="pagans.privateKey"
*
* in <html>
* <button class="btn btn-outline-primary" onclick="app.downloadlink('pagans.privateKey',obj,prefix);" >Download PrivateKey</button>
*
*
*/
const dwn = (fn, t) => {
var element = document.createElement("a");
element.setAttribute(
"href",
"data:text/plain;charset=utf-8," + encodeURIComponent(t)
);
element.setAttribute("download", fn);
element.style.display = "none";
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
};
const subobj = keys.split(".").reduce((val, k) => (val = val[k]), object);
const txt = typeof subobj == "string" ? subobj : JSON.stringify(subobj);
dwn(`${prefix}_${keys.split(".").pop()}.txt`, txt);
};
app.setupdata = () => {
//todo generate tpldata.listofarticle get html from /static/html
apx.data.tpldata.listofarticle = {
mostread: [{}],
news: [{}],
search: [],
articles: "html",
};
const list = {}
document.querySelectorAll("[add2data]").forEach((e) => {
/** Collect from any tag with add2data url attribute (tpl tpldata object)
* name is the filename :
* for tpl and tpldata (relativepath/filename_xx.ext) name=filename
* For public object (pagans, towns, nations, block) not tribes object are gettable (only)
* with /nationchains/objectName/idx/existingindex.json
* or for an item /itm//primarykey_value_of_item.json
*
* For tribe object get or for modification you need to use api and to have accessright setup properly:
* for object index (/api/odmdb/objectname/idx/filename.json) name =objectname_filename
* for object item (/api/odmdb/objectname/itm/primarykey.json) name =objectname_primarykey
*/
if (e.getAttribute('object')){
const url = e.getAttribute('object')
const spliturlobj=url.split("/").slice(-3);
const objectname=spliturlobj[0];
const objecttype=spliturlobj[1];
const objectkey=spliturlobj[2].substring(0,spliturlobj[2].length-5)
if (!list[objectname]) list[objectname]={};
list[objectname][`${objecttype}${objectkey}`]= url;
};
for (let k of ["tpl", "tpldata"]) {
if (e.getAttribute(k)){
const url=e.getAttribute(k);
let localname=url.split('/').slice(-1)[0];
if (url.includes('.mustache')) localname=localname.substring(0,localname.length-12);
if (url.includes('.html') || url.includes('.html') ) localname=localname.substring(0,localname.length-6);
if (!list[k]) list[k]={};
list[k][localname]=url;
}
}
});
// load external template and data
for (let k of Object.keys(list) ) {
console.log(k, list[k]);
apx.loadfile(list[k], k);
}
//alert(apx.data.firsttimeload)
if (apx.data.firsttimeload) {
// Need to wait the first time apx.data fully load
setTimeout(() => {
app.setuppage();
}, 300);
delete apx.data.firsttimeload;
apx.save();
}else{
app.setuppage();
}
};
app.load = (idtoload, tplname, tpldata) => {
const tpl = apx.data.tpl[tplname]
? apx.data.tpl[tplname]
: `missing template ${tplname}`;
const data = typeof tpldata == "string" ? apx.data.tpldata[tpldata] : tpldata;
document.getElementById(idtoload).innerHTML = Mustache.render(tpl, data);
};
app.setuppage = () => {
// load partial template
document.querySelectorAll("[apptoload]").forEach((e) => {
console.log(e.getAttribute("apptoload"));
eval(e.getAttribute("apptoload"));
});
};
apx.ready(app.setupdata);

View File

@@ -0,0 +1,211 @@
/*eslint no-undef:0*/
/*eslint-env browser*/
"use strict";
var apx = apx || {};
/**
* Js lib to interact with apxtrib backend
*
* html page must have apxlocal with at least headers key
* <script>
const apxlocal={
headers:{xalias:"",xhash:"",xtribe:"smatchit", xapp:"smatchapp", xlang:"en" },
firstimeload:true,
forceload:true,
tpl:{
footer:"{{{msg}}}"
},
tpldata:{
footer:{msg:"<p>Made with love for people freedom, enjoy!</p>"}
},
objects:{}
};
* apx.generateKey(params) create a public/private key compatible with apXtrib backend and store it in apx.data
* apx.detachedSignature(params) generate a detachedSignature for a Message that backend can check with the publicKey of the alias
* apx.checkdetachedSignature(params) check a detachedSignature for a Message (used on the backend as well)
* apx.ready(callback) equivalent of jquery Document.ready()
* apx.save() save apx.data as xapp value in localStorage
* apx.update() get localStorage up to date
* apx.loadfile({url:name},dest,axiosoptions) async that wait to load a list of relativ url and store it in a apx.data[dest]
*/
apx.generateKey = async (alias, passphrase) => {
/**
* @param {string} alias a unique alias that identify an identity
* @param {string} passphrase a string to cipher the publicKey (can be empty, less secure but simpler)
* @return {publicKey,privateKey} with userIds = [{alias}]
*/
const { privateKey, publicKey } = await openpgp.generateKey({
type: "ecc", // Type of the key, defaults to ECC
curve: "curve25519", // ECC curve name, defaults to curve25519
userIDs: [{ alias: alias }], // you can pass multiple user IDs
passphrase: passphrase, // protects the private key
format: "armored", // output key format, defaults to 'armored' (other options: 'binary' or 'object')
});
// key start by '-----BEGIN PGP PRIVATE KEY BLOCK ... '
// get liste of alias:pubklickey await axios.get('api/v0/pagans')
// check alias does not exist
return { alias, privateKey, publicKey };
/* document.getElementById('privatekey').innerHTML=privateKey;
document.getElementById('publickey').innerHTML=publicKey;
apx.data.pagans={}
apx.data.pagans.privateKey=privateKey;
apx.data.pagans.publicKey=publicKey;
apx.save();
console.log(apx.data)
*/
};
apx.detachedSignature = async (pubK, privK, passphrase, message) => {
/**
* @pubK {string} a text public key
* @privK {string} a test priv key
* @passphrase {string} used to read privK
* @message {string} message to sign
* @Return a detached Signature of the message
*/
const publicKey = await openpgp.readKey({ armoredKey: pubK });
const privateKey = await openpgp.decryptKey({
privateKey: await openpgp.readPrivateKey({ armoredKey: privK }),
passphrase,
});
const msg = await openpgp.createMessage({ text: message });
return await openpgp.sign({ msg, signinKeys: privK, detached: true });
};
apx.checkdetachedSignature = async (
alias,
pubK,
detachedSignature,
message
) => {
/**
* @alias {string} alias link to the publicKey
* @pubK {string} publiKey text format
* @detachedSignature {string} a detachedsignatured get from apx.detachedSignature
* @message {string} the message signed
* @return {boolean} true the message was signed by alias
* false the message was not signed by alias
*/
const publicKey = await openpgp.readKey({ armoredKey: pubK });
const msg = await openpgp.createMessage({ text: message });
const signature = await openpgp.readSignature({
armoredSignature: detachedSignature, // parse detached signature
});
const verificationResult = await openpgp.verify({
msg, // Message object
signature,
verificationKeys: publicKey,
});
const { verified, keyID } = verificationResult.signatures[0];
try {
await verified; // throws on invalid signature
console.log("Signed by key id " + keyID.toHex());
return KeyId.toHex().alias == alias;
} catch (e) {
console.log("Signature could not be verified: " + e.message);
return false;
}
};
apx.ready = (callback) => {
/**
* Wait loading DOM, when ready run callback function
*/
if (!callback) {
alert(
"You have an unknown callback pwa.state.ready(callback), you need to order your code callback = ()=>{} then pwa.state.ready(callback), boring but js rules ;-)"
);
}
if (document.readyState != "loading") callback();
// modern browsers
else if (document.addEventListener)
document.addEventListener("DOMContentLoaded", callback);
// IE <= 8
else
document.attachEvent("onreadystatechange", function () {
if (document.readyState == "complete") callback();
});
};
apx.loadfile = async (list, dest, axiosoptions) => {
/**
* Load external file as tpl, tpldata (temmplate and data), objects index of object
* @param {object} list {name:url} it will run as promise all the requested url
* @param {string} dest where to store it in apx.data (tpl, tpldata, objectname,...)
* @param {object} axiosoptions alow to add headers any option to axios
* @return {object} load into apx.data[dest]={name:{object}} and localStorage.xapp[dest]={name:{object}}
*
* @example <caption>Load into apx.data.tpl.blocncol ="string"</caption>
* apx.loadfile({blocncol:"static/tpl/blocncol.mustache"},"tpl",{headers:apx.data.header})
*
*/
const invertlist = {};
Object.keys(list).forEach((n) => {
invertlist[list[n]] = n;
});
//console.log( 'invertlist', invertlist )
if (
apx.data.forcereload ||
!apx.data[dest] ||
Object.keys(apx.data[dest]).length == 0
) {
if (!apx.data[dest]) apx.data[dest] = {};
const fetchURL = (r, options) => {
return axios.get(r, options);
};
const urls = Object.keys(invertlist);
if (!axiosoptions) {
axiosoptions = { headers: apx.data.headers };
}
console.log('axiosiptions',axiosoptions)
const promiseArray = urls.map((r) => fetchURL(r, axiosoptions));
await Promise.all(promiseArray)
.then((data) => {
console.log(data)
for (let pos = 0; pos < urls.length; pos++) {
//console.log( 'url', urls[ pos ] )
//console.log( data[ pos ] );
apx.data[dest][invertlist[urls[pos]]] = data[pos].data;
console.log(
`store apx.data[ ${dest} ][ invertlist[ ${urls[pos]} ] ]`
);
apx.save();
}
})
.catch((err) => {
console.log("erreur de loading", err);
});
}
};
apx.save = () => {
localStorage.setItem(apx.data.headers.xapp, JSON.stringify(apx.data));
};
apx.update = async () => {
if (!apxlocal) {
console.log(
'Please add to the html page header, this line <script> const apxlocal={headers:{xalias:"",xhash:"",xtribe:"smatchit", xapp:"smatchapp", xlang:"en" }};</script> '
);
return;
}
if (document.querySelector("html").getAttribute("lang")) {
apxlocal.headers.xlang = document
.querySelector("html")
.getAttribute("lang");
}
if (localStorage.getItem(apxlocal.headers.xapp)) {
apx.data = JSON.parse(localStorage.getItem(apxlocal.headers.xapp));
if (apx.data.headers.xtribe != apxlocal.headers.xtribe) {
// if an app change of tribe
localStorage.removeItem(apxlocal.headers.xapp);
delete apx.data;
}
}
if (!apx.data) {
apx.data = apxlocal;
}
console.log("apx.data", apx.data);
apx.save();
};
apx.ready(apx.update);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,39 @@
<div class="row">
<div class="col-sm-3">
<h3>webapp creation</h3>
<p>Step by step </p>
<div class="input-group mb-3">
<input class="form-control me-1" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-primary" onclick="app.search(this)">
<i class="fa-solid fa-magnifying-glass"></i>
</button>
</div>
<h4 class="mt-4">Articles</h4>
<p>Most read</p>
<ul class="nav nav-pills flex-column">
{{#mostread}}
<li class="nav-item">
<a class="nav-link" onclick="app.load('apxmain','{{tplname}}','{{tpldata}}')">{{{title}}}</a>
</li>
{{/mostread}}
</ul>
<hr class="d-sm-none">
<p>News</p>
<ul class="nav nav-pills flex-column">
{{#news}}
<li class="nav-item">
<a class="nav-link" onclick="app.load('apxmain','{{tplname}}','{{tpldata}}')">{{{title}}}</a>
</li>
{{/news}}
</ul>
<hr class="d-sm-none">
</div>
<div class="col-sm-9">
{{#articles}}
<h2>{{{heading}}</h2>
<h5>{{{shortdescdate}}}</h5>
<div class="fakeimg">Fake Image</div>
{{{htmlcontent}}}
{{/articles}}
</div>
</div>

View File

@@ -0,0 +1,23 @@
<div class="container">
<h5>How to identify ourself</h5>
<p>You need to know your alias and to have your privateKey file</p>
<div class="mb-3">
<label for="youralias" class="form-label">Your alias</label>
<input type="email" class="form-control" id="youralias" aria-describedby="aliasHelp">
<div id="aliasHelp" class="form-text">Your unique alias when you create your account</div>
</div>
<div class="mb-3">
<label for="inputprivateKey" class="form-label">Copy & paste or load your private Key</label>
<textarea type="password" class="form-control" id="inputprivateKey" rows="6"></textarea>
<div id="inputprivateKey" class="form-text">I forgot my keys, <a onclick="">click to request it with my email recovery</a> or <a onclick="">Click to receive it from my alias</a> </div>
</div>
<div class="mb-3">
<label for="emailrecovery" class="form-label">Your email recovery</label>
<input type="email" class="form-control" id="emailrecovery" placeholder="name@example.com">
</div>
<div class="input-group">
<input type="file" class="form-control" id="inputGroupFile04" aria-describedby="inputGroupFileAddon04" aria-label="Upload">
<button class="btn btn-outline-secondary" type="button" id="inputGroupFileAddon04">Button</button>
</div>
<button type="submit" class="btn btn-primary d-none">Identify you</button>
</div>

View File

@@ -0,0 +1,54 @@
<div class="row">
<div class="col-sm-6" data-spacename="explain">
<h2>How it works</h2>
<p> Alias is a unique string that humainly help to match a PublicKey to check existing alias</p>
<code>
GET /api/odmdb/idx/pagans/pagans_alias_all.json with a correct headers
RESULT
data:{alias:publicKey}
</code>
<p>
Run
</p>
</div>
<div class="col-sm-6" data-spacename="userinterface">
<div class="row g-3">
<div class="col-md-6">
<label for="inputalias" class="form-label">Your alias</label>
<input type="text" class="form-control" id="inputalias" placeholder="A public alias that any one see">
</div>
<div class="col-md-6">
<label for="inputemailrecovery" class="form-label">Email Recovery</label>
<input type="email" class="form-control" id="inputemailrecovery" placeholder="optional, if you want to receive by mail your keys">
</div>
<div class="col-12">
<label for="inputpassphrase" class="form-label">A passphrase</label>
<input type="text" class="form-control" id="inputpassphrase" placeholder="optional, a passphrase to remember, each time something try to use your privateKey this passphrase will be requested">
</div>
<div class="col-12">
<button type="button" id="generatekeys" onclick="app.createIdentity(document.getElementById('inputalias').value,document.getElementById('inputpassphrase').value)" class="btn btn-primary">Generate keys</button>
</div>
<div class="col-12">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="gridCheck">
<label class="form-check-label small" for="gridCheck">
<b>I trust smatchit to keep my private key and email </b><br>
<b>If i don't trust</b> please download your keys (be aware, none than you can have access to your cipher data).<br>
If you set a correct email then you will receive your keys on your mailbox (Carefull by sending email, smatchit and anyone that access to your email can see your keys).<br>
The safer to be sure no one else than your local browser can see it, just download localy and save it on a personnal cold support (usb key).<br>
If you use a browser that <b>can be accessible by someone else, don't forget to "logout"</b> to clean up any trace.<br>
If you have any suspicious please
</label>
</div>
</div>
<div id="downloadkeys" class="btn-group d-none">
<p>Download your keys at least PrivateKey this have to save in a secret place</p>
<button id="privatekey" key="" class="btn btn-outline-primary" onclick="app.downloadlink('pagans.privateKey',apx.data,apx.data.headers.xapp);" >Download PrivateKey</button>
<button id="publickey" key="" class="btn btn-outline-primary" onclick="app.downloadlink('publicKey',this.getAttribute('key'),apx.data.headers.xapp);">Download PublicKey</button>
</div>
<div id="createId" class="col-12 d-none">
<button class="btn btn-primary" onclick="app.registerIdentity()">Create this identity</button>
</div>
</div>
</div>

View File

@@ -0,0 +1 @@
{}