From 4c3d5f5433847b7e04ea7b24df4f87fdf0f916bc Mon Sep 17 00:00:00 2001 From: phondropoulos Date: Fri, 5 Jul 2024 14:02:09 +0300 Subject: [PATCH 1/3] More understanable readme --- README.md | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index b5de54f..351c8e5 100644 --- a/README.md +++ b/README.md @@ -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,30 +122,34 @@ 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 -$ npm install --global yarn -$ yarn --version -# Find a non existing town to join to an existing nation see https://apxtri.crabedance.com -$ mkdir ~/apxtowns # if it does not exist +$ node --version # to check the Node.js version +$ npm install --global yarn +$ 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 -$ dns=apxtri.ydns.io user=apxuser yarn dev + +# Set up and run for the first time +$ dns=apxtri.ydns.io user=apxuser yarn dev + + ################################# # For production ############### From 06cbd8f8e8f94948c1100aac86c4a93c2995568c Mon Sep 17 00:00:00 2001 From: phondropoulos Date: Tue, 9 Jul 2024 21:11:40 +0300 Subject: [PATCH 2/3] Updated Pagansunittest --- models/unittest/Pagansunittest.js | 271 ++++++++++-------------------- 1 file changed, 89 insertions(+), 182 deletions(-) diff --git a/models/unittest/Pagansunittest.js b/models/unittest/Pagansunittest.js index ccd7ed3..8313da9 100644 --- a/models/unittest/Pagansunittest.js +++ b/models/unittest/Pagansunittest.js @@ -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", - }, - ], + try { + 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(`Error joining tribe for alias ${alias}: ${error.message}`); + throw error; + } }; -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` - ); - } - } catch (error) { - console.error( - `Test case ${testCase.name} for ${user.alias} failed:`, - 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}.`); } - console.log(`--- Finished testing for ${user.alias} ---\n`); + // 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("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); }); } From bd98a0739cd164d5ecac81eb4611c590b5453a30 Mon Sep 17 00:00:00 2001 From: phondropoulos Date: Tue, 9 Jul 2024 21:22:18 +0300 Subject: [PATCH 3/3] Deleted unnecessary unittest files --- models/unittest/Paganstest.js | 245 ---------------------------------- 1 file changed, 245 deletions(-) delete mode 100644 models/unittest/Paganstest.js diff --git a/models/unittest/Paganstest.js b/models/unittest/Paganstest.js deleted file mode 100644 index 6eeb5ed..0000000 --- a/models/unittest/Paganstest.js +++ /dev/null @@ -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); -});