Mise à jour de 'Devrules'

philc 2023-03-27 08:53:43 +00:00
parent 32aafedfe9
commit e1a05c7fb6

@ -1,268 +1,274 @@
# Developers # Developers
This page is about to save time to a dev to quickly onboard to add a features or debug any issues. This is also a good start if you want just dev a plugin for a tribe. This page is about to save time to a dev to quickly onboard to add a features or debug any issues. This is also a good start if you want just dev a plugin for a tribe.
Visual studio theme @id:ms-vscode.cpptools-themes Visual studio theme @id:ms-vscode.cpptools-themes
## git management ## git management
**Relations between git branches and environment** **Relations between git branches and environment**
Those branches are corresponding to various environment: Those branches are corresponding to various environment:
- **branch `main` is used for the production only** and needs a pull request to allow developers changes; - **branch `main` is used for the production only** and needs a pull request to allow developers changes;
- **branch `staging` is used for testing** and needs a pull request to allow developers changes; - **branch `staging` is used for testing** and needs a pull request to allow developers changes;
- **branch `develop` is the current last working version under development of the application .** Writing changes is allowed for developers on this branch. - **branch `develop` is the current last working version under development of the application .** Writing changes is allowed for developers on this branch.
Initialize a developer branch, each developer must create and checkout a new branch named `devel/${USERNAME}` to work. Initialize a developer branch, each developer must create and checkout a new branch named `devel/${USERNAME}` to work.
**Git process for developers** **Git process for developers**
1. Select a feature to develop or a bug to fix. ideally work on different files and isolated from other work done in parallel by other developers. This will avoid or limit problems when merging branches. 1. Select a feature to develop or a bug to fix. ideally work on different files and isolated from other work done in parallel by other developers. This will avoid or limit problems when merging branches.
2. Before any change on your local repository, please previously : 2. Before any change on your local repository, please previously :
- run a `git pull`; - run a `git pull`;
- merge your branch with the last commit of the `devel` branch : - merge your branch with the last commit of the `devel` branch :
```shell ```shell
git checkout devel/${USERNAME} git checkout devel/${USERNAME}
git merge devel git merge devel
``` ```
- fix conflicts on your local repository if necessary. - fix conflicts on your local repository if necessary.
3. Program your changes. 3. Program your changes.
4. **Don't forget to test!** Check if your changes are working locally. 4. **Don't forget to test!** Check if your changes are working locally.
5. Commit local changes on your named branch: `git commit -am "[comment]` 5. Commit local changes on your named branch: `git commit -am "[comment]`
6. Push on your named branch: `git push -u origin devel/${USERNAME}` 6. Push on your named branch: `git push -u origin devel/${USERNAME}`
7. Merge your modifications on the `devel` branch : `git checkout devel && git merge devel/${USERNAME}` 7. Merge your modifications on the `devel` branch : `git checkout devel && git merge devel/${USERNAME}`
- Fix conflict if needed. - Fix conflict if needed.
8. Push on the reference `devel` branch your changes: `git push -u origin devel` 8. Push on the reference `devel` branch your changes: `git push -u origin devel`
9. Return to your local git branch to avoid errors directly on the `devel` reference branch 9. Return to your local git branch to avoid errors directly on the `devel` reference branch
**Git process for product owner** (aka P.O.) **Git process for product owner** (aka P.O.)
1. The P.O. can merge `testing` branch with latest commit of the `develop` branch **only if application is working and functional**. 1. The P.O. can merge `testing` branch with latest commit of the `develop` branch **only if application is working and functional**.
2. Add a git tag on commit according [SemVer](semver.org/) standards: `git tag v[SEMVER_VERSION] -m "[comment]" "&& git push --tags` 2. Add a git tag on commit according [SemVer](semver.org/) standards: `git tag v[SEMVER_VERSION] -m "[comment]" "&& git push --tags`
- *This tag is essential to correctly track application versions and to integrate it into a CI/CD process that is standardized and compliant!** - *This tag is essential to correctly track application versions and to integrate it into a CI/CD process that is standardized and compliant!**
3. Test the application on the related environment. 3. Test the application on the related environment.
4. Then the P.O. can merge `main` branch with latest commit of the `testing` branch **only if application is working and functional**. 4. Then the P.O. can merge `main` branch with latest commit of the `testing` branch **only if application is working and functional**.
## Common rules ## Common rules
### Security ### Security
- **Never store any password, API keys or any another sensible information in the Git repository!** - **Never store any password, API keys or any another sensible information in the Git repository!**
- **Think twice before adding a package in your project, get answer about licence, audited or not,** - **Think twice before adding a package in your project, get answer about licence, audited or not,**
### Performance ### Performance
- **use require function by loading only what you need** - **use require function by loading only what you need**
- **be a bootleneck hunter, use async when it is possible but keep your code readable and simple** - **be a bootleneck hunter, use async when it is possible but keep your code readable and simple**
## apXtrib Key points ## apXtrib Key points
* this is a npm/yarn classical organization (package.json give you 1st info) * this is a npm/yarn classical organization (package.json give you 1st info)
* **Entry point** ./apxtrib.js * **Entry point** ./apxtrib.js
* apXtrib is organize around an express.js api and respect the restFULL concept on an object. * apXtrib is organize around an express.js api and respect the restFULL concept on an object.
* An **object** has: * An **object** has:
- a unique objectName - a unique objectName
- a schema definition that describe each character to qualify an object - a schema definition that describe each character to qualify an object
- a route named ./routes/objectName.js from the api /objectName/ parameters to request acting on items of this objectName - a route named ./routes/objectName.js from the api /objectName/ parameters to request acting on items of this objectName
- a model named ./models/ObjectName.js that act on items - a model named ./models/ObjectName.js that act on items
- a language info in infolg/ObjectName.js - a language info in infolg/ObjectName.js
* **Access control** is done by 3 middlewares: * **Access control** is done by 3 middlewares:
- checkHeaders.js that check ./tribes/townconf.json.exposedHeaders are presents - checkHeaders.js that check ./tribes/townconf.json.exposedHeaders are presents
- isAuthenticated.js check the token (header.xauth ) for header.xpaganid is valid - isAuthenticated.js check the token (header.xauth ) for header.xpaganid is valid
- hasAccessrighton.js check accessright of pagan to act (CRUD) on an object into a tribe (xworkon) - hasAccessrighton.js check accessright of pagan to act (CRUD) on an object into a tribe (xworkon)
* A **request** is send with specific header to be accepted. * A **request** is send with specific header to be accepted.
``` ```
{ {
xauth: 'jwt token 24hours valid or 1 if not authenticated', xauth: 'jwt token 24hours valid or 1 if not authenticated',
xpaganid: 'uuid of the connected user' xpaganid: 'uuid of the connected user'
xlang:' lang international notification 2 letters of the request', xlang:' lang international notification 2 letters of the request',
xtribe: 'name of the tribe, xpaganId belongs to', xtribe: 'name of the tribe, xpaganId belongs to',
xworkon: 'name of tribe user want to act if accessrights are properly set up', xworkon: 'name of tribe user want to act if accessrights are properly set up',
xapp: 'name of app requesting action "tribename:nappname" if accessrights are set up' xapp: 'name of app requesting action "tribename:nappname" if accessrights are set up'
} }
``` ```
* A **response** is structured as * A **response** is structured as
``` ```
{ {
status: mandatory Integer,(web status code)[https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml] status: mandatory Integer,(web status code)[https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml]
info: optional string, info: optional string,
data: optional object data: optional object
} }
``` ```
* **Multilanguage management** depending of header.xlang request * **Multilanguage management** depending of header.xlang request
- info:"|model|key" starting by | mean a file is available in ./nationchains/static/info/model_lg.json to match {key:"information in language lg} - info:"|model|key" starting by | mean a file is available in ./nationchains/static/info/model_lg.json to match {key:"information in language lg}
## apXtrib Coding Convention ### apXtrib Coding Convention
Standard: Eslint 6 with a .eslintrc.js Standard: Eslint 6 with a .eslintrc.js
lib used for: lib used for:
- file json manipulation: fs-extra.js - file json manipulation: fs-extra.js
- templating szysteme: mustache.js - templating szysteme: mustache.js
- encryption with simple hash : bcrypt that is more efficient than crypto-js that is use inside a browser or node for cypher and uncipher - encryption with simple hash : bcrypt that is more efficient than crypto-js that is use inside a browser or node for cypher and uncipher
- time management use luxon and no more moment - time management use luxon and no more moment
- cross domain management: cors.js - cross domain management: cors.js
- to generate unique id use lib uuid.v4() - to generate unique id use lib uuid.v4()
- stripe to allow payment in $,€,... any device - stripe to allow payment in $,€,... any device
In general try to not install other lib in your dev. An apXtrib town mayor have to globaly valid to add a new lib into apxtrib so if you do then you can only use your town to provide your service and cannot use other town to deal wwith. In general try to not install other lib in your dev. An apXtrib town mayor have to globaly valid to add a new lib into apxtrib so if you do then you can only use your town to provide your service and cannot use other town to deal wwith.
### apiDoc
## CORS and global
We use apidoc to generate the apXtrib documentation in nationscjains/apidoc/
global variable into node: Each route has to respect https://apidocjs.com/
* ${__base} is the current dir where project are install in case you need absolute path. Before a push please run yarn apidoc to update the documentation.
* config is set from ./tribes/townconf.json where:
- system data are available to sync town and nation (linux user, url, nation and town name)
- express set up parameter appset allow to set any key:val parameter of express ### CORS and global
-
* const app is an express instance that is set into apixtrib.js global variable into node:
* ${__base} is the current dir where project are install in case you need absolute path.
* config is set from ./tribes/townconf.json where:
- system data are available to sync town and nation (linux user, url, nation and town name)
## route template - express set up parameter appset allow to set any key:val parameter of express
-
A route analyse (data structure and user accesrights) a http request to act a model action * const app is an express instance that is set into apixtrib.js
## model template
A model is a logical to apply onto an object. It is indepedant of the interface ### route template
export model to make it importable into route or any other app
A route analyse (data structure and user accesrights) a http request to act a model action
### model template
## Object organization
A model is a logical to apply onto an object. It is indepedant of the interface
Object properties are strongly inspire of https://schema.org/docs/schemas.html <br> export model to make it importable into route or any other app
Fom https://json-schema.org/learn/<br>
https://json-schema.org/understanding-json-schema/index.html<br>
https://json-schema.org/draft/2020-12/release-notes.html<br> ## Object organization
Warning: stay in those specification much as it is possible, try to use existing object like person, organisation, .... Object properties are strongly inspire of https://schema.org/docs/schemas.html <br>
As it is still on draft, a Odmdb.js (Objectdatamodeldatabase) is managing any CRUD on json object Fom https://json-schema.org/learn/<br>
Any apxtrib key word is **prefix by apx** to inform that it does not exist in JSON schema protocole. This can be change in the futur if json schema will be stable enough. https://json-schema.org/understanding-json-schema/index.html<br>
https://json-schema.org/draft/2020-12/release-notes.html<br>
An **object is defined by a schema** store into ./nationchains/socialworld/schema/objectName.json or tribe/tribeId/plugins/pluginName/schema/objectName.json
It lists key definition of an item's object. Warning: stay in those specification much as it is possible, try to use existing object like person, organisation, ....
In basic configuration Items object are store into ./nationchains/socialworld/objects/objectName/objectNameid.json or tribe/tribeId/objects/objectName/objectNameid.json.
If an **item have a language** properties:lang that describe in with language is used by this item. If the object item cannot be translate this means that it is a different object. As it is still on draft, a Odmdb.js (Objectdatamodeldatabase) is managing any CRUD on json object
Any apxtrib key word is **prefix by apx** to inform that it does not exist in JSON schema protocole. This can be change in the futur if json schema will be stable enough.
apXtrib **convention to manage language** to get a schema in a language:lg :
|objectName|keyword => file ./nationchains/socialworld/objects_lang/objectName_lg.json = {keyword:description in lg} An **object is defined by a schema** store into ./nationchains/socialworld/schema/objectName.json or tribe/tribeId/plugins/pluginName/schema/objectName.json
or tribe/tribeId/objects_lang/objectName_lg.json It lists key definition of an item's object.
In basic configuration Items object are store into ./nationchains/socialworld/objects/objectName/objectNameid.json or tribe/tribeId/objects/objectName/objectNameid.json.
If any string start with | mean it exist a file translation If an **item have a language** properties:lang that describe in with language is used by this item. If the object item cannot be translate this means that it is a different object.
A models/objectName.js manage all items of an objectName: apXtrib **convention to manage language** to get a schema in a language:lg :
- CRUD action on any items depind of pagan accessright |objectName|keyword => file ./nationchains/socialworld/objects_lang/objectName_lg.json = {keyword:description in lg}
- index builder that are store into /objectName/searchindex/ or tribe/tribeId/objects_lang/objectName_lg.json
a searchindex file is named as objectname_idfield1_idfiled2_lg.json
and contain: { value1idfiled1:[ value1idfield2 ] } If any string start with | mean it exist a file translation
Depending of volume, it is possible to have objectName_UUID_UUID_lg.json this contain
{ valueuuid: { key:value of object} } A models/objectName.js manage all items of an objectName:
- CRUD action on any items depind of pagan accessright
- index builder that are store into /objectName/searchindex/
### Object key description a searchindex file is named as objectname_idfield1_idfiled2_lg.json
and contain: { value1idfiled1:[ value1idfield2 ] }
Main properties key: Depending of volume, it is possible to have objectName_UUID_UUID_lg.json this contain
* **description** a short description that can be use in GUI { valueuuid: { key:value of object} }
* **desclong** a long description
* **info** a long or short html description
* **default** value by default if not set when object is save, this can be a function ### Object key description
example: UUID.v4() or moment(new Date()).format('YYYY-MM-DD')
* **format** usefull for date or any text structured example:"YYYY-MM-DD" Main properties key:
* **type** string / int / * **description** a short description that can be use in GUI
* **enum** list of valid data * **desclong** a long description
* **$apxenumkey** if "data" then properties status.data has to be set as a {key:value} * **info** a long or short html description
else a web link (absolute http:/... or relative ./...) to a {key:value} * **default** value by default if not set when object is save, this can be a function
mean the value have to be one of the key of this json file if it is required example: UUID.v4() or moment(new Date()).format('YYYY-MM-DD')
* * **format** usefull for date or any text structured example:"YYYY-MM-DD"
* **type** string / int /
En prevision de smatchit : * **enum** list of valid data
person shema * **$apxenumkey** if "data" then properties status.data has to be set as a {key:value}
{ else a web link (absolute http:/... or relative ./...) to a {key:value}
"idfield": "telephone", mean the value have to be one of the key of this json file if it is required
"desc": "|Pagans|telephonedesc", *
"check": ["phone"]
"tpl": "input", En prevision de smatchit :
"type": "text" person shema
}, {
{ "idfield": "telephone",
"idfield": "familyName", "desc": "|Pagans|telephonedesc",
"desc": "|Pagans|familyNamedesc", "check": ["phone"]
"tpl": "input", "tpl": "input",
"type": "text" "type": "text"
}, },
{ {
"idfield": "givenName", "idfield": "familyName",
"desc": "|Pagans|givenNamedesc", "desc": "|Pagans|familyNamedesc",
"tpl": "input", "tpl": "input",
"type": "text" "type": "text"
}, },
{ {
"idfield": "additionalName", "idfield": "givenName",
"desc": "|Pagans|additionalNamedesc", "desc": "|Pagans|givenNamedesc",
"tpl": "input", "tpl": "input",
"type": "text", "type": "text"
"info": "|Pagans|additionalNameinfo" },
}, {
"idfield": "additionalName",
"desc": "|Pagans|additionalNamedesc",
**searchindex** array of index to generate "tpl": "input",
keyword "all" => generate objectname/searchinndex/objectname_UUID_UUID.json = {uuid:{full key:value}} "type": "text",
* **nouserupdate** user cannot modify this field from a request (only internal process can change this) "info": "|Pagans|additionalNameinfo"
* **check** array of keyword required, unique, ... },
a checkdata lib (./natonchains/socialworld/contracts/checkdata.js) can be used
into a browser : <script src="https://townName.nationName.dns/socialworld/contracts/checkdata.js"></script> **searchindex** array of index to generate
or into a node.js : const checkdata = require( `../nationchains/socialworld/contracts/checkdata.js`); keyword "all" => generate objectname/searchinndex/objectname_UUID_UUID.json = {uuid:{full key:value}}
* **nouserupdate** user cannot modify this field from a request (only internal process can change this)
Some test function need context (ctx ) for example to check a value is unique * **check** array of keyword required, unique, ...
example: @TODO key example
a checkdata lib (./natonchains/socialworld/contracts/checkdata.js) can be used
checkdata.evaluate = (contexte (list ), metaobject (definition of object metaobject/name.json), data (item object set to evaluate)) into a browser : <script src="https://townName.nationName.dns/socialworld/contracts/checkdata.js"></script>
or into a node.js : const checkdata = require( `../nationchains/socialworld/contracts/checkdata.js`);
In case of unconsistency(ies) a new field call invalidfor array of list of unconsitencies is returned
Some test function need context (ctx ) for example to check a value is unique
example: @TODO key example
### Object Nationschains
checkdata.evaluate = (contexte (list ), metaobject (definition of object metaobject/name.json), data (item object set to evaluate))
This model manage the socialworld based on nations and towns to run a blockchain where a node is a town and a nation is a blockchain rules that any town respect.
Rules are manage in Contracts. In case of unconsistency(ies) a new field call invalidfor array of list of unconsitencies is returned
.models/Setup.js is the interface of this model, to create a node/town for dev that is an unchain town or for production that is a chain town (real node) [process of setup] (https://gitea.ndda.fr/apxtrib/apxtrib/wiki/Setup)
### Object Nationschains
A pagan have an uuid + public key + private key and belong to only one tribe at a time optionaly an email + login + psw to recover his login/psw into his tribe. His private key is the only way to prove a user his the owner of an uuid account. No one else than the pagan knows his private key.
This model manage the socialworld based on nations and towns to run a blockchain where a node is a town and a nation is a blockchain rules that any town respect.
At a time: Rules are manage in Contracts.
* A pagan belong to only 1 tribe.
* A tribe belong to only 1 town. .models/Setup.js is the interface of this model, to create a node/town for dev that is an unchain town or for production that is a chain town (real node) [process of setup] (https://gitea.ndda.fr/apxtrib/apxtrib/wiki/Setup)
* A town belong to only 1 nation.
A pagan have an uuid + public key + private key and belong to only one tribe at a time optionaly an email + login + psw to recover his login/psw into his tribe. His private key is the only way to prove a user his the owner of an uuid account. No one else than the pagan knows his private key.
The blockchain register only data about pagan (uuid/publickey)
Each town is fully decentralized manage by a pagan with mayor role. At a time:
**A mayor knows** pagans informations from all tribes (uuid, publickey and optionaly: login/hash password and any information store). * A pagan belong to only 1 tribe.
**A Druid rent** a space to the mayor of the town in exchange of anything (fiat currency, services, ...). * A tribe belong to only 1 town.
**Druid knows** all about his user he can ask and store any data (cipher it or not) about pagans hosted in his tribe space. * A town belong to only 1 nation.
With a contract a druid can generate token currency that are valuate by stacking the equivalent of crypto's nation into the mayor wallet. Druid then can distribute as he wants those token to his community of pagan to value Pagans activities.
The blockchain register only data about pagan (uuid/publickey)
A pagan can at any time convert a token in his equivalent in the crypto's nation. Then token's druid are destoyed. Each town is fully decentralized manage by a pagan with mayor role.
A pagan owns data store into the blockchain and can request to move from tribe A to tribe B. By doing this all token owns will be convert to crypto's nation and all specific data will stay the properties of Druid or not(can be removed by him or not but Pagan will have no more access to it). **A mayor knows** pagans informations from all tribes (uuid, publickey and optionaly: login/hash password and any information store).
**A Druid rent** a space to the mayor of the town in exchange of anything (fiat currency, services, ...).
**Druid knows** all about his user he can ask and store any data (cipher it or not) about pagans hosted in his tribe space.
With a contract a druid can generate token currency that are valuate by stacking the equivalent of crypto's nation into the mayor wallet. Druid then can distribute as he wants those token to his community of pagan to value Pagans activities.
### Object Contracts A pagan can at any time convert a token in his equivalent in the crypto's nation. Then token's druid are destoyed.
A contract is a script js that is apply into the blockchain to register important transaction into the social world. A pagan owns data store into the blockchain and can request to move from tribe A to tribe B. By doing this all token owns will be convert to crypto's nation and all specific data will stay the properties of Druid or not(can be removed by him or not but Pagan will have no more access to it).
### Object Tribes
Tribes are localy manage, by a pagan that have mayor role that can Create Delete a ./tribes/tribeId
### Object Contracts
### Object Pagans A contract is a script js that is apply into the blockchain to register important transaction into the social world.
### Object Tribes
Tribes are localy manage, by a pagan that have mayor role that can Create Delete a ./tribes/tribeId
### Object Pagans
Pagans is managed by a pagan that have druid role for his tribe. He can host any other pagan. A pagan can only belong to one tribe Pagans is managed by a pagan that have druid role for his tribe. He can host any other pagan. A pagan can only belong to one tribe