Adds full OAuth2 flow, bidirectional task sync, calendar event CRUD, caching with background refresh, and shared token management for Microsoft/Outlook services. Extracts common token refresh logic into shared outlook-token.ts utility. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
42 lines
1.5 KiB
TypeScript
42 lines
1.5 KiB
TypeScript
import { prisma } from '@/lib/prisma';
|
|
import { refreshAccessToken } from '@/lib/outlook-calendar';
|
|
|
|
/**
|
|
* Get a valid Outlook access token for a user, refreshing if needed.
|
|
* Shared across task sync, import, and list routes.
|
|
*/
|
|
export async function getOutlookAccessToken(userId: string): Promise<string | null> {
|
|
const conn = await prisma.calendarConnection.findFirst({
|
|
where: { userId, provider: 'outlook' }
|
|
});
|
|
if (!conn) return null;
|
|
|
|
const bufferMs = 5 * 60 * 1000;
|
|
const needsRefresh = !conn.expiresAt ||
|
|
new Date().getTime() > (new Date(conn.expiresAt).getTime() - bufferMs);
|
|
|
|
if (needsRefresh && conn.refreshToken) {
|
|
try {
|
|
const tokenData = await refreshAccessToken(conn.refreshToken);
|
|
if (tokenData.access_token) {
|
|
const expiresAt = new Date();
|
|
expiresAt.setSeconds(expiresAt.getSeconds() + tokenData.expires_in);
|
|
await prisma.calendarConnection.update({
|
|
where: { id: conn.id },
|
|
data: {
|
|
accessToken: tokenData.access_token,
|
|
refreshToken: tokenData.refresh_token || conn.refreshToken,
|
|
expiresAt
|
|
}
|
|
});
|
|
return tokenData.access_token;
|
|
}
|
|
} catch (e) {
|
|
console.error('Failed to refresh Outlook token:', e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
return conn.accessToken;
|
|
}
|