diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 45558a55..98ba9cd5 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -480,7 +480,7 @@ function initializeSingleContext(block:string):BlockContext{ export const addMiddlewares = async (baseUrl: string, app: Express) => { const mws = [ - 'timestamp', 'git', 'db', 'files', 'redis', 'influxdb', 'http', + 'timestamp', 'identity', 'git', 'db', 'files', 'redis', 'influxdb', 'http', 'fabric', 'planetmint', 'sawroom', 'ethereum', 'logger', 'ui', ] diff --git a/packages/create-restroom/templates/restroom.mustache b/packages/create-restroom/templates/restroom.mustache index 523aa1f9..a958f3ac 100644 --- a/packages/create-restroom/templates/restroom.mustache +++ b/packages/create-restroom/templates/restroom.mustache @@ -7,6 +7,9 @@ import zencode from "@restroom-mw/core"; {{#@restroom-mw/timestamp}} import timestamp from "@restroom-mw/timestamp"; {{/@restroom-mw/timestamp}} +{{#@restroom-mw/identity}} +import identity from "@restroom-mw/identity"; +{{/@restroom-mw/identity}} {{#@restroom-mw/git}} import git from "@restroom-mw/git"; {{/@restroom-mw/git}} @@ -63,6 +66,9 @@ app.use(bodyParser.json()); app.use(morgan("dev")); app.set("json spaces", 2); +{{#@restroom-mw/identity}} +app.use(identity.default); +{{/@restroom-mw/identity}} {{#@restroom-mw/db}} app.use(db.default); {{/@restroom-mw/db}} diff --git a/packages/identity/package.json b/packages/identity/package.json new file mode 100644 index 00000000..bf6bd11d --- /dev/null +++ b/packages/identity/package.json @@ -0,0 +1,38 @@ +{ + "name": "@restroom-mw/identity", + "version": "0.13.0", + "description": "Identity utilities middleware for Restroom", + "author": "Rebecca Selvaggini ", + "contributors": [ + "Luca Di Domenico " + ], + "homepage": "https://dyne.github.io/restroom-mw/", + "license": "AGPL-3.0", + "main": "dist/index.js", + "files": [ + "src", + "dist" + ], + "publishConfig": { + "registry": "https://registry.npmjs.org/" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/dyne/restroom-mw.git" + }, + "scripts": { + "clean": "rimraf dist && rimraf tsconfig.tsbuildinfo", + "doc": "documentation readme src/** -g -f md -s 'API' --readme-file ../../docs/packages/identity.md --shallow", + "links": "yarn link", + "unlinks": "yarn unlink", + "watch": "tsc -b tsconfig.json -w", + "build": "tsc -b tsconfig.json" + }, + "bugs": { + "url": "https://github.com/dyne/restroom-mw/issues" + }, + "dependencies": { + "axios": "^0.26.0" + }, + "gitHead": "5015ad3c33829d0690ed914900c45f0576b70aee" +} diff --git a/packages/identity/src/actions.ts b/packages/identity/src/actions.ts new file mode 100644 index 00000000..b3f81790 --- /dev/null +++ b/packages/identity/src/actions.ts @@ -0,0 +1,11 @@ +export enum Action { + /** + * `Given I resolve the did 'myDid' from 'myUrl' and save the output into 'myOutput'`

+ * Resolve 'myDid' using the resolver in 'myUrl' and save the resolved did json inside 'myOutput'. + * By repeting the statement *n* times, it will perform *n* parallel get. + * @param {string} myDid - Name of the variable containing the did to be resolved + * @param {string} myUrl - Name of the variable containing the url of the resolver + * @param {string} myOutput - Name of the variable where the output json will be stored + */ + RESOLVE_DID = "resolve the did {} from {} and save the output into {}", +} diff --git a/packages/identity/src/index.ts b/packages/identity/src/index.ts new file mode 100644 index 00000000..0722c5f3 --- /dev/null +++ b/packages/identity/src/index.ts @@ -0,0 +1,52 @@ +import { Restroom } from "@restroom-mw/core"; +import { ObjectLiteral } from "@restroom-mw/types"; +import { Zencode } from "@restroom-mw/zencode"; +import { NextFunction, Request, Response } from "express"; +import axios from "axios"; +import { Action } from "./actions"; +import { chunks } from "@restroom-mw/http/src/utils"; + +export default (req: Request, res: Response, next: NextFunction) => { + const rr = new Restroom(req, res); + let content: ObjectLiteral = {}; + let promises: Promise[] = []; + let outputs: string[] = []; + + rr.onBefore( + async (params: { + zencode: Zencode; + keys: ObjectLiteral; + data: ObjectLiteral; + }) => { + let { zencode, keys, data } = params; + content = rr.combineDataKeys(data, keys); + + if (zencode.match(Action.RESOLVE_DID)) { + for (let [did, urlName, o] of chunks(zencode.paramsOf(Action.RESOLVE_DID), 3)) { + let check_url : URL; + let url_resolver : URL; + try { + check_url = new URL(content[urlName]); + } catch (err) { + throw new Error("The string " + content[urlName] + " is an invalid URL"); + } + try{ + url_resolver = new URL(check_url.toString() + "/" + content[did]); + } catch(err){ + throw new Error("The string " + content[did] + " is an invalid URL"); + } + promises.push(axios.get(url_resolver.toString())); + outputs.push(o); + } + } + if(promises.length){ + const result = await Promise.all(promises); + result.map((r, i) => { + const out = outputs[i]; + data[out] = r.data; + }); + } + } + ) + next(); +} diff --git a/packages/identity/tests/index.js b/packages/identity/tests/index.js new file mode 100644 index 00000000..15203451 --- /dev/null +++ b/packages/identity/tests/index.js @@ -0,0 +1,52 @@ +import test from "ava"; +import request from "supertest"; +import express from "express"; +import bodyParser from "body-parser"; + +process.env.ZENCODE_DIR = "./test/identity"; +const identity = require("..").default; +const zencode = require("../../core").default; + +test("Resolve did", + async (t) => { + const app = express(); + app.use(bodyParser.json()); + app.use(identity); + app.use("/*", zencode); + const res = await request(app).post("/resolve-did"); + t.true( + Object.keys(res.body).includes("myOutput"), + 'could not find "myOutput " in response' + ); + let output = res.body.myOutput; + t.true( + Object.keys(output).includes("didDocument"), + 'could not find "didDocument" in myOutput' + ); + t.true( + Object.keys(output).includes("didDocumentMetadata"), + 'could not find "didDocumentMetadata" in myOutput' + ); + t.true( + Object.keys(output).includes("@context"), + 'could not find "@context" in myOutput' + ); + t.true( + Object.keys(res.body).includes("myOutput2"), + 'could not find "myOutput2 " in response' + ); + output = res.body.myOutput2; + t.true( + Object.keys(output).includes("didDocument"), + 'could not find "didDocument" in myOutput2' + ); + t.true( + Object.keys(output).includes("didDocumentMetadata"), + 'could not find "didDocumentMetadata" in myOutput2' + ); + t.true( + Object.keys(output).includes("@context"), + 'could not find "@context" in myOutput2' + ); + t.is(res.status, 200); + }); diff --git a/packages/identity/tsconfig.json b/packages/identity/tsconfig.json new file mode 100644 index 00000000..dd02e330 --- /dev/null +++ b/packages/identity/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./src" + }, + "references": [{ + "path": "../core/" + }, { + "path": "../types" + }], + "exclude": ["dist", "tests"] +} diff --git a/test/identity/resolve-did.keys b/test/identity/resolve-did.keys new file mode 100644 index 00000000..17d56833 --- /dev/null +++ b/test/identity/resolve-did.keys @@ -0,0 +1,5 @@ +{ + "myUrl": "https://did.dyne.org/dids", + "myDid": "did:dyne:sandbox.zenswarm:HwSjX94eXVmVpqGnN6L5HD3rjSBwxJeNc9xByJKB83wB", + "myDid2": "did:dyne:sandbox.test:AR4tjXRTHzoiUoR8pcPrZRbHPFeR9LLqQLWfAhJrehEv" +} diff --git a/test/identity/resolve-did.zen b/test/identity/resolve-did.zen new file mode 100644 index 00000000..10b2dab8 --- /dev/null +++ b/test/identity/resolve-did.zen @@ -0,0 +1,10 @@ +Rule caller restroom-mw + +Given I have a 'string' named 'myDid' +Given I have a 'string' named 'myDid2' +Given I have a 'string' named 'myUrl' +Given I have a 'string dictionary' named 'myOutput' +Given I have a 'string dictionary' named 'myOutput2' +Given I resolve the did 'myDid' from 'myUrl' and save the output into 'myOutput' +Given I resolve the did 'myDid2' from 'myUrl' and save the output into 'myOutput2' +Then print all data