Compare commits
17 Commits
0dd928d28b
...
76a1d38e09
Author | SHA1 | Date | |
---|---|---|---|
![]() |
76a1d38e09 | ||
![]() |
8a0a8e2df2 | ||
![]() |
48194dd2de | ||
![]() |
8e9d7f0c76 | ||
![]() |
eda7102ded | ||
ec99d101ab | |||
![]() |
205796d22a | ||
b072495cea | |||
![]() |
9a601056b7 | ||
![]() |
13b605a850 | ||
![]() |
0a860bd559 | ||
![]() |
a8b0248b5f | ||
![]() |
0dc3c83c3c | ||
![]() |
1a87a4db14 | ||
![]() |
67cd7a1662 | ||
![]() |
337a6adc60 | ||
![]() |
d8422de94e |
43
.github/workflows/cicd.yml
vendored
Normal file
43
.github/workflows/cicd.yml
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
name: Build and Push to Registry
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ cicd ]
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: git.4nkweb.com
|
||||||
|
IMAGE_NAME: 4nk/ihm_client
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-push:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up SSH agent
|
||||||
|
uses: webfactory/ssh-agent@v0.9.1
|
||||||
|
with:
|
||||||
|
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Login to Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ secrets.USER }}
|
||||||
|
password: ${{ secrets.TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
ssh: default
|
||||||
|
build-args: |
|
||||||
|
ENV_VARS=${{ secrets.ENV_VARS }}
|
||||||
|
tags: |
|
||||||
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||||
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ gitea.sha }}
|
74
Dockerfile
74
Dockerfile
@ -1,13 +1,61 @@
|
|||||||
FROM node:20
|
# syntax=docker/dockerfile:1.4
|
||||||
|
FROM rust:1.82-alpine AS wasm-builder
|
||||||
ENV TZ=Europe/Paris
|
WORKDIR /build
|
||||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
|
||||||
|
# Installation des dépendances nécessaires pour la compilation
|
||||||
# use this user because he have uid et gid 1000 like theradia
|
RUN apk update && apk add --no-cache \
|
||||||
USER node
|
git \
|
||||||
|
openssh-client \
|
||||||
WORKDIR /app
|
curl \
|
||||||
|
nodejs \
|
||||||
CMD ["npm", "start"]
|
npm \
|
||||||
# "--disable-host-check", "--host", "0.0.0.0", "--ssl", "--ssl-cert", "/ssl/certs/site.crt", "--ssl-key", "/ssl/private/site.dec.key"]
|
build-base \
|
||||||
|
pkgconfig \
|
||||||
|
clang \
|
||||||
|
llvm \
|
||||||
|
musl-dev \
|
||||||
|
nginx
|
||||||
|
|
||||||
|
# Installation de wasm-pack
|
||||||
|
RUN curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||||
|
|
||||||
|
# Configuration SSH basique
|
||||||
|
RUN mkdir -p /root/.ssh && \
|
||||||
|
ssh-keyscan git.4nkweb.com >> /root/.ssh/known_hosts
|
||||||
|
|
||||||
|
# On se place dans le bon répertoire parent
|
||||||
|
WORKDIR /build
|
||||||
|
# Copie du projet ihm_client
|
||||||
|
COPY . ihm_client/
|
||||||
|
|
||||||
|
# Clonage du sdk_client au même niveau que ihm_client en utilisant la clé SSH montée
|
||||||
|
RUN --mount=type=ssh git clone -b cicd ssh://git@git.4nkweb.com/4nk/sdk_client.git
|
||||||
|
|
||||||
|
# Build du WebAssembly avec accès SSH pour les dépendances
|
||||||
|
WORKDIR /build/sdk_client
|
||||||
|
RUN --mount=type=ssh wasm-pack build --out-dir ../ihm_client/pkg --target bundler --dev
|
||||||
|
|
||||||
|
FROM node:20-alpine
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Installation des dépendances nécessaires
|
||||||
|
RUN apk update && apk add --no-cache git nginx
|
||||||
|
|
||||||
|
# Copie des fichiers du projet
|
||||||
|
COPY --from=wasm-builder /build/ihm_client/pkg ./pkg
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Installation des dépendances Node.js
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
# Copie de la configuration nginx
|
||||||
|
COPY nginx.dev.conf /etc/nginx/http.d/default.conf
|
||||||
|
|
||||||
|
# Script de démarrage
|
||||||
|
COPY start-dev.sh /start-dev.sh
|
||||||
|
RUN chmod +x /start-dev.sh
|
||||||
|
|
||||||
|
EXPOSE 3003 80
|
||||||
|
|
||||||
|
CMD ["/start-dev.sh"]
|
||||||
|
|
||||||
|
48
nginx.dev.conf
Normal file
48
nginx.dev.conf
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
# Redirection des requêtes HTTP vers Vite
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:3003;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "Upgrade";
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /ws/ {
|
||||||
|
proxy_pass http://localhost:8090;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "Upgrade";
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-NginX-Proxy true;
|
||||||
|
proxy_read_timeout 86400;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /storage/ {
|
||||||
|
rewrite ^/storage(/.*)$ $1 break;
|
||||||
|
proxy_pass http://localhost:8080;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "Upgrade";
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://localhost:8091;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
# CORS headers
|
||||||
|
add_header Access-Control-Allow-Origin "*" always;
|
||||||
|
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE" always;
|
||||||
|
add_header Access-Control-Allow-Headers "Authorization,Content-Type,Accept,X-Requested-With" always;
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,7 @@
|
|||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"build_wasm": "wasm-pack build --out-dir ../ihm_client_dev3/pkg ../sdk_client --target bundler --dev",
|
"build_wasm": "wasm-pack build --out-dir ../ihm_client/pkg ../sdk_client --target bundler --dev",
|
||||||
"start": "vite --host 0.0.0.0",
|
"start": "vite --host 0.0.0.0",
|
||||||
"build": "tsc && vite build",
|
"build": "tsc && vite build",
|
||||||
"deploy": "sudo cp -r dist/* /var/www/html/",
|
"deploy": "sudo cp -r dist/* /var/www/html/",
|
||||||
|
@ -27,6 +27,8 @@ export enum MessageType {
|
|||||||
LISTENING = 'LISTENING',
|
LISTENING = 'LISTENING',
|
||||||
REQUEST_LINK = 'REQUEST_LINK',
|
REQUEST_LINK = 'REQUEST_LINK',
|
||||||
LINK_ACCEPTED = 'LINK_ACCEPTED',
|
LINK_ACCEPTED = 'LINK_ACCEPTED',
|
||||||
|
CREATE_PAIRING = 'CREATE_PAIRING',
|
||||||
|
PAIRING_CREATED = 'PAIRING_CREATED',
|
||||||
ERROR = 'ERROR',
|
ERROR = 'ERROR',
|
||||||
VALIDATE_TOKEN = 'VALIDATE_TOKEN',
|
VALIDATE_TOKEN = 'VALIDATE_TOKEN',
|
||||||
RENEW_TOKEN = 'RENEW_TOKEN',
|
RENEW_TOKEN = 'RENEW_TOKEN',
|
||||||
|
@ -207,19 +207,8 @@ export async function registerAllListeners() {
|
|||||||
cancelText: 'Annuler'
|
cancelText: 'Annuler'
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
try {
|
if (!result) {
|
||||||
if (!result) {
|
const errorMsg = 'Failed to pair device: User refused to link';
|
||||||
throw new Error('User refused to link');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!services.isPaired()) {
|
|
||||||
// New device - do pairing process
|
|
||||||
console.log('🚀 The device is not paired');
|
|
||||||
await prepareAndSendPairingTx();
|
|
||||||
await services.confirmPairing();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
const errorMsg = `Failed to pair device: ${error}`;
|
|
||||||
errorResponse(errorMsg, event.origin, event.data.messageId);
|
errorResponse(errorMsg, event.origin, event.data.messageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,6 +230,47 @@ export async function registerAllListeners() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleCreatePairing = async (event: MessageEvent) => {
|
||||||
|
if (event.data.type !== MessageType.CREATE_PAIRING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (services.isPaired()) {
|
||||||
|
const errorMsg = 'Device already paired';
|
||||||
|
errorResponse(errorMsg, event.origin, event.data.messageId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { accessToken } = event.data;
|
||||||
|
|
||||||
|
if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) {
|
||||||
|
throw new Error('Invalid or expired session token');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🚀 Starting pairing process');
|
||||||
|
await prepareAndSendPairingTx();
|
||||||
|
await services.confirmPairing();
|
||||||
|
|
||||||
|
const pairingId = services.getPairingProcessId();
|
||||||
|
|
||||||
|
if (!pairingId) {
|
||||||
|
throw new Error('Failed to get pairing process id');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send success response
|
||||||
|
const successMsg = {
|
||||||
|
type: MessageType.PAIRING_CREATED,
|
||||||
|
pairingId,
|
||||||
|
messageId: event.data.messageId
|
||||||
|
};
|
||||||
|
window.parent.postMessage(successMsg, event.origin);
|
||||||
|
} catch (e) {
|
||||||
|
const errorMsg = `Failed to create pairing process: ${e}`;
|
||||||
|
errorResponse(errorMsg, event.origin, event.data.messageId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleGetMyProcesses = async (event: MessageEvent) => {
|
const handleGetMyProcesses = async (event: MessageEvent) => {
|
||||||
if (event.data.type !== MessageType.GET_MY_PROCESSES) {
|
if (event.data.type !== MessageType.GET_MY_PROCESSES) {
|
||||||
return;
|
return;
|
||||||
@ -814,6 +844,9 @@ export async function registerAllListeners() {
|
|||||||
case MessageType.REQUEST_LINK:
|
case MessageType.REQUEST_LINK:
|
||||||
await handleRequestLink(event);
|
await handleRequestLink(event);
|
||||||
break;
|
break;
|
||||||
|
case MessageType.CREATE_PAIRING:
|
||||||
|
await handleCreatePairing(event);
|
||||||
|
break;
|
||||||
case MessageType.GET_MY_PROCESSES:
|
case MessageType.GET_MY_PROCESSES:
|
||||||
await handleGetMyProcesses(event);
|
await handleGetMyProcesses(event);
|
||||||
break;
|
break;
|
||||||
|
@ -541,10 +541,40 @@ export default class Services {
|
|||||||
// await this.saveCipherTxToDb(parsedTx)
|
// await this.saveCipherTxToDb(parsedTx)
|
||||||
}
|
}
|
||||||
|
|
||||||
async parseNewTx(tx: string) {
|
async parseNewTx(newTxMsg: string) {
|
||||||
|
const parsedMsg: NewTxMessage = JSON.parse(newTxMsg);
|
||||||
|
if (parsedMsg.error !== null) {
|
||||||
|
console.error('Received error in new tx message:', parsedMsg.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const membersList = this.getAllMembers();
|
const membersList = this.getAllMembers();
|
||||||
try {
|
try {
|
||||||
const parsedTx = this.sdkClient.parse_new_tx(tx, 0, membersList);
|
// Does the transaction spend the tip of a process?
|
||||||
|
const prevouts = this.sdkClient.get_prevouts(parsedMsg.transaction);
|
||||||
|
console.log('prevouts:', prevouts);
|
||||||
|
for (const process of Object.values(this.processesCache)) {
|
||||||
|
const tip = process.states[process.states.length - 1].commited_in;
|
||||||
|
if (prevouts.includes(tip)) {
|
||||||
|
const processId = process.states[0].commited_in;
|
||||||
|
const newTip = this.sdkClient.get_txid(parsedMsg.transaction);
|
||||||
|
console.log('Transaction', newTip, 'spends the tip of process', processId);
|
||||||
|
// We take the data out of the output
|
||||||
|
const newStateId = this.sdkClient.get_new_state_id(parsedMsg.transaction);
|
||||||
|
console.log('newStateId:', newStateId);
|
||||||
|
// We update the relevant process
|
||||||
|
const updatedProcess = this.sdkClient.process_commit_new_state(process, newStateId, newTip);
|
||||||
|
this.processesCache[processId] = updatedProcess;
|
||||||
|
console.log('updatedProcess:', updatedProcess);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to parse new tx for commitments:', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const parsedTx = this.sdkClient.parse_new_tx(parsedMsg.transaction, 0, membersList);
|
||||||
if (parsedTx) {
|
if (parsedTx) {
|
||||||
try {
|
try {
|
||||||
await this.handleApiReturn(parsedTx);
|
await this.handleApiReturn(parsedTx);
|
||||||
@ -555,7 +585,7 @@ export default class Services {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.trace(e);
|
console.debug(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1060,7 +1090,7 @@ export default class Services {
|
|||||||
await this.restoreProcessesFromDB();
|
await this.restoreProcessesFromDB();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore process in wasm with persistent storage
|
// Restore processes cache from persistent storage
|
||||||
public async restoreProcessesFromDB() {
|
public async restoreProcessesFromDB() {
|
||||||
const db = await Database.getInstance();
|
const db = await Database.getInstance();
|
||||||
try {
|
try {
|
||||||
@ -1068,7 +1098,6 @@ export default class Services {
|
|||||||
if (processes && Object.keys(processes).length != 0) {
|
if (processes && Object.keys(processes).length != 0) {
|
||||||
console.log(`Restoring ${Object.keys(processes).length} processes`);
|
console.log(`Restoring ${Object.keys(processes).length} processes`);
|
||||||
this.processesCache = processes;
|
this.processesCache = processes;
|
||||||
this.sdkClient.set_process_cache(processes);
|
|
||||||
} else {
|
} else {
|
||||||
console.log('No processes to restore!');
|
console.log('No processes to restore!');
|
||||||
}
|
}
|
||||||
|
7
start-dev.sh
Normal file
7
start-dev.sh
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Démarrer nginx en arrière-plan
|
||||||
|
nginx
|
||||||
|
|
||||||
|
# Démarrer le serveur de développement Vite
|
||||||
|
npm run start
|
@ -57,7 +57,7 @@ export default defineConfig({
|
|||||||
fs: {
|
fs: {
|
||||||
cachedChecks: false,
|
cachedChecks: false,
|
||||||
},
|
},
|
||||||
port: 3004,
|
port: 3003,
|
||||||
proxy: {
|
proxy: {
|
||||||
'/storage': {
|
'/storage': {
|
||||||
target: 'https://demo.4nkweb.com',
|
target: 'https://demo.4nkweb.com',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user