jwt debug
All checks were successful
Test - Build & Deploy to Scaleway / build-and-push-image-lecoffre (push) Successful in 1m18s
Test - Build & Deploy to Scaleway / deploy-to-scaleway-lecoffre (push) Successful in 3s

This commit is contained in:
Sosthene 2025-08-03 18:31:51 +02:00
parent 66f4c65158
commit 59bfa9bd55
2 changed files with 193 additions and 0 deletions

View File

@ -0,0 +1,122 @@
import React, { useEffect, useState } from "react";
import JwtService from "@Front/Services/JwtService/JwtService";
interface JwtDebuggerProps {
expectedRules?: string[];
showAlways?: boolean;
}
export default function JwtDebugger({ expectedRules = [], showAlways = false }: JwtDebuggerProps) {
const [isVisible, setIsVisible] = useState(showAlways);
const [debugInfo, setDebugInfo] = useState<any>(null);
useEffect(() => {
// Only show in development
if (process.env.NODE_ENV !== "development" && !showAlways) {
return;
}
const jwt = JwtService.getInstance().debugJwtToken();
if (jwt) {
setDebugInfo(jwt);
}
}, [showAlways]);
// Keyboard shortcut to toggle debugger (Ctrl+Shift+D)
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (e.ctrlKey && e.shiftKey && e.key === "D") {
e.preventDefault();
setIsVisible(!isVisible);
}
};
document.addEventListener("keydown", handleKeyDown);
return () => document.removeEventListener("keydown", handleKeyDown);
}, [isVisible]);
if (!isVisible) return null;
return (
<div style={{
position: "fixed",
top: "10px",
right: "10px",
background: "#1a1a1a",
color: "#fff",
padding: "15px",
borderRadius: "8px",
fontSize: "12px",
fontFamily: "monospace",
maxWidth: "400px",
maxHeight: "80vh",
overflow: "auto",
zIndex: 9999,
border: "1px solid #333"
}}>
<div style={{ marginBottom: "10px", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
<strong>JWT Debugger</strong>
<button
onClick={() => setIsVisible(false)}
style={{ background: "none", border: "none", color: "#fff", cursor: "pointer" }}
>
</button>
</div>
{debugInfo && (
<div>
<div><strong>User ID:</strong> {debugInfo.userId}</div>
<div><strong>Email:</strong> {debugInfo.email}</div>
<div><strong>Role:</strong> {debugInfo.role}</div>
<div><strong>Office ID:</strong> {debugInfo.office_Id}</div>
<div><strong>Rules Count:</strong> {debugInfo.rules?.length || 0}</div>
<div><strong>Rules:</strong></div>
<ul style={{ margin: "5px 0", paddingLeft: "20px" }}>
{debugInfo.rules?.map((rule: string, index: number) => (
<li key={index}>{rule}</li>
))}
</ul>
<div><strong>Expires:</strong> {new Date(debugInfo.exp * 1000).toLocaleString()}</div>
{expectedRules.length > 0 && (
<div style={{ marginTop: "15px" }}>
<div><strong>Expected Rules:</strong></div>
<ul style={{ margin: "5px 0", paddingLeft: "20px" }}>
{expectedRules.map((rule, index) => (
<li key={index} style={{
color: debugInfo.rules?.includes(rule) ? "#4ade80" : "#f87171"
}}>
{rule} {debugInfo.rules?.includes(rule) ? "✓" : "✗"}
</li>
))}
</ul>
</div>
)}
<div style={{ marginTop: "15px" }}>
<strong>Quick Tests:</strong>
<div style={{ marginTop: "5px" }}>
<button
onClick={() => JwtService.getInstance().checkSpecificRule("folders", "GET")}
style={{ marginRight: "5px", padding: "2px 5px", fontSize: "10px" }}
>
Test GET folders
</button>
<button
onClick={() => JwtService.getInstance().checkSpecificRule("users", "POST")}
style={{ marginRight: "5px", padding: "2px 5px", fontSize: "10px" }}
>
Test POST users
</button>
</div>
</div>
</div>
)}
<div style={{ marginTop: "10px", fontSize: "10px", color: "#888" }}>
Press Ctrl+Shift+D to toggle
</div>
</div>
);
}

View File

@ -165,4 +165,75 @@ export default class JwtService {
if (!token) return false; if (!token) return false;
return token?.rules?.some((rule: string) => rule === `${action} ${name}`); return token?.rules?.some((rule: string) => rule === `${action} ${name}`);
} }
/**
* Debug method to log JWT token details including rules
*/
public debugJwtToken() {
const token = this.decodeJwt();
if (!token) {
console.warn("No JWT token found");
return null;
}
console.log("=== JWT Token Debug Info ===");
console.log("User ID:", token.userId);
console.log("Email:", token.email);
console.log("Role:", token.role);
console.log("Office ID:", token.office_Id);
console.log("Rules count:", token.rules?.length || 0);
console.log("Rules:", token.rules);
console.log("Expiration:", new Date(token.exp * 1000).toISOString());
console.log("=============================");
return token;
}
/**
* Check if a specific rule exists in the JWT token
*/
public checkSpecificRule(name: string, action: string) {
const token = this.decodeJwt();
if (!token) {
console.warn("No JWT token found");
return false;
}
const expectedRule = `${action} ${name}`;
const hasRule = token?.rules?.some((rule: string) => rule === expectedRule);
console.log(`=== Rule Check: ${expectedRule} ===`);
console.log("Expected rule:", expectedRule);
console.log("Available rules:", token.rules);
console.log("Rule found:", hasRule);
console.log("=============================");
return hasRule;
}
/**
* Compare JWT rules with expected rules from database
*/
public compareRulesWithDatabase(expectedRules: string[]) {
const token = this.decodeJwt();
if (!token) {
console.warn("No JWT token found");
return { missing: expectedRules, extra: [], matches: [] };
}
const jwtRules = token.rules || [];
const missing = expectedRules.filter(rule => !jwtRules.includes(rule));
const extra = jwtRules.filter(rule => !expectedRules.includes(rule));
const matches = jwtRules.filter(rule => expectedRules.includes(rule));
console.log("=== Rules Comparison ===");
console.log("Expected rules (from DB):", expectedRules);
console.log("JWT rules:", jwtRules);
console.log("Missing rules:", missing);
console.log("Extra rules:", extra);
console.log("Matching rules:", matches);
console.log("=========================");
return { missing, extra, matches };
}
} }