Skip to content

Commit d3519f3

Browse files
authored
Feat/esigner (#650)
* chore: move eSigner code to monorepo * feat: eSigner web3 adapter * feat: make esigner respect name * chore: revert pictique avatar changes * feat: make pictique trim system message prefix in preview * feat: user dropdown * fix: lint * fix: build issue with lint * fix: cardinality on entities
1 parent 3fdea04 commit d3519f3

File tree

89 files changed

+7353
-44
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+7353
-44
lines changed

.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ PUBLIC_APP_STORE_EID_WALLET=""
6363
PUBLIC_PLAY_STORE_EID_WALLET=""
6464
NOTIFICATION_SHARED_SECRET=your-notification-secret-key
6565

66+
PUBLIC_ESIGNER_BASE_URL="http://localhost:3004"
67+
6668
DREAMSYNC_DATABASE_URL=postgresql://postgres:postgres@localhost:5432/dreamsync
6769
VITE_DREAMSYNC_BASE_URL="http://localhost:8888"
6870

.github/workflows/check-code.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,6 @@ jobs:
2626
pnpm i
2727
2828
- name: Check Code
29-
run: pnpm check
29+
run: |
30+
cp .env.example .env
31+
pnpm check

platforms/esigner-api/package.json

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"name": "esigner-api",
3+
"version": "1.0.0",
4+
"description": "eSigner Document Signing Platform API",
5+
"main": "src/index.ts",
6+
"scripts": {
7+
"start": "ts-node src/index.ts",
8+
"dev": "nodemon --exec ts-node src/index.ts",
9+
"build": "tsc && cp -r src/web3adapter/mappings dist/web3adapter/",
10+
"typeorm": "typeorm-ts-node-commonjs",
11+
"migration:generate": "npm run typeorm migration:generate -- -d src/database/data-source.ts",
12+
"migration:run": "npm run typeorm migration:run -- -d src/database/data-source.ts",
13+
"migration:revert": "npm run typeorm migration:revert -- -d src/database/data-source.ts"
14+
},
15+
"dependencies": {
16+
"axios": "^1.6.7",
17+
"cors": "^2.8.5",
18+
"dotenv": "^16.4.5",
19+
"eventsource-polyfill": "^0.9.6",
20+
"express": "^4.18.2",
21+
"graphql-request": "^6.1.0",
22+
"jsonwebtoken": "^9.0.2",
23+
"multer": "^1.4.5-lts.1",
24+
"pg": "^8.11.3",
25+
"reflect-metadata": "^0.2.1",
26+
"typeorm": "^0.3.24",
27+
"uuid": "^9.0.1",
28+
"signature-validator": "workspace:*",
29+
"web3-adapter": "workspace:*"
30+
},
31+
"devDependencies": {
32+
"@types/cors": "^2.8.17",
33+
"@types/express": "^4.17.21",
34+
"@types/jsonwebtoken": "^9.0.5",
35+
"@types/multer": "^1.4.11",
36+
"@types/node": "^20.11.24",
37+
"@types/pg": "^8.11.2",
38+
"@types/uuid": "^9.0.8",
39+
"@typescript-eslint/eslint-plugin": "^7.0.1",
40+
"@typescript-eslint/parser": "^7.0.1",
41+
"eslint": "^8.56.0",
42+
"nodemon": "^3.0.3",
43+
"ts-node": "^10.9.2",
44+
"typescript": "^5.3.3"
45+
}
46+
}
47+
48+
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import { Request, Response } from "express";
2+
import { v4 as uuidv4 } from "uuid";
3+
import { UserService } from "../services/UserService";
4+
import { EventEmitter } from "events";
5+
import { signToken } from "../utils/jwt";
6+
import { isVersionValid } from "../utils/version";
7+
import { verifySignature } from "signature-validator";
8+
9+
const MIN_REQUIRED_VERSION = "0.4.0";
10+
11+
export class AuthController {
12+
private userService: UserService;
13+
private eventEmitter: EventEmitter;
14+
15+
constructor() {
16+
this.userService = new UserService();
17+
this.eventEmitter = new EventEmitter();
18+
}
19+
20+
sseStream = async (req: Request, res: Response) => {
21+
const { id } = req.params;
22+
23+
res.writeHead(200, {
24+
"Content-Type": "text/event-stream",
25+
"Cache-Control": "no-cache",
26+
Connection: "keep-alive",
27+
"Access-Control-Allow-Origin": "*",
28+
});
29+
30+
const handler = (data: any) => {
31+
res.write(`data: ${JSON.stringify(data)}\n\n`);
32+
};
33+
34+
this.eventEmitter.on(id, handler);
35+
36+
req.on("close", () => {
37+
this.eventEmitter.off(id, handler);
38+
res.end();
39+
});
40+
41+
req.on("error", (error) => {
42+
console.error("SSE Error:", error);
43+
this.eventEmitter.off(id, handler);
44+
res.end();
45+
});
46+
};
47+
48+
getOffer = async (req: Request, res: Response) => {
49+
const url = new URL(
50+
"/api/auth",
51+
process.env.PUBLIC_ESIGNER_BASE_URL,
52+
).toString();
53+
const session = uuidv4();
54+
const offer = `w3ds://auth?redirect=${url}&session=${session}&platform=esigner`;
55+
res.json({ uri: offer });
56+
};
57+
58+
login = async (req: Request, res: Response) => {
59+
try {
60+
const { ename, session, appVersion, signature } = req.body;
61+
62+
if (!ename) {
63+
return res.status(400).json({ error: "ename is required" });
64+
}
65+
66+
if (!session) {
67+
return res.status(400).json({ error: "session is required" });
68+
}
69+
70+
if (!signature) {
71+
return res.status(400).json({ error: "signature is required" });
72+
}
73+
74+
if (!appVersion || !isVersionValid(appVersion, MIN_REQUIRED_VERSION)) {
75+
const errorMessage = {
76+
error: true,
77+
message: `Your eID Wallet app version is outdated. Please update to version ${MIN_REQUIRED_VERSION} or later.`,
78+
type: "version_mismatch"
79+
};
80+
this.eventEmitter.emit(session, errorMessage);
81+
return res.status(400).json({
82+
error: "App version too old",
83+
message: errorMessage.message
84+
});
85+
}
86+
87+
const registryBaseUrl = process.env.PUBLIC_REGISTRY_URL;
88+
if (!registryBaseUrl) {
89+
console.error("PUBLIC_REGISTRY_URL not configured");
90+
return res.status(500).json({ error: "Server configuration error" });
91+
}
92+
93+
const verificationResult = await verifySignature({
94+
eName: ename,
95+
signature: signature,
96+
payload: session,
97+
registryBaseUrl: registryBaseUrl,
98+
});
99+
100+
if (!verificationResult.valid) {
101+
console.error("Signature validation failed:", verificationResult.error);
102+
return res.status(401).json({
103+
error: "Invalid signature",
104+
message: verificationResult.error
105+
});
106+
}
107+
108+
let user = await this.userService.findByEname(ename);
109+
110+
if (!user) {
111+
throw new Error("User not found");
112+
}
113+
114+
const token = signToken({ userId: user.id });
115+
116+
const data = {
117+
user: {
118+
id: user.id,
119+
ename: user.ename,
120+
isVerified: user.isVerified,
121+
isPrivate: user.isPrivate,
122+
},
123+
token,
124+
};
125+
this.eventEmitter.emit(session, data);
126+
res.status(200).json(data);
127+
} catch (error) {
128+
console.error("Error during login:", error);
129+
res.status(500).json({ error: "Internal server error" });
130+
}
131+
};
132+
}
133+
134+

0 commit comments

Comments
 (0)