Skip to content

Commit

Permalink
Merge pull request #14 from digitalcredentials/convert-to-bsl
Browse files Browse the repository at this point in the history
Converts Status List 2021 to Bitstring Status List and does related cleanup
  • Loading branch information
kezike authored Jun 28, 2024
2 parents e3f44e3 + 67e9ef5 commit ece765d
Show file tree
Hide file tree
Showing 15 changed files with 540 additions and 332 deletions.
4 changes: 2 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ ENABLE_HTTPS_FOR_DEV=false # ONLY for development when need https; default
ENABLE_ACCESS_LOGGING=true
ENABLE_STATUS_SERVICE=false

STATUS_SERVICE_ENDPOINT=localhost:4008
SIGNING_SERVICE_ENDPOINT=localhost:4006
STATUS_SERVICE=localhost:4008
SIGNING_SERVICE=localhost:4006

# Tokens for protecting tenant endpoints.
# Add a token for any tenant name,
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ types/
# dotenv environment variables file
.env
.signing-service.env
.status-service.env
.status-service-db.env
.status-service-git.env
.coordinator.env
.env.test

Expand Down
18 changes: 18 additions & 0 deletions .status-service-db.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
PORT=4008 # default port is 4008
ENABLE_HTTPS_FOR_DEV=false # ONLY for dev when need https; default is false

# Database specific environment variables
CRED_STATUS_SERVICE=mongodb
CRED_STATUS_DID_SEED=z1AackbUm8U69ohKnihoRRFkXcXJd4Ra1PkAboQ2ZRy1ngB
STATUS_CRED_SITE_ORIGIN=https://credentials.example.edu
CRED_STATUS_DB_URL=mongodb+srv://user:[email protected]?retryWrites=false
CRED_STATUS_DB_HOST=domain.mongodb.net # ignored if CRED_STATUS_DB_URL is configured
CRED_STATUS_DB_PORT=27017 # ignored if CRED_STATUS_DB_URL is configured
CRED_STATUS_DB_USER=testuser # ignored if CRED_STATUS_DB_URL is configured
CRED_STATUS_DB_PASS=testpass # ignored if CRED_STATUS_DB_URL is configured
CRED_STATUS_DB_NAME= # autogenerated if omitted
STATUS_CRED_TABLE_NAME= # autogenerated if omitted
USER_CRED_TABLE_NAME= # autogenerated if omitted
CONFIG_TABLE_NAME= # autogenerated if omitted
EVENT_TABLE_NAME= # autogenerated if omitted
CRED_EVENT_TABLE_NAME= # autogenerated if omitted
12 changes: 12 additions & 0 deletions .status-service-git.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
PORT=4008 # default port is 4008
ENABLE_HTTPS_FOR_DEV=false # ONLY for dev when need https; default is false

# Git specific environment variables
CRED_STATUS_SERVICE=github
CRED_STATUS_DID_SEED=z1AackbUm8U69ohKnihoRRFkXcXJd4Ra1PkAboQ2ZRy1ngB
CRED_STATUS_REPO_OWNER=digitalcredentials
CRED_STATUS_REPO_NAME=credential-status-test-jc
CRED_STATUS_REPO_ID=12345678 # only required when CRED_STATUS_SERVICE = 'gitlab'
CRED_STATUS_META_REPO_NAME=credential-status-metadata-test-jc
CRED_STATUS_META_REPO_ID=87654321 # only required when CRED_STATUS_SERVICE = 'gitlab'
CRED_STATUS_ACCESS_TOKEN=REPLACE_THIS_WITH_A_GITHUB_ACCESS_TOKEN
9 changes: 0 additions & 9 deletions .status-service.env

This file was deleted.

9 changes: 7 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
# exchange-coordinator Changelog
# workflow-coordinator Changelog

## 1.0.0 - TBD

### Added

- Initial commit.

### Changed
- Convert Status List 2021 to Bitstring Status List.
- Differentiate between database status service and Git status service.
- Rename environment variables.
- Update revocation and suspension instructions.
433 changes: 232 additions & 201 deletions README.md

Large diffs are not rendered by default.

29 changes: 16 additions & 13 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
version: '3.5'
services:
coordinator:
image: digitalcredentials/exchange-coordinator:0.1.0
# env_file:
# - ./.coordinator.env
image: digitalcredentials/workflow-coordinator:0.1.0
env_file:
- ./.coordinator.env
ports:
- "4005:4005"
signing:
image: digitalcredentials/signing-service:0.1.0
# env_file:
# - ./.signing-service.env
transactions:
image: digitalcredentials/signing-service:0.1.0
env_file:
- ./.signing-service.env
transaction:
image: digitalcredentials/transaction-service:0.1.0
# env_file:
# - ./.transactions-service.env
#status:
# image: digitalcredentials/status-service:0.1.0
# env_file:
# - ./.status-service.env
env_file:
- ./.transaction-service.env
status:
image: digitalcredentials/status-service-db:0.1.0
# image: digitalcredentials/status-service-git:0.1.0
env_file:
- ./.status-service-db.env
# - ./.status-service-git.env

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@digitalcredentials/exchange-coordinator",
"name": "@digitalcredentials/workflow-coordinator",
"version": "0.0.0",
"private": true,
"type": "module",
Expand Down Expand Up @@ -47,8 +47,8 @@
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/digitalcredentials/exchange-coordinator"
"url": "https://github.com/digitalcredentials/workflow-coordinator"
},
"homepage": "https://github.com/digitalcredentials/exchange-coordinator",
"bugs": "https://github.com/digitalcredentials/exchange-coordinator/issues"
"homepage": "https://github.com/digitalcredentials/workflow-coordinator",
"bugs": "https://github.com/digitalcredentials/workflow-coordinator/issues"
}
50 changes: 23 additions & 27 deletions src/app.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import express from 'express';
import cors from 'cors';
import axios from 'axios';
import https from "https"
import https from 'https'
import accessLogger from './middleware/accessLogger.js';
import errorHandler from './middleware/errorHandler.js';
import errorLogger from './middleware/errorLogger.js';
Expand All @@ -25,7 +25,7 @@ async function callService(endpoint, body) {

export async function build(opts = {}) {

const { enableStatusService, coordinatorServiceEndpoint, statusServiceEndpoint, signingServiceEndpoint, transactionServiceEndpoint, exchangeHost } = getConfig();
const { enableStatusService, coordinatorService, statusService, signingService, transactionService, exchangeHost } = getConfig();
var app = express();
// Add the middleware to write access logs
app.use(accessLogger());
Expand All @@ -36,7 +36,7 @@ export async function build(opts = {}) {
app.get('/', async function (req, res, next) {
if (enableStatusService) {
try {
await axios.get(`http://${statusServiceEndpoint}/`)
await axios.get(`http://${statusService}/`)
} catch (e) {
next({
message: 'status service is NOT running.',
Expand All @@ -46,7 +46,7 @@ export async function build(opts = {}) {
}
}
try {
await axios.get(`http://${signingServiceEndpoint}/`)
await axios.get(`http://${signingService}/`)
} catch (e) {
next({
message: 'signing service is NOT running.',
Expand All @@ -55,7 +55,7 @@ export async function build(opts = {}) {
})
}
try {
await axios.get(`http://${transactionServiceEndpoint}/`)
await axios.get(`http://${transactionService}/`)
} catch (e) {
next({
message: 'transaction service is NOT running.',
Expand All @@ -64,25 +64,23 @@ export async function build(opts = {}) {
})
}
const message = enableStatusService ?
"exchange-coordinator, status-service, transaction-service, and signing-service all ok."
:
"exchange-coordinator, transaction-service, and signing-service all ok. status-service is disabled."
'workflow-coordinator, status-service, transaction-service, and signing-service all ok.' :
'workflow-coordinator, transaction-service, and signing-service all ok. status-service is disabled.'

res.status(200).send({ message })

});

/*
A test that mocks the 'issuer coordinator app', i.e, the client code
that a university would write to invoke the exchange-coordinator. this
that a university would write to invoke the workflow-coordinator. this
should be called from a web browser on a phone (or emulator)
because it will redirect to the Learner Credential Wallet running on the
phone.
*/
app.get('/demo', async (req, res, next) => {
const retrievalId = 'ohmy'
// 1. post the test vc to the /setup endpoint
const data = {tenantName: "test", data: [{ vc: testVC, retrievalId: 'ohmy' }]}
const data = {tenantName: 'test', data: [{ vc: testVC, retrievalId: 'ohmy' }]}
const walletQuerys = await callService(`${exchangeHost}/exchange/setup`, data)
// The exchange endpoint stores the data and returns a deeplink (with challenge)
// to which the student can be redirected, and which will then open the wallet
Expand All @@ -109,25 +107,23 @@ export async function build(opts = {}) {
* which to then initiate the exchange.
* Note that by setting 'flow=direct' on the object posted
* to this endpoint, we can tell the exchanger to skip the
* inititation step and give the wallet the endpoint to which
* initiation step and give the wallet the endpoint to which
* to send the DIDAuth. This is for backward compatability.
*/
app.post("/exchange/setup",
app.post('/exchange/setup',
async (req, res, next) => {
try {
//const tenantName = req.params.tenantName //the issuer instance/tenant with which to sign
console.log("in the exchange setup")
const exchangeData = req.body;
// TODO: CHECK THE INCOMING DATA FOR CORRECTNESS HERE
if (!exchangeData || !Object.keys(exchangeData).length) throw new CoordinatorException(400, 'You must provide data for the exchange. Check the README for details.')
exchangeData.exchangeHost = exchangeHost

await verifyAuthHeader(req.headers.authorization, exchangeData.tenantName)

const walletQuerys = await callService(`http://${transactionServiceEndpoint}/exchange`, exchangeData)
const walletQuerys = await callService(`http://${transactionService}/exchange`, exchangeData)

return res.json(walletQuerys)

} catch (error) {
// catch async errors and forward error handling
// middleware
Expand All @@ -144,11 +140,11 @@ console.log("in the exchange setup")
* Note that this step can be skipped by setting
* flow=direct in the object we pass in to the setup endpoint.
*/
app.post("/exchange/:exchangeId",
app.post('/exchange/:exchangeId',
async (req, res, next) => {
try {
const exchangeId = req.params.exchangeId
const vpr = await callService(`http://${transactionServiceEndpoint}/exchange/${exchangeId}/`)
const vpr = await callService(`http://${transactionService}/exchange/${exchangeId}/`)
return res.json(vpr)

} catch (error) {
Expand All @@ -167,7 +163,7 @@ console.log("in the exchange setup")
* the status service and signing service before returning
* to the wallet.
*/
app.post("/exchange/:exchangeId/:transactionId",
app.post('/exchange/:exchangeId/:transactionId',
async (req, res, next) => {
try {
const exchangeId = req.params.exchangeId
Expand All @@ -177,20 +173,20 @@ console.log("in the exchange setup")
// make a deep copy of the didAuth because something seemed to be
// going wrong with the streams
const didAuth = JSON.parse(JSON.stringify(body))
const transactionEndpoint = `http://${transactionServiceEndpoint}/exchange/${exchangeId}/${transactionId}`
const transactionEndpoint = `http://${transactionService}/exchange/${exchangeId}/${transactionId}`
const response = await axios.post(transactionEndpoint, didAuth);
const { data } = response
const { tenantName, vc: unSignedVC } = data
unSignedVC.credentialSubject.id = didAuth.holder

// add credential status if enabled
const vcReadyToSign = enableStatusService ?
await callService(`http://${statusServiceEndpoint}/credentials/status/allocate`, unSignedVC)
await callService(`http://${statusService}/credentials/status/allocate`, unSignedVC)
:
unSignedVC

// sign the credential
const signedVC = await callService(`http://${signingServiceEndpoint}/instance/${tenantName.toLowerCase()}/credentials/sign`, vcReadyToSign)
const signedVC = await callService(`http://${signingService}/instance/${tenantName.toLowerCase()}/credentials/sign`, vcReadyToSign)
return res.json(signedVC)

} catch (error) {
Expand All @@ -201,13 +197,13 @@ console.log("in the exchange setup")
})

// updates the status
// the body will look like: {credentialId: '23kdr', credentialStatus: [{type: 'StatusList2021Credential', status: 'revoked'}]}
app.post("/instance/:tenantName/credentials/status",
// the body will look like: {credentialId: '23kdr', credentialStatus: [{type: 'BitstringStatusListCredential', status: 'revoked'}]}
app.post('/instance/:tenantName/credentials/status',
async (req, res, next) => {
if (!enableStatusService) return res.status(405).send("The status service has not been enabled.")
if (!enableStatusService) return res.status(405).send('The status service has not been enabled.')
try {
await verifyAccess(req.headers.authorization, req.params.tenantName)
const updateResult = await callService(`http://${statusServiceEndpoint}/instance/${tenantName}/credentials/sign`, vcWithStatus)
const updateResult = await callService(`http://${statusService}/instance/${tenantName}/credentials/sign`, vcWithStatus)
return res.json(updateResult)
} catch (error) {
// have to catch and forward async errors to middleware:
Expand All @@ -216,7 +212,7 @@ console.log("in the exchange setup")
})

app.get('/seedgen', async (req, res, next) => {
const response = await axios.get(`http://${signingServiceEndpoint}/seedgen`)
const response = await axios.get(`http://${signingService}/seedgen`)
return res.json(response.data)
});

Expand Down
Loading

0 comments on commit ece765d

Please sign in to comment.