diff --git a/deploy/nginx-dashfront.conf b/deploy/nginx-dashfront.conf index 1ebda20..f056f4b 100644 --- a/deploy/nginx-dashfront.conf +++ b/deploy/nginx-dashfront.conf @@ -13,7 +13,7 @@ map $http_upgrade $connection_upgrade { server { listen 80; listen [::]:80; - server_name dash.example.com; # <-- Replace with your domain or server IP + server_name dashdev.quixpos.com; location ^~ /.well-known/acme-challenge/ { root /var/www/certbot; @@ -32,11 +32,11 @@ server { listen [::]:443 ssl; http2 on; - server_name dash.example.com; # <-- Replace with your domain or server IP + server_name dashdev.quixpos.com; # --- SSL / TLS Certificates --- - ssl_certificate /etc/letsencrypt/live/dash.example.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/dash.example.com/privkey.pem; + ssl_certificate /etc/letsencrypt/live/dashdev.quixpos.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/dashdev.quixpos.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305; @@ -45,6 +45,9 @@ server { ssl_session_cache shared:SSL:10m; ssl_session_tickets off; + # --- Header Buffer Limits (prevents HTTP/2 RST_STREAM / ERR_HTTP2_PROTOCOL_ERROR) --- + large_client_header_buffers 4 128k; + # --- Static File Root --- root /home/seb/src/dashfront/dist; index index.html; @@ -87,16 +90,21 @@ server { proxy_pass http://127.0.0.1:4208; proxy_http_version 1.1; - proxy_set_header Connection ""; + # Clear Connection & Accept-Encoding to prevent upstream gzip/chunk buffering + proxy_set_header Connection ""; + proxy_set_header Accept-Encoding ""; proxy_set_header Host $http_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; + # Disable buffering and compression completely for immediate push proxy_buffering off; proxy_cache off; chunked_transfer_encoding off; + gzip off; + # Prevent premature disconnections; keep SSE open for 24 hours proxy_read_timeout 86400s; proxy_send_timeout 86400s; } @@ -106,6 +114,8 @@ server { proxy_pass http://127.0.0.1:4208; proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; diff --git a/src/automats/authAutomat.js b/src/automats/authAutomat.js index 5657eda..7de7933 100644 --- a/src/automats/authAutomat.js +++ b/src/automats/authAutomat.js @@ -40,6 +40,15 @@ export function setAuthEventDispatcher(dispatch) { emit = dispatch; } +function normalizePicture(picture) { + if (!picture || typeof picture !== 'string') return null; + if (picture.startsWith('http://') || picture.startsWith('https://') || picture.startsWith('data:')) { + return picture; + } + const mime = picture.startsWith('/9j/') ? 'image/jpeg' : 'image/png'; + return `data:${mime};base64,${picture}`; +} + /** * Merges API user data while retaining the current company selection when the * response does not contain one. @@ -52,7 +61,11 @@ function mergeUser(current, incoming) { if (!incoming) return current; const selectedCompanyId = incoming.selectedCompanyId ?? current?.selectedCompanyId ?? null; - return { ...current, ...incoming, selectedCompanyId }; + const merged = { ...current, ...incoming, selectedCompanyId }; + if (merged.picture) { + merged.picture = normalizePicture(merged.picture); + } + return merged; } let authAutomat; @@ -104,8 +117,9 @@ const actions = { if (!session?.user) { throw new Error('Login ok but session cookie not accepted (/api/auth/me still unauthorized)'); } + const user = mergeUser(authAutomat.state.user, session.user); authAutomat.setState({ - user: session.user, + user, googleClientId: session.googleClientId ?? authAutomat.state.googleClientId, status: 'authed', }); diff --git a/src/components/UserMenu.jsx b/src/components/UserMenu.jsx index fa15dd3..7ff5390 100644 --- a/src/components/UserMenu.jsx +++ b/src/components/UserMenu.jsx @@ -81,6 +81,16 @@ class UserMenu extends PureComponent { const { user, anchorEl, settingsOpen, numbersOpen } = this.state; const open = Boolean(anchorEl); + const pictureSrc = (() => { + const pic = user?.picture; + if (!pic || typeof pic !== 'string') return undefined; + if (pic.startsWith('http://') || pic.startsWith('https://') || pic.startsWith('data:')) { + return pic; + } + const mime = pic.startsWith('/9j/') ? 'image/jpeg' : 'image/png'; + return `data:${mime};base64,${pic}`; + })(); + return ( <> @@ -89,7 +99,7 @@ class UserMenu extends PureComponent { onMouseDown={(e) => e.preventDefault()} sx={{ p: 0, width: 32, height: 32, borderRadius: '50%' }} > - + {user?.email?.[0]?.toUpperCase()}