Mise à jour de GitLab prévue ce samedi 23 octobre 2021 à partir de 9h00 CET

Commit dc702149 authored by Cédric Moreau's avatar Cédric Moreau
Browse files

Merge branch 'dev'

parents 9a5aae9a 68f34bb1
......@@ -22,6 +22,7 @@
"no-trailing-spaces": 0,
"no-unused-expressions": 0,
"comma-spacing": 0,
"semi": 0,
"quotes": [0, "double"],
"linebreak-style": [1,"unix"],
......@@ -37,7 +38,6 @@
"no-unused-vars": [1],
"space-infix-ops": [1],
"handle-callback-err": [1],
"semi": [1,"always"],
"no-extra-semi": [1]
},
"env": {
......
This diff is collapsed.
"use strict";
const co = require('co');
const dos2unix = require('../lib/system/dos2unix');
module.exports = function AbstractController (server) {
const logger = require('../lib/logger')('abstractController');
this.pushEntity = (req, rawer, type) => co(function *() {
let rawDocument = rawer(req);
rawDocument = dos2unix(rawDocument);
const written = yield server.writeRaw(rawDocument, type);
try {
return written.json();
} catch (e) {
logger.error('Written:', written);
logger.error(e);
throw e;
}
});
};
"use strict";
const co = require('co');
const _ = require('underscore');
const rules = require('../lib/rules');
const constants = require('../lib/constants');
const http2raw = require('../lib/helpers/http2raw');
const Membership = require('../lib/entity/membership');
const AbstractController = require('./abstract');
module.exports = function (server) {
return new BlockchainBinding(server);
};
function BlockchainBinding (server) {
AbstractController.call(this, server);
const conf = server.conf;
// Services
const ParametersService = server.ParametersService;
const BlockchainService = server.BlockchainService;
const IdentityService = server.IdentityService;
// Models
const Block = require('../lib/entity/block');
const Stat = require('../lib/entity/stat');
this.parseMembership = (req) => this.pushEntity(req, http2raw.membership, constants.ENTITY_MEMBERSHIP);
this.parseBlock = (req) => this.pushEntity(req, http2raw.block, constants.ENTITY_BLOCK);
this.parameters = () => server.dal.getParameters();
this.with = {
newcomers: getStat('newcomers'),
certs: getStat('certs'),
joiners: getStat('joiners'),
actives: getStat('actives'),
leavers: getStat('leavers'),
revoked: getStat('revoked'),
excluded: getStat('excluded'),
ud: getStat('ud'),
tx: getStat('tx')
};
function getStat (statName) {
return () => co(function *() {
let stat = yield server.dal.getStat(statName);
return { result: new Stat(stat).json() };
});
}
this.promoted = (req) => co(function *() {
const number = yield ParametersService.getNumberP(req);
const promoted = yield BlockchainService.promoted(number);
return new Block(promoted).json();
});
this.blocks = (req) => co(function *() {
const params = ParametersService.getCountAndFrom(req);
const count = parseInt(params.count);
const from = parseInt(params.from);
let blocks = yield BlockchainService.blocksBetween(from, count);
blocks = blocks.map((b) => (new Block(b).json()));
return blocks;
});
this.current = () => co(function *() {
const current = yield server.dal.getCurrentBlockOrNull();
if (!current) throw constants.ERRORS.NO_CURRENT_BLOCK;
return new Block(current).json();
});
this.hardship = (req) => co(function *() {
let nextBlockNumber = 0;
const search = yield ParametersService.getSearchP(req);
const idty = yield IdentityService.findMemberWithoutMemberships(search);
if (!idty) {
throw constants.ERRORS.NO_MATCHING_IDENTITY;
}
if (!idty.member) {
throw constants.ERRORS.NOT_A_MEMBER;
}
const current = yield BlockchainService.current();
if (current) {
nextBlockNumber = current ? current.number + 1 : 0;
}
const difficulty = yield server.getBcContext().getIssuerPersonalizedDifficulty(idty.pubkey);
return {
"block": nextBlockNumber,
"level": difficulty
};
});
this.difficulties = () => co(function *() {
const current = yield server.dal.getCurrentBlockOrNull();
const number = (current && current.number) || 0;
const issuers = yield server.dal.getUniqueIssuersBetween(number - 1 - current.issuersFrame, number - 1);
const difficulties = [];
for (const issuer of issuers) {
const member = yield server.dal.getWrittenIdtyByPubkey(issuer);
const difficulty = yield server.getBcContext().getIssuerPersonalizedDifficulty(member.pubkey);
difficulties.push({
uid: member.uid,
level: difficulty
});
}
return {
"block": number + 1,
"levels": _.sortBy(difficulties, (diff) => diff.level)
};
});
this.memberships = (req) => co(function *() {
const search = yield ParametersService.getSearchP(req);
const idty = yield IdentityService.findMember(search);
const json = {
pubkey: idty.pubkey,
uid: idty.uid,
sigDate: idty.buid,
memberships: []
};
json.memberships = idty.memberships.map((msObj) => {
const ms = new Membership(msObj);
return {
version: ms.version,
currency: conf.currency,
membership: ms.membership,
blockNumber: parseInt(ms.blockNumber),
blockHash: ms.blockHash,
written: (!ms.written_number && ms.written_number !== 0) ? null : ms.written_number
};
});
json.memberships = _.sortBy(json.memberships, 'blockNumber');
json.memberships.reverse();
return json;
});
this.branches = () => co(function *() {
const branches = yield BlockchainService.branches();
const blocks = branches.map((b) => new Block(b).json());
return {
blocks: blocks
};
});
}
"use strict";
const _ = require('underscore');
const co = require('co');
const Q = require('q');
const http2raw = require('../lib/helpers/http2raw');
const constants = require('../lib/constants');
const Peer = require('../lib/entity/peer');
const AbstractController = require('./abstract');
module.exports = function (server) {
return new NetworkBinding(server);
};
function NetworkBinding (server) {
AbstractController.call(this, server);
// Services
const MerkleService = server.MerkleService;
const PeeringService = server.PeeringService;
this.cert = PeeringService.cert;
this.peer = () => co(function *() {
const p = yield PeeringService.peer();
if (!p) {
throw constants.ERRORS.SELF_PEER_NOT_FOUND;
}
return p.json();
});
this.peersGet = (req) => co(function *() {
let merkle = yield server.dal.merkleForPeers();
return yield MerkleService.processForURL(req, merkle, (hashes) => {
return co(function *() {
try {
let peers = yield server.dal.findPeersWhoseHashIsIn(hashes);
const map = {};
peers.forEach((peer) => {
map[peer.hash] = Peer.statics.peerize(peer).json();
});
if (peers.length == 0) {
throw constants.ERRORS.PEER_NOT_FOUND;
}
return map;
} catch (e) {
throw e;
}
});
});
});
this.peersPost = (req) => this.pushEntity(req, http2raw.peer, constants.ENTITY_PEER);
this.peers = () => co(function *() {
let peers = yield server.dal.listAllPeers();
return {
peers: peers.map((p) => {
return _.pick(p,
'version',
'currency',
'status',
'first_down',
'last_try',
'pubkey',
'block',
'signature',
'endpoints');
})
};
});
}
"use strict";
const co = require('co');
module.exports = function (server) {
return new NodeBinding(server);
};
function NodeBinding (server) {
this.summary = () => {
return {
"duniter": {
"software": "duniter",
"version": server.version,
"forkWindowSize": server.conf.forksize
}
};
};
this.sandboxes = () => co(function*() {
return {
identities: yield sandboxIt(server.dal.idtyDAL.sandbox),
certifications: yield sandboxIt(server.dal.certDAL.sandbox),
memberships: yield sandboxIt(server.dal.msDAL.sandbox),
transactions: yield sandboxIt(server.dal.txsDAL.sandbox)
};
});
}
function sandboxIt(sandbox) {
return co(function*() {
return {
size: sandbox.maxSize,
free: yield sandbox.getSandboxRoom()
};
});
}
"use strict";
const co = require('co');
const _ = require('underscore');
const http2raw = require('../lib/helpers/http2raw');
const Transaction = require('../lib/entity/transaction');
const constants = require('../lib/constants');
const AbstractController = require('./abstract');
module.exports = function (server) {
return new TransactionBinding(server);
};
function TransactionBinding(server) {
AbstractController.call(this, server);
const conf = server.conf;
// Services
const ParametersService = server.ParametersService;
// Models
const Source = require('../lib/entity/source');
this.parseTransaction = (req) => this.pushEntity(req, http2raw.transaction, constants.ENTITY_TRANSACTION);
this.getSources = (req) => co(function *() {
const pubkey = yield ParametersService.getPubkeyP(req);
const sources = yield server.dal.getAvailableSourcesByPubkey(pubkey);
const result = {
"currency": conf.currency,
"pubkey": pubkey,
"sources": []
};
sources.forEach(function (src) {
result.sources.push(new Source(src).json());
});
return result;
});
this.getHistory = (req) => co(function *() {
const pubkey = yield ParametersService.getPubkeyP(req);
return getFilteredHistory(pubkey, (results) => results);
});
this.getHistoryBetweenBlocks = (req) => co(function *() {
const pubkey = yield ParametersService.getPubkeyP(req);
const from = yield ParametersService.getFromP(req);
const to = yield ParametersService.getToP(req);
return getFilteredHistory(pubkey, (res) => {
const histo = res.history;
histo.sent = _.filter(histo.sent, function(tx){ return tx && tx.block_number >= from && tx.block_number <= to; });
histo.received = _.filter(histo.received, function(tx){ return tx && tx.block_number >= from && tx.block_number <= to; });
_.extend(histo, { sending: [], receiving: [] });
return res;
});
});
this.getHistoryBetweenTimes = (req) => co(function *() {
const pubkey = yield ParametersService.getPubkeyP(req);
const from = yield ParametersService.getFromP(req);
const to = yield ParametersService.getToP(req);
return getFilteredHistory(pubkey, (res) => {
const histo = res.history;
histo.sent = _.filter(histo.sent, function(tx){ return tx && tx.time >= from && tx.time <= to; });
histo.received = _.filter(histo.received, function(tx){ return tx && tx.time >= from && tx.time <= to; });
_.extend(histo, { sending: [], receiving: [] });
return res;
});
});
this.getPendingForPubkey = (req) => co(function *() {
const pubkey = yield ParametersService.getPubkeyP(req);
return getFilteredHistory(pubkey, function(res) {
const histo = res.history;
_.extend(histo, { sent: [], received: [] });
return res;
});
});
this.getPending = (req) => co(function *() {
const pending = yield server.dal.getTransactionsPending();
const res = {
"currency": conf.currency,
"pending": pending
};
pending.map(function(tx, index) {
pending[index] = _.omit(new Transaction(tx).json(), 'currency', 'raw');
});
return res;
});
const getFilteredHistory = (pubkey, filter) => co(function*() {
let history = yield server.dal.getTransactionsHistory(pubkey);
let result = {
"currency": conf.currency,
"pubkey": pubkey,
"history": history
};
_.keys(history).map((key) => {
history[key].map((tx, index) => {
history[key][index] = _.omit(new Transaction(tx).json(), 'currency', 'raw');
_.extend(history[key][index], {block_number: tx && tx.block_number, time: tx && tx.time});
});
});
return filter(result);
});
return this;
}
"use strict";
const co = require('co');
const Q = require('q');
const _ = require('underscore');
module.exports = function (server) {
return new UDBinding(server);
};
function UDBinding(server) {
const conf = server.conf;
// Services
const ParametersService = server.ParametersService;
// Models
const Source = require('../lib/entity/source');
this.getHistory = (req) => co(function *() {
const pubkey = yield ParametersService.getPubkeyP(req);
return getUDSources(pubkey, (results) => results);
});
this.getHistoryBetweenBlocks = (req) => co(function *() {
const pubkey = yield ParametersService.getPubkeyP(req);
const from = yield ParametersService.getFromP(req);
const to = yield ParametersService.getToP(req);
return getUDSources(pubkey, (results) => {
results.history.history = _.filter(results.history.history, function(ud){ return ud.block_number >= from && ud.block_number <= to; });
return results;
});
});
this.getHistoryBetweenTimes = (req) => co(function *() {
const pubkey = yield ParametersService.getPubkeyP(req);
const from = yield ParametersService.getFromP(req);
const to = yield ParametersService.getToP(req);
return getUDSources(pubkey, (results) => {
results.history.history = _.filter(results.history.history, function(ud){ return ud.time >= from && ud.time <= to; });
return results;
});
});
function getUDSources(pubkey, filter) {
return co(function *() {
const history = yield server.dal.getUDHistory(pubkey);
const result = {
"currency": conf.currency,
"pubkey": pubkey,
"history": history
};
_.keys(history).map((key) => {
history[key].map((src, index) => {
history[key][index] = _.omit(new Source(src).UDjson(), 'currency', 'raw');
_.extend(history[key][index], { block_number: src && src.block_number, time: src && src.time });
});
});
return filter(result);
});
}
return this;
}
"use strict";
const co = require('co');
const _ = require('underscore');
const http2raw = require('../lib/helpers/http2raw');
const constants = require('../lib/constants');
const AbstractController = require('./abstract');
const logger = require('../lib/logger')();
module.exports = function (server) {
return new WOTBinding(server);
};
function WOTBinding (server) {
AbstractController.call(this, server);
const ParametersService = server.ParametersService;
const IdentityService = server.IdentityService;
const BlockchainService = server.BlockchainService;
const Identity = require('../lib/entity/identity');
this.lookup = (req) => co(function *() {
// Get the search parameter from HTTP query
const search = yield ParametersService.getSearchP(req);
// Make the research
const identities = yield IdentityService.searchIdentities(search);
// Entitify each result
identities.forEach((idty, index) => identities[index] = new Identity(idty));
// Prepare some data to avoid displaying expired certifications
for (const idty of identities) {
const certs = yield server.dal.certsToTarget(idty.pubkey, idty.getTargetHash());
const validCerts = [];
for (const cert of certs) {
const member = yield IdentityService.getWrittenByPubkey(cert.from);
if (member) {
cert.uids = [member.uid];
cert.isMember = member.member;
cert.wasMember = member.wasMember;
} else {
const potentials = yield IdentityService.getPendingFromPubkey(cert.from);
cert.uids = _(potentials).pluck('uid');
cert.isMember = false;
cert.wasMember = false;
}
validCerts.push(cert);
}
idty.certs = validCerts;
const signed = yield server.dal.certsFrom(idty.pubkey);
const validSigned = [];
for (let j = 0; j < signed.length; j++) {
const cert = _.clone(signed[j]);
cert.idty = yield server.dal.getIdentityByHashOrNull(cert.target);
if (cert.idty) {
validSigned.push(cert);
} else {
logger.debug('A certification to an unknown identity was found (%s => %s)', cert.from, cert.to);
}
}
idty.signed = validSigned;
}
if (identities.length == 0) {
throw constants.ERRORS.NO_MATCHING_IDENTITY;
}
const resultsByPubkey = {};
identities.forEach((identity) => {
const jsoned = identity.json();
if (!resultsByPubkey[jsoned.pubkey]) {
// Create the first matching identity with this pubkey in the map
resultsByPubkey[jsoned.pubkey] = jsoned;
} else {
// Merge the identity with the existing(s)
const existing = resultsByPubkey[jsoned.pubkey];
// We add the UID of the identity to the list of already added UIDs
existing.uids = existing.uids.concat(jsoned.uids);
// We do not merge the `signed`: every identity with the same pubkey has the same `signed` because it the *pubkey* which signs, not the identity
}
});
return {
partial: false,
results: Object.values(resultsByPubkey)
};
});
this.members = () => co(function *() {
const identities = yield server.dal.getMembers();
const json = {
results: []
};
identities.forEach((identity) => json.results.push({ pubkey: identity.pubkey, uid: identity.uid }));
return json;
});
this.certifiersOf = (req) => co(function *() {
const search = yield ParametersService.getSearchP(req);
const idty = yield IdentityService.findMemberWithoutMemberships(search);
const certs = yield server.dal.certsToTarget(idty.pubkey, idty.getTargetHash());
idty.certs = [];
for (const cert of certs) {
const certifier = yield server.dal.getWrittenIdtyByPubkey(cert.from);
if (certifier) {
cert.uid = certifier.uid;
cert.isMember = certifier.member;
cert.sigDate = certifier.buid;
cert.wasMember = true; // As we checked if(certified)
if (!cert.cert_time) {