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

feat: add decentralized-web-node app #57

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ jobs:
BUILD_ID: ${{ steps.tag_version.outputs.new_tag }}
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
run: |
docker build -t $ECR_REGISTRY/${{ steps.env_vars.outputs.aws_ecr_repository }}:$BUILD_ID -f Dockerfile .
docker build -t $ECR_REGISTRY/${{ steps.env_vars.outputs.aws_ecr_repository }}:$BUILD_ID -f docker/vc-api/Dockerfile .
docker push $ECR_REGISTRY/${{ steps.env_vars.outputs.aws_ecr_repository }}:$BUILD_ID
- name: Logout of Amazon ECR
if: always()
Expand Down
22 changes: 20 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
name: CI
name: Test

on:
push:

jobs:
build-and-test:
services:
postgres:
image: postgres:12
env:
POSTGRES_USER: user-test
POSTGRES_DB: dev-test
POSTGRES_PASSWORD: password-test
ports:
- 5432:5432
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: actions/setup-node@v2
with:
node-version: '14'
node-version: '16.10.0'

- name: Rush install
run: node common/scripts/install-run-rush.js install
Expand All @@ -21,4 +31,12 @@ jobs:
run: node common/scripts/install-run-rush.js build --verbose

- name: Run test
env:
CI: true
NESTJS_PORT: 3000
DB_HOST: localhost
DB_PORT: 5432
DB_USERNAME: user-test
DB_PASSWORD: password-test
DB_NAME: dev-test
run: node common/scripts/install-run-rush.js test --verbose
17 changes: 17 additions & 0 deletions apps/decentralized-web-node/.env.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# NESTJS CONFIG
NESTJS_PORT=3000

# DB Config
DB_HOST=postgres
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=password
DB_NAME=dev-test

# SENTRY CONFIG
SENTRY_DNS=
SENTRY_ENV=
SENTRY_RELEASE=

# LOGS CONFIG
LOGS_DIRECTORY=logs
46 changes: 46 additions & 0 deletions apps/decentralized-web-node/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# compiled output
/dist
/node_modules
/src/ethers
.env

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
*-audit.json

# OS
.DS_Store

# Tests
/coverage
/.nyc_output

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

.env

# Using either dev or prod docker-compose file
docker-compose.yml
db_dumps
ormconfig.json
private.pem
public.pem
3 changes: 3 additions & 0 deletions apps/decentralized-web-node/.sentryclirc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[defaults]
project=ssi-dwn
org=energy-web
58 changes: 58 additions & 0 deletions apps/decentralized-web-node/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# SSI Decentralized Web Node

## Description

This [ssi-dwn](./apps/decentralized-web-node) is a NestJs implementation of the [DIF Identity foundation](https://identity.foundation/) [Decentralized Web Node](https://identity.foundation/decentralized-web-node/spec/).
[Nest](https://github.com/nestjs/nest) is a Typescript framework for server-side applications.

## Installation

Install using the [rush commands](../../README.md#installation) described in the root README.

## Running the app

Alternatively to `npm`, `pnpm` can be used for the commands below.

```bash
# development
$ npm run start

# watch mode
$ npm run start:dev

# production mode
$ npm run start:prod
```
### Swagger/OpenAPI

After starting the `ssi-dwn` app,
the Swagger/OpenAPI test page can be see at `{appURL}/api` (`http://localhost:3000/api` if running locally)

## Test

Alternatively to `npm`, `pnpm` can be used for the commands below.

```bash
# e2e tests
$ npm run test

# test coverage
$ npm run test:cov
```

### Decentralized web node Module
An implementation of the [Decentralized Web Node](https://identity.foundation/decentralized-web-node/spec/). Currently it's acting as a Verifiable Credential Storage.

### Presentation exchange Module
Module is responsible for matching Verifiable Credentials to given presentation definition. Credentials are taken from
decentralized web node module.
## Database
Currently, the app uses an **PostgreSQL** database for app execution and tests.

## Auth
All endpoints are requiring authentication. Request must contain `token` cookies which contain identity token that can be obtain from [SSI Hub](https://github.com/energywebfoundation/ssi-hub).

## License

This project is licensed under the GNU General Public License v3.0 or later - see the [LICENSE](LICENSE) file for details
NestJs is [MIT licensed](LICENSE).
4 changes: 4 additions & 0 deletions apps/decentralized-web-node/nest-cli.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"collection": "@nestjs/schematics",
"sourceRoot": "src"
}
108 changes: 108 additions & 0 deletions apps/decentralized-web-node/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
{
"name": "@energyweb/ssi-dwn",
"version": "0.0.1",
"description": "",
"author": "",
"private": true,
"license": "UNLICENSED",
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/src/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "npm run test:e2e",
"test:unit": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@ew-did-registry/credentials-interface": "^0.6.3-alpha.531.0",
"@nestjs/axios": "0.0.7",
"@nestjs/common": "^8.0.6",
"@nestjs/config": "^1.0.1",
"@nestjs/core": "^8.0.6",
"@nestjs/jwt": "^8.0.0",
"@nestjs/passport": "^8.1.0",
"@nestjs/platform-express": "^8.0.6",
"@nestjs/swagger": "^5.0.9",
"@nestjs/terminus": "^8.0.1",
"@nestjs/typeorm": "^8.0.2",
"@sentry/integrations": "^6.2.2",
"@sentry/node": "^6.16.1",
"@sentry/tracing": "^6.16.1",
"@sentry/types": "^6.2.2",
"@sphereon/pex": "^1.0.2",
"@types/passport": "^1.0.7",
"class-transformer": "^0.5.0",
"class-validator": "^0.13.0",
"compression": "^1.7.4",
"cookie-parser": "^1.4.5",
"dotenv": "^10.0.0",
"express": "^4.18.0",
"helmet": "^4.4.1",
"multiformats": "^9.6.4",
"passport": "^0.5.2",
"passport-jwt": "^4.0.0",
"pg": "^8.5.1",
"redact-pii": "^3.2.3",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.3.0",
"swagger-ui-express": "^4.1.4",
"typeorm": "^0.2.41",
"uuid": "^8.3.2",
"winston": "^3.3.3",
"winston-daily-rotate-file": "^4.5.0"
},
"devDependencies": {
"@types/jsonwebtoken": "^8.5.8",
"@energyweb/eslint-config": "^0.0.2",
"@energyweb/prettier-config": "^0.0.1",
"@nestjs/cli": "^7.5.6",
"@nestjs/schematics": "^7.2.9",
"@nestjs/testing": "^8.0.6",
"@types/compression": "^1.7.0",
"@types/cookie-parser": "^1.4.2",
"@types/express": "^4.17.3",
"@types/jest": "27.4.1",
"@types/node": "^13.9.1",
"@types/passport-jwt": "^3.0.3",
"@types/supertest": "^2.0.8",
"@types/uuid": "^8.3.0",
"@typescript-eslint/eslint-plugin": "^5.9.1",
"@typescript-eslint/parser": "^5.9.1",
"base64url": "^3.0.1",
"ethers": "^5.6.1",
"eslint": "^8.6.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.25.4",
"jest": "27.5.1",
"jsonwebtoken": "^8.5.1",
"npm-run-all": "^4.1.5",
"prettier": "^2.5.1",
"rimraf": "^3.0.2",
"supertest": "^4.0.2",
"ts-jest": "27.1.4",
"ts-loader": "^6.2.1",
"ts-node": "^9.0.0",
"typedoc": "^0.22.0",
"typedoc-plugin-markdown": "^3.11.0",
"typescript": "^4.3.5"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"testEnvironment": "node"
}
}
29 changes: 29 additions & 0 deletions apps/decentralized-web-node/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import { LoggerModule } from './modules/logger/logger.module';
import { SentryModule } from './modules/sentry/sentry.module';
import { InterceptorsModule } from './modules/interceptors/interceptors.module';
import { HealthCheckModule } from './modules/health-check/health-check.module';
import { DecentralizedWebNodeModule } from './modules/decentralized-web-node/decentralized-web-node.module';
import { PresentationExchangeModule } from './modules/presentation-exchange/presentation-exchange.module';
import { getDBConfig } from './config/database.config';

@Module({
imports: [
TypeOrmModule.forRootAsync({
inject: [ConfigService],
useFactory: getDBConfig
}),
ConfigModule.forRoot({
isGlobal: true
}),
LoggerModule,
SentryModule,
InterceptorsModule,
HealthCheckModule,
DecentralizedWebNodeModule,
PresentationExchangeModule
]
})
export class AppModule {}
12 changes: 12 additions & 0 deletions apps/decentralized-web-node/src/common/test.utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { INestApplication, ValidationPipe, VersioningType } from '@nestjs/common';
import cookieParser from 'cookie-parser';

export function appConfig(app: INestApplication) {
app.enableVersioning({
type: VersioningType.URI
});

// add cookie parser to read jwt token cookie
app.use(cookieParser());
app.useGlobalPipes(new ValidationPipe());
}
42 changes: 42 additions & 0 deletions apps/decentralized-web-node/src/config/database.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import fs from 'fs';
import path from 'path';
import { ConfigService } from '@nestjs/config';
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
import { LoggerOptions } from 'typeorm';

export const getDBConfig = (configService: ConfigService) => {
const isProduction = configService.get<string>('NODE_ENV') === 'production';

const typeormLoggerOptions = configService
.get<string>('TYPEORM_LOGGING', 'error,migration,warn,info')
.split(',') as LoggerOptions;

const config: TypeOrmModuleOptions = {
type: 'postgres',
host: configService.get<string>('DB_HOST'),
port: +configService.get<string>('DB_PORT'),
username: configService.get<string>('DB_USERNAME'),
password: configService.get<string>('DB_PASSWORD'),
database: configService.get<string>('DB_NAME'),
migrations: [path.join(__dirname + '/..') + '/migrations/**/*{.ts,.js}'],
cli: { migrationsDir: 'src/migrations' },
migrationsRun: true,
migrationsTableName: 'migrations_iam_cache_server',
logging: typeormLoggerOptions[0] === 'all' ? 'all' : typeormLoggerOptions,
autoLoadEntities: true,
// Options from pool config https://node-postgres.com/api/pool
extra: {
max: configService.get<number>('DB_MAXIMUM_CONNECTION_POOL', 10),
connectionTimeoutMillis: configService.get<number>('DB_CONNECTION_TIMEOUT', 1000)
}
};

// Generating ormconfig.json for running typeOrm CLI in dev env
!isProduction &&
fs.writeFileSync(
'ormconfig.json',
JSON.stringify({ ...config, entities: ['dist/**/*.entity.js'] }, null, 2)
);

return config;
};
Loading