security: 移除程式碼中硬編碼的敏感資訊
- 移除 database.py、settings.py、auth_service.py 中的硬編碼預設值 - 移除 tools/*.py 中的硬編碼 IP 位址和服務名稱 - 更新 generate_documentation.py 移除硬編碼的帳號密碼 - 更新 MES_Database_Reference.md 和 Oracle_Authorized_Objects.md 移除敏感資訊 - 更新 .env.example 和 README.md 使用 placeholder 值 - 所有敏感設定現在必須透過 .env 檔案配置 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,9 +10,9 @@
|
|||||||
# Database Configuration (REQUIRED)
|
# Database Configuration (REQUIRED)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# Oracle Database connection settings
|
# Oracle Database connection settings
|
||||||
DB_HOST=10.1.1.58
|
DB_HOST=your_database_host
|
||||||
DB_PORT=1521
|
DB_PORT=1521
|
||||||
DB_SERVICE=DWDB
|
DB_SERVICE=your_service_name
|
||||||
DB_USER=your_username
|
DB_USER=your_username
|
||||||
DB_PASSWORD=your_password
|
DB_PASSWORD=your_password
|
||||||
|
|
||||||
@@ -41,10 +41,10 @@ SESSION_LIFETIME=28800
|
|||||||
# Authentication Configuration
|
# Authentication Configuration
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# LDAP API endpoint for user authentication
|
# LDAP API endpoint for user authentication
|
||||||
LDAP_API_URL=https://adapi.panjit.com.tw
|
LDAP_API_URL=https://your-ldap-api-endpoint.example.com
|
||||||
|
|
||||||
# Admin email addresses (comma-separated for multiple)
|
# Admin email addresses (comma-separated for multiple)
|
||||||
ADMIN_EMAILS=ymirliu@panjit.com.tw
|
ADMIN_EMAILS=admin@example.com
|
||||||
|
|
||||||
# Local Authentication (for development/testing)
|
# Local Authentication (for development/testing)
|
||||||
# When enabled, uses local credentials instead of LDAP
|
# When enabled, uses local credentials instead of LDAP
|
||||||
|
|||||||
@@ -111,9 +111,9 @@ nano .env # 編輯資料庫連線等設定
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 資料庫設定(必填)
|
# 資料庫設定(必填)
|
||||||
DB_HOST=10.1.1.58
|
DB_HOST=your_database_host
|
||||||
DB_PORT=1521
|
DB_PORT=1521
|
||||||
DB_SERVICE=DWDB
|
DB_SERVICE=your_service_name
|
||||||
DB_USER=your_username
|
DB_USER=your_username
|
||||||
DB_PASSWORD=your_password
|
DB_PASSWORD=your_password
|
||||||
|
|
||||||
@@ -304,8 +304,8 @@ CIRCUIT_BREAKER_RECOVERY_TIMEOUT=30
|
|||||||
### 資料庫
|
### 資料庫
|
||||||
|
|
||||||
- Oracle Database 19c Enterprise Edition
|
- Oracle Database 19c Enterprise Edition
|
||||||
- 主機: 10.1.1.58:1521
|
- 主機: 詳見 .env 檔案 (DB_HOST:DB_PORT)
|
||||||
- 服務名: DWDB
|
- 服務名: 詳見 .env 檔案 (DB_SERVICE)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -21,22 +21,27 @@
|
|||||||
| 参数 | 值 |
|
| 参数 | 值 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| 数据库类型 | Oracle Database 19c Enterprise Edition |
|
| 数据库类型 | Oracle Database 19c Enterprise Edition |
|
||||||
| 主机地址 | 10.1.1.58 |
|
| 主机地址 | 請參考 .env 檔案 (DB_HOST) |
|
||||||
| 端口 | 1521 |
|
| 端口 | 請參考 .env 檔案 (DB_PORT) |
|
||||||
| 服务名 | DWDB |
|
| 服务名 | 請參考 .env 檔案 (DB_SERVICE) |
|
||||||
| 用户名 | MBU1_R |
|
| 用户名 | 請參考 .env 檔案 (DB_USER) |
|
||||||
| 密码 | Pj2481mbu1 |
|
| 密码 | 請參考 .env 檔案 (DB_PASSWORD) |
|
||||||
|
|
||||||
### Python 连接示例
|
### Python 连接示例
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
import os
|
||||||
import oracledb
|
import oracledb
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
# 连接配置
|
# 載入環境變數
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
# 连接配置 (從環境變數讀取)
|
||||||
DB_CONFIG = {
|
DB_CONFIG = {
|
||||||
'user': 'MBU1_R',
|
'user': os.getenv('DB_USER'),
|
||||||
'password': 'Pj2481mbu1',
|
'password': os.getenv('DB_PASSWORD'),
|
||||||
'dsn': '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=10.1.1.58)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=DWDB)))'
|
'dsn': f"(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST={os.getenv('DB_HOST')})(PORT={os.getenv('DB_PORT')})))(CONNECT_DATA=(SERVICE_NAME={os.getenv('DB_SERVICE')})))"
|
||||||
}
|
}
|
||||||
|
|
||||||
# 建立连接
|
# 建立连接
|
||||||
@@ -55,7 +60,7 @@ connection.close()
|
|||||||
### JDBC 连接字符串
|
### JDBC 连接字符串
|
||||||
|
|
||||||
```
|
```
|
||||||
jdbc:oracle:thin:@10.1.1.58:1521:DWDB
|
jdbc:oracle:thin:@${DB_HOST}:${DB_PORT}:${DB_SERVICE}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -1287,7 +1292,7 @@ jdbc:oracle:thin:@10.1.1.58:1521:DWDB
|
|||||||
|
|
||||||
### 数据权限
|
### 数据权限
|
||||||
|
|
||||||
- 当前账号 `MBU1_R` 为只读账号
|
- 當前帳號為唯讀帳號 (詳見 .env 中的 DB_USER)
|
||||||
- 仅可执行 SELECT 查询
|
- 仅可执行 SELECT 查询
|
||||||
- 无法进行 INSERT, UPDATE, DELETE 操作
|
- 无法进行 INSERT, UPDATE, DELETE 操作
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Oracle 可使用 TABLE/VIEW 清單(DWH)
|
# Oracle 可使用 TABLE/VIEW 清單(DWH)
|
||||||
|
|
||||||
**產生時間**: 2026-01-29 13:34:22
|
**產生時間**: 2026-01-29 13:34:22
|
||||||
**使用者**: MBU1_R
|
**使用者**: (詳見 .env 中的 DB_USER)
|
||||||
**Schema**: DWH
|
**Schema**: DWH
|
||||||
|
|
||||||
## 摘要
|
## 摘要
|
||||||
|
|||||||
@@ -20,9 +20,10 @@ except ImportError:
|
|||||||
pass # python-dotenv not installed, rely on system environment variables
|
pass # python-dotenv not installed, rely on system environment variables
|
||||||
|
|
||||||
# Database connection settings from environment variables
|
# Database connection settings from environment variables
|
||||||
DB_HOST = os.getenv('DB_HOST', '10.1.1.58')
|
# All values MUST be set in .env file - no hardcoded defaults for security
|
||||||
|
DB_HOST = os.getenv('DB_HOST', '')
|
||||||
DB_PORT = os.getenv('DB_PORT', '1521')
|
DB_PORT = os.getenv('DB_PORT', '1521')
|
||||||
DB_SERVICE = os.getenv('DB_SERVICE', 'DWDB')
|
DB_SERVICE = os.getenv('DB_SERVICE', '')
|
||||||
DB_USER = os.getenv('DB_USER', '')
|
DB_USER = os.getenv('DB_USER', '')
|
||||||
DB_PASSWORD = os.getenv('DB_PASSWORD', '')
|
DB_PASSWORD = os.getenv('DB_PASSWORD', '')
|
||||||
|
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ class Config:
|
|||||||
DB_POOL_SIZE = _int_env("DB_POOL_SIZE", 5)
|
DB_POOL_SIZE = _int_env("DB_POOL_SIZE", 5)
|
||||||
DB_MAX_OVERFLOW = _int_env("DB_MAX_OVERFLOW", 10)
|
DB_MAX_OVERFLOW = _int_env("DB_MAX_OVERFLOW", 10)
|
||||||
|
|
||||||
# Auth configuration
|
# Auth configuration - MUST be set in .env file
|
||||||
LDAP_API_URL = os.getenv("LDAP_API_URL", "https://adapi.panjit.com.tw")
|
LDAP_API_URL = os.getenv("LDAP_API_URL", "")
|
||||||
ADMIN_EMAILS = os.getenv("ADMIN_EMAILS", "ymirliu@panjit.com.tw")
|
ADMIN_EMAILS = os.getenv("ADMIN_EMAILS", "")
|
||||||
SECRET_KEY = os.getenv("SECRET_KEY", "dev-secret-key-change-in-prod")
|
SECRET_KEY = os.getenv("SECRET_KEY", "dev-secret-key-change-in-prod")
|
||||||
|
|
||||||
# Session configuration
|
# Session configuration
|
||||||
|
|||||||
@@ -10,11 +10,9 @@ import requests
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Configuration
|
# Configuration - MUST be set in .env file
|
||||||
LDAP_API_BASE = os.environ.get("LDAP_API_URL", "https://adapi.panjit.com.tw")
|
LDAP_API_BASE = os.environ.get("LDAP_API_URL", "")
|
||||||
ADMIN_EMAILS = os.environ.get(
|
ADMIN_EMAILS = os.environ.get("ADMIN_EMAILS", "").lower().split(",")
|
||||||
"ADMIN_EMAILS", "ymirliu@panjit.com.tw"
|
|
||||||
).lower().split(",")
|
|
||||||
|
|
||||||
# Timeout for LDAP API requests
|
# Timeout for LDAP API requests
|
||||||
LDAP_TIMEOUT = 10
|
LDAP_TIMEOUT = 10
|
||||||
|
|||||||
@@ -14,25 +14,25 @@ with open(DATA_FILE, 'r', encoding='utf-8') as f:
|
|||||||
table_info = json.load(f)
|
table_info = json.load(f)
|
||||||
|
|
||||||
# 表用途描述(根据表名推断)
|
# 表用途描述(根据表名推断)
|
||||||
TABLE_DESCRIPTIONS = {
|
TABLE_DESCRIPTIONS = {
|
||||||
'DW_MES_CONTAINER': '容器/批次主檔 - 目前在製容器狀態、數量與流程資訊',
|
'DW_MES_CONTAINER': '容器/批次主檔 - 目前在製容器狀態、數量與流程資訊',
|
||||||
'DW_MES_HOLDRELEASEHISTORY': 'Hold/Release 歷史表 - 批次停工與解除紀錄',
|
'DW_MES_HOLDRELEASEHISTORY': 'Hold/Release 歷史表 - 批次停工與解除紀錄',
|
||||||
'DW_MES_JOB': '設備維修工單表 - 維修工單的當前狀態與流程',
|
'DW_MES_JOB': '設備維修工單表 - 維修工單的當前狀態與流程',
|
||||||
'DW_MES_LOTREJECTHISTORY': '批次不良/報廢歷史表 - 不良原因與數量',
|
'DW_MES_LOTREJECTHISTORY': '批次不良/報廢歷史表 - 不良原因與數量',
|
||||||
'DW_MES_LOTWIPDATAHISTORY': '在製數據採集歷史表 - 製程量測/參數紀錄',
|
'DW_MES_LOTWIPDATAHISTORY': '在製數據採集歷史表 - 製程量測/參數紀錄',
|
||||||
'DW_MES_LOTWIPHISTORY': '在製流轉歷史表 - 批次進出站與流程軌跡',
|
'DW_MES_LOTWIPHISTORY': '在製流轉歷史表 - 批次進出站與流程軌跡',
|
||||||
'DW_MES_MAINTENANCE': '設備保養/維護紀錄表 - 保養計畫與點檢數據',
|
'DW_MES_MAINTENANCE': '設備保養/維護紀錄表 - 保養計畫與點檢數據',
|
||||||
'DW_MES_PARTREQUESTORDER': '維修用料請求表 - 維修/設備零件請領',
|
'DW_MES_PARTREQUESTORDER': '維修用料請求表 - 維修/設備零件請領',
|
||||||
'DW_MES_PJ_COMBINEDASSYLOTS': '併批紀錄表 - 合批/合併批次關聯與數量資訊',
|
'DW_MES_PJ_COMBINEDASSYLOTS': '併批紀錄表 - 合批/合併批次關聯與數量資訊',
|
||||||
'DW_MES_RESOURCESTATUS': '設備狀態變更歷史表 - 狀態切換與原因',
|
'DW_MES_RESOURCESTATUS': '設備狀態變更歷史表 - 狀態切換與原因',
|
||||||
'DW_MES_RESOURCESTATUS_SHIFT': '設備狀態班次彙總表 - 班次級狀態/工時',
|
'DW_MES_RESOURCESTATUS_SHIFT': '設備狀態班次彙總表 - 班次級狀態/工時',
|
||||||
'DW_MES_WIP': '在製品現況表(含歷史累積)- 當前 WIP 狀態/數量',
|
'DW_MES_WIP': '在製品現況表(含歷史累積)- 當前 WIP 狀態/數量',
|
||||||
'DW_MES_HM_LOTMOVEOUT': '批次出站事件歷史表 - 出站/移出交易',
|
'DW_MES_HM_LOTMOVEOUT': '批次出站事件歷史表 - 出站/移出交易',
|
||||||
'DW_MES_JOBTXNHISTORY': '維修工單交易歷史表 - 工單狀態變更紀錄',
|
'DW_MES_JOBTXNHISTORY': '維修工單交易歷史表 - 工單狀態變更紀錄',
|
||||||
'DW_MES_LOTMATERIALSHISTORY': '批次物料消耗歷史表 - 用料與批次關聯',
|
'DW_MES_LOTMATERIALSHISTORY': '批次物料消耗歷史表 - 用料與批次關聯',
|
||||||
'DW_MES_RESOURCE': '資源表 - 設備/載具等資源基本資料(OBJECTCATEGORY=ASSEMBLY 時,RESOURCENAME 為設備編號)'
|
'DW_MES_RESOURCE': '資源表 - 設備/載具等資源基本資料(OBJECTCATEGORY=ASSEMBLY 時,RESOURCENAME 為設備編號)'
|
||||||
}
|
}
|
||||||
|
|
||||||
# 常见字段说明
|
# 常见字段说明
|
||||||
COMMON_FIELD_NOTES = {
|
COMMON_FIELD_NOTES = {
|
||||||
'ID': '唯一标识符',
|
'ID': '唯一标识符',
|
||||||
@@ -79,21 +79,26 @@ def generate_markdown():
|
|||||||
md.append("| 参数 | 值 |")
|
md.append("| 参数 | 值 |")
|
||||||
md.append("|------|------|")
|
md.append("|------|------|")
|
||||||
md.append("| 数据库类型 | Oracle Database 19c Enterprise Edition |")
|
md.append("| 数据库类型 | Oracle Database 19c Enterprise Edition |")
|
||||||
md.append("| 主机地址 | 10.1.1.58 |")
|
md.append("| 主机地址 | 請參考 .env 檔案 (DB_HOST) |")
|
||||||
md.append("| 端口 | 1521 |")
|
md.append("| 端口 | 請參考 .env 檔案 (DB_PORT) |")
|
||||||
md.append("| 服务名 | DWDB |")
|
md.append("| 服务名 | 請參考 .env 檔案 (DB_SERVICE) |")
|
||||||
md.append("| 用户名 | MBU1_R |")
|
md.append("| 用户名 | 請參考 .env 檔案 (DB_USER) |")
|
||||||
md.append("| 密码 | Pj2481mbu1 |\n")
|
md.append("| 密码 | 請參考 .env 檔案 (DB_PASSWORD) |\n")
|
||||||
|
|
||||||
md.append("### Python 连接示例\n")
|
md.append("### Python 连接示例\n")
|
||||||
md.append("```python")
|
md.append("```python")
|
||||||
|
md.append("import os")
|
||||||
md.append("import oracledb")
|
md.append("import oracledb")
|
||||||
|
md.append("from dotenv import load_dotenv")
|
||||||
md.append("")
|
md.append("")
|
||||||
md.append("# 连接配置")
|
md.append("# 載入環境變數")
|
||||||
|
md.append("load_dotenv()")
|
||||||
|
md.append("")
|
||||||
|
md.append("# 连接配置 (從環境變數讀取)")
|
||||||
md.append("DB_CONFIG = {")
|
md.append("DB_CONFIG = {")
|
||||||
md.append(" 'user': 'MBU1_R',")
|
md.append(" 'user': os.getenv('DB_USER'),")
|
||||||
md.append(" 'password': 'Pj2481mbu1',")
|
md.append(" 'password': os.getenv('DB_PASSWORD'),")
|
||||||
md.append(" 'dsn': '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=10.1.1.58)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=DWDB)))'")
|
md.append(" 'dsn': f\"(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST={os.getenv('DB_HOST')})(PORT={os.getenv('DB_PORT')})))(CONNECT_DATA=(SERVICE_NAME={os.getenv('DB_SERVICE')})))\"")
|
||||||
md.append("}")
|
md.append("}")
|
||||||
md.append("")
|
md.append("")
|
||||||
md.append("# 建立连接")
|
md.append("# 建立连接")
|
||||||
@@ -111,7 +116,7 @@ def generate_markdown():
|
|||||||
|
|
||||||
md.append("### JDBC 连接字符串\n")
|
md.append("### JDBC 连接字符串\n")
|
||||||
md.append("```")
|
md.append("```")
|
||||||
md.append("jdbc:oracle:thin:@10.1.1.58:1521:DWDB")
|
md.append("jdbc:oracle:thin:@${DB_HOST}:${DB_PORT}:${DB_SERVICE}")
|
||||||
md.append("```\n")
|
md.append("```\n")
|
||||||
|
|
||||||
# 2. 数据库概览
|
# 2. 数据库概览
|
||||||
@@ -231,7 +236,7 @@ def generate_markdown():
|
|||||||
md.append("")
|
md.append("")
|
||||||
|
|
||||||
md.append("### 数据时效性\n")
|
md.append("### 数据时效性\n")
|
||||||
md.append("- **实时数据表**: `DW_MES_WIP`(含歷史累積), `DW_MES_RESOURCESTATUS`")
|
md.append("- **实时数据表**: `DW_MES_WIP`(含歷史累積), `DW_MES_RESOURCESTATUS`")
|
||||||
md.append("- **历史数据表**: 带有 `HISTORY` 后缀的表")
|
md.append("- **历史数据表**: 带有 `HISTORY` 后缀的表")
|
||||||
md.append("- **主数据表**: `DW_MES_RESOURCE`, `DW_MES_CONTAINER`")
|
md.append("- **主数据表**: `DW_MES_RESOURCE`, `DW_MES_CONTAINER`")
|
||||||
md.append("")
|
md.append("")
|
||||||
@@ -244,7 +249,7 @@ def generate_markdown():
|
|||||||
md.append("")
|
md.append("")
|
||||||
|
|
||||||
md.append("### 数据权限\n")
|
md.append("### 数据权限\n")
|
||||||
md.append("- 当前账号 `MBU1_R` 为只读账号")
|
md.append("- 當前帳號為唯讀帳號 (詳見 .env 中的 DB_USER)")
|
||||||
md.append("- 仅可执行 SELECT 查询")
|
md.append("- 仅可执行 SELECT 查询")
|
||||||
md.append("- 无法进行 INSERT, UPDATE, DELETE 操作")
|
md.append("- 无法进行 INSERT, UPDATE, DELETE 操作")
|
||||||
md.append("")
|
md.append("")
|
||||||
|
|||||||
@@ -23,10 +23,10 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# 数据库连接信息 (从环境变量读取)
|
# 数据库连接信息 (从环境变量读取,必须在 .env 中设置)
|
||||||
DB_HOST = os.getenv('DB_HOST', '10.1.1.58')
|
DB_HOST = os.getenv('DB_HOST', '')
|
||||||
DB_PORT = os.getenv('DB_PORT', '1521')
|
DB_PORT = os.getenv('DB_PORT', '1521')
|
||||||
DB_SERVICE = os.getenv('DB_SERVICE', 'DWDB')
|
DB_SERVICE = os.getenv('DB_SERVICE', '')
|
||||||
DB_USER = os.getenv('DB_USER', '')
|
DB_USER = os.getenv('DB_USER', '')
|
||||||
DB_PASSWORD = os.getenv('DB_PASSWORD', '')
|
DB_PASSWORD = os.getenv('DB_PASSWORD', '')
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# 数据库连接信息 (从环境变量读取)
|
# 数据库连接信息 (从环境变量读取,必须在 .env 中设置)
|
||||||
DB_HOST = os.getenv('DB_HOST', '10.1.1.58')
|
DB_HOST = os.getenv('DB_HOST', '')
|
||||||
DB_PORT = os.getenv('DB_PORT', '1521')
|
DB_PORT = os.getenv('DB_PORT', '1521')
|
||||||
DB_SERVICE = os.getenv('DB_SERVICE', 'DWDB')
|
DB_SERVICE = os.getenv('DB_SERVICE', '')
|
||||||
DB_USER = os.getenv('DB_USER', '')
|
DB_USER = os.getenv('DB_USER', '')
|
||||||
DB_PASSWORD = os.getenv('DB_PASSWORD', '')
|
DB_PASSWORD = os.getenv('DB_PASSWORD', '')
|
||||||
|
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ def load_env() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def get_connection():
|
def get_connection():
|
||||||
host = os.getenv("DB_HOST", "10.1.1.58")
|
host = os.getenv("DB_HOST", "")
|
||||||
port = os.getenv("DB_PORT", "1521")
|
port = os.getenv("DB_PORT", "1521")
|
||||||
service = os.getenv("DB_SERVICE", "DWDB")
|
service = os.getenv("DB_SERVICE", "")
|
||||||
user = os.getenv("DB_USER", "")
|
user = os.getenv("DB_USER", "")
|
||||||
password = os.getenv("DB_PASSWORD", "")
|
password = os.getenv("DB_PASSWORD", "")
|
||||||
dsn = (
|
dsn = (
|
||||||
|
|||||||
Reference in New Issue
Block a user