update schema

This commit is contained in:
philc 2023-06-21 09:27:59 +02:00
parent 64ade17aef
commit e3b65831fd
11 changed files with 501 additions and 33 deletions

View File

@ -0,0 +1,164 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css">
<title>Immersive Training</title>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<!-- Navbar -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<a class="navbar-brand" href="#">Immersive Training</a>
</div>
</nav>
<!-- Hero Section -->
<header class="bg-primary text-white text-center py-5">
<h1 class="display-4">Acquire Operational Know-How</h1>
<p class="lead">Join our immersive training program and become proficient in your field.</p>
<a href="#contact" class="btn btn-light btn-lg">Contact Us</a>
</header>
<section id="bootcamp-offer" class="py-5">
<div class="container">
<h2 class="text-center mb-5">Entrepreneur Bootcamp: Launch Your Business with AI Tools</h2>
<p><strong>Target:</strong> Higher level of education comfortable with office tools, having an entrepreneurial
project.</p>
<p>An assessment questionnaire is required to select a maximum of 6 candidates.</p>
<p><strong>Objective of the 5 days:</strong> Be ready to launch your business with digital tools and start
independently with minimal expenses.</p>
<ul class="nav nav-pills mb-4" id="bootcamp-tabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="monday-tab" data-bs-toggle="pill" data-bs-target="#monday" type="button"
role="tab" aria-controls="monday" aria-selected="true">Monday</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="tuesday-tab" data-bs-toggle="pill" data-bs-target="#tuesday" type="button"
role="tab" aria-controls="tuesday" aria-selected="false">Tuesday</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="wednesday-tab" data-bs-toggle="pill" data-bs-target="#wednesday" type="button"
role="tab" aria-controls="wednesday" aria-selected="false">Wednesday</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="thursday-tab" data-bs-toggle="pill" data-bs-target="#thursday" type="button"
role="tab" aria-controls="thursday" aria-selected="false">Thursday</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="friday-tab" data-bs-toggle="pill" data-bs-target="#friday" type="button"
role="tab" aria-controls="friday" aria-selected="false">Friday</button>
</li>
</ul>
<div class="tab-content" id="bootcamp-content">
<div class="tab-pane fade show active" id="monday" role="tabpanel" aria-labelledby="monday-tab">
<h4>Monday</h4>
<ul>
<li>10 min Pitch of each project.</li>
<li>Business plan challenge method and introduction to chatgpt.</li>
<li>Evaluate your business model with chatgpt and refine your pitch.</li>
<li>Google search techniques to stay updated and find relevant information.</li>
<li>Create your graphic charter for email tools, brochures, business cards, and website (domain name, logo,
color code, fonts).</li>
</ul>
</div>
<div class="tab-pane fade" id="tuesday" role="tabpanel" aria-labelledby="tuesday-tab">
<h4>Tuesday</h4>
<ul>
<li>Register your domain name, create and host your web page adapted to your business model.</li>
<li>Learn how to update and manage your web page for effective SEO.</li>
<li>Use AI to optimize SEO and generate your pitches.</li>
<li>Use AI to generate visually appealing content.</li>
</ul>
</div>
<div class="tab-pane fade" id="wednesday" role="tabpanel" aria-labelledby="wednesday-tab">
<h4>Wednesday</h4>
<ul>
<li>Tips & tricks to easily animate your pages and make your one-page website come alive (add a contact
form, etc.).</li>
<li>Install visitor tracking tools to understand your visitors' expectations.</li>
<li>Open an email box with your domain name, use a CRM to launch your prospecting.</li>
<li>Build your contact database, automate your emails, and create customizable sales emails with AI.</li>
</ul>
</div>
<div class="tab-pane fade" id="thursday" role="tabpanel" aria-labelledby="thursday-tab">
<h4>Thursday</h4>
<ul>
<li>Explore social networks adapted to the group (Google My Business, LinkedIn, Facebook, YouTube, TikTok,
etc.).</li>
<li>Create accounts, prepare post charters, and automate marketing campaigns (network, email, SMS) with AI.
</li>
</ul>
</div>
<div class="tab-pane fade" id="friday" role="tabpanel" aria-labelledby="friday-tab">
<h4>Friday</h4>
<ul>
<li>New pitch from each participant.</li>
<li>Deepening according to the expectations of the group.</li>
</ul>
</div>
</div>
</div>
</section>
<!-- Contact Section -->
<section id="contact" class="py-5">
<div class="container">
<h2 class="text-center mb-5">Contact Us</h2>
<form>
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control" id="name" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" required>
</div>
<div class="mb-3">
<label for="message" class="form-label">Message</label>
<textarea class="form-control" id="message" rows="5" required></textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</section>
<!-- Booking and Payment Section -->
<section class="bg-light py-5">
<div class="container">
<h2 class="text-center mb-5">Book Your Spot</h2>
<div class="row">
<div class="col-md-6">
<h3>Training Details</h3>
<p>Location: Troo 41800, 30 minutes from Vendome</p>
<p>Date: [Insert Training Date]</p>
<p>Price: €1500 (€1250 in Bitcoin)</p>
</div>
<div class="col-md-6">
<h3>Payment</h3>
<!-- Add Stripe integration code here -->
<button class="btn btn-primary">Pay with Stripe</button>
</div>
</div>
</div>
</section>
<!-- Footer -->
<footer class="bg-dark text-white text-center py-3">
<p>&copy; 2023 Immersive Training. All rights reserved.</p>
</footer>
<script src="https://js.stripe.com/v3/"></script> <!-- Stripe JS library -->
</body>
</html>

View File

@ -1 +0,0 @@
{}

View File

@ -0,0 +1,15 @@
{
"title": "Une Personne au niveau d'une tribut avec des informations personnelle",
"description": "Un alias peut se stoquer comme un objet Person avec des informations supplémentaire permettant de qualifier son profil",
"properties": {
"alias": {"title":"Une identité numérique d'apxtrib"},
"dt_create": {"title":"Date de creation de cette personne"},
"dt_update": { "title":"Date de derniére mise à jour"},
"dt_lastlogin": { "title":"Date de derniere authentification" },
"dt_close": { "title": "Date de fermeture de compte" },
"recoveryauth":{"title":"Information pour recuperer ses codes d'accès"},
"biography": {"title":"Description courte"},
"imgavatar": {"title":"Url de l'image utilisée comme avatar"},
"accessrights": {"title":"Droits d'accès"}
}
}

View File

@ -0,0 +1,10 @@
{
"title": "Contiens la cle privée avec un email de recovery",
"description": "Cs trouve au niveau d'une person (sous la responsabilité d'une tribut et permet pour un alias de recevoir par email une clé privée",
"properties":{
"email": { "title":"email de recuperation" },
"alias": {"title": "Alias qui doit exister comme une Person dans une tribu"},
"privatekey": { "title": "Private key link to alias" },
"passphrase": {"title":"Passphrase to uncipher privatekey"}
}
}

View File

@ -10,22 +10,47 @@
"minLength": 5, "minLength": 5,
"pattern": "^[a-z0-9]*$" "pattern": "^[a-z0-9]*$"
}, },
"owner": {
"title": "Alias that own this object",
"type": "string",
"format": "Alias"
},
"dt_create": { "dt_create": {
"type": "string", "type": "string",
"format": "datetime", "format": "datetime",
"default": "dayjs.now()" "default": "dayjs.now()"
}, },
"dt_update": { "type": "string", "format": "datetime" }, "dt_update": {
"dt_lastlogin": { "type": "string", "format": "datetime" }, "type": "string",
"dt_close": { "type": "string", "format": "datetime" }, "format": "datetime"
"recovery": {
"type": "object",
"$ref": {
"email": { "type": "string", "format": "email" },
"privatekey": { "type": "string", "format": "eccCorve25519armored" }
}
}, },
"recoveryauth":{"type":"object","$ref":""}, "dt_lastlogin": {
"type": "string",
"format": "datetime"
},
"dt_close": {
"type": "string",
"format": "datetime"
},
"recoveryauth": {
"type": "object",
"$ref": "schema/recoveryauth.json"
},
"firstname": {
"type": "string"
},
"lastname": {
"type": "string"
},
"dt_birth":{
"type":"string",
"format":"date"
},
"gender":{
"type":"string",
"enum":[ "M","MME","OTHER"]
},
"emailcom":{"type":"string","format":"email"},
"biography": { "biography": {
"type": "string", "type": "string",
"pattern": "^.{O,150}$" "pattern": "^.{O,150}$"
@ -34,15 +59,28 @@
"type": "string" "type": "string"
}, },
"accessrights": { "accessrights": {
"type": "object", "title": "Accessright per Object or per Object.key belonging to tribe",
"$ref": "nationchains/schema/accessright.json" "description": "A Person has to exist and want to create read update delete, if Own means if owner = alias of user requested some CRUD action to owner then he can act on this object or object.key",
"description": "List of Object with CRUDO value like {Person:'RUDO',"Person.recoveryauth":'O',...}",
"type": "object"
} }
}, },
"required": ["alias", "accessright"], "required": [
"alias",
"accessright"
],
"apxprimarykey": "alias", "apxprimarykey": "alias",
"apxunique": [""], "apxunique": [
""
],
"apxsearchindex": [ "apxsearchindex": [
{ "key": "alias", "value": [] }, {
{ "key": "recovery.email", "value": "alias" } "key": "alias",
"value": []
},
{
"key": "recovery.email",
"value": "alias"
}
] ]
} }

View File

@ -0,0 +1,11 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "/schema/recoveryauth",
"title": "Store numeric identity to recover it by email",
"description": "This object store numeric identity alias with an email mainly used at Person level to recover by email a private and passphrase key associate to alias",
"properties":{
"email": { "type": "string", "format": "email" },
"alias": {"type": "string", "format":"Pagan"},
"privatekey": { "type": "string", "format": "eccCorve25519armored" }
}
}

View File

@ -0,0 +1,8 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "/schema/person",
"title": "Person minimum definition to link a person to a pagan identity",
"description": "A person is a human with a apxtrib identity (Public Private Key. Information stored (not cipher) for a person are only visible from the town's Mayor and the tribe's Druid. You need at least trus the druid that trust the mayor (for sensitive data Mayor and Druid can be the same apx Identity.) Only a pagan that have the privateKey can read cipher data. The purpose of this sschema is to link a person to a tribe and manage basic activities, profil will be a tribe object if need more personnal information",
"type": "object",
"properties": {}
}

View File

@ -0,0 +1,17 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "/schema/seeker",
"title": "Data Profil of a person that is in a seek process",
"description": "All those data have to store any useffull logistical data and profil about a seeker (skill, ...) ",
"type": "object",
"properties": {
"emailseek":{"type":"string","format":"email"},
"mainlivinglocation":{"type":"object","$ref":"https://schema.org/PostalAddress"},
"secondlivinglocation":{"type":"object","$ref":"https://schema.org/PostalAddress"},
"thirdlivinglocation":{"type":"object","$ref":"https://schema.org/PostalAddress"},
"seekcriterias":{"type":"array","$ref":"schema/seekcriteria.json"},
"skills":{"type":"array","$ref":"schema/skills.json"},
"educations":{"type":"array","$ref":"schema/educations.json"},
"experiences":{"type":"array","$ref":"schema/experiences.json"}
}
}

View File

@ -8,15 +8,22 @@ towns.loadtpldata = () => {
// adapte tpldata to template tpl // adapte tpldata to template tpl
const dataowner = apx.data.tpldata.setup; const dataowner = apx.data.tpldata.setup;
dataowner.alias=apx.data.headers.xalias; dataowner.alias=apx.data.headers.xalias;
dataowner.auth = dataowner.alias=="anonymous"; dataowner.auth = dataowner.alias!="anonymous";
dataowner.devtown = dataowner.townId == "devfarm"; dataowner.devtown = dataowner.townId == "devfarm";
if (dataowner.mayorid) dataowner.owner = dataowner.mayorid == dataowner.alias; if (dataowner.mayorid) dataowner.owner = dataowner.mayorid == dataowner.alias;
console.log('Data return to template',dataowner) console.log('Data return to template',dataowner)
return dataowner; return dataowner;
}; };
towns.owntown = () => { towns.owntown = (newowner) => {
// only the owner can give ownership to someone else // only the owner can give ownership to someone else
if (!newowner) {newowner=apx.data.headers.xalias}
axios.get(`api/towns/changeowner/${newowner}`,{ headers: apx.data.headers }).then(rep=>{
console.log(rep)
apx.data.tpldata.setup.moyorId=newowner;
apx.save();
app.load('apxmain','townowner',towns.loadtpldata())
}).catch(err=>{
console.log(err)
})
}; };

View File

@ -1,13 +1,45 @@
const bcrypt = require( 'bcrypt' ); const bcrypt = require("bcrypt");
const fs = require( 'fs-extra' ); const fs = require("fs-extra");
const glob = require( 'glob' ); const glob = require("glob");
const moment = require( 'moment' ); const moment = require("moment");
const jwt = require( 'jwt-simple' ); const jwt = require("jwt-simple");
const UUID = require( 'uuid' ); const UUID = require("uuid");
const conf=require(`${process.env.dirtown}/conf.json`) const conf = require(`${process.env.dirtown}/conf.json`);
const Checkjson = require(`./Checkjson.js`); const Checkjson = require(`./Checkjson.js`);
const Towns = {}; const Towns = {};
Towns.changeowner = (newowner, requestby) => {
/**
*
*/
if (!fs.existsSync(`./nationchains/pagans/itm/${newowner}.json`)) {
return {
status: 404,
ref: "towns",
msg: "newownerdoesnotexist",
data: { alias: newowner },
};
}
if (!conf.mayorId || conf.mayorId == requestby) {
// update object town + town/conf.json + setup_xx.json
conf.mayorId = newowner;
fs.outputJsonSync(`${process.env.dirtown}/conf.json`, conf);
const setup = fs.readJSONSync(`${dirapi}/adminapi/www/adminapx/conf/setup_xx.json`)
setup.mayorId=newowner;
fs.outputJsonSync(`${dirapi}/adminapi/www/adminapx/conf/setup_xx.json`,setup);
return {
status: 200,
ref: "towns",
msg: "newownerchangesusccess",
data: { alias: newowner },
};
}
return {
status: 403,
ref: "towns",
msg: "notallow",
data: { newowner, currentowner: conf.mayorId },
};
};
module.exports = Towns; module.exports = Towns;

167
api/routes/towns.js Executable file
View File

@ -0,0 +1,167 @@
const express = require("express");
const path = require("path");
// Classes
const Towns = require("../models/Towns.js");
const Notifications = require("../models/Notifications.js");
// Middlewares
const checkHeaders = require("../middlewares/checkHeaders");
const isAuthenticated = require("../middlewares/isAuthenticated");
const hasAccessrighton = require("../middlewares/hasAccessrighton");
const router = express.Router();
/*
*/
router.get("/changeowner/:alias",checkHeaders, isAuthenticated, (req, res) => {
/**
* @api {get} /towns/ownershipr/:alias
* @apiName Change owner of a town mayorId
* @apiGroup Pagans
* @param {string} alias an alias that will become owner of a town
* @apiSuccess (200) {object} {ref:"towns",msg:"ownerchangesuccess",data: { alias } }
* @apiError (404) {object} {ref:"towns",msg:"aliasnotallow",data: { alias} }
*
**/
res.send(Towns.changeowner(req.params.alias, req.session.header.alias));
});
router.get("/person/:alias", checkHeaders, isAuthenticated, (req, res) => {
/**
* @api {get} /pagans/person:alias
* @apiName Is register check xalias and xhash
* @apiGroup Pagans
* @apiUse apxHeader
* @param {string} alias that exist
* @param {string} tribeId that exist with a person alias
* @apiSuccess (200) {ref:"pagans",msg:"personexist",data: { person } }
* @apiError (404) {ref:"pagans",msg:"persondoesnotexist",data: { person } }
*
* @todo check accessright for req.session.header.xalias to see if jhe can get person data
* if req.param.alias == req.session.header.xalias => Owner
* else need accessright to on person set at R
* */
res.send(Pagans.getperson(req.params.alias, req.session.header.xtribe));
});
router.get("/isauth", checkHeaders, isAuthenticated, (req, res) => {
/**
* @api {get} /pagans/isauth
* @apiName Is register check xalias and xhash
* @apiGroup Pagans
* @apiUse apxHeader
*
* @apiError (400) {object} status missingheaders / xalias does not exist / signaturefailled
* @apiError (401) {object} alias anonymous (not authenticated)
* @apiError (404) {string} tribe does not exist
*
* @apiSuccess (200) {object} data contains indexfile requested
*
*/
res.send({
status: 200,
ref: "headers",
msg: "authenticated",
data: {
xalias: req.session.header.xalias,
},
});
});
router.post("/", checkHeaders, isAuthenticated, (req, res) => {
/**
* @api {post} /pagans
* @apiName Is register check xalias and xhash
* @apiGroup Pagans
* @apiUse apxHeader
*
* Create a pagan account from alias, publickey, if trusted recovery =>
* Create a person in xtribe/person/xalias.json with profil.auth={email,privatekey, passphrase}
* Middleware isAuthenticated check that:
* - xhash is well signed from private key linked to the publickey of alias
* - check that alias does not already exist (if yes then verifiedsigne would be false)
* Need to wait next block chain to be sure that alias is register in the blokchain
*/
console.log("pass ici", req.body);
const feedback = { alias: req.body.alias, publickey: req.body.publickey };
const newpagan = Pagans.create(req.body.alias, req.body.publickey);
if (newpagan.status == 200) {
if (req.body.email) {
feedback.withemail = true;
feedback.email = req.body.email;
feedback.privatekey = req.body.privatekey;
feedback.passphrase = req.body.passphrase;
Notifications.send({
type: "email",
from: "",
dest: [req.body.email],
tpl: "registeremail",
tribe: req.session.header.xtribe,
data: feedback,
});
}
if (req.body.trustedtribe) {
if (req.app.locals.tribeids.includes(req.body.trustedtribe)) {
delete feedback.withemail;
const persondata = { recovery: feedback };
res.send(
Pagans.personupdate(req.body.alias, req.body.trustedtribe, persondata)
);
} else {
res.send({
status: 404,
ref: "Pagans",
msg: "tribedoesnotexist",
data: { tribe: req.body.trustedtribe },
});
}
} else {
newpagan.data = feedback;
res.send(newpagan);
}
} else {
//error to create pagan
res.send(newpagan);
}
});
router.put("/person", checkHeaders, isAuthenticated, (req, res) => {
/**
* @api {put} /pagans/person
* @apiName Is register check xalias and xhash
* @apiGroup Pagans
* @apiUse apxHeader
*
* add/update a person = alias + tribe with specific accessright and specific schema link to tribe
* @todo add tribe/schema/person.json
*/
console.log(req.body);
res.send(
Pagans.personupdate(req.body.alias, req.session.header.xtribe, req.body)
);
});
router.delete("/:alias", checkHeaders, isAuthenticated, (req, res) => {
/**
* @api {delete} /pagans/:alias
* @apiName Is register check xalias and xhash
* @apiGroup Pagans
* @apiUse apxHeader
* */
console.log(`DELETE pagans nationchains/pagans/${req.params.alias}.json`);
const result = Pagans.delete(req.params.id, req.session.header);
res.status(result.status).send(result.data);
});
router.get("/keyrecovery/:tribeid/:email", checkHeaders, (req, res) => {
/**
* @api {get} /pagans/keyrecovery/tribe/email
* @apiName apxtrib
* @apiGroup Pagans
*
*
*
* @apiError (400) {object} status missingheaders / xalias does not exist / signaturefailled
* @apiError (401) {object} alias anonymous (not authenticated)
* @apiError (404) {string} tribe does not exist
*
* @apiSuccess (200) {object} data contains indexfile requested
*
*/
res.send(Pagans.keyrecovery(req.params.tribeId, req.params.email));
});
module.exports = router;