1
0
forked from apxtri/apxtri
Modiification notification
This commit is contained in:
philc 2024-07-11 13:31:38 +02:00
commit 6e71911978
3 changed files with 114 additions and 450 deletions

View File

@ -1,7 +1,7 @@
## apxtri  Decentralized Autonomous Organisation (DAO)
You are here on the tech side, to understand under the wood how it works and how you can contribute to this tech journey.
See [apxtri web site](https://apxtri.crabdance.com) how to create a new social world with apxtri.
Welcome to the technical side of apxtri, where you'll learn how it works and how you can contribute. Visit [apxtri web site](https://apxtri.crabdance.com) to discover how to create a new social world with apxtri.
## apxtri Architecture: a quick view & keywords definition
@ -15,7 +15,7 @@ See [apxtri web site](https://apxtri.crabdance.com) how to create a new social w
* **the XBE coin** is the token that drive the blockchain, it materialises an exchange value and is a conterpoint
* **a git apxtri** is a package ready to install a town by a mayor into a physical server that will be able to join a nation (mean accept thoses nation rules). You can also create a nation and stay alone or not. Then mayor will be able to host druid request to create tribe. Then druid will invite pagan to join his tribe...
All actors will have the same target to respect contracts and are free to leave or to stay into a nation, a town or a tribe. If a contract is not fair, then a nation, tribe, will be empty mean not creating value mean die. Only fair rules will survive but any try will rewards actor with XTRIB coin.
All actors will have the same target to respect contracts and are free to leave or to stay into a nation, a town or a tribe. Unfair contracts lead to empty towns, tribes, or nations, resulting in no value creation. Only fair rules will survive, rewarding actors with XTRIB coins.
```plaintext
/town-nation/ tribe sapce
@ -69,7 +69,7 @@ Pre-request: linux maxhine on a vps or physical machine ( we choose ubuntu serve
To start you need to 
* setup your network and for production a Domain Name server and a SSL certificat to your IP town
* setup your network and for production a Domain Name Server (DNS) and a SSL certificat to your town's IP
* setup your machine by installing snap, nginx, nvm, npm, node
As a mayor, you have to understand what you are doing, your numeric reputation is in the game. Always check sources before downloading any things. For dev use town name: **dev** and nation name :**ants** 
@ -85,9 +85,9 @@ $ sudo useradd -s /bin/bash -m -d /home/{apxuser} -c "{apxuser}" {apxuser}
$ sudo passwd {apxuser}
$ sudo usermod -aG sudo {apxuser}
$ sudo visudo
# add the next line in the file
# Add the following line to the file:
$ {apxuser} ALL=(ALL) NOPASSWD: ALL
# exit and save
# Exit and save, then switch to the new user:
$ su {apxuser}
```
@ -99,14 +99,12 @@ FOR DEV:  you can just use local http:/dev-ants
```plaintext
$ sudo vim /etc/hosts # add 127.0.0.1 dev-ants
# Then after "Machine" install, open in your browser http://dev-ants
# Open http://dev-ants in your browser after installation.
```
if you use chrome change settings for CORS for dev chrome://flags/#block-insecure-private-network-requests  change to disabled  
FOR PRODUCTION: 
You need a domain name, to get a free one [http://ydns.io](http://ydns.io) create one like apxtri.ydns.io that content your IP adress the get your url update something like [https://ydns.io/hosts/update/Tl7FDQAETmQre312edztgsI](https://ydns.io/hosts/update/Tl7FDQAETmQre312edztgsI)[Uy](https://ydns.io/hosts/update/Tl7FDQAETmQre312edztgsIUy)
You need a domain name. To get a free one, visit [http://ydns.io] and create one like apxtri.ydns.io that contains your IP address. Then, update your URL with something like [https://ydns.io/hosts/update/Tl7FDQAETmQre312edztgsI](https://ydns.io/hosts/update/Tl7FDQAETmQre312edztgsI)[Uy](https://ydns.io/hosts/update/Tl7FDQAETmQre312edztgsIUy)
```plaintext
# Into your production machine
@ -124,31 +122,35 @@ This allow public access from internet to your DMZ local server.  Think to use
```plaintext
$ sudo apt install git vim libcap2-bin p7zip-full p7zip-rar curl nginx
# Install last nvm** (check website to get latest v0.xx from https://github.com/nvm-sh/nvm)
# Install the latest version of nvm (check the website for the latest version: https://github.com/nvm-sh/nvm)
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
# close and re-open terminal under apxuser
# Close and re-open the terminal under the apxuser
$ nvm --version
# if nvm not found then cc paste 3 last line : export NVM_DIR= ....
# and recheck nvm --version
# Install node/npm/yarn in general follow the directiv they gave online to update properly the config
# If nvm is not found, copy and paste the last 3 lines of the installation script: export NVM_DIR=....
# Then recheck the nvm version
$ nvm --version
# Install Node.js, npm, and yarn. Follow the online instructions to update the configuration properly.
$ nvm install node
$ node --version #to check
$ node --version # to check the Node.js version
$ npm install --global yarn
$ yarn --version
# Find a non existing town to join to an existing nation see https://apxtri.crabedance.com
$ yarn --version # to check the yarn version
# Find a non-existing town to join an existing nation. See https://apxtri.crabedance.com
$ mkdir ~/apxtowns # if it does not exist
$ mkdir ~/apxtowns/{town}-{nation}
$ sudo chown {apxuser}:root /etc/nginx/nginx.conf
#################################
# For dev #######################
# For Dev ###############
#################################
$ mkdir ~/apxtowns/{town}-{nation}/adminapi/
$ cd ~/apxtowns/{town}-{nation}/adminapi/
$ git clone https://gitea.ndda.fr/apxtri/apxtri.git
$ yarn install
# to setup run the 1st time
# Set up and run for the first time
$ dns=apxtri.ydns.io user=apxuser yarn dev
#################################
# For production ###############
#################################

View File

@ -1,245 +0,0 @@
const assert = require('assert');
const axios = require('axios');
const dayjs = require('dayjs');
const openpgp = require('openpgp');
// Mock axios using a simple approach
const mockAxios = (() => {
const mocks = [];
return {
get: (url, config) => {
const mock = mocks.find(m => m.method === 'get' && m.url === url);
if (mock) return Promise.resolve(mock.response);
return axios.get(url, config); // Fallback to real axios if no mock found
},
post: (url, data, config) => {
const mock = mocks.find(m => m.method === 'post' && m.url === url);
if (mock) return Promise.resolve(mock.response);
return axios.post(url, data, config); // Fallback to real axios if no mock found
},
put: (url, data, config) => {
const mock = mocks.find(m => m.method === 'put' && m.url === url);
if (mock) return Promise.resolve(mock.response);
return axios.put(url, data, config); // Fallback to real axios if no mock found
},
delete: (url, config) => {
const mock = mocks.find(m => m.method === 'delete' && m.url === url);
if (mock) return Promise.resolve(mock.response);
return axios.delete(url, config); // Fallback to real axios if no mock found
},
mock: (method, url, response) => {
mocks.push({ method, url, response });
},
clear: () => {
mocks.length = 0;
}
};
})();
// apx.js functions implemented within the test file
const apx = {};
apx.generateKey = async (alias, passphrase) => {
const pgpParams = {
type: 'ecc',
curve: 'curve25519',
userIDs: [{ name: alias }],
passphrase: passphrase,
format: 'armored'
};
const key = await openpgp.generateKey(pgpParams);
return {
alias,
privatekey: key.privateKeyArmored,
publickey: key.publicKeyArmored
};
};
apx.createIdentity = async (alias, passphrase) => {
try {
const { privatekey, publickey } = await apx.generateKey(alias, passphrase);
const response = await axios.post('/api/adminapi/pagans', {
alias,
publickey
});
return response.data;
} catch (error) {
console.error('Error creating identity:', error);
}
};
apx.clearmsgSignature = async (privateKeyArmored, passphrase, message) => {
const { keys: [privateKey] } = await openpgp.decryptKey({
privateKey: await openpgp.readKey({ armoredKey: privateKeyArmored }),
passphrase
});
const signedMessage = await openpgp.sign({
message: await openpgp.createMessage({ text: message }),
signingKeys: privateKey
});
return signedMessage;
};
apx.jointribe = async (headers) => {
try {
const response = await axios.put(`/api/adminapi/pagans/person/${headers.xtribe}`, {
headers
});
return response.data;
} catch (error) {
console.error('Error joining tribe:', error);
}
};
apx.deleteIdentity = async (headers, alias) => {
try {
const response = await axios.delete(`/api/adminapi/pagans/person/${headers.xtribe}/${alias}`, {
headers
});
return response.data;
} catch (error) {
console.error('Error deleting identity:', error);
}
};
const headers = {
xtrkversion: 1,
xalias: 'anonymous',
xapp: 'smatchapp',
xdays: 0,
xhash: 'anonymous',
xlang: 'fr',
xprofils: 'anonymous',
xtribe: 'smatchit',
xuuid: '0'
};
let alias = 'testalias';
let passphrase = 'testpassphrase';
let privateKey, publicKey;
let authHeaders;
const testCases = [
{
name: 'Create Identity',
async run() {
const keys = await apx.generateKey(alias, passphrase);
privateKey = keys.privatekey;
publicKey = keys.publickey;
mockAxios.mock('get', `/api/adminapi/pagans/alias/${alias}`, { status: 404 });
mockAxios.mock('post', '/api/adminapi/pagans', { data: { status: 200, ref: 'Pagans', msg: 'identitycreated', data: { alias } } });
await apx.createIdentity(alias, passphrase);
},
async verify() {
const response = await mockAxios.get(`/api/adminapi/pagans/alias/${alias}`);
assert.strictEqual(response.status, 200, 'Alias should exist after creation');
assert.strictEqual(response.data.alias, alias, 'Alias data should match');
}
},
{
name: 'Authenticate',
async run() {
headers.xalias = alias;
headers.xdays = dayjs().valueOf();
const msg = `${alias}_${headers.xdays}`;
headers.xhash = await apx.clearmsgSignature(privateKey, passphrase, msg);
mockAxios.mock('get', '/api/adminapi/pagans/isauth', { data: { data: { xprofils: ['pagans', 'persons'] } } });
authHeaders = {
...headers,
xhash: headers.xhash,
xdays: headers.xdays
};
await mockAxios.get('/api/adminapi/pagans/isauth', { headers: authHeaders });
},
verify() {
// Assertions can be added here if needed
}
},
{
name: 'Join Tribe',
async run() {
mockAxios.mock('put', `/api/adminapi/pagans/person/${headers.xtribe}`, { status: 200 });
await apx.jointribe(authHeaders);
},
verify() {
// Assertions can be added here if needed
}
},
{
name: 'Modify First Name',
async run() {
const newFirstName = 'NewFirstName';
mockAxios.mock('put', `/api/adminapi/pagans/person/${headers.xtribe}`, { status: 200, data: { alias, firstName: newFirstName } });
await mockAxios.put(`/api/adminapi/pagans/person/${headers.xtribe}`, {
alias,
addprofil: 'newprofil',
persontochange: alias
}, { headers: authHeaders });
},
async verify() {
const response = await mockAxios.get(`/api/adminapi/pagans/person/${headers.xtribe}/${alias}`, { headers: authHeaders });
assert.strictEqual(response.data.firstName, 'NewFirstName', 'First name should be updated');
}
},
{
name: 'Revert First Name',
async run() {
const originalFirstName = 'OriginalFirstName';
mockAxios.mock('put', `/api/adminapi/pagans/person/${headers.xtribe}`, { status: 200, data: { alias, firstName: originalFirstName } });
await mockAxios.put(`/api/adminapi/pagans/person/${headers.xtribe}`, {
alias,
addprofil: 'newprofil',
persontochange: alias
}, { headers: authHeaders });
},
async verify() {
const response = await mockAxios.get(`/api/adminapi/pagans/person/${headers.xtribe}/${alias}`, { headers: authHeaders });
assert.strictEqual(response.data.firstName, 'OriginalFirstName', 'First name should be reverted');
}
},
{
name: 'Delete Identity',
async run() {
mockAxios.mock('delete', `/api/adminapi/pagans/person/${headers.xtribe}/${alias}`, { status: 200 });
await apx.deleteIdentity(authHeaders, alias);
},
async verify() {
const response = await mockAxios.get(`/api/adminapi/pagans/alias/${alias}`);
assert.strictEqual(response.status, 404, 'Alias should not exist after deletion');
}
}
];
const runTests = async () => {
for (const testCase of testCases) {
console.log(`Running test case: ${testCase.name}`);
await testCase.run();
await testCase.verify();
mockAxios.clear(); // Clear mocks between tests
}
};
runTests().then(() => {
console.log('All test cases ran successfully');
}).catch(err => {
console.error('Test case failed:', err);
});

View File

@ -1,9 +1,42 @@
const assert = require("assert");
const openpgp = require("openpgp");
const dayjs = require("dayjs");
const assert = require('assert');
const openpgp = require('openpgp');
const Pagans = require('../Pagans');
const ut = { name: "Pagans" };
const ut = { name: 'Pagans' };
// Data
ut.test = {
tribe: "smatchit",
pagans: [
{
alias: "unittestadminsmatchit",
passphrase: "adminsmatchitPass",
persons: { firstname: "toto", lastname: "titi", profils: ["anonymous"] },
testprofil: "adminrecruiter",
},
{
alias: "unittestseeker",
passphrase: "",
persons: { firstname: "toto", lastname: "titi", profils: ["anonymous"] },
testprofil: "seeker",
},
{
alias: "unittestrecruiter",
passphrase: "recruiterPass",
persons: { firstname: "toto", lastname: "titi", profils: ["anonymous"] },
testprofil: "recruiter",
},
{
alias: "unittestadminrecruiter",
passphrase: "adminrecruiterPass",
persons: { firstname: "toto", lastname: "titi", profils: ["anonymous"] },
testprofil: "adminrecruiter",
},
],
};
// Apx
const apx = {};
apx.generateKey = async (alias, passphrase) => {
@ -35,203 +68,77 @@ apx.generateKey = async (alias, passphrase) => {
apx.createIdentity = async (alias, passphrase) => {
try {
const { privatekey, publickey } = await apx.generateKey(alias, passphrase);
if (!privatekey || !publickey) {
throw new Error(`Failed to generate keys for ${alias}`);
}
console.log(`Identity created successfully for alias: ${alias}`);
return { alias, privatekey, publickey };
} catch (error) {
console.error(`Error creating identity for alias: ${alias}`, error);
throw error;
}
};
// Mock joinTribe
apx.joinTribe = async (alias, tribe) => {
// Mock implementation of joining a tribe
console.log(`Alias ${alias} joined tribe ${tribe}`);
return true;
};
apx.deleteAlias = async (alias) => {
// Mock implementation of deleting an alias
console.log(`Alias ${alias} deleted`);
return true;
};
const personData = {};
const apxFunctions = {
modifyPersonData(alias, newFirstName) {
if (!personData[alias]) {
personData[alias] = {};
}
personData[alias].firstName = newFirstName;
return personData[alias];
},
checkPersonData(alias, expectedFirstName) {
return (
personData[alias] && personData[alias].firstName === expectedFirstName
);
},
removePersonModification(alias, originalFirstName) {
if (personData[alias]) {
personData[alias].firstName = originalFirstName;
}
return personData[alias];
},
deleteAlias(alias) {
delete personData[alias];
return !personData[alias];
},
};
ut.test = {
tribe: "smatchit",
pagans: [
{
alias: "unittestadminsmatchit",
passphrase: "adminsmatchitPass",
persons: { firstname: "toto", lastname: "titi", profils: ["anonymous"] },
testprofil: "adminrecruiter",
},
{
alias: "unittestseeker",
passphrase: "",
persons: { firstname: "toto", lastname: "titi", profils: ["anonymous"] },
testprofil: "seeker",
},
],
};
ut.createpersons=()=>{
let msg = "";
ut.test.pagans.forEach((t) => {
//test if alias does not already exist
const pagan={}
const getalias= Pagans.getalias(t.alias);
if (getalias.status!=404) then alias already exist
else {delete}
const keys = apx.generatekey(t.alias, t.passphrase)
pagans.public key
schema.properties = t.properties;
const res = Checkjson.schema.data(schema, t.data);
if (res.status != t.status) {
msg = msg == "" ? "Unconsistent testproperties() name list: " : `${msg},`;
if (options.verbose) {
console.log(t);
console.log(res);
}
msg += res.err.map((e) => ` ${t.name} ${e.info}`);
}
});
return assert.deepEqual(msg, "", msg);
}
Object.keys(pagans).forEach((key) => {
pagans[key].headers = {
xtrkversion: 1,
xalias: "anonymous",
xapp: "smatchapp",
xdays: 0,
xhash: "anonymous",
xlang: "fr",
xprofils: "anonymous",
xtribe: "smatchit",
xuuid: "0",
};
});
const testCases = [
{
name: "Create Identity",
async run(user) {
const identity = await apx.createIdentity(user.alias, user.passphrase);
if (identity) {
user.privateKey = identity.privatekey;
user.publicKey = identity.publickey;
}
return identity;
},
verify(identity, alias) {
assert(identity, "Identity should not be undefined");
assert(identity.alias === alias, "Alias should match");
assert(
identity.privatekey &&
identity.privatekey.includes("BEGIN PGP PRIVATE KEY BLOCK"),
"Private key is not valid"
);
assert(
identity.publickey &&
identity.publickey.includes("BEGIN PGP PUBLIC KEY BLOCK"),
"Public key is not valid"
);
},
},
{
name: "Join Tribe",
async run(user) {
return await apx.joinTribe(user.alias, "smatchit");
},
verify(result) {
assert(result, "Joining tribe should return true");
},
},
{
name: "Delete Alias",
async run(user) {
return await apx.deleteAlias(user.alias);
},
verify(result) {
assert(result, "Deleting alias should return true");
},
},
];
ut.run = async (options) => {
console.log("Test Pagans Registration and Authentication");
// Create and test identities for all users
for (const userKey of Object.keys(pagans)) {
const user = pagans[userKey];
console.log(`\n--- Creating and testing identity for ${user.alias} ---`);
for (const testCase of testCases) {
console.log(`Running test case: ${testCase.name} for ${user.alias}`);
try {
const result = await testCase.run(user);
if (result) {
testCase.verify(result, user.alias);
console.log(`Test case ${testCase.name} for ${user.alias} passed`);
} else {
console.error(
`Test case ${testCase.name} for ${user.alias} failed: No result returned`
);
}
console.log(`Joining alias ${alias} to tribe ${tribe}`);
console.log(`Alias ${alias} successfully joined tribe ${tribe}`);
return { status: 200, message: 'Success' }; // Mock success response
} catch (error) {
console.error(
`Test case ${testCase.name} for ${user.alias} failed:`,
error
);
console.error(`Error joining tribe for alias ${alias}: ${error.message}`);
throw error;
}
};
ut.createIdentity = async (t) => {
try {
// Test if alias already exists
const getalias = await Pagans.getalias(t.alias);
if (getalias.status !== 404) {
console.log(`Alias ${t.alias} already exists. Deleting...`);
await Pagans.deletealias(t.alias);
console.log(`Deleted ${t.alias}.`);
}
// Generate keys
const keys = await apx.createIdentity(t.alias, t.passphrase);
if (!keys.privatekey || !keys.publickey) {
throw new Error(`Failed to generate keys for ${t.alias}`);
}
// Join tribe
await apx.joinTribe(t.alias, ut.test.tribe);
return keys;
} catch (error) {
throw new Error(`Error creating identity for ${t.alias}: ${error.message}`);
}
};
ut.run = async () => {
console.log('Test Pagans Registration and Authentication');
for (const t of ut.test.pagans) {
try {
console.log(`Creating identity for ${t.alias}`);
const identity = await ut.createIdentity(t);
console.log(`All operations for ${t.alias} completed successfully.`);
} catch (error) {
console.error(`Error processing ${t.alias}: ${error.message}`);
}
}
console.log(`--- Finished testing for ${user.alias} ---\n`);
}
console.log("All test cases ran successfully");
console.log('All test cases ran successfully');
};
module.exports = ut;
if (require.main === module) {
ut.run({ verbose: true }).catch((err) => {
console.error("Test case failed:", err);
ut.run().catch(err => {
console.error('Test case failed:', err);
});
}