# Gmail Tokens 데이터베이스 구성 ## 작성일: 2025-08-18 ## 작성자: Claude (with heejae) --- ## 1. 테이블 생성 정보 ### 1.1 데이터베이스 접속 정보 ```bash Host: localhost Port: 5432 Database: auth_db User: robeings Password: robeings ``` ### 1.2 생성된 테이블: `gmail_tokens` ```sql CREATE TABLE gmail_tokens ( id SERIAL PRIMARY KEY, user_id VARCHAR(100) UNIQUE NOT NULL, robing_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 (필수) ```json { "access_token": "ya29.xxxx", "refresh_token": "1//xxxx", "token_type": "Bearer" } ``` ### 2.2 oauth_config ```json { "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 ```json [ "https://www.googleapis.com/auth/gmail.send", "https://www.googleapis.com/auth/gmail.readonly", "https://www.googleapis.com/auth/gmail.modify" ] ``` ### 2.4 metadata ```json { "email": "user@gmail.com", "display_name": "사용자명", "account_type": "gmail", "slack_user_id": "U091UNVE41M", "source_file": "original_filename.json", "imported_at": "2025-08-18" } ``` --- ## 3. 인덱스 구성 ```sql -- 기본 인덱스 CREATE INDEX idx_gmail_tokens_user_id ON gmail_tokens(user_id); CREATE INDEX idx_gmail_tokens_robing_id ON gmail_tokens(robing_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. 자동 업데이트 트리거 ```sql -- 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 | robing_id | 권한 상태 | 이메일 발송 가능 | |---------|-----------|-----------|-----------------| | heejae | rb8001 | gmail.modify만 있음 | ❌ 불가능 | | test | rb8001 | gmail.send + modify | ✅ 가능 | | unknown | NULL | 프로필 권한만 | ❌ 불가능 | ### 5.3 권한 문제 - **중요**: `gmail.modify`만으로는 이메일 발송 불가 - 이메일 발송하려면 `gmail.send` 권한 필수 - heejae 계정은 재인증 필요 --- ## 6. 유용한 쿼리 ### 6.1 토큰 조회 ```sql -- 특정 사용자 토큰 조회 SELECT token_data->>'access_token' as access_token FROM gmail_tokens WHERE user_id = 'test'; -- 이메일 발송 가능한 사용자 찾기 SELECT user_id, robing_id FROM gmail_tokens WHERE scopes @> '["https://www.googleapis.com/auth/gmail.send"]'; ``` ### 6.2 토큰 업데이트 ```sql -- 액세스 토큰 갱신 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 메타데이터 활용 ```sql -- Slack 사용자와 매핑 SELECT * FROM gmail_tokens WHERE metadata->>'slack_user_id' = 'U091UNVE41M'; -- 특정 로빙의 Gmail 계정 찾기 SELECT user_id, metadata->>'email' as gmail_account FROM gmail_tokens WHERE robing_id = 'rb8001'; ``` --- ## 7. Python 연동 예시 ```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 1. **권한 수정 필요** - heejae 계정에 `gmail.send` 권한 추가 (재인증 필요) - unknown 계정 용도 확인 및 권한 설정 2. **Slack 사용자 매핑** - metadata에 slack_user_id 추가 - Slack User ID ↔ Gmail 계정 매핑 테이블 고려 3. **토큰 자동 갱신** - refresh_token 사용한 자동 갱신 로직 구현 - expiry 필드 활용한 만료 체크 4. **보안 강화** - 토큰 암호화 고려 - 접근 로그 테이블 추가 5. **skill-email 서비스 수정** - 파일 기반 → DB 기반 토큰 조회로 변경 - PostgreSQL 연결 설정 추가 --- ## 9. 참고사항 - JSONB 타입 사용으로 유연한 스키마 확장 가능 - GIN 인덱스로 JSON 내부 검색 성능 최적화 - 트리거로 updated_at 자동 관리 - 모든 토큰 정보가 중앙 집중식으로 관리됨