From 1fc4cf738563aa0ef1d48a4c767728fdaf2bae36 Mon Sep 17 00:00:00 2001 From: SoSweetHam Date: Mon, 13 Oct 2025 14:52:24 +0530 Subject: [PATCH 1/3] feat: motd --- platforms/registry/motd.json | 4 ++++ platforms/registry/src/index.ts | 22 +++++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 platforms/registry/motd.json diff --git a/platforms/registry/motd.json b/platforms/registry/motd.json new file mode 100644 index 00000000..66d5ec88 --- /dev/null +++ b/platforms/registry/motd.json @@ -0,0 +1,4 @@ +{ + "status": "up", + "message": "Registry service is running" +} \ No newline at end of file diff --git a/platforms/registry/src/index.ts b/platforms/registry/src/index.ts index df063a53..2f45f68e 100644 --- a/platforms/registry/src/index.ts +++ b/platforms/registry/src/index.ts @@ -1,13 +1,29 @@ import fastify from "fastify"; import { generateEntropy, generatePlatformToken, getJWK } from "./jwt"; import dotenv from "dotenv"; -import path from "path"; +import path from "node:path"; import { AppDataSource } from "./config/database"; import { VaultService } from "./services/VaultService"; import { UriResolutionService } from "./services/UriResolutionService"; import { KubernetesService } from "./services/KubernetesService"; import cors from "@fastify/cors"; +import fs from "node:fs"; + +function loadMotdJSON() { + const motdJSON = fs.readFileSync(path.resolve(__dirname, "../motd.json"), "utf8"); + return JSON.parse(motdJSON) as { + status: "up" | "maintenance" + message: string + }; +} + +let motd = loadMotdJSON(); + +fs.watchFile(path.resolve(__dirname, "../motd.json"), (_curr, _prev) => { + motd = loadMotdJSON(); +}); + dotenv.config({ path: path.resolve(__dirname, "../../../.env") }); const server = fastify({ logger: true }); @@ -55,6 +71,10 @@ const checkSharedSecret = async (request: any, reply: any) => { } }; +server.get("/motd", async (request, reply) => { + return motd; +}); + // Create a new vault entry server.post( "/register", From 7620d5d4b2604489eb2b9d6d13fb5250e9a44569 Mon Sep 17 00:00:00 2001 From: SoSweetHam Date: Mon, 13 Oct 2025 15:03:27 +0530 Subject: [PATCH 2/3] feat: ui --- .../components/common/maintenance-banner.tsx | 36 ++++++++++++++++++ platforms/blabsy/src/pages/_app.tsx | 2 + platforms/eVoting/src/app/layout.tsx | 2 + .../src/components/MaintenanceBanner.tsx | 38 +++++++++++++++++++ .../group-charter-manager/src/app/layout.tsx | 2 + .../src/components/MaintenanceBanner.tsx | 38 +++++++++++++++++++ .../MaintenanceBanner.svelte | 23 +++++++++++ platforms/pictique/src/routes/+layout.svelte | 18 +++++---- platforms/registry/motd.json | 4 +- 9 files changed, 154 insertions(+), 9 deletions(-) create mode 100644 platforms/blabsy/src/components/common/maintenance-banner.tsx create mode 100644 platforms/eVoting/src/components/MaintenanceBanner.tsx create mode 100644 platforms/group-charter-manager/src/components/MaintenanceBanner.tsx create mode 100644 platforms/pictique/src/lib/fragments/MaintenanceBanner/MaintenanceBanner.svelte diff --git a/platforms/blabsy/src/components/common/maintenance-banner.tsx b/platforms/blabsy/src/components/common/maintenance-banner.tsx new file mode 100644 index 00000000..4612868d --- /dev/null +++ b/platforms/blabsy/src/components/common/maintenance-banner.tsx @@ -0,0 +1,36 @@ +import { useEffect, useState } from 'react'; +import axios from 'axios'; + +interface Motd { + status: 'up' | 'maintenance'; + message: string; +} + +export function MaintenanceBanner(): JSX.Element | null { + const [motd, setMotd] = useState(null); + + useEffect(() => { + const fetchMotd = async () => { + try { + const registryUrl = process.env.NEXT_PUBLIC_REGISTRY_URL || 'http://localhost:4321'; + const response = await axios.get(`${registryUrl}/motd`); + setMotd(response.data); + } catch (error) { + console.error('Failed to fetch motd:', error); + } + }; + + void fetchMotd(); + }, []); + + if (motd?.status !== 'maintenance') { + return null; + } + + return ( +
+ ⚠️ {motd.message} +
+ ); +} + diff --git a/platforms/blabsy/src/pages/_app.tsx b/platforms/blabsy/src/pages/_app.tsx index 9ccb7d92..42be43b1 100644 --- a/platforms/blabsy/src/pages/_app.tsx +++ b/platforms/blabsy/src/pages/_app.tsx @@ -3,6 +3,7 @@ import '@styles/globals.scss'; import { AuthContextProvider } from '@lib/context/auth-context'; import { ThemeContextProvider } from '@lib/context/theme-context'; import { AppHead } from '@components/common/app-head'; +import { MaintenanceBanner } from '@components/common/maintenance-banner'; import type { ReactElement, ReactNode } from 'react'; import type { NextPage } from 'next'; import type { AppProps } from 'next/app'; @@ -24,6 +25,7 @@ export default function App({ return ( <> + {getLayout()} diff --git a/platforms/eVoting/src/app/layout.tsx b/platforms/eVoting/src/app/layout.tsx index bc268840..0c34992b 100644 --- a/platforms/eVoting/src/app/layout.tsx +++ b/platforms/eVoting/src/app/layout.tsx @@ -1,6 +1,7 @@ import type { Metadata } from "next"; import "./globals.css"; import { AuthProvider } from "@/lib/auth-context"; +import { MaintenanceBanner } from "@/components/MaintenanceBanner"; export const metadata: Metadata = { title: "eVoting Platform", @@ -18,6 +19,7 @@ export default function RootLayout({ return ( + {children} diff --git a/platforms/eVoting/src/components/MaintenanceBanner.tsx b/platforms/eVoting/src/components/MaintenanceBanner.tsx new file mode 100644 index 00000000..a97d0e3f --- /dev/null +++ b/platforms/eVoting/src/components/MaintenanceBanner.tsx @@ -0,0 +1,38 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import axios from 'axios'; + +interface Motd { + status: 'up' | 'maintenance'; + message: string; +} + +export function MaintenanceBanner() { + const [motd, setMotd] = useState(null); + + useEffect(() => { + const fetchMotd = async () => { + try { + const registryUrl = process.env.NEXT_PUBLIC_REGISTRY_URL || 'http://localhost:4321'; + const response = await axios.get(`${registryUrl}/motd`); + setMotd(response.data); + } catch (error) { + console.error('Failed to fetch motd:', error); + } + }; + + fetchMotd(); + }, []); + + if (motd?.status !== 'maintenance') { + return null; + } + + return ( +
+ ⚠️ {motd.message} +
+ ); +} + diff --git a/platforms/group-charter-manager/src/app/layout.tsx b/platforms/group-charter-manager/src/app/layout.tsx index b642fe82..1036a9d1 100644 --- a/platforms/group-charter-manager/src/app/layout.tsx +++ b/platforms/group-charter-manager/src/app/layout.tsx @@ -4,6 +4,7 @@ import "./globals.css"; import { Toaster } from "@/components/ui/toaster"; import { AuthProvider } from "@/components/auth/auth-provider"; import DisclaimerModal from "@/components/disclaimer-modal"; +import { MaintenanceBanner } from "@/components/MaintenanceBanner"; const inter = Inter({ subsets: ["latin"] }); @@ -23,6 +24,7 @@ export default function RootLayout({ return ( + {children} diff --git a/platforms/group-charter-manager/src/components/MaintenanceBanner.tsx b/platforms/group-charter-manager/src/components/MaintenanceBanner.tsx new file mode 100644 index 00000000..a97d0e3f --- /dev/null +++ b/platforms/group-charter-manager/src/components/MaintenanceBanner.tsx @@ -0,0 +1,38 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import axios from 'axios'; + +interface Motd { + status: 'up' | 'maintenance'; + message: string; +} + +export function MaintenanceBanner() { + const [motd, setMotd] = useState(null); + + useEffect(() => { + const fetchMotd = async () => { + try { + const registryUrl = process.env.NEXT_PUBLIC_REGISTRY_URL || 'http://localhost:4321'; + const response = await axios.get(`${registryUrl}/motd`); + setMotd(response.data); + } catch (error) { + console.error('Failed to fetch motd:', error); + } + }; + + fetchMotd(); + }, []); + + if (motd?.status !== 'maintenance') { + return null; + } + + return ( +
+ ⚠️ {motd.message} +
+ ); +} + diff --git a/platforms/pictique/src/lib/fragments/MaintenanceBanner/MaintenanceBanner.svelte b/platforms/pictique/src/lib/fragments/MaintenanceBanner/MaintenanceBanner.svelte new file mode 100644 index 00000000..3c3c270a --- /dev/null +++ b/platforms/pictique/src/lib/fragments/MaintenanceBanner/MaintenanceBanner.svelte @@ -0,0 +1,23 @@ + + +{#if motd?.status === 'maintenance'} +
+ ⚠️ {motd.message} +
+{/if} + diff --git a/platforms/pictique/src/routes/+layout.svelte b/platforms/pictique/src/routes/+layout.svelte index a3763778..9928cf8b 100644 --- a/platforms/pictique/src/routes/+layout.svelte +++ b/platforms/pictique/src/routes/+layout.svelte @@ -4,6 +4,7 @@ import { onMount } from 'svelte'; import '../app.css'; import { page } from '$app/state'; + import MaintenanceBanner from '$lib/fragments/MaintenanceBanner/MaintenanceBanner.svelte'; let { children } = $props(); @@ -46,11 +47,14 @@ logo {:else} -
- {@render children()} -
+
+ +
+ {@render children()} +
+
{/if} diff --git a/platforms/registry/motd.json b/platforms/registry/motd.json index 66d5ec88..6d56100a 100644 --- a/platforms/registry/motd.json +++ b/platforms/registry/motd.json @@ -1,4 +1,4 @@ { - "status": "up", - "message": "Registry service is running" + "status": "maintenance", + "message": "Registry service is down" } \ No newline at end of file From 0f641cbe4962cff01756df8be62a3e5c934583ca Mon Sep 17 00:00:00 2001 From: SoSweetHam Date: Mon, 13 Oct 2025 15:09:54 +0530 Subject: [PATCH 3/3] fix: env var --- .env.example | 5 ++++- platforms/blabsy/.env.example | 4 ++++ platforms/pictique/.env.example | 4 ++++ .../lib/fragments/MaintenanceBanner/MaintenanceBanner.svelte | 4 ++-- 4 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 platforms/blabsy/.env.example create mode 100644 platforms/pictique/.env.example diff --git a/.env.example b/.env.example index 67764b19..70e3e9f7 100644 --- a/.env.example +++ b/.env.example @@ -4,10 +4,13 @@ PUBLIC_PICTIQUE_BASE_URL=your_public_pictique_base_url_here # Blabsy Configuration PUBLIC_BLABSY_BASE_URL=your_public_blabsy_base_url_here -# Eid Wallet Configuration +# Eid Wallet & Pictique Configuration (Svelte) PUBLIC_REGISTRY_URL=your_public_registry_url_here PUBLIC_PROVISIONER_URL=your_public_provisioner_url_here +# Next.js Applications Configuration (eVoting, Blabsy, Group Charter Manager) +NEXT_PUBLIC_REGISTRY_URL=your_public_registry_url_here + # Neo4j Configuration NEO4J_URI=bolt://neo4j:7687 NEO4J_USER=neo4j diff --git a/platforms/blabsy/.env.example b/platforms/blabsy/.env.example new file mode 100644 index 00000000..dec26a5f --- /dev/null +++ b/platforms/blabsy/.env.example @@ -0,0 +1,4 @@ +# Registry URL for fetching motd and other registry services +# Note: In Next.js, environment variables exposed to the browser must be prefixed with NEXT_PUBLIC_ +NEXT_PUBLIC_REGISTRY_URL=http://localhost:4321 + diff --git a/platforms/pictique/.env.example b/platforms/pictique/.env.example new file mode 100644 index 00000000..13fe0853 --- /dev/null +++ b/platforms/pictique/.env.example @@ -0,0 +1,4 @@ +# Registry URL for fetching motd and other registry services +# Note: In SvelteKit, public environment variables must be prefixed with PUBLIC_ +PUBLIC_REGISTRY_URL=http://localhost:4321 + diff --git a/platforms/pictique/src/lib/fragments/MaintenanceBanner/MaintenanceBanner.svelte b/platforms/pictique/src/lib/fragments/MaintenanceBanner/MaintenanceBanner.svelte index 3c3c270a..58b1ef09 100644 --- a/platforms/pictique/src/lib/fragments/MaintenanceBanner/MaintenanceBanner.svelte +++ b/platforms/pictique/src/lib/fragments/MaintenanceBanner/MaintenanceBanner.svelte @@ -1,12 +1,13 @@