ci: docker_tag=ext feat(front): env build args + ID.Not flow fixes
Some checks failed
build-and-push-ext / build_push (push) Failing after 6s

This commit is contained in:
Debian Dev4 2025-09-23 15:22:16 +00:00
parent 8d5e32fb79
commit f659362682
6 changed files with 327 additions and 28 deletions

View File

@ -93,6 +93,8 @@ ARG NEXT_PUBLIC_4NK_IFRAME_URL
ARG NEXT_PUBLIC_API_URL
ARG NEXT_PUBLIC_DEFAULT_VALIDATOR_ID
ARG NEXT_PUBLIC_DEFAULT_STORAGE_URLS
ARG NEXT_PUBLIC_BACK_BASE
ARG NEXT_PUBLIC_IDNOT_REDIRECT_URI_FIXED
ENV NEXT_PUBLIC_BACK_API_PROTOCOL=${NEXT_PUBLIC_BACK_API_PROTOCOL} \
NEXT_PUBLIC_BACK_API_HOST=${NEXT_PUBLIC_BACK_API_HOST} \
@ -112,7 +114,9 @@ ENV NEXT_PUBLIC_BACK_API_PROTOCOL=${NEXT_PUBLIC_BACK_API_PROTOCOL} \
NEXT_PUBLIC_4NK_IFRAME_URL=${NEXT_PUBLIC_4NK_IFRAME_URL} \
NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL} \
NEXT_PUBLIC_DEFAULT_VALIDATOR_ID=${NEXT_PUBLIC_DEFAULT_VALIDATOR_ID} \
NEXT_PUBLIC_DEFAULT_STORAGE_URLS=${NEXT_PUBLIC_DEFAULT_STORAGE_URLS}
NEXT_PUBLIC_DEFAULT_STORAGE_URLS=${NEXT_PUBLIC_DEFAULT_STORAGE_URLS} \
NEXT_PUBLIC_BACK_BASE=${NEXT_PUBLIC_BACK_BASE} \
NEXT_PUBLIC_IDNOT_REDIRECT_URI_FIXED=${NEXT_PUBLIC_IDNOT_REDIRECT_URI_FIXED}
RUN --mount=type=cache,target=/leCoffre-front/.next/cache npm run build
@ -153,6 +157,8 @@ ARG NEXT_PUBLIC_4NK_IFRAME_URL
ARG NEXT_PUBLIC_API_URL
ARG NEXT_PUBLIC_DEFAULT_VALIDATOR_ID
ARG NEXT_PUBLIC_DEFAULT_STORAGE_URLS
ARG NEXT_PUBLIC_BACK_BASE
ARG NEXT_PUBLIC_IDNOT_REDIRECT_URI_FIXED
ENV NODE_ENV=production \
PORT=3000 \
@ -174,7 +180,9 @@ ENV NODE_ENV=production \
NEXT_PUBLIC_4NK_IFRAME_URL=${NEXT_PUBLIC_4NK_IFRAME_URL} \
NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL} \
NEXT_PUBLIC_DEFAULT_VALIDATOR_ID=${NEXT_PUBLIC_DEFAULT_VALIDATOR_ID} \
NEXT_PUBLIC_DEFAULT_STORAGE_URLS=${NEXT_PUBLIC_DEFAULT_STORAGE_URLS}
NEXT_PUBLIC_DEFAULT_STORAGE_URLS=${NEXT_PUBLIC_DEFAULT_STORAGE_URLS} \
NEXT_PUBLIC_BACK_BASE=${NEXT_PUBLIC_BACK_BASE} \
NEXT_PUBLIC_IDNOT_REDIRECT_URI_FIXED=${NEXT_PUBLIC_IDNOT_REDIRECT_URI_FIXED}
# Next.js standalone runtime (output: 'standalone')
COPY --from=builder /leCoffre-front/.next/standalone ./

View File

@ -0,0 +1,15 @@
# HTTP server for ACME and redirect to HTTPS
server {
listen 80;
server_name dev4.4nkweb.com;
# ACME HTTP-01 challenges
location /.well-known/acme-challenge/ {
root /var/www/letsencrypt;
}
# Redirection vers HTTPS pour toutes les autres requêtes
location / {
return 301 https://$server_name$request_uri;
}
}

View File

@ -0,0 +1,221 @@
# Configuration HTTPS pour dev4.4nkweb.com
server {
listen 443 ssl http2;
server_name dev4.4nkweb.com;
# Certificats SSL
ssl_certificate /etc/letsencrypt/live/dev4.4nkweb.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dev4.4nkweb.com/privkey.pem;
# Configuration SSL
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:ECDHE-RSA-AES256-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Headers de sécurité
add_header Strict-Transport-Security "max-age=63072000" always;
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
# Grafana - Interface de monitoring (DOIT être avant location /)
location /grafana/ {
proxy_pass http://localhost:3005/;
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;
# Configuration spécifique pour Grafana
proxy_set_header X-Grafana-Org-Id 1;
# Support des WebSockets pour les live updates
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Buffer settings
proxy_buffering off;
proxy_request_buffering off;
}
# Loki API - API de logs (DOIT être avant location /)
location /loki/ {
proxy_pass http://localhost:3100/;
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 pour les requêtes depuis Grafana
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type, Authorization";
if ($request_method = 'OPTIONS') {
return 204;
}
}
# Page de statut des services (DOIT être avant location /)
location /status {
# Redirection vers /status/
return 301 /status/;
}
location /status/ {
# Serveur statique pour la page HTML
alias /var/www/lecoffre/status/;
index index.html;
try_files $uri $uri/ /status/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;
# Cache pour les assets statiques
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg)$ {
expires 1h;
add_header Cache-Control "public, immutable";
}
}
# API de statut des services (DOIT être avant location /)
location /status/api {
proxy_pass http://localhost:3006/api;
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 pour les requêtes AJAX
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type, Authorization";
# Timeouts
proxy_connect_timeout 10s;
proxy_send_timeout 10s;
proxy_read_timeout 10s;
if ($request_method = 'OPTIONS') {
return 204;
}
}
# API backend - route /back/ vers /api/ du backend
location ~* ^/back/(.*)$ {
proxy_pass http://localhost:8080/api/$1;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";
proxy_buffering off;
}
# API direct - route /api/ vers le backend
# Autorisations CORS dynamiques pour origines connues
set $cors_origin "";
if ($http_origin ~* ^(http://local\.4nkweb\.com:3000|https://dev4\.4nkweb\.com)$) {
set $cors_origin $http_origin;
}
location /api/ {
# CORS pour développement local Next.js
proxy_hide_header Access-Control-Allow-Origin;
proxy_hide_header Access-Control-Allow-Credentials;
proxy_hide_header Access-Control-Allow-Headers;
proxy_hide_header Access-Control-Allow-Methods;
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin $cors_origin always;
add_header Access-Control-Allow-Credentials "true" always;
add_header Access-Control-Allow-Headers "Content-Type, x-session-id, Authorization" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
return 204;
}
add_header Access-Control-Allow-Origin $cors_origin always;
add_header Access-Control-Allow-Credentials "true" always;
add_header Access-Control-Allow-Headers "Content-Type, x-session-id, Authorization" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
proxy_pass http://dev3.4nkweb.com:8080/api/;
include /etc/nginx/proxy_params;
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_send_timeout 300;
}
# WebSocket relay (sdk_relay)
location /ws/ {
proxy_pass http://localhost:8090/;
proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key;
proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version;
proxy_set_header Sec-WebSocket-Protocol $http_sec_websocket_protocol;
proxy_set_header Sec-WebSocket-Extensions $http_sec_websocket_extensions;
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
# API de transfert de fonds
location /api/v1/funds/ {
proxy_pass http://dev3.4nkweb.com:8080/api/v1/funds/;
include /etc/nginx/proxy_params;
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_send_timeout 300;
}
# favicon
location = /favicon.ico {
root /home/debian/lecoffre_node/conf/nginx/assets;
try_files /favicon.ico =404;
}
# blindbit
location /blindbit/ {
proxy_pass http://localhost:8000/;
include /etc/nginx/proxy_params;
}
# signer (sdk_signer) avec support WebSocket
# lecoffre-front - Application LeCoffre
location /lecoffre {
proxy_pass http://localhost:3004;
include /etc/nginx/proxy_params;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 300;
proxy_send_timeout 300;
proxy_connect_timeout 300;
}
# ihm_client (root) - DOIT être en dernier
location / {
proxy_pass http://localhost:3003;
include /etc/nginx/proxy_params;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 300;
}
}

View File

@ -0,0 +1,64 @@
server {
listen 0.0.0.0:3000;
listen [::]:3000;
server_name local.4nkweb.com;
# HTTP pur: pas de HTTPS ni HSTS
# Favicon
location = /favicon.ico {
root /home/debian/lecoffre_node/conf/nginx/assets;
}
# Compat: callback ID.not sans basePath (toutes variantes et querystring)
location /authorized-client {
proxy_pass http://127.0.0.2:3004/lecoffre/authorized-client;
include /etc/nginx/proxy_params;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto http;
proxy_set_header X-Forwarded-Prefix /lecoffre;
proxy_read_timeout 300;
}
# Entrée sans slash
location = /lecoffre {
proxy_pass http://127.0.0.2:3004;
include /etc/nginx/proxy_params;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto http;
proxy_set_header X-Forwarded-Prefix /lecoffre;
proxy_read_timeout 300;
}
# BasePath /lecoffre
location /lecoffre/ {
proxy_pass http://127.0.0.2:3004;
include /etc/nginx/proxy_params;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto http;
proxy_set_header X-Forwarded-Prefix /lecoffre;
proxy_read_timeout 300;
}
# HMR (si utilisé en local)
location /lecoffre/_next/webpack-hmr {
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-Forwarded-Proto http;
proxy_buffering off;
proxy_pass http://127.0.0.2:3004/lecoffre/_next/webpack-hmr;
proxy_read_timeout 600s;
}
# Assets Next.js
location ~* ^(/_next/static/|/lecoffre/_next/static/|/.+\.(?:css|js|png|jpg|jpeg|gif|svg|ico|webp|woff2?))$ {
expires 7d;
add_header Cache-Control "public, max-age=604800, immutable" always;
proxy_pass http://127.0.0.2:3004$request_uri;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto http;
proxy_read_timeout 300;
}
}

View File

@ -0,0 +1,9 @@
server {
listen 80;
server_name local.4nkweb.com;
# HTTP only: pas de redirection HTTPS, pas d'HSTS
location / {
return 302 http://local.4nkweb.com:3000$request_uri;
}
}

View File

@ -53,22 +53,24 @@ export default function StepEmail(props: IProps) {
const variables = FrontendVariables.getInstance();
try {
const nextUrl = typeof window !== 'undefined' ? `${window.location.origin}/authorized-client` : `${variables.FRONT_APP_HOST}/authorized-client`;
const backBase = variables.BACK_BASE || `${variables.BACK_API_PROTOCOL}://${variables.BACK_API_HOST}${variables.BACK_API_PORT ? `:${variables.BACK_API_PORT}` : ''}`;
const stateEndpoint = new URL(`/api/v1/idnot/state`, backBase);
const resp = await fetch(stateEndpoint.toString(), {
let backBase = variables.BACK_BASE || (process.env.NEXT_PUBLIC_BACK_BASE as string) || `${variables.BACK_API_PROTOCOL}://${variables.BACK_API_HOST}${variables.BACK_API_PORT ? `:${variables.BACK_API_PORT}` : ''}`;
if (!backBase || !/^https?:\/\//i.test(backBase)) {
console.warn('[IDNOT] BACK_BASE invalid or missing, falling back to https://dev3.4nkweb.com');
backBase = 'https://dev3.4nkweb.com';
}
const stateEndpoint = `${backBase.replace(/\/$/, '')}/api/v1/idnot/state`;
const resp = await fetch(stateEndpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ next_url: nextUrl })
});
if (!resp.ok) {
console.error('[IDNOT] Failed to create state', resp.status);
setIsErrorModalOpen(4);
return;
}
const { state } = await resp.json();
if (!state) {
console.warn('[IDNOT] Backend returned empty state');
setIsErrorModalOpen(4);
return;
}
const fixedRedirect = variables.IDNOT_REDIRECT_URI_FIXED || 'http://local.4nkweb.com:3000/authorized-client';
@ -79,7 +81,6 @@ export default function StepEmail(props: IProps) {
router.push(authorizeUrl);
} catch (e) {
console.error('[IDNOT] Unexpected error while starting login', e);
setIsErrorModalOpen(4);
}
}, [router, setIsErrorModalOpen]);
@ -193,26 +194,7 @@ export default function StepEmail(props: IProps) {
</a>
</div>
</Confirm>
<Confirm
isOpen={isErrorModalOpen === 4}
onClose={closeErrorModal}
showCancelButton={false}
onAccept={closeErrorModal}
closeBtn
header={"Connexion à ID.Not impossible"}
confirmText={"Fermer"}>
<div className={classes["modal-content"]}>
<Typography typo={ETypo.TEXT_MD_REGULAR} className={classes["text"]}>
Notre partenaire ID.Not rencontre actuellement un problème technique. Nous vous tiendrons informé de l'évolution.
Pour toute question, contactez-nous à support@lecoffre.io.
</Typography>
<a className={classes["modal-button"]} href="mailto:support@lecoffre.io" target="_blank">
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.COLOR_SECONDARY_500} className={classes["button-text"]}>
Contactez le support
</Typography>
</a>
</div>
</Confirm>
{/* Outage modal intentionally removed to restore normal API usage */}
{/* <Confirm
isOpen={isErrorModalOpen === 4}
onClose={closeErrorModal}