chore: add waf
This commit is contained in:
@@ -139,6 +139,23 @@ func UpdateMyProfile(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetMyProfile retourne le profil du client connecté
|
||||||
|
// GET /api/v1/profile
|
||||||
|
func GetMyProfile(c *gin.Context) {
|
||||||
|
database := c.MustGet("database").(*db.Database)
|
||||||
|
username, exists := c.Get("username")
|
||||||
|
if !exists {
|
||||||
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
client, err := database.GetClientByUsername(username.(string))
|
||||||
|
if err != nil || client == nil {
|
||||||
|
c.JSON(http.StatusNotFound, gin.H{"error": "Client non trouvé"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, gin.H{"success": true, "client": sanitizeClient(client)})
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// MODIFICATION PROFIL CLIENT (PAR ADMIN)
|
// MODIFICATION PROFIL CLIENT (PAR ADMIN)
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|||||||
@@ -101,8 +101,9 @@ func SetupRoutes(router *gin.Engine, database *db.Database, geoService *services
|
|||||||
cartGroupV1.POST("/push-token", handlers.RegisterPushToken)
|
cartGroupV1.POST("/push-token", handlers.RegisterPushToken)
|
||||||
cartGroupV1.DELETE("/push-token", handlers.UnregisterPushToken)
|
cartGroupV1.DELETE("/push-token", handlers.UnregisterPushToken)
|
||||||
|
|
||||||
// 👤 PROFIL CLIENT - MODIFICATION PAR LE CLIENT
|
// 👤 PROFIL CLIENT
|
||||||
cartGroupV1.PUT("/profile/update", handlers.UpdateMyProfile) // ✅ Modifier mon profil
|
cartGroupV1.GET("/profile", handlers.GetMyProfile) // ✅ Récupérer mon profil
|
||||||
|
cartGroupV1.PUT("/profile/update", handlers.UpdateMyProfile) // ✅ Modifier mon profil
|
||||||
|
|
||||||
// 🎁 PARRAINAGE CLIENT
|
// 🎁 PARRAINAGE CLIENT
|
||||||
cartGroupV1.GET("/referral/balance", handlers.GetMyReferralBalance)
|
cartGroupV1.GET("/referral/balance", handlers.GetMyReferralBalance)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ WORKDIR /app
|
|||||||
RUN apk add --no-cache git ca-certificates tzdata gcc musl-dev
|
RUN apk add --no-cache git ca-certificates tzdata gcc musl-dev
|
||||||
|
|
||||||
# Copier go mod files
|
# Copier go mod files
|
||||||
COPY backend/backend/gestion/go.mod backend/backend/gestion/go.sum ./
|
COPY backend/gestion/go.mod backend/gestion/go.sum ./
|
||||||
|
|
||||||
# Configurer Go et télécharger les dépendances
|
# Configurer Go et télécharger les dépendances
|
||||||
ENV GOPROXY=https://proxy.golang.org,direct
|
ENV GOPROXY=https://proxy.golang.org,direct
|
||||||
@@ -16,7 +16,7 @@ ENV CGO_ENABLED=0
|
|||||||
RUN go mod download
|
RUN go mod download
|
||||||
|
|
||||||
# Copier tout le code source
|
# Copier tout le code source
|
||||||
COPY backend/backend/gestion/ .
|
COPY backend/gestion/ .
|
||||||
|
|
||||||
# Build le binaire
|
# Build le binaire
|
||||||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
|
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
|
||||||
@@ -26,7 +26,7 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
|
|||||||
# =========================================================
|
# =========================================================
|
||||||
# Stage 2: Runtime
|
# Stage 2: Runtime
|
||||||
# =========================================================
|
# =========================================================
|
||||||
FROM alpine:latest
|
FROM alpine:latest AS runtime
|
||||||
|
|
||||||
# Installer les dépendances runtime
|
# Installer les dépendances runtime
|
||||||
RUN apk --no-cache add ca-certificates tzdata wget
|
RUN apk --no-cache add ca-certificates tzdata wget
|
||||||
@@ -55,3 +55,30 @@ USER app
|
|||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
|
||||||
ENTRYPOINT ["./entrypoint.sh"]
|
ENTRYPOINT ["./entrypoint.sh"]
|
||||||
|
|
||||||
|
# =========================================================
|
||||||
|
# Stage 3: WAF (Nginx + ModSecurity)
|
||||||
|
# =========================================================
|
||||||
|
FROM owasp/modsecurity-crs:nginx-alpine AS waf
|
||||||
|
|
||||||
|
USER root
|
||||||
|
|
||||||
|
# Logs ModSecurity
|
||||||
|
RUN mkdir -p /var/log/modsec && chown -R nginx:nginx /var/log/modsec
|
||||||
|
|
||||||
|
# Certificats SSL
|
||||||
|
RUN mkdir -p /etc/nginx/certs
|
||||||
|
COPY docker/backend/certs/cert.pem /etc/nginx/certs/cert.pem
|
||||||
|
COPY docker/backend/certs/key.pem /etc/nginx/certs/key.pem
|
||||||
|
RUN chown -R nginx:nginx /etc/nginx/certs && chmod 640 /etc/nginx/certs/key.pem
|
||||||
|
|
||||||
|
COPY docker/backend/nginx.conf /etc/nginx/conf.d/app.conf
|
||||||
|
COPY docker/backend/custom-rules.conf /etc/nginx/modsec/custom-rules.conf
|
||||||
|
RUN echo "Include /etc/nginx/modsec/custom-rules.conf" > /etc/nginx/modsec/custom-includes.conf
|
||||||
|
|
||||||
|
RUN rm -f /etc/nginx/templates/conf.d/default.conf.template || true
|
||||||
|
RUN chown -R nginx:nginx /usr/share/nginx/html
|
||||||
|
|
||||||
|
USER nginx
|
||||||
|
EXPOSE 80 443
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
# =========================================================
|
||||||
|
# Request ID for correlation
|
||||||
|
# =========================================================
|
||||||
|
map $http_x_request_id $req_id {
|
||||||
|
default $http_x_request_id;
|
||||||
|
"" $request_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
# =========================================================
|
||||||
|
# Backend interne (réseau Docker)
|
||||||
|
# =========================================================
|
||||||
|
upstream backend {
|
||||||
|
server backend:8080;
|
||||||
|
keepalive 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
# =========================================================
|
||||||
|
# HTTP → HTTPS redirect
|
||||||
|
# =========================================================
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name 5.181.0.112.nip.io;
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
# =========================================================
|
||||||
|
# HTTPS Server (WAF)
|
||||||
|
# =========================================================
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
listen [::]:443 ssl;
|
||||||
|
server_name 5.181.0.112.nip.io;
|
||||||
|
|
||||||
|
ssl_certificate /etc/nginx/certs/cert.pem;
|
||||||
|
ssl_certificate_key /etc/nginx/certs/key.pem;
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
|
||||||
|
client_max_body_size 10M;
|
||||||
|
|
||||||
|
modsecurity on;
|
||||||
|
modsecurity_rules_file /etc/nginx/modsec/custom-rules.conf;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
limit_except GET POST PUT PATCH DELETE OPTIONS { deny all; }
|
||||||
|
|
||||||
|
if ($request_method = 'OPTIONS') {
|
||||||
|
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
|
||||||
|
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, PATCH, DELETE, OPTIONS' always;
|
||||||
|
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Request-ID' always;
|
||||||
|
add_header 'Access-Control-Allow-Credentials' 'true' always;
|
||||||
|
add_header 'Access-Control-Max-Age' 86400 always;
|
||||||
|
add_header 'Content-Length' 0;
|
||||||
|
add_header 'Content-Type' 'text/plain charset=UTF-8';
|
||||||
|
return 204;
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy_pass http://backend;
|
||||||
|
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 X-Request-ID $req_id;
|
||||||
|
proxy_set_header Connection "";
|
||||||
|
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
location ~ /\. {
|
||||||
|
deny all;
|
||||||
|
access_log off;
|
||||||
|
log_not_found off;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* (\.env|\.git|package\.json|package-lock\.json|yarn\.lock|Dockerfile|docker-compose\.yml)$ {
|
||||||
|
deny all;
|
||||||
|
access_log off;
|
||||||
|
log_not_found off;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: ..
|
context: ..
|
||||||
dockerfile: docker/backend/Dockerfile
|
dockerfile: docker/backend/Dockerfile
|
||||||
|
target: runtime
|
||||||
container_name: gestion-backend
|
container_name: gestion-backend
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
@@ -26,8 +27,7 @@ services:
|
|||||||
- TOMTOM_API_KEY=${TOMTOM_API_KEY}
|
- TOMTOM_API_KEY=${TOMTOM_API_KEY}
|
||||||
- API_PORT=${API_PORT:-8080}
|
- API_PORT=${API_PORT:-8080}
|
||||||
volumes:
|
volumes:
|
||||||
# ✅ Volume partagé pour les uploads (même volume que le frontend)
|
- backend_uploads:/app/uploads
|
||||||
- frontend_uploads:/app/uploads
|
|
||||||
networks:
|
networks:
|
||||||
- gestion-network
|
- gestion-network
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -37,28 +37,29 @@ services:
|
|||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
# Frontend Nginx + ModSecurity
|
# WAF (Nginx + ModSecurity)
|
||||||
# =========================================================
|
# =========================================================
|
||||||
frontend:
|
waf:
|
||||||
build:
|
build:
|
||||||
context: ..
|
context: ..
|
||||||
dockerfile: docker/frontend/Dockerfile
|
dockerfile: docker/backend/Dockerfile
|
||||||
container_name: gestion-frontend
|
target: waf
|
||||||
|
container_name: gestion-waf
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
- DISABLE_MODSEC_ENV_SUBST=true
|
- DISABLE_MODSEC_ENV_SUBST=true
|
||||||
- PARANOIA=2
|
- PARANOIA=2
|
||||||
- ANOMALY_INBOUND=5
|
- ANOMALY_INBOUND=5
|
||||||
- ANOMALY_OUTBOUND=4
|
- ANOMALY_OUTBOUND=4
|
||||||
- BACKEND_HOST=backend
|
|
||||||
- BACKEND_PORT=${API_PORT:-8080}
|
|
||||||
ports:
|
ports:
|
||||||
- "80:80"
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
volumes:
|
volumes:
|
||||||
# ✅ Volume partagé pour les uploads (accessible via nginx)
|
- backend_uploads:/usr/share/nginx/html/uploads:ro
|
||||||
- frontend_uploads:/usr/share/nginx/html/uploads
|
|
||||||
networks:
|
networks:
|
||||||
- gestion-network
|
- gestion-network
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
# PostgreSQL
|
# PostgreSQL
|
||||||
@@ -132,6 +133,5 @@ volumes:
|
|||||||
driver: local
|
driver: local
|
||||||
redis_data:
|
redis_data:
|
||||||
driver: local
|
driver: local
|
||||||
# ✅ Volume partagé entre backend et frontend
|
backend_uploads:
|
||||||
frontend_uploads:
|
|
||||||
driver: local
|
driver: local
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
# =========================================================
|
|
||||||
# Stage 1: Build Frontend
|
|
||||||
# =========================================================
|
|
||||||
FROM node:20-alpine AS builder
|
|
||||||
|
|
||||||
WORKDIR /build
|
|
||||||
|
|
||||||
# Copier package files depuis frontend-prep
|
|
||||||
COPY frontend/frontend-prep/package*.json ./
|
|
||||||
|
|
||||||
# Installer les dépendances
|
|
||||||
RUN npm ci
|
|
||||||
|
|
||||||
# Copier le code source
|
|
||||||
COPY frontend/frontend-prep/ .
|
|
||||||
|
|
||||||
# Build
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
# =========================================================
|
|
||||||
# Stage 2: Nginx + ModSecurity
|
|
||||||
# =========================================================
|
|
||||||
FROM owasp/modsecurity-crs:nginx-alpine
|
|
||||||
|
|
||||||
USER root
|
|
||||||
|
|
||||||
# Copier build frontend
|
|
||||||
COPY --from=builder /build/dist /usr/share/nginx/html
|
|
||||||
|
|
||||||
#COPY docker/frontend/cert/cert.pem /etc/nginx/certs/cert.pem
|
|
||||||
#COPY docker/frontend/cert/key.pem /etc/nginx/certs/key.pem
|
|
||||||
#RUN chown root:nginx /etc/nginx/certs/cert.pem /etc/nginx/certs/key.pem && \
|
|
||||||
# chmod 644 /etc/nginx/certs/cert.pem && \
|
|
||||||
# chmod 640 /etc/nginx/certs/key.pem
|
|
||||||
|
|
||||||
# Logs ModSecurity
|
|
||||||
RUN mkdir -p /var/log/modsec && chown -R nginx:nginx /var/log/modsec
|
|
||||||
|
|
||||||
COPY docker/frontend/nginx.conf /etc/nginx/conf.d/app.conf
|
|
||||||
COPY docker/frontend/custom-rules.conf /etc/nginx/modsec/custom-rules.conf
|
|
||||||
RUN echo "Include /etc/nginx/modsec/custom-rules.conf" > /etc/nginx/modsec/custom-includes.conf
|
|
||||||
|
|
||||||
RUN rm -f /etc/nginx/templates/conf.d/default.conf.template || true
|
|
||||||
RUN chown -R nginx:nginx /usr/share/nginx/html
|
|
||||||
|
|
||||||
USER nginx
|
|
||||||
EXPOSE 80
|
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIECjCCAnKgAwIBAgIQQesYDZxq7zMlKT1zztYmUDANBgkqhkiG9w0BAQsFADBh
|
|
||||||
MR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExGzAZBgNVBAsMEnhvcl9m
|
|
||||||
YWtlcnNAQXN1c1hvcjEiMCAGA1UEAwwZbWtjZXJ0IHhvcl9mYWtlcnNAQXN1c1hv
|
|
||||||
cjAeFw0yNjAxMjAwODQxNDhaFw0yODA0MjAwNzQxNDhaMEYxJzAlBgNVBAoTHm1r
|
|
||||||
Y2VydCBkZXZlbG9wbWVudCBjZXJ0aWZpY2F0ZTEbMBkGA1UECwwSeG9yX2Zha2Vy
|
|
||||||
c0BBc3VzWG9yMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4gjHuXBb
|
|
||||||
eRVHf29Lsn1JlFSHpSTsImMrjLHnUh0jCR+1i2xQ3GQVFJY8YLWvwJv64SnsDZBE
|
|
||||||
JBbSdsocfmJJl8mnW8INYgLqFBe/Cr/DFZqJcAcANVuxzjVpmWBqvLA3fYPKJHB3
|
|
||||||
66Lot6QZoObbvuOJpar+PubAiNVH6F/0ehy4O5daegfUlGxdZOTRsVhV8uwjH9+H
|
|
||||||
V8wL9ZyK8h6kl9VjQifP/FTdpaGhtkSoVHod/uynmVzF/PscTcUVwh+uQcqWj3fd
|
|
||||||
Itzcinj8K46xZLiFp/QHoz1kX/mDLtwbxbDAD9kGxf28J366VqyxJQzDjdvv/VYZ
|
|
||||||
QoEThibA34msTQIDAQABo1kwVzAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYI
|
|
||||||
KwYBBQUHAwEwHwYDVR0jBBgwFoAUyPQyLZZ7Al7A1Dvf/5xLRLY9aDYwDwYDVR0R
|
|
||||||
BAgwBocErBSn7TANBgkqhkiG9w0BAQsFAAOCAYEAWVgf0e/30255rHo8Z3/35YBE
|
|
||||||
Hrauwf8ef+aGVB+cLk2p1+UiYOgzvXKOeRP+9AVaASPg/mB7yA17DVrClWW7QjpU
|
|
||||||
iBkVCP6AsOlMVTPfKrKUucrWtac337TTleAMgtSjeApfdHbd3D4imilc16GLzVOG
|
|
||||||
9CKuvx6hJam4Bo4BfsO8TWh6F2hWxJL1dtY0d65ceBC40FXfowdJARgD85XCbJnY
|
|
||||||
4i/Twu80Hgrhok+CVDdH49DgMvUifckdsFCKqigZpJPRhGfbzfT61ysVcCXXsmj/
|
|
||||||
yFPo71zE5bq4T2ig+zGDbt64C+tP6a0P643SEnzyfEiUVTCWfIcrE17bSapzl5oa
|
|
||||||
PYSDkbC/OKoXsvvfVwDljNY0qXHTVjoTw6/8cXSAomZAaTAWZGkAWYBZEFpyEYu/
|
|
||||||
aBRDw5T/qo2N2xOt3NrmmWmkU8cFF8oESk5GJDoFFO/yp9MEvANWq6OQ4PZVEsdN
|
|
||||||
VtqzP07AD88B7kkD6qn8pSp8yZBYoL+Qk4d93HPg
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
-----BEGIN PRIVATE KEY-----
|
|
||||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDiCMe5cFt5FUd/
|
|
||||||
b0uyfUmUVIelJOwiYyuMsedSHSMJH7WLbFDcZBUUljxgta/Am/rhKewNkEQkFtJ2
|
|
||||||
yhx+YkmXyadbwg1iAuoUF78Kv8MVmolwBwA1W7HONWmZYGq8sDd9g8okcHfroui3
|
|
||||||
pBmg5tu+44mlqv4+5sCI1UfoX/R6HLg7l1p6B9SUbF1k5NGxWFXy7CMf34dXzAv1
|
|
||||||
nIryHqSX1WNCJ8/8VN2loaG2RKhUeh3+7KeZXMX8+xxNxRXCH65BypaPd90i3NyK
|
|
||||||
ePwrjrFkuIWn9AejPWRf+YMu3BvFsMAP2QbF/bwnfrpWrLElDMON2+/9VhlCgROG
|
|
||||||
JsDfiaxNAgMBAAECggEAB2kzyTH0odPvh+9Ze0Tt1mnuF51OC7OWMDL+C1xus2Qh
|
|
||||||
gux+ezdh1I63dJFIbad/koXaGji+bzN7W481X3RwBsTDErhaUXoYfCeqKRtP9WOf
|
|
||||||
eXeVS2qR+hmYuIFnhn+9lgUt6cNxPx3UhP7hozumfUv/DZo9Y0kUC3h4ttb8kEtU
|
|
||||||
ePfv0RledHKOEM35zvhvVTpyF4LfvnMyu/E+hJp2kIptPZ5DEsvXT3CsLCNGOWmt
|
|
||||||
HZlvVihQ0dtUp1FjDQsiwB8zSErQkZDTv8L0OvBvVyFqhhP/KReZi2pCTsBSYcYU
|
|
||||||
MGmZanqg1mLCqVDVPnaquCcuo39DCfETXNS4OFK4qQKBgQD8tsmwXtU0ai4ryVne
|
|
||||||
SOOJiCQFsGfZgxuSJ7XPWj8BnLSs0pi3ddEdJQvkj7z43iZ4AaW2VX9abQkZhlNv
|
|
||||||
v1Y80+MBTwCSM6CZLzCYWMnzRNY1hUR6bwQa/x5JyXU0sbx3B/GCH9hvhjWn9Dit
|
|
||||||
uphoPgC8ryKy26de7E5FKIfzFQKBgQDk+S7oUoQFXZ7YAIIXXVjp4nQVdU8zb7nW
|
|
||||||
B+yxyE5L+q6afgi2w9Jmm7DrQAg5GuY+3xlhICol/oxLb6nWkX5C2FTYTFaqSi5B
|
|
||||||
rZVqD6D/WGosNzwbcgai4TjmiJ81ssVwMuizQLksOPexuVYDUikofaWsF1G/E5af
|
|
||||||
rGRJbuACWQKBgQCwMNCVgsiq7oyaQpvBepgJPz2+Kat93wbN85myo3ziJttg0sNe
|
|
||||||
xWmyJC4SgJSD/n5blOpwIVPVO8foX9q0QnZhmmjedLI1PIFvy5LZ5K2ISin+zpdb
|
|
||||||
tSLrn4sCbs6kmnaHlqYuzv0bZDrsij0qArpXk0L4SjKq+LHMYHyBgyylsQKBgBHI
|
|
||||||
kK4Wio5oIQghsfjilR9FKULpY4dZLBPFdcqxBfO8uobhNwgK2XKCsRD0Xi8hObS0
|
|
||||||
WyJB/0QIKxlIyOYTUr0aVCygcTK0pDcRpkMgh56NXWGlwJNZHc7Uszikb8kZ41+9
|
|
||||||
dHlHk5otqn8xJ88GOJAeghmFjiHLAa3RE9DoPZmxAoGAC2sRi0M7pr6TV7Pz1f8S
|
|
||||||
DUy+iout42FNKCt00J2C7TxoTsKsWH4UKL0mqqanOr7vb0Wkow6nH7xT8u4DUGsA
|
|
||||||
oXfJqcGShNaG/XYFo5TaVC4k7rZY87+P12429J42uXVtGgjCR3lE53CdS3bY0tl5
|
|
||||||
OG0lgtOwXaXbU53BuLCbndU=
|
|
||||||
-----END PRIVATE KEY-----
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,156 +0,0 @@
|
|||||||
# =========================================================
|
|
||||||
# Request ID for correlation
|
|
||||||
# =========================================================
|
|
||||||
map $http_x_request_id $req_id {
|
|
||||||
default $http_x_request_id;
|
|
||||||
"" $request_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
# =========================================================
|
|
||||||
# Backend distant
|
|
||||||
# =========================================================
|
|
||||||
upstream backend {
|
|
||||||
server uber-stup.club:443;
|
|
||||||
keepalive 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
# =========================================================
|
|
||||||
# HTTP Server (MAIN)
|
|
||||||
# =========================================================
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
listen [::]:80;
|
|
||||||
server_name _;
|
|
||||||
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html;
|
|
||||||
client_max_body_size 10M;
|
|
||||||
|
|
||||||
modsecurity on;
|
|
||||||
modsecurity_rules_file /etc/nginx/modsec/custom-rules.conf;
|
|
||||||
location /api/ {
|
|
||||||
limit_except GET POST PUT PATCH DELETE OPTIONS { deny all; }
|
|
||||||
|
|
||||||
if ($request_method = 'OPTIONS') {
|
|
||||||
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
|
|
||||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, PATCH, DELETE, OPTIONS' always;
|
|
||||||
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Request-ID' always;
|
|
||||||
add_header 'Access-Control-Allow-Credentials' 'true' always;
|
|
||||||
add_header 'Access-Control-Max-Age' 86400 always;
|
|
||||||
add_header 'Content-Length' 0;
|
|
||||||
add_header 'Content-Type' 'text/plain charset=UTF-8';
|
|
||||||
return 204;
|
|
||||||
}
|
|
||||||
|
|
||||||
proxy_pass https://backend;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
|
|
||||||
proxy_ssl_server_name on;
|
|
||||||
proxy_ssl_name uber-stup.club;
|
|
||||||
|
|
||||||
proxy_set_header Host uber-stup.club;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header X-Request-ID $req_id;
|
|
||||||
proxy_set_header Connection "";
|
|
||||||
|
|
||||||
proxy_connect_timeout 60s;
|
|
||||||
proxy_send_timeout 60s;
|
|
||||||
proxy_read_timeout 60s;
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
|
|
||||||
add_header Pragma "no-cache" always;
|
|
||||||
add_header Expires "0" always;
|
|
||||||
}
|
|
||||||
location /uploads/ {
|
|
||||||
# ✅ IMPORTANT : alias doit se terminer par / ET le chemin aussi
|
|
||||||
alias /usr/share/nginx/html/uploads/;
|
|
||||||
|
|
||||||
# ✅ Désactiver ModSecurity pour les uploads
|
|
||||||
modsecurity off;
|
|
||||||
|
|
||||||
# Cache headers
|
|
||||||
expires 30d;
|
|
||||||
add_header Cache-Control "public, immutable";
|
|
||||||
}
|
|
||||||
location ^~ /uploads/images/ {
|
|
||||||
alias /usr/share/nginx/html/uploads/images/;
|
|
||||||
|
|
||||||
# ✅ Désactiver ModSecurity
|
|
||||||
modsecurity off;
|
|
||||||
|
|
||||||
# ✅ CORS pour images publiques
|
|
||||||
add_header Access-Control-Allow-Origin "*" always;
|
|
||||||
add_header Access-Control-Allow-Methods "GET, HEAD, OPTIONS" always;
|
|
||||||
|
|
||||||
# Cache agressif
|
|
||||||
expires 30d;
|
|
||||||
add_header Cache-Control "public, immutable" always;
|
|
||||||
|
|
||||||
# Types MIME
|
|
||||||
types {
|
|
||||||
image/jpeg jpg jpeg;
|
|
||||||
image/png png;
|
|
||||||
image/gif gif;
|
|
||||||
image/webp webp;
|
|
||||||
image/svg+xml svg;
|
|
||||||
}
|
|
||||||
default_type image/jpeg;
|
|
||||||
}
|
|
||||||
|
|
||||||
# =========================================================
|
|
||||||
# ✅ UPLOADS VIDEOS (priorité maximale avec ^~)
|
|
||||||
# =========================================================
|
|
||||||
location ^~ /uploads/videos/ {
|
|
||||||
alias /usr/share/nginx/html/uploads/videos/;
|
|
||||||
|
|
||||||
# ✅ Désactiver ModSecurity
|
|
||||||
modsecurity off;
|
|
||||||
|
|
||||||
# ✅ CORS pour vidéos publiques
|
|
||||||
add_header Access-Control-Allow-Origin "*" always;
|
|
||||||
add_header Access-Control-Allow-Methods "GET, HEAD, OPTIONS" always;
|
|
||||||
|
|
||||||
# Cache agressif
|
|
||||||
expires 30d;
|
|
||||||
add_header Cache-Control "public, immutable" always;
|
|
||||||
|
|
||||||
# Types MIME pour vidéos
|
|
||||||
types {
|
|
||||||
video/mp4 mp4;
|
|
||||||
video/webm webm;
|
|
||||||
video/ogg ogv;
|
|
||||||
}
|
|
||||||
default_type video/mp4;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
add_header Content-Security-Policy "
|
|
||||||
default-src 'self';
|
|
||||||
script-src 'self' 'unsafe-inline' 'unsafe-eval';
|
|
||||||
style-src 'self' 'unsafe-inline';
|
|
||||||
img-src 'self' data: https:;
|
|
||||||
font-src 'self' data:;
|
|
||||||
connect-src 'self' https://api.tomtom.com https://uber-stup.club;
|
|
||||||
" always;
|
|
||||||
|
|
||||||
location ~ /\. {
|
|
||||||
deny all;
|
|
||||||
access_log off;
|
|
||||||
log_not_found off;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~* (\.env|\.git|package\.json|package-lock\.json|yarn\.lock|Dockerfile|docker-compose\.yml)$ {
|
|
||||||
deny all;
|
|
||||||
access_log off;
|
|
||||||
log_not_found off;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,8 +9,8 @@ import type {
|
|||||||
Alert,
|
Alert,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
||||||
const V2 = "http://5.181.0.112/api/v2";
|
const V2 = "https://5.181.0.112.nip.io/api/v2";
|
||||||
const CABINE_URL = "http://5.181.0.112/api/v1/cabine";
|
const CABINE_URL = "https://5.181.0.112.nip.io/api/v1/cabine";
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// AUTH
|
// AUTH
|
||||||
@@ -622,7 +622,7 @@ export const getCommandCountByStatus = async (
|
|||||||
// CATÉGORIES
|
// CATÉGORIES
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
const V1_PUBLIC = "http://5.181.0.112/api/v1";
|
const V1_PUBLIC = "https://5.181.0.112.nip.io/api/v1";
|
||||||
|
|
||||||
export interface Category {
|
export interface Category {
|
||||||
id: number;
|
id: number;
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import type {
|
|||||||
Alert,
|
Alert,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
||||||
const API = "http://5.181.0.112/api/v1/cabine";
|
const API = "https://5.181.0.112.nip.io/api/v1/cabine";
|
||||||
const V2 = "http://5.181.0.112/api/v2";
|
const V2 = "https://5.181.0.112.nip.io/api/v2";
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// ITEMS
|
// ITEMS
|
||||||
@@ -395,7 +395,7 @@ export const markCabineNotificationsRead = async (): Promise<void> => {
|
|||||||
export const getPublicSettings = async (): Promise<PublicSettings> => {
|
export const getPublicSettings = async (): Promise<PublicSettings> => {
|
||||||
try {
|
try {
|
||||||
const { data } = await apiClient.get(
|
const { data } = await apiClient.get(
|
||||||
`http://5.181.0.112/api/v1/app-settings`,
|
`https://5.181.0.112.nip.io/api/v1/app-settings`,
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
penalties_enabled: data.penalties_enabled ?? true,
|
penalties_enabled: data.penalties_enabled ?? true,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import type {
|
|||||||
Alert,
|
Alert,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
||||||
const API = "http://5.181.0.112/api/v1/livreur";
|
const API = "https://5.181.0.112.nip.io/api/v1/livreur";
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// STATUT
|
// STATUT
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import axios from "axios";
|
|||||||
import { getToken, getAdminToken } from "../auth/tokenStorage";
|
import { getToken, getAdminToken } from "../auth/tokenStorage";
|
||||||
|
|
||||||
// Change this to your server IP/domain
|
// Change this to your server IP/domain
|
||||||
export const API_BASE_URL = "http://5.181.0.112";
|
export const API_BASE_URL = "https://5.181.0.112.nip.io";
|
||||||
|
|
||||||
const apiClient = axios.create({
|
const apiClient = axios.create({
|
||||||
baseURL: API_BASE_URL,
|
baseURL: API_BASE_URL,
|
||||||
|
|||||||
@@ -37,24 +37,12 @@ import { useAlert } from "../../hooks/useAlert";
|
|||||||
|
|
||||||
type Nav = NativeStackNavigationProp<AdminStackParamList>;
|
type Nav = NativeStackNavigationProp<AdminStackParamList>;
|
||||||
|
|
||||||
const STATUS_FILTERS = [
|
|
||||||
"all",
|
|
||||||
"pending",
|
|
||||||
"assigned",
|
|
||||||
"en_route",
|
|
||||||
"arrived",
|
|
||||||
"livre",
|
|
||||||
"approved",
|
|
||||||
"cancelled",
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function OrdersScreen() {
|
export default function OrdersScreen() {
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
const navigation = useNavigation<Nav>();
|
const navigation = useNavigation<Nav>();
|
||||||
const [commands, setCommands] = useState<CommandResponse[]>([]);
|
const [commands, setCommands] = useState<CommandResponse[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [refreshing, setRefreshing] = useState(false);
|
const [refreshing, setRefreshing] = useState(false);
|
||||||
const [filter, setFilter] = useState("all");
|
|
||||||
const { alert, showError, showSuccess, showConfirm, hideAlert } =
|
const { alert, showError, showSuccess, showConfirm, hideAlert } =
|
||||||
useAlert();
|
useAlert();
|
||||||
|
|
||||||
@@ -87,14 +75,13 @@ export default function OrdersScreen() {
|
|||||||
|
|
||||||
const loadData = useCallback(async () => {
|
const loadData = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
const status = filter === "all" ? undefined : filter;
|
const result = await getAllCommands(undefined);
|
||||||
const result = await getAllCommands(status);
|
|
||||||
setCommands(result.commands);
|
setCommands(result.commands);
|
||||||
} catch {
|
} catch {
|
||||||
/* ignore */
|
/* ignore */
|
||||||
}
|
}
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}, [filter]);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadData();
|
loadData();
|
||||||
@@ -250,11 +237,6 @@ export default function OrdersScreen() {
|
|||||||
() =>
|
() =>
|
||||||
StyleSheet.create({
|
StyleSheet.create({
|
||||||
container: { flex: 1, backgroundColor: colors.bgPrimary },
|
container: { flex: 1, backgroundColor: colors.bgPrimary },
|
||||||
filterList: {
|
|
||||||
maxHeight: 50,
|
|
||||||
paddingHorizontal: spacing.l,
|
|
||||||
paddingVertical: spacing.s,
|
|
||||||
},
|
|
||||||
refreshRow: {
|
refreshRow: {
|
||||||
paddingHorizontal: spacing.l,
|
paddingHorizontal: spacing.l,
|
||||||
paddingBottom: spacing.s,
|
paddingBottom: spacing.s,
|
||||||
@@ -275,24 +257,6 @@ export default function OrdersScreen() {
|
|||||||
color: colors.textSecondary,
|
color: colors.textSecondary,
|
||||||
fontSize: fontSize.sm,
|
fontSize: fontSize.sm,
|
||||||
},
|
},
|
||||||
filterBtn: {
|
|
||||||
paddingHorizontal: spacing.l,
|
|
||||||
paddingVertical: spacing.s,
|
|
||||||
backgroundColor: colors.bgCard,
|
|
||||||
borderRadius: borderRadius.xl,
|
|
||||||
marginRight: spacing.s,
|
|
||||||
borderWidth: 1,
|
|
||||||
borderColor: colors.border,
|
|
||||||
},
|
|
||||||
filterActive: {
|
|
||||||
backgroundColor: colors.accent,
|
|
||||||
borderColor: colors.accent,
|
|
||||||
},
|
|
||||||
filterText: {
|
|
||||||
color: colors.textSecondary,
|
|
||||||
fontSize: fontSize.sm,
|
|
||||||
},
|
|
||||||
filterTextActive: { color: colors.textWhite },
|
|
||||||
cardText: {
|
cardText: {
|
||||||
color: colors.textSecondary,
|
color: colors.textSecondary,
|
||||||
fontSize: fontSize.sm,
|
fontSize: fontSize.sm,
|
||||||
@@ -615,31 +579,6 @@ export default function OrdersScreen() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<FlatList
|
|
||||||
horizontal
|
|
||||||
data={STATUS_FILTERS}
|
|
||||||
keyExtractor={(i) => i}
|
|
||||||
renderItem={({ item }) => (
|
|
||||||
<TouchableOpacity
|
|
||||||
style={[
|
|
||||||
styles.filterBtn,
|
|
||||||
filter === item && styles.filterActive,
|
|
||||||
]}
|
|
||||||
onPress={() => setFilter(item)}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
styles.filterText,
|
|
||||||
filter === item && styles.filterTextActive,
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{item === "all" ? "Tous" : item}
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
)}
|
|
||||||
style={styles.filterList}
|
|
||||||
showsHorizontalScrollIndicator={false}
|
|
||||||
/>
|
|
||||||
<View style={styles.refreshRow}>
|
<View style={styles.refreshRow}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={styles.refreshBtn}
|
style={styles.refreshBtn}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import type {
|
|||||||
import { getToken } from "../auth/tokenStorage";
|
import { getToken } from "../auth/tokenStorage";
|
||||||
import { extractUsernameFromToken } from "../auth/jwtUtils";
|
import { extractUsernameFromToken } from "../auth/jwtUtils";
|
||||||
|
|
||||||
const V1 = "http://5.181.0.112/api/v1";
|
const V1 = "https://5.181.0.112.nip.io/api/v1";
|
||||||
|
|
||||||
export const getJwtUsername = async (): Promise<string | null> => {
|
export const getJwtUsername = async (): Promise<string | null> => {
|
||||||
const token = await getToken();
|
const token = await getToken();
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import axios from "axios";
|
|||||||
import { getToken, getAdminToken } from "../auth/tokenStorage";
|
import { getToken, getAdminToken } from "../auth/tokenStorage";
|
||||||
|
|
||||||
// Change this to your server IP/domain
|
// Change this to your server IP/domain
|
||||||
export const API_BASE_URL = "http://5.181.0.112";
|
export const API_BASE_URL = "https://5.181.0.112.nip.io";
|
||||||
|
|
||||||
const apiClient = axios.create({
|
const apiClient = axios.create({
|
||||||
baseURL: API_BASE_URL,
|
baseURL: API_BASE_URL,
|
||||||
|
|||||||
Reference in New Issue
Block a user