Compare commits
4 Commits
e87b1ddde5
...
59bfa9bd55
Author | SHA1 | Date | |
---|---|---|---|
![]() |
59bfa9bd55 | ||
![]() |
66f4c65158 | ||
![]() |
6217cfb170 | ||
![]() |
ea7e74ba06 |
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -17,8 +17,6 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
|
||||||
ref: cicd
|
|
||||||
- name: Setup SSH
|
- name: Setup SSH
|
||||||
run: |
|
run: |
|
||||||
mkdir -p ~/.ssh
|
mkdir -p ~/.ssh
|
||||||
|
@ -30,6 +30,15 @@ export default abstract class BaseApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected buildHeaders(contentType: ContentType) {
|
protected buildHeaders(contentType: ContentType) {
|
||||||
|
// Don't try to access cookies during server-side rendering
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
const headers = new Headers();
|
||||||
|
if (contentType === ContentType.JSON || contentType === ContentType.PDF) {
|
||||||
|
headers.set("Content-Type", contentType);
|
||||||
|
}
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
const token = CookieService.getInstance().getCookie("leCoffreAccessToken");
|
const token = CookieService.getInstance().getCookie("leCoffreAccessToken");
|
||||||
|
|
||||||
const headers = new Headers();
|
const headers = new Headers();
|
||||||
@ -37,7 +46,14 @@ export default abstract class BaseApiService {
|
|||||||
if (contentType === ContentType.JSON || contentType === ContentType.PDF) {
|
if (contentType === ContentType.JSON || contentType === ContentType.PDF) {
|
||||||
headers.set("Content-Type", contentType);
|
headers.set("Content-Type", contentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only set Authorization header if token exists
|
||||||
|
if (token) {
|
||||||
headers.set("Authorization", `Bearer ${token}`);
|
headers.set("Authorization", `Bearer ${token}`);
|
||||||
|
} else {
|
||||||
|
console.warn("No access token found in cookies when building headers");
|
||||||
|
}
|
||||||
|
|
||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,39 +150,67 @@ export default abstract class BaseApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async checkJwtToken() {
|
private async checkJwtToken() {
|
||||||
const accessToken = CookieService.getInstance().getCookie("leCoffreAccessToken");
|
// Don't check tokens during server-side rendering
|
||||||
if (!accessToken) return;
|
if (typeof window === 'undefined') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const accessToken = CookieService.getInstance().getCookie("leCoffreAccessToken");
|
||||||
|
if (!accessToken) {
|
||||||
|
console.warn("No access token found during JWT check");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
const userDecodedToken = jwt_decode(accessToken) as IUserJwtPayload;
|
const userDecodedToken = jwt_decode(accessToken) as IUserJwtPayload;
|
||||||
const customerDecodedToken = jwt_decode(accessToken) as ICustomerJwtPayload;
|
const customerDecodedToken = jwt_decode(accessToken) as ICustomerJwtPayload;
|
||||||
|
|
||||||
if (!userDecodedToken && !customerDecodedToken) return;
|
if (!userDecodedToken && !customerDecodedToken) {
|
||||||
|
console.warn("Invalid token format during JWT check");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const now = Math.floor(Date.now() / 1000);
|
const now = Math.floor(Date.now() / 1000);
|
||||||
|
|
||||||
if (userDecodedToken.userId && userDecodedToken.exp < now) {
|
if (userDecodedToken.userId && userDecodedToken.exp < now) {
|
||||||
const refreshToken = CookieService.getInstance().getCookie("leCoffreRefreshToken");
|
const refreshToken = CookieService.getInstance().getCookie("leCoffreRefreshToken");
|
||||||
if (!refreshToken) {
|
if (!refreshToken) {
|
||||||
|
console.warn("Access token expired but no refresh token found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const decodedRefreshToken = jwt_decode(refreshToken) as IUserJwtPayload | ICustomerJwtPayload;
|
const decodedRefreshToken = jwt_decode(refreshToken) as IUserJwtPayload | ICustomerJwtPayload;
|
||||||
if (decodedRefreshToken.exp < now) {
|
if (decodedRefreshToken.exp < now) {
|
||||||
|
console.warn("Both access and refresh tokens are expired");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await JwtService.getInstance().refreshToken(refreshToken);
|
const refreshSuccess = await JwtService.getInstance().refreshToken(refreshToken);
|
||||||
|
if (!refreshSuccess) {
|
||||||
|
console.error("Failed to refresh token");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (customerDecodedToken.customerId && customerDecodedToken.exp < now) {
|
if (customerDecodedToken.customerId && customerDecodedToken.exp < now) {
|
||||||
const refreshToken = CookieService.getInstance().getCookie("leCoffreRefreshToken");
|
const refreshToken = CookieService.getInstance().getCookie("leCoffreRefreshToken");
|
||||||
if (!refreshToken) {
|
if (!refreshToken) {
|
||||||
|
console.warn("Access token expired but no refresh token found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const decodedRefreshToken = jwt_decode(refreshToken) as IUserJwtPayload | ICustomerJwtPayload;
|
const decodedRefreshToken = jwt_decode(refreshToken) as IUserJwtPayload | ICustomerJwtPayload;
|
||||||
if (decodedRefreshToken.exp < now) {
|
if (decodedRefreshToken.exp < now) {
|
||||||
|
console.warn("Both access and refresh tokens are expired");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await JwtService.getInstance().refreshToken(refreshToken);
|
const refreshSuccess = await JwtService.getInstance().refreshToken(refreshToken);
|
||||||
}
|
if (!refreshSuccess) {
|
||||||
|
console.error("Failed to refresh token");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error during JWT token check:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected async processResponse<T>(response: Response, request: () => Promise<Response>, ref?: IRef, fileName?: string): Promise<T> {
|
protected async processResponse<T>(response: Response, request: () => Promise<Response>, ref?: IRef, fileName?: string): Promise<T> {
|
||||||
let responseContent: T;
|
let responseContent: T;
|
||||||
|
122
src/front/Components/Debug/JwtDebugger.tsx
Normal file
122
src/front/Components/Debug/JwtDebugger.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
@ -36,6 +36,7 @@ export default function Header(props: IProps) {
|
|||||||
|
|
||||||
const loadSubscription = useCallback(async () => {
|
const loadSubscription = useCallback(async () => {
|
||||||
const jwt = JwtService.getInstance().decodeJwt();
|
const jwt = JwtService.getInstance().decodeJwt();
|
||||||
|
console.log("jwt:", jwt);
|
||||||
const subscription = await Subscriptions.getInstance().get({ where: { office: { uid: jwt?.office_Id } } });
|
const subscription = await Subscriptions.getInstance().get({ where: { office: { uid: jwt?.office_Id } } });
|
||||||
if (subscription[0]) {
|
if (subscription[0]) {
|
||||||
const stripeSubscription = await Stripe.getInstance().getStripeSubscriptionByUid(subscription[0].stripe_subscription_id!);
|
const stripeSubscription = await Stripe.getInstance().getStripeSubscriptionByUid(subscription[0].stripe_subscription_id!);
|
||||||
|
@ -18,6 +18,7 @@ export default function SubscriptionError() {
|
|||||||
|
|
||||||
const loadSubscription = useCallback(async () => {
|
const loadSubscription = useCallback(async () => {
|
||||||
const jwt = JwtService.getInstance().decodeJwt();
|
const jwt = JwtService.getInstance().decodeJwt();
|
||||||
|
console.log("jwt:", jwt);
|
||||||
const subscription = await Subscriptions.getInstance().get({ where: { office: { uid: jwt?.office_Id } } });
|
const subscription = await Subscriptions.getInstance().get({ where: { office: { uid: jwt?.office_Id } } });
|
||||||
if (!subscription[0]) return;
|
if (!subscription[0]) return;
|
||||||
setSubscription(subscription[0]);
|
setSubscription(subscription[0]);
|
||||||
|
@ -42,6 +42,7 @@ export default function SubscriptionFacturation() {
|
|||||||
const manageSubscription = async () => {
|
const manageSubscription = async () => {
|
||||||
try {
|
try {
|
||||||
const jwt = JwtService.getInstance().decodeJwt();
|
const jwt = JwtService.getInstance().decodeJwt();
|
||||||
|
console.log("jwt:", jwt);
|
||||||
const subscription = await Subscriptions.getInstance().get({ where: { office: { uid: jwt?.office_Id } } });
|
const subscription = await Subscriptions.getInstance().get({ where: { office: { uid: jwt?.office_Id } } });
|
||||||
if (!subscription[0]) return;
|
if (!subscription[0]) return;
|
||||||
const stripe_client_portal = await Stripe.getInstance().getClientPortalSession(subscription[0].stripe_subscription_id!);
|
const stripe_client_portal = await Stripe.getInstance().getClientPortalSession(subscription[0].stripe_subscription_id!);
|
||||||
@ -52,6 +53,7 @@ export default function SubscriptionFacturation() {
|
|||||||
const cancelOrReactivateSubscription = async () => {
|
const cancelOrReactivateSubscription = async () => {
|
||||||
try {
|
try {
|
||||||
const jwt = JwtService.getInstance().decodeJwt();
|
const jwt = JwtService.getInstance().decodeJwt();
|
||||||
|
console.log("jwt:", jwt);
|
||||||
const subscription = await Subscriptions.getInstance().get({ where: { office: { uid: jwt?.office_Id } } });
|
const subscription = await Subscriptions.getInstance().get({ where: { office: { uid: jwt?.office_Id } } });
|
||||||
if (!subscription[0]) return;
|
if (!subscription[0]) return;
|
||||||
const stripe_client_portal = await Stripe.getInstance().getClientPortalSession(subscription[0].stripe_subscription_id!);
|
const stripe_client_portal = await Stripe.getInstance().getClientPortalSession(subscription[0].stripe_subscription_id!);
|
||||||
@ -66,6 +68,7 @@ export default function SubscriptionFacturation() {
|
|||||||
const manageBilling = async () => {
|
const manageBilling = async () => {
|
||||||
try {
|
try {
|
||||||
const jwt = JwtService.getInstance().decodeJwt();
|
const jwt = JwtService.getInstance().decodeJwt();
|
||||||
|
console.log("jwt:", jwt);
|
||||||
const subscription = await Subscriptions.getInstance().get({ where: { office: { uid: jwt?.office_Id } } });
|
const subscription = await Subscriptions.getInstance().get({ where: { office: { uid: jwt?.office_Id } } });
|
||||||
if (!subscription[0]) return;
|
if (!subscription[0]) return;
|
||||||
const stripe_client_portal = await Stripe.getInstance().getClientPortalSession(subscription[0].stripe_subscription_id!);
|
const stripe_client_portal = await Stripe.getInstance().getClientPortalSession(subscription[0].stripe_subscription_id!);
|
||||||
@ -75,6 +78,7 @@ export default function SubscriptionFacturation() {
|
|||||||
|
|
||||||
const loadSubscription = useCallback(async () => {
|
const loadSubscription = useCallback(async () => {
|
||||||
const jwt = JwtService.getInstance().decodeJwt();
|
const jwt = JwtService.getInstance().decodeJwt();
|
||||||
|
console.log("jwt:", jwt);
|
||||||
const subscription = await Subscriptions.getInstance().get({ where: { office: { uid: jwt?.office_Id } } });
|
const subscription = await Subscriptions.getInstance().get({ where: { office: { uid: jwt?.office_Id } } });
|
||||||
if (!subscription[0]) {
|
if (!subscription[0]) {
|
||||||
router.push(Module.getInstance().get().modules.pages.Subscription.pages.New.props.path);
|
router.push(Module.getInstance().get().modules.pages.Subscription.pages.New.props.path);
|
||||||
|
@ -21,6 +21,7 @@ export default function SubscriptionSuccess() {
|
|||||||
|
|
||||||
const loadSubscription = useCallback(async () => {
|
const loadSubscription = useCallback(async () => {
|
||||||
const jwt = JwtService.getInstance().decodeJwt();
|
const jwt = JwtService.getInstance().decodeJwt();
|
||||||
|
console.log("jwt:", jwt);
|
||||||
const subscription = await Subscriptions.getInstance().get({ where: { office: { uid: jwt?.office_Id } } });
|
const subscription = await Subscriptions.getInstance().get({ where: { office: { uid: jwt?.office_Id } } });
|
||||||
if (!subscription[0]) return;
|
if (!subscription[0]) return;
|
||||||
setSubscription(subscription[0]);
|
setSubscription(subscription[0]);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import Users from "@Front/Api/LeCoffreApi/Notary/Users/Users";
|
import Users from "@Front/Api/LeCoffreApi/Notary/Users/Users";
|
||||||
import JwtService from "@Front/Services/JwtService/JwtService";
|
import JwtService from "@Front/Services/JwtService/JwtService";
|
||||||
|
import UserStore from "@Front/Stores/UserStore";
|
||||||
import User from "le-coffre-resources/dist/Notary";
|
import User from "le-coffre-resources/dist/Notary";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
@ -7,8 +8,23 @@ export default function useUser() {
|
|||||||
const [user, setUser] = useState<User | null>();
|
const [user, setUser] = useState<User | null>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// Don't run on server-side
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if user is connected before making API calls
|
||||||
|
if (!UserStore.instance.isConnected()) {
|
||||||
|
console.warn("User not connected, skipping API call");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const decodedJwt = JwtService.getInstance().decodeJwt();
|
const decodedJwt = JwtService.getInstance().decodeJwt();
|
||||||
if (!decodedJwt) return;
|
if (!decodedJwt) {
|
||||||
|
console.warn("No valid JWT found, skipping API call");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Users.getInstance()
|
Users.getInstance()
|
||||||
.getByUid(decodedJwt.userId, {
|
.getByUid(decodedJwt.userId, {
|
||||||
q: {
|
q: {
|
||||||
@ -17,6 +33,9 @@ export default function useUser() {
|
|||||||
})
|
})
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
setUser(user);
|
setUser(user);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Failed to fetch user:", error);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
@ -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 };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,46 @@ export default class UserStore {
|
|||||||
protected readonly event = new EventEmitter();
|
protected readonly event = new EventEmitter();
|
||||||
public accessToken: string | null = null;
|
public accessToken: string | null = null;
|
||||||
public refreshToken: string | null = null;
|
public refreshToken: string | null = null;
|
||||||
|
private initialized = false;
|
||||||
|
|
||||||
private constructor() {}
|
private constructor() {
|
||||||
|
// Don't initialize tokens during server-side rendering
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
this.initializeFromCookies();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private initializeFromCookies() {
|
||||||
|
if (this.initialized) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const accessToken = CookieService.getInstance().getCookie("leCoffreAccessToken");
|
||||||
|
const refreshToken = CookieService.getInstance().getCookie("leCoffreRefreshToken");
|
||||||
|
|
||||||
|
if (accessToken) {
|
||||||
|
this.accessToken = accessToken;
|
||||||
|
}
|
||||||
|
if (refreshToken) {
|
||||||
|
this.refreshToken = refreshToken;
|
||||||
|
}
|
||||||
|
this.initialized = true;
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("Failed to initialize tokens from cookies:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public isConnected(): boolean {
|
public isConnected(): boolean {
|
||||||
|
// Ensure initialization on client side
|
||||||
|
if (typeof window !== 'undefined' && !this.initialized) {
|
||||||
|
this.initializeFromCookies();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check both instance variable and cookie to ensure consistency
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
const cookieToken = CookieService.getInstance().getCookie("leCoffreAccessToken");
|
||||||
|
return !!(this.accessToken || cookieToken);
|
||||||
|
}
|
||||||
|
|
||||||
return !!this.accessToken;
|
return !!this.accessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,6 +63,10 @@ export default class UserStore {
|
|||||||
CookieService.getInstance().setCookie("leCoffreAccessToken", accessToken);
|
CookieService.getInstance().setCookie("leCoffreAccessToken", accessToken);
|
||||||
CookieService.getInstance().setCookie("leCoffreRefreshToken", refreshToken);
|
CookieService.getInstance().setCookie("leCoffreRefreshToken", refreshToken);
|
||||||
|
|
||||||
|
// Update instance variables
|
||||||
|
this.accessToken = accessToken;
|
||||||
|
this.refreshToken = refreshToken;
|
||||||
|
|
||||||
this.event.emit("connection", this.accessToken);
|
this.event.emit("connection", this.accessToken);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@ -41,6 +81,10 @@ export default class UserStore {
|
|||||||
CookieService.getInstance().deleteCookie("leCoffreAccessToken");
|
CookieService.getInstance().deleteCookie("leCoffreAccessToken");
|
||||||
CookieService.getInstance().deleteCookie("leCoffreRefreshToken");
|
CookieService.getInstance().deleteCookie("leCoffreRefreshToken");
|
||||||
|
|
||||||
|
// Clear instance variables
|
||||||
|
this.accessToken = null;
|
||||||
|
this.refreshToken = null;
|
||||||
|
|
||||||
this.event.emit("disconnection", this.accessToken);
|
this.event.emit("disconnection", this.accessToken);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
@ -9,10 +9,46 @@ export default class UserStore {
|
|||||||
protected readonly event = new EventEmitter();
|
protected readonly event = new EventEmitter();
|
||||||
public accessToken: string | null = null;
|
public accessToken: string | null = null;
|
||||||
public refreshToken: string | null = null;
|
public refreshToken: string | null = null;
|
||||||
|
private initialized = false;
|
||||||
|
|
||||||
private constructor() {}
|
private constructor() {
|
||||||
|
// Don't initialize tokens during server-side rendering
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
this.initializeFromCookies();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private initializeFromCookies() {
|
||||||
|
if (this.initialized) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const accessToken = CookieService.getInstance().getCookie("leCoffreAccessToken");
|
||||||
|
const refreshToken = CookieService.getInstance().getCookie("leCoffreRefreshToken");
|
||||||
|
|
||||||
|
if (accessToken) {
|
||||||
|
this.accessToken = accessToken;
|
||||||
|
}
|
||||||
|
if (refreshToken) {
|
||||||
|
this.refreshToken = refreshToken;
|
||||||
|
}
|
||||||
|
this.initialized = true;
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("Failed to initialize tokens from cookies:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public isConnected(): boolean {
|
public isConnected(): boolean {
|
||||||
|
// Ensure initialization on client side
|
||||||
|
if (typeof window !== 'undefined' && !this.initialized) {
|
||||||
|
this.initializeFromCookies();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check both instance variable and cookie to ensure consistency
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
const cookieToken = CookieService.getInstance().getCookie("leCoffreAccessToken");
|
||||||
|
return !!(this.accessToken || cookieToken);
|
||||||
|
}
|
||||||
|
|
||||||
return !!this.accessToken;
|
return !!this.accessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,6 +63,10 @@ export default class UserStore {
|
|||||||
CookieService.getInstance().setCookie("leCoffreAccessToken", accessToken);
|
CookieService.getInstance().setCookie("leCoffreAccessToken", accessToken);
|
||||||
CookieService.getInstance().setCookie("leCoffreRefreshToken", refreshToken);
|
CookieService.getInstance().setCookie("leCoffreRefreshToken", refreshToken);
|
||||||
|
|
||||||
|
// Update instance variables
|
||||||
|
this.accessToken = accessToken;
|
||||||
|
this.refreshToken = refreshToken;
|
||||||
|
|
||||||
this.event.emit("connection", this.accessToken);
|
this.event.emit("connection", this.accessToken);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@ -41,6 +81,10 @@ export default class UserStore {
|
|||||||
CookieService.getInstance().deleteCookie("leCoffreAccessToken");
|
CookieService.getInstance().deleteCookie("leCoffreAccessToken");
|
||||||
CookieService.getInstance().deleteCookie("leCoffreRefreshToken");
|
CookieService.getInstance().deleteCookie("leCoffreRefreshToken");
|
||||||
|
|
||||||
|
// Clear instance variables
|
||||||
|
this.accessToken = null;
|
||||||
|
this.refreshToken = null;
|
||||||
|
|
||||||
this.event.emit("disconnection", this.accessToken);
|
this.event.emit("disconnection", this.accessToken);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user