- Gmail passport 아이템 시스템 설계 - 작업 분담: 종태(프론트), 희재(통합), 서버관리자(인프라) - robeing_id로 컬럼명 통일 - 레벨 5 제한, passport 슬롯 정의 - DB 테이블 구조 수정 (robing_id → robeing_id)
5.8 KiB
5.8 KiB
Gmail Tokens 데이터베이스 구성
작성일: 2025-08-18
작성자: Claude (with heejae)
1. 테이블 생성 정보
1.1 데이터베이스 접속 정보
Host: localhost
Port: 5432
Database: auth_db
User: robeings
Password: robeings
1.2 생성된 테이블: gmail_tokens
CREATE TABLE gmail_tokens (
id SERIAL PRIMARY KEY,
user_id VARCHAR(100) UNIQUE NOT NULL,
robeing_id VARCHAR(50),
token_data JSONB NOT NULL,
oauth_config JSONB,
scopes JSONB,
metadata JSONB,
expiry TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
2. JSONB 컬럼 구조
2.1 token_data (필수)
{
"access_token": "ya29.xxxx",
"refresh_token": "1//xxxx",
"token_type": "Bearer"
}
2.2 oauth_config
{
"client_id": "xxx.apps.googleusercontent.com",
"client_secret": "GOCSPX-xxxx",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_uri": "https://accounts.google.com/o/oauth2/auth"
}
2.3 scopes
[
"https://www.googleapis.com/auth/gmail.send",
"https://www.googleapis.com/auth/gmail.readonly",
"https://www.googleapis.com/auth/gmail.modify"
]
2.4 metadata
{
"email": "user@gmail.com",
"display_name": "사용자명",
"account_type": "gmail",
"slack_user_id": "U091UNVE41M",
"source_file": "original_filename.json",
"imported_at": "2025-08-18"
}
3. 인덱스 구성
-- 기본 인덱스
CREATE INDEX idx_gmail_tokens_user_id ON gmail_tokens(user_id);
CREATE INDEX idx_gmail_tokens_robeing_id ON gmail_tokens(robeing_id);
-- JSON 검색용 GIN 인덱스
CREATE INDEX idx_gmail_tokens_token_data ON gmail_tokens USING GIN (token_data);
CREATE INDEX idx_gmail_tokens_oauth_config ON gmail_tokens USING GIN (oauth_config);
4. 자동 업데이트 트리거
-- updated_at 자동 갱신 함수
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- 트리거 생성
CREATE TRIGGER update_gmail_tokens_updated_at
BEFORE UPDATE ON gmail_tokens
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
5. 마이그레이션 완료 데이터
5.1 원본 파일 위치
/home/admin/auth-server/tokens/
├── heejae_gmail.json
├── test_gmail.json
└── unknown_gmail.json
5.2 현재 저장된 데이터
| user_id | robeing_id | 권한 상태 | 이메일 발송 가능 |
|---|---|---|---|
| heejae | rb8001 | gmail.modify만 있음 | ❌ 불가능 |
| test | rb8001 | gmail.send + modify | ✅ 가능 |
| unknown | NULL | 프로필 권한만 | ❌ 불가능 |
5.3 권한 문제
- 중요:
gmail.modify만으로는 이메일 발송 불가 - 이메일 발송하려면
gmail.send권한 필수 - heejae 계정은 재인증 필요
6. 유용한 쿼리
6.1 토큰 조회
-- 특정 사용자 토큰 조회
SELECT token_data->>'access_token' as access_token
FROM gmail_tokens
WHERE user_id = 'test';
-- 이메일 발송 가능한 사용자 찾기
SELECT user_id, robeing_id
FROM gmail_tokens
WHERE scopes @> '["https://www.googleapis.com/auth/gmail.send"]';
6.2 토큰 업데이트
-- 액세스 토큰 갱신
UPDATE gmail_tokens
SET token_data = jsonb_set(
token_data,
'{access_token}',
'"new_access_token"'
)
WHERE user_id = 'test';
-- 스코프 추가
UPDATE gmail_tokens
SET scopes = scopes || '["https://www.googleapis.com/auth/gmail.send"]'::jsonb
WHERE user_id = 'heejae';
6.3 메타데이터 활용
-- Slack 사용자와 매핑
SELECT * FROM gmail_tokens
WHERE metadata->>'slack_user_id' = 'U091UNVE41M';
-- 특정 로빙의 Gmail 계정 찾기
SELECT user_id, metadata->>'email' as gmail_account
FROM gmail_tokens
WHERE robeing_id = 'rb8001';
7. Python 연동 예시
import psycopg2
import json
from psycopg2.extras import RealDictCursor
# 연결
conn = psycopg2.connect(
host="localhost",
database="auth_db",
user="robeings",
password="robeings"
)
# 토큰 조회
with conn.cursor(cursor_factory=RealDictCursor) as cur:
cur.execute("""
SELECT
token_data->>'access_token' as access_token,
token_data->>'refresh_token' as refresh_token,
oauth_config,
scopes
FROM gmail_tokens
WHERE user_id = %s
""", ('test',))
token_info = cur.fetchone()
# Google OAuth 객체 생성에 사용
credentials = {
'token': token_info['access_token'],
'refresh_token': token_info['refresh_token'],
'client_id': token_info['oauth_config']['client_id'],
'client_secret': token_info['oauth_config']['client_secret'],
'scopes': token_info['scopes']
}
8. 다음 단계 TODO
-
권한 수정 필요
- heejae 계정에
gmail.send권한 추가 (재인증 필요) - unknown 계정 용도 확인 및 권한 설정
- heejae 계정에
-
Slack 사용자 매핑
- metadata에 slack_user_id 추가
- Slack User ID ↔ Gmail 계정 매핑 테이블 고려
-
토큰 자동 갱신
- refresh_token 사용한 자동 갱신 로직 구현
- expiry 필드 활용한 만료 체크
-
보안 강화
- 토큰 암호화 고려
- 접근 로그 테이블 추가
-
skill-email 서비스 수정
- 파일 기반 → DB 기반 토큰 조회로 변경
- PostgreSQL 연결 설정 추가
9. 참고사항
- JSONB 타입 사용으로 유연한 스키마 확장 가능
- GIN 인덱스로 JSON 내부 검색 성능 최적화
- 트리거로 updated_at 자동 관리
- 모든 토큰 정보가 중앙 집중식으로 관리됨