New token arch
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { create } from 'zustand';
|
||||
import { persist, createJSONStorage } from 'zustand/middleware';
|
||||
import { GLOBAL_USER_ROLES, type GlobalUserRole } from '../types/roles';
|
||||
import { getSubscriptionFromJWT, getTenantAccessFromJWT, getPrimaryTenantIdFromJWT, JWTSubscription } from '../utils/jwt';
|
||||
import { JWTSubscription as JWTSubscriptionType } from '../utils/jwt';
|
||||
|
||||
export interface User {
|
||||
id: string;
|
||||
@@ -26,6 +28,14 @@ export interface AuthState {
|
||||
isAuthenticated: boolean;
|
||||
isLoading: boolean;
|
||||
error: string | null;
|
||||
jwtSubscription: JWTSubscription | null;
|
||||
jwtTenantAccess: Array<{
|
||||
id: string;
|
||||
role: string;
|
||||
tier: string;
|
||||
}> | null;
|
||||
primaryTenantId: string | null;
|
||||
subscription_from_jwt?: boolean;
|
||||
|
||||
// Actions
|
||||
login: (email: string, password: string) => Promise<void>;
|
||||
@@ -43,7 +53,7 @@ export interface AuthState {
|
||||
updateUser: (updates: Partial<User>) => void;
|
||||
clearError: () => void;
|
||||
setLoading: (loading: boolean) => void;
|
||||
setDemoAuth: (token: string, demoUser: Partial<User>) => void;
|
||||
setDemoAuth: (token: string, demoUser: Partial<User>, subscriptionTier?: string) => void;
|
||||
|
||||
// Permission helpers
|
||||
hasPermission: (permission: string) => boolean;
|
||||
@@ -78,6 +88,11 @@ export const useAuthStore = create<AuthState>()(
|
||||
apiClient.setRefreshToken(response.refresh_token);
|
||||
}
|
||||
|
||||
// NEW: Extract subscription from JWT
|
||||
const jwtSubscription = getSubscriptionFromJWT(response.access_token);
|
||||
const jwtTenantAccess = getTenantAccessFromJWT(response.access_token);
|
||||
const primaryTenantId = getPrimaryTenantIdFromJWT(response.access_token);
|
||||
|
||||
set({
|
||||
user: response.user || null,
|
||||
token: response.access_token,
|
||||
@@ -85,6 +100,9 @@ export const useAuthStore = create<AuthState>()(
|
||||
isAuthenticated: true,
|
||||
isLoading: false,
|
||||
error: null,
|
||||
jwtSubscription,
|
||||
jwtTenantAccess,
|
||||
primaryTenantId,
|
||||
});
|
||||
} else {
|
||||
throw new Error('Login failed');
|
||||
@@ -192,12 +210,23 @@ export const useAuthStore = create<AuthState>()(
|
||||
apiClient.setRefreshToken(response.refresh_token);
|
||||
}
|
||||
|
||||
// NEW: Extract FRESH subscription from new JWT
|
||||
const jwtSubscription = getSubscriptionFromJWT(response.access_token);
|
||||
const jwtTenantAccess = getTenantAccessFromJWT(response.access_token);
|
||||
const primaryTenantId = getPrimaryTenantIdFromJWT(response.access_token);
|
||||
|
||||
set({
|
||||
token: response.access_token,
|
||||
refreshToken: response.refresh_token || refreshToken,
|
||||
isLoading: false,
|
||||
error: null,
|
||||
// NEW: Update subscription from fresh JWT
|
||||
jwtSubscription,
|
||||
jwtTenantAccess,
|
||||
primaryTenantId,
|
||||
});
|
||||
|
||||
console.log('Auth refreshed with new subscription:', jwtSubscription?.tier);
|
||||
} else {
|
||||
throw new Error('Token refresh failed');
|
||||
}
|
||||
@@ -231,12 +260,19 @@ export const useAuthStore = create<AuthState>()(
|
||||
set({ isLoading: loading });
|
||||
},
|
||||
|
||||
setDemoAuth: (token: string, demoUser: Partial<User>) => {
|
||||
setDemoAuth: (token: string, demoUser: Partial<User>, subscriptionTier?: string) => {
|
||||
console.log('🔧 [Auth Store] setDemoAuth called - demo sessions use X-Demo-Session-Id header, not JWT');
|
||||
// DO NOT set API client token for demo sessions!
|
||||
// Demo authentication works via X-Demo-Session-Id header, not JWT
|
||||
// The demo middleware handles authentication server-side
|
||||
|
||||
// NEW: Create synthetic JWT subscription data for demo sessions
|
||||
const jwtSubscription = subscriptionTier ? {
|
||||
tier: subscriptionTier as 'starter' | 'professional' | 'enterprise',
|
||||
status: 'active' as const,
|
||||
valid_until: null
|
||||
} : null;
|
||||
|
||||
// Update store state so user is marked as authenticated
|
||||
set({
|
||||
token: null, // No JWT token for demo sessions
|
||||
@@ -245,8 +281,10 @@ export const useAuthStore = create<AuthState>()(
|
||||
isAuthenticated: true, // User is authenticated via demo session
|
||||
isLoading: false,
|
||||
error: null,
|
||||
jwtSubscription, // NEW: Set subscription data for demo sessions
|
||||
subscription_from_jwt: true, // NEW: Flag to indicate subscription is from JWT
|
||||
});
|
||||
console.log('✅ [Auth Store] Demo auth state updated (no JWT token)');
|
||||
console.log('✅ [Auth Store] Demo auth state updated (no JWT token)', { subscriptionTier });
|
||||
},
|
||||
|
||||
// Permission helpers - Global user permissions only
|
||||
@@ -323,6 +361,9 @@ export const useAuthUser = () => useAuthStore((state) => state.user);
|
||||
export const useIsAuthenticated = () => useAuthStore((state) => state.isAuthenticated);
|
||||
export const useAuthLoading = () => useAuthStore((state) => state.isLoading);
|
||||
export const useAuthError = () => useAuthStore((state) => state.error);
|
||||
export const useJWTSubscription = () => useAuthStore((state) => state.jwtSubscription);
|
||||
export const useJWTTenantAccess = () => useAuthStore((state) => state.jwtTenantAccess);
|
||||
export const usePrimaryTenantId = () => useAuthStore((state) => state.primaryTenantId);
|
||||
export const usePermissions = () => useAuthStore((state) => ({
|
||||
hasPermission: state.hasPermission,
|
||||
hasRole: state.hasRole,
|
||||
|
||||
Reference in New Issue
Block a user