UNPKG

reshuffle-eidr-connector

Version:
411 lines 23.9 kB
"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