diff --git a/.env.example b/.env.example
index d81932bd..b31437a3 100644
--- a/.env.example
+++ b/.env.example
@@ -71,3 +71,5 @@ EREPUTATION_MAPPING_DB_PATH="/path/to/erep/mapping/db"
VITE_EREPUTATION_BASE_URL=http://localhost:8765
LOAD_TEST_USER_COUNT=6
+
+PUBLIC_EID_WALLET_TOKEN=obtained-from-post-registry-service-/platforms/certification
diff --git a/db/init-multiple-databases.sh b/db/init-multiple-databases.sh
new file mode 100755
index 00000000..299ad717
--- /dev/null
+++ b/db/init-multiple-databases.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+set -e
+
+# Get the list of databases from environment variable
+# Default to empty if not set
+POSTGRES_MULTIPLE_DATABASES=${POSTGRES_MULTIPLE_DATABASES:-}
+
+# If no databases specified, exit
+if [ -z "$POSTGRES_MULTIPLE_DATABASES" ]; then
+ echo "No databases specified in POSTGRES_MULTIPLE_DATABASES"
+ exit 0
+fi
+
+echo "Creating multiple databases..."
+
+# Split the comma-separated list and create each database
+IFS=',' read -ra DATABASES <<< "$POSTGRES_MULTIPLE_DATABASES"
+for db in "${DATABASES[@]}"; do
+ # Trim whitespace
+ db=$(echo "$db" | xargs)
+
+ if [ -n "$db" ]; then
+ # Check if database exists
+ DB_EXISTS=$(psql -v ON_ERROR_STOP=0 --username "$POSTGRES_USER" --dbname postgres -tAc "SELECT 1 FROM pg_database WHERE datname='$db'" 2>/dev/null || echo "")
+
+ if [ "$DB_EXISTS" = "1" ]; then
+ echo "Database $db already exists, skipping..."
+ else
+ echo "Creating database: $db"
+ # Create the database directly (not inside a function)
+ psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname postgres <<-EOSQL
+ CREATE DATABASE "$db";
+EOSQL
+ fi
+ fi
+done
+
+echo "Multiple databases created successfully!"
+
diff --git a/dev-docker-compose.yaml b/dev-docker-compose.yaml
index f17b6dbc..ec998f71 100644
--- a/dev-docker-compose.yaml
+++ b/dev-docker-compose.yaml
@@ -126,6 +126,19 @@ services:
networks:
- metastate-network
<<: *common-host-access
+ entrypoint: ["/bin/sh", "-c"]
+ command:
+ - |
+ # Remove any stale PID files before starting Neo4j
+ # Neo4j stores PID files in /var/lib/neo4j/run/neo4j.pid
+ rm -f /var/lib/neo4j/run/neo4j.pid 2>/dev/null || true
+ rm -f /var/lib/neo4j/data/run/neo4j.pid 2>/dev/null || true
+ rm -f /var/lib/neo4j/data/neo4j.pid 2>/dev/null || true
+ # Also clean up any other PID files
+ find /var/lib/neo4j -name "*.pid" -type f -delete 2>/dev/null || true
+ find /var/lib/neo4j/data -name "*.pid" -type f -delete 2>/dev/null || true
+ # Start Neo4j with the original entrypoint
+ exec /startup/docker-entrypoint.sh neo4j
healthcheck:
test: [ "CMD-SHELL", "cypher-shell -u neo4j -p ${NEO4J_PASSWORD:-neo4j} 'RETURN 1' || exit 1" ]
interval: 10s
diff --git a/infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/Project.xml b/infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/Project.xml
new file mode 100644
index 00000000..7643783a
--- /dev/null
+++ b/infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/Project.xml
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ xmlns:android
+
+ ^$
+
+
+
+
+
+
+
+
+ xmlns:.*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*:id
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ .*:name
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ name
+
+ ^$
+
+
+
+
+
+
+
+
+ style
+
+ ^$
+
+
+
+
+
+
+
+
+ .*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*
+
+ http://schemas.android.com/apk/res/android
+
+
+ ANDROID_ATTRIBUTE_ORDER
+
+
+
+
+
+
+ .*
+
+ .*
+
+
+ BY_NAME
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/codeStyleConfig.xml b/infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 00000000..79ee123c
--- /dev/null
+++ b/infrastructure/eid-wallet/src-tauri/gen/android/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/infrastructure/eid-wallet/src-tauri/gen/android/.idea/kotlinc.xml b/infrastructure/eid-wallet/src-tauri/gen/android/.idea/kotlinc.xml
index 4cb74572..fe63bb67 100644
--- a/infrastructure/eid-wallet/src-tauri/gen/android/.idea/kotlinc.xml
+++ b/infrastructure/eid-wallet/src-tauri/gen/android/.idea/kotlinc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/infrastructure/eid-wallet/src/lib/global/controllers/evault.ts b/infrastructure/eid-wallet/src/lib/global/controllers/evault.ts
index 917f6ab4..349f9618 100644
--- a/infrastructure/eid-wallet/src/lib/global/controllers/evault.ts
+++ b/infrastructure/eid-wallet/src/lib/global/controllers/evault.ts
@@ -1,14 +1,14 @@
import {
- PUBLIC_REGISTRY_URL,
- PUBLIC_PROVISIONER_URL,
PUBLIC_EID_WALLET_TOKEN,
+ PUBLIC_PROVISIONER_URL,
+ PUBLIC_REGISTRY_URL,
} from "$env/static/public";
import type { Store } from "@tauri-apps/plugin-store";
import axios from "axios";
import { GraphQLClient } from "graphql-request";
import NotificationService from "../../services/NotificationService";
-import type { UserController } from "./user";
import type { KeyService } from "./key";
+import type { UserController } from "./user";
const STORE_META_ENVELOPE = `
mutation StoreMetaEnvelope($input: MetaEnvelopeInput!) {
@@ -176,7 +176,7 @@ export class VaultController {
};
if (authToken) {
- headers["Authorization"] = `Bearer ${authToken}`;
+ headers.Authorization = `Bearer ${authToken}`;
}
await axios.patch(patchUrl, { publicKey }, { headers });
diff --git a/infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte b/infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte
index 5027dc51..6628964f 100644
--- a/infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte
+++ b/infrastructure/eid-wallet/src/routes/(auth)/onboarding/+page.svelte
@@ -198,6 +198,7 @@ onMount(async () => {
new URL("/entropy", PUBLIC_REGISTRY_URL).toString(),
);
const registryEntropy = entropyRes.data.token;
+ console.log("Registry entropy:", registryEntropy);
const provisionRes = await axios.post(
new URL("/provision", PUBLIC_PROVISIONER_URL).toString(),
@@ -208,6 +209,7 @@ onMount(async () => {
publicKey: await getApplicationPublicKey(),
},
);
+ console.log("Provision response:", provisionRes.data);
if (!provisionRes.data?.success) {
throw new Error("Invalid verification code");
diff --git a/infrastructure/evault-core/src/core/http/server.ts b/infrastructure/evault-core/src/core/http/server.ts
index 898901de..c4cacb63 100644
--- a/infrastructure/evault-core/src/core/http/server.ts
+++ b/infrastructure/evault-core/src/core/http/server.ts
@@ -1,116 +1,125 @@
-import fastify, { FastifyInstance } from "fastify";
import swagger from "@fastify/swagger";
import swaggerUi from "@fastify/swagger-ui";
-import { WatcherRequest, TypedRequest, TypedReply } from "./types";
-import { ProvisioningService, ProvisionRequest } from "../../services/ProvisioningService";
-import { DbService } from "../db/db.service";
-import * as jose from "jose";
import axios from "axios";
+import fastify, { type FastifyInstance } from "fastify";
+import * as jose from "jose";
+import type {
+ ProvisionRequest,
+ ProvisioningService,
+} from "../../services/ProvisioningService";
+import type { DbService } from "../db/db.service";
+import { type TypedReply, type TypedRequest, WatcherRequest } from "./types";
interface WatcherSignatureRequest {
- w3id: string;
- logEntryId: string;
- proof: {
- signature: string;
- alg: string;
- kid: string;
- };
+ w3id: string;
+ logEntryId: string;
+ proof: {
+ signature: string;
+ alg: string;
+ kid: string;
+ };
}
export async function registerHttpRoutes(
- server: FastifyInstance,
- evault: any, // EVault instance to access publicKey
- provisioningService?: ProvisioningService,
- dbService?: DbService
+ server: FastifyInstance,
+ evault: any, // EVault instance to access publicKey
+ provisioningService?: ProvisioningService,
+ dbService?: DbService,
): Promise {
- // Register Swagger
- await server.register(swagger, {
- swagger: {
- info: {
- title: "eVault Core API",
- description: "API documentation for eVault Core HTTP endpoints",
- version: "1.0.0",
- },
- tags: [
- { name: "identity", description: "Identity related endpoints" },
- {
- name: "watchers",
- description: "Watcher signature related endpoints",
- },
- {
- name: "provisioning",
- description: "eVault provisioning endpoints",
+ // Register Swagger
+ await server.register(swagger, {
+ swagger: {
+ info: {
+ title: "eVault Core API",
+ description: "API documentation for eVault Core HTTP endpoints",
+ version: "1.0.0",
+ },
+ tags: [
+ { name: "identity", description: "Identity related endpoints" },
+ {
+ name: "watchers",
+ description: "Watcher signature related endpoints",
+ },
+ {
+ name: "provisioning",
+ description: "eVault provisioning endpoints",
+ },
+ ],
},
- ],
- },
- });
+ });
- await server.register(swaggerUi, {
- routePrefix: "/docs",
- });
+ await server.register(swaggerUi, {
+ routePrefix: "/docs",
+ });
- // Whois endpoint - returns both W3ID identifier and public key
- server.get(
- "/whois",
- {
- schema: {
- tags: ["identity"],
- description: "Get eVault W3ID identifier and public key",
- headers: {
- type: "object",
- required: ["X-ENAME"],
- properties: {
- "X-ENAME": { type: "string" },
- },
- },
- response: {
- 200: {
- type: "object",
- properties: {
- w3id: { type: "string" },
- publicKey: { type: "string", nullable: true },
- },
- },
- 400: {
- type: "object",
- properties: {
- error: { type: "string" },
+ // Whois endpoint - returns both W3ID identifier and public key
+ server.get(
+ "/whois",
+ {
+ schema: {
+ tags: ["identity"],
+ description: "Get eVault W3ID identifier and public key",
+ headers: {
+ type: "object",
+ required: ["X-ENAME"],
+ properties: {
+ "X-ENAME": { type: "string" },
+ },
+ },
+ response: {
+ 200: {
+ type: "object",
+ properties: {
+ w3id: { type: "string" },
+ publicKey: { type: "string", nullable: true },
+ },
+ },
+ 400: {
+ type: "object",
+ properties: {
+ error: { type: "string" },
+ },
+ },
+ },
},
- },
},
- },
- },
- async (request: TypedRequest<{}>, reply: TypedReply) => {
- const eName = request.headers["x-ename"] || request.headers["X-ENAME"];
-
- if (!eName || typeof eName !== "string") {
- return reply.status(400).send({ error: "X-ENAME header is required" });
- }
-
- // Get public key from database if dbService is available
- let publicKey: string | null = null;
- if (dbService) {
- try {
- publicKey = await dbService.getPublicKey(eName);
- } catch (error) {
- console.error("Error getting public key from database:", error);
- // Continue with null publicKey
- }
- }
-
- const result = {
- w3id: eName,
- publicKey: publicKey,
- };
- console.log("Whois request:", result);
- return result;
- }
- );
+ async (request: TypedRequest<{}>, reply: TypedReply) => {
+ const eName =
+ request.headers["x-ename"] || request.headers["X-ENAME"];
+
+ if (!eName || typeof eName !== "string") {
+ return reply
+ .status(400)
+ .send({ error: "X-ENAME header is required" });
+ }
+
+ // Get public key from database if dbService is available
+ let publicKey: string | null = null;
+ if (dbService) {
+ try {
+ publicKey = await dbService.getPublicKey(eName);
+ } catch (error) {
+ console.error(
+ "Error getting public key from database:",
+ error,
+ );
+ // Continue with null publicKey
+ }
+ }
+
+ const result = {
+ w3id: eName,
+ publicKey: publicKey,
+ };
+ console.log("Whois request:", result);
+ return result;
+ },
+ );
- // Watchers signature endpoint - DISABLED: Requires W3ID functionality
- // This endpoint is disabled because the eVault no longer creates/manages W3IDs
- // The private key is now stored on the user's phone
- /*
+ // Watchers signature endpoint - DISABLED: Requires W3ID functionality
+ // This endpoint is disabled because the eVault no longer creates/manages W3IDs
+ // The private key is now stored on the user's phone
+ /*
server.post<{ Body: WatcherSignatureRequest }>(
"/watchers/sign",
{
@@ -199,10 +208,10 @@ export async function registerHttpRoutes(
);
*/
- // Watchers request endpoint - DISABLED: Requires W3ID functionality
- // This endpoint is disabled because the eVault no longer creates/manages W3IDs
- // The private key is now stored on the user's phone
- /*
+ // Watchers request endpoint - DISABLED: Requires W3ID functionality
+ // This endpoint is disabled because the eVault no longer creates/manages W3IDs
+ // The private key is now stored on the user's phone
+ /*
server.post<{ Body: WatcherRequest }>(
"/watchers/request",
{
@@ -283,181 +292,228 @@ export async function registerHttpRoutes(
);
*/
- // Helper function to validate JWT token
- async function validateToken(authHeader: string | null): Promise {
- if (!authHeader || !authHeader.startsWith("Bearer ")) {
- console.error("Token validation: Missing or invalid Authorization header format");
- return null;
- }
-
- const token = authHeader.substring(7); // Remove 'Bearer ' prefix
+ // Helper function to validate JWT token
+ async function validateToken(
+ authHeader: string | null,
+ ): Promise {
+ if (!authHeader || !authHeader.startsWith("Bearer ")) {
+ console.error(
+ "Token validation: Missing or invalid Authorization header format",
+ );
+ return null;
+ }
- try {
- // Try REGISTRY_URL first, fallback to PUBLIC_REGISTRY_URL
- const registryUrl = process.env.REGISTRY_URL || process.env.PUBLIC_REGISTRY_URL;
- if (!registryUrl) {
- console.error("Token validation: REGISTRY_URL or PUBLIC_REGISTRY_URL is not set");
- return null;
- }
+ const token = authHeader.substring(7); // Remove 'Bearer ' prefix
- const jwksUrl = new URL(`/.well-known/jwks.json`, registryUrl).toString();
- console.log(`Token validation: Fetching JWKS from ${jwksUrl}`);
-
- const jwksResponse = await axios.get(jwksUrl, {
- timeout: 5000,
- });
-
- console.log(`Token validation: JWKS response keys count: ${jwksResponse.data?.keys?.length || 0}`);
-
- const JWKS = jose.createLocalJWKSet(jwksResponse.data);
-
- // Decode token header to see what kid it's using
- const decodedHeader = jose.decodeProtectedHeader(token);
- console.log(`Token validation: Token header - alg: ${decodedHeader.alg}, kid: ${decodedHeader.kid}`);
-
- const { payload } = await jose.jwtVerify(token, JWKS);
-
- console.log(`Token validation: Token verified successfully, payload:`, payload);
- return payload;
- } catch (error: any) {
- console.error("Token validation failed:", error.message || error);
- if (error.code) {
- console.error(`Token validation error code: ${error.code}`);
- }
- if (error.response) {
- console.error(`Token validation HTTP error: ${error.response.status} - ${error.response.statusText}`);
- }
- if (error.cause) {
- console.error(`Token validation error cause:`, error.cause);
- }
- return null;
+ try {
+ // Try REGISTRY_URL first, fallback to PUBLIC_REGISTRY_URL
+ const registryUrl =
+ process.env.REGISTRY_URL || process.env.PUBLIC_REGISTRY_URL;
+ if (!registryUrl) {
+ console.error(
+ "Token validation: REGISTRY_URL or PUBLIC_REGISTRY_URL is not set",
+ );
+ return null;
+ }
+
+ const jwksUrl = new URL(
+ "/.well-known/jwks.json",
+ registryUrl,
+ ).toString();
+ console.log(`Token validation: Fetching JWKS from ${jwksUrl}`);
+
+ const jwksResponse = await axios.get(jwksUrl, {
+ timeout: 5000,
+ });
+
+ console.log(
+ `Token validation: JWKS response keys count: ${jwksResponse.data?.keys?.length || 0}`,
+ );
+
+ const JWKS = jose.createLocalJWKSet(jwksResponse.data);
+
+ // Decode token header to see what kid it's using
+ const decodedHeader = jose.decodeProtectedHeader(token);
+ console.log(
+ `Token validation: Token header - alg: ${decodedHeader.alg}, kid: ${decodedHeader.kid}`,
+ );
+
+ const { payload } = await jose.jwtVerify(token, JWKS);
+
+ console.log(
+ `Token validation: Token verified successfully, payload:`,
+ payload,
+ );
+ return payload;
+ } catch (error: any) {
+ console.error("Token validation failed:", error.message || error);
+ if (error.code) {
+ console.error(`Token validation error code: ${error.code}`);
+ }
+ if (error.response) {
+ console.error(
+ `Token validation HTTP error: ${error.response.status} - ${error.response.statusText}`,
+ );
+ }
+ if (error.cause) {
+ console.error(`Token validation error cause:`, error.cause);
+ }
+ return null;
+ }
}
- }
- // PATCH endpoint to save public key
- server.patch<{ Body: { publicKey: string } }>(
- "/public-key",
- {
- schema: {
- tags: ["identity"],
- description: "Save public key for a user's eName",
- headers: {
- type: "object",
- required: ["X-ENAME", "Authorization"],
- properties: {
- "X-ENAME": { type: "string" },
- "Authorization": { type: "string" },
- },
- },
- body: {
- type: "object",
- required: ["publicKey"],
- properties: {
- publicKey: { type: "string" },
- },
- },
- response: {
- 200: {
- type: "object",
- properties: {
- success: { type: "boolean" },
- message: { type: "string" },
- },
- },
- 400: {
- type: "object",
- properties: {
- error: { type: "string" },
- },
- },
- 401: {
- type: "object",
- properties: {
- error: { type: "string" },
+ // PATCH endpoint to save public key
+ server.patch<{ Body: { publicKey: string } }>(
+ "/public-key",
+ {
+ schema: {
+ tags: ["identity"],
+ description: "Save public key for a user's eName",
+ headers: {
+ type: "object",
+ required: ["X-ENAME", "Authorization"],
+ properties: {
+ "X-ENAME": { type: "string" },
+ Authorization: { type: "string" },
+ },
+ },
+ body: {
+ type: "object",
+ required: ["publicKey"],
+ properties: {
+ publicKey: { type: "string" },
+ },
+ },
+ response: {
+ 200: {
+ type: "object",
+ properties: {
+ success: { type: "boolean" },
+ message: { type: "string" },
+ },
+ },
+ 400: {
+ type: "object",
+ properties: {
+ error: { type: "string" },
+ },
+ },
+ 401: {
+ type: "object",
+ properties: {
+ error: { type: "string" },
+ },
+ },
+ },
},
- },
},
- },
- },
- async (request: TypedRequest<{ publicKey: string }>, reply: TypedReply) => {
- const eName = request.headers["x-ename"] || request.headers["X-ENAME"];
-
- if (!eName || typeof eName !== "string") {
- return reply.status(400).send({ error: "X-ENAME header is required" });
- }
-
- const authHeader = request.headers.authorization || request.headers["Authorization"];
- const tokenPayload = await validateToken(
- typeof authHeader === "string" ? authHeader : null
- );
-
- if (!tokenPayload) {
- return reply.status(401).send({ error: "Invalid or missing authentication token" });
- }
-
- const { publicKey } = request.body;
- if (!publicKey) {
- return reply.status(400).send({ error: "publicKey is required in request body" });
- }
-
- if (!dbService) {
- return reply.status(500).send({ error: "Database service not available" });
- }
-
- try {
- await dbService.setPublicKey(eName, publicKey);
- return {
- success: true,
- message: "Public key saved successfully",
- };
- } catch (error) {
- console.error("Error saving public key:", error);
- return reply.status(500).send({
- error: error instanceof Error ? error.message : "Failed to save public key",
- });
- }
- }
- );
+ async (
+ request: TypedRequest<{ publicKey: string }>,
+ reply: TypedReply,
+ ) => {
+ const eName =
+ request.headers["x-ename"] || request.headers["X-ENAME"];
+
+ if (!eName || typeof eName !== "string") {
+ return reply
+ .status(400)
+ .send({ error: "X-ENAME header is required" });
+ }
+
+ const authHeader =
+ request.headers.authorization ||
+ request.headers["Authorization"];
+ const tokenPayload = await validateToken(
+ typeof authHeader === "string" ? authHeader : null,
+ );
+
+ if (!tokenPayload) {
+ return reply
+ .status(401)
+ .send({ error: "Invalid or missing authentication token" });
+ }
+
+ const { publicKey } = request.body;
+ if (!publicKey) {
+ return reply
+ .status(400)
+ .send({ error: "publicKey is required in request body" });
+ }
+
+ if (!dbService) {
+ return reply
+ .status(500)
+ .send({ error: "Database service not available" });
+ }
+
+ try {
+ await dbService.setPublicKey(eName, publicKey);
+ return {
+ success: true,
+ message: "Public key saved successfully",
+ };
+ } catch (error) {
+ console.error("Error saving public key:", error);
+ return reply.status(500).send({
+ error:
+ error instanceof Error
+ ? error.message
+ : "Failed to save public key",
+ });
+ }
+ },
+ );
- // Provision eVault endpoint
- if (provisioningService) {
- server.post<{ Body: ProvisionRequest }>(
- "/provision",
- {
- schema: {
- tags: ["provisioning"],
- description: "Provision a new eVault instance (logical only, no infrastructure)",
- body: {
- type: "object",
- required: ["registryEntropy", "namespace", "verificationId", "publicKey"],
- properties: {
- registryEntropy: { type: "string" },
- namespace: { type: "string" },
- verificationId: { type: "string" },
- publicKey: { type: "string" },
+ // Provision eVault endpoint
+ if (provisioningService) {
+ server.post<{ Body: ProvisionRequest }>(
+ "/provision",
+ {
+ schema: {
+ tags: ["provisioning"],
+ description:
+ "Provision a new eVault instance (logical only, no infrastructure)",
+ body: {
+ type: "object",
+ required: [
+ "registryEntropy",
+ "namespace",
+ "verificationId",
+ "publicKey",
+ ],
+ properties: {
+ registryEntropy: { type: "string" },
+ namespace: { type: "string" },
+ verificationId: { type: "string" },
+ publicKey: { type: "string" },
+ },
+ },
+ response: {
+ 200: {
+ type: "object",
+ properties: {
+ success: { type: "boolean" },
+ w3id: { type: "string" },
+ uri: { type: "string" },
+ message: { type: "string" },
+ error: { type: "string" },
+ },
+ },
+ },
+ },
},
- },
- response: {
- 200: {
- type: "object",
- properties: {
- success: { type: "boolean" },
- w3id: { type: "string" },
- uri: { type: "string" },
- message: { type: "string" },
- error: { type: "string" },
- },
+ async (
+ request: TypedRequest,
+ reply: TypedReply,
+ ) => {
+ const result = await provisioningService.provisionEVault(
+ request.body,
+ );
+ if (!result.success) {
+ return reply.status(500).send(result);
+ }
+ return result;
},
- },
- },
- },
- async (request: TypedRequest, reply: TypedReply) => {
- const result = await provisioningService.provisionEVault(request.body);
- if (!result.success) {
- return reply.status(500).send(result);
- }
- return result;
- }
- );
- }
+ );
+ }
}
diff --git a/platforms/registry/src/index.ts b/platforms/registry/src/index.ts
index 0bf76ede..04eb6c03 100644
--- a/platforms/registry/src/index.ts
+++ b/platforms/registry/src/index.ts
@@ -1,19 +1,22 @@
-import fastify from "fastify";
-import { generateEntropy, generatePlatformToken, getJWK } from "./jwt";
-import dotenv from "dotenv";
import path from "node:path";
+import cors from "@fastify/cors";
+import dotenv from "dotenv";
+import fastify from "fastify";
import { AppDataSource } from "./config/database";
-import { VaultService } from "./services/VaultService";
+import { generateEntropy, generatePlatformToken, getJWK } from "./jwt";
import { UriResolutionService } from "./services/UriResolutionService";
-import cors from "@fastify/cors";
+import { VaultService } from "./services/VaultService";
import fs from "node:fs";
function loadMotdJSON() {
- const motdJSON = fs.readFileSync(path.resolve(__dirname, "../motd.json"), "utf8");
+ const motdJSON = fs.readFileSync(
+ path.resolve(__dirname, "../motd.json"),
+ "utf8",
+ );
return JSON.parse(motdJSON) as {
- status: "up" | "maintenance"
- message: string
+ status: "up" | "maintenance";
+ message: string;
};
}
@@ -41,7 +44,10 @@ const initializeDatabase = async () => {
await AppDataSource.initialize();
server.log.info("Database connection initialized");
} catch (error) {
- server.log.error({message: "Error during database initialization", detail: error});
+ server.log.error({
+ message: "Error during database initialization",
+ detail: error,
+ });
process.exit(1);
}
};
@@ -102,6 +108,7 @@ server.post(
// Generate and return a signed JWT with entropy
server.get("/entropy", async (request, reply) => {
+ console.log("Generating entropy");
try {
const token = await generateEntropy();
return { token };
@@ -123,21 +130,19 @@ server.post("/platforms/certification", async (request, reply) => {
});
server.get("/platforms", async (request, reply) => {
- const platforms = [
- process.env.PUBLIC_PICTIQUE_BASE_URL,
- process.env.PUBLIC_BLABSY_BASE_URL,
- process.env.PUBLIC_GROUP_CHARTER_BASE_URL,
- process.env.PUBLIC_CERBERUS_BASE_URL,
+ const platforms = [
+ process.env.PUBLIC_PICTIQUE_BASE_URL,
+ process.env.PUBLIC_BLABSY_BASE_URL,
+ process.env.PUBLIC_GROUP_CHARTER_BASE_URL,
+ process.env.PUBLIC_CERBERUS_BASE_URL,
process.env.PUBLIC_EVOTING_BASE_URL,
process.env.VITE_DREAMSYNC_BASE_URL,
- process.env.VITE_EREPUTATION_BASE_URL
- ]
+ process.env.VITE_EREPUTATION_BASE_URL,
+ ];
- return platforms
+ return platforms;
});
-
-
// Expose the JWK used for signing
server.get("/.well-known/jwks.json", async (request, reply) => {
try {
@@ -184,11 +189,13 @@ server.get("/resolve", async (request, reply) => {
server.get("/list", async (request, reply) => {
try {
const vaults = await vaultService.findAll();
-
+
// Resolve URIs for all vaults
const resolvedVaults = await Promise.all(
vaults.map(async (vault) => {
- const resolvedUri = await uriResolutionService.resolveUri(vault.uri);
+ const resolvedUri = await uriResolutionService.resolveUri(
+ vault.uri,
+ );
return {
ename: vault.ename,
uri: resolvedUri,
@@ -196,9 +203,9 @@ server.get("/list", async (request, reply) => {
originalUri: vault.uri,
resolved: resolvedUri !== vault.uri,
};
- })
+ }),
);
-
+
return resolvedVaults;
} catch (error) {
server.log.error(error);
diff --git a/platforms/registry/src/services/HealthCheckService.ts b/platforms/registry/src/services/HealthCheckService.ts
index 55e36631..0a0cdb2c 100644
--- a/platforms/registry/src/services/HealthCheckService.ts
+++ b/platforms/registry/src/services/HealthCheckService.ts
@@ -1,4 +1,4 @@
-import axios from 'axios';
+import axios from "axios";
export class HealthCheckService {
private readonly timeout = 5000; // 5 second timeout
@@ -10,7 +10,7 @@ export class HealthCheckService {
try {
// Parse the URI to extract IP:PORT
const { ip, port } = this.parseUri(uri);
-
+
if (!ip || !port) {
console.log(`Invalid URI format: ${uri}`);
return false;
@@ -18,20 +18,22 @@ export class HealthCheckService {
// Construct the whois endpoint URL
const whoisUrl = `http://${ip}:${port}/whois`;
-
+
console.log(`Health checking: ${whoisUrl}`);
-
+
// Make a request to the whois endpoint with timeout
const response = await axios.get(whoisUrl, {
timeout: this.timeout,
- validateStatus: (status) => status < 500 // Accept any status < 500 as "reachable"
+ validateStatus: (status) => status < 500, // Accept any status < 500 as "reachable"
});
-
+
console.log(`Health check passed for ${uri}: ${response.status}`);
return true;
-
} catch (error) {
- console.log(`Health check failed for ${uri}:`, error instanceof Error ? error.message : 'Unknown error');
+ console.log(
+ `Health check failed for ${uri}:`,
+ error instanceof Error ? error.message : "Unknown error",
+ );
return false;
}
}
@@ -43,21 +45,21 @@ export class HealthCheckService {
private parseUri(uri: string): { ip: string | null; port: string | null } {
try {
// Remove protocol if present
- const cleanUri = uri.replace(/^https?:\/\//, '');
-
+ const cleanUri = uri.replace(/^https?:\/\//, "");
+
// Split by colon to get IP and PORT
- const parts = cleanUri.split(':');
-
+ const parts = cleanUri.split(":");
+
if (parts.length === 2) {
const ip = parts[0];
const port = parts[1];
-
+
// Basic validation
if (this.isValidIp(ip) && this.isValidPort(port)) {
return { ip, port };
}
}
-
+
return { ip: null, port: null };
} catch (error) {
console.error(`Error parsing URI ${uri}:`, error);
@@ -70,7 +72,8 @@ export class HealthCheckService {
*/
private isValidIp(ip: string): boolean {
// Simple regex for IP validation
- const ipRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
+ const ipRegex =
+ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
return ipRegex.test(ip);
}
@@ -78,7 +81,7 @@ export class HealthCheckService {
* Basic port validation
*/
private isValidPort(port: string): boolean {
- const portNum = parseInt(port, 10);
+ const portNum = Number.parseInt(port, 10);
return portNum >= 1 && portNum <= 65535;
}
-}
\ No newline at end of file
+}
diff --git a/platforms/registry/src/services/VaultService.ts b/platforms/registry/src/services/VaultService.ts
index 899f6fcc..36886de1 100644
--- a/platforms/registry/src/services/VaultService.ts
+++ b/platforms/registry/src/services/VaultService.ts
@@ -1,32 +1,32 @@
-import { Repository } from "typeorm"
-import { Vault} from "../entities/Vault"
+import type { Repository } from "typeorm";
+import type { Vault } from "../entities/Vault";
export class VaultService {
constructor(private readonly serviceRepository: Repository) {}
async create(ename: string, uri: string, evault: string): Promise {
- const service = this.serviceRepository.create({ ename, uri, evault })
- return await this.serviceRepository.save(service)
+ const service = this.serviceRepository.create({ ename, uri, evault });
+ return await this.serviceRepository.save(service);
}
async findAll(): Promise {
- return await this.serviceRepository.find()
+ return await this.serviceRepository.find();
}
- async findOne(id: number): Promise {
- return await this.serviceRepository.findOneBy({ id })
+ async findOne(id: number): Promise {
+ return await this.serviceRepository.findOneBy({ id });
}
async findByEname(ename: string): Promise {
- return await this.serviceRepository.findOneBy({ ename })
+ return await this.serviceRepository.findOneBy({ ename });
}
- async update(id: number, data: Partial): Promise {
- await this.serviceRepository.update(id, data)
- return await this.findOne(id)
+ async update(id: number, data: Partial): Promise {
+ await this.serviceRepository.update(id, data);
+ return await this.findOne(id);
}
async delete(id: number): Promise {
- await this.serviceRepository.delete(id)
+ await this.serviceRepository.delete(id);
}
-}
\ No newline at end of file
+}
diff --git a/scripts/get-eid-wallet-token.sh b/scripts/get-eid-wallet-token.sh
new file mode 100755
index 00000000..6f2f845b
--- /dev/null
+++ b/scripts/get-eid-wallet-token.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+# Get the registry URL from environment or use default
+REGISTRY_URL="${PUBLIC_REGISTRY_URL:-http://localhost:4321}"
+
+# Request platform token for eid-wallet
+echo "Requesting platform token from registry at $REGISTRY_URL..."
+echo ""
+
+RESPONSE=$(curl -s -X POST "$REGISTRY_URL/platforms/certification" \
+ -H "Content-Type: application/json" \
+ -d '{"platform": "eid-wallet"}')
+
+# Check if curl was successful
+if [ $? -ne 0 ]; then
+ echo "Error: Failed to connect to registry at $REGISTRY_URL"
+ exit 1
+fi
+
+# Extract token using jq if available, otherwise use grep/sed
+if command -v jq &> /dev/null; then
+ TOKEN=$(echo "$RESPONSE" | jq -r '.token')
+ if [ "$TOKEN" = "null" ] || [ -z "$TOKEN" ]; then
+ echo "Error: Failed to get token from response:"
+ echo "$RESPONSE"
+ exit 1
+ fi
+else
+ # Fallback: extract token manually
+ TOKEN=$(echo "$RESPONSE" | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
+ if [ -z "$TOKEN" ]; then
+ echo "Error: Failed to parse token from response:"
+ echo "$RESPONSE"
+ exit 1
+ fi
+fi
+
+echo "Token obtained successfully!"
+echo ""
+echo "Add this to your .env file:"
+echo "PUBLIC_EID_WALLET_TOKEN=\"$TOKEN\""
+echo ""
+echo "Or use it directly:"
+echo "$TOKEN"
+
+
+