-
Notifications
You must be signed in to change notification settings - Fork 1
로컬 디비 생성 로직 및 utils, 암호화 부분 생성 #32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7d66003
2011e7f
10565b2
c33a2ec
8a9644f
9167bc7
416235e
b8d50d3
bb14bce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| # app/core/db_driver_enum.py | ||
| # app/core/enum/db_driver.py | ||
| from enum import Enum | ||
|
|
||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| import os | ||
| import base64 | ||
| from Crypto.Cipher import AES | ||
| from Crypto.Util.Padding import pad, unpad | ||
| from Crypto.Random import get_random_bytes | ||
|
|
||
| """ | ||
| 보안 원칙을 적용한 AES-256 암호화 및 복호화 클래스입니다. | ||
| - 암호화 시 매번 새로운 랜덤 IV를 생성합니다. | ||
| """ | ||
| class AES256: | ||
| _key = base64.b64decode(os.getenv("ENV_AES256_KEY")) | ||
|
|
||
| @staticmethod | ||
| def encrypt(text: str) -> str: | ||
| iv = get_random_bytes(AES.block_size) | ||
|
|
||
| cipher = AES.new(AES256._key, AES.MODE_CBC, iv) | ||
|
|
||
| data_bytes = text.encode('utf-8') | ||
| padded_bytes = pad(data_bytes, AES.block_size) | ||
|
|
||
| encrypted_bytes = cipher.encrypt(padded_bytes) | ||
|
|
||
| combined_bytes = iv + encrypted_bytes | ||
| return base64.b64encode(combined_bytes).decode('utf-8') | ||
|
|
||
| @staticmethod | ||
| def decrypt(cipher_text: str) -> str: | ||
| """ | ||
| AES-256으로 암호화된 텍스트를 복호화합니다. | ||
| """ | ||
| combined_bytes = base64.b64decode(cipher_text) | ||
|
|
||
| iv = combined_bytes[:AES.block_size] | ||
| encrypted_bytes = combined_bytes[AES.block_size:] | ||
|
|
||
| cipher = AES.new(AES256._key, AES.MODE_CBC, iv) | ||
|
|
||
| decrypted_padded_bytes = cipher.decrypt(encrypted_bytes) | ||
| decrypted_bytes = unpad(decrypted_padded_bytes, AES.block_size) | ||
|
|
||
| return decrypted_bytes.decode('utf-8') | ||
|
|
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 추후에 UUID 는 언제 사용해야하나요?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. uuid는 auto_increment로 진행되는 부분을 uuid로 진행할지 고민중이라 일단 만들어놨습니다.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 그러면 로컬 db에 값 추가(생성)할때 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| import uuid | ||
| from pathlib import Path | ||
|
|
||
| # 앱 데이터를 저장할 폴더 이름 | ||
| APP_DATA_DIR_NAME = ".qgenie" | ||
|
|
||
| def get_db_path() -> Path: | ||
| """ | ||
| 사용자 홈 디렉터리 내에 앱 데이터 폴더를 만들고, | ||
| SQLite DB 파일의 전체 경로를 반환합니다. | ||
| """ | ||
| home_dir = Path.home() | ||
| app_data_dir = home_dir / APP_DATA_DIR_NAME | ||
| app_data_dir.mkdir(exist_ok=True) | ||
| db_path = app_data_dir / "local_storage.sqlite" | ||
| return db_path | ||
|
|
||
| def generate_uuid() -> str: | ||
| return uuid.uuid4().hex.upper() | ||
|
|
||
| def generate_prefixed_uuid(prefix: str) -> str: | ||
| return f"{prefix.upper()}-{uuid.uuid4().hex.upper()}" | ||
|
|
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ConnectionProfile 테이블 생성안의 name이 profile_name인거죠? 나머지 DB 테이블들은 추후 추가 ?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| # db/init_db.py | ||
| import sqlite3 | ||
| from app.core.utils import get_db_path | ||
|
|
||
| """ | ||
| 데이터베이스에 연결하고, 애플리케이션에 필요한 테이블이 없으면 생성합니다. | ||
| """ | ||
| def initialize_database(): | ||
|
|
||
| db_path = get_db_path() | ||
| conn = None | ||
| try: | ||
| conn = sqlite3.connect(db_path) | ||
| cursor = conn.cursor() | ||
| # db_profile 테이블 생성 | ||
| cursor.execute(""" | ||
| CREATE TABLE IF NOT EXISTS db_profile ( | ||
| id VARCHAR(64) PRIMARY KEY NOT NULL, | ||
| type VARCHAR(32) NOT NULL, | ||
| host VARCHAR(255) NOT NULL, | ||
| port INTEGER NOT NULL, | ||
| name VARCHAR(64), | ||
| username VARCHAR(128) NOT NULL, | ||
| password VARCHAR(128) NOT NULL, | ||
| created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
| updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP | ||
| ); | ||
| """) | ||
| # db_profile 테이블의 updated_at을 자동으로 업데이트하는 트리거 | ||
| cursor.execute(""" | ||
| CREATE TRIGGER IF NOT EXISTS update_db_profile_updated_at | ||
| BEFORE UPDATE ON db_profile | ||
| FOR EACH ROW | ||
| BEGIN | ||
| UPDATE db_profile SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id; | ||
| END; | ||
| """) | ||
|
|
||
| # ai_credential 테이블 생성 | ||
| cursor.execute(""" | ||
| CREATE TABLE IF NOT EXISTS ai_credential ( | ||
| id VARCHAR(64) PRIMARY KEY NOT NULL, | ||
| service_name VARCHAR(32) NOT NULL, | ||
| api_key VARCHAR(256) NOT NULL, | ||
| created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
| updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP | ||
| ); | ||
| """) | ||
| # ai_credential 테이블의 updated_at을 자동으로 업데이트하는 트리거 | ||
| cursor.execute(""" | ||
| CREATE TRIGGER IF NOT EXISTS update_ai_credential_updated_at | ||
| BEFORE UPDATE ON ai_credential | ||
| FOR EACH ROW | ||
| BEGIN | ||
| UPDATE ai_credential SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id; | ||
| END; | ||
| """) | ||
|
|
||
| # chat_tab 테이블 생성 | ||
| cursor.execute(""" | ||
| CREATE TABLE IF NOT EXISTS chat_tab ( | ||
| id VARCHAR(64) PRIMARY KEY NOT NULL, | ||
| name VARCHAR(255), | ||
| created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
| updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP | ||
| ); | ||
| """) | ||
| # chat_tab 테이블의 updated_at을 자동으로 업데이트하는 트리거 | ||
| cursor.execute(""" | ||
| CREATE TRIGGER IF NOT EXISTS update_chat_tab_updated_at | ||
| BEFORE UPDATE ON chat_tab | ||
| FOR EACH ROW | ||
| BEGIN | ||
| UPDATE chat_tab SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id; | ||
| END; | ||
| """) | ||
|
|
||
| # chat_message 테이블 생성 | ||
| cursor.execute(""" | ||
| CREATE TABLE IF NOT EXISTS chat_message ( | ||
| id VARCHAR(64) PRIMARY KEY NOT NULL, | ||
| chat_tab_id VARCHAR(64) NOT NULL, | ||
| sender VARCHAR(1) NOT NULL, | ||
| message TEXT NOT NULL, | ||
| created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
| updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
| FOREIGN KEY (chat_tab_id) REFERENCES chat_tab(id) | ||
| ); | ||
| """) | ||
| # chat_message 테이블의 updated_at을 자동으로 업데이트하는 트리거 | ||
| cursor.execute(""" | ||
| CREATE TRIGGER IF NOT EXISTS update_chat_message_updated_at | ||
| BEFORE UPDATE ON chat_message | ||
| FOR EACH ROW | ||
| BEGIN | ||
| UPDATE chat_message SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id; | ||
| END; | ||
| """) | ||
|
|
||
| # query_history 테이블 생성 | ||
| cursor.execute(""" | ||
| CREATE TABLE IF NOT EXISTS query_history ( | ||
| id VARCHAR(64) PRIMARY KEY NOT NULL, | ||
| chat_message_id VARCHAR(64) NOT NULL, | ||
| query_text TEXT NOT NULL, | ||
| is_success VARCHAR(1) NOT NULL, | ||
| error_message TEXT NOT NULL, | ||
| created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
| updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
| FOREIGN KEY (chat_message_id) REFERENCES chat_message(id) | ||
| ); | ||
| """) | ||
| # query_history 테이블의 updated_at을 자동으로 업데이트하는 트리거 | ||
| cursor.execute(""" | ||
| CREATE TRIGGER IF NOT EXISTS update_query_history_updated_at | ||
| BEFORE UPDATE ON query_history | ||
| FOR EACH ROW | ||
| BEGIN | ||
| UPDATE query_history SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id; | ||
| END; | ||
| """) | ||
|
|
||
| conn.commit() | ||
|
|
||
| except sqlite3.Error as e: | ||
| print(f"데이터베이스 초기화 중 오류 발생: {e}") | ||
| finally: | ||
| if conn: | ||
| conn.close() | ||
|
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_key값은 추후에 환경변수로 분리하실 예정이시죠?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.