Add source:sociowire for user posts, fix time filter, cross-origin SSO

This commit is contained in:
SocioWire 2026-01-04 07:10:36 +00:00
parent d4829ae628
commit d5aa930d34
4 changed files with 59 additions and 1 deletions

33
Dockerfile Normal file
View File

@ -0,0 +1,33 @@
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
ARG VITE_API_BASE_URL=
ARG VITE_KC_URL=/auth
ENV VITE_API_BASE_URL=${VITE_API_BASE_URL}
ENV VITE_KC_URL=${VITE_KC_URL}
RUN npm run build
FROM nginx:alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY --from=build /app/dist /usr/share/nginx/html
COPY <<EOF /etc/nginx/conf.d/default.conf
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
location / {
try_files \$uri \$uri/ /index.html;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
EOF
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

View File

@ -17,6 +17,16 @@ const KC_REALM = import.meta?.env?.VITE_KC_REALM || "sociowire";
const KC_CLIENT_ID = import.meta?.env?.VITE_KC_CLIENT_ID || "sociowire-frontend";
const KC_SSO_ENABLED = (import.meta?.env?.VITE_KC_SSO || "true") !== "false";
// Check if Keycloak is on a different origin (cross-domain SSO)
function isCrossOriginSSO() {
try {
const kcOrigin = new URL(KC_URL).origin;
return kcOrigin !== window.location.origin;
} catch {
return true;
}
}
let kcInstance = null;
function getKeycloak() {
if (!kcInstance) {
@ -473,6 +483,7 @@ export function AuthProvider({ children }) {
try {
kc = getKeycloak();
} catch (err) {
console.error("[Auth] Keycloak init error:", err);
setAnon("SSO failed to initialize. Please try again.");
return { ok: false, reason: "init_failed", detail: err?.message || "" };
}
@ -482,6 +493,7 @@ export function AuthProvider({ children }) {
const errDesc = params.get("error_description") || params.get("kc_error_description") || "";
if (errCode) {
console.error("[Auth] SSO error from Keycloak:", errCode, errDesc);
setAnon(`SSO failed: ${errCode}${errDesc ? " - " + errDesc : ""}`);
cleanupAuthUrl();
return { ok: false, reason: "kc_error", detail: errDesc || errCode };
@ -489,18 +501,23 @@ export function AuthProvider({ children }) {
let ok = false;
try {
console.log("[Auth] Initializing Keycloak for SSO callback...");
ok = await kc.init({
onLoad: "check-sso",
pkceMethod: "S256",
checkLoginIframe: false,
enableLogging: true,
});
console.log("[Auth] Keycloak init result:", ok, "authenticated:", kc.authenticated);
} catch (err) {
console.error("[Auth] Keycloak init failed:", err);
setAnon("SSO failed to finish. Please try again.");
cleanupAuthUrl();
return { ok: false, reason: "kc_init_failed", detail: err?.message || "" };
}
if (!ok || !kc.authenticated || !kc.token) {
console.warn("[Auth] Keycloak not authenticated after init");
setAnon("SSO login failed. Please try again.");
cleanupAuthUrl();
return { ok: false, reason: "not_authenticated" };
@ -540,6 +557,12 @@ export function AuthProvider({ children }) {
}
async function trySilentKeycloakSession() {
// Skip silent SSO check for cross-origin (third-party cookies blocked)
if (isCrossOriginSSO()) {
console.log("[Auth] Skipping silent SSO check (cross-origin)");
return false;
}
let kc = null;
try {
if (sessionStorage.getItem("sociowire:logout")) {

View File

@ -2,7 +2,7 @@ import React from "react";
export default function TimeFilterButtons({ activeHours, onSelect }) {
const buttons = [
{ hours: 5, label: "Now", icon: "fa-solid fa-bolt" },
{ hours: 3, label: "Now", icon: "fa-solid fa-bolt" },
{ hours: 24, label: "Today", icon: "fa-solid fa-sun" },
{ hours: 96, label: "4Days", icon: "fa-solid fa-calendar-days" },
{ hours: 336, label: "Old", icon: "fa-solid fa-hourglass-half" },

View File

@ -1376,6 +1376,8 @@ export default function MapView({
.split(",")
.map((u) => u.trim())
.filter(Boolean),
// Mark as user-created post so enrichment preserves the position
source: "sociowire",
};
if (draftUrl.trim()) {