docs: bridges obfs4 Tor et dépannage signet; add netcat for diagnostics; clarify CONFIGURATION/TESTING; update CHANGELOG
This commit is contained in:
parent
a34b4fbc6d
commit
dcc032df48
102
.cursorignore
Normal file
102
.cursorignore
Normal file
@ -0,0 +1,102 @@
|
||||
# Fichiers et répertoires à ignorer pour l’indexation Cursor
|
||||
|
||||
# Dépendances frontend / JS
|
||||
node_modules/
|
||||
**/node_modules/**
|
||||
|
||||
# Artefacts de build et caches courants
|
||||
dist/
|
||||
build/
|
||||
out/
|
||||
.next/
|
||||
coverage/
|
||||
.cache/
|
||||
.turbo/
|
||||
.parcel-cache/
|
||||
.eslintcache
|
||||
|
||||
# Logs et temporaires
|
||||
*.log
|
||||
*.tmp
|
||||
*.swp
|
||||
*.swo
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Environnements et secrets (ne pas indexer)
|
||||
.env
|
||||
.env.*
|
||||
*.pem
|
||||
*.key
|
||||
*.crt
|
||||
|
||||
# Artefacts tests
|
||||
tests/logs/
|
||||
tests/reports/
|
||||
tests/**/tmp/
|
||||
|
||||
# Répertoires développeur
|
||||
.nvm/
|
||||
.venv/
|
||||
.idea/
|
||||
.vscode/
|
||||
|
||||
# Système
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Rust (si présent localement)
|
||||
target/
|
||||
|
||||
# Docker (artefacts locaux éventuels)
|
||||
docker-compose.override.yml
|
||||
docker-compose.*.yml.local
|
||||
*.docker.tar
|
||||
docker-image-*.tar
|
||||
docker-save-*.tar
|
||||
.docker/
|
||||
.docker-compose/
|
||||
docker-data/
|
||||
docker-volumes/
|
||||
docker-logs/
|
||||
|
||||
# ihm_client spécifiques
|
||||
ihm_client/.vercel/
|
||||
ihm_client/.pnpm-store/
|
||||
ihm_client/.yarn/**
|
||||
|
||||
# Archives et sauvegardes (ne pas indexer)
|
||||
*.zip
|
||||
*.tar
|
||||
*.tar.gz
|
||||
*.tgz
|
||||
*.gz
|
||||
*.bz2
|
||||
*.xz
|
||||
*.zst
|
||||
*.7z
|
||||
*.rar
|
||||
*.iso
|
||||
*.bak
|
||||
*.backup
|
||||
*.old
|
||||
*.orig
|
||||
|
||||
# Répertoire d’archives du projet
|
||||
archive/
|
||||
|
||||
# Dumps SQL et exports de bases de données
|
||||
*.sql
|
||||
*.sql.gz
|
||||
*.dump
|
||||
*.dmp
|
||||
*.sqlite
|
||||
*.sqlite3
|
||||
*.db
|
||||
*.db3
|
||||
*.bak.sql
|
||||
sql_dumps/
|
||||
db_dumps/
|
||||
database_dumps/
|
||||
backups/sql/
|
22
CHANGELOG.md
22
CHANGELOG.md
@ -8,21 +8,43 @@ et ce projet adhère au [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- Script d’amorçage `scripts/bootstrap.sh` pour installer git, Docker, Docker Compose, Node.js/npm (nvm) et ajouter l’utilisateur au groupe docker
|
||||
- Test de prérequis `tests/external/test_tooling_versions.sh` pour vérifier les versions des outils
|
||||
- Infrastructure de tests complète avec organisation par catégorie
|
||||
- Scripts d'exécution automatisés pour les tests
|
||||
- Documentation technique complète (Architecture, API)
|
||||
- Guide de contribution et code de conduite
|
||||
- Scripts de maintenance et nettoyage automatique
|
||||
- Reverse proxy central `reverse_proxy` (Nginx) servant `ihm_client` et proxifiant `sdk_relay` (HTTPS/WSS)
|
||||
- Script `scripts/generate_certs.sh` pour certificats auto-signés sécurisés (droits durcis)
|
||||
- Script `scripts/build_ui_local.sh` pour construire l’UI localement (gestion des permissions `dist/`)
|
||||
- Script `scripts/cleanup_legacy.sh` pour archiver les fichiers devenus obsolètes
|
||||
- Fichier `proxy/nginx.conf` consolidant la configuration publique (CSP, MIME, WS, CORS)
|
||||
- Service Tor reconstruit localement (`tor/Dockerfile`) avec support `obfs4proxy` et healthcheck
|
||||
|
||||
### Changed
|
||||
- Mise à jour de `.cursorignore` pour exclure dépendances, artefacts de build, logs et secrets
|
||||
- Ajout d’exclusions `.cursorignore` pour artefacts Docker et dossiers spécifiques `ihm_client`
|
||||
- Ajout d’exclusions `.cursorignore` pour archives et sauvegardes (zip, tar, gz, bz2, xz, zst, 7z, rar, iso, bak)
|
||||
- Exclusion du répertoire `archive/` dans `.cursorignore`
|
||||
- Ajout d’exclusions `.cursorignore` pour dumps SQL et exports de bases (sql, dump, sqlite, db)
|
||||
- Réorganisation complète de la structure des tests
|
||||
- Amélioration de la documentation avec guides détaillés
|
||||
- Optimisation des scripts de démarrage et redémarrage
|
||||
- `docker-compose.yml` modernisé (suppression de la clé `version:`) et services internes (ports supprimés)
|
||||
- Sortie d’Nginx hors `ihm_client` et centralisation dans `reverse_proxy`
|
||||
- Documentation mise à jour (Architecture, Configuration, Installation, Usage, Testing)
|
||||
- `tor/torrc` actualisé (ControlPort local, logs stdout, bridges obfs4 optionnels)
|
||||
- Activation et test des bridges obfs4 fournis par le Tor Project ; ajout de recommandations de diagnostic (netcat, tests SOCKS, distinction onion public vs pair signet)
|
||||
|
||||
### Fixed
|
||||
- Correction des problèmes de connectivité entre services
|
||||
- Amélioration de la gestion des erreurs dans les tests
|
||||
- Correction des configurations Docker
|
||||
- Résolution des erreurs TypeScript liées à `pkg/sdk_client` en ajoutant `scripts/setup-remote-deps.sh` et mise à jour du build UI
|
||||
- Correction des erreurs de MIME et de download côté Nginx via `proxy/nginx.conf`
|
||||
- Correction `EACCES` de build UI via gestion des permissions `ihm_client/dist`
|
||||
- Diagnostic et correction outillage réseau : installation de `netcat-openbsd` sur l’hôte et dans `bitcoin-signet` pour tests SOCKS/TCP
|
||||
|
||||
## [1.0.0] - 2024-12-19
|
||||
|
||||
|
@ -50,10 +50,14 @@ Client → sdk_relay → Bitcoin Core
|
||||
git clone git@git.4nkweb.com:4nk/4NK_node.git
|
||||
cd 4NK_node
|
||||
|
||||
# 2. Démarrer tous les services
|
||||
# 2. Amorcer l’environnement (git, Docker, Compose, Node/npm)
|
||||
./scripts/bootstrap.sh
|
||||
# Astuce: se déconnecter/reconnecter pour activer le groupe docker
|
||||
|
||||
# 3. Démarrer tous les services
|
||||
./restart_4nk_node.sh
|
||||
|
||||
# 3. Vérifier le statut
|
||||
# 4. Vérifier le statut
|
||||
docker ps
|
||||
```
|
||||
|
||||
|
@ -9,7 +9,9 @@ RUN apk update && apk add --no-cache \
|
||||
build-base \
|
||||
python3 \
|
||||
make \
|
||||
g++
|
||||
g++ \
|
||||
curl \
|
||||
ca-certificates
|
||||
|
||||
# Copie des fichiers de dépendances
|
||||
COPY package*.json ./
|
||||
@ -20,6 +22,15 @@ RUN npm install
|
||||
# Copie du code source
|
||||
COPY . .
|
||||
|
||||
# Préparation des dépendances wasm (pkg/sdk_client)
|
||||
ARG SDK_CLIENT_PKG_URL=""
|
||||
ARG SDK_CLIENT_PKG_TARBALL=""
|
||||
ARG SDK_CLIENT_PKG_BASE="https://git.4nkweb.com/4nk/ihm_client/raw/branch/docker-support/pkg"
|
||||
ENV SDK_CLIENT_PKG_URL=${SDK_CLIENT_PKG_URL}
|
||||
ENV SDK_CLIENT_PKG_TARBALL=${SDK_CLIENT_PKG_TARBALL}
|
||||
ENV SDK_CLIENT_PKG_BASE=${SDK_CLIENT_PKG_BASE}
|
||||
RUN chmod +x ./scripts/setup-remote-deps.sh && npm run build_wasm
|
||||
|
||||
# Build de l'application
|
||||
RUN npm run build
|
||||
|
||||
@ -27,7 +38,7 @@ RUN npm run build
|
||||
FROM nginx:alpine
|
||||
|
||||
# Installation de Node.js pour les scripts de démarrage
|
||||
RUN apk update && apk add --no-cache nodejs npm
|
||||
RUN apk update && apk add --no-cache nodejs npm wget
|
||||
|
||||
# Copie des fichiers buildés
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
@ -35,6 +46,7 @@ COPY --from=builder /app/package*.json /app/
|
||||
|
||||
# Copie de la configuration nginx optimisée pour 4NK_node
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
RUN sed -i 's|types_hash_max_size .*;|types_hash_max_size 4096;|' /etc/nginx/nginx.conf || true
|
||||
|
||||
# Script de démarrage
|
||||
COPY start.sh /start-4nk-node.sh
|
@ -80,13 +80,12 @@ echo "🔄 L'interface utilisateur se connectera directement à Blindbit"
|
||||
echo "⚙️ Génération de la configuration dynamique..."
|
||||
|
||||
# Créer un fichier de configuration JavaScript pour l'application
|
||||
cat > /usr/share/nginx/html/config.js << EOF
|
||||
# Pour l'accès via reverse proxy public, utiliser des chemins relatifs /ws et /api
|
||||
cat > /usr/share/nginx/html/config.js << 'EOF'
|
||||
window.ENV_CONFIG = {
|
||||
SDK_RELAY_WS_URL: '$SDK_RELAY_WS_URL',
|
||||
SDK_RELAY_HTTP_URL: '$SDK_RELAY_HTTP_URL',
|
||||
BITCOIN_RPC_URL: '$BITCOIN_RPC_URL',
|
||||
BLINDBIT_URL: '$BLINDBIT_URL',
|
||||
ENVIRONMENT: '4nk-node'
|
||||
SDK_RELAY_WS_URL: '/ws',
|
||||
SDK_RELAY_HTTP_URL: '/api',
|
||||
ENVIRONMENT: '4nk-node'
|
||||
};
|
||||
EOF
|
||||
|
1
archive/tmp_sdk_relay/sdk_relay
Submodule
1
archive/tmp_sdk_relay/sdk_relay
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 09b45d14888724760cde0ae89cce6c42e4a59b8f
|
@ -19,6 +19,7 @@ rpcdoccheck=1
|
||||
|
||||
# Paramètres ZMQ
|
||||
zmqpubhashblock=tcp://0.0.0.0:29000
|
||||
zmqpubrawblock=tcp://0.0.0.0:29000
|
||||
zmqpubrawtx=tcp://0.0.0.0:29000
|
||||
|
||||
[signet]
|
||||
|
19
certs/server.crt
Normal file
19
certs/server.crt
Normal file
@ -0,0 +1,19 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDETCCAfmgAwIBAgIUJboCRW/xrzBSG2jYDSdNfURIzd4wDQYJKoZIhvcNAQEL
|
||||
BQAwGDEWMBQGA1UEAwwNOTIuMjQzLjI3LjE2MDAeFw0yNTA4MjYwMTQxNTRaFw0y
|
||||
NjA4MjYwMTQxNTRaMBgxFjAUBgNVBAMMDTkyLjI0My4yNy4xNjAwggEiMA0GCSqG
|
||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDje8YeBKYLCYnUSOR3mQIX3j2JNbIlHrz9
|
||||
XV5egpEmHArbuh1UV4qsYL8vXv8DuWDSIbFLIvY/QekX++Ug1wMVDQsp+LHWbRp2
|
||||
StsvkLCfyyVU9tfQ90fy4ylILdVVFaptskgKmY5JyVkJJ/s7qFvOeG10r4DfIA5W
|
||||
LisWZv3WQtS1ShPxLIDn6/2I6sNA5sxmOo+szud9mC7RPC5V2hD1mnZaB5o7Ovvd
|
||||
ZfDXfk+cE0qO1rly+CDRSw1YNXmpzpeO8/sRDmMvfA51S/U59NK43C5PgtJ4dunm
|
||||
XWsVrIzt7QjeF+ANldHBGF8jh88gKxRTYJQNYTwIfhL57ipTokfpAgMBAAGjUzBR
|
||||
MB0GA1UdDgQWBBRM/sctXRsTyTY0JwP58SmsoM8+FjAfBgNVHSMEGDAWgBRM/sct
|
||||
XRsTyTY0JwP58SmsoM8+FjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUA
|
||||
A4IBAQAPAV2VNg+V67gKamXCNkgJCCJlC1PrSEdD3W5/SKMQwtORSrYV7OjOpvBb
|
||||
msZ3a769PPOcvV72p35fturzWnave/WHC5sM+2WqZmSQCfoV+d8sHJGB84rDnLV2
|
||||
zl4sKcwSMwUMZhwxPvSYV+d5ZxQ2SfbQ8ZwTiNDLsWGB8K0E1nK/4SbPRIEfAu5U
|
||||
m29RkByl74T1kgTHinu0F/eNWQJsV5aQIkD2hhTnazmf0rC9MI4dRlGF1Ycup7xT
|
||||
FdiBDfkjPkt6YlvA8Mk9aEz/Mm2bh7flmEw2DD9xho6WZfI6974HKQwsngJgb4be
|
||||
JDIzbS+JLEjB7lR1IuXTN83ZUg1l
|
||||
-----END CERTIFICATE-----
|
28
certs/server.key
Normal file
28
certs/server.key
Normal file
@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDje8YeBKYLCYnU
|
||||
SOR3mQIX3j2JNbIlHrz9XV5egpEmHArbuh1UV4qsYL8vXv8DuWDSIbFLIvY/QekX
|
||||
++Ug1wMVDQsp+LHWbRp2StsvkLCfyyVU9tfQ90fy4ylILdVVFaptskgKmY5JyVkJ
|
||||
J/s7qFvOeG10r4DfIA5WLisWZv3WQtS1ShPxLIDn6/2I6sNA5sxmOo+szud9mC7R
|
||||
PC5V2hD1mnZaB5o7OvvdZfDXfk+cE0qO1rly+CDRSw1YNXmpzpeO8/sRDmMvfA51
|
||||
S/U59NK43C5PgtJ4dunmXWsVrIzt7QjeF+ANldHBGF8jh88gKxRTYJQNYTwIfhL5
|
||||
7ipTokfpAgMBAAECggEALKQ0i92DrDTR/HvVgfbf50kwsEV+UTSIB/yTsV5UF7N3
|
||||
GgmbCdsoFo3h1u0AhH2Tl4kPHtyckGthz9gZ7ejj7PSjVTg9xgOhJsen3dy6HJGk
|
||||
INlUHuj4EJ0tk8GS1OCsklxjMNlTh/1gYKCc9+chJRKTAEwUsTS8O4NR51KMy8fw
|
||||
2yzDQTuIFO3Fk9F5QvHrw1cE8iylxutS1Y9K8JCKP2nsWIcwEpXtiemKFZKODLzj
|
||||
7HJLSdUgIX4xIlxbBgUZgPpRg3HKI6JAldVKQyXdQfk+8rqDSNu6q3jrL0GkctOM
|
||||
e6o2l/3yi+MbiZ/uhLQYfEMcpIYiz/cJ7X3ShK0cAQKBgQD9mlpwtc2zuJmVSE/5
|
||||
c6B8amKq+NcnWU4KtpbNPWGlGirFurT9pic2beHI+o6Ka1ArmdphP5xI9V+YQHyv
|
||||
Xmdew8mZ11qxodBk0a1KCCY+5TGeZ1EC70MrAZtm3to5PINCco5yLvjJzHt5I8ve
|
||||
8L+xfGe3ajJ6uYbwkPP0TutsaQKBgQDlojgQWhus1HAdk5F4mbd6nYmAUUlDWFwF
|
||||
UCscqiBsp4AYt53C8a0J0B1EIEhqVmyFOQ6VOi2Qgbkf7W7+hKXfcBpi3MJApJ0H
|
||||
K/PcXxavibqB+VLfc+Ip9ZX+PTbu8Zt42HGjK+TwCGfNj48wSXulE7DY0qkqPxBq
|
||||
hA2oe6KPgQKBgEt3GR6dGx81+Y3wvMuwWrtrNP1Hm068RnrtpqZgc6Qby0qXqrAo
|
||||
N1b9D8kstin+kRbIa7GwqiMT0WSPHAtbfks229EJwpVFX6wAsR5smmTw8vj+KZ9D
|
||||
76rmiYXtHucVWMH3MOhNjf8O+FcuDcbDwWdha8OquGbIupzvpYi3y1qxAoGAPTEV
|
||||
L4ZTiaKyna8NPM35jrscQQ1oMIIDQ4cxddn/+fRItk13xNMSAWNr6ROROIT/NiEW
|
||||
Ob3fFnr7Ef77bOd8LCZ7YYziVseG8LpNqZPNP8m74ZbG9rSyt+uxpKY7VUEc5P8I
|
||||
iSrRPwV+Y9C1n3B1em/c2GqKma9keH3oBdWsZAECgYBHvF+l9m3FE8JW0gOvcpDu
|
||||
6ny1K8FcQhtuUFM+yeNTZCQoBkzw33DSO3GQJvO5qp6SDGAHVLrV7sshgc699gz8
|
||||
u9T2zUEHMK7b3VV90Cwl/SzDCyrK23TnJJQTf/lzdRwOxgrymxSaLXi9Dla8Z1a4
|
||||
8eSPkI1JPI4SWVxVvZXkUg==
|
||||
-----END PRIVATE KEY-----
|
@ -1,8 +1,7 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
tor:
|
||||
image: dperson/torproxy:latest
|
||||
build: ./tor
|
||||
image: 4nk_node-tor
|
||||
container_name: tor-proxy
|
||||
networks:
|
||||
btcnet:
|
||||
@ -12,6 +11,14 @@ services:
|
||||
- "9050:9050" # Port SOCKS
|
||||
- "9051:9051" # Port de contrôle
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./tor/torrc:/etc/tor/torrc:ro
|
||||
command: ["tor", "-f", "/etc/tor/torrc"]
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "nc -z 127.0.0.1 9050"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
bitcoin:
|
||||
build: ./bitcoin
|
||||
@ -21,10 +28,7 @@ services:
|
||||
volumes:
|
||||
- bitcoin_data:/home/bitcoin/.bitcoin
|
||||
- ./bitcoin/bitcoin.conf:/home/bitcoin/.bitcoin/bitcoin.conf
|
||||
ports:
|
||||
- "38333:38333" # signet p2p
|
||||
- "18443:18443" # signet rpc
|
||||
- "29000:29000" # zmq
|
||||
# ports supprimés: service interne uniquement
|
||||
networks:
|
||||
btcnet:
|
||||
aliases:
|
||||
@ -48,8 +52,7 @@ services:
|
||||
- blindbit_data:/data
|
||||
- ./blindbit/blindbit.toml:/data/blindbit.toml
|
||||
- bitcoin_data:/home/bitcoin/.bitcoin
|
||||
ports:
|
||||
- "8000:8000"
|
||||
# ports supprimés: service interne uniquement
|
||||
networks:
|
||||
btcnet:
|
||||
aliases:
|
||||
@ -71,9 +74,7 @@ services:
|
||||
- ./bitcoin/bitcoin.conf:/home/bitcoin/.bitcoin/bitcoin.conf
|
||||
- sdk_relay_1_data:/home/bitcoin/.4nk
|
||||
- ./sdk_relay/.conf.docker.relay1:/home/bitcoin/.conf.docker
|
||||
ports:
|
||||
- "8090:8090"
|
||||
- "8091:8091"
|
||||
# ports supprimés: service utilisé via reverse proxy interne
|
||||
networks:
|
||||
btcnet:
|
||||
aliases:
|
||||
@ -102,7 +103,7 @@ services:
|
||||
curl -s --connect-timeout 5 http://bitcoin:18443 &&
|
||||
echo 'Bitcoin accessible via curl' &&
|
||||
echo 'Starting sdk_relay_1:' &&
|
||||
/usr/local/bin/sdk_relay --config .conf"
|
||||
/usr/local/bin/sdk_relay serve --config .conf --ws 0.0.0.0:8090 --http 0.0.0.0:8091"
|
||||
healthcheck:
|
||||
test: ["CMD", "/usr/local/bin/healthcheck.sh"]
|
||||
interval: 30s
|
||||
@ -125,9 +126,7 @@ services:
|
||||
- ./bitcoin/bitcoin.conf:/home/bitcoin/.bitcoin/bitcoin.conf
|
||||
- sdk_relay_2_data:/home/bitcoin/.4nk
|
||||
- ./sdk_relay/.conf.docker.relay2:/home/bitcoin/.conf.docker
|
||||
ports:
|
||||
- "8092:8090"
|
||||
- "8093:8091"
|
||||
# ports supprimés: service utilisé via reverse proxy interne
|
||||
networks:
|
||||
btcnet:
|
||||
aliases:
|
||||
@ -156,7 +155,7 @@ services:
|
||||
curl -s --connect-timeout 5 http://bitcoin:18443 &&
|
||||
echo 'Bitcoin accessible via curl' &&
|
||||
echo 'Starting sdk_relay_2:' &&
|
||||
/usr/local/bin/sdk_relay --config .conf"
|
||||
/usr/local/bin/sdk_relay serve --config .conf --ws 0.0.0.0:8090 --http 0.0.0.0:8091"
|
||||
healthcheck:
|
||||
test: ["CMD", "/usr/local/bin/healthcheck.sh"]
|
||||
interval: 30s
|
||||
@ -179,9 +178,7 @@ services:
|
||||
- ./bitcoin/bitcoin.conf:/home/bitcoin/.bitcoin/bitcoin.conf
|
||||
- sdk_relay_3_data:/home/bitcoin/.4nk
|
||||
- ./sdk_relay/.conf.docker.relay3:/home/bitcoin/.conf.docker
|
||||
ports:
|
||||
- "8094:8090"
|
||||
- "8095:8091"
|
||||
# ports supprimés: service utilisé via reverse proxy interne
|
||||
networks:
|
||||
btcnet:
|
||||
aliases:
|
||||
@ -210,7 +207,7 @@ services:
|
||||
curl -s --connect-timeout 5 http://bitcoin:18443 &&
|
||||
echo 'Bitcoin accessible via curl' &&
|
||||
echo 'Starting sdk_relay_3:' &&
|
||||
/usr/local/bin/sdk_relay --config .conf"
|
||||
/usr/local/bin/sdk_relay serve --config .conf --ws 0.0.0.0:8090 --http 0.0.0.0:8091"
|
||||
healthcheck:
|
||||
test: ["CMD", "/usr/local/bin/healthcheck.sh"]
|
||||
interval: 30s
|
||||
@ -219,32 +216,30 @@ services:
|
||||
start_period: 60s
|
||||
|
||||
ihm_client:
|
||||
build:
|
||||
context: ./ihm_client
|
||||
dockerfile: Dockerfile
|
||||
image: busybox:latest
|
||||
container_name: 4nk-ihm-client
|
||||
ports:
|
||||
- "8080:80"
|
||||
environment:
|
||||
- SDK_RELAY_WS_URL=ws://sdk_relay_1:8090
|
||||
- SDK_RELAY_HTTP_URL=http://sdk_relay_1:8091
|
||||
- BITCOIN_RPC_URL=http://bitcoin:18443
|
||||
- BLINDBIT_URL=http://blindbit:8000
|
||||
command: sh -c "sleep infinity"
|
||||
volumes:
|
||||
- ihm_client_logs:/var/log/nginx
|
||||
- ./ihm_client/dist:/usr/share/nginx/html:ro
|
||||
networks:
|
||||
- btcnet
|
||||
|
||||
reverse_proxy:
|
||||
image: nginx:alpine
|
||||
container_name: 4nk-reverse-proxy
|
||||
depends_on:
|
||||
- sdk_relay_1
|
||||
- sdk_relay_2
|
||||
- sdk_relay_3
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--quiet", "--tries=1", "--timeout=5", "--spider", "http://localhost"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
volumes:
|
||||
- ./proxy/nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
- ./certs:/etc/nginx/certs:ro
|
||||
- ./ihm_client/dist:/usr/share/nginx/html:ro
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
networks:
|
||||
btcnet:
|
||||
aliases:
|
||||
- reverse_proxy
|
||||
|
||||
volumes:
|
||||
bitcoin_data:
|
||||
@ -257,8 +252,6 @@ volumes:
|
||||
name: 4nk_node_sdk_relay_2_data
|
||||
sdk_relay_3_data:
|
||||
name: 4nk_node_sdk_relay_3_data
|
||||
ihm_client_logs:
|
||||
driver: local
|
||||
|
||||
networks:
|
||||
btcnet:
|
||||
|
@ -35,6 +35,18 @@ L'infrastructure 4NK Node est composée de plusieurs services interconnectés qu
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
### Reverse proxy public (Nginx)
|
||||
|
||||
Un reverse proxy dédié assure désormais l'exposition publique unique de l'infrastructure :
|
||||
|
||||
- Sert les assets statiques de l’interface `ihm_client` générés dans `ihm_client/dist`
|
||||
- Termine TLS en 443 (auto-signé par défaut) et force la redirection HTTP→HTTPS
|
||||
- Proxifie les routes applicatives :
|
||||
- `/` → UI statique
|
||||
- `/api/` → `sdk_relay_1` (HTTP)
|
||||
- `/ws/` → `sdk_relay_1` (WebSocket, upgrade)
|
||||
- Tous les autres services restent strictement internes au réseau Docker `btcnet`
|
||||
|
||||
## Composants Principaux
|
||||
|
||||
### 1. Bitcoin Core (Nœud Signet)
|
||||
@ -230,33 +242,33 @@ pub struct MeshConnection {
|
||||
|
||||
### Configuration Docker
|
||||
|
||||
Le système supporte la configuration de plusieurs relais via Docker :
|
||||
Le système supporte la configuration de plusieurs relais via Docker, avec une publication unique via reverse proxy :
|
||||
|
||||
```yaml
|
||||
# Publication unique via reverse proxy
|
||||
services:
|
||||
reverse_proxy:
|
||||
image: nginx:alpine
|
||||
volumes:
|
||||
- ./proxy/nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
- ./certs:/etc/nginx/certs:ro
|
||||
- ./ihm_client/dist:/usr/share/nginx/html:ro
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
networks:
|
||||
- btcnet
|
||||
|
||||
# Relais internes seulement (pas de ports exposés)
|
||||
sdk_relay_1:
|
||||
container_name: sdk_relay_1
|
||||
ports:
|
||||
- "8090:8090"
|
||||
- "8091:8091"
|
||||
environment:
|
||||
- ENABLE_SYNC_TEST=1
|
||||
|
||||
networks:
|
||||
- btcnet
|
||||
sdk_relay_2:
|
||||
container_name: sdk_relay_2
|
||||
ports:
|
||||
- "8092:8090"
|
||||
- "8093:8091"
|
||||
environment:
|
||||
- ENABLE_SYNC_TEST=1
|
||||
|
||||
networks:
|
||||
- btcnet
|
||||
sdk_relay_3:
|
||||
container_name: sdk_relay_3
|
||||
ports:
|
||||
- "8094:8090"
|
||||
- "8095:8091"
|
||||
environment:
|
||||
- ENABLE_SYNC_TEST=1
|
||||
networks:
|
||||
- btcnet
|
||||
```
|
||||
|
||||
### Configuration par Relais
|
||||
@ -323,7 +335,7 @@ Client ──── WebSocket ──── SDK Relay ──── Bitcoin Core R
|
||||
### 1. Isolation Réseau
|
||||
|
||||
- **Réseau privé :** `btcnet` pour la communication inter-services
|
||||
- **Ports exposés :** Seulement les ports nécessaires
|
||||
- **Ports exposés :** Uniquement 80/443 sur `reverse_proxy` ; tous les autres services sont internes (aucune publication de ports)
|
||||
- **Volumes :** Données persistantes isolées
|
||||
|
||||
### 2. Authentification
|
||||
|
@ -46,11 +46,10 @@ sed -i 's/4nk_default/4nk-network/g' docker-compose.yml
|
||||
#### Configuration de Pare-feu
|
||||
|
||||
```bash
|
||||
# Autoriser les ports nécessaires
|
||||
sudo ufw allow 18443/tcp # Bitcoin Core RPC
|
||||
sudo ufw allow 8090/tcp # sdk_relay WebSocket
|
||||
sudo ufw allow 8000/tcp # Blindbit API
|
||||
sudo ufw allow 9050/tcp # Tor SOCKS
|
||||
# Exposition publique centralisée via reverse proxy uniquement
|
||||
sudo ufw allow 80/tcp # HTTP (redirection)
|
||||
sudo ufw allow 443/tcp # HTTPS (UI + API + WS)
|
||||
sudo ufw enable
|
||||
sudo ufw enable
|
||||
|
||||
# Vérifier les règles
|
||||
@ -390,51 +389,99 @@ certificate_verification = true
|
||||
|
||||
## 🔧 Configuration Tor
|
||||
|
||||
### 1. Configuration de Base
|
||||
### 1. Image et service Tor
|
||||
|
||||
Fichier : `tor/torrc`
|
||||
- Le service Tor est désormais construit localement depuis `tor/Dockerfile` et monté avec `tor/torrc`.
|
||||
- Le conteneur tourne en utilisateur `debian-tor` et expose uniquement le SOCKS (9050) et, en interne, un ControlPort local (127.0.0.1:9051).
|
||||
|
||||
Extrait `docker-compose.yml` (service `tor`):
|
||||
|
||||
```yaml
|
||||
services:
|
||||
tor:
|
||||
build: ./tor
|
||||
image: 4nk_node-tor
|
||||
container_name: tor-proxy
|
||||
ports:
|
||||
- "9050:9050"
|
||||
- "9051:9051"
|
||||
volumes:
|
||||
- ./tor/torrc:/etc/tor/torrc:ro
|
||||
command: ["tor", "-f", "/etc/tor/torrc"]
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "nc -z 127.0.0.1 9050"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
networks:
|
||||
- btcnet
|
||||
```
|
||||
|
||||
### 2. Fichier `tor/torrc`
|
||||
|
||||
Configuration de base (extrait) :
|
||||
|
||||
```ini
|
||||
# Configuration Tor
|
||||
SocksPort 9050
|
||||
ControlPort 9051
|
||||
SocksPort 0.0.0.0:9050
|
||||
ControlPort 127.0.0.1:9051
|
||||
DataDirectory /var/lib/tor
|
||||
PidFile /var/run/tor/tor.pid
|
||||
|
||||
# Logs
|
||||
Log notice file /var/log/tor/notices.log
|
||||
Log info file /var/log/tor/info.log
|
||||
|
||||
# Sécurité
|
||||
CookieAuthentication 1
|
||||
Log notice stdout
|
||||
ClientUseIPv6 1
|
||||
SafeLogging 1
|
||||
ReducedConnectionPadding 1
|
||||
SocksPolicy accept 0.0.0.0/0
|
||||
AutomapHostsOnResolve 1
|
||||
```
|
||||
|
||||
### 2. Configuration Avancée
|
||||
### 3. Bridges obfs4 (optionnels)
|
||||
|
||||
#### Performance
|
||||
Pour contourner des filtrages réseaux, activer les bridges obfs4 dans `tor/torrc` :
|
||||
|
||||
```ini
|
||||
# Optimisation réseau
|
||||
MaxCircuitDirtiness 600
|
||||
MaxClientCircuitsPending 32
|
||||
EnforceDistinctSubnets 1
|
||||
|
||||
# Cache
|
||||
MaxMemInQueues 64 MB
|
||||
UseBridges 1
|
||||
ClientTransportPlugin obfs4 exec /usr/bin/obfs4proxy
|
||||
Bridge obfs4 81.64.0.218:6697 53E6469DC06BED50543AED0311D66082F4B66676 cert=zOKy+MnZ4wWbKcENcyaElPu62PEaXdE/c802ssuzCIDa2aIC1+J4LyfPhAwSiLaAo/I/bg iat-mode=0
|
||||
Bridge obfs4 198.98.53.149:443 886CA31F71272FC8B3808C601FA3ABB8A2905DB4 cert=D+zypuFdMpP8riBUbInxIguzqClR0JKkP1DbkKz5es1+OP2Fao8jiXyM+B/+DYA2ZFy6UA iat-mode=0
|
||||
```
|
||||
|
||||
#### Sécurité
|
||||
L’image Tor installe `obfs4proxy`. Après modification :
|
||||
|
||||
```ini
|
||||
# Authentification
|
||||
CookieAuthentication 1
|
||||
ControlPort 9051
|
||||
|
||||
# Limites
|
||||
MaxConnections 1000
|
||||
MaxConnectionsEntry 100
|
||||
```bash
|
||||
sudo docker compose build tor
|
||||
sudo docker compose up -d tor
|
||||
```
|
||||
|
||||
Vérifications :
|
||||
|
||||
```bash
|
||||
sudo docker compose ps tor
|
||||
sudo docker logs tor-proxy --tail=40
|
||||
sudo docker exec tor-proxy nc -z 127.0.0.1 9050 && echo SOCKS:OK
|
||||
```
|
||||
|
||||
#### Notes et recommandations (Tor/bridges)
|
||||
|
||||
- Le `ControlPort 127.0.0.1:9051` est utilisé pour le diagnostic interne. Ne pas l’exposer publiquement. Une authentification peut être activée si un contrôle à distance est requis.
|
||||
- Les bridges obfs4 ci‑dessus proviennent de la page de référence du Tor Project. En cas d’échec répété (messages « general SOCKS server failure » côté Tor), ajouter 2–3 bridges supplémentaires depuis la même source et redémarrer le service Tor.
|
||||
- Les tests de connectivité doivent distinguer :
|
||||
- Accès SOCKS vers des services onion « publics » (ex. DuckDuckGo) pour valider le proxy Tor.
|
||||
- Accès SOCKS vers l’onion cible du signet pour valider la reachability du pair.
|
||||
- À la date d’édition, le proxy SOCKS fonctionne (onion publics accessibles), mais le pair signet `.onion:38333` est injoignable (host unreachable). La configuration du signet (signetchallenge et addnode) doit rester inchangée, conformément à la contrainte fonctionnelle.
|
||||
|
||||
#### Outils de diagnostic réseau
|
||||
|
||||
- Installer `netcat-openbsd` sur l’hôte et dans les conteneurs pertinents pour faciliter les vérifications :
|
||||
- Hôte : `sudo apt-get install -y netcat-openbsd`
|
||||
- Conteneur Bitcoin (root) : `apt-get update && apt-get install -y --no-install-recommends netcat-openbsd`
|
||||
- Exemples de vérifications :
|
||||
- `nc -vz -w 10 -x 127.0.0.1:9050 -X 5 <onion> 80`
|
||||
- `nc -vz -w 10 -x 127.0.0.1:9050 -X 5 <onion_signet> 38333`
|
||||
|
||||
#### DNS externes (ex. dev.4nkweb.com)
|
||||
|
||||
- Si un nom de domaine (ex. `dev.4nkweb.com`) doit pointer vers un service, s’assurer qu’un enregistrement DNS A/AAAA existe. En l’absence de résolution, les tests échoueront côté HTTP/HTTPS et TCP.
|
||||
- En phase de test, une entrée temporaire peut être ajoutée dans `/etc/hosts` si l’IP est connue.
|
||||
|
||||
## 🔧 Configuration Docker Compose
|
||||
|
||||
### 1. Configuration de Base
|
||||
@ -442,112 +489,34 @@ MaxConnectionsEntry 100
|
||||
Fichier : `docker-compose.yml`
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
# Compose modernisé (sans clé version), publication unique via reverse proxy
|
||||
services:
|
||||
tor:
|
||||
image: dperson/torproxy:latest
|
||||
container_name: tor-proxy
|
||||
reverse_proxy:
|
||||
image: nginx:alpine
|
||||
depends_on:
|
||||
- sdk_relay_1
|
||||
volumes:
|
||||
- ./proxy/nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
- ./certs:/etc/nginx/certs:ro
|
||||
- ./ihm_client/dist:/usr/share/nginx/html:ro
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
networks:
|
||||
btcnet:
|
||||
aliases:
|
||||
- tor
|
||||
ports:
|
||||
- "9050:9050"
|
||||
- "9051:9051"
|
||||
restart: unless-stopped
|
||||
- reverse_proxy
|
||||
|
||||
# Tous les autres services sont internes (pas de ports exposés)
|
||||
bitcoin:
|
||||
build: ./bitcoin
|
||||
container_name: bitcoin-signet
|
||||
depends_on:
|
||||
- tor
|
||||
volumes:
|
||||
- bitcoin_data:/home/bitcoin/.bitcoin
|
||||
- ./bitcoin/bitcoin.conf:/home/bitcoin/.bitcoin/bitcoin.conf
|
||||
ports:
|
||||
- "38333:38333"
|
||||
- "18443:18443"
|
||||
- "29000:29000"
|
||||
networks:
|
||||
btcnet:
|
||||
aliases:
|
||||
- bitcoin
|
||||
environment:
|
||||
- TOR_HOST=tor
|
||||
- TOR_PORT=9050
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "bitcoin-cli", "-conf=/home/bitcoin/.bitcoin/bitcoin.conf", "getblockchaininfo"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
- btcnet
|
||||
blindbit:
|
||||
build: ./blindbit
|
||||
container_name: blindbit-oracle
|
||||
depends_on:
|
||||
- bitcoin
|
||||
volumes:
|
||||
- blindbit_data:/data
|
||||
- ./blindbit/blindbit.toml:/data/blindbit.toml
|
||||
- bitcoin_data:/home/bitcoin/.bitcoin
|
||||
ports:
|
||||
- "8000:8000"
|
||||
networks:
|
||||
btcnet:
|
||||
aliases:
|
||||
- blindbit
|
||||
restart: unless-stopped
|
||||
|
||||
- btcnet
|
||||
sdk_relay_1:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: 4NK_node/sdk_relay/Dockerfile
|
||||
container_name: sdk_relay_1
|
||||
depends_on:
|
||||
bitcoin:
|
||||
condition: service_healthy
|
||||
blindbit:
|
||||
condition: service_started
|
||||
volumes:
|
||||
- bitcoin_data:/home/bitcoin/.bitcoin
|
||||
- ./bitcoin/bitcoin.conf:/home/bitcoin/.bitcoin/bitcoin.conf
|
||||
- sdk_relay_1_data:/home/bitcoin/.4nk
|
||||
- ./sdk_relay/.conf.docker.relay1:/home/bitcoin/.conf.docker
|
||||
- ./sdk_relay/external_nodes.conf:/home/bitcoin/.4nk/external_nodes.conf
|
||||
ports:
|
||||
- "8090:8090"
|
||||
- "8091:8091"
|
||||
networks:
|
||||
btcnet:
|
||||
aliases:
|
||||
- sdk_relay_1
|
||||
environment:
|
||||
- RUST_LOG=debug,bitcoincore_rpc=trace
|
||||
- HOME=/home/bitcoin
|
||||
- BITCOIN_COOKIE_PATH=/home/bitcoin/.bitcoin/signet/.cookie
|
||||
- ENABLE_SYNC_TEST=1
|
||||
restart: on-failure:3
|
||||
healthcheck:
|
||||
test: ["CMD", "/usr/local/bin/healthcheck.sh"]
|
||||
interval: 30s
|
||||
timeout: 15s
|
||||
retries: 3
|
||||
start_period: 60s
|
||||
|
||||
volumes:
|
||||
bitcoin_data:
|
||||
name: 4nk_node_bitcoin_data
|
||||
blindbit_data:
|
||||
name: 4nk_node_blindbit_data
|
||||
sdk_relay_1_data:
|
||||
name: 4nk_node_sdk_relay_1_data
|
||||
|
||||
networks:
|
||||
btcnet:
|
||||
name: 4nk_node_btcnet
|
||||
driver: bridge
|
||||
- btcnet
|
||||
```
|
||||
|
||||
### 2. Configuration Avancée
|
||||
@ -601,34 +570,12 @@ services:
|
||||
### 1. Certificat Auto-Signé
|
||||
|
||||
```bash
|
||||
# Générer un certificat auto-signé
|
||||
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
|
||||
# Générer et protéger des certificats auto-signés
|
||||
./scripts/generate_certs.sh
|
||||
|
||||
# Configurer nginx comme proxy SSL
|
||||
cat > nginx.conf << EOF
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name your-domain.com;
|
||||
|
||||
ssl_certificate cert.pem;
|
||||
ssl_certificate_key key.pem;
|
||||
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
location / {
|
||||
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;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
# Les certificats sont montés par le reverse proxy :
|
||||
# - certs/server.crt -> /etc/nginx/certs/server.crt
|
||||
# - certs/server.key -> /etc/nginx/certs/server.key
|
||||
```
|
||||
|
||||
### 2. Certificat Let's Encrypt
|
||||
|
@ -21,7 +21,16 @@ Guide complet pour installer et configurer l'infrastructure 4NK Node.
|
||||
|
||||
## 🚀 Installation
|
||||
|
||||
### 1. Installation de Docker
|
||||
### 1. Amorçage automatique (recommandé)
|
||||
|
||||
Exécuter le script d’amorçage qui installe git, Docker, Docker Compose, Node.js/npm (via nvm, dernière LTS) et ajoute l’utilisateur au groupe docker dès le début.
|
||||
|
||||
```bash
|
||||
./scripts/bootstrap.sh
|
||||
# Se déconnecter/reconnecter ensuite ou `newgrp docker` pour activer le groupe docker
|
||||
```
|
||||
|
||||
### 2. Installation de Docker (manuel)
|
||||
|
||||
#### Ubuntu/Debian
|
||||
|
||||
@ -70,7 +79,7 @@ sudo systemctl enable docker
|
||||
sudo usermod -aG docker $USER
|
||||
```
|
||||
|
||||
### 2. Configuration SSH (Recommandé)
|
||||
### 3. Configuration SSH (recommandé)
|
||||
|
||||
```bash
|
||||
# Générer une clé SSH
|
||||
@ -91,7 +100,7 @@ cat ~/.ssh/id_ed25519_4nk.pub
|
||||
2. Coller la clé publique
|
||||
3. Cliquer sur "Add key"
|
||||
|
||||
### 3. Clonage du Repository
|
||||
### 4. Clonage du repository
|
||||
|
||||
```bash
|
||||
# Cloner avec SSH (recommandé)
|
||||
@ -103,7 +112,7 @@ cd 4NK_node
|
||||
# cd 4NK_node
|
||||
```
|
||||
|
||||
### 4. Vérification de l'Installation
|
||||
### 5. Vérification de l'installation
|
||||
|
||||
```bash
|
||||
# Vérifier Docker
|
||||
@ -117,7 +126,7 @@ ssh -T git@git.4nkweb.com
|
||||
ls -la
|
||||
```
|
||||
|
||||
## 🔧 Configuration Initiale
|
||||
## 🔧 Configuration initiale
|
||||
|
||||
### 1. Configuration des Variables d'Environnement
|
||||
|
||||
@ -147,7 +156,23 @@ RELAY_3_PORTS=8094:8090,8095:8091
|
||||
EOF
|
||||
```
|
||||
|
||||
### 2. Configuration Bitcoin Core
|
||||
### 2. Préparation de l’UI (ihm_client)
|
||||
|
||||
```bash
|
||||
# Construire l’UI localement et produire ./ihm_client/dist
|
||||
chmod +x scripts/build_ui_local.sh
|
||||
./scripts/build_ui_local.sh
|
||||
```
|
||||
|
||||
### 3. Génération des certificats
|
||||
|
||||
```bash
|
||||
# Générer les certificats auto-signés et appliquer les bons droits
|
||||
chmod +x scripts/generate_certs.sh
|
||||
./scripts/generate_certs.sh
|
||||
```
|
||||
|
||||
### 4. Configuration Bitcoin Core
|
||||
|
||||
```bash
|
||||
# Vérifier la configuration Bitcoin
|
||||
@ -172,7 +197,26 @@ server=1
|
||||
listen=1
|
||||
```
|
||||
|
||||
### 3. Configuration Blindbit
|
||||
### 5. Configuration Tor (option bridges)
|
||||
|
||||
Si votre réseau nécessite des bridges obfs4, ajoutez-les dans `tor/torrc` :
|
||||
|
||||
```ini
|
||||
UseBridges 1
|
||||
ClientTransportPlugin obfs4 exec /usr/bin/obfs4proxy
|
||||
# Exemple
|
||||
Bridge obfs4 81.64.0.218:6697 53E6469DC06BED50543AED0311D66082F4B66676 cert=zOKy+MnZ4wWbKcENcyaElPu62PEaXdE/c802ssuzCIDa2aIC1+J4LyfPhAwSiLaAo/I/bg iat-mode=0
|
||||
Bridge obfs4 198.98.53.149:443 886CA31F71272FC8B3808C601FA3ABB8A2905DB4 cert=D+zypuFdMpP8riBUbInxIguzqClR0JKkP1DbkKz5es1+OP2Fao8jiXyM+B/+DYA2ZFy6UA iat-mode=0
|
||||
```
|
||||
|
||||
Puis reconstruire et (re)démarrer :
|
||||
|
||||
```bash
|
||||
sudo docker compose build tor
|
||||
sudo docker compose up -d tor
|
||||
```
|
||||
|
||||
### 6. Configuration Blindbit
|
||||
|
||||
```bash
|
||||
# Vérifier la configuration Blindbit
|
||||
@ -194,7 +238,7 @@ max_parallel_tweak_computations = 4
|
||||
max_parallel_requests = 4
|
||||
```
|
||||
|
||||
### 4. Configuration des Relais
|
||||
### 7. Configuration des Relais
|
||||
|
||||
```bash
|
||||
# Vérifier les configurations des relais
|
||||
@ -227,8 +271,8 @@ relay_id=relay-1 # Changer pour chaque relay
|
||||
### 1. Démarrage Complet
|
||||
|
||||
```bash
|
||||
# Démarrer tous les services
|
||||
./restart_4nk_node.sh
|
||||
# Démarrer l’infrastructure (reverse proxy inclus)
|
||||
sudo docker compose up -d --build
|
||||
|
||||
# Vérifier le statut
|
||||
docker ps
|
||||
@ -237,21 +281,21 @@ docker ps
|
||||
### 2. Démarrage Séquentiel (Debug)
|
||||
|
||||
```bash
|
||||
# Démarrer Tor
|
||||
./restart_4nk_node.sh -t
|
||||
# Démarrer Tor (si utilisé)
|
||||
sudo docker compose up -d tor
|
||||
|
||||
# Démarrer Bitcoin Core
|
||||
./restart_4nk_node.sh -b
|
||||
sudo docker compose up -d bitcoin
|
||||
|
||||
# Attendre la synchronisation Bitcoin (10-30 minutes)
|
||||
echo "Attendre la synchronisation Bitcoin..."
|
||||
docker logs bitcoin-signet | grep "progress"
|
||||
|
||||
# Démarrer Blindbit
|
||||
./restart_4nk_node.sh -l
|
||||
sudo docker compose up -d blindbit
|
||||
|
||||
# Démarrer les relais
|
||||
./restart_4nk_node.sh -r
|
||||
# Démarrer les relais et le reverse proxy
|
||||
sudo docker compose up -d sdk_relay_1 sdk_relay_2 sdk_relay_3 reverse_proxy
|
||||
```
|
||||
|
||||
### 3. Vérification du Démarrage
|
||||
@ -263,8 +307,9 @@ docker ps
|
||||
# Vérifier les logs
|
||||
docker-compose logs --tail=50
|
||||
|
||||
# Vérifier la connectivité
|
||||
./test_final_sync.sh
|
||||
# Vérifier l’accès public
|
||||
curl -kI https://<IP_VM>/
|
||||
curl -kI https://<IP_VM>/api/
|
||||
```
|
||||
|
||||
## 🧪 Tests Post-Installation
|
||||
|
@ -91,6 +91,7 @@ Options disponibles :
|
||||
- `test_final_sync.sh` : Test complet de synchronisation
|
||||
- `test_sync_logs.sh` : Test des logs de synchronisation
|
||||
- `test_messages.sh` : Test des messages entre relais
|
||||
- `scripts/test_ui.sh` : Build UI, déploiement reverse proxy et vérifications HTTPS (headers, index, modules JS)
|
||||
|
||||
**Prérequis :**
|
||||
- Tous les services Docker démarrés (bitcoin, blindbit, sdk_relay)
|
||||
@ -104,6 +105,12 @@ Options disponibles :
|
||||
**Tests inclus :**
|
||||
- `test_connectivity.sh` : Test de connectivité des services
|
||||
- `test_websocket_messages.py` : Test des messages WebSocket
|
||||
- Tests externes reverse proxy :
|
||||
```bash
|
||||
curl -kI https://<IP_VM>/
|
||||
curl -kI https://<IP_VM>/api/
|
||||
npx wscat -c wss://<IP_VM>/ws --no-check
|
||||
```
|
||||
|
||||
**Prérequis :**
|
||||
- Services Docker démarrés
|
||||
@ -276,6 +283,64 @@ Structure du rapport :
|
||||
**Symptôme** : Erreur SSL dans les tests externes
|
||||
**Solution** : Vérifier les certificats et la configuration SSL
|
||||
|
||||
### Dépannage Tor/Bitcoin (signet custom)
|
||||
|
||||
#### Vérifier Tor
|
||||
```bash
|
||||
# État du conteneur Tor
|
||||
sudo docker compose ps tor
|
||||
|
||||
# Derniers logs Tor
|
||||
sudo docker logs tor-proxy --tail=60
|
||||
|
||||
# Test du port SOCKS interne
|
||||
sudo docker exec tor-proxy nc -z 127.0.0.1 9050 && echo SOCKS:OK
|
||||
```
|
||||
|
||||
#### Bridges obfs4 et diagnostics
|
||||
|
||||
- Les bridges obfs4 peuvent être ajoutés dans `tor/torrc` (cf. docs/CONFIGURATION.md). Après ajout, redémarrer le service Tor.
|
||||
- En cas d’échec « general SOCKS server failure », remplacer/ajouter des bridges et re‑tester.
|
||||
- Valider la différence entre :
|
||||
- `nc -vz -w 10 -x 127.0.0.1:9050 -X 5 duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion 80` (référence onion publique)
|
||||
- `nc -vz -w 10 -x 127.0.0.1:9050 -X 5 <onion_signet> 38333` (pair signet cible)
|
||||
|
||||
#### Vérifier Bitcoin Core côté réseau
|
||||
```bash
|
||||
# Connexions réseau
|
||||
sudo docker exec bitcoin-signet bitcoin-cli -signet getnetworkinfo | jq '.connections,.connections_in,.connections_out'
|
||||
|
||||
# Pairs et nombre total
|
||||
sudo docker exec bitcoin-signet bitcoin-cli -signet getpeerinfo | wc -l
|
||||
```
|
||||
|
||||
#### Forcer une tentative de pair (onion existant)
|
||||
```bash
|
||||
ONION=$(awk -F= '/^addnode=/{print $2}' bitcoin/bitcoin.conf | head -n1)
|
||||
sudo docker exec bitcoin-signet bitcoin-cli -signet addnode ${ONION}:38333 onetry
|
||||
sleep 5
|
||||
sudo docker exec bitcoin-signet bitcoin-cli -signet getconnectioncount
|
||||
```
|
||||
|
||||
#### Boucle de retry signet (optionnelle)
|
||||
|
||||
Un script dédié permet de tenter automatiquement l’ajout du pair signet `.onion` et de redémarrer `sdk_relay_1` une fois des connexions établies :
|
||||
|
||||
```bash
|
||||
./scripts/retry_signet_sync.sh
|
||||
```
|
||||
|
||||
Les logs sont conservés sous `tests/logs/signet_sync_*.log`.
|
||||
|
||||
#### Vérifier l’ouverture des ports du relais et l’API
|
||||
```bash
|
||||
# Ports 8090/8091 dans sdk_relay_1
|
||||
sudo docker exec sdk_relay_1 sh -lc 'ss -lntp 2>/dev/null || netstat -tlnp 2>/dev/null' | grep -E ':8090 |:8091 ' || echo no-listen
|
||||
|
||||
# Test /api via reverse proxy
|
||||
curl -k -I https://localhost/api/
|
||||
```
|
||||
|
||||
#### Dépendances Python
|
||||
**Symptôme** : ModuleNotFoundError
|
||||
**Solution** : Installer les dépendances avec `pip install websockets`
|
||||
|
@ -7,8 +7,8 @@ Guide complet pour utiliser l'infrastructure 4NK Node au quotidien.
|
||||
### 1. Démarrage Rapide
|
||||
|
||||
```bash
|
||||
# Démarrer tous les services
|
||||
./restart_4nk_node.sh
|
||||
# Démarrer l’infrastructure (reverse proxy inclus)
|
||||
sudo docker compose up -d --build
|
||||
|
||||
# Vérifier le statut
|
||||
docker ps
|
||||
@ -17,21 +17,21 @@ docker ps
|
||||
### 2. Démarrage Séquentiel
|
||||
|
||||
```bash
|
||||
# Démarrer Tor
|
||||
./restart_4nk_node.sh -t
|
||||
# Démarrer Tor (si utilisé)
|
||||
sudo docker compose up -d tor
|
||||
|
||||
# Démarrer Bitcoin Core
|
||||
./restart_4nk_node.sh -b
|
||||
sudo docker compose up -d bitcoin
|
||||
|
||||
# Attendre la synchronisation Bitcoin
|
||||
echo "Attendre la synchronisation Bitcoin (10-30 minutes)..."
|
||||
docker logs bitcoin-signet | grep "progress"
|
||||
|
||||
# Démarrer Blindbit
|
||||
./restart_4nk_node.sh -l
|
||||
sudo docker compose up -d blindbit
|
||||
|
||||
# Démarrer les relais
|
||||
./restart_4nk_node.sh -r
|
||||
# Démarrer les relais et le reverse proxy
|
||||
sudo docker compose up -d sdk_relay_1 sdk_relay_2 sdk_relay_3 reverse_proxy
|
||||
```
|
||||
|
||||
### 3. Vérification du Démarrage
|
||||
@ -99,17 +99,17 @@ docker-compose logs --since="2024-01-01T00:00:00"
|
||||
docker-compose logs --tail=100
|
||||
```
|
||||
|
||||
## 🌐 Utilisation du Réseau de Relais
|
||||
## 🌐 Utilisation via reverse proxy
|
||||
|
||||
### 1. Configuration des Relais
|
||||
|
||||
L'infrastructure utilise 3 relais locaux :
|
||||
|
||||
| Relay | Port WebSocket | Port HTTP | Configuration |
|
||||
|-------|----------------|-----------|---------------|
|
||||
| **Relay 1** | 8090 | 8091 | `sdk_relay/.conf.docker.relay1` |
|
||||
| **Relay 2** | 8092 | 8093 | `sdk_relay/.conf.docker.relay2` |
|
||||
| **Relay 3** | 8094 | 8095 | `sdk_relay/.conf.docker.relay3` |
|
||||
Les accès externes se font via le reverse proxy unique :
|
||||
|
||||
- UI : `https://<IP_VM>/`
|
||||
- API : `https://<IP_VM>/api/`
|
||||
- WebSocket : `wss://<IP_VM>/ws/`
|
||||
|
||||
### 2. Test de Connectivité des Relais
|
||||
|
||||
|
6771
ihm_client/dist/account-component-DE4nz5rE.mjs
vendored
Normal file
6771
ihm_client/dist/account-component-DE4nz5rE.mjs
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
ihm_client/dist/assets/4nk_image.png
vendored
Executable file
BIN
ihm_client/dist/assets/4nk_image.png
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 61 KiB |
BIN
ihm_client/dist/assets/4nk_revoke.jpg
vendored
Executable file
BIN
ihm_client/dist/assets/4nk_revoke.jpg
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 67 KiB |
BIN
ihm_client/dist/assets/bgd.webp
vendored
Executable file
BIN
ihm_client/dist/assets/bgd.webp
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 509 KiB |
BIN
ihm_client/dist/assets/camera.jpg
vendored
Executable file
BIN
ihm_client/dist/assets/camera.jpg
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 73 KiB |
34
ihm_client/dist/assets/home.js
vendored
Executable file
34
ihm_client/dist/assets/home.js
vendored
Executable file
@ -0,0 +1,34 @@
|
||||
document.querySelectorAll('.tab').forEach(tab => {
|
||||
tab.addEventListener('click', () => {
|
||||
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
|
||||
tab.classList.add('active');
|
||||
|
||||
document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
|
||||
document.getElementById(tab.getAttribute('data-tab')).classList.add('active');
|
||||
});
|
||||
});
|
||||
function toggleMenu() {
|
||||
var menu = document.getElementById('menu');
|
||||
if (menu.style.display === 'block') {
|
||||
menu.style.display = 'none';
|
||||
} else {
|
||||
menu.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
//// Modal
|
||||
function openModal() {
|
||||
document.getElementById('modal').style.display = 'flex';
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
document.getElementById('modal').style.display = 'none';
|
||||
}
|
||||
|
||||
// Close modal when clicking outside of it
|
||||
window.onclick = function(event) {
|
||||
const modal = document.getElementById('modal');
|
||||
if (event.target === modal) {
|
||||
closeModal();
|
||||
}
|
||||
}
|
BIN
ihm_client/dist/assets/qr_code.png
vendored
Executable file
BIN
ihm_client/dist/assets/qr_code.png
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 8.9 KiB |
6
ihm_client/dist/document.utils-SxcZpxzG.mjs
vendored
Normal file
6
ihm_client/dist/document.utils-SxcZpxzG.mjs
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
function getCorrectDOM(componentTag) {
|
||||
const dom = document?.querySelector(componentTag)?.shadowRoot || document;
|
||||
return dom;
|
||||
}
|
||||
|
||||
export { getCorrectDOM as g };
|
9546
ihm_client/dist/index-C1Gp83RD.mjs
vendored
Normal file
9546
ihm_client/dist/index-C1Gp83RD.mjs
vendored
Normal file
File diff suppressed because one or more lines are too long
13
ihm_client/dist/index.html
vendored
Normal file
13
ihm_client/dist/index.html
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>4NK UI</title>
|
||||
<link rel="stylesheet" href="/style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/index.js"></script>
|
||||
</body>
|
||||
</html>
|
1
ihm_client/dist/index.js
vendored
Normal file
1
ihm_client/dist/index.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
export { D as Database, M as MessageType, S as Services } from './index-C1Gp83RD.mjs';
|
14
ihm_client/dist/process-element-BXlOpT8a.mjs
vendored
Normal file
14
ihm_client/dist/process-element-BXlOpT8a.mjs
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
import { S as Services } from './index-C1Gp83RD.mjs';
|
||||
import { g as getCorrectDOM } from './document.utils-SxcZpxzG.mjs';
|
||||
|
||||
async function initProcessElement(id, zone) {
|
||||
await getProcesses();
|
||||
getCorrectDOM("process-4nk-component");
|
||||
}
|
||||
async function getProcesses() {
|
||||
const service = await Services.getInstance();
|
||||
const processes = await service.getProcesses();
|
||||
return processes;
|
||||
}
|
||||
|
||||
export { initProcessElement };
|
100
ihm_client/dist/qr-scanner-worker.min-Dy0qkKA4.mjs
vendored
Normal file
100
ihm_client/dist/qr-scanner-worker.min-Dy0qkKA4.mjs
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
const createWorker=()=>new Worker(URL.createObjectURL(new Blob([`class x{constructor(a,b){this.width=b;this.height=a.length/b;this.data=a}static createEmpty(a,b){return new x(new Uint8ClampedArray(a*b),a)}get(a,b){return 0>a||a>=this.width||0>b||b>=this.height?!1:!!this.data[b*this.width+a]}set(a,b,c){this.data[b*this.width+a]=c?1:0}setRegion(a,b,c,d,e){for(let f=b;f<b+d;f++)for(let g=a;g<a+c;g++)this.set(g,f,!!e)}}
|
||||
class A{constructor(a,b,c){this.width=a;a*=b;if(c&&c.length!==a)throw Error("Wrong buffer size");this.data=c||new Uint8ClampedArray(a)}get(a,b){return this.data[b*this.width+a]}set(a,b,c){this.data[b*this.width+a]=c}}
|
||||
class ba{constructor(a){this.bitOffset=this.byteOffset=0;this.bytes=a}readBits(a){if(1>a||32<a||a>this.available())throw Error("Cannot read "+a.toString()+" bits");var b=0;if(0<this.bitOffset){b=8-this.bitOffset;var c=a<b?a:b;b-=c;b=(this.bytes[this.byteOffset]&255>>8-c<<b)>>b;a-=c;this.bitOffset+=c;8===this.bitOffset&&(this.bitOffset=0,this.byteOffset++)}if(0<a){for(;8<=a;)b=b<<8|this.bytes[this.byteOffset]&255,this.byteOffset++,a-=8;0<a&&(c=8-a,b=b<<a|(this.bytes[this.byteOffset]&255>>c<<c)>>c,
|
||||
this.bitOffset+=a)}return b}available(){return 8*(this.bytes.length-this.byteOffset)-this.bitOffset}}var B,C=B||(B={});C.Numeric="numeric";C.Alphanumeric="alphanumeric";C.Byte="byte";C.Kanji="kanji";C.ECI="eci";C.StructuredAppend="structuredappend";var D,E=D||(D={});E[E.Terminator=0]="Terminator";E[E.Numeric=1]="Numeric";E[E.Alphanumeric=2]="Alphanumeric";E[E.Byte=4]="Byte";E[E.Kanji=8]="Kanji";E[E.ECI=7]="ECI";E[E.StructuredAppend=3]="StructuredAppend";let F="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:".split("");
|
||||
function ca(a,b){let c=[],d="";b=a.readBits([8,16,16][b]);for(let e=0;e<b;e++){let f=a.readBits(8);c.push(f)}try{d+=decodeURIComponent(c.map(e=>\`%\${("0"+e.toString(16)).substr(-2)}\`).join(""))}catch(e){}return{bytes:c,text:d}}
|
||||
function da(a,b){a=new ba(a);let c=9>=b?0:26>=b?1:2;for(b={text:"",bytes:[],chunks:[],version:b};4<=a.available();){var d=a.readBits(4);if(d===D.Terminator)return b;if(d===D.ECI)0===a.readBits(1)?b.chunks.push({type:B.ECI,assignmentNumber:a.readBits(7)}):0===a.readBits(1)?b.chunks.push({type:B.ECI,assignmentNumber:a.readBits(14)}):0===a.readBits(1)?b.chunks.push({type:B.ECI,assignmentNumber:a.readBits(21)}):b.chunks.push({type:B.ECI,assignmentNumber:-1});else if(d===D.Numeric){var e=a,f=[];d="";for(var g=
|
||||
e.readBits([10,12,14][c]);3<=g;){var h=e.readBits(10);if(1E3<=h)throw Error("Invalid numeric value above 999");var k=Math.floor(h/100),m=Math.floor(h/10)%10;h%=10;f.push(48+k,48+m,48+h);d+=k.toString()+m.toString()+h.toString();g-=3}if(2===g){g=e.readBits(7);if(100<=g)throw Error("Invalid numeric value above 99");e=Math.floor(g/10);g%=10;f.push(48+e,48+g);d+=e.toString()+g.toString()}else if(1===g){e=e.readBits(4);if(10<=e)throw Error("Invalid numeric value above 9");f.push(48+e);d+=e.toString()}b.text+=
|
||||
d;b.bytes.push(...f);b.chunks.push({type:B.Numeric,text:d})}else if(d===D.Alphanumeric){e=a;f=[];d="";for(g=e.readBits([9,11,13][c]);2<=g;)m=e.readBits(11),k=Math.floor(m/45),m%=45,f.push(F[k].charCodeAt(0),F[m].charCodeAt(0)),d+=F[k]+F[m],g-=2;1===g&&(e=e.readBits(6),f.push(F[e].charCodeAt(0)),d+=F[e]);b.text+=d;b.bytes.push(...f);b.chunks.push({type:B.Alphanumeric,text:d})}else if(d===D.Byte)d=ca(a,c),b.text+=d.text,b.bytes.push(...d.bytes),b.chunks.push({type:B.Byte,bytes:d.bytes,text:d.text});
|
||||
else if(d===D.Kanji){f=a;d=[];e=f.readBits([8,10,12][c]);for(g=0;g<e;g++)k=f.readBits(13),k=Math.floor(k/192)<<8|k%192,k=7936>k?k+33088:k+49472,d.push(k>>8,k&255);f=(new TextDecoder("shift-jis")).decode(Uint8Array.from(d));b.text+=f;b.bytes.push(...d);b.chunks.push({type:B.Kanji,bytes:d,text:f})}else d===D.StructuredAppend&&b.chunks.push({type:B.StructuredAppend,currentSequence:a.readBits(4),totalSequence:a.readBits(4),parity:a.readBits(8)})}if(0===a.available()||0===a.readBits(a.available()))return b}
|
||||
class G{constructor(a,b){if(0===b.length)throw Error("No coefficients.");this.field=a;let c=b.length;if(1<c&&0===b[0]){let d=1;for(;d<c&&0===b[d];)d++;if(d===c)this.coefficients=a.zero.coefficients;else for(this.coefficients=new Uint8ClampedArray(c-d),a=0;a<this.coefficients.length;a++)this.coefficients[a]=b[d+a]}else this.coefficients=b}degree(){return this.coefficients.length-1}isZero(){return 0===this.coefficients[0]}getCoefficient(a){return this.coefficients[this.coefficients.length-1-a]}addOrSubtract(a){if(this.isZero())return a;
|
||||
if(a.isZero())return this;let b=this.coefficients;a=a.coefficients;b.length>a.length&&([b,a]=[a,b]);let c=new Uint8ClampedArray(a.length),d=a.length-b.length;for(var e=0;e<d;e++)c[e]=a[e];for(e=d;e<a.length;e++)c[e]=b[e-d]^a[e];return new G(this.field,c)}multiply(a){if(0===a)return this.field.zero;if(1===a)return this;let b=this.coefficients.length,c=new Uint8ClampedArray(b);for(let d=0;d<b;d++)c[d]=this.field.multiply(this.coefficients[d],a);return new G(this.field,c)}multiplyPoly(a){if(this.isZero()||
|
||||
a.isZero())return this.field.zero;let b=this.coefficients,c=b.length;a=a.coefficients;let d=a.length,e=new Uint8ClampedArray(c+d-1);for(let f=0;f<c;f++){let g=b[f];for(let h=0;h<d;h++)e[f+h]=H(e[f+h],this.field.multiply(g,a[h]))}return new G(this.field,e)}multiplyByMonomial(a,b){if(0>a)throw Error("Invalid degree less than 0");if(0===b)return this.field.zero;let c=this.coefficients.length;a=new Uint8ClampedArray(c+a);for(let d=0;d<c;d++)a[d]=this.field.multiply(this.coefficients[d],b);return new G(this.field,
|
||||
a)}evaluateAt(a){let b=0;if(0===a)return this.getCoefficient(0);let c=this.coefficients.length;if(1===a)return this.coefficients.forEach(d=>{b^=d}),b;b=this.coefficients[0];for(let d=1;d<c;d++)b=H(this.field.multiply(a,b),this.coefficients[d]);return b}}function H(a,b){return a^b}
|
||||
class ea{constructor(a,b,c){this.primitive=a;this.size=b;this.generatorBase=c;this.expTable=Array(this.size);this.logTable=Array(this.size);a=1;for(b=0;b<this.size;b++)this.expTable[b]=a,a*=2,a>=this.size&&(a=(a^this.primitive)&this.size-1);for(a=0;a<this.size-1;a++)this.logTable[this.expTable[a]]=a;this.zero=new G(this,Uint8ClampedArray.from([0]));this.one=new G(this,Uint8ClampedArray.from([1]))}multiply(a,b){return 0===a||0===b?0:this.expTable[(this.logTable[a]+this.logTable[b])%(this.size-1)]}inverse(a){if(0===
|
||||
a)throw Error("Can't invert 0");return this.expTable[this.size-this.logTable[a]-1]}buildMonomial(a,b){if(0>a)throw Error("Invalid monomial degree less than 0");if(0===b)return this.zero;a=new Uint8ClampedArray(a+1);a[0]=b;return new G(this,a)}log(a){if(0===a)throw Error("Can't take log(0)");return this.logTable[a]}exp(a){return this.expTable[a]}}
|
||||
function fa(a,b,c,d){b.degree()<c.degree()&&([b,c]=[c,b]);let e=a.zero;for(var f=a.one;c.degree()>=d/2;){var g=b;let h=e;b=c;e=f;if(b.isZero())return null;c=g;f=a.zero;g=b.getCoefficient(b.degree());for(g=a.inverse(g);c.degree()>=b.degree()&&!c.isZero();){let k=c.degree()-b.degree(),m=a.multiply(c.getCoefficient(c.degree()),g);f=f.addOrSubtract(a.buildMonomial(k,m));c=c.addOrSubtract(b.multiplyByMonomial(k,m))}f=f.multiplyPoly(e).addOrSubtract(h);if(c.degree()>=b.degree())return null}d=f.getCoefficient(0);
|
||||
if(0===d)return null;a=a.inverse(d);return[f.multiply(a),c.multiply(a)]}
|
||||
function ha(a,b){let c=new Uint8ClampedArray(a.length);c.set(a);a=new ea(285,256,0);var d=new G(a,c),e=new Uint8ClampedArray(b),f=!1;for(var g=0;g<b;g++){var h=d.evaluateAt(a.exp(g+a.generatorBase));e[e.length-1-g]=h;0!==h&&(f=!0)}if(!f)return c;d=new G(a,e);d=fa(a,a.buildMonomial(b,1),d,b);if(null===d)return null;b=d[0];g=b.degree();if(1===g)b=[b.getCoefficient(1)];else{e=Array(g);f=0;for(h=1;h<a.size&&f<g;h++)0===b.evaluateAt(h)&&(e[f]=a.inverse(h),f++);b=f!==g?null:e}if(null==b)return null;e=d[1];
|
||||
f=b.length;d=Array(f);for(g=0;g<f;g++){h=a.inverse(b[g]);let k=1;for(let m=0;m<f;m++)g!==m&&(k=a.multiply(k,H(1,a.multiply(b[m],h))));d[g]=a.multiply(e.evaluateAt(h),a.inverse(k));0!==a.generatorBase&&(d[g]=a.multiply(d[g],h))}for(e=0;e<b.length;e++){f=c.length-1-a.log(b[e]);if(0>f)return null;c[f]^=d[e]}return c}
|
||||
let I=[{infoBits:null,versionNumber:1,alignmentPatternCenters:[],errorCorrectionLevels:[{ecCodewordsPerBlock:7,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:19}]},{ecCodewordsPerBlock:10,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:16}]},{ecCodewordsPerBlock:13,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:13}]},{ecCodewordsPerBlock:17,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:9}]}]},{infoBits:null,versionNumber:2,alignmentPatternCenters:[6,18],errorCorrectionLevels:[{ecCodewordsPerBlock:10,ecBlocks:[{numBlocks:1,
|
||||
dataCodewordsPerBlock:34}]},{ecCodewordsPerBlock:16,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:28}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:22}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:16}]}]},{infoBits:null,versionNumber:3,alignmentPatternCenters:[6,22],errorCorrectionLevels:[{ecCodewordsPerBlock:15,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:55}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:44}]},{ecCodewordsPerBlock:18,
|
||||
ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:17}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:13}]}]},{infoBits:null,versionNumber:4,alignmentPatternCenters:[6,26],errorCorrectionLevels:[{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:80}]},{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:32}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:24}]},{ecCodewordsPerBlock:16,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:9}]}]},
|
||||
{infoBits:null,versionNumber:5,alignmentPatternCenters:[6,30],errorCorrectionLevels:[{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:108}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:43}]},{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:15},{numBlocks:2,dataCodewordsPerBlock:16}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:11},{numBlocks:2,dataCodewordsPerBlock:12}]}]},{infoBits:null,versionNumber:6,alignmentPatternCenters:[6,
|
||||
34],errorCorrectionLevels:[{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:68}]},{ecCodewordsPerBlock:16,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:27}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:19}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:15}]}]},{infoBits:31892,versionNumber:7,alignmentPatternCenters:[6,22,38],errorCorrectionLevels:[{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:78}]},{ecCodewordsPerBlock:18,
|
||||
ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:31}]},{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:14},{numBlocks:4,dataCodewordsPerBlock:15}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:13},{numBlocks:1,dataCodewordsPerBlock:14}]}]},{infoBits:34236,versionNumber:8,alignmentPatternCenters:[6,24,42],errorCorrectionLevels:[{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:97}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:38},
|
||||
{numBlocks:2,dataCodewordsPerBlock:39}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:18},{numBlocks:2,dataCodewordsPerBlock:19}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:14},{numBlocks:2,dataCodewordsPerBlock:15}]}]},{infoBits:39577,versionNumber:9,alignmentPatternCenters:[6,26,46],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:36},
|
||||
{numBlocks:2,dataCodewordsPerBlock:37}]},{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:16},{numBlocks:4,dataCodewordsPerBlock:17}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:12},{numBlocks:4,dataCodewordsPerBlock:13}]}]},{infoBits:42195,versionNumber:10,alignmentPatternCenters:[6,28,50],errorCorrectionLevels:[{ecCodewordsPerBlock:18,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:68},{numBlocks:2,dataCodewordsPerBlock:69}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4,
|
||||
dataCodewordsPerBlock:43},{numBlocks:1,dataCodewordsPerBlock:44}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:19},{numBlocks:2,dataCodewordsPerBlock:20}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:15},{numBlocks:2,dataCodewordsPerBlock:16}]}]},{infoBits:48118,versionNumber:11,alignmentPatternCenters:[6,30,54],errorCorrectionLevels:[{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:81}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:1,
|
||||
dataCodewordsPerBlock:50},{numBlocks:4,dataCodewordsPerBlock:51}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:22},{numBlocks:4,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:12},{numBlocks:8,dataCodewordsPerBlock:13}]}]},{infoBits:51042,versionNumber:12,alignmentPatternCenters:[6,32,58],errorCorrectionLevels:[{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:92},{numBlocks:2,dataCodewordsPerBlock:93}]},
|
||||
{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:36},{numBlocks:2,dataCodewordsPerBlock:37}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:20},{numBlocks:6,dataCodewordsPerBlock:21}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:14},{numBlocks:4,dataCodewordsPerBlock:15}]}]},{infoBits:55367,versionNumber:13,alignmentPatternCenters:[6,34,62],errorCorrectionLevels:[{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:107}]},
|
||||
{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:37},{numBlocks:1,dataCodewordsPerBlock:38}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:20},{numBlocks:4,dataCodewordsPerBlock:21}]},{ecCodewordsPerBlock:22,ecBlocks:[{numBlocks:12,dataCodewordsPerBlock:11},{numBlocks:4,dataCodewordsPerBlock:12}]}]},{infoBits:58893,versionNumber:14,alignmentPatternCenters:[6,26,46,66],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:115},
|
||||
{numBlocks:1,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:40},{numBlocks:5,dataCodewordsPerBlock:41}]},{ecCodewordsPerBlock:20,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:16},{numBlocks:5,dataCodewordsPerBlock:17}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:12},{numBlocks:5,dataCodewordsPerBlock:13}]}]},{infoBits:63784,versionNumber:15,alignmentPatternCenters:[6,26,48,70],errorCorrectionLevels:[{ecCodewordsPerBlock:22,
|
||||
ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:87},{numBlocks:1,dataCodewordsPerBlock:88}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:41},{numBlocks:5,dataCodewordsPerBlock:42}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:24},{numBlocks:7,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:12},{numBlocks:7,dataCodewordsPerBlock:13}]}]},{infoBits:68472,versionNumber:16,alignmentPatternCenters:[6,26,50,
|
||||
74],errorCorrectionLevels:[{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:98},{numBlocks:1,dataCodewordsPerBlock:99}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:45},{numBlocks:3,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:15,dataCodewordsPerBlock:19},{numBlocks:2,dataCodewordsPerBlock:20}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:15},{numBlocks:13,dataCodewordsPerBlock:16}]}]},{infoBits:70749,
|
||||
versionNumber:17,alignmentPatternCenters:[6,30,54,78],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:107},{numBlocks:5,dataCodewordsPerBlock:108}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:46},{numBlocks:1,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:22},{numBlocks:15,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:14},{numBlocks:17,
|
||||
dataCodewordsPerBlock:15}]}]},{infoBits:76311,versionNumber:18,alignmentPatternCenters:[6,30,56,82],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:120},{numBlocks:1,dataCodewordsPerBlock:121}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:9,dataCodewordsPerBlock:43},{numBlocks:4,dataCodewordsPerBlock:44}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:22},{numBlocks:1,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:2,
|
||||
dataCodewordsPerBlock:14},{numBlocks:19,dataCodewordsPerBlock:15}]}]},{infoBits:79154,versionNumber:19,alignmentPatternCenters:[6,30,58,86],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:113},{numBlocks:4,dataCodewordsPerBlock:114}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:44},{numBlocks:11,dataCodewordsPerBlock:45}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:21},{numBlocks:4,dataCodewordsPerBlock:22}]},
|
||||
{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:9,dataCodewordsPerBlock:13},{numBlocks:16,dataCodewordsPerBlock:14}]}]},{infoBits:84390,versionNumber:20,alignmentPatternCenters:[6,34,62,90],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:107},{numBlocks:5,dataCodewordsPerBlock:108}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:41},{numBlocks:13,dataCodewordsPerBlock:42}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:15,dataCodewordsPerBlock:24},
|
||||
{numBlocks:5,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:15,dataCodewordsPerBlock:15},{numBlocks:10,dataCodewordsPerBlock:16}]}]},{infoBits:87683,versionNumber:21,alignmentPatternCenters:[6,28,50,72,94],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:116},{numBlocks:4,dataCodewordsPerBlock:117}]},{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:42}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:22},
|
||||
{numBlocks:6,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:19,dataCodewordsPerBlock:16},{numBlocks:6,dataCodewordsPerBlock:17}]}]},{infoBits:92361,versionNumber:22,alignmentPatternCenters:[6,26,50,74,98],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:111},{numBlocks:7,dataCodewordsPerBlock:112}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:24},
|
||||
{numBlocks:16,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:24,ecBlocks:[{numBlocks:34,dataCodewordsPerBlock:13}]}]},{infoBits:96236,versionNumber:23,alignmentPatternCenters:[6,30,54,74,102],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:121},{numBlocks:5,dataCodewordsPerBlock:122}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:47},{numBlocks:14,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:24},
|
||||
{numBlocks:14,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:16,dataCodewordsPerBlock:15},{numBlocks:14,dataCodewordsPerBlock:16}]}]},{infoBits:102084,versionNumber:24,alignmentPatternCenters:[6,28,54,80,106],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:117},{numBlocks:4,dataCodewordsPerBlock:118}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:45},{numBlocks:14,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30,
|
||||
ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:24},{numBlocks:16,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:30,dataCodewordsPerBlock:16},{numBlocks:2,dataCodewordsPerBlock:17}]}]},{infoBits:102881,versionNumber:25,alignmentPatternCenters:[6,32,58,84,110],errorCorrectionLevels:[{ecCodewordsPerBlock:26,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:106},{numBlocks:4,dataCodewordsPerBlock:107}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:47},{numBlocks:13,
|
||||
dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:24},{numBlocks:22,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:22,dataCodewordsPerBlock:15},{numBlocks:13,dataCodewordsPerBlock:16}]}]},{infoBits:110507,versionNumber:26,alignmentPatternCenters:[6,30,58,86,114],errorCorrectionLevels:[{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:114},{numBlocks:2,dataCodewordsPerBlock:115}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:19,
|
||||
dataCodewordsPerBlock:46},{numBlocks:4,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:28,dataCodewordsPerBlock:22},{numBlocks:6,dataCodewordsPerBlock:23}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:33,dataCodewordsPerBlock:16},{numBlocks:4,dataCodewordsPerBlock:17}]}]},{infoBits:110734,versionNumber:27,alignmentPatternCenters:[6,34,62,90,118],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:122},{numBlocks:4,dataCodewordsPerBlock:123}]},
|
||||
{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:22,dataCodewordsPerBlock:45},{numBlocks:3,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:8,dataCodewordsPerBlock:23},{numBlocks:26,dataCodewordsPerBlock:24}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:12,dataCodewordsPerBlock:15},{numBlocks:28,dataCodewordsPerBlock:16}]}]},{infoBits:117786,versionNumber:28,alignmentPatternCenters:[6,26,50,74,98,122],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:117},
|
||||
{numBlocks:10,dataCodewordsPerBlock:118}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:3,dataCodewordsPerBlock:45},{numBlocks:23,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:4,dataCodewordsPerBlock:24},{numBlocks:31,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:15},{numBlocks:31,dataCodewordsPerBlock:16}]}]},{infoBits:119615,versionNumber:29,alignmentPatternCenters:[6,30,54,78,102,126],errorCorrectionLevels:[{ecCodewordsPerBlock:30,
|
||||
ecBlocks:[{numBlocks:7,dataCodewordsPerBlock:116},{numBlocks:7,dataCodewordsPerBlock:117}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:21,dataCodewordsPerBlock:45},{numBlocks:7,dataCodewordsPerBlock:46}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:1,dataCodewordsPerBlock:23},{numBlocks:37,dataCodewordsPerBlock:24}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:19,dataCodewordsPerBlock:15},{numBlocks:26,dataCodewordsPerBlock:16}]}]},{infoBits:126325,versionNumber:30,alignmentPatternCenters:[6,
|
||||
26,52,78,104,130],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:5,dataCodewordsPerBlock:115},{numBlocks:10,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:19,dataCodewordsPerBlock:47},{numBlocks:10,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:15,dataCodewordsPerBlock:24},{numBlocks:25,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:23,dataCodewordsPerBlock:15},{numBlocks:25,dataCodewordsPerBlock:16}]}]},
|
||||
{infoBits:127568,versionNumber:31,alignmentPatternCenters:[6,30,56,82,108,134],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:13,dataCodewordsPerBlock:115},{numBlocks:3,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:46},{numBlocks:29,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:42,dataCodewordsPerBlock:24},{numBlocks:1,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:23,dataCodewordsPerBlock:15},
|
||||
{numBlocks:28,dataCodewordsPerBlock:16}]}]},{infoBits:133589,versionNumber:32,alignmentPatternCenters:[6,34,60,86,112,138],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:115}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:46},{numBlocks:23,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:24},{numBlocks:35,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:19,
|
||||
dataCodewordsPerBlock:15},{numBlocks:35,dataCodewordsPerBlock:16}]}]},{infoBits:136944,versionNumber:33,alignmentPatternCenters:[6,30,58,86,114,142],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:115},{numBlocks:1,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:14,dataCodewordsPerBlock:46},{numBlocks:21,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:29,dataCodewordsPerBlock:24},{numBlocks:19,dataCodewordsPerBlock:25}]},
|
||||
{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:11,dataCodewordsPerBlock:15},{numBlocks:46,dataCodewordsPerBlock:16}]}]},{infoBits:141498,versionNumber:34,alignmentPatternCenters:[6,34,62,90,118,146],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:13,dataCodewordsPerBlock:115},{numBlocks:6,dataCodewordsPerBlock:116}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:14,dataCodewordsPerBlock:46},{numBlocks:23,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:44,
|
||||
dataCodewordsPerBlock:24},{numBlocks:7,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:59,dataCodewordsPerBlock:16},{numBlocks:1,dataCodewordsPerBlock:17}]}]},{infoBits:145311,versionNumber:35,alignmentPatternCenters:[6,30,54,78,102,126,150],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:12,dataCodewordsPerBlock:121},{numBlocks:7,dataCodewordsPerBlock:122}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:12,dataCodewordsPerBlock:47},{numBlocks:26,dataCodewordsPerBlock:48}]},
|
||||
{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:39,dataCodewordsPerBlock:24},{numBlocks:14,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:22,dataCodewordsPerBlock:15},{numBlocks:41,dataCodewordsPerBlock:16}]}]},{infoBits:150283,versionNumber:36,alignmentPatternCenters:[6,24,50,76,102,128,154],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:6,dataCodewordsPerBlock:121},{numBlocks:14,dataCodewordsPerBlock:122}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:6,
|
||||
dataCodewordsPerBlock:47},{numBlocks:34,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:46,dataCodewordsPerBlock:24},{numBlocks:10,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:2,dataCodewordsPerBlock:15},{numBlocks:64,dataCodewordsPerBlock:16}]}]},{infoBits:152622,versionNumber:37,alignmentPatternCenters:[6,28,54,80,106,132,158],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:17,dataCodewordsPerBlock:122},{numBlocks:4,dataCodewordsPerBlock:123}]},
|
||||
{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:29,dataCodewordsPerBlock:46},{numBlocks:14,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:49,dataCodewordsPerBlock:24},{numBlocks:10,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:24,dataCodewordsPerBlock:15},{numBlocks:46,dataCodewordsPerBlock:16}]}]},{infoBits:158308,versionNumber:38,alignmentPatternCenters:[6,32,58,84,110,136,162],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:4,
|
||||
dataCodewordsPerBlock:122},{numBlocks:18,dataCodewordsPerBlock:123}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:13,dataCodewordsPerBlock:46},{numBlocks:32,dataCodewordsPerBlock:47}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:48,dataCodewordsPerBlock:24},{numBlocks:14,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:42,dataCodewordsPerBlock:15},{numBlocks:32,dataCodewordsPerBlock:16}]}]},{infoBits:161089,versionNumber:39,alignmentPatternCenters:[6,26,54,82,110,138,166],
|
||||
errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:20,dataCodewordsPerBlock:117},{numBlocks:4,dataCodewordsPerBlock:118}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:40,dataCodewordsPerBlock:47},{numBlocks:7,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:43,dataCodewordsPerBlock:24},{numBlocks:22,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:10,dataCodewordsPerBlock:15},{numBlocks:67,dataCodewordsPerBlock:16}]}]},{infoBits:167017,
|
||||
versionNumber:40,alignmentPatternCenters:[6,30,58,86,114,142,170],errorCorrectionLevels:[{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:19,dataCodewordsPerBlock:118},{numBlocks:6,dataCodewordsPerBlock:119}]},{ecCodewordsPerBlock:28,ecBlocks:[{numBlocks:18,dataCodewordsPerBlock:47},{numBlocks:31,dataCodewordsPerBlock:48}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:34,dataCodewordsPerBlock:24},{numBlocks:34,dataCodewordsPerBlock:25}]},{ecCodewordsPerBlock:30,ecBlocks:[{numBlocks:20,dataCodewordsPerBlock:15},
|
||||
{numBlocks:61,dataCodewordsPerBlock:16}]}]}];function J(a,b){a^=b;for(b=0;a;)b++,a&=a-1;return b}function K(a,b){return b<<1|a}
|
||||
let ia=[{bits:21522,formatInfo:{errorCorrectionLevel:1,dataMask:0}},{bits:20773,formatInfo:{errorCorrectionLevel:1,dataMask:1}},{bits:24188,formatInfo:{errorCorrectionLevel:1,dataMask:2}},{bits:23371,formatInfo:{errorCorrectionLevel:1,dataMask:3}},{bits:17913,formatInfo:{errorCorrectionLevel:1,dataMask:4}},{bits:16590,formatInfo:{errorCorrectionLevel:1,dataMask:5}},{bits:20375,formatInfo:{errorCorrectionLevel:1,dataMask:6}},{bits:19104,formatInfo:{errorCorrectionLevel:1,dataMask:7}},{bits:30660,formatInfo:{errorCorrectionLevel:0,
|
||||
dataMask:0}},{bits:29427,formatInfo:{errorCorrectionLevel:0,dataMask:1}},{bits:32170,formatInfo:{errorCorrectionLevel:0,dataMask:2}},{bits:30877,formatInfo:{errorCorrectionLevel:0,dataMask:3}},{bits:26159,formatInfo:{errorCorrectionLevel:0,dataMask:4}},{bits:25368,formatInfo:{errorCorrectionLevel:0,dataMask:5}},{bits:27713,formatInfo:{errorCorrectionLevel:0,dataMask:6}},{bits:26998,formatInfo:{errorCorrectionLevel:0,dataMask:7}},{bits:5769,formatInfo:{errorCorrectionLevel:3,dataMask:0}},{bits:5054,
|
||||
formatInfo:{errorCorrectionLevel:3,dataMask:1}},{bits:7399,formatInfo:{errorCorrectionLevel:3,dataMask:2}},{bits:6608,formatInfo:{errorCorrectionLevel:3,dataMask:3}},{bits:1890,formatInfo:{errorCorrectionLevel:3,dataMask:4}},{bits:597,formatInfo:{errorCorrectionLevel:3,dataMask:5}},{bits:3340,formatInfo:{errorCorrectionLevel:3,dataMask:6}},{bits:2107,formatInfo:{errorCorrectionLevel:3,dataMask:7}},{bits:13663,formatInfo:{errorCorrectionLevel:2,dataMask:0}},{bits:12392,formatInfo:{errorCorrectionLevel:2,
|
||||
dataMask:1}},{bits:16177,formatInfo:{errorCorrectionLevel:2,dataMask:2}},{bits:14854,formatInfo:{errorCorrectionLevel:2,dataMask:3}},{bits:9396,formatInfo:{errorCorrectionLevel:2,dataMask:4}},{bits:8579,formatInfo:{errorCorrectionLevel:2,dataMask:5}},{bits:11994,formatInfo:{errorCorrectionLevel:2,dataMask:6}},{bits:11245,formatInfo:{errorCorrectionLevel:2,dataMask:7}}],ja=[a=>0===(a.y+a.x)%2,a=>0===a.y%2,a=>0===a.x%3,a=>0===(a.y+a.x)%3,a=>0===(Math.floor(a.y/2)+Math.floor(a.x/3))%2,a=>0===a.x*a.y%
|
||||
2+a.x*a.y%3,a=>0===(a.y*a.x%2+a.y*a.x%3)%2,a=>0===((a.y+a.x)%2+a.y*a.x%3)%2];
|
||||
function ka(a,b,c){c=ja[c.dataMask];let d=a.height;var e=17+4*b.versionNumber;let f=x.createEmpty(e,e);f.setRegion(0,0,9,9,!0);f.setRegion(e-8,0,8,9,!0);f.setRegion(0,e-8,9,8,!0);for(var g of b.alignmentPatternCenters)for(var h of b.alignmentPatternCenters)6===g&&6===h||6===g&&h===e-7||g===e-7&&6===h||f.setRegion(g-2,h-2,5,5,!0);f.setRegion(6,9,1,e-17,!0);f.setRegion(9,6,e-17,1,!0);6<b.versionNumber&&(f.setRegion(e-11,0,3,6,!0),f.setRegion(0,e-11,6,3,!0));b=[];h=g=0;e=!0;for(let k=d-1;0<k;k-=2){6===
|
||||
k&&k--;for(let m=0;m<d;m++){let l=e?d-1-m:m;for(let n=0;2>n;n++){let q=k-n;if(!f.get(q,l)){h++;let r=a.get(q,l);c({y:l,x:q})&&(r=!r);g=g<<1|r;8===h&&(b.push(g),g=h=0)}}}e=!e}return b}
|
||||
function la(a){var b=a.height,c=Math.floor((b-17)/4);if(6>=c)return I[c-1];c=0;for(var d=5;0<=d;d--)for(var e=b-9;e>=b-11;e--)c=K(a.get(e,d),c);d=0;for(e=5;0<=e;e--)for(let g=b-9;g>=b-11;g--)d=K(a.get(e,g),d);a=Infinity;let f;for(let g of I){if(g.infoBits===c||g.infoBits===d)return g;b=J(c,g.infoBits);b<a&&(f=g,a=b);b=J(d,g.infoBits);b<a&&(f=g,a=b)}if(3>=a)return f}
|
||||
function ma(a){let b=0;for(var c=0;8>=c;c++)6!==c&&(b=K(a.get(c,8),b));for(c=7;0<=c;c--)6!==c&&(b=K(a.get(8,c),b));var d=a.height;c=0;for(var e=d-1;e>=d-7;e--)c=K(a.get(8,e),c);for(e=d-8;e<d;e++)c=K(a.get(e,8),c);a=Infinity;d=null;for(let {bits:f,formatInfo:g}of ia){if(f===b||f===c)return g;e=J(b,f);e<a&&(d=g,a=e);b!==c&&(e=J(c,f),e<a&&(d=g,a=e))}return 3>=a?d:null}
|
||||
function na(a,b,c){let d=b.errorCorrectionLevels[c],e=[],f=0;d.ecBlocks.forEach(h=>{for(let k=0;k<h.numBlocks;k++)e.push({numDataCodewords:h.dataCodewordsPerBlock,codewords:[]}),f+=h.dataCodewordsPerBlock+d.ecCodewordsPerBlock});if(a.length<f)return null;a=a.slice(0,f);b=d.ecBlocks[0].dataCodewordsPerBlock;for(c=0;c<b;c++)for(var g of e)g.codewords.push(a.shift());if(1<d.ecBlocks.length)for(g=d.ecBlocks[0].numBlocks,b=d.ecBlocks[1].numBlocks,c=0;c<b;c++)e[g+c].codewords.push(a.shift());for(;0<a.length;)for(let h of e)h.codewords.push(a.shift());
|
||||
return e}function L(a){let b=la(a);if(!b)return null;var c=ma(a);if(!c)return null;a=ka(a,b,c);var d=na(a,b,c.errorCorrectionLevel);if(!d)return null;c=d.reduce((e,f)=>e+f.numDataCodewords,0);c=new Uint8ClampedArray(c);a=0;for(let e of d){d=ha(e.codewords,e.codewords.length-e.numDataCodewords);if(!d)return null;for(let f=0;f<e.numDataCodewords;f++)c[a++]=d[f]}try{return da(c,b.versionNumber)}catch(e){return null}}
|
||||
function M(a,b,c,d){var e=a.x-b.x+c.x-d.x;let f=a.y-b.y+c.y-d.y;if(0===e&&0===f)return{a11:b.x-a.x,a12:b.y-a.y,a13:0,a21:c.x-b.x,a22:c.y-b.y,a23:0,a31:a.x,a32:a.y,a33:1};let g=b.x-c.x;var h=d.x-c.x;let k=b.y-c.y,m=d.y-c.y;c=g*m-h*k;h=(e*m-h*f)/c;e=(g*f-e*k)/c;return{a11:b.x-a.x+h*b.x,a12:b.y-a.y+h*b.y,a13:h,a21:d.x-a.x+e*d.x,a22:d.y-a.y+e*d.y,a23:e,a31:a.x,a32:a.y,a33:1}}
|
||||
function oa(a,b,c,d){a=M(a,b,c,d);return{a11:a.a22*a.a33-a.a23*a.a32,a12:a.a13*a.a32-a.a12*a.a33,a13:a.a12*a.a23-a.a13*a.a22,a21:a.a23*a.a31-a.a21*a.a33,a22:a.a11*a.a33-a.a13*a.a31,a23:a.a13*a.a21-a.a11*a.a23,a31:a.a21*a.a32-a.a22*a.a31,a32:a.a12*a.a31-a.a11*a.a32,a33:a.a11*a.a22-a.a12*a.a21}}
|
||||
function pa(a,b){var c=oa({x:3.5,y:3.5},{x:b.dimension-3.5,y:3.5},{x:b.dimension-6.5,y:b.dimension-6.5},{x:3.5,y:b.dimension-3.5}),d=M(b.topLeft,b.topRight,b.alignmentPattern,b.bottomLeft),e=d.a11*c.a11+d.a21*c.a12+d.a31*c.a13,f=d.a12*c.a11+d.a22*c.a12+d.a32*c.a13,g=d.a13*c.a11+d.a23*c.a12+d.a33*c.a13,h=d.a11*c.a21+d.a21*c.a22+d.a31*c.a23,k=d.a12*c.a21+d.a22*c.a22+d.a32*c.a23,m=d.a13*c.a21+d.a23*c.a22+d.a33*c.a23,l=d.a11*c.a31+d.a21*c.a32+d.a31*c.a33,n=d.a12*c.a31+d.a22*c.a32+d.a32*c.a33,q=d.a13*
|
||||
c.a31+d.a23*c.a32+d.a33*c.a33;c=x.createEmpty(b.dimension,b.dimension);d=(r,u)=>{const p=g*r+m*u+q;return{x:(e*r+h*u+l)/p,y:(f*r+k*u+n)/p}};for(let r=0;r<b.dimension;r++)for(let u=0;u<b.dimension;u++){let p=d(u+.5,r+.5);c.set(u,r,a.get(Math.floor(p.x),Math.floor(p.y)))}return{matrix:c,mappingFunction:d}}let N=(a,b)=>Math.sqrt(Math.pow(b.x-a.x,2)+Math.pow(b.y-a.y,2));function O(a){return a.reduce((b,c)=>b+c)}
|
||||
function qa(a,b,c){let d=N(a,b),e=N(b,c),f=N(a,c),g,h,k;e>=d&&e>=f?[g,h,k]=[b,a,c]:f>=e&&f>=d?[g,h,k]=[a,b,c]:[g,h,k]=[a,c,b];0>(k.x-h.x)*(g.y-h.y)-(k.y-h.y)*(g.x-h.x)&&([g,k]=[k,g]);return{bottomLeft:g,topLeft:h,topRight:k}}
|
||||
function ra(a,b,c,d){d=(O(P(a,c,d,5))/7+O(P(a,b,d,5))/7+O(P(c,a,d,5))/7+O(P(b,a,d,5))/7)/4;if(1>d)throw Error("Invalid module size");b=Math.round(N(a,b)/d);a=Math.round(N(a,c)/d);a=Math.floor((b+a)/2)+7;switch(a%4){case 0:a++;break;case 2:a--}return{dimension:a,moduleSize:d}}
|
||||
function Q(a,b,c,d){let e=[{x:Math.floor(a.x),y:Math.floor(a.y)}];var f=Math.abs(b.y-a.y)>Math.abs(b.x-a.x);if(f){var g=Math.floor(a.y);var h=Math.floor(a.x);a=Math.floor(b.y);b=Math.floor(b.x)}else g=Math.floor(a.x),h=Math.floor(a.y),a=Math.floor(b.x),b=Math.floor(b.y);let k=Math.abs(a-g),m=Math.abs(b-h),l=Math.floor(-k/2),n=g<a?1:-1,q=h<b?1:-1,r=!0;for(let u=g,p=h;u!==a+n;u+=n){g=f?p:u;h=f?u:p;if(c.get(g,h)!==r&&(r=!r,e.push({x:g,y:h}),e.length===d+1))break;l+=m;if(0<l){if(p===b)break;p+=q;l-=k}}c=
|
||||
[];for(f=0;f<d;f++)e[f]&&e[f+1]?c.push(N(e[f],e[f+1])):c.push(0);return c}function P(a,b,c,d){let e=b.y-a.y,f=b.x-a.x;b=Q(a,b,c,Math.ceil(d/2));a=Q(a,{x:a.x-f,y:a.y-e},c,Math.ceil(d/2));c=b.shift()+a.shift()-1;return a.concat(c).concat(...b)}function R(a,b){let c=O(a)/O(b),d=0;b.forEach((e,f)=>{d+=Math.pow(a[f]-e*c,2)});return{averageSize:c,error:d}}
|
||||
function S(a,b,c){try{let d=P(a,{x:-1,y:a.y},c,b.length),e=P(a,{x:a.x,y:-1},c,b.length),f=P(a,{x:Math.max(0,a.x-a.y)-1,y:Math.max(0,a.y-a.x)-1},c,b.length),g=P(a,{x:Math.min(c.width,a.x+a.y)+1,y:Math.min(c.height,a.y+a.x)+1},c,b.length),h=R(d,b),k=R(e,b),m=R(f,b),l=R(g,b),n=(h.averageSize+k.averageSize+m.averageSize+l.averageSize)/4;return Math.sqrt(h.error*h.error+k.error*k.error+m.error*m.error+l.error*l.error)+(Math.pow(h.averageSize-n,2)+Math.pow(k.averageSize-n,2)+Math.pow(m.averageSize-n,2)+
|
||||
Math.pow(l.averageSize-n,2))/n}catch(d){return Infinity}}function T(a,b){for(var c=Math.round(b.x);a.get(c,Math.round(b.y));)c--;for(var d=Math.round(b.x);a.get(d,Math.round(b.y));)d++;c=(c+d)/2;for(d=Math.round(b.y);a.get(Math.round(c),d);)d--;for(b=Math.round(b.y);a.get(Math.round(c),b);)b++;return{x:c,y:(d+b)/2}}
|
||||
function sa(a){var b=[],c=[];let d=[];var e=[];for(let p=0;p<=a.height;p++){var f=0,g=!1;let t=[0,0,0,0,0];for(let v=-1;v<=a.width;v++){var h=a.get(v,p);if(h===g)f++;else{t=[t[1],t[2],t[3],t[4],f];f=1;g=h;var k=O(t)/7;k=Math.abs(t[0]-k)<k&&Math.abs(t[1]-k)<k&&Math.abs(t[2]-3*k)<3*k&&Math.abs(t[3]-k)<k&&Math.abs(t[4]-k)<k&&!h;var m=O(t.slice(-3))/3;h=Math.abs(t[2]-m)<m&&Math.abs(t[3]-m)<m&&Math.abs(t[4]-m)<m&&h;if(k){let z=v-t[3]-t[4],y=z-t[2];k={startX:y,endX:z,y:p};m=c.filter(w=>y>=w.bottom.startX&&
|
||||
y<=w.bottom.endX||z>=w.bottom.startX&&y<=w.bottom.endX||y<=w.bottom.startX&&z>=w.bottom.endX&&1.5>t[2]/(w.bottom.endX-w.bottom.startX)&&.5<t[2]/(w.bottom.endX-w.bottom.startX));0<m.length?m[0].bottom=k:c.push({top:k,bottom:k})}if(h){let z=v-t[4],y=z-t[3];h={startX:y,y:p,endX:z};k=e.filter(w=>y>=w.bottom.startX&&y<=w.bottom.endX||z>=w.bottom.startX&&y<=w.bottom.endX||y<=w.bottom.startX&&z>=w.bottom.endX&&1.5>t[2]/(w.bottom.endX-w.bottom.startX)&&.5<t[2]/(w.bottom.endX-w.bottom.startX));0<k.length?
|
||||
k[0].bottom=h:e.push({top:h,bottom:h})}}}b.push(...c.filter(v=>v.bottom.y!==p&&2<=v.bottom.y-v.top.y));c=c.filter(v=>v.bottom.y===p);d.push(...e.filter(v=>v.bottom.y!==p));e=e.filter(v=>v.bottom.y===p)}b.push(...c.filter(p=>2<=p.bottom.y-p.top.y));d.push(...e);c=[];for(var l of b)2>l.bottom.y-l.top.y||(b=(l.top.startX+l.top.endX+l.bottom.startX+l.bottom.endX)/4,e=(l.top.y+l.bottom.y+1)/2,a.get(Math.round(b),Math.round(e))&&(f=[l.top.endX-l.top.startX,l.bottom.endX-l.bottom.startX,l.bottom.y-l.top.y+
|
||||
1],f=O(f)/f.length,g=S({x:Math.round(b),y:Math.round(e)},[1,1,3,1,1],a),c.push({score:g,x:b,y:e,size:f})));if(3>c.length)return null;c.sort((p,t)=>p.score-t.score);l=[];for(b=0;b<Math.min(c.length,5);++b){e=c[b];f=[];for(var n of c)n!==e&&f.push(Object.assign(Object.assign({},n),{score:n.score+Math.pow(n.size-e.size,2)/e.size}));f.sort((p,t)=>p.score-t.score);l.push({points:[e,f[0],f[1]],score:e.score+f[0].score+f[1].score})}l.sort((p,t)=>p.score-t.score);let {topRight:q,topLeft:r,bottomLeft:u}=qa(...l[0].points);
|
||||
l=U(a,d,q,r,u);n=[];l&&n.push({alignmentPattern:{x:l.alignmentPattern.x,y:l.alignmentPattern.y},bottomLeft:{x:u.x,y:u.y},dimension:l.dimension,topLeft:{x:r.x,y:r.y},topRight:{x:q.x,y:q.y}});l=T(a,q);b=T(a,r);c=T(a,u);(a=U(a,d,l,b,c))&&n.push({alignmentPattern:{x:a.alignmentPattern.x,y:a.alignmentPattern.y},bottomLeft:{x:c.x,y:c.y},topLeft:{x:b.x,y:b.y},topRight:{x:l.x,y:l.y},dimension:a.dimension});return 0===n.length?null:n}
|
||||
function U(a,b,c,d,e){let f,g;try{({dimension:f,moduleSize:g}=ra(d,c,e,a))}catch(l){return null}var h=c.x-d.x+e.x,k=c.y-d.y+e.y;c=(N(d,e)+N(d,c))/2/g;e=1-3/c;let m={x:d.x+e*(h-d.x),y:d.y+e*(k-d.y)};b=b.map(l=>{const n=(l.top.startX+l.top.endX+l.bottom.startX+l.bottom.endX)/4;l=(l.top.y+l.bottom.y+1)/2;if(a.get(Math.floor(n),Math.floor(l))){var q=S({x:Math.floor(n),y:Math.floor(l)},[1,1,1],a)+N({x:n,y:l},m);return{x:n,y:l,score:q}}}).filter(l=>!!l).sort((l,n)=>l.score-n.score);return{alignmentPattern:15<=
|
||||
c&&b.length?b[0]:m,dimension:f}}
|
||||
function V(a){var b=sa(a);if(!b)return null;for(let e of b){b=pa(a,e);var c=b.matrix;if(null==c)c=null;else{var d=L(c);if(d)c=d;else{for(d=0;d<c.width;d++)for(let f=d+1;f<c.height;f++)c.get(d,f)!==c.get(f,d)&&(c.set(d,f,!c.get(d,f)),c.set(f,d,!c.get(f,d)));c=L(c)}}if(c)return{binaryData:c.bytes,data:c.text,chunks:c.chunks,version:c.version,location:{topRightCorner:b.mappingFunction(e.dimension,0),topLeftCorner:b.mappingFunction(0,0),bottomRightCorner:b.mappingFunction(e.dimension,e.dimension),bottomLeftCorner:b.mappingFunction(0,
|
||||
e.dimension),topRightFinderPattern:e.topRight,topLeftFinderPattern:e.topLeft,bottomLeftFinderPattern:e.bottomLeft,bottomRightAlignmentPattern:e.alignmentPattern},matrix:b.matrix}}return null}let ta={inversionAttempts:"attemptBoth",greyScaleWeights:{red:.2126,green:.7152,blue:.0722,useIntegerApproximation:!1},canOverwriteImage:!0};function W(a,b){Object.keys(b).forEach(c=>{a[c]=b[c]})}
|
||||
function X(a,b,c,d={}){let e=Object.create(null);W(e,ta);W(e,d);d="onlyInvert"===e.inversionAttempts||"invertFirst"===e.inversionAttempts;var f="attemptBoth"===e.inversionAttempts||d;var g=e.greyScaleWeights,h=e.canOverwriteImage,k=b*c;if(a.length!==4*k)throw Error("Malformed data passed to binarizer.");var m=0;if(h){var l=new Uint8ClampedArray(a.buffer,m,k);m+=k}l=new A(b,c,l);if(g.useIntegerApproximation)for(var n=0;n<c;n++)for(var q=0;q<b;q++){var r=4*(n*b+q);l.set(q,n,g.red*a[r]+g.green*a[r+1]+
|
||||
g.blue*a[r+2]+128>>8)}else for(n=0;n<c;n++)for(q=0;q<b;q++)r=4*(n*b+q),l.set(q,n,g.red*a[r]+g.green*a[r+1]+g.blue*a[r+2]);g=Math.ceil(b/8);n=Math.ceil(c/8);q=g*n;if(h){var u=new Uint8ClampedArray(a.buffer,m,q);m+=q}u=new A(g,n,u);for(q=0;q<n;q++)for(r=0;r<g;r++){var p=Infinity,t=0;for(var v=0;8>v;v++)for(let w=0;8>w;w++){let aa=l.get(8*r+w,8*q+v);p=Math.min(p,aa);t=Math.max(t,aa)}v=(p+t)/2;v=Math.min(255,1.11*v);24>=t-p&&(v=p/2,0<q&&0<r&&(t=(u.get(r,q-1)+2*u.get(r-1,q)+u.get(r-1,q-1))/4,p<t&&(v=t)));
|
||||
u.set(r,q,v)}h?(q=new Uint8ClampedArray(a.buffer,m,k),m+=k,q=new x(q,b)):q=x.createEmpty(b,c);r=null;f&&(h?(a=new Uint8ClampedArray(a.buffer,m,k),r=new x(a,b)):r=x.createEmpty(b,c));for(b=0;b<n;b++)for(a=0;a<g;a++){c=g-3;c=2>a?2:a>c?c:a;h=n-3;h=2>b?2:b>h?h:b;k=0;for(m=-2;2>=m;m++)for(p=-2;2>=p;p++)k+=u.get(c+m,h+p);c=k/25;for(h=0;8>h;h++)for(k=0;8>k;k++)m=8*a+h,p=8*b+k,t=l.get(m,p),q.set(m,p,t<=c),f&&r.set(m,p,!(t<=c))}f=f?{binarized:q,inverted:r}:{binarized:q};let {binarized:z,inverted:y}=f;(f=V(d?
|
||||
y:z))||"attemptBoth"!==e.inversionAttempts&&"invertFirst"!==e.inversionAttempts||(f=V(d?z:y));return f}X.default=X;let Y="dontInvert",Z={red:77,green:150,blue:29,useIntegerApproximation:!0};
|
||||
self.onmessage=a=>{let b=a.data.id,c=a.data.data;switch(a.data.type){case "decode":(a=X(c.data,c.width,c.height,{inversionAttempts:Y,greyScaleWeights:Z}))?self.postMessage({id:b,type:"qrResult",data:a.data,cornerPoints:[a.location.topLeftCorner,a.location.topRightCorner,a.location.bottomRightCorner,a.location.bottomLeftCorner]}):self.postMessage({id:b,type:"qrResult",data:null});break;case "grayscaleWeights":Z.red=c.red;Z.green=c.green;Z.blue=c.blue;Z.useIntegerApproximation=c.useIntegerApproximation;
|
||||
break;case "inversionMode":switch(c){case "original":Y="dontInvert";break;case "invert":Y="onlyInvert";break;case "both":Y="attemptBoth";break;default:throw Error("Invalid inversion mode");}break;case "close":self.close()}}
|
||||
`]),{type:"application/javascript"}));
|
||||
|
||||
export { createWorker };
|
1528
ihm_client/dist/sdk_client-BJ65BQeE.mjs
vendored
Normal file
1528
ihm_client/dist/sdk_client-BJ65BQeE.mjs
vendored
Normal file
File diff suppressed because one or more lines are too long
2104
ihm_client/dist/signature-component-DK4oRzT9.mjs
vendored
Normal file
2104
ihm_client/dist/signature-component-DK4oRzT9.mjs
vendored
Normal file
File diff suppressed because one or more lines are too long
877
ihm_client/dist/style.css
vendored
Normal file
877
ihm_client/dist/style.css
vendored
Normal file
File diff suppressed because one or more lines are too long
877
ihm_client/dist/style/4nk.css
vendored
Executable file
877
ihm_client/dist/style/4nk.css
vendored
Executable file
@ -0,0 +1,877 @@
|
||||
:root {
|
||||
--primary-color
|
||||
: #3A506B;
|
||||
/* Bleu métallique */
|
||||
--secondary-color
|
||||
: #B0BEC5;
|
||||
/* Gris acier */
|
||||
--accent-color
|
||||
: #D68C45;
|
||||
/* Cuivre */
|
||||
}
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #f4f4f4;
|
||||
background-image: url(../assets/bgd.webp);
|
||||
background-repeat:no-repeat;
|
||||
background-size: cover;
|
||||
background-blend-mode :soft-light;
|
||||
height: 100vh;
|
||||
}
|
||||
.message {
|
||||
margin: 30px 0;
|
||||
font-size: 14px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.message strong{
|
||||
font-family: "Segoe UI Emoji", "Noto Color Emoji", "Apple Color Emoji", sans-serif;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
/** Modal Css */
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
width: 55%;
|
||||
height: 30%;
|
||||
background-color: white;
|
||||
border-radius: 4px;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
margin: 0;
|
||||
padding-bottom: 8px;
|
||||
width: 100%;
|
||||
font-size: 0.9em;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.confirmation-box {
|
||||
/* margin-top: 20px; */
|
||||
align-content: center;
|
||||
width: 70%;
|
||||
height: 20%;
|
||||
/* padding: 20px; */
|
||||
font-size: 1.5em;
|
||||
color: #333333;
|
||||
top: 5%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Confirmation Modal Styles */
|
||||
#confirmation-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
width: 90%;
|
||||
max-width: 500px;
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.modal-confirmation {
|
||||
text-align: left;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.modal-confirmation h3 {
|
||||
margin-bottom: 15px;
|
||||
color: var(--primary-color);
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.modal-confirmation p {
|
||||
margin: 8px 0;
|
||||
font-size: 0.9em;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
margin-top: 20px;
|
||||
padding-top: 15px;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
|
||||
.modal-footer button {
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: var(--primary-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: var(--secondary-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media only screen and (max-width: 600px) {
|
||||
.modal-content {
|
||||
width: 95%;
|
||||
margin: 10px;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.modal-confirmation h3 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.modal-confirmation p {
|
||||
font-size: 0.85em;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-wrapper {
|
||||
position: fixed;
|
||||
z-index: 2;
|
||||
background: radial-gradient(circle, white, var(--primary-color));
|
||||
/* background-color: #CFD8DC; */
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
color: #37474F;
|
||||
height: 9vh;
|
||||
width: 100vw;
|
||||
left: 0;
|
||||
top: 0;
|
||||
box-shadow: 0px 8px 10px -5px rgba(0, 0, 0, .2), 0px 16px 24px 2px rgba(0, 0, 0, .14), 0px 6px 30px 5px rgba(0, 0, 0, .12);
|
||||
|
||||
.nav-right-icons {
|
||||
display: flex;
|
||||
.notification-container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
.notification-bell, .burger-menu {
|
||||
z-index: 3;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
.notification-badge {
|
||||
position: absolute;
|
||||
top: -.7rem;
|
||||
left: -.8rem;
|
||||
background-color: red;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
padding: 2.5px 6px;
|
||||
font-size: 0.8em;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.notification-board {
|
||||
position: absolute;
|
||||
width: 20rem;
|
||||
min-height: 8rem;
|
||||
background-color: white;
|
||||
right: 0.5rem;
|
||||
display: none;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
display: none;
|
||||
|
||||
.notification-element {
|
||||
padding: .8rem 0;
|
||||
width: 100%;
|
||||
&:hover {
|
||||
background-color: rgba(26, 28, 24, .08);
|
||||
}
|
||||
}
|
||||
.notification-element:not(:last-child) {
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.brand-logo {
|
||||
height: 100%;
|
||||
width: 100vw;
|
||||
align-content: center;
|
||||
position: relative;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.container {
|
||||
text-align: center;
|
||||
display: grid;
|
||||
height: 100vh;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
gap: 10px;
|
||||
grid-auto-rows: 10vh 15vh 1fr;
|
||||
}
|
||||
.title-container {
|
||||
grid-column: 2 / 7;
|
||||
grid-row: 2;
|
||||
}
|
||||
.page-container {
|
||||
grid-column: 2 / 7;
|
||||
grid-row: 3 ;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
padding: 1rem;
|
||||
box-sizing: border-box;
|
||||
max-height: 60vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 20px 0;
|
||||
}
|
||||
@media only screen and (min-width: 600px) {
|
||||
.tab-container {
|
||||
display: none;
|
||||
}
|
||||
.page-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.process-container {
|
||||
grid-column: 3 / 6;
|
||||
grid-row: 3 ;
|
||||
|
||||
.card {
|
||||
min-width: 40vw;
|
||||
}
|
||||
}
|
||||
.separator {
|
||||
width: 2px;
|
||||
background-color: #78909C;
|
||||
height: 80%;
|
||||
margin: 0 0.5em;
|
||||
}
|
||||
.tab-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
height: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 600px) {
|
||||
.process-container {
|
||||
grid-column: 2 / 7;
|
||||
grid-row: 3 ;
|
||||
}
|
||||
.container {
|
||||
grid-auto-rows: 10vh 15vh 15vh 1fr;
|
||||
}
|
||||
.tab-container {
|
||||
grid-column: 1 / 8;
|
||||
grid-row: 3;
|
||||
}
|
||||
.page-container {
|
||||
grid-column: 2 / 7;
|
||||
grid-row: 4 ;
|
||||
}
|
||||
.separator {
|
||||
display: none;
|
||||
}
|
||||
.tabs {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-color: #E0E4D6;
|
||||
}
|
||||
|
||||
.tab {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
cursor: pointer;
|
||||
font-size: 1em;
|
||||
color: #6200ea;
|
||||
&:hover {
|
||||
background-color: rgba(26, 28, 24, .08);
|
||||
}
|
||||
}
|
||||
.tab.active {
|
||||
border-bottom: 2px solid #6200ea;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.card.tab-content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-content.active {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 80%;
|
||||
}
|
||||
.modal-content {
|
||||
width: 80%;
|
||||
height: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
.qr-code {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.emoji-display {
|
||||
font-family: "Segoe UI Emoji", "Noto Color Emoji", "Apple Color Emoji", sans-serif;
|
||||
font-size: 20px;
|
||||
|
||||
}
|
||||
|
||||
#emoji-display-2{
|
||||
margin-top: 30px;
|
||||
font-family: "Segoe UI Emoji", "Noto Color Emoji", "Apple Color Emoji", sans-serif;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#okButton{
|
||||
margin-bottom: 2em;
|
||||
cursor: pointer;
|
||||
background-color: #D0D0D7;
|
||||
color: white;
|
||||
border-style: none;
|
||||
border-radius: 5px;
|
||||
color: #000;
|
||||
padding: 2px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.pairing-request {
|
||||
font-family: "Segoe UI Emoji", "Noto Color Emoji", "Apple Color Emoji", sans-serif;
|
||||
font-size: 14px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.sp-address-btn {
|
||||
margin-bottom: 2em;
|
||||
cursor: pointer;
|
||||
background-color: #D0D0D7;
|
||||
color: white;
|
||||
border-style: none;
|
||||
border-radius: 5px;
|
||||
color: #000;
|
||||
padding: 2px;
|
||||
|
||||
}
|
||||
|
||||
.camera-card {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
/* height: 200px; */
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
padding: 10px 20px;
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
text-align: center;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #3700b3;
|
||||
}
|
||||
|
||||
|
||||
.card {
|
||||
min-width: 300px;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 8px;
|
||||
background-color: white;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
height: 60vh;
|
||||
justify-content: flex-start;
|
||||
padding: 1rem;
|
||||
overflow-y: auto;
|
||||
|
||||
}
|
||||
|
||||
.card-content {
|
||||
flex-grow: 1;
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
text-align: left;
|
||||
font-size: .8em;
|
||||
position: relative;
|
||||
left: 2vw;
|
||||
width: 90%;
|
||||
.process-title {
|
||||
font-weight: bold;
|
||||
padding: 1rem 0;
|
||||
}
|
||||
.process-element {
|
||||
padding: .4rem 0;
|
||||
&:hover {
|
||||
background-color: rgba(26, 28, 24, .08);
|
||||
}
|
||||
&.selected {
|
||||
background-color: rgba(26, 28, 24, .08);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-description {
|
||||
padding: 20px;
|
||||
font-size: 1em;
|
||||
color: #333;
|
||||
width: 90%;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
|
||||
.card-action {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.menu-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 3.4rem;
|
||||
right: 1rem;
|
||||
background-color: white;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.menu-content a {
|
||||
display: block;
|
||||
padding: 10px 20px;
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
&:hover {
|
||||
background-color: rgba(26, 28, 24, .08);
|
||||
}
|
||||
}
|
||||
|
||||
.menu-content a:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.qr-code-scanner {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/* QR READER */
|
||||
#qr-reader div {
|
||||
position: inherit;
|
||||
}
|
||||
|
||||
#qr-reader div img{
|
||||
top: 15px ;
|
||||
right: 25px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
|
||||
/* INPUT CSS **/
|
||||
.input-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
background-color: #ECEFF1;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
width: 36vw;
|
||||
padding: 10px 0;
|
||||
font-size: 1em;
|
||||
border: none;
|
||||
border-bottom: 1px solid #ccc;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
transition: border-color 0.3s;
|
||||
}
|
||||
|
||||
.input-field:focus {
|
||||
border-bottom: 2px solid #6200ea;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
position: absolute;
|
||||
margin-top: -0.5em;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 10px 0;
|
||||
font-size: 1em;
|
||||
color: #999;
|
||||
pointer-events: none;
|
||||
transition: transform 0.3s, color 0.3s, font-size 0.3s;
|
||||
}
|
||||
|
||||
.input-field:focus + .input-label,
|
||||
.input-field:not(:placeholder-shown) + .input-label {
|
||||
transform: translateY(-20px);
|
||||
font-size: 0.8em;
|
||||
color: #6200ea;
|
||||
}
|
||||
|
||||
.input-underline {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
background-color: #6200ea;
|
||||
transition: width 0.3s, left 0.3s;
|
||||
}
|
||||
|
||||
.input-field:focus ~ .input-underline {
|
||||
width: 100%;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.dropdown-content {
|
||||
position: absolute;
|
||||
flex-direction: column;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
background-color: white;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
display: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.dropdown-content span {
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.dropdown-content span:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** AUTOCOMPLETE **/
|
||||
|
||||
select[data-multi-select-plugin] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.multi-select-component {
|
||||
width: 36vw;
|
||||
padding: 5px 0;
|
||||
font-size: 1em;
|
||||
border: none;
|
||||
border-bottom: 1px solid #ccc;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: auto;
|
||||
width: 100%;
|
||||
-o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
|
||||
transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
|
||||
}
|
||||
|
||||
.autocomplete-list {
|
||||
border-radius: 4px 0px 0px 4px;
|
||||
}
|
||||
|
||||
.multi-select-component:focus-within {
|
||||
box-shadow: inset 0px 0px 0px 2px #78ABFE;
|
||||
}
|
||||
|
||||
.multi-select-component .btn-group {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.multiselect-native-select .multiselect-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.selected-processes {
|
||||
background-color: white;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
.selected-wrapper {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
display: inline-block;
|
||||
border: 1px solid #d9d9d9;
|
||||
background-color: #ededed;
|
||||
white-space: nowrap;
|
||||
margin: 1px 5px 5px 0;
|
||||
height: 22px;
|
||||
vertical-align: top;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.selected-wrapper .selected-label {
|
||||
max-width: 514px;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
padding-left: 4px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.selected-wrapper .selected-close {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
line-height: 1.49em;
|
||||
margin-left: 5px;
|
||||
padding-bottom: 10px;
|
||||
height: 100%;
|
||||
vertical-align: top;
|
||||
padding-right: 4px;
|
||||
opacity: 0.2;
|
||||
color: #000;
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.search-container .selected-input {
|
||||
background: none;
|
||||
border: 0;
|
||||
height: 20px;
|
||||
width: 60px;
|
||||
padding: 0;
|
||||
margin-bottom: 6px;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.search-container .selected-input:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.dropdown-icon.active {
|
||||
transform: rotateX(180deg)
|
||||
}
|
||||
|
||||
.search-container .dropdown-icon {
|
||||
display: inline-block;
|
||||
padding: 10px 5px;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border: 0 !important;
|
||||
/* needed */
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
/* SVG background image */
|
||||
background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2212%22%20height%3D%2212%22%20viewBox%3D%220%200%2012%2012%22%3E%3Ctitle%3Edown-arrow%3C%2Ftitle%3E%3Cg%20fill%3D%22%23818181%22%3E%3Cpath%20d%3D%22M10.293%2C3.293%2C6%2C7.586%2C1.707%2C3.293A1%2C1%2C0%2C0%2C0%2C.293%2C4.707l5%2C5a1%2C1%2C0%2C0%2C0%2C1.414%2C0l5-5a1%2C1%2C0%2C1%2C0-1.414-1.414Z%22%20fill%3D%22%23818181%22%3E%3C%2Fpath%3E%3C%2Fg%3E%3C%2Fsvg%3E");
|
||||
background-position: center;
|
||||
background-size: 10px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.search-container ul {
|
||||
position: absolute;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
z-index: 3;
|
||||
margin-top: 29px;
|
||||
width: 100%;
|
||||
right: 0px;
|
||||
background: #fff;
|
||||
border: 1px solid #ccc;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
|
||||
}
|
||||
|
||||
.search-container ul :focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.search-container ul li {
|
||||
display: block;
|
||||
text-align: left;
|
||||
padding: 8px 29px 2px 12px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
font-size: 14px;
|
||||
min-height: 31px;
|
||||
}
|
||||
|
||||
.search-container ul li:first-child {
|
||||
border-top: 1px solid #ccc;
|
||||
border-radius: 4px 0px 0 0;
|
||||
}
|
||||
|
||||
.search-container ul li:last-child {
|
||||
border-radius: 4px 0px 0 0;
|
||||
}
|
||||
|
||||
|
||||
.search-container ul li:hover.not-cursor {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.search-container ul li:hover {
|
||||
color: #333;
|
||||
background-color: #f0f0f0;
|
||||
;
|
||||
border-color: #adadad;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Adding scrool to select options */
|
||||
.autocomplete-list {
|
||||
max-height: 130px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**************************************** Process page card ******************************************************/
|
||||
.process-card {
|
||||
min-width: 300px;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 8px;
|
||||
background-color: white;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
min-height: 40vh;
|
||||
max-height: 60vh;
|
||||
justify-content: space-between;
|
||||
padding: 1rem;
|
||||
overflow-y: auto;
|
||||
|
||||
}
|
||||
|
||||
.process-card-content {
|
||||
text-align: left;
|
||||
font-size: .8em;
|
||||
position: relative;
|
||||
left: 2vw;
|
||||
width: 90%;
|
||||
.process-title {
|
||||
font-weight: bold;
|
||||
padding: 1rem 0;
|
||||
}
|
||||
.process-element {
|
||||
padding: .4rem 0;
|
||||
&:hover {
|
||||
background-color: rgba(26, 28, 24, .08);
|
||||
}
|
||||
&.selected {
|
||||
background-color: rgba(26, 28, 24, .08);
|
||||
}
|
||||
}
|
||||
.selected-process-zone {
|
||||
background-color: rgba(26, 28, 24, .08);
|
||||
}
|
||||
}
|
||||
|
||||
.process-card-description {
|
||||
padding: 20px;
|
||||
font-size: 1em;
|
||||
color: #333;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
|
||||
.process-card-action {
|
||||
width: 100%;
|
||||
}
|
1507
ihm_client/dist/style/account.css
vendored
Executable file
1507
ihm_client/dist/style/account.css
vendored
Executable file
File diff suppressed because it is too large
Load Diff
597
ihm_client/dist/style/chat.css
vendored
Executable file
597
ihm_client/dist/style/chat.css
vendored
Executable file
@ -0,0 +1,597 @@
|
||||
/* Styles de base */
|
||||
:root {
|
||||
--primary-color: #3A506B;
|
||||
/* Bleu métallique */
|
||||
--secondary-color: #B0BEC5;
|
||||
/* Gris acier */
|
||||
--accent-color: #D68C45;
|
||||
/* Cuivre */
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/* 4NK NAVBAR */
|
||||
|
||||
.brand-logo {
|
||||
text-align: center;
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.nav-wrapper {
|
||||
position: fixed;
|
||||
background: radial-gradient(circle, white, var(--primary-color));
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: #37474F;
|
||||
height: 9vh;
|
||||
width: 100vw;
|
||||
left: 0;
|
||||
top: 0;
|
||||
box-shadow: 0px 8px 10px -5px rgba(0, 0, 0, .2), 0px 16px 24px 2px rgba(0, 0, 0, .14), 0px 6px 30px 5px rgba(0, 0, 0, .12);
|
||||
}
|
||||
|
||||
/* Icônes de la barre de navigation */
|
||||
.nav-right-icons {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.notification-bell,
|
||||
.burger-menu {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin-right: 1rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.notification-container {
|
||||
position: relative;
|
||||
/* Conserve la position pour le notification-board */
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.notification-board {
|
||||
position: absolute;
|
||||
/* Position absolue pour le placer par rapport au container */
|
||||
top: 40px;
|
||||
right: 0;
|
||||
background-color: white;
|
||||
border: 1px solid #ccc;
|
||||
padding: 10px;
|
||||
width: 200px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
/* Scroll si les notifications dépassent la taille */
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
z-index: 10;
|
||||
/* Définit la priorité d'affichage au-dessus des autres éléments */
|
||||
display: none;
|
||||
/* Par défaut, la notification est masquée */
|
||||
}
|
||||
|
||||
.notification-item{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.notification-badge {
|
||||
position: absolute;
|
||||
top: -18px;
|
||||
right: 35px;
|
||||
background-color: red;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
padding: 4px 8px;
|
||||
font-size: 12px;
|
||||
display: none;
|
||||
/* S'affiche seulement lorsqu'il y a des notifications */
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* Par défaut, le menu est masqué */
|
||||
#menu {
|
||||
display: none;
|
||||
/* Menu caché par défaut */
|
||||
transition: display 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.burger-menu {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Icône burger */
|
||||
#burger-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.menu-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 3.4rem;
|
||||
right: 1rem;
|
||||
background-color: white;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.menu-content a {
|
||||
display: block;
|
||||
padding: 10px 20px;
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(26, 28, 24, .08);
|
||||
}
|
||||
}
|
||||
|
||||
.menu-content a:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/* Ajustement pour la barre de navigation fixe */
|
||||
.container {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
height: 90vh;
|
||||
margin-top: 9vh;
|
||||
margin-left: -1%;
|
||||
text-align: left;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
|
||||
/* Liste des groupes */
|
||||
|
||||
.group-list {
|
||||
width: 25%;
|
||||
background-color: #1f2c3d;
|
||||
color: white;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
border-right: 2px solid #2c3e50;
|
||||
flex-shrink: 0;
|
||||
padding-right: 10px;
|
||||
height: 91vh;
|
||||
}
|
||||
.group-list ul {
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
padding-right: 10px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.group-list li {
|
||||
margin-bottom: 20px;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
background-color: #273646;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s, box-shadow 0.3s;
|
||||
}
|
||||
|
||||
.group-list li:hover {
|
||||
background-color: #34495e;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
|
||||
.group-list .member-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.group-list .member-container button {
|
||||
margin-left: 40px;
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
background: var(--primary-color);
|
||||
color: white;
|
||||
border: 0px solid var(--primary-color);
|
||||
border-radius: 50px;
|
||||
position: absolute;
|
||||
top: -25px;
|
||||
right: -25px;
|
||||
}
|
||||
|
||||
.group-list .member-container button:hover {
|
||||
background: var(--accent-color)
|
||||
}
|
||||
|
||||
|
||||
/* Zone de chat */
|
||||
.chat-area {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
background-color:#f1f1f1;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
|
||||
margin: 1% 0% 0.5% 1%;
|
||||
}
|
||||
|
||||
/* En-tête du chat */
|
||||
.chat-header {
|
||||
background-color: #34495e;
|
||||
color: white;
|
||||
padding: 15px;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
border-radius: 10px 10px 0 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Messages */
|
||||
.messages {
|
||||
flex: 1;
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
background-color: #f1f1f1;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.message-container {
|
||||
display: flex;
|
||||
margin: 8px;
|
||||
}
|
||||
.message-container .message {
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.message-container .message.user {
|
||||
align-self: flex-end;
|
||||
margin-left: auto;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.message {
|
||||
max-width: 70%;
|
||||
padding: 10px;
|
||||
border-radius: 12px;
|
||||
background:var(--secondary-color);
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
/* Messages de l'utilisateur */
|
||||
.message.user {
|
||||
background: #2196f3;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.message-time {
|
||||
font-size: 0.7em;
|
||||
opacity: 0.7;
|
||||
margin-left: 0px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
|
||||
/* Amélioration de l'esthétique des messages */
|
||||
/* .message.user:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: -10px;
|
||||
border: 10px solid transparent;
|
||||
border-left-color: #3498db;
|
||||
} */
|
||||
|
||||
/* Zone de saisie */
|
||||
.input-area {
|
||||
padding: 10px;
|
||||
background-color: #bdc3c7;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 10px;
|
||||
margin: 1%;
|
||||
/* Alignement vertical */
|
||||
}
|
||||
|
||||
.input-area input[type="text"] {
|
||||
flex: 1;
|
||||
/* Prend l'espace restant */
|
||||
padding: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.input-area .attachment-icon {
|
||||
margin: 0 10px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.input-area button {
|
||||
padding: 10px;
|
||||
margin-left: 10px;
|
||||
background-color: #2980b9;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.input-area button:hover {
|
||||
background-color: #1f608d;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
margin: 20px 0px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tabs button {
|
||||
padding: 10px 20px;
|
||||
cursor: pointer;
|
||||
background: var(--primary-color);
|
||||
color: white;
|
||||
border: 0px solid var(--primary-color);
|
||||
margin-right: 5px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.tabs button:hover {
|
||||
background: var(--secondary-color);
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
/* Signature */
|
||||
.signature-area {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
background-color:#f1f1f1;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
|
||||
margin: 1% 0% 0.5% 1%;
|
||||
transition: all 1s ease 0.1s;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.signature-area.hidden {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
display: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.signature-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
border-radius: 10px 10px 0 0;
|
||||
padding-left: 4%;
|
||||
}
|
||||
|
||||
.signature-content {
|
||||
padding: 10px;
|
||||
background-color: var(--secondary-color);
|
||||
color: var(--primary-color);
|
||||
height: 100%;
|
||||
border-radius: 10px;
|
||||
margin: 1%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.signature-description {
|
||||
height: 20%;
|
||||
width: 100%;
|
||||
margin: 0% 10% 0% 10%;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.signature-description li {
|
||||
margin: 1% 0% 1% 0%;
|
||||
list-style: none;
|
||||
padding: 2%;
|
||||
border-radius: 10px;
|
||||
background-color: var(--primary-color);
|
||||
color: var(--secondary-color);
|
||||
width: 20%;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
margin-right: 2%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.signature-description li .member-list {
|
||||
margin-left: -30%;
|
||||
}
|
||||
|
||||
.signature-description li .member-list li {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.signature-description li .member-list li:hover {
|
||||
background-color: var(--secondary-color);
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.signature-documents {
|
||||
height: 80%;
|
||||
width: 100%;
|
||||
margin: 0% 10% 0% 10%;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.signature-documents-header {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 15%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#request-document-button {
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 8px;
|
||||
cursor: pointer;
|
||||
margin-left: 5%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#request-document-button:hover {
|
||||
background-color: var(--accent-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#close-signature {
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
margin-left: auto;
|
||||
margin-right: 2%;
|
||||
border-radius: 50%;
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: -3%;
|
||||
margin-top: -5%;
|
||||
font-size: 1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#close-signature:hover {
|
||||
background-color: var(--secondary-color);
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
/* REQUEST MODAL */
|
||||
.request-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: var(--secondary-color);
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
position: relative;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.close-modal {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
border: none;
|
||||
background: none;
|
||||
font-size: 1.5em;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.close-modal:hover {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.modal-members {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.modal-members ul li{
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.file-upload-container {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.file-list {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 5px;
|
||||
margin: 5px 0;
|
||||
background: var(--background-color-secondary);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.remove-file {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-color);
|
||||
cursor: pointer;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.remove-file:hover {
|
||||
color: var(--error-color);
|
||||
}
|
||||
|
||||
#message-input {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
resize: none;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
max-width: 100%;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media screen and (max-width: 768px) {
|
||||
.group-list {
|
||||
display: none;
|
||||
/* Masquer la liste des groupes sur les petits écrans */
|
||||
}
|
||||
|
||||
.chat-area {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--primary-color);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--secondary-color);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--accent-color);
|
||||
}
|
1664
ihm_client/dist/style/signature.css
vendored
Executable file
1664
ihm_client/dist/style/signature.css
vendored
Executable file
File diff suppressed because it is too large
Load Diff
2
ihm_client/dist/types/components/header/header.d.ts
vendored
Normal file
2
ihm_client/dist/types/components/header/header.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
export declare function unpair(): Promise<void>;
|
||||
export declare function initHeader(): Promise<void>;
|
1
ihm_client/dist/types/components/modal/confirmation-modal.d.ts
vendored
Normal file
1
ihm_client/dist/types/components/modal/confirmation-modal.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export declare function closeConfirmationModal(): Promise<void>;
|
10
ihm_client/dist/types/components/qrcode-scanner/qrcode-scanner-component.d.ts
vendored
Normal file
10
ihm_client/dist/types/components/qrcode-scanner/qrcode-scanner-component.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
export default class QrScannerComponent extends HTMLElement {
|
||||
videoElement: any;
|
||||
wrapper: any;
|
||||
qrScanner: any;
|
||||
constructor();
|
||||
connectedCallback(): void;
|
||||
initializeScanner(): Promise<void>;
|
||||
onQrCodeScanned(result: any): Promise<void>;
|
||||
disconnectedCallback(): void;
|
||||
}
|
1
ihm_client/dist/types/components/validation-modal/validation-modal.d.ts
vendored
Normal file
1
ihm_client/dist/types/components/validation-modal/validation-modal.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export declare function initValidationModal(processDiffs: any): Promise<void>;
|
14
ihm_client/dist/types/components/validation-rule-modal/validation-rule-modal.d.ts
vendored
Normal file
14
ihm_client/dist/types/components/validation-rule-modal/validation-rule-modal.d.ts
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
export interface ValidationRule {
|
||||
quorum: number;
|
||||
fields: string[];
|
||||
min_sig_member: number;
|
||||
}
|
||||
/**
|
||||
* Loads and injects the modal HTML into the document if not already loaded.
|
||||
*/
|
||||
export declare function loadValidationRuleModal(templatePath?: string): Promise<void>;
|
||||
/**
|
||||
* Opens the modal and lets the user input a ValidationRule.
|
||||
* Calls the callback with the constructed rule on submit.
|
||||
*/
|
||||
export declare function showValidationRuleModal(onSubmit: (rule: ValidationRule) => void): void;
|
3
ihm_client/dist/types/index.d.ts
vendored
Normal file
3
ihm_client/dist/types/index.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
export { default as Services } from './services/service';
|
||||
export { default as Database } from './services/database.service';
|
||||
export { MessageType } from './models/process.model';
|
24
ihm_client/dist/types/interface/groupInterface.d.ts
vendored
Normal file
24
ihm_client/dist/types/interface/groupInterface.d.ts
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
import { DocumentSignature } from '~/models/signature.models';
|
||||
export interface Group {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
roles: Array<{
|
||||
name: string;
|
||||
members: Array<{
|
||||
id: string | number;
|
||||
name: string;
|
||||
}>;
|
||||
documents?: Array<any>;
|
||||
}>;
|
||||
commonDocuments: Array<{
|
||||
id: number;
|
||||
name: string;
|
||||
visibility: string;
|
||||
description: string;
|
||||
createdAt?: string | null;
|
||||
deadline?: string | null;
|
||||
signatures?: DocumentSignature[];
|
||||
status?: string;
|
||||
}>;
|
||||
}
|
10
ihm_client/dist/types/interface/memberInterface.d.ts
vendored
Normal file
10
ihm_client/dist/types/interface/memberInterface.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
export interface Member {
|
||||
id: string | number;
|
||||
name: string;
|
||||
email?: string;
|
||||
avatar?: string;
|
||||
processRoles?: Array<{
|
||||
processId: number | string;
|
||||
role: string;
|
||||
}>;
|
||||
}
|
13
ihm_client/dist/types/main.d.ts
vendored
Normal file
13
ihm_client/dist/types/main.d.ts
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
import { SignatureComponent } from './pages/signature/signature-component';
|
||||
import { SignatureElement } from './pages/signature/signature';
|
||||
import { AccountComponent } from './pages/account/account-component';
|
||||
import { AccountElement } from './pages/account/account';
|
||||
export { SignatureComponent, SignatureElement, AccountComponent, AccountElement };
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'signature-component': SignatureComponent;
|
||||
'signature-element': SignatureElement;
|
||||
'account-component': AccountComponent;
|
||||
'account-element': AccountElement;
|
||||
}
|
||||
}
|
118
ihm_client/dist/types/mocks/mock-account/constAccountMock.d.ts
vendored
Normal file
118
ihm_client/dist/types/mocks/mock-account/constAccountMock.d.ts
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
export declare const ALLOWED_ROLES: string[];
|
||||
export declare const STORAGE_KEYS: {
|
||||
pairing: string;
|
||||
wallet: string;
|
||||
process: string;
|
||||
data: string;
|
||||
};
|
||||
export declare const defaultRows: {
|
||||
column1: string;
|
||||
column2: string;
|
||||
column3: string;
|
||||
}[];
|
||||
export declare const mockNotifications: {
|
||||
[key: string]: Notification[];
|
||||
};
|
||||
export declare const notificationMessages: string[];
|
||||
export declare const mockDataRows: {
|
||||
column1: string;
|
||||
column2: string;
|
||||
column3: string;
|
||||
column4: string;
|
||||
column5: string;
|
||||
column6: string;
|
||||
processName: string;
|
||||
zone: string;
|
||||
}[];
|
||||
export declare const mockProcessRows: ({
|
||||
process: string;
|
||||
role: string;
|
||||
notification: {
|
||||
messages: {
|
||||
id: number;
|
||||
read: boolean;
|
||||
date: string;
|
||||
message: string;
|
||||
}[];
|
||||
unread?: undefined;
|
||||
total?: undefined;
|
||||
};
|
||||
} | {
|
||||
process: string;
|
||||
role: string;
|
||||
notification: {
|
||||
unread: number;
|
||||
total: number;
|
||||
messages: {
|
||||
id: number;
|
||||
read: boolean;
|
||||
date: string;
|
||||
message: string;
|
||||
}[];
|
||||
};
|
||||
})[];
|
||||
export declare const mockContracts: {
|
||||
'Contract #123': {
|
||||
title: string;
|
||||
date: string;
|
||||
parties: string[];
|
||||
terms: string[];
|
||||
content: string;
|
||||
};
|
||||
'Contract #456': {
|
||||
title: string;
|
||||
date: string;
|
||||
parties: string[];
|
||||
terms: string[];
|
||||
content: string;
|
||||
};
|
||||
'Contract #789': {
|
||||
title: string;
|
||||
date: string;
|
||||
parties: string[];
|
||||
terms: string[];
|
||||
content: string;
|
||||
};
|
||||
'Contract #101': {
|
||||
title: string;
|
||||
date: string;
|
||||
parties: string[];
|
||||
terms: string[];
|
||||
content: string;
|
||||
};
|
||||
'Contract #102': {
|
||||
title: string;
|
||||
date: string;
|
||||
parties: string[];
|
||||
terms: string[];
|
||||
content: string;
|
||||
};
|
||||
'Contract #103': {
|
||||
title: string;
|
||||
date: string;
|
||||
parties: string[];
|
||||
terms: string[];
|
||||
content: string;
|
||||
};
|
||||
'Contract #104': {
|
||||
title: string;
|
||||
date: string;
|
||||
parties: string[];
|
||||
terms: string[];
|
||||
content: string;
|
||||
};
|
||||
'Contract #105': {
|
||||
title: string;
|
||||
date: string;
|
||||
parties: string[];
|
||||
terms: string[];
|
||||
content: string;
|
||||
};
|
||||
'Contract #106': {
|
||||
title: string;
|
||||
date: string;
|
||||
parties: string[];
|
||||
terms: string[];
|
||||
content: string;
|
||||
};
|
||||
};
|
38
ihm_client/dist/types/mocks/mock-account/interfacesAccountMock.d.ts
vendored
Normal file
38
ihm_client/dist/types/mocks/mock-account/interfacesAccountMock.d.ts
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
export interface Row {
|
||||
column1: string;
|
||||
column2: string;
|
||||
column3: string;
|
||||
}
|
||||
export interface Contract {
|
||||
title: string;
|
||||
date: string;
|
||||
parties: string[];
|
||||
terms: string[];
|
||||
content: string;
|
||||
}
|
||||
export interface WalletRow {
|
||||
column1: string;
|
||||
column2: string;
|
||||
column3: string;
|
||||
}
|
||||
export interface DataRow {
|
||||
column1: string;
|
||||
column2: string;
|
||||
column3: string;
|
||||
column4: string;
|
||||
column5: string;
|
||||
column6: string;
|
||||
processName: string;
|
||||
zone: string;
|
||||
}
|
||||
export interface Notification {
|
||||
message: string;
|
||||
timestamp: string;
|
||||
isRead: boolean;
|
||||
}
|
||||
export interface NotificationMessage {
|
||||
id: number;
|
||||
read: boolean;
|
||||
date: string;
|
||||
message: string;
|
||||
}
|
119
ihm_client/dist/types/mocks/mock-signature/groupsMock.d.ts
vendored
Normal file
119
ihm_client/dist/types/mocks/mock-signature/groupsMock.d.ts
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
export const groupsMock: {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
commonDocuments: {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
visibility: string;
|
||||
status: string;
|
||||
createdAt: null;
|
||||
deadline: null;
|
||||
signatures: never[];
|
||||
}[];
|
||||
roles: ({
|
||||
name: string;
|
||||
members: {
|
||||
id: number;
|
||||
name: string;
|
||||
}[];
|
||||
documents: ({
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
visibility: string;
|
||||
createdAt: string;
|
||||
deadline: string;
|
||||
signatures: ({
|
||||
member: {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
signed: boolean;
|
||||
signedAt: string;
|
||||
} | {
|
||||
member: {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
signed: boolean;
|
||||
signedAt?: undefined;
|
||||
})[];
|
||||
status?: undefined;
|
||||
} | {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
visibility: string;
|
||||
createdAt: null;
|
||||
deadline: null;
|
||||
signatures: never[];
|
||||
status?: undefined;
|
||||
} | {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
visibility: string;
|
||||
status: string;
|
||||
createdAt: null;
|
||||
deadline: null;
|
||||
signatures: never[];
|
||||
})[];
|
||||
} | {
|
||||
name: string;
|
||||
members: {
|
||||
id: number;
|
||||
name: string;
|
||||
}[];
|
||||
documents: ({
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
visibility: string;
|
||||
createdAt: string;
|
||||
deadline: string;
|
||||
signatures: {
|
||||
member: {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
signed: boolean;
|
||||
signedAt: string;
|
||||
}[];
|
||||
status?: undefined;
|
||||
} | {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
visibility: string;
|
||||
status: string;
|
||||
createdAt: null;
|
||||
deadline: null;
|
||||
signatures: never[];
|
||||
} | {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
visibility: string;
|
||||
status: string;
|
||||
createdAt: string;
|
||||
deadline: string;
|
||||
signatures: ({
|
||||
member: {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
signed: boolean;
|
||||
signedAt: string;
|
||||
} | {
|
||||
member: {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
signed: boolean;
|
||||
signedAt?: undefined;
|
||||
})[];
|
||||
})[];
|
||||
})[];
|
||||
}[];
|
10
ihm_client/dist/types/mocks/mock-signature/membersMocks.d.ts
vendored
Normal file
10
ihm_client/dist/types/mocks/mock-signature/membersMocks.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
export const membersMock: {
|
||||
id: number;
|
||||
name: string;
|
||||
avatar: string;
|
||||
email: string;
|
||||
processRoles: {
|
||||
processId: number;
|
||||
role: string;
|
||||
}[];
|
||||
}[];
|
9
ihm_client/dist/types/mocks/mock-signature/messagesMock.d.ts
vendored
Normal file
9
ihm_client/dist/types/mocks/mock-signature/messagesMock.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
export declare const messagesMock: {
|
||||
memberId: number;
|
||||
messages: {
|
||||
id: number;
|
||||
sender: string;
|
||||
text: string;
|
||||
time: string;
|
||||
}[];
|
||||
}[];
|
6
ihm_client/dist/types/models/backup.model.d.ts
vendored
Normal file
6
ihm_client/dist/types/models/backup.model.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
import { Device, Process, SecretsStore } from "pkg/sdk_client";
|
||||
export interface BackUp {
|
||||
device: Device;
|
||||
secrets: SecretsStore;
|
||||
processes: Record<string, Process>;
|
||||
}
|
24
ihm_client/dist/types/models/notification.model.d.ts
vendored
Normal file
24
ihm_client/dist/types/models/notification.model.d.ts
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
export interface INotification {
|
||||
id: number;
|
||||
title: string;
|
||||
description: string;
|
||||
sendToNotificationPage?: boolean;
|
||||
path?: string;
|
||||
}
|
||||
export interface IUser {
|
||||
id: string;
|
||||
information?: any;
|
||||
}
|
||||
export interface IMessage {
|
||||
id: string;
|
||||
message: any;
|
||||
}
|
||||
export interface UserDiff {
|
||||
new_state_merkle_root: string;
|
||||
field: string;
|
||||
previous_value: string;
|
||||
new_value: string;
|
||||
notify_user: boolean;
|
||||
need_validation: boolean;
|
||||
proof: any;
|
||||
}
|
56
ihm_client/dist/types/models/process.model.d.ts
vendored
Normal file
56
ihm_client/dist/types/models/process.model.d.ts
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
export interface IProcess {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
icon?: string;
|
||||
zoneList: IZone[];
|
||||
}
|
||||
export interface IZone {
|
||||
id: number;
|
||||
name: string;
|
||||
path: string;
|
||||
icon?: string;
|
||||
}
|
||||
export interface INotification {
|
||||
id: number;
|
||||
title: string;
|
||||
description: string;
|
||||
sendToNotificationPage?: boolean;
|
||||
path?: string;
|
||||
}
|
||||
export declare enum MessageType {
|
||||
LISTENING = "LISTENING",
|
||||
REQUEST_LINK = "REQUEST_LINK",
|
||||
LINK_ACCEPTED = "LINK_ACCEPTED",
|
||||
CREATE_PAIRING = "CREATE_PAIRING",
|
||||
PAIRING_CREATED = "PAIRING_CREATED",
|
||||
ERROR = "ERROR",
|
||||
VALIDATE_TOKEN = "VALIDATE_TOKEN",
|
||||
RENEW_TOKEN = "RENEW_TOKEN",
|
||||
GET_PAIRING_ID = "GET_PAIRING_ID",
|
||||
GET_PROCESSES = "GET_PROCESSES",
|
||||
GET_MY_PROCESSES = "GET_MY_PROCESSES",
|
||||
PROCESSES_RETRIEVED = "PROCESSES_RETRIEVED",
|
||||
RETRIEVE_DATA = "RETRIEVE_DATA",
|
||||
DATA_RETRIEVED = "DATA_RETRIEVED",
|
||||
DECODE_PUBLIC_DATA = "DECODE_PUBLIC_DATA",
|
||||
PUBLIC_DATA_DECODED = "PUBLIC_DATA_DECODED",
|
||||
GET_MEMBER_ADDRESSES = "GET_MEMBER_ADDRESSES",
|
||||
MEMBER_ADDRESSES_RETRIEVED = "MEMBER_ADDRESSES_RETRIEVED",
|
||||
CREATE_PROCESS = "CREATE_PROCESS",
|
||||
PROCESS_CREATED = "PROCESS_CREATED",
|
||||
UPDATE_PROCESS = "UPDATE_PROCESS",
|
||||
PROCESS_UPDATED = "PROCESS_UPDATED",
|
||||
NOTIFY_UPDATE = "NOTIFY_UPDATE",
|
||||
UPDATE_NOTIFIED = "UPDATE_NOTIFIED",
|
||||
VALIDATE_STATE = "VALIDATE_STATE",
|
||||
STATE_VALIDATED = "STATE_VALIDATED",
|
||||
HASH_VALUE = "HASH_VALUE",
|
||||
VALUE_HASHED = "VALUE_HASHED",
|
||||
GET_MERKLE_PROOF = "GET_MERKLE_PROOF",
|
||||
MERKLE_PROOF_RETRIEVED = "MERKLE_PROOF_RETRIEVED",
|
||||
VALIDATE_MERKLE_PROOF = "VALIDATE_MERKLE_PROOF",
|
||||
MERKLE_PROOF_VALIDATED = "MERKLE_PROOF_VALIDATED",
|
||||
ADD_DEVICE = "ADD_DEVICE",
|
||||
DEVICE_ADDED = "DEVICE_ADDED"
|
||||
}
|
60
ihm_client/dist/types/models/signature.models.d.ts
vendored
Normal file
60
ihm_client/dist/types/models/signature.models.d.ts
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
export interface Group {
|
||||
id: number;
|
||||
name: string;
|
||||
description?: string;
|
||||
roles: {
|
||||
id?: number;
|
||||
name: string;
|
||||
members: {
|
||||
id: string | number;
|
||||
name: string;
|
||||
}[];
|
||||
documents?: {
|
||||
id: number;
|
||||
name: string;
|
||||
description?: string;
|
||||
visibility: string;
|
||||
createdAt: string | null;
|
||||
deadline: string | null;
|
||||
signatures: DocumentSignature[];
|
||||
status?: string;
|
||||
files?: Array<{
|
||||
name: string;
|
||||
url: string;
|
||||
}>;
|
||||
}[];
|
||||
}[];
|
||||
}
|
||||
export interface Message {
|
||||
id: number;
|
||||
sender: string;
|
||||
text?: string;
|
||||
time: string;
|
||||
type: 'text' | 'file';
|
||||
fileName?: string;
|
||||
fileData?: string;
|
||||
}
|
||||
export interface MemberMessages {
|
||||
memberId: string;
|
||||
messages: Message[];
|
||||
}
|
||||
export interface DocumentSignature {
|
||||
signed: boolean;
|
||||
member: {
|
||||
name: string;
|
||||
};
|
||||
signedAt?: string;
|
||||
}
|
||||
export interface RequestParams {
|
||||
processId: number;
|
||||
processName: string;
|
||||
roleId: number;
|
||||
roleName: string;
|
||||
documentId: number;
|
||||
documentName: string;
|
||||
}
|
||||
export interface Notification {
|
||||
memberId: string;
|
||||
text: string;
|
||||
time: string;
|
||||
}
|
12
ihm_client/dist/types/pages/account/account-component.d.ts
vendored
Normal file
12
ihm_client/dist/types/pages/account/account-component.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
import { AccountElement } from './account';
|
||||
declare class AccountComponent extends HTMLElement {
|
||||
_callback: any;
|
||||
accountElement: AccountElement | null;
|
||||
constructor();
|
||||
connectedCallback(): void;
|
||||
fetchData(): Promise<void>;
|
||||
set callback(fn: any);
|
||||
get callback(): any;
|
||||
render(): void;
|
||||
}
|
||||
export { AccountComponent };
|
98
ihm_client/dist/types/pages/account/account.d.ts
vendored
Normal file
98
ihm_client/dist/types/pages/account/account.d.ts
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
declare global {
|
||||
interface Window {
|
||||
initAccount: () => void;
|
||||
showContractPopup: (contractId: string) => void;
|
||||
showPairing: () => Promise<void>;
|
||||
showWallet: () => void;
|
||||
showData: () => void;
|
||||
addWalletRow: () => void;
|
||||
confirmWalletRow: () => void;
|
||||
cancelWalletRow: () => void;
|
||||
openAvatarPopup: () => void;
|
||||
closeAvatarPopup: () => void;
|
||||
editDeviceName: (cell: HTMLTableCellElement) => void;
|
||||
showNotifications: (processName: string) => void;
|
||||
closeNotificationPopup: (event: Event) => void;
|
||||
markAsRead: (processName: string, messageId: number, element: HTMLElement) => void;
|
||||
exportRecovery: () => void;
|
||||
confirmDeleteAccount: () => void;
|
||||
deleteAccount: () => void;
|
||||
updateNavbarBanner: (bannerUrl: string) => void;
|
||||
saveBannerToLocalStorage: (bannerUrl: string) => void;
|
||||
loadSavedBanner: () => void;
|
||||
cancelAddRowPairing: () => void;
|
||||
saveName: (cell: HTMLElement, input: HTMLInputElement) => void;
|
||||
showProcessNotifications: (processName: string) => void;
|
||||
handleLogout: () => void;
|
||||
initializeEventListeners: () => void;
|
||||
showProcess: () => void;
|
||||
showProcessCreation: () => void;
|
||||
showDocumentValidation: () => void;
|
||||
updateNavbarName: (name: string) => void;
|
||||
updateNavbarLastName: (lastName: string) => void;
|
||||
showAlert: (title: string, text?: string, icon?: string) => void;
|
||||
addRowPairing: () => void;
|
||||
confirmRowPairing: () => void;
|
||||
cancelRowPairing: () => void;
|
||||
deleteRowPairing: (button: HTMLButtonElement) => void;
|
||||
generateRecoveryWords: () => string[];
|
||||
exportUserData: () => void;
|
||||
updateActionButtons: () => void;
|
||||
showQRCodeModal: (pairingId: string) => void;
|
||||
}
|
||||
}
|
||||
declare class AccountElement extends HTMLElement {
|
||||
private dom;
|
||||
constructor();
|
||||
connectedCallback(): void;
|
||||
private showAlert;
|
||||
private confirmDeleteAccount;
|
||||
private deleteAccount;
|
||||
private updateNavbarBanner;
|
||||
private saveBannerToLocalStorage;
|
||||
private loadSavedBanner;
|
||||
private closeNotificationPopup;
|
||||
private markAsRead;
|
||||
private calculateNotifications;
|
||||
private exportRecovery;
|
||||
private generateRecoveryWords;
|
||||
private exportUserData;
|
||||
private updateActionButtons;
|
||||
private getConfirmFunction;
|
||||
private getCancelFunction;
|
||||
private addRowPairing;
|
||||
private updateTableContent;
|
||||
private confirmRowPairing;
|
||||
private cancelRowPairing;
|
||||
private resetButtonContainer;
|
||||
private deleteRowPairing;
|
||||
private editDeviceName;
|
||||
private finishEditing;
|
||||
private handleAvatarUpload;
|
||||
private showProcessCreation;
|
||||
private showDocumentValidation;
|
||||
private showProcess;
|
||||
private showProcessNotifications;
|
||||
private handleLogout;
|
||||
private showContractPopup;
|
||||
private hideAllContent;
|
||||
private showPairing;
|
||||
private showWallet;
|
||||
private updateWalletTableContent;
|
||||
private showData;
|
||||
private addWalletRow;
|
||||
private confirmWalletRow;
|
||||
private cancelWalletRow;
|
||||
private updateDataTableContent;
|
||||
private openAvatarPopup;
|
||||
private setupEventListeners;
|
||||
private closeAvatarPopup;
|
||||
private loadAvatar;
|
||||
private loadUserInfo;
|
||||
private updateNavbarName;
|
||||
private updateNavbarLastName;
|
||||
private updateProfilePreview;
|
||||
private initializeEventListeners;
|
||||
private showQRCodeModal;
|
||||
}
|
||||
export { AccountElement };
|
33
ihm_client/dist/types/pages/account/document-validation.d.ts
vendored
Normal file
33
ihm_client/dist/types/pages/account/document-validation.d.ts
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
export interface Vin {
|
||||
txid: string;
|
||||
vout: number;
|
||||
prevout: {
|
||||
scriptpubkey: string;
|
||||
scriptpubkey_asm: string;
|
||||
scriptpubkey_type: string;
|
||||
scriptpubkey_address: string;
|
||||
value: number;
|
||||
};
|
||||
scriptsig: string;
|
||||
scriptsig_asm: string;
|
||||
witness: string[];
|
||||
is_coinbase: boolean;
|
||||
sequence: number;
|
||||
}
|
||||
export interface TransactionInfo {
|
||||
txid: string;
|
||||
version: number;
|
||||
locktime: number;
|
||||
vin: Vin[];
|
||||
vout: any[];
|
||||
size: number;
|
||||
weight: number;
|
||||
fee: number;
|
||||
status: {
|
||||
confirmed: boolean;
|
||||
block_height: number;
|
||||
block_hash: string;
|
||||
block_time: number;
|
||||
};
|
||||
}
|
||||
export declare function getDocumentValidation(container: HTMLElement): void;
|
8
ihm_client/dist/types/pages/account/key-value-section.d.ts
vendored
Normal file
8
ihm_client/dist/types/pages/account/key-value-section.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
import type { RoleDefinition } from '../../../pkg/sdk_client';
|
||||
export declare function createKeyValueSection(title: string, id: string, isRoleSection?: boolean): {
|
||||
element: HTMLDivElement;
|
||||
getData: () => Record<string, RoleDefinition> | Record<string, string | {
|
||||
type: string;
|
||||
data: Uint8Array;
|
||||
}>;
|
||||
};
|
1
ihm_client/dist/types/pages/account/process-creation.d.ts
vendored
Normal file
1
ihm_client/dist/types/pages/account/process-creation.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export declare function getProcessCreation(container: HTMLElement): Promise<void>;
|
4
ihm_client/dist/types/pages/account/process.d.ts
vendored
Normal file
4
ihm_client/dist/types/pages/account/process.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
export declare function createProcessTab(container: HTMLElement, processes: {
|
||||
name: string;
|
||||
publicData: Record<string, any>;
|
||||
}[]): HTMLElement;
|
8
ihm_client/dist/types/pages/home/home-component.d.ts
vendored
Normal file
8
ihm_client/dist/types/pages/home/home-component.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
export declare class LoginComponent extends HTMLElement {
|
||||
_callback: any;
|
||||
constructor();
|
||||
connectedCallback(): void;
|
||||
set callback(fn: any);
|
||||
get callback(): any;
|
||||
render(): void;
|
||||
}
|
4
ihm_client/dist/types/pages/home/home.d.ts
vendored
Normal file
4
ihm_client/dist/types/pages/home/home.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
import QrScannerComponent from '../../components/qrcode-scanner/qrcode-scanner-component';
|
||||
export { QrScannerComponent };
|
||||
export declare function initHomePage(): Promise<void>;
|
||||
export declare function openModal(myAddress: string, receiverAddress: string): Promise<void>;
|
10
ihm_client/dist/types/pages/process-element/process-component.d.ts
vendored
Normal file
10
ihm_client/dist/types/pages/process-element/process-component.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
export declare class ProcessListComponent extends HTMLElement {
|
||||
_callback: any;
|
||||
id: string;
|
||||
zone: string;
|
||||
constructor();
|
||||
connectedCallback(): void;
|
||||
set callback(fn: any);
|
||||
get callback(): any;
|
||||
render(): void;
|
||||
}
|
1
ihm_client/dist/types/pages/process-element/process-element.d.ts
vendored
Normal file
1
ihm_client/dist/types/pages/process-element/process-element.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export declare function initProcessElement(id: string, zone: string): Promise<void>;
|
12
ihm_client/dist/types/pages/signature/signature-component.d.ts
vendored
Normal file
12
ihm_client/dist/types/pages/signature/signature-component.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
import { SignatureElement } from './signature';
|
||||
declare class SignatureComponent extends HTMLElement {
|
||||
_callback: any;
|
||||
signatureElement: SignatureElement | null;
|
||||
constructor();
|
||||
connectedCallback(): void;
|
||||
fetchData(): Promise<void>;
|
||||
set callback(fn: any);
|
||||
get callback(): any;
|
||||
render(): void;
|
||||
}
|
||||
export { SignatureComponent };
|
71
ihm_client/dist/types/pages/signature/signature.d.ts
vendored
Normal file
71
ihm_client/dist/types/pages/signature/signature.d.ts
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
declare global {
|
||||
interface Window {
|
||||
toggleUserList: () => void;
|
||||
switchUser: (userId: string | number) => void;
|
||||
closeProcessDetails: (groupId: number) => void;
|
||||
loadMemberChat: (memberId: string | number) => void;
|
||||
closeRoleDocuments: (roleName: string) => void;
|
||||
newRequest: (params: RequestParams) => void;
|
||||
submitRequest: () => void;
|
||||
closeNewRequest: () => void;
|
||||
closeModal: (button: HTMLElement) => void;
|
||||
submitDocumentRequest: (documentId: number) => void;
|
||||
submitNewDocument: (event: Event) => void;
|
||||
submitCommonDocument: (event: Event) => void;
|
||||
signDocument: (documentId: number, processId: number, isCommonDocument: boolean) => void;
|
||||
confirmSignature: (documentId: number, processId: number, isCommonDocument: boolean) => void;
|
||||
}
|
||||
}
|
||||
import { RequestParams } from '../../models/signature.models';
|
||||
declare class SignatureElement extends HTMLElement {
|
||||
private selectedMemberId;
|
||||
private messagesMock;
|
||||
private dom;
|
||||
private notifications;
|
||||
private notificationBadge;
|
||||
private notificationBoard;
|
||||
private notificationBell;
|
||||
private selectedSignatories;
|
||||
private allMembers;
|
||||
private showAlert;
|
||||
private signDocument;
|
||||
constructor();
|
||||
private initMessageEvents;
|
||||
private initFileUpload;
|
||||
private calculateDuration;
|
||||
private canUserAccessDocument;
|
||||
private canUserSignDocument;
|
||||
private closeProcessDetails;
|
||||
private removeNotification;
|
||||
private renderNotifications;
|
||||
private updateNotificationBadge;
|
||||
private addNotification;
|
||||
private sendMessage;
|
||||
private showProcessDetails;
|
||||
private scrollToBottom;
|
||||
private loadMemberChat;
|
||||
private toggleMembers;
|
||||
private toggleRoles;
|
||||
private loadGroupList;
|
||||
private toggleUserList;
|
||||
private switchUser;
|
||||
private updateCurrentUserDisplay;
|
||||
private generateAutoReply;
|
||||
private sendFile;
|
||||
private fileList;
|
||||
private getFileList;
|
||||
private showRoleDocuments;
|
||||
private closeRoleDocuments;
|
||||
private handleFiles;
|
||||
private newRequest;
|
||||
private closeModal;
|
||||
private submitNewDocument;
|
||||
private submitCommonDocument;
|
||||
private submitRequest;
|
||||
private closeNewRequest;
|
||||
private submitDocumentRequest;
|
||||
private confirmSignature;
|
||||
private initializeEventListeners;
|
||||
connectedCallback(): void;
|
||||
}
|
||||
export { SignatureElement };
|
5
ihm_client/dist/types/router.d.ts
vendored
Normal file
5
ihm_client/dist/types/router.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
import '../public/style/4nk.css';
|
||||
export declare let currentRoute: string;
|
||||
export declare function navigate(path: string): Promise<void>;
|
||||
export declare function init(): Promise<void>;
|
||||
export declare function registerAllListeners(): Promise<void>;
|
43
ihm_client/dist/types/services/database.service.d.ts
vendored
Normal file
43
ihm_client/dist/types/services/database.service.d.ts
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
export declare class Database {
|
||||
private static instance;
|
||||
private db;
|
||||
private dbName;
|
||||
private dbVersion;
|
||||
private serviceWorkerRegistration;
|
||||
private messageChannel;
|
||||
private messageChannelForGet;
|
||||
private serviceWorkerCheckIntervalId;
|
||||
private storeDefinitions;
|
||||
private constructor();
|
||||
static getInstance(): Promise<Database>;
|
||||
private init;
|
||||
getDb(): Promise<IDBDatabase>;
|
||||
getStoreList(): {
|
||||
[key: string]: string;
|
||||
};
|
||||
registerServiceWorker(path: string): Promise<void>;
|
||||
private waitForServiceWorkerActivation;
|
||||
private checkForUpdates;
|
||||
private handleServiceWorkerMessage;
|
||||
private handleDownloadList;
|
||||
private handleAddObjectResponse;
|
||||
private handleGetObjectResponse;
|
||||
addObject(payload: {
|
||||
storeName: string;
|
||||
object: any;
|
||||
key: any;
|
||||
}): Promise<void>;
|
||||
batchWriting(payload: {
|
||||
storeName: string;
|
||||
objects: {
|
||||
key: any;
|
||||
object: any;
|
||||
}[];
|
||||
}): Promise<void>;
|
||||
getObject(storeName: string, key: string): Promise<any | null>;
|
||||
dumpStore(storeName: string): Promise<Record<string, any>>;
|
||||
deleteObject(storeName: string, key: string): Promise<void>;
|
||||
clearStore(storeName: string): Promise<void>;
|
||||
requestStoreByIndex(storeName: string, indexName: string, request: string): Promise<any[]>;
|
||||
}
|
||||
export default Database;
|
28
ihm_client/dist/types/services/modal.service.d.ts
vendored
Normal file
28
ihm_client/dist/types/services/modal.service.d.ts
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
import type { RoleDefinition } from 'pkg/sdk_client';
|
||||
interface ConfirmationModalOptions {
|
||||
title: string;
|
||||
content: string;
|
||||
confirmText?: string;
|
||||
cancelText?: string;
|
||||
}
|
||||
export default class ModalService {
|
||||
private static instance;
|
||||
private stateId;
|
||||
private processId;
|
||||
private constructor();
|
||||
private paired_addresses;
|
||||
private modal;
|
||||
static getInstance(): Promise<ModalService>;
|
||||
openLoginModal(myAddress: string, receiverAddress: string): void;
|
||||
injectModal(members: any[]): Promise<void>;
|
||||
injectCreationModal(members: any[]): Promise<void>;
|
||||
injectWaitingModal(): Promise<void>;
|
||||
injectValidationModal(processDiff: any): Promise<void>;
|
||||
closeValidationModal(): Promise<void>;
|
||||
openPairingConfirmationModal(roleDefinition: Record<string, RoleDefinition>, processId: string, stateId: string): Promise<void>;
|
||||
confirmLogin(): void;
|
||||
closeLoginModal(): Promise<void>;
|
||||
showConfirmationModal(options: ConfirmationModalOptions, fullscreen?: boolean): Promise<boolean>;
|
||||
closeConfirmationModal(): Promise<void>;
|
||||
}
|
||||
export {};
|
167
ihm_client/dist/types/services/service.d.ts
vendored
Normal file
167
ihm_client/dist/types/services/service.d.ts
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
import type { ApiReturn, Device, Member, MerkleProofResult, Process, ProcessState, RoleDefinition, SecretsStore, UserDiff } from '../../pkg/sdk_client';
|
||||
import { BackUp } from '~/models/backup.model';
|
||||
export declare const U32_MAX = 4294967295;
|
||||
export default class Services {
|
||||
private static initializing;
|
||||
private static instance;
|
||||
private processId;
|
||||
private stateId;
|
||||
private sdkClient;
|
||||
private processesCache;
|
||||
private myProcesses;
|
||||
private notifications;
|
||||
private subscriptions;
|
||||
private database;
|
||||
private routingInstance;
|
||||
private relayAddresses;
|
||||
private membersList;
|
||||
private currentBlockHeight;
|
||||
private constructor();
|
||||
static getInstance(): Promise<Services>;
|
||||
init(): Promise<void>;
|
||||
setProcessId(processId: string | null): void;
|
||||
setStateId(stateId: string | null): void;
|
||||
getProcessId(): string | null;
|
||||
getStateId(): string | null;
|
||||
/**
|
||||
* Calls `this.addWebsocketConnection` for each `wsurl` in relayAddresses.
|
||||
* Waits for at least one handshake message before returning.
|
||||
*/
|
||||
connectAllRelays(): Promise<void>;
|
||||
addWebsocketConnection(url: string): Promise<void>;
|
||||
/**
|
||||
* Add or update a key/value pair in relayAddresses.
|
||||
* @param wsurl - The WebSocket URL (key).
|
||||
* @param spAddress - The SP Address (value).
|
||||
*/
|
||||
updateRelay(wsurl: string, spAddress: string): void;
|
||||
/**
|
||||
* Retrieve the spAddress for a given wsurl.
|
||||
* @param wsurl - The WebSocket URL to look up.
|
||||
* @returns The SP Address if found, or undefined if not.
|
||||
*/
|
||||
getSpAddress(wsurl: string): string | undefined;
|
||||
/**
|
||||
* Get all key/value pairs from relayAddresses.
|
||||
* @returns An array of objects containing wsurl and spAddress.
|
||||
*/
|
||||
getAllRelays(): {
|
||||
wsurl: string;
|
||||
spAddress: string;
|
||||
}[];
|
||||
/**
|
||||
* Print all key/value pairs for debugging.
|
||||
*/
|
||||
printAllRelays(): void;
|
||||
isPaired(): boolean;
|
||||
unpairDevice(): Promise<void>;
|
||||
getSecretForAddress(address: string): Promise<string | null>;
|
||||
getAllSecrets(): Promise<SecretsStore>;
|
||||
getAllDiffs(): Promise<Record<string, UserDiff>>;
|
||||
getDiffByValue(value: string): Promise<UserDiff | null>;
|
||||
private getTokensFromFaucet;
|
||||
checkConnections(members: Member[]): Promise<void>;
|
||||
connectAddresses(addresses: string[]): Promise<ApiReturn>;
|
||||
private ensureSufficientAmount;
|
||||
private waitForAmount;
|
||||
createPairingProcess(userName: string, pairWith: string[]): Promise<ApiReturn>;
|
||||
private isFileBlob;
|
||||
private splitData;
|
||||
createProcess(privateData: Record<string, any>, publicData: Record<string, any>, roles: Record<string, RoleDefinition>): Promise<ApiReturn>;
|
||||
updateProcess(process: Process, privateData: Record<string, any>, publicData: Record<string, any>, roles: Record<string, RoleDefinition> | null): Promise<ApiReturn>;
|
||||
createPrdUpdate(processId: string, stateId: string): Promise<ApiReturn>;
|
||||
createPrdResponse(processId: string, stateId: string): Promise<ApiReturn>;
|
||||
approveChange(processId: string, stateId: string): Promise<ApiReturn>;
|
||||
rejectChange(processId: string, stateId: string): Promise<ApiReturn>;
|
||||
resetDevice(): Promise<void>;
|
||||
sendNewTxMessage(message: string): void;
|
||||
sendCommitMessage(message: string): void;
|
||||
sendCipherMessages(ciphers: string[]): void;
|
||||
sendFaucetMessage(message: string): void;
|
||||
parseCipher(message: string): Promise<void>;
|
||||
parseNewTx(newTxMsg: string): Promise<void>;
|
||||
handleApiReturn(apiReturn: ApiReturn): Promise<void>;
|
||||
openPairingConfirmationModal(processId: string): Promise<void>;
|
||||
confirmPairing(): Promise<void>;
|
||||
updateDevice(): Promise<void>;
|
||||
pairDevice(): Promise<void>;
|
||||
getAmount(): BigInt;
|
||||
getDeviceAddress(): string;
|
||||
dumpDeviceFromMemory(): Device;
|
||||
dumpNeuteredDevice(): Device | null;
|
||||
getPairingProcessId(): string;
|
||||
saveDeviceInDatabase(device: Device): Promise<void>;
|
||||
getDeviceFromDatabase(): Promise<Device | null>;
|
||||
getMemberFromDevice(): Promise<string[] | null>;
|
||||
isChildRole(parent: any, child: any): boolean;
|
||||
rolesContainsUs(roles: Record<string, RoleDefinition>): boolean;
|
||||
rolesContainsMember(roles: Record<string, RoleDefinition>, pairingProcessId: string): boolean;
|
||||
dumpWallet(): Promise<any>;
|
||||
createFaucetMessage(): any;
|
||||
createNewDevice(): Promise<string>;
|
||||
restoreDevice(device: Device): void;
|
||||
updateDeviceBlockHeight(): Promise<void>;
|
||||
private removeProcess;
|
||||
batchSaveProcessesToDb(processes: Record<string, Process>): Promise<void>;
|
||||
saveProcessToDb(processId: string, process: Process): Promise<void>;
|
||||
saveBlobToDb(hash: string, data: Blob): Promise<void>;
|
||||
getBlobFromDb(hash: string): Promise<Blob | null>;
|
||||
saveDataToStorage(hash: string, data: Blob, ttl: number | null): Promise<void>;
|
||||
fetchValueFromStorage(hash: string): Promise<any | null>;
|
||||
testDataInStorage(hash: string): Promise<Record<string, boolean | null> | null>;
|
||||
saveDiffsToDb(diffs: UserDiff[]): Promise<void>;
|
||||
getProcess(processId: string): Promise<Process | null>;
|
||||
getProcesses(): Promise<Record<string, Process>>;
|
||||
restoreProcessesFromBackUp(processes: Record<string, Process>): Promise<void>;
|
||||
restoreProcessesFromDB(): Promise<void>;
|
||||
clearSecretsFromDB(): Promise<void>;
|
||||
restoreSecretsFromBackUp(secretsStore: SecretsStore): Promise<void>;
|
||||
restoreSecretsFromDB(): Promise<void>;
|
||||
decodeValue(value: number[]): any | null;
|
||||
decryptAttribute(processId: string, state: ProcessState, attribute: string): Promise<any | null>;
|
||||
getNotifications(): any[] | null;
|
||||
setNotifications(notifications: any[]): void;
|
||||
importJSON(backup: BackUp): Promise<void>;
|
||||
createBackUp(): Promise<BackUp | null>;
|
||||
device1: boolean;
|
||||
device2Ready: boolean;
|
||||
resetState(): void;
|
||||
handleHandshakeMsg(url: string, parsedMsg: any): Promise<void>;
|
||||
private lookForStateId;
|
||||
/**
|
||||
* Waits for at least one handshake message to be received from any connected relay.
|
||||
* This ensures that the relay addresses are fully populated and the member list is updated.
|
||||
* @returns A promise that resolves when at least one handshake message is received.
|
||||
*/
|
||||
private waitForHandshakeMessage;
|
||||
/**
|
||||
* Retourne la liste de tous les membres ordonnés par leur process id
|
||||
* @returns Un tableau contenant tous les membres
|
||||
*/
|
||||
getAllMembersSorted(): Record<string, Member>;
|
||||
getAllMembers(): Record<string, Member>;
|
||||
getAddressesForMemberId(memberId: string): string[] | null;
|
||||
compareMembers(memberA: string[], memberB: string[]): boolean;
|
||||
handleCommitError(response: string): Promise<void>;
|
||||
getRoles(process: Process): Record<string, RoleDefinition> | null;
|
||||
getPublicData(process: Process): Record<string, any> | null;
|
||||
getProcessName(process: Process): string | null;
|
||||
getMyProcesses(): Promise<string[] | null>;
|
||||
requestDataFromPeers(processId: string, stateIds: string[], roles: Record<string, RoleDefinition>[]): Promise<void>;
|
||||
hexToBlob(hexString: string): Blob;
|
||||
hexToUInt8Array(hexString: string): Uint8Array;
|
||||
blobToHex(blob: Blob): Promise<string>;
|
||||
getHashForFile(commitedIn: string, label: string, fileBlob: {
|
||||
type: string;
|
||||
data: Uint8Array;
|
||||
}): string;
|
||||
getMerkleProofForFile(processState: ProcessState, attributeName: string): MerkleProofResult;
|
||||
validateMerkleProof(proof: MerkleProofResult, hash: string): boolean;
|
||||
getLastCommitedState(process: Process): ProcessState | null;
|
||||
getLastCommitedStateIndex(process: Process): number | null;
|
||||
getUncommitedStates(process: Process): ProcessState[];
|
||||
getStateFromId(process: Process, stateId: string): ProcessState | null;
|
||||
getNextStateAfterId(process: Process, stateId: string): ProcessState | null;
|
||||
isPairingProcess(roles: Record<string, RoleDefinition>): boolean;
|
||||
updateMemberPublicName(process: Process, newName: string): Promise<ApiReturn>;
|
||||
}
|
4
ihm_client/dist/types/services/storage.service.d.ts
vendored
Normal file
4
ihm_client/dist/types/services/storage.service.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
import { AxiosResponse } from 'axios';
|
||||
export declare function storeData(servers: string[], key: string, value: Blob, ttl: number | null): Promise<AxiosResponse | null>;
|
||||
export declare function retrieveData(servers: string[], key: string): Promise<ArrayBuffer | null>;
|
||||
export declare function testData(servers: string[], key: string): Promise<Record<string, boolean | null> | null>;
|
17
ihm_client/dist/types/services/token.d.ts
vendored
Normal file
17
ihm_client/dist/types/services/token.d.ts
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
interface TokenPair {
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
}
|
||||
export default class TokenService {
|
||||
private static instance;
|
||||
private readonly SECRET_KEY;
|
||||
private readonly ACCESS_TOKEN_EXPIRATION;
|
||||
private readonly REFRESH_TOKEN_EXPIRATION;
|
||||
private readonly encoder;
|
||||
private constructor();
|
||||
static getInstance(): Promise<TokenService>;
|
||||
generateSessionToken(origin: string): Promise<TokenPair>;
|
||||
validateToken(token: string, origin: string): Promise<boolean>;
|
||||
refreshAccessToken(refreshToken: string, origin: string): Promise<string | null>;
|
||||
}
|
||||
export {};
|
1
ihm_client/dist/types/utils/document.utils.d.ts
vendored
Normal file
1
ihm_client/dist/types/utils/document.utils.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export declare function getCorrectDOM(componentTag: string): Node;
|
4
ihm_client/dist/types/utils/html.utils.d.ts
vendored
Normal file
4
ihm_client/dist/types/utils/html.utils.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
export declare function interpolate(template: string, data: {
|
||||
[key: string]: string;
|
||||
}): string;
|
||||
export declare function getCorrectDOM(componentTag: string): Node;
|
12
ihm_client/dist/types/utils/messageMock.d.ts
vendored
Normal file
12
ihm_client/dist/types/utils/messageMock.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
declare class MessageStore {
|
||||
private readonly STORAGE_KEY;
|
||||
private messages;
|
||||
constructor();
|
||||
private loadFromLocalStorage;
|
||||
getMessages(): any[];
|
||||
setMessages(messages: any[]): void;
|
||||
private saveToLocalStorage;
|
||||
addMessage(memberId: string | number, message: any): void;
|
||||
}
|
||||
export declare const messageStore: MessageStore;
|
||||
export {};
|
23
ihm_client/dist/types/utils/notification.store.d.ts
vendored
Normal file
23
ihm_client/dist/types/utils/notification.store.d.ts
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
interface INotification {
|
||||
id: number;
|
||||
title: string;
|
||||
description: string;
|
||||
time?: string;
|
||||
memberId?: string;
|
||||
}
|
||||
declare class NotificationStore {
|
||||
private static instance;
|
||||
private notifications;
|
||||
private constructor();
|
||||
static getInstance(): NotificationStore;
|
||||
addNotification(notification: INotification): void;
|
||||
removeNotification(index: number): void;
|
||||
getNotifications(): INotification[];
|
||||
private saveToLocalStorage;
|
||||
private loadFromLocalStorage;
|
||||
private updateUI;
|
||||
private renderNotificationBoard;
|
||||
refreshNotifications(): void;
|
||||
}
|
||||
export declare const notificationStore: NotificationStore;
|
||||
export {};
|
5
ihm_client/dist/types/utils/service.utils.d.ts
vendored
Normal file
5
ihm_client/dist/types/utils/service.utils.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
export declare function splitPrivateData(data: Record<string, any>, privateFields: string[]): {
|
||||
privateData: Record<string, any>;
|
||||
publicData: Record<string, any>;
|
||||
};
|
||||
export declare function isValid32ByteHex(value: string): boolean;
|
8
ihm_client/dist/types/utils/sp-address.utils.d.ts
vendored
Normal file
8
ihm_client/dist/types/utils/sp-address.utils.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
export declare function copyToClipboard(fullAddress: string): Promise<void>;
|
||||
export declare function generateEmojiList(): string[];
|
||||
export declare function addressToEmoji(text: string): Promise<string>;
|
||||
export declare function displayEmojis(text: string): Promise<void>;
|
||||
export declare function initAddressInput(): void;
|
||||
export declare function prepareAndSendPairingTx(): Promise<void>;
|
||||
export declare function generateQRCode(spAddress: string): Promise<void>;
|
||||
export declare function generateCreateBtn(): Promise<void>;
|
2
ihm_client/dist/types/utils/subscription.utils.d.ts
vendored
Normal file
2
ihm_client/dist/types/utils/subscription.utils.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
export declare function cleanSubscriptions(): void;
|
||||
export declare function addSubscription(element: Element | Document, event: any, eventHandler: EventListenerOrEventListenerObject): void;
|
5
ihm_client/dist/types/websockets.d.ts
vendored
Normal file
5
ihm_client/dist/types/websockets.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
import type { AnkFlag } from 'pkg/sdk_client';
|
||||
export declare function initWebsocket(url: string): Promise<void>;
|
||||
export declare function sendMessage(flag: AnkFlag, message: string): void;
|
||||
export declare function getUrl(): string;
|
||||
export declare function close(): void;
|
@ -1,96 +0,0 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
# Gestion des fichiers statiques
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
|
||||
# Headers de sécurité
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
}
|
||||
|
||||
# Proxy vers sdk_relay WebSocket
|
||||
location /ws/ {
|
||||
proxy_pass http://sdk_relay_1: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_read_timeout 86400;
|
||||
proxy_send_timeout 86400;
|
||||
}
|
||||
|
||||
# Proxy vers sdk_relay HTTP API
|
||||
location /api/ {
|
||||
proxy_pass http://sdk_relay_1: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;
|
||||
|
||||
# Gestion des requêtes OPTIONS
|
||||
if ($request_method = 'OPTIONS') {
|
||||
add_header Access-Control-Allow-Origin "*";
|
||||
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE";
|
||||
add_header Access-Control-Allow-Headers "Authorization,Content-Type,Accept,X-Requested-With";
|
||||
add_header Content-Length 0;
|
||||
add_header Content-Type text/plain;
|
||||
return 204;
|
||||
}
|
||||
}
|
||||
|
||||
# Proxy vers Bitcoin Core RPC (si nécessaire)
|
||||
location /bitcoin/ {
|
||||
proxy_pass http://bitcoin:18443/;
|
||||
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;
|
||||
|
||||
# Authentification basique pour Bitcoin RPC
|
||||
auth_basic "Bitcoin RPC";
|
||||
auth_basic_user_file /etc/nginx/.htpasswd;
|
||||
}
|
||||
|
||||
# Proxy vers Blindbit (si nécessaire)
|
||||
location /blindbit/ {
|
||||
proxy_pass http://blindbit:8000/;
|
||||
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;
|
||||
}
|
||||
|
||||
# Cache pour les assets statiques
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
# Gestion des erreurs
|
||||
error_page 404 /index.html;
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
|
||||
# Logs
|
||||
access_log /var/log/nginx/ihm_client_access.log;
|
||||
error_log /var/log/nginx/ihm_client_error.log;
|
||||
}
|
1
ihm_client/node_modules/.bin/acorn
generated
vendored
Symbolic link
1
ihm_client/node_modules/.bin/acorn
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../acorn/bin/acorn
|
1
ihm_client/node_modules/.bin/ansi-html
generated
vendored
Symbolic link
1
ihm_client/node_modules/.bin/ansi-html
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../ansi-html-community/bin/ansi-html
|
1
ihm_client/node_modules/.bin/browserslist
generated
vendored
Symbolic link
1
ihm_client/node_modules/.bin/browserslist
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../browserslist/cli.js
|
1
ihm_client/node_modules/.bin/ejs
generated
vendored
Symbolic link
1
ihm_client/node_modules/.bin/ejs
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../ejs/bin/cli.js
|
1
ihm_client/node_modules/.bin/envinfo
generated
vendored
Symbolic link
1
ihm_client/node_modules/.bin/envinfo
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../envinfo/dist/cli.js
|
1
ihm_client/node_modules/.bin/esbuild
generated
vendored
Symbolic link
1
ihm_client/node_modules/.bin/esbuild
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../esbuild/bin/esbuild
|
1
ihm_client/node_modules/.bin/flat
generated
vendored
Symbolic link
1
ihm_client/node_modules/.bin/flat
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../flat/cli.js
|
1
ihm_client/node_modules/.bin/glob
generated
vendored
Symbolic link
1
ihm_client/node_modules/.bin/glob
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../glob/dist/esm/bin.mjs
|
1
ihm_client/node_modules/.bin/he
generated
vendored
Symbolic link
1
ihm_client/node_modules/.bin/he
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../he/bin/he
|
1
ihm_client/node_modules/.bin/html-minifier-terser
generated
vendored
Symbolic link
1
ihm_client/node_modules/.bin/html-minifier-terser
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../html-minifier-terser/cli.js
|
1
ihm_client/node_modules/.bin/import-local-fixture
generated
vendored
Symbolic link
1
ihm_client/node_modules/.bin/import-local-fixture
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../import-local/fixtures/cli.js
|
1
ihm_client/node_modules/.bin/is-docker
generated
vendored
Symbolic link
1
ihm_client/node_modules/.bin/is-docker
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../is-docker/cli.js
|
1
ihm_client/node_modules/.bin/is-inside-container
generated
vendored
Symbolic link
1
ihm_client/node_modules/.bin/is-inside-container
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../is-inside-container/cli.js
|
1
ihm_client/node_modules/.bin/jake
generated
vendored
Symbolic link
1
ihm_client/node_modules/.bin/jake
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../jake/bin/cli.js
|
1
ihm_client/node_modules/.bin/jsesc
generated
vendored
Symbolic link
1
ihm_client/node_modules/.bin/jsesc
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../jsesc/bin/jsesc
|
1
ihm_client/node_modules/.bin/json5
generated
vendored
Symbolic link
1
ihm_client/node_modules/.bin/json5
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../json5/lib/cli.js
|
1
ihm_client/node_modules/.bin/mime
generated
vendored
Symbolic link
1
ihm_client/node_modules/.bin/mime
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../mime/cli.js
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user