moeralib
Version:
Library to interact with Moera decentralized social network
126 lines (125 loc) • 5.6 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MoeraCarteSource = exports.MoeraCartesError = void 0;
exports.generateCarte = generateCarte;
const crypto_1 = __importDefault(require("crypto"));
const util_1 = require("util");
const types_1 = require("./types");
const fingerprints_1 = require("./fingerprints");
const crypto_2 = require("../crypto");
/**
* Error obtaining valid cartes.
*/
class MoeraCartesError extends Error {
/**
* @param {string} message - error message
*/
constructor(message) {
super(message);
}
}
exports.MoeraCartesError = MoeraCartesError;
/**
* Class that gets cartes from the given node, caches them and supplies them for authentication.
*/
class MoeraCarteSource {
/**
* @param {MoeraNode} node node to get cartes from
* @param {Scope[] | null} clientScope permissions to be granted to the cartes; if not set, all permissions of
* the cartes' owner are granted
* @param {Scope[] | null} adminScope additional administrative permissions (of those granted to the cartes' owner
* by the target node) to be granted to the cartes
* @param {string | null} targetNodeName if set, the cartes are valid for authentication on the specified node only
*/
constructor(node, clientScope = null, adminScope = null, targetNodeName = null) {
this.cartes = [];
this.node = node;
this.clientScope = clientScope !== null && clientScope !== void 0 ? clientScope : ["all"];
this.adminScope = adminScope !== null && adminScope !== void 0 ? adminScope : [];
this.targetNodeName = targetNodeName;
}
/**
* Force renewing the cached list of cartes.
*/
renew() {
return __awaiter(this, void 0, void 0, function* () {
const attributes = {
clientScope: this.clientScope,
adminScope: this.adminScope,
nodeName: this.targetNodeName
};
this.cartes = (yield this.node.createCartes(attributes)).cartes;
});
}
/**
* Get a valid carte. Use one of the cached ones, if possible.
*
* @return {Promise<string>} the carte
*/
getCarte() {
return __awaiter(this, void 0, void 0, function* () {
for (const renewed of [false, true]) {
const now = Math.floor(Date.now() / 1000);
this.cartes = this.cartes.filter(c => c.deadline > now);
if (this.cartes.length === 0) {
if (renewed) {
throw new MoeraCartesError("Could not obtain a valid carte from the node");
}
yield this.renew();
continue;
}
for (const c of this.cartes) {
if (c.beginning <= now) {
return c.carte;
}
}
throw new MoeraCartesError("Could not obtain a carte valid for now");
}
throw new MoeraCartesError("Could not obtain a carte valid for now");
});
}
}
exports.MoeraCarteSource = MoeraCarteSource;
function toScopeMask(scope) {
let mask = 0;
for (const sc of scope) {
mask |= types_1.SCOPE_VALUES[sc];
}
return mask;
}
/**
* Generate a carte with the given parameters and sign it with the provided private signing key.
*
* @param {string | null} ownerName - name of the node authenticating with the carte
* @param {crypto.KeyObject} signingKey - the private signing key to sign the carte
* @param {number} beginning - timestamp of the beginning of the carte's life
* @param {GenerateCarteOptions} options - carte options
* @return {Promise<string>} the carte
*/
function generateCarte(ownerName_1, signingKey_1, beginning_1) {
return __awaiter(this, arguments, void 0, function* (ownerName, signingKey, beginning, { ttl = 600, address = null, nodeName = null, clientScope = types_1.SCOPE_VALUES["all"], adminScope = 0 } = {}) {
if (Array.isArray(clientScope)) {
clientScope = toScopeMask(clientScope);
}
if (Array.isArray(adminScope)) {
adminScope = toScopeMask(adminScope);
}
const addresses = address == null ? null : Array.isArray(address) ? address : [address];
const salt = yield (0, util_1.promisify)(crypto_1.default.randomBytes)(8);
const fingerprint = (0, fingerprints_1.createCarteFingerprint3)(ownerName, addresses, beginning, beginning + ttl, nodeName, clientScope, adminScope, salt);
const signature = (0, crypto_2.signFingerprint)(fingerprint, signingKey);
return Buffer.concat([fingerprint, signature]).toString("base64url");
});
}