import { queryOne } from '../../utils/db' import { requireAuth } from '../../utils/session' /** * 구글 그룹 목록 조회 * GET /api/google-group/list * * Cloud Identity Groups API 사용 */ export default defineEventHandler(async (event) => { const session = await requireAuth(event) // 사용자의 Google 토큰 조회 const employee = await queryOne(` SELECT google_access_token, google_refresh_token, google_token_expires_at FROM wr_employee_info WHERE employee_id = $1 `, [session.employeeId]) if (!employee?.google_access_token) { throw createError({ statusCode: 401, message: 'Google 계정이 연결되지 않았습니다. 먼저 Google 로그인을 해주세요.' }) } let accessToken = employee.google_access_token // 토큰 만료 확인 및 갱신 if (employee.google_token_expires_at && new Date(employee.google_token_expires_at) < new Date()) { accessToken = await refreshGoogleToken(session.employeeId, employee.google_refresh_token) } try { // Cloud Identity Groups API로 그룹 목록 조회 const response = await $fetch('https://cloudidentity.googleapis.com/v1/groups:search', { method: 'GET', headers: { 'Authorization': `Bearer ${accessToken}` }, query: { query: 'parent == "customers/my_customer" && "cloudidentity.googleapis.com/groups.discussion_forum" in labels', pageSize: 100 } }) return { groups: (response.groups || []).map((g: any) => ({ groupId: g.name?.split('/')[1], groupKey: g.groupKey?.id, displayName: g.displayName, description: g.description, email: g.groupKey?.id })) } } catch (e: any) { console.error('Google Groups API error:', e) // 권한 없음 에러 if (e.status === 403) { throw createError({ statusCode: 403, message: '구글 그룹 접근 권한이 없습니다. 관리자에게 문의하세요.' }) } throw createError({ statusCode: 500, message: '구글 그룹 목록을 가져오는데 실패했습니다.' }) } }) /** * Google 토큰 갱신 */ async function refreshGoogleToken(employeeId: number, refreshToken: string): Promise { const config = useRuntimeConfig() const response = await $fetch('https://oauth2.googleapis.com/token', { method: 'POST', body: new URLSearchParams({ client_id: config.googleClientId, client_secret: config.googleClientSecret, refresh_token: refreshToken, grant_type: 'refresh_token' }).toString(), headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }) if (response.access_token) { // DB 업데이트 const { execute } = await import('../../utils/db') await execute(` UPDATE wr_employee_info SET google_access_token = $1, google_token_expires_at = NOW() + INTERVAL '${response.expires_in} seconds' WHERE employee_id = $2 `, [response.access_token, employeeId]) return response.access_token } throw new Error('토큰 갱신 실패') }