Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add sdk-development compliance validation to CI #291

Merged
merged 3 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/tests-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,9 @@ jobs:
- file: packages/api/src/index.ts
docsReporter: api-extractor
docsGenerator: typedoc-markdown
web5-spec:
finn-block marked this conversation as resolved.
Show resolved Hide resolved
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v4
finn-block marked this conversation as resolved.
Show resolved Hide resolved
- uses: TBD54566975/sdk-development@v0.2.3
9 changes: 9 additions & 0 deletions .web5-spec/Dockerfile
finn-block marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM node:18-alpine
RUN apk add --no-cache git python3 make g++
ADD . /web5-js
WORKDIR /web5-js
RUN npm ci --ws
RUN npm install --no-save express express-openapi
RUN npm run build
RUN npx tsc -p .web5-spec/tsconfig.json
CMD ["node", ".web5-spec/dist/main.js"]
3 changes: 3 additions & 0 deletions .web5-spec/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# web5-spec

this directory contains glue to allow [our standardized test suite](https://github.com/TBD54566975/sdk-development) to run against the web5-js SDK.
53 changes: 53 additions & 0 deletions .web5-spec/credentials.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Request, Response } from 'express';
import { VerifiableCredential, SignOptions } from '@web5/credentials';
import { DidKeyMethod, PortableDid } from '@web5/dids';
import { Ed25519, Jose } from '@web5/crypto';
import { paths } from './openapi.js';

type Signer = (data: Uint8Array) => Promise<Uint8Array>;

let _ownDid: PortableDid;

async function getOwnDid(): Promise<PortableDid> {
if(_ownDid) {
return _ownDid;
}
_ownDid = await DidKeyMethod.create();
return _ownDid;
}

export async function credentialIssue(req: Request, res: Response) {
const body: paths["/credentials/issue"]["post"]["requestBody"]["content"]["application/json"] =
req.body;

const ownDid = await getOwnDid()

// build signing options
const [signingKeyPair] = ownDid.keySet.verificationMethodKeys!;
const privateKey = (await Jose.jwkToKey({ key: signingKeyPair.privateKeyJwk!})).keyMaterial;
const subjectIssuerDid = body.credential.credentialSubject["id"] as string;
const signer = EdDsaSigner(privateKey);
const signOptions: SignOptions = {
issuerDid : ownDid.did,
subjectDid : subjectIssuerDid,
kid : '#' + ownDid.did.split(':')[2],
signer : signer
};

const vc: VerifiableCredential = VerifiableCredential.create(body.credential.type[body.credential.type.length - 1], body.credential.issuer, subjectIssuerDid, body.credential.credentialSubject);
const vcJwt: string = await vc.sign(signOptions);

const resp: paths["/credentials/issue"]["post"]["responses"]["200"]["content"]["application/json"] =
{
verifiableCredential: {data: vcJwt}
};

res.json(resp);
}

function EdDsaSigner(privateKey: Uint8Array): Signer {
return async (data: Uint8Array): Promise<Uint8Array> => {
const signature = await Ed25519.sign({ data, key: privateKey});
return signature;
};
}
15 changes: 15 additions & 0 deletions .web5-spec/did-ion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { DidIonMethod } from "@web5/dids";
import { paths } from "./openapi.js";
import { Request, Response } from "express";


export async function didIonCreate(req: Request, res: Response) {
const did = await DidIonMethod.create({});

const resp: paths["/did-ion/create"]["post"]["responses"]["200"]["content"]["application/json"] =
{
did: did.did,
};

res.json(resp);
}
40 changes: 40 additions & 0 deletions .web5-spec/encoders.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { paths } from "./openapi.js";
import { Request, Response } from "express";
import { Convert } from "@web5/common";
import { sha256 } from "@noble/hashes/sha256";

export function encoderBase64Encode(req: Request, res: Response) {
const requestBody: paths["/encoders/base64/encode"]["post"]["requestBody"]["content"]["application/json"] =
req.body;

const resp: paths["/encoders/base64/encode"]["post"]["responses"]["200"]["content"]["application/json"] =
{
data: Convert.string(requestBody.data).toBase64Url(),
};

res.json(resp);
}

export function encoderBase64Decode(req: Request, res: Response) {
const requestBody: paths["/encoders/base64/encode"]["post"]["requestBody"]["content"]["application/json"] =
req.body;

const resp: paths["/encoders/base64/encode"]["post"]["responses"]["200"]["content"]["application/json"] =
{
data: Convert.base64Url(requestBody.data).toString(),
};

res.json(resp);
}

export function encoderSha256Encode(req: Request, res: Response) {
const requestBody: paths["/encoders/sha256/encode"]["post"]["requestBody"]["content"]["application/json"] =
req.body;

const resp: paths["/encoders/sha256/encode"]["post"]["responses"]["200"]["content"]["application/json"] =
{
data: Convert.arrayBuffer(sha256(requestBody.data)).toHex(),
};

res.json(resp);
}
53 changes: 53 additions & 0 deletions .web5-spec/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import express from "express";
import { credentialIssue } from "./credentials.js";
import { didIonCreate } from "./did-ion.js";
import {
encoderBase64Decode,
encoderBase64Encode,
encoderSha256Encode,
} from "./encoders.js";
import type * as http from "http";
import type { Request, Response } from "express";
import { paths } from "./openapi.js"; // generated with npx openapi-typescript .web5-component/openapi.yaml -o .web5-component/openapi.d.ts
import bodyparser from "body-parser";

const app: express.Application = express();
app.use(express.json());
app.use(bodyparser.json());

app.post("/did-ion/create", didIonCreate);

app.post("/credentials/issue", credentialIssue);

app.post("/encoders/base64/encode", encoderBase64Encode);
app.post("/encoders/base64/decode", encoderBase64Decode);
app.post("/encoders/sha256/encode", encoderSha256Encode);

const serverID: paths["/"]["get"]["responses"]["200"]["content"]["application/json"] =
{
name: "web5-js",
language: "JavaScript",
url: "https://github.com/TBD54566975/web5-js",
};
app.get("/", (req, res) => {
res.json(serverID);
});

let server: http.Server;
app.get("/shutdown", (req: Request, res: Response) => {
res.send("ok");
console.log("shutting down server");
server.close((e) => {
if (e) {
console.error("error shutting down server:", e.stack || e);
}
});
});

server = app.listen(8080, () => console.log("test server started"));
process.on("SIGTERM", () => {
console.log("SIGTERM signal received: closing HTTP server");
server.close(() => {
console.log("HTTP server closed");
});
});
Loading
Loading