diff --git a/.dockerignore b/.dockerignore index c96b1224..1e9aeb0c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,11 +3,10 @@ **/.github **/node_modules **/dist +**/docker # Skip unnecessary files **/*.md -Dockerfile -docker-compose.yml # Exceptions !LICENSE diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 42066a7b..efd66924 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -47,6 +47,7 @@ jobs: uses: docker/metadata-action@v4 with: images: | + ${{ env.IMAGE_NAME }} ghcr.io/${{ env.IMAGE_NAME }} registry.digitalocean.com/${{ env.IMAGE_NAME }} tags: | @@ -58,7 +59,7 @@ jobs: uses: docker/build-push-action@v4 with: context: . - file: Dockerfile + file: docker/Dockerfile platforms: linux/amd64 load: true target: runner diff --git a/.gitignore b/.gitignore index 774b9fe2..02de076e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,15 @@ ### APP-SPECIFIC EXCLUSIONS ### + +### Folders ### tmp -database.sqlite -tsconfig.tsbuildinfo -worker/ -transpiled + +### Files ### .env .snyk +**/docker-compose-no-db-local.yml +database.sqlite +**/no-db-local.env +tsconfig.tsbuildinfo ### GENERAL EXCLUSIONS ### diff --git a/README.md b/README.md index 206612ac..10e1e97d 100644 --- a/README.md +++ b/README.md @@ -10,37 +10,14 @@ The purpose of this service is to issue and verify credentials. This service by itself does not take care of storing the credentials. If you'd like to store credentials, you would have to pair this service with [secret-box-service](https://github.com/cheqd/secret-box-service.git). This service is also dependent on [auth0-service](https://github.com/cheqd/auth0-service) -## 📖 Endpoints - -### Issue a credential - -- **Endpoint** POST `/credentials/issue` -- **Accepts**: `application/json` -- **Request Body**: JSON object with following fields - - `attributes` - A json object with all the credential attributes - - `subjectDid` - DID of the holder of the credential - - `type` - A string representation of the credential type e.g. "PERSON" (optional) - - `@context` - context of the issued credential (optional) - - `expirationDate` - Date of expiration of the JWT (optional) -- **Success Response Code**: 200 -- **Invalid Request Response Code** - 400 -- **Internal Error Response Code** - 500 - -### Verify a Credential - -- **Endpoint** POST `/credentials/verify` -- **Accepts**: `application/json` -- **Request Body**: JSON object with following fields: - - `credential` - A verifiable credential or the JWT string -- **Success Response Code** - 200 -- **Invalid Request Response Code**: - - 400: Bad request body - - 405: Wrong content type -- **Internal Error Response Code** - 500 - -### Health Check - -- **Endpoint**: `/` (This endpoint redirects to the swagger api docs) +## 📖 Usage + +We run hosted endpoints for this package (in case you don't want to run it yourself) which have Swagger / OpenAPI definition endpoints that list all of the APIs and how they work. + +The Swagger API definition pages are: + +- [Production / Stable Release APIs](https://credential-service.cheqd.net/swagger/) +- [Staging / Development Release APIs](https://credential-service-staging.cheqd.net/swagger/) ## 🔧 Configuration @@ -50,18 +27,20 @@ The application allows configuring the following parameters using environment va #### Network API endpoints -1. `MAINNET_RPC_URL`: RPC endpoint for cheqd mainnet. (Default: `https://rpc.cheqd.net:443`) -2. `TESTNET_RPC_URL`: RPC endpoint for cheqd testnet. (`https://rpc.cheqd.network:443`) +1. `MAINNET_RPC_URL`: RPC endpoint for cheqd mainnet (Default: `https://rpc.cheqd.net:443`). +2. `TESTNET_RPC_URL`: RPC endpoint for cheqd testnet (`https://rpc.cheqd.network:443`). 3. `RESOLVER_URL`: API endpoint for a [DID Resolver](https://github.com/cheqd/did-resolver) endpoint that supports `did:cheqd`. -4. `APPLICATION_BASE_URL`: URL of the application (external domain name) +4. `APPLICATION_BASE_URL`: URL of the application (external domain name). +5. `ALLOWED_ORIGINS`: CORS allowed origins used in the app. #### Veramo KMS Database The application supports two modes in which keys are managed: either just storing them in-memory while a container is running, or persisting them in a PostgresSQL database with Veramo SDK. Using an external Postgres database allows for "custodian" mode where identity and cheqd/Cosmos keys can be offloaded by client applications to be stored in the database. -1. `DB_CONNECTION_URL`: Postgres database connection URL, e.g. `postgres://:@:/` -2. `DB_ENCRYPTION_KEY`: Secret key used to encrypt the Veramo key-specific database tables. This adds a layer of protection by not storing the database in plaintext. -3. `DB_CERTIFICATE`: Custom CA certificate required to connect to the database (optional). +1. `ENABLE_EXTERNAL_DB`: Turns external database on/off (Default: `false`). If `ENABLE_EXTERNAL_DB=true`, then define below environment variables in `.env` file: + - `EXTERNAL_DB_CONNECTION_URL`: Postgres database connection URL, e.g. `postgres://:@:/`. + - `EXTERNAL_DB_ENCRYPTION_KEY`: Secret key used to encrypt the Veramo key-specific database tables. This adds a layer of protection by not storing the database in plaintext. + - `EXTERNAL_DB_CERTIFICATE`: Custom CA certificate required to connect to the database (optional). #### API Authentication using LogTo @@ -69,15 +48,14 @@ By default, the application has API authentication disabled (which can be change We use a self-hosted version of [LogTo](https://logto.io/), which supports OpenID Connect. Theoretically, these values could also be replaced with [LogTo Cloud](http://cloud.logto.io/) or any other OpenID Connect identity provider. -1. `ENABLE_AUTHENTICATION`: Turns API authentication guards on/off. (Default: `false`) +1. `ENABLE_AUTHENTICATION`: Turns API authentication guards on/off (Default: `false`). If `ENABLE_AUTHENTICATION=false`, then define below environment variable in `.env` file: + - `DEFAULT_CUSTOMER_ID`: Customer/user in LogTo to use for unauthenticated users. 2. `LOGTO_ENDPOINT`: API endpoint for LogTo server 3. `LOGTO_RESOURCE_URL`: API resource associated with application 4. `LOGTO_APP_ID`: Application ID from LogTo. For now, Application is supposed to be a TraditionalWeb 5. `LOGTO_APP_SECRET`: Application secret. Also should encrypted in deployment -6. `ALLOWED_ORIGINS`: CORS allowed origins used in the app -7. `DEFAULT_CUSTOMER_ID`: Customer/user in LogTo to use for unauthenticated users -8. `ALL_SCOPES`: List of all scopes. Should be a string with scopes divided by whitespace, like `account:create account:read did:create` -9. `COOKIE_SECRET`: Secret for cookie encryption. +6. `ALL_SCOPES`: List of all scopes. Should be a string with scopes divided by whitespace, like `account:create account:read did:create` +7. `COOKIE_SECRET`: Secret for cookie encryption. ### 3rd Party Connectors @@ -87,46 +65,49 @@ The app supports 3rd party connectors for credential storage and delivery. The app's [Verida Network](https://www.verida.network/) connector can be enabled to deliver generated credentials to Verida Wallet. -1. `ENABLE_VERIDA_CONNECTOR`: Turns Verida connector on/off. (Default: `false`) -2. `VERIDA_NETWORK`: Verida Network type to connect to. (Default: `testnet`) -3. `VERIDA_PRIVATE_KEY`: Secret key for Verida Network API. -4. `POLYGON_RPC_URL`: Polygon Network RPC URL for connections. -5. `POLYGON_PRIVATE_KEY`: Secret key for Polygon Network. +1. `ENABLE_VERIDA_CONNECTOR`: Turns Verida connector on/off (Default: `false`). If `ENABLE_VERIDA_CONNECTOR=true`, then define below environment variables in `.env` file: + - `VERIDA_NETWORK`: Verida Network type to connect to. (Default: `testnet`) + - `VERIDA_PRIVATE_KEY`: Secret key for Verida Network API. + - `POLYGON_PRIVATE_KEY`: Secret key for Polygon Network. + +## 🧑‍💻🛠 Developer Guide -### Run the application +### Run as standalone application using Docker Compose -Initiate a Postgres database, in case you're using an external database. +If you want to run the application without any external databases or dependent services, we provide [a Docker Compose file](docker/no-external-db/docker-compose-no-db.yml) to spin up a standalone service. ```bash -docker pull postgres -docker run --name some-postgres -e POSTGRES_PASSWORD=mysecretpassword -d postgres +docker compose -f docker/no-external-db/docker-compose-no-db.yml up --detach ``` -Construct the postgres url and configure the env variables mentioned above +This standalone service uses an in-memory database with no persistence, and therefore is recommended only if you're managing key/secret storage separately. -Once configured, the app can be run using NPM: +The [`no-db.env` file](docker/no-external-db/no-db.env) in the same folder contains all the environment variables necessary to configure the service. (See section *Configuration* above.) -```bash -npm start -``` +### Run with external Key Management System (KMS) and/or authentication service using Docker Compose -## 🧑‍💻🛠 Developer Guide +Construct the postgres URL and configure the env variables mentioned above. -### Build using NPM +Spinning up a Docker container from the [pre-built credential-service Docker image on Github](https://github.com/cheqd/credential-service/pkgs/container/credential-service) is as simple as the command below: -Dependencies can be installed using NPM or any other node package manager. +- Running credential-service using Docker with external database: + - Set `POSTGRES_USER`, `POSTGRES_PASSWORD`, `POSTGRES_DB` environment variables in `docker/.env`: + - `POSTGRES_USER`: Postgres database username using in Docker database service. + - `POSTGRES_PASSWORD`: Postgres database password using in Docker database service. + - `POSTGRES_DB`: Postgres database name using in Docker database service. + +Run credential-service with external database: ```bash -npm install -npm run build +docker compose -f docker/docker-compose.yml --profile credential-service-with-external-db up --detach ``` ### Build using Docker -To build and run in Docker, use the [Dockerfile](Dockerfile) provided. +To build your own image using Docker, use the [Dockerfile](docker/Dockerfile) provided. ```bash -docker build -t credential-service . +docker build --file docker/Dockerfile --target runner . --tag credential-service:local ``` ## 🐞 Bug reports & 🤔 feature requests @@ -142,4 +123,3 @@ Please reach out to us there for discussions, help, and feedback on the project. ## 🙋 Find us elsewhere [![Telegram](https://img.shields.io/badge/Telegram-2CA5E0?style=for-the-badge\&logo=telegram\&logoColor=white)](https://t.me/cheqd) [![Discord](https://img.shields.io/badge/Discord-7289DA?style=for-the-badge\&logo=discord\&logoColor=white)](http://cheqd.link/discord-github) [![Twitter](https://img.shields.io/badge/Twitter-1DA1F2?style=for-the-badge\&logo=twitter\&logoColor=white)](https://twitter.com/intent/follow?screen\_name=cheqd\_io) [![LinkedIn](https://img.shields.io/badge/LinkedIn-0077B5?style=for-the-badge\&logo=linkedin\&logoColor=white)](http://cheqd.link/linkedin) [![Slack](https://img.shields.io/badge/Slack-4A154B?style=for-the-badge\&logo=slack\&logoColor=white)](http://cheqd.link/join-cheqd-slack) [![Medium](https://img.shields.io/badge/Medium-12100E?style=for-the-badge\&logo=medium\&logoColor=white)](https://blog.cheqd.io) [![YouTube](https://img.shields.io/badge/YouTube-FF0000?style=for-the-badge\&logo=youtube\&logoColor=white)](https://www.youtube.com/channel/UCBUGvvH6t3BAYo5u41hJPzw/) - diff --git a/custom_button.js b/custom_button.js deleted file mode 100644 index d15c01bc..00000000 --- a/custom_button.js +++ /dev/null @@ -1,30 +0,0 @@ -window.addEventListener("load", function () { - - var base_url = window.location.origin - - var login_button = document.createElement('button') - login_button.innerHTML = 'Log in' - login_button.classList.add('btn', 'authorize') - login_button.onclick = function () { - window.location.href = base_url + '/logto/sign-in' - } - - var user_button = document.createElement('button') - user_button.innerHTML = 'User info' - user_button.classList.add('btn', 'authorize') - user_button.onclick = function () { - window.location.href = base_url + '/user' - } - - var logout_button = document.createElement('button') - logout_button.innerHTML = 'Log out' - logout_button.classList.add('btn', 'authorize') - logout_button.onclick = function () { - window.location.href = base_url + '/logto/sign-out' - } - - var auth_pan = document.getElementsByClassName('auth-wrapper')[0] - auth_pan.appendChild(login_button) - auth_pan.appendChild(user_button) - auth_pan.appendChild(logout_button) -}) \ No newline at end of file diff --git a/Dockerfile b/docker/Dockerfile similarity index 90% rename from Dockerfile rename to docker/Dockerfile index a9f4d41d..ccbd4a9c 100644 --- a/Dockerfile +++ b/docker/Dockerfile @@ -50,9 +50,10 @@ ARG TESTNET_RPC_URL=https://rpc.cheqd.network:443 ARG RESOLVER_URL=https://resolver.cheqd.net/1.0/identifiers/ # Veramo Database configuration: build-time -ARG DB_CONNECTION_URL -ARG DB_ENCRYPTION_KEY -ARG DB_CERTIFICATE +ARG ENABLE_EXTERNAL_DB=false +ARG EXTERNAL_DB_CONNECTION_URL +ARG EXTERNAL_DB_ENCRYPTION_KEY +ARG EXTERNAL_DB_CERT # LogTo: build-time ARG ENABLE_AUTHENTICATION=false @@ -83,9 +84,10 @@ ENV RESOLVER_URL ${RESOLVER_URL} ENV APPLICATION_BASE_URL ${APPLICATION_BASE_URL} # Environment variables: Veramo Database configuration -ENV DB_CONNECTION_URL ${DB_CONNECTION_URL} -ENV DB_ENCRYPTION_KEY ${DB_ENCRYPTION_KEY} -ENV DB_CERTIFICATE ${DB_CERTIFICATE} +ENV ENABLE_EXTERNAL_DB ${ENABLE_EXTERNAL_DB} +ENV EXTERNAL_DB_CONNECTION_URL ${EXTERNAL_DB_CONNECTION_URL} +ENV EXTERNAL_DB_ENCRYPTION_KEY ${EXTERNAL_DB_ENCRYPTION_KEY} +ENV EXTERNAL_DB_CERT ${EXTERNAL_DB_CERT} # Environment variables: LogTo ENV ENABLE_AUTHENTICATION ${ENABLE_AUTHENTICATION} diff --git a/docker/no-external-db/docker-compose-no-db.yml b/docker/no-external-db/docker-compose-no-db.yml new file mode 100644 index 00000000..e80dc3ab --- /dev/null +++ b/docker/no-external-db/docker-compose-no-db.yml @@ -0,0 +1,13 @@ +version: '3.8' + +# CAUTION: Please ensure you edit necessary values in .env.no-db before using this Docker Compose file. + +# SYNTAX: docker compose -f docker/docker-compose-no-db.yml up --detach + +services: + app: + image: ghcr.io/cheqd/credential-service:latest + ports: + - 3000:3000 + env_file: + - no-db.env diff --git a/docker/no-external-db/no-db.env b/docker/no-external-db/no-db.env new file mode 100644 index 00000000..0b3becfa --- /dev/null +++ b/docker/no-external-db/no-db.env @@ -0,0 +1,23 @@ +MAINNET_RPC_URL="https://rpc.cheqd.net:443" +TESTNET_RPC_URL="https://rpc.cheqd.network:443" +RESOLVER_URL="https://resolver.cheqd.net/1.0/identifiers/" +APPLICATION_BASE_URL="http://localhost:3000" +ALLOWED_ORIGINS="http://localhost:3000" + +# Database +ENABLE_EXTERNAL_DB="false" + +# Authentication +ENABLE_AUTHENTICATION="false" + +# verida +ENABLE_VERIDA_CONNECTOR="false" +VERIDA_PRIVATE_KEY="akjvncanv....avoa" +POLYGON_PRIVATE_KEY="alnvca...dvncioa" +VERIDA_NETWORK="testnet" + +# Standalone install (no external DB for KMS) +ISSUER_PUBLIC_KEY_HEX="alnvca...dvncioa" +ISSUER_PRIVATE_KEY_HEX="akjvncanv....avoa" +ISSUER_DID="did:cheqd:testnet:afcnoa...adv" +DEFAULT_FEE_PAYER_MNEMONIC="sketch mountain ....." diff --git a/docker/with-external-db/docker-compose-with-db.yml b/docker/with-external-db/docker-compose-with-db.yml new file mode 100644 index 00000000..3d9a1b2b --- /dev/null +++ b/docker/with-external-db/docker-compose-with-db.yml @@ -0,0 +1,67 @@ +version: '3.8' + +# CAUTION: Please ensure you edit necessary values in .env before using this Docker Compose file. + +# SYNTAX: docker compose -f docker/docker-compose.yml up --detach + +services: + app: + image: ghcr.io/cheqd/credential-service:latest + depends_on: + postgres: + condition: service_healthy + ports: + - 3000:3000 + env_file: + - .env.with-db + + app-migrations: + image: ghcr.io/cheqd/credential-service:latest + depends_on: + postgres: + condition: service_healthy + ports: + - 3000:3000 + env_file: + - .env.with-db + entrypoint: [ "npm", "run", "migrate", "&&", "npm", "run", "start" ] + profiles: + - setup + + logto: + image: ghcr.io/cheqd/creds-auth:latest + ports: + - 3001:3001 + - 3002:3002 + env_file: + - .env + profiles: + - logto + + logto-migrations: + image: ghcr.io/cheqd/creds-auth:latest + ports: + - 3001:3001 + - 3002:3002 + env_file: + - .env + entrypoint: [ "npm", "run", "migrate", "&&", "npm", "run", "seed" ] + profiles: + - setup + - logto + + postgres: + image: postgres + user: postgres + ports: + - 5432:5432 + env_file: + - .env + healthcheck: + test: [ "CMD-SHELL", "pg_isready" ] + interval: 10s + timeout: 5s + retries: 5 + profiles: + - external-kms + - logto diff --git a/docker/with-external-db/with-db.env b/docker/with-external-db/with-db.env new file mode 100644 index 00000000..0b3becfa --- /dev/null +++ b/docker/with-external-db/with-db.env @@ -0,0 +1,23 @@ +MAINNET_RPC_URL="https://rpc.cheqd.net:443" +TESTNET_RPC_URL="https://rpc.cheqd.network:443" +RESOLVER_URL="https://resolver.cheqd.net/1.0/identifiers/" +APPLICATION_BASE_URL="http://localhost:3000" +ALLOWED_ORIGINS="http://localhost:3000" + +# Database +ENABLE_EXTERNAL_DB="false" + +# Authentication +ENABLE_AUTHENTICATION="false" + +# verida +ENABLE_VERIDA_CONNECTOR="false" +VERIDA_PRIVATE_KEY="akjvncanv....avoa" +POLYGON_PRIVATE_KEY="alnvca...dvncioa" +VERIDA_NETWORK="testnet" + +# Standalone install (no external DB for KMS) +ISSUER_PUBLIC_KEY_HEX="alnvca...dvncioa" +ISSUER_PRIVATE_KEY_HEX="akjvncanv....avoa" +ISSUER_DID="did:cheqd:testnet:afcnoa...adv" +DEFAULT_FEE_PAYER_MNEMONIC="sketch mountain ....." diff --git a/.env.example b/example.env similarity index 66% rename from .env.example rename to example.env index d19ed9f5..bb83e5a6 100644 --- a/.env.example +++ b/example.env @@ -1,14 +1,14 @@ -MAINNET_RPC_URL=https://rpc.cheqd.net:443 -TESTNET_RPC_URL=https://rpc.cheqd.network:443 +MAINNET_RPC_URL="https://rpc.cheqd.net:443" +TESTNET_RPC_URL="https://rpc.cheqd.network:443" RESOLVER_URL="https://resolver.cheqd.net/1.0/identifiers/" -ALLOWED_ORIGINS="http://localhost:8787" APPLICATION_BASE_URL="http://localhost:8787" +ALLOWED_ORIGINS="http://localhost:8787" # Database ENABLE_EXTERNAL_DB="false" -EXTERNAL_DB_CONNECTION_URL=postgres://logto:password@localhost:5432/logto +EXTERNAL_DB_CONNECTION_URL="postgres://:@:/" EXTERNAL_DB_ENCRYPTION_KEY="" -# EXTERNAL_DB_CERT="certs/issuer.crt" +EXTERNAL_DB_CERT="" # OpenId LOGTO_RESOURCE_URL='http://localhost:8787' @@ -20,7 +20,7 @@ LOGTO_APP_SECRET='sdf...sdf' COOKIE_SECRET='sdf...sdf' # Authentication -ENABLE_AUTHENTICATION="boolean,default:false" +ENABLE_AUTHENTICATION="false" DEFAULT_CUSTOMER_ID="default customer id" ALL_SCOPES="account:create did:create credential:issue" @@ -32,7 +32,7 @@ POLYGON_PRIVATE_KEY="alnvca...dvncioa" VERIDA_NETWORK="testnet" # Without Database -ISSUER_ID_PRIVATE_KEY_HEX="akjvncanv....avoa" -ISSUER_ID_PUBLIC_KEY_HEX="alnvca...dvncioa" +ISSUER_PRIVATE_KEY_HEX="akjvncanv....avoa" +ISSUER_PUBLIC_KEY_HEX="alnvca...dvncioa" ISSUER_DID="did:cheqd:testnet:afcnoa...adv" -FEE_PAYER_MNEMONIC="sketch mountain ....." \ No newline at end of file +DEFAULT_FEE_PAYER_MNEMONIC="sketch mountain ....." \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index e99982e5..e3b9021c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@cheqd/credential-service", - "version": "2.3.0", + "version": "2.3.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@cheqd/credential-service", - "version": "2.3.0", + "version": "2.3.1", "license": "Apache-2.0", "dependencies": { - "@cheqd/did-provider-cheqd": "^3.3.1", + "@cheqd/did-provider-cheqd": "3.3.1", "@cosmjs/amino": "^0.30.1", "@cosmjs/encoding": "^0.30.1", "@logto/express": "^2.0.1", diff --git a/package.json b/package.json index c10c3c8e..bbd78d8c 100644 --- a/package.json +++ b/package.json @@ -11,24 +11,22 @@ "exports": { ".": { "types": "./dist/types/index.d.ts", - "import": "./dist/src/index.js", - "default": "./dist/src/index.js" + "import": "./dist/index.js", + "default": "./dist/index.js" }, "./*": { "types": "./dist/types/*.d.ts", - "import": "./dist/src/*.js", - "default": "./dist/src/*.js" + "import": "./dist/*.js", + "default": "./dist/*.js" } }, "scripts": { - "copy-files": "copyfiles -u 1 src/static/**/*.js dist/src", - "postbuild": "npm run copy-files", "build": "tsc", - "start": "node dist/src/index.js", + "start": "node dist/index.js", "format": "prettier --write '*.{json,js}' 'src/**/*.{js,ts}' 'test/**/*.{js,ts}'", "lint": "eslint --max-warnings=0 src && prettier --check '*.{json,js}' 'src/**/*.{js,ts}' 'test/**/*.{js,ts}'", "test": "jest --config jestconfig.json --verbose", - "typeorm": "typeorm-ts-node-esm -d ./dist/src/database/ormconfig.js", + "typeorm": "typeorm-ts-node-esm -d ./dist/database/ormconfig.js", "migration": "npm run typeorm migration:generate . && npm run typeorm migration:run" }, "eslintConfig": { @@ -45,7 +43,7 @@ "README.md" ], "dependencies": { - "@cheqd/did-provider-cheqd": "^3.3.1", + "@cheqd/did-provider-cheqd": "3.3.1", "@cosmjs/amino": "^0.30.1", "@cosmjs/encoding": "^0.30.1", "@logto/express": "^2.0.1", diff --git a/src/app.ts b/src/app.ts index 32f97155..6d9a3ecf 100644 --- a/src/app.ts +++ b/src/app.ts @@ -15,7 +15,7 @@ import { Connection } from './database/connection/connection.js' import { RevocationController } from './controllers/revocation.js' import { CORS_ERROR_MSG, configLogToExpress } from './types/constants.js' -import swaggerJSONDoc from '../swagger.json' assert { type: "json" } +import swaggerJSONDoc from './static/swagger.json' assert { type: "json" } import * as dotenv from 'dotenv' dotenv.config() @@ -24,7 +24,7 @@ import { UserInfo } from './controllers/user_info.js' import path from 'path' const swagger_options = { - customJs: '/static/custom_button.js', + customJs: '/static/custom-button.js', } class App { @@ -103,9 +103,9 @@ class App { app.get(`/account`, new CustomerController().get) // static files - app.get('/static/custom_button.js', + app.get('/static/custom-button.js', express.static( - path.join(process.cwd(), '/dist/src'), + path.join(process.cwd(), '/dist'), {extensions: ['js'], index: false})) // 404 for all other requests diff --git a/src/services/identity/index.ts b/src/services/identity/index.ts index b4bf3962..6853f06a 100644 --- a/src/services/identity/index.ts +++ b/src/services/identity/index.ts @@ -11,11 +11,10 @@ export class Identity { static instance = new Identity().agent constructor() { - if (process.env.ENABLE_EXTERNAL_DB == 'true') { - this.agent = PostgresIdentity.instance + if (process.env.ENABLE_EXTERNAL_DB === 'true') { + this.agent = new PostgresIdentity() } else { - this.agent = LocalIdentity.instance + this.agent = new LocalIdentity() } - this.agent.initAgent() } -} \ No newline at end of file +} diff --git a/src/services/identity/local.ts b/src/services/identity/local.ts index 8f1f7ea8..325d9d23 100644 --- a/src/services/identity/local.ts +++ b/src/services/identity/local.ts @@ -23,9 +23,9 @@ dotenv.config() const { MAINNET_RPC_URL, TESTNET_RPC_URL, - FEE_PAYER_MNEMONIC, - ISSUER_ID_PUBLIC_KEY_HEX, - ISSUER_ID_PRIVATE_KEY_HEX, + DEFAULT_FEE_PAYER_MNEMONIC, + ISSUER_PUBLIC_KEY_HEX, + ISSUER_PRIVATE_KEY_HEX, ISSUER_DID } = process.env @@ -34,8 +34,12 @@ export class LocalIdentity implements IIdentity { privateStore?: AbstractPrivateKeyStore public static instance = new LocalIdentity() + constructor() { + this.agent = this.initAgent() + } + initAgent() { - if (!FEE_PAYER_MNEMONIC) { + if (!DEFAULT_FEE_PAYER_MNEMONIC) { throw new Error(`No fee payer found`) } if(this.agent) { @@ -47,7 +51,7 @@ export class LocalIdentity implements IIdentity { const mainnetProvider = new CheqdDIDProvider( { defaultKms: 'local', - cosmosPayerSeed: FEE_PAYER_MNEMONIC, + cosmosPayerSeed: DEFAULT_FEE_PAYER_MNEMONIC, networkType: CheqdNetwork.Mainnet, rpcUrl: MAINNET_RPC_URL || DefaultRPCUrl.Mainnet, } @@ -55,7 +59,7 @@ export class LocalIdentity implements IIdentity { const testnetProvider = new CheqdDIDProvider( { defaultKms: 'local', - cosmosPayerSeed: FEE_PAYER_MNEMONIC, + cosmosPayerSeed: DEFAULT_FEE_PAYER_MNEMONIC, networkType: CheqdNetwork.Testnet, rpcUrl: TESTNET_RPC_URL || DefaultRPCUrl.Testnet, } @@ -103,11 +107,11 @@ export class LocalIdentity implements IIdentity { } async importDid(): Promise { - if (!(ISSUER_DID && ISSUER_ID_PUBLIC_KEY_HEX && ISSUER_ID_PRIVATE_KEY_HEX)) throw new Error('No DIDs and Keys found') + if (!(ISSUER_DID && ISSUER_PUBLIC_KEY_HEX && ISSUER_PRIVATE_KEY_HEX)) throw new Error('No DIDs and Keys found') try { return await this.getDid(ISSUER_DID) } catch { - const identifier: IIdentifier = await Veramo.instance.importDid(this.initAgent(), ISSUER_DID, ISSUER_ID_PRIVATE_KEY_HEX, ISSUER_ID_PUBLIC_KEY_HEX) + const identifier: IIdentifier = await Veramo.instance.importDid(this.initAgent(), ISSUER_DID, ISSUER_PRIVATE_KEY_HEX, ISSUER_PUBLIC_KEY_HEX) return identifier } } diff --git a/src/services/identity/postgres.ts b/src/services/identity/postgres.ts index 488351bd..d662eb5e 100644 --- a/src/services/identity/postgres.ts +++ b/src/services/identity/postgres.ts @@ -35,8 +35,7 @@ const { export class PostgresIdentity implements IIdentity { agent: TAgent privateStore?: AbstractPrivateKeyStore - public static instance = new PostgresIdentity() - + constructor() { this.agent = this.initAgent() } diff --git a/src/static/custom-button.ts b/src/static/custom-button.ts new file mode 100644 index 00000000..9f2f1729 --- /dev/null +++ b/src/static/custom-button.ts @@ -0,0 +1,30 @@ +window.addEventListener("load", function () { + const base_url: string = window.location.origin; + + const login_button: HTMLButtonElement = document.createElement('button'); + login_button.innerHTML = 'Log in'; + login_button.classList.add('btn', 'authorize'); + login_button.onclick = function () { + window.location.href = base_url + '/logto/sign-in'; + }; + + const user_button: HTMLButtonElement = document.createElement('button'); + user_button.innerHTML = 'User info'; + user_button.classList.add('btn', 'authorize'); + user_button.onclick = function () { + window.location.href = base_url + '/user'; + }; + + const logout_button: HTMLButtonElement = document.createElement('button'); + logout_button.innerHTML = 'Log out'; + logout_button.classList.add('btn', 'authorize'); + logout_button.onclick = function () { + window.location.href = base_url + '/logto/sign-out'; + }; + + const auth_pan: Element = document.getElementsByClassName('auth-wrapper')[0]; + auth_pan.appendChild(login_button); + auth_pan.appendChild(user_button); + auth_pan.appendChild(logout_button); + }); + \ No newline at end of file diff --git a/src/static/custom_button.js b/src/static/custom_button.js deleted file mode 100644 index d15c01bc..00000000 --- a/src/static/custom_button.js +++ /dev/null @@ -1,30 +0,0 @@ -window.addEventListener("load", function () { - - var base_url = window.location.origin - - var login_button = document.createElement('button') - login_button.innerHTML = 'Log in' - login_button.classList.add('btn', 'authorize') - login_button.onclick = function () { - window.location.href = base_url + '/logto/sign-in' - } - - var user_button = document.createElement('button') - user_button.innerHTML = 'User info' - user_button.classList.add('btn', 'authorize') - user_button.onclick = function () { - window.location.href = base_url + '/user' - } - - var logout_button = document.createElement('button') - logout_button.innerHTML = 'Log out' - logout_button.classList.add('btn', 'authorize') - logout_button.onclick = function () { - window.location.href = base_url + '/logto/sign-out' - } - - var auth_pan = document.getElementsByClassName('auth-wrapper')[0] - auth_pan.appendChild(login_button) - auth_pan.appendChild(user_button) - auth_pan.appendChild(logout_button) -}) \ No newline at end of file diff --git a/swagger.json b/src/static/swagger.json similarity index 100% rename from swagger.json rename to src/static/swagger.json diff --git a/src/types/environment.d.ts b/src/types/environment.d.ts index fa3f0232..28d59a20 100644 --- a/src/types/environment.d.ts +++ b/src/types/environment.d.ts @@ -14,11 +14,10 @@ declare global { TESTNET_RPC_URL: string RESOLVER_URL: string ALLOWED_ORIGINS: string | undefined - ENABLE_EXTERNAL_DB: string + ENABLE_EXTERNAL_DB: string | "false" EXTERNAL_DB_CONNECTION_URL: string EXTERNAL_DB_ENCRYPTION_KEY: string EXTERNAL_DB_CERT: string | undefined - ISSUER_DATABASE_CERT: string | undefined APPLICATION_BASE_URL: string // LogTo @@ -28,22 +27,22 @@ declare global { LOGTO_RESOURCE_URL: string // Authentication - ENABLE_AUTHENTICATION: string + ENABLE_AUTHENTICATION: string | "false" DEFAULT_CUSTOMER_ID: string | undefined ALL_SCOPES: string COOKIE_SECRET: string // Verida - ENABLE_VERIDA_CONNECTOR: string + ENABLE_VERIDA_CONNECTOR: string | "false" VERIDA_NETWORK: NetworkType POLYGON_RPC_URL: string VERIDA_PRIVATE_KEY: string POLYGON_PRIVATE_KEY: string // Without external db - ISSUER_ID_PRIVATE_KEY_HEX: string - ISSUER_ID_PUBLIC_KEY_HEX: string - FEE_PAYER_MNEMONIC: string + ISSUER_PRIVATE_KEY_HEX: string + ISSUER_PUBLIC_KEY_HEX: string + DEFAULT_FEE_PAYER_MNEMONIC: string ISSUER_DID: string } } diff --git a/src/types/types.ts b/src/types/types.ts index 96232a5b..8eb71940 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -118,7 +118,7 @@ class MethodToScope { export class ApiGuarding { private routeToScoupe: MethodToScope[] = [] - private static pathSkip = ['/', '/swagger', '/user', '/static/custom_button.js'] + private static pathSkip = ['/', '/swagger', '/user', '/static/custom-button.js'] private static regExpSkip = new RegExp("^/.*js") constructor() { this.registerRoute('/account', 'GET', 'account:read') diff --git a/tsconfig.json b/tsconfig.json index 3dcea717..e7040e40 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,7 +15,7 @@ "sourceMap": true, /* Generates corresponding '.map' file. */ // "outFile": "./", /* Concatenate and emit output to single file. */ "outDir": "dist", /* Redirect output structure to the directory. */ - // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + "rootDir": "src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ // "composite": true, /* Enable project compilation */ // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ // "removeComments": true, /* Do not emit comments to output. */