Briefing granulaire, pistes rapides puis enrichissement async, layout persisté v5, suggestions agents, intégration Gmail et navigation sidebar alignée sur /home. Co-authored-by: Cursor <cursoragent@cursor.com>
67 lines
2.2 KiB
TypeScript
67 lines
2.2 KiB
TypeScript
import prisma from '@/lib/prisma'
|
|
|
|
export function getGoogleOAuthCredentials() {
|
|
return {
|
|
clientId: process.env.GOOGLE_CALENDAR_CLIENT_ID || process.env.AUTH_GOOGLE_ID || '',
|
|
clientSecret: process.env.GOOGLE_CALENDAR_CLIENT_SECRET || process.env.AUTH_GOOGLE_SECRET || '',
|
|
}
|
|
}
|
|
|
|
export async function readIntegrationMeta(userId: string): Promise<Record<string, unknown>> {
|
|
const aiSettings = await prisma.userAISettings.findUnique({
|
|
where: { userId },
|
|
select: { integrationTokens: true },
|
|
})
|
|
try {
|
|
const raw = aiSettings?.integrationTokens
|
|
if (!raw) return {}
|
|
return typeof raw === 'string' ? JSON.parse(raw) : (raw as Record<string, unknown>)
|
|
} catch {
|
|
return {}
|
|
}
|
|
}
|
|
|
|
export async function writeIntegrationMeta(userId: string, meta: Record<string, unknown>) {
|
|
await prisma.userAISettings.upsert({
|
|
where: { userId },
|
|
update: { integrationTokens: JSON.stringify(meta) },
|
|
create: { userId, integrationTokens: JSON.stringify(meta) },
|
|
})
|
|
}
|
|
|
|
export async function getGoogleTokens(
|
|
userId: string,
|
|
prefix: 'calendar' | 'gmail',
|
|
): Promise<{ accessToken: string; refreshToken: string } | null> {
|
|
const meta = await readIntegrationMeta(userId)
|
|
const accessToken = meta[`${prefix}AccessToken`] as string | undefined
|
|
const refreshToken = meta[`${prefix}RefreshToken`] as string | undefined
|
|
if (accessToken && refreshToken) return { accessToken, refreshToken }
|
|
return null
|
|
}
|
|
|
|
export async function refreshGoogleAccessToken(
|
|
userId: string,
|
|
prefix: 'calendar' | 'gmail',
|
|
refreshToken: string,
|
|
): Promise<string | null> {
|
|
const { clientId, clientSecret } = getGoogleOAuthCredentials()
|
|
const res = await fetch('https://oauth2.googleapis.com/token', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
body: new URLSearchParams({
|
|
client_id: clientId,
|
|
client_secret: clientSecret,
|
|
refresh_token: refreshToken,
|
|
grant_type: 'refresh_token',
|
|
}),
|
|
})
|
|
const data = await res.json()
|
|
if (!data.access_token) return null
|
|
|
|
const meta = await readIntegrationMeta(userId)
|
|
meta[`${prefix}AccessToken`] = data.access_token
|
|
await writeIntegrationMeta(userId, meta)
|
|
return data.access_token as string
|
|
}
|