reshuffle-eidr-connector
Version:
Reshuffle connectors for eidr.org
411 lines • 23.9 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
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 __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
exports.__esModule = true;
exports.EIDRConnector = void 0;
var crypto_1 = __importDefault(require("crypto"));
var xml2js_1 = __importDefault(require("xml2js"));
var node_fetch_1 = __importDefault(require("node-fetch"));
var reshuffle_base_connector_1 = require("reshuffle-base-connector");
var validate_1 = require("./validate");
var jsonQuery_1 = require("./jsonQuery");
var jsonPopulateValue_1 = require("./jsonPopulateValue");
var availableApiVersions = ['2.6.0', '2.7.0', '2.7.1'];
var eidrApiVersion = '2.7.1';
// eslint-disable-next-line @typescript-eslint/no-var-requires
var eidrConnectorVersion = require('../package.json').version;
var GraphTraversalTypes;
(function (GraphTraversalTypes) {
GraphTraversalTypes["FindAncestors"] = "FindAncestors";
GraphTraversalTypes["FindDescendants"] = "FindDescendants";
GraphTraversalTypes["GetDependents"] = "GetDependents";
GraphTraversalTypes["GetSeriesAncestry"] = "GetSeriesAncestry";
GraphTraversalTypes["GetLightweightRelationships"] = "GetLightweightRelationships";
GraphTraversalTypes["GetRemotestAncestor"] = "GetRemotestAncestor";
GraphTraversalTypes["GetLeafDescendants"] = "GetLeafDescendants";
GraphTraversalTypes["GetParent"] = "GetParent";
GraphTraversalTypes["GetChildren"] = "GetChildren";
})(GraphTraversalTypes || (GraphTraversalTypes = {}));
var EIDRError = /** @class */ (function (_super) {
__extends(EIDRError, _super);
function EIDRError(message, status, details) {
if (details === void 0) { details = message; }
var _this = _super.call(this, "EIDRConnector: ".concat(message)) || this;
_this.status = status;
_this.details = details;
return _this;
}
return EIDRError;
}(Error));
var Authorization = /** @class */ (function () {
function Authorization(credentials) {
this.headers = {};
this.registered = false;
function validate(tag, value) {
if (typeof value !== 'string' || value.trim().length === 0) {
throw new EIDRError("Invalid ".concat(tag), 401);
}
return value.trim();
}
if (typeof credentials === 'string') {
if (!/^Eidr [^\s]+:[^\s]+:[^\s]+$/.test(credentials)) {
throw new EIDRError('Invalid credentials string', 401);
}
var _a = credentials.substr(5).split(':'), userId = _a[0], partyId = _a[1], shadow = _a[2];
this.headers = { Authorization: "Eidr ".concat(userId, ":").concat(partyId, ":").concat(shadow) };
this.registered = true;
}
else if (credentials.userId) {
var userId = validate('userId', credentials.userId);
var partyId = validate('partyId', credentials.partyId);
var shadow = void 0;
if (credentials.password) {
var password = validate('password', credentials.password);
shadow = crypto_1["default"].createHash('md5').update(password).digest('base64');
}
else if (credentials.shadow) {
shadow = validate('shadow', credentials.shadow);
}
else {
throw new EIDRError('Missing password', 401, 'Password of shadow must be part of credentials');
}
this.headers = { Authorization: "Eidr ".concat(userId, ":").concat(partyId, ":").concat(shadow) };
this.registered = true;
}
var domain = typeof credentials === 'string' || !credentials.domain ?
'resolve.eidr.org' :
validate('domain', credentials.domain);
this.endpoint = "https://".concat(domain, "/EIDR/");
}
return Authorization;
}());
var EIDRConnector = /** @class */ (function (_super) {
__extends(EIDRConnector, _super);
function EIDRConnector(app, options, id) {
if (options === void 0) { options = {}; }
var _this = _super.call(this, app, options, id) || this;
_this.authorization = new Authorization(options);
_this.xmlOptions = {
trim: true,
explicitArray: false
};
return _this;
}
EIDRConnector.prototype.renderOperationRequest = function (operation) {
return "\n <Request xmlns=\"http://www.eidr.org/schema\">\n <Operation>\n ".concat(operation, "\n </Operation>\n </Request>\n ");
};
EIDRConnector.prototype.renderQueryRequest = function (query, opts) {
return this.renderOperationRequest("\n <Query>\n ".concat(opts.root ? "<ID>".concat(opts.root, "</ID>") : '', "\n <Expression><![CDATA[").concat(query, "]]></Expression>\n <PageNumber>").concat(opts.pageNumber || 1, "</PageNumber>\n <PageSize>").concat(opts.pageSize || 25, "</PageSize>\n </Query>\n "));
};
EIDRConnector.prototype.renderGraphTraversalRequest = function (id, graphRequest) {
return this.renderOperationRequest("\n <".concat(graphRequest, ">\n <ID>").concat(id, "</ID>\n </").concat(graphRequest, ">\n "));
};
// May be needed in the future
// private renderRelationshipsRequest(id: string) {
// return this.renderOperationRequest(`
// <GetLightweightRelationships>
// <ID>${id}</ID>
// </GetLightweightRelationships>
// `)
// }
EIDRConnector.prototype.request = function (method, path, auth, body, customEidrVersion) {
if (auth === void 0) { auth = this.authorization; }
return __awaiter(this, void 0, void 0, function () {
var res, xml;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, (0, node_fetch_1["default"])(auth.endpoint + path, __assign({ method: method, headers: __assign(__assign({}, auth.headers), { 'Content-Type': 'text/xml', 'EIDR-Version': customEidrVersion || eidrApiVersion }) }, (body ? { body: body } : {})))];
case 1:
res = _a.sent();
if (res.status !== 200) {
throw new EIDRError('API error', res.status, "HTTP error accessing EIDR registry API: ".concat(res.status, " ").concat(res.statusText));
}
return [4 /*yield*/, res.text()];
case 2:
xml = _a.sent();
return [2 /*return*/, xml2js_1["default"].parseStringPromise(xml, this.xmlOptions)];
}
});
});
};
// Actions ////////////////////////////////////////////////////////
EIDRConnector.prototype.info = function () {
return {
eidrApiVersion: eidrApiVersion,
eidrConnectorVersion: eidrConnectorVersion,
availableApiVersions: availableApiVersions
};
};
EIDRConnector.prototype.graphTraversal = function (id, graphRequest, credentials, apiVersion) {
return __awaiter(this, void 0, void 0, function () {
var auth, req, obj, res;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
auth = credentials ?
new Authorization(credentials) :
this.authorization;
if (!auth.registered) {
throw new EIDRError('Unregistered', 401, 'Query requires registered user credentials');
}
if (!graphRequest || Object.values(GraphTraversalTypes)
.indexOf(graphRequest) === -1) {
throw new EIDRError('Invalid graph traversal request', 500, "A valid graph request type must be provided: \n FindAncestors, FindDescendants, GetDependents,\n GetSeriesAncestry, GetLightweightRelationships,\n GetRemotestAncestor, GetLeafDescendants, GetParent,\n GetChildren");
}
if (!id) {
throw new EIDRError('Invalid graph traversal request', 500, 'EIDR ID must be provided');
}
req = this.renderGraphTraversalRequest(id, graphRequest);
return [4 /*yield*/, this.request('POST', 'object/graph', auth, req, apiVersion)];
case 1:
obj = _a.sent();
res = obj.Response;
if (res.Status.Code !== '0') {
throw new EIDRError("Error ".concat(res.Status.Code, " ").concat(res.Status.Type), (res.Status.Code === '4' || res.Status.Code === '5') ? 403 : 500, res.Status.Details);
}
return [2 /*return*/, res.SimpleMetadata ? (0, jsonPopulateValue_1.parseJsonWithValue)(res.SimpleMetadata) : null];
}
});
});
};
EIDRConnector.prototype.query = function (exprOrObj, options, credentials, apiVersion) {
if (options === void 0) { options = {}; }
return __awaiter(this, void 0, void 0, function () {
var auth, expr, req, obj, res, data, array;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
auth = credentials ?
new Authorization(credentials) :
this.authorization;
if (!auth.registered) {
throw new EIDRError('Unregistered', 401, 'Query requires registered user credentials');
}
expr = typeof exprOrObj === 'string' ? exprOrObj :
typeof exprOrObj === 'object' ? (0, jsonQuery_1.buildJsonQuery)(exprOrObj) :
undefined;
if (expr === undefined) {
throw new EIDRError('Invalid query', 500, "Query must be a string or an object: ".concat(typeof exprOrObj));
}
req = this.renderQueryRequest(expr, options);
return [4 /*yield*/, this.request('POST', "query/".concat(options.idOnly ? '?type=ID' : ''), auth, req, apiVersion)];
case 1:
obj = _a.sent();
res = obj.Response;
if (res.Status.Code !== '0') {
throw new EIDRError("Error ".concat(res.Status.Code, " ").concat(res.Status.Type), (res.Status.Code === '4' || res.Status.Code === '5') ? 403 : 500, res.Status.Details);
}
if (res.QueryResults) {
data = res.QueryResults[options.idOnly ? 'ID' : 'SimpleMetadata'];
array = data ? (Array.isArray(data) ? data : [data]) : [];
return [2 /*return*/, {
totalMatches: Number(res.QueryResults.TotalMatches),
results: (0, jsonPopulateValue_1.parseJsonWithValue)(array)
}];
}
throw new EIDRError('Unrecognized response', 500, 'Unrecognized response from registry');
}
});
});
};
EIDRConnector.prototype.resolve = function (id, type, credentials, apiVersion) {
if (type === void 0) { type = 'Full'; }
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
if (!(0, validate_1.validateId)(id)) {
throw new EIDRError('Invalid ID', 400, "Invalid EIDR ID: ".concat(id));
}
if (id.startsWith('10.5240')) {
return [2 /*return*/, this.resolveContentID(id, type, credentials, apiVersion)];
}
if (id.startsWith('10.5239') || id.startsWith('10.5237')) {
return [2 /*return*/, this.resolveOtherID(id, type, credentials, apiVersion)];
}
throw new EIDRError('Unsupported type', 500, "Unsupported record type: ".concat(id.substring(0, 7)));
});
});
};
EIDRConnector.prototype.resolveContentID = function (id, type, credentials, apiVersion) {
if (type === void 0) { type = 'Full'; }
return __awaiter(this, void 0, void 0, function () {
var auth, pth, res, attr_1, prop, attr, _a, $, response;
var _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
auth = credentials ?
new Authorization(credentials) :
undefined;
if (type !== 'AlternateIDs' &&
type !== 'DOIKernel' &&
type !== 'Full' &&
type !== 'LinkedAlternateIDs' &&
type !== 'Provenance' &&
type !== 'SelfDefined' &&
type !== 'Simple') {
throw new EIDRError('Unsupported type', 500, "Unsupported resolution type: id=".concat(id, " type=").concat(type));
}
pth = "object/".concat(encodeURIComponent(id), "?type=").concat(type);
return [4 /*yield*/, this.request('GET', pth, auth, undefined, apiVersion)];
case 1:
res = _c.sent();
if (res.Response &&
res.Response.Status &&
res.Response.Status.Code !== '0') {
throw new EIDRError("Error ".concat(res.Response.Status.Code, " ").concat(res.Response.Status.Type), 500, "Registry error: id=".concat(id, " type=").concat(res.Response.Status.Type));
}
if (type === 'Full' || type === 'SelfDefined') {
attr_1 = "".concat(type, "Metadata");
if (!res[attr_1] || !res[attr_1].BaseObjectData) {
throw new EIDRError('Unrecognized response', 500, "Unrecognized response resolving: id=".concat(id, " type=").concat(type));
}
return [2 /*return*/, (0, jsonPopulateValue_1.parseJsonWithValue)(__assign(__assign({}, res[attr_1].BaseObjectData), { ExtraObjectMetadata: res[attr_1].ExtraObjectMetadata }))];
}
if (type === 'AlternateIDs' || type === 'LinkedAlternateIDs') {
prop = type.slice(0, -1);
if (!res[type]) {
throw new EIDRError('Unrecognized response', 500, "Unrecognized response resolving: id=".concat(id, " type=").concat(type));
}
return [2 /*return*/, (0, jsonPopulateValue_1.parseJsonWithValue)((_b = {
ID: res[type].ID
},
_b[prop] = res[type][prop] || [],
_b))];
}
attr = "".concat(type === 'DOIKernel' ? 'kernel' : type, "Metadata");
if (!res[attr]) {
throw new EIDRError('Unrecognized response', 500, "Unrecognized response resolving: id=".concat(id, " type=").concat(type));
}
_a = res[attr], $ = _a.$, response = __rest(_a, ["$"]);
return [2 /*return*/, (0, jsonPopulateValue_1.parseJsonWithValue)(response)];
}
});
});
};
EIDRConnector.prototype.resolveOtherID = function (id, type, credentials, apiVersion) {
if (type === void 0) { type = 'Full'; }
return __awaiter(this, void 0, void 0, function () {
var auth, prefix, pth, res, which, payload, $, response;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (type !== 'Full' && type !== 'DOIKernel') {
throw new EIDRError('Unsupported type', 500, "Unsupported resolution: id=".concat(id, " type=").concat(type));
}
auth = credentials ?
new Authorization(credentials) :
undefined;
prefix = id.startsWith('10.5237') ? 'party' : 'service';
pth = "".concat(prefix, "/resolve/").concat(encodeURIComponent(id), "?type=").concat(type);
return [4 /*yield*/, this.request('GET', pth, auth, undefined, apiVersion)];
case 1:
res = _a.sent();
if (res.Response &&
res.Response.Status &&
res.Response.Status.Code !== '0') {
throw new EIDRError("Error ".concat(res.Response.Status.Code, " ").concat(res.Response.Status.Type), 500, "Registry error: id=".concat(id, " type=").concat(res.Response.Status.Type));
}
which = id.startsWith('10.5237') ? 'Party' : 'Service';
payload = res && res[type === 'Full' ? which : 'kernelMetadata'];
if (!payload) {
throw new EIDRError('Unrecognized response', 500, "Unrecognized response resolving: id=".concat(id, " type=").concat(type));
}
$ = payload.$, response = __rest(payload, ["$"]);
return [2 /*return*/, (0, jsonPopulateValue_1.parseJsonWithValue)(response)];
}
});
});
};
EIDRConnector.prototype.simpleQuery = function (exprOrObj, compareFunction, credentials) {
return __awaiter(this, void 0, void 0, function () {
var results, defaultCompareFunction;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.query(exprOrObj, {}, credentials)];
case 1:
results = (_a.sent()).results;
defaultCompareFunction = (function (a, b) { return ((new Date(b.ReleaseDate)).getTime() -
(new Date(a.ReleaseDate)).getTime()); });
return [2 /*return*/, results.sort(compareFunction || defaultCompareFunction)];
}
});
});
};
return EIDRConnector;
}(reshuffle_base_connector_1.BaseConnector));
exports.EIDRConnector = EIDRConnector;
//# sourceMappingURL=index.js.map