1st commit

This commit is contained in:
2025-07-01 11:09:51 +02:00
commit 2d3e33d643
787 changed files with 185055 additions and 0 deletions

698
wco/apxauth/apxauth.js Normal file
View File

@@ -0,0 +1,698 @@
var apx = apx || {};
apx.apxauth = {};
apx.apxauth.loadwco = async (id, ctx) => {
// check if not authenticate, do nothing cause by default screensignin and wait authentification
// if authenticate, if url xhash then redirect if no url then change wco-link=screenmytribes
// if (dayjs(apx.data.headers.xdays).diff(dayjs(), "hours") >= 24) apx.apxauth.checkisauth();
//load main.mustache of the component
//when wco-xxx change it run this function
console.log(`Load wconame:apxauth apx.apxauth.loadwco with id:${id} and ctx: ${JSON.stringify(ctx)}`);
const tpldataname = `${apx.data.pagename}_${id}_apxauth`;
const apxauthid = document.getElementById(id)
const data = apx.apxauth.getdata(id, ctx);
if (apxauthid.innerHTML.trim() === "") {
apxauthid.innerHTML = Mustache.render(
apx.data.tpl.apxauthmain,
data
);
}
apxauthid.querySelector(`.screenaction`).innerHTML = Mustache.render(
apx.data.tpl[`apxauthscreen${ctx.link}`],
data
);
apxauthid.querySelector(`.msginfo`).innerHTML = "";
};
apx.apxauth.getdata = (id, ctx) => {
const tpldataname = `${apx.data.pagename}_${id}_apxauth`;
const data = JSON.parse(JSON.stringify(apx.data.tpldata[tpldataname]));
data.id = id;
data.xalias = apx.data.headers.xalias;
data.xtribe = apx.data.headers.xtribe;
data.emailssuport = apx.data.appdata.emailsupport;
switch (ctx.link) {
case "logout":
if (!data.profils) data.profils = [];
apx.data.headers.xprofils.forEach((p) => {
if (!["anonymous", "pagans", "persons"].includes(p)) {
data.profils.push(apx.data.options.profil.itms[p].title);
}
});
data.noprofils = data.profils.length == 0;
data.member = apx.data.headers.xprofils.includes("persons");
data.websites = apx.data.appdata.websites;
// get tribes activities
/*["", "https://wall-ants.ndda.fr"];
axios
.get(`/api/apxtri/tribes/activities`, {
headers: apx.data.headers,
})
.then((rep) => {})
.catch((err) => {});
*/
break;
default:
break;
}
console.log("data for tpl:", data);
return data
};
apx.apxauth.redirecturlwithauth = (url, tribe, webapp, newwindow, windowname = '_blank') => {
url = url.replace(/_[a-zA-Z0-9]{2}\.html/, `_${apx.data.headers.xlang}.html`)
url += `?xtribe=${tribe}&xapp=${webapp}&xalias=${apx.data.headers.xalias}`
url += `&xdays=${apx.data.headers.xdays}&xhash=${apx.data.headers.xhash}`
url += `&xprofils=${apx.data.headers.xprofils.join(',')}`
url += `&xtrkversion=${apx.data.headers.xtrkversion}&xuuid=${apx.data.headers.xuuid}`
if (newwindow) {
try {
const newwin = window.open(url, windowname)
if (newwin === null || typeof newwin === 'undefined') {
console.warn("L'ouverture de la fenêtre a été bloquée par un bloqueur de pop-up.");
// Vous pouvez informer l'utilisateur ici qu'il doit désactiver son bloqueur de pop-up
alert("Votre navigateur a bloqué l'ouverture d'un nouvel onglet. Veuillez autoriser les pop-ups pour ce site.");
} else {
// Optionnel: Mettre le focus sur la nouvelle fenêtre/onglet
newwin.focus();
}
return newwin;
} catch (error) {
console.error("Une erreur est survenue lors de l'ouverture de l'onglet :", error);
return null;
}
}
}
/**
* logout
* Clean any private key into memory of this app and in the backend
*/
apx.apxauth.logout = () => {
axios
.get(`/api/apxtri/pagans/logout`, {
headers: apx.data.headers,
})
.then((rep) => {
console.log("logout", rep);
})
.catch((err) => {
console.log("Erreur logout check:", err);
});
apx.data = apxtri;
apx.save();
if (apx.pagecontext.hash.url) {
window.location.href = apx.pagecontext.hash.url;
} else {
location.reload();
}
};
apx.apxauth.setheadersauth = async (
alias,
passphrase,
publickey,
privatekey,
rememberme
) => {
/**
* Set header with relevant authentification data
* @return {status=200 if apx.data.headers and apx.data.auth properly set}
* {status: 406 or 500 in case issue}
*/
//console.log(alias, passphrase, publickey, privatekey);
if (
alias.length < 3 ||
publickey.length < 200 ||
(privatekey && privatekey.lengtht < 200)
) {
return {
status: 406,
ref: "Pagans",
msg: "aliasorprivkeytooshort",
data: {},
};
}
if (!passphrase) passphrase = "";
if (rememberme) {
apx.data.auth = {
alias: alias,
publickey: publickey,
privatekey: privatekey,
passphrase: passphrase,
};
} else if (apx.data.auth) {
delete apx.data.auth;
apx.save();
}
apx.data.headers.xalias = alias;
apx.data.headers.xdays = dayjs().valueOf();
const msg = `${alias}_${apx.data.headers.xdays}`;
//console.log("pvk", privatekey);
try {
apx.data.headers.xhash = await apx.apxauth.clearmsgSignature(
publickey,
privatekey,
passphrase,
msg
);
} catch (err) {
return {
status: 500,
ref: "Middlewares",
msg: "unconsistentpgp",
data: { err: err },
};
}
apx.save();
console.log("xhash set with:", apx.data.headers.xhash);
return { status: 200 };
};
apx.apxauth.authentifyme = async (
id,
alias,
passphrase,
privatekey,
rememberme
) => {
/**
* Set apx.data.auth with pub, priv, passphrase alias that allow authentification
* set headers with xdays (timestamp) and xhash of message: {alias}_{timestamp} generate with pub & priv key
*
* @Param {key} publickeycreate optional when alias does not exist
*/
//console.log(alias, passphrase);
//console.log(privatekey);
//clean previous answer if exist
const idparent=document.getElementById(id).parentElement?.closest('[wco-name]').getAttribute('id')
document.querySelector(`#${id} .msginfo`).innerHTML = "";
if (alias.length < 3 || privatekey.length < 200) {
apx.notification(`#${id} .msginfo`, {
status: 500,
ref: "Pagans",
msg: "aliasorprivkeytooshort",
data: {},
});
return false;
}
console.log(`get /api/apxtri/pagans/alias/${alias}`);
axios
.get(`/api/apxtri/pagans/alias/${alias}`, {
headers: apx.data.headers,
})
.then(async (rep) => {
//console.log(rep.data);
const setheaders = await apx.apxauth.setheadersauth(
alias,
passphrase,
rep.data.data.publickey,
privatekey,
rememberme
);
if (setheaders.status != 200) {
apx.notification(`#${id} .msginfo`, setheaders);
} else {
console.log("SetheadersOK");
console.log(`/api/apxtri/pagans/isauth`);
axios
.get(`/api/apxtri/pagans/isauth`, {
headers: apx.data.headers,
})
.then((rep) => {
// Authenticate then store profils in header
apx.data.headers.xprofils = rep.data.data.xprofils;
apx.save();
// if this page is call with apxid_fr.html?url=httpsxxx then it redirect to this page.
//alert(`${window.location.href.includes("/src/")?"/src/":""}${apx.pagecontext.hash.url}`)
if (apx.pagecontext.hash.url) {
window.location.href = `${apx.pagecontext.hash.url}`;
} else {
//location.reload();
document.getElementById(idparent).setAttribute('wco-link','mytribes');
}
})
.catch((err) => {
console.log("Not authentify:", err);
delete apx.data.auth;
apx.save();
document.getElementById(idparent).setAttribute("wco-link", "signin")
if (err.response) {
apx.notification(`#${id} .msginfo`, err.response.data);
} else if (err.request) {
apx.notification(`#${id} .msginfo`, {
status: 500,
ref: "Middlewares",
msg: "errrequest",
data: { err: err.request.response },
});
}
});
}
})
.catch((err) => {
//console.log(err.response);
//console.log(err.request);
console.log("checkalias:", err);
if (err.response && err.response.data.msg) {
//remove auth if not well created previously
//console.log(err.response.data.msg);
if (err.response.data.msg == "aliasdoesnotexist") {
delete apx.data.auth;
apx.save();
apx.notification(`#${id} .msginfo`, {
status: 404,
ref: "Pagans",
msg: "aliasdoesnotexist",
data: { alias },
});
//document.getElementById("inputaliasauth").value="";
//document.getElementById("inputpassphraseauth").value="";
//document.getElementById("privatekeyauth").value=""
//window.location.reload();
}
apx.notification(`#${id} .msginfo`, err.response.data);
} else {
apx.notification(`#${id} .msginfo`, {
status: 500,
ref: "Middlewares",
msg: "errrequest",
data: { err },
});
}
});
};
apx.apxauth.recoverykey = (id, aliasoremail) => {
if (aliasoremail.length < 3) {
apx.notification(`#${id} .msginfo`, {
status: 406,
ref: "Pagans",
msg: "recoveryemailnotfound",
data: { tribe: apx.data.headers.xtribe, search: aliasoremail },
});
return false;
}
const recodata = { tribe: apx.data.headers.xtribe, search: aliasoremail };
recodata.emailalias = Checkjson.testformat(aliasoremail, "email")
? "email"
: "alias";
document.querySelector(`#${id} .msginfo`).innerHTML = "";
axios
.post(`/api/apxtri/pagans/keyrecovery`, recodata, {
headers: apx.data.headers,
})
.then((rep) => {
rep.data.data.search = aliasoremail;
apx.notification(`#${id} .msginfo`, rep.data, true);
})
.catch((err) => {
//console.log("error:", err);
const dataerr =
err.response && err.response.data
? err.response.data
: { status: 500, ref: "Pagans", msg: "checkconsole", data: {} };
dataerr.data.search = aliasoremail;
apx.notification(`#${id} .msginfo`, dataerr, true);
});
};
apx.apxauth.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 pgpparam = {
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' (options: 'armored', 'binary' or 'object')
};
const { privateKey, publicKey } = await openpgp.generateKey(pgpparam);
// 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: privateKey, publickey: publicKey };
};
apx.apxauth.verifyKeys = async (
publicKeyArmored,
privateKeyArmored,
passphrase
) => {
try {
// Charger la clé publique
const publicKey = await openpgp.readKey({ armoredKey: publicKeyArmored });
// Charger la clé privée
const privateKey = await openpgp.decryptKey({
privateKey: await openpgp.readPrivateKey({
armoredKey: privateKeyArmored,
}),
passphrase: passphrase, // Passphrase de la clé privée (si nécessaire)
});
// Créer un message simple à signer
const message = await openpgp.createMessage({ text: "Test message" });
// Signer le message avec la clé privée
const signedMessage = await openpgp.sign({
message: message, // Message à signer
signingKeys: privateKey, // Clé privée pour signer
});
// Vérifier la signature avec la clé publique
const verificationResult = await openpgp.verify({
message: await openpgp.readCleartextMessage({
cleartextMessage: signedMessage,
}),
verificationKeys: publicKey, // Clé publique pour vérifier
});
// Vérifier si la signature est valide
const { verified } = verificationResult.signatures[0];
await verified; // Resolve la promesse
console.log("Les clés correspondent et sont valides !");
return true;
} catch (error) {
console.error("Erreur lors de la vérification des clés : ", error);
return false;
}
};
apx.apxauth.testcreatekey = async (alias, passphrase) => {
const pgpparam = {
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' (options: 'armored', 'binary' or 'object')
};
const { privateKey, publicKey } = await openpgp.generateKey(pgpparam);
console.log(verifyKeys(publicKey, privateKey, passphrase));
};
apx.apxauth.detachedSignature = async (privK, passphrase, message) => {
/**
* @privK {string} a test priv key
* @passphrase {string} used to read privK
* @message {string} message to sign
* @Return a detached Signature of the message
*/
let privatekey;
if (passphrase == "" || passphrase == undefined) {
privatekey = await openpgp.readKey({ armoredKey: privK });
} else {
privatekey = await openpgp.decryptKey({
privateKey: await openpgp.readPrivateKey({ armoredKey: privK }),
passphrase,
});
}
//console.log(message);
const msg = await openpgp.createMessage({ text: message });
//console.log(msg);
const sig = await openpgp.sign({
message: msg,
signingKeys: privatekey,
detached: true,
});
return btoa(sig);
};
apx.apxauth.clearmsgSignature = async (pubK, privK, passphrase, message) => {
/**
* @privK {string} a test priv key
* @passphrase {string} used to read privK
* @message {string} message to sign
* @Return an base64 Signature of the message or error
*/
const publickey = await openpgp.readKey({ armoredKey: pubK });
let privatekey;
if (passphrase == "" || passphrase == undefined) {
privatekey = await openpgp.readKey({ armoredKey: privK });
} else {
privatekey = await openpgp.decryptKey({
privateKey: await openpgp.readPrivateKey({ armoredKey: privK }),
passphrase,
});
}
const cleartextMessage = await openpgp.sign({
message: await openpgp.createCleartextMessage({ text: message }),
signingKeys: privatekey,
});
console.log(cleartextMessage);
const verificationResult = await openpgp.verify({
message: await openpgp.readCleartextMessage({ cleartextMessage }),
verificationKeys: publickey,
});
const verified = verificationResult.signatures[0];
const validity = await verified.verified;
if (!validity) throw new Error("invalidsignature");
return btoa(cleartextMessage);
};
apx.apxauth.authenticatedetachedSignature = async (
alias,
pubK,
detachedSignature,
message
) => {
/**
* Check that alias (pubkey) signe a message
* @alias {string} alias link to the publickey
* @pubK {string} publiKey text format
* @detachedSignature {string} a detachedsignatured get from apx.apxauth.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: atob(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.apxauth.createIdentity = async (
id,
alias,
recoemail,
passphrase = ""
) => {
document.querySelector(`#${id} .msginfo`).innerHTML = ""
const aliasregex = /^[a-z0-9]*$/;
//console.log(aliasregex.test(alias));
if (!(alias && alias.length > 3 && aliasregex.test(alias))) {
apx.notification(
`#${id} .msginfo`,
{
status: "406",
ref: "Pagans",
msg: "invalidalias",
data: {},
},
true
);
return false;
}
if (recoemail.length > 0 && !Checkjson.testformat(recoemail, "email")) {
apx.notification(`#${id} .msginfo`, {
status: 406,
ref: "Pagans",
msg: "invalidemail",
data: {},
});
return false;
}
axios
.get(`/api/apxtri/pagans/alias/${alias}`, {
headers: apx.data.headers,
})
.then((rep) => {
console.log(rep);
apx.notification(
`#${id} .msginfo`,
{
ref: "Pagans",
msg: "aliasexist",
data: { alias },
},
true
);
})
.catch(async (err) => {
console.log("checkalias:", err);
if (err.response && err.response.status == 404) {
// alias does not exist create it is possible
const keys = await apx.apxauth.generateKey(alias, passphrase);
apx.data.tmpauth = { keys, recoemail, passphrase };
//console.log(apx.data.tmpauth);
["publickey", "privatekey"].forEach((k) => {
console.log(`${id} button.signup${k}`);
const btn = document.querySelector(
`#${id} button.signup${k}`
);
btn.addEventListener("click", () => {
const blob = new Blob([keys[k]], { type: "text/plain" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = `${alias}_${k}.txt`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
});
});
document
.querySelectorAll(
`#${id} .signupalias, #${id} .signupemailrecovery, #${id} .signuppassphrase`
)
.forEach((e) => e.setAttribute("disabled", "disabled"));
document
.querySelector(`#${id} .getmykeys`)
.classList.remove("hidden");
document
.querySelector(`#${id} .btncreatekey`)
.classList.add("hidden");
} else {
apx.notification(
`#${id} .msginfo`,
{
ref: "Middlewares",
msg: "errrequest",
data: {},
},
true
);
}
});
};
/**
*
* @param {string} alias to create
* @param {string} publickey
* @param {string} trustedtribe if none => means no passphrase, no privatekey, no trustedtribe
* @param {string} passphrase
* @param {string} privatekey
* @param {string} email if none => means no passphrase, no privatekey, no trustedtribe
*
* if email!=none and trustedtribe!= none create a person with parson profil in trustedtribe
* if email!=none and trustedtribe==none then send an email at registration with all element but doi not store in backend for futur recovery
*
*/
apx.apxauth.test = () => {
//"apx.apxauth.registerIdentity(document.getElementById('inputalias').value,document.getElementById('publickey').document.getElementById('inputpassphrase').value)"
console.log(apx.data.tmpauth);
};
apx.apxauth.registerIdentity = async (id, trustedtribe) => {
const authid = document.getElementById(id);
// trustedtribe boolean
//previously store in apx.data.tmpauth={keys:{alias,privatekey,publickey},recoemail,passphrase}
const setheaders = await apx.apxauth.setheadersauth(
apx.data.tmpauth.keys.alias,
apx.data.tmpauth.passphrase,
apx.data.tmpauth.keys.publickey,
apx.data.tmpauth.keys.privatekey,
false
);
if (setheaders.status != 200) {
apx.notification(`#${id} .msginfo`, setheaders);
} else {
// add withpublickeyforcreate to check isAuthenticated alias does not already exist
const data = {};
data.alias = apx.data.tmpauth.keys.alias;
data.publickey = apx.data.tmpauth.keys.publickey;
console.log(apx.data.tmpauth.recoemail, Checkjson.testformat(apx.data.tmpauth.recoemail, "email"))
if (apx.data.tmpauth.recoemail && Checkjson.testformat(apx.data.tmpauth.recoemail, "email")) {
data.passphrase = apx.data.tmpauth.keyspassphrase;
data.privatekey = apx.data.tmpauth.keysprivatekey;
data.email = apx.data.tmpauth.recoemail;
}
data.trustedtribe = trustedtribe;
axios
.post(`/api/apxtri/pagans`, data, { headers: apx.data.headers })
.then((reppagan) => {
//console.log(reppagan.data);
apx.notification(`#${id} .msginfo`, reppagan.data);
authid.querySelector(`.btncreateidentity`)
.classList.add("hidden");
authid.querySelector(`.signupbtnreload`)
.classList.remove("hidden");
//remove tmp cause create phc change to keep tplauth in memory and avoid asking again the pasword
//delete apx.data.tmpauth;
//apx.save();
})
.catch((err) => {
console.log("error:", err);
const dataerr =
err.response && err.response.data
? err.response.data
: { status: 500, ref: "Pagans", msg: "", data: {} };
apx.notification(`#${id} .msginfo`, dataerr);
});
}
};
apx.apxauth.jointribe = (id) => {
/**
* Allow a pagan to register as a person into a tribe
* header must be authenticated with alias into an app belonging to xtribe AND schema person must have apxaccessright with role "pagan": {"C": []}
*/
//console.log(apx.data);
if (!apx.data.headers.xprofils.includes("persons")) {
apx.data.headers.xprofils.push("persons");
}
const data = {
alias: apx.data.headers.xalias,
profils: apx.data.headers.xprofils,
};
axios
.put(`/api/apxtri/pagans/person/${apx.data.headers.xtribe}`, data, {
headers: apx.data.headers,
})
.then((rep) => {
apx.notification(`#${id} .msginfo`, rep.data);
axios
.get(`/api/apxtri/pagans/logout`, {
headers: apx.data.headers,
})
.then((rep) => {
console.log("logout", rep);
apx.apxauth.authentifyme(
id,
apx.data.auth.alias,
apx.data.auth.passphrase,
apx.data.auth.privatekey
);
})
.catch((err) => {
console.log("Erreur logout check:", err);
});
})
.catch((err) => {
console.log("sorry", err);
if (err.response && err.response.data)
apx.notification("#msginfo", err.response.data);
else
apx.notification("#msginfo", {
status: 500,
ref: "Pagans",
msg: "errcreate",
data: {},
});
});
};

View File

@@ -0,0 +1,5 @@
{
"aliasinvalid": "Combinaison de 3 à 150 caractères <br /> composée de minuscules (a à z) et/ou de chiffres (0 à 9)",
"aliastitle": "Uniquement minuscules ou chiffres",
"privatekeyplaceholder": "Votre clé privée"
}

View File

@@ -0,0 +1,7 @@
<!-- screen action-->
<div class="screenaction mt-5 sm:mx-auto sm:w-full sm:max-w-sm">
</div>
<!-- feedback action-->
<div class="my-5">
<p class="msginfo text-center text-info"></p>
</div>

View File

@@ -0,0 +1,44 @@
<div class="mt-1">
<label class="input validator mbt-1">
<svg class="h-[1em] opacity-50" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<g
stroke-linejoin="round"
stroke-linecap="round"
stroke-width="1"
fill="black"
stroke="black"
>
<path d="M11.89 4.111a5.5 5.5 0 1 0 0 7.778.75.75 0 1 1 1.06 1.061A7 7 0 1 1 15 8a2.5 2.5 0 0 1-4.083 1.935A3.5 3.5 0 1 1 11.5 8a1 1 0 0 0 2 0 5.48 5.48 0 0 0-1.61-3.889ZM10 8a2 2 0 1 0-4 0 2 2 0 0 0 4 0Z"></path>
</g>
</svg>
|
<svg class="h-[1em] opacity-50" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<g
stroke-linejoin="round"
stroke-linecap="round"
stroke-width="1"
fill="black"
stroke="black"
>
<path d="M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM12.735 14c.618 0 1.093-.561.872-1.139a6.002 6.002 0 0 0-11.215 0c-.22.578.254 1.139.872 1.139h9.47Z"></path>
</g>
</svg>
<input id="inputaliasrecovery" type="text" placeholder="mail@site.com | alias" required />
</label>
<div class="validator-hint hidden">
Enter a valid email or an alias (lowercase a-z and 0-9)
</div>
</div>
<div class="my-5">
<p>
Si vous avez fait confiance à ce domaine pour garder vos clés, un email va être envoyé avec vos clés.
</p>
</div>
<div class="my-5">
<button
class="btn btn-primary w-full justify-center hover:bg-secondary focus:outline focus:outline-primary"
onclick="apx.apxauth.recoverykey('{{id}}',document.getElementById('inputaliasrecovery').value);"
>
M'envoyer un email avec mes clés
</button>
</div>

View File

@@ -0,0 +1,41 @@
<div class="space-y-6 text-justify">
<h2>Qu'est-ce qu'une identité numérique décentralisée?</h2>
<p>
C'est <span class="text-secondary">un moyen de s'identifier en prouvant qu'on est le propriétaire
d'un alias ou d'une clé publique</span>. Cette clé publique est accessible à tous et utilisée dans le
monde numérique pour informer, payer, échanger,... et porte une
réputation publique.
</p>
<p>
Concrètement, c'est une paire de fichiers texte appelée clé publique
et clé privée. La clé publique ne porte pas d'information
personnelle autre que celles que vous avez bien voulu y associer.
</p>
<p>
Une fonction mathématique permet au propriétaire de la clé privée de
signer un message. Le destinataire dispose d'une autre fonction qui
permet de vérifier que la signature a été faite avec la clé privée.
</p>
<p>
Cette interface permet de créer une identité et de l'utiliser pour
s'authentifier pour 24 heures. Elle n'envoie que le couple alias/clé
publique sur internet, la clé privée est
<span class="text-secondary">votre propriété et ne doit jamais être communiquée</span>. Si vous
la perdez, vous ne pourrez plus récupérer les informations
associées. Sauf si vous
<span class="text-secondary">avez fait confiance à ce nom de domaine</span>, vous pourrez lui
demander d'envoyer un email avec ces clés.
</p>
<p>
Vous pouvez avoir autant d'identités que vous voulez, vous pouvez
créer une identité pour des objets uniques. La seule limite est qu'à
partir du moment où vous associez des informations personnelles à
cette clé, le destinataire de ces informations peut les relier aux
activités de cette identité inscrite dans la blockchain apxtri.
</p>
<p>
Pour auditer le code js, utiliser l'outil de développement de votre
navigateur. Pour toute remarque, question ou détection de failles :
{{supportemail}}
</p>
</div>

View File

@@ -0,0 +1,39 @@
<div class="flex flex-col space-y-1 text-center">
<div class="mt-1">
<h1 class="mb-6">
Bonjour {{xalias}},
</h1>
<p>
Si cet appareil ne vous appartiens pas et que vous n'utilisez pas l'application, vous devriez vous deconnecter.
</p>
<p class="text-center text-gray-500">
Nettoyer mes traces de cet appareil?
<a class="font-semibold leading-6 text-secondary hover:text-primary"
onclick="apx.apxauth.logout('{{id}}','logout','logout','apxauth')">Se deconnecter</a>
</p>
</div>
<div class="mt-4">
<p class="text-center text-gray-500">
Voir mes échanges?
<a class="font-semibold leading-6 text-secondary hover:text-primary"
href="https://wall-ants.ndda.fr/apxwallet_fr.html" >Mon activité </a>
</p>
{{#member}}
<p>
Vous êtes membre de {{xtribe}} {{#noprofils}} sand profil particulier {{/noprofils}} {{^noprofils}}avec le(s) profil(s):<br><span class="text-info"> {{#profils}} {{.}}<br> {{/profils}} </span> {{/noprofils}}
</p>
{{/member}}
{{^member}}
<p> Vous n'êtes pas encore membre de {{xtribe}} </p>
<p class=" mt-1 text-center text-gray-500">
Envie d'jouter cette tribut {{xtribe}}?
<a class="font-semibold leading-6 text-secondary hover:text-primary"
onclick="apx.apxauth.jointribe('{{id}}')">Rejoindre {{xtribe}}</a>
</p>
{{/member}}
<p>Les applications ou pages web de {{xtribe}} à visiter:<br>
{{#websites}}<a class="font-semibold leading-6 text-secondary hover:text-primary" href='{{{href}}}'>{{{name}}}</a><br> {{/websites}}
</p>
<button class="btn btn-primary" onclick="apx.apxauth.runtest()">testbtn</button>
</div>
</div>

View File

@@ -0,0 +1,23 @@
<div class="flex flex-col space-y-1 text-center">
<div class="mt-1">
<h1 class="mb-6">
Bonjour {{xalias}},
</h1>
</div>
<div class="mt-4">
<p class="text-center text-gray-500">
Redirige vers
<a class="font-semibold leading-6 text-secondary hover:text-primary"
onclick="apx.apxauth.redirecturlwithauth('http://recruiter.smatchit.newdev.ants/src/offer_fr.html','smatchit','recruiter',true);" >Redirige vers recruiter.smatchit.io/offer_fr.html&xhash....</a>
</p>
{{#member}}
<p>
Vous êtes membre de {{xtribe}} {{#noprofils}} sand profil particulier {{/noprofils}} {{^noprofils}}avec le(s) profil(s):<br><span class="text-info"> {{#profils}} {{.}}<br> {{/profils}} </span> {{/noprofils}}
</p>
{{/member}}
<p>Les applications ou pages web de {{xtribe}} à visiter:<br>
{{#websites}}<a class="font-semibold leading-6 text-secondary hover:text-primary" href='{{{href}}}'>{{{name}}}</a><br> {{/websites}}
</p>
<button class="btn btn-primary" onclick="apx.apxauth.runtest()">testbtn</button>
</div>
</div>

View File

@@ -0,0 +1,69 @@
<p data-wco="createid" class="text-center text-neutral-content">
{{{signintitle}}}
</p>
<div class="mt-2">
<label class="input validator">
<svg class="h-[1em] opacity-90" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<g
stroke-linejoin="round"
stroke-linecap="round"
stroke-width="1"
fill="black"
stroke="black"
>
<path d="M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM12.735 14c.618 0 1.093-.561.872-1.139a6.002 6.002 0 0 0-11.215 0c-.22.578.254 1.139.872 1.139h9.47Z"></path>
</g>
</svg>
<input
class="signinalias"
type="input"
required
placeholder="alias"
pattern="[a-z0-9\-]*"
minlength="3"
maxlength="30"
title="{{{aliastitle}}}"
/>
</label>
<p class="validator-hint hidden"> {{{aliasinvalid}}}</p>
</div>
<div class="mt-2">
<label class="input mt-1">
<svg class="h-[1em] opacity-90" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<g
stroke-linejoin="round"
stroke-linecap="round"
stroke-width="1"
fill="black"
stroke="black"
>
<path d="M11.5 1A3.5 3.5 0 0 0 8 4.5V7H2.5A1.5 1.5 0 0 0 1 8.5v5A1.5 1.5 0 0 0 2.5 15h7a1.5 1.5 0 0 0 1.5-1.5v-5A1.5 1.5 0 0 0 9.5 7V4.5a2 2 0 1 1 4 0v1.75a.75.75 0 0 0 1.5 0V4.5A3.5 3.5 0 0 0 11.5 1Z"></path>
</g>
</svg>
<input type="text" class="signinpassphrase" placeholder="passphrase (option)" />
</label>
</div>
<div class="mt-2">
<textarea rows=5 class="mt-2 textarea signinprivatekey" placeholder="{{{privatekeyplaceholder}}}"></textarea>
</div>
<div class="flex m-6">
<div class="w-14 flex-none">
<input type="checkbox" checked="checked" class="checkbox signinrememberme" />
</div>
<div class="flex-1">
<p class="text-sm text-justify" >{{{remembermetext}}}</p>
</div>
</div>
<div class="m-4">
<button
class="btn btn-primary w-full justify-center hover:bg-secondary focus:outline focus:outline-primary"
onclick="const loginid= document.getElementById('{{id}}');apx.apxauth.authentifyme(
'{{id}}',
loginid.querySelector('.signinalias').value,
loginid.querySelector('.signinpassphrase').value,
loginid.querySelector('.signinprivatekey').value,
loginid.querySelector('.signinrememberme').checked
)">
{{{authentifyme}}}
</button>
</div>

View File

@@ -0,0 +1,121 @@
<p data-wco="createid" class="text-center text-neutral-content">
{{{signuptitle}}}
</p>
<div class="paramid">
<div class="mt-2">
<label class="input validator mbt-1">
<svg class="h-[1em] opacity-90" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<g
stroke-linejoin="round"
stroke-linecap="round"
stroke-width="1"
fill="black"
stroke="black"
>
<path d="M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM12.735 14c.618 0 1.093-.561.872-1.139a6.002 6.002 0 0 0-11.215 0c-.22.578.254 1.139.872 1.139h9.47Z"></path>
</g>
</svg>
<input
class="signupalias"
type="input"
required
placeholder="alias"
pattern="[a-z0-9\-]*"
minlength="3"
maxlength="30"
title="{{{aliastitle}}}"
/>
</label>
<div class="validator-hint hidden">
<p>{{{aliasinvalid}}}</p>
</div>
</div>
<div class="mt-2">
<label class="input validator mt-1">
<svg class="h-[1em] opacity-50" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<g
stroke-linejoin="round"
stroke-linecap="round"
stroke-width="1"
fill="black"
stroke="black"
>
<rect width="20" height="16" x="2" y="4" rx="2"></rect>
<path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"></path>
</g>
</svg>
<input class="signupemailrecovery" type="email" placeholder="mail@site.com" required />
</label>
<div class="validator-hint hidden">
{{{emailinvalid}}}
</div>
</div>
<div class="mt-2">
<label class="input mt-1">
<svg class="h-[1em] opacity-90" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<g
stroke-linejoin="round"
stroke-linecap="round"
stroke-width="1"
fill="black"
stroke="black"
>
<path d="M11.5 1A3.5 3.5 0 0 0 8 4.5V7H2.5A1.5 1.5 0 0 0 1 8.5v5A1.5 1.5 0 0 0 2.5 15h7a1.5 1.5 0 0 0 1.5-1.5v-5A1.5 1.5 0 0 0 9.5 7V4.5a2 2 0 1 1 4 0v1.75a.75.75 0 0 0 1.5 0V4.5A3.5 3.5 0 0 0 11.5 1Z"></path>
</g>
</svg>
<input type="text" class="signuppassphrase" placeholder="passphrase (option)" />
</label>
</div>
<div class="mt-5">
<button
class="btncreatekey btn btn-primary w-full justify-center hover:bg-secondary focus:outline focus:outline-primary"
onclick="const authid=document.getElementById('{{id}}');console.log('{{id}}'); apx.apxauth.createIdentity(
'{{id}}',
authid.querySelector('.signupalias').value,
authid.querySelector('.signupemailrecovery').value,
authid.querySelector('.signuppassphrase').value
)"
>
{{{createkey}}}
</button>
</div>
</div>
<div class="getmykeys hidden mt-1">
<div class="flex m-6">
<div class="w-14 flex-none">
<input type="checkbox" checked="checked" class="signuptrustedcheck checkbox checkbox-secondary" />
</div>
<div class="flex-1">
<p class="text-sm text-justify" >{{{trusttext}}}</p>
</div>
</div>
<div class="downloadkeys text-center mt-1">
<button
class="signuppublickey btn btn-outline btn-accent text-white shadow-sm"
>
{{{downloadPuK}}}
</button>
<button
class="signupprivatekey btn btn-outline btn-accent text-white shadow-sm"
>
{{{downloadPrK}}}
</button>
</div>
<div class="mt-2">
<button
class="btncreateidentity btn btn-primary w-full justify-center hover:bg-secondary focus:outline focus:outline-primary"
onclick="const authid=document.getElementById('{{id}}');apx.apxauth.registerIdentity(
'{{id}}',
authid.querySelector('.signuptrustedcheck').checked
)"
>{{{saveidentity}}}
</button>
<button
class="signupbtnreload hidden btn btn-primary w-full justify-center hover:bg-secondary focus:outline focus:outline-primary"
onclick="location.reload(true)"
>
{{{nextpage}}}
</button>
</div>
</div>