From b221a83ecef1dd7f9583d5107017d24e668205a6 Mon Sep 17 00:00:00 2001
From: Kamal Wickramanayake <kamal@inbox.lk>
Date: Thu, 2 Jul 2026 20:17:44 +0530
Subject: Added React global state + role based security sample app

---
 .../src/contexts/AuthContext.jsx                   | 83 ++++++++++++++++++++++
 1 file changed, 83 insertions(+)
 create mode 100644 react/08-auth-with-context/src/contexts/AuthContext.jsx

(limited to 'react/08-auth-with-context/src/contexts/AuthContext.jsx')

diff --git a/react/08-auth-with-context/src/contexts/AuthContext.jsx b/react/08-auth-with-context/src/contexts/AuthContext.jsx
new file mode 100644
index 0000000..9ac16b1
--- /dev/null
+++ b/react/08-auth-with-context/src/contexts/AuthContext.jsx
@@ -0,0 +1,83 @@
+import { createContext, useState, useEffect, use } from 'react';
+
+// 1. Initialize Context
+const AuthContext = createContext(null);
+
+// 2. Create a Custom Provider Component
+export function AuthProvider({ children }) {
+    const [user, setUser] = useState(null);
+
+    useEffect(() => {
+        // Fetch user data from your backend API
+        const fetchUser = async () => {
+            const response = await fetch('/bff/api/security/user');
+            const data = await response.json();
+            setUser(data); // Data format: { username: "john", name: "John", roles: ["ADMIN", "MANAGER"] }
+        };
+        fetchUser();
+    }, []);
+
+    const login = () => {
+        // TODO: Start single sign-on process (say using OAuth2, OpenID)
+
+        // For testing
+        setUser({ username: "john", name: "John", roles: ["ADMIN", "MANAGER"] })
+    }
+
+    const logout = async () => {
+        const logoutUser = async () => {
+            const response = await fetch('/bff/logout');
+            const data = await response.json();
+            setUser(null);
+            // TODO: Send user to somewhere
+        };
+        logoutUser();
+
+        // For testing
+        setUser(null);
+    };
+
+    const isLoggedIn = () => {
+        if (user) {
+            return true;
+        }
+
+        return false;
+    };
+
+    const isAdmin = () => {
+        return isInRole("ADMIN");
+    }
+
+    const isInRole = (role) => {
+        if (user && role && user.roles) {
+            return user.roles.includes(role);
+        }
+
+        return false;
+    };
+
+    const isInRoles = (roles) => {
+        if (user && roles && user.roles) {
+            return roles.some(value => user.roles.includes(value));
+        }
+
+        return false;
+    }
+
+    // Provide the state and the modifier function as a value object
+    return (
+        <AuthContext value={{ user, login, logout, isLoggedIn, isAdmin, isInRole, isInRoles }}>
+            {children}
+        </AuthContext>
+    );
+}
+
+// 3. Create a clean Custom Hook to consume this specific context
+export function useAuth() {
+    const context = use(AuthContext);
+    if (!context) {
+        throw new Error('useAuth must be used within an AuthProvider');
+    }
+    return context;
+}
-- 
cgit v1.2.3

