diff --git a/app/api/auth/[...nextauth]/route.ts b/app/api/auth/[...nextauth]/route.ts index 5cc81efb..4ff56ed4 100644 --- a/app/api/auth/[...nextauth]/route.ts +++ b/app/api/auth/[...nextauth]/route.ts @@ -14,6 +14,8 @@ declare module "next-auth" { role: string[]; }; accessToken: string; + rocketChatToken: string | null; + rocketChatUserId: string | null; } interface JWT { @@ -24,6 +26,8 @@ declare module "next-auth" { username: string; first_name: string; last_name: string; + rocketChatToken: string | null; + rocketChatUserId: string | null; } } @@ -68,7 +72,6 @@ export const authOptions: NextAuthOptions = { token.username = (profile as any).preferred_username ?? profile.email?.split('@')[0] ?? ''; token.first_name = (profile as any).given_name ?? ''; token.last_name = (profile as any).family_name ?? ''; - return token; } // Return previous token if not expired @@ -110,6 +113,8 @@ export const authOptions: NextAuthOptions = { accessToken: tokens.access_token, refreshToken: tokens.refresh_token ?? token.refreshToken, accessTokenExpires: Date.now() + tokens.expires_in * 1000, + rocketChatToken: token.rocketChatToken || null, + rocketChatUserId: token.rocketChatUserId || null, }; } catch (error) { console.error("Error refreshing token for user:", token.sub); @@ -118,6 +123,8 @@ export const authOptions: NextAuthOptions = { return { ...token, error: "RefreshAccessTokenError", + rocketChatToken: null, + rocketChatUserId: null, }; } }, @@ -140,6 +147,11 @@ export const authOptions: NextAuthOptions = { username: token.username ?? '', role: token.role ?? [], }; + + // Add Rocket.Chat credentials to session + session.rocketChatToken = token.rocketChatToken || null; + session.rocketChatUserId = token.rocketChatUserId || null; + return session; }, }, diff --git a/app/api/rocket-chat/messages/route.ts b/app/api/rocket-chat/messages/route.ts index c7294227..7a7fe602 100644 --- a/app/api/rocket-chat/messages/route.ts +++ b/app/api/rocket-chat/messages/route.ts @@ -2,30 +2,34 @@ import { getServerSession } from "next-auth"; import { authOptions } from "@/app/api/auth/[...nextauth]/route"; import { NextResponse } from "next/server"; -// Helper function to create/refresh token -async function ensureValidToken(baseUrl: string, userId: string, currentToken: string | null) { +// Helper function to get user token using admin credentials +async function getUserToken(baseUrl: string) { try { - // Try to create a new token - const tokenResponse = await fetch(`${baseUrl}/api/v1/users.createToken`, { + // Step 1: Use admin token to authenticate + const adminHeaders = { + 'X-Auth-Token': process.env.ROCKET_CHAT_TOKEN!, + 'X-User-Id': process.env.ROCKET_CHAT_USER_ID!, + 'Content-Type': 'application/json' + }; + + // Step 2: Create user token using admin credentials + const createTokenResponse = await fetch(`${baseUrl}/api/v1/users.createToken`, { method: 'POST', - headers: { - 'X-Auth-Token': currentToken || '', - 'X-User-Id': userId, - }, + headers: adminHeaders }); - if (tokenResponse.ok) { - const tokenData = await tokenResponse.json(); - return { - token: tokenData.data.authToken, - userId: tokenData.data.userId, - }; + if (!createTokenResponse.ok) { + console.error('Failed to create user token:', createTokenResponse.status); + return null; } - console.error('Failed to create/refresh token:', tokenResponse.status); - return null; + const tokenData = await createTokenResponse.json(); + return { + authToken: tokenData.data.authToken, + userId: tokenData.data.userId + }; } catch (error) { - console.error('Error creating/refreshing token:', error); + console.error('Error getting user token:', error); return null; } } @@ -71,25 +75,20 @@ export async function GET(request: Request) { }); } - // Ensure we have valid token - const tokenInfo = await ensureValidToken( - baseUrl, - session.rocketChatUserId || '', - session.rocketChatToken || null - ); - - if (!tokenInfo) { - return new Response(JSON.stringify({ error: 'Failed to authenticate with Rocket.Chat' }), { + // Step 1 & 2: Get user token using admin credentials + const userToken = await getUserToken(baseUrl); + if (!userToken) { + return new Response(JSON.stringify({ error: 'Failed to create user token' }), { status: 401, headers: { 'Content-Type': 'application/json' }, }); } - // Get user's subscriptions with new token + // Step 3: Use the user token to fetch subscriptions const subscriptionsResponse = await fetch(`${baseUrl}/api/v1/subscriptions.get`, { headers: { - 'X-Auth-Token': tokenInfo.token, - 'X-User-Id': tokenInfo.userId, + 'X-Auth-Token': userToken.authToken, + 'X-User-Id': userToken.userId, }, }); @@ -102,13 +101,11 @@ export async function GET(request: Request) { } const subscriptionsData = await subscriptionsResponse.json(); - const userSubscriptions = subscriptionsData.update.filter((subscription: any) => - subscription.t === 'd' ? subscription.rid.includes(tokenInfo.userId) : true - ); - + const userSubscriptions = subscriptionsData.update; const messages: any[] = []; const processedRooms = new Set(); + // Step 3: Use the same user token to fetch messages for (const subscription of userSubscriptions) { if (messages.length >= 6 || processedRooms.has(subscription.rid)) continue; processedRooms.add(subscription.rid); @@ -118,8 +115,8 @@ export async function GET(request: Request) { `${baseUrl}/api/v1/chat.getMessage`, { method: 'POST', headers: { - 'X-Auth-Token': tokenInfo.token, - 'X-User-Id': tokenInfo.userId, + 'X-Auth-Token': userToken.authToken, + 'X-User-Id': userToken.userId, 'Content-Type': 'application/json', }, body: JSON.stringify({ diff --git a/components/parole.tsx b/components/parole.tsx index eec78562..c211abf0 100644 --- a/components/parole.tsx +++ b/components/parole.tsx @@ -34,16 +34,11 @@ export function Parole() { if (isRefresh) { setRefreshing(true); } + const response = await fetch('/api/rocket-chat/messages', { cache: 'no-store', next: { revalidate: 0 }, }); - - if (response.status === 401) { - // Handle authentication error - setError('Session expired. Please sign in again.'); - return; - } if (!response.ok) { const errorData = await response.json(); @@ -62,11 +57,6 @@ export function Parole() { console.error('Error fetching messages:', err); const errorMessage = err instanceof Error ? err.message : 'Failed to fetch messages'; setError(errorMessage); - - // Clear polling if we have an authentication error - if (errorMessage.includes('Session expired')) { - return; - } } finally { setLoading(false); setRefreshing(false);