diff --git a/api/account_manager.py b/api/account_manager.py
index 5a6a2ed..0a7cbf0 100755
--- a/api/account_manager.py
+++ b/api/account_manager.py
@@ -7,6 +7,7 @@ import logging
from datetime import datetime, timezone
import psycopg2.extras
from database import get_db_cursor, execute_query, execute_update
+from tenant_manager import TenantManager # Import TenantManager for tenant operations
# 配置日志
logger = logging.getLogger(__name__)
@@ -65,6 +66,26 @@ class AccountManager:
cursor.connection.commit()
logger.info(f"用户 {username} 邮箱 {email} 注册成功!")
+
+ # 创建租户并关联角色
+ try:
+ # 创建租户(租户名为"账号名's Workspace")
+ tenant_name = f"{username}'s Workspace"
+ tenant_id = TenantManager.create_tenant(tenant_name)
+
+ # 关联新账号为自建租户的owner
+ AccountManager.associate_with_tenant(result[0], tenant_id, "owner")
+
+ # 关联新账号为ucas's Workspace的normal角色
+ ucas_tenant = TenantManager.get_tenant_by_name("ucas's Workspace")
+ if ucas_tenant:
+ AccountManager.associate_with_tenant(result[0], ucas_tenant['id'], "normal")
+ else:
+ logger.warning("ucas's Workspace not found - skipping normal role association")
+ except Exception as e:
+ logger.error(f"租户创建或关联失败: {e}")
+ # Continue even if tenant operations fail since account creation succeeded
+
return {
"id": result[0],
"username": result[1],
@@ -289,11 +310,14 @@ class AccountManager:
def get_account_tenants(account_id):
"""获取账户关联的所有租户"""
try:
+ # 处理account_id可能是UUID对象或字符串的情况
+ account_id_str = str(account_id) if hasattr(account_id, 'hex') else account_id
+
# 验证account_id是否为有效UUID
try:
- uuid.UUID(account_id)
+ uuid.UUID(account_id_str)
except ValueError:
- logger.error(f"无效的account_id格式: {account_id}")
+ logger.error(f"无效的account_id格式: {account_id_str}")
return []
query = """
@@ -302,7 +326,7 @@ class AccountManager:
JOIN tenant_account_joins j ON t.id = j.tenant_id
WHERE j.account_id = %s::uuid;
"""
- tenants = execute_query(query, (account_id,))
+ tenants = execute_query(query, (account_id_str,))
if not tenants:
logger.info(f"账号 {account_id} 未关联任何租户")
return []
diff --git a/api/app.py b/api/app.py
index e6c7d41..8b67d02 100755
--- a/api/app.py
+++ b/api/app.py
@@ -256,6 +256,21 @@ async def refresh_token(current_user: dict = Depends(get_current_user)):
return {"access_token": access_token, "token_type": "bearer"}
# 账户管理路由组
+@app.post("/api/accounts/")
+async def create_account(account: AccountCreate):
+ """创建后台管理账户"""
+ try:
+ user = backend_account_manager.create_account(account.username, account.email, account.password)
+ return {
+ "user_id": str(user["id"]),
+ "username": user["username"],
+ "email": user["email"],
+ "created_at": user["created_at"]
+ }
+ except Exception as e:
+ logger.error(f"创建后台账户失败: {e}")
+ raise HTTPException(status_code=400, detail="创建后台账户失败")
+
@app.post("/api/dify_accounts/")
async def create_dify_account(account: AccountCreate):
"""创建Dify账户"""
diff --git a/api/privkeys/7136c592-e061-4875-aa9b-707f1efcf4f8/private.pem b/api/privkeys/7136c592-e061-4875-aa9b-707f1efcf4f8/private.pem
new file mode 100644
index 0000000..0bd72b0
--- /dev/null
+++ b/api/privkeys/7136c592-e061-4875-aa9b-707f1efcf4f8/private.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAvRzEAE/Cbm+QKTqGQ5Xry+W60kTJeIeoQMb8G374PcbTxdPe
+0hURUaIH/h7jQ1rhDkNvkaBXC26v0q6ZkCBt89i4TopWCxewVzXb18DAcUswW2z2
+qQs70ssZqpSIn8sQbKfdZn20CD8C1Exkt18uI01VquWqMB30iwZvK8Wly94jm3WC
+6xiqnItOz64Y+prOQFhLr0trvoYEf0aKOAnrJr5qeOP6/XnxdF/bHJwOXCU0uFHA
+8RXHp58O60fDEZctdSTp9iUQeZidSXS0p3B85NRj/Y2rd/UOEiQ9Sj+DSXg0knXk
+CnYiLCeMBpV88bWyCwopRn3Im0haxzVrp9UYVQIDAQABAoIBAAuiuHXjHRhvFCn6
+ktuXtDFlyiU5MZg76ItLyE6SH7NVXMmq6+Z11gygG+kefLyJMUMPvSPy/0gRyw77
+H9xb/R09dAxJELA6szvlHB4Imw6dd1/jXW3bO2wQg7IY1NXYHa5BydU43hnfyUxy
+Atm8KSTnk4zMorhhL3RaX1QMeNNelXRzddzm82u1A/mItIMwyu3b3RXrDjIB/VsS
+VtY9C1hiXhcWvZdVcRMTRSQt4nbh7ap1QQG1oCHQKBDwBH4rryZHXioKBdKdJOvJ
+/1rNtvwWmUtsUwxVNDQ0GnQQlRhg4QoWoEvL9PzMqEEx/Oix2OPEZMa9ePJjUWoj
+j0udMkUCgYEA7YrwB/7ASDrNNC2x6dZvNHFAz5Ng9IDqjdBu+u6V61Aq5whoJFDh
+ysmywbSaz5NiVtTltr1wggkmWZJKvCLq3CJ+eRm0UfSAsWzeyeOii1+7eazW5zzp
+0PpIGdhNBoQf9jo6hn84iyCnxaehyTPDH+0HecFmYu2xyqGwPvFCqfMCgYEAy856
+tbXM/TSeO5GVX/giJ6OzebXcyannbyqeTOgSZ3wlm9pTtsyRhcIfjV4/VjnDkpby
+WTPsQqDjCQnWD6kPJXSwRjxQlhoT84FnDf3TtogxOkPUQgp7TRZRFPAy9WtisTyY
+EvZefWllw1U5G5WQclBLk4jtWLF8gPG3cya+PpcCgYAGkkJjpjuBhAbrO5xhYKpA
+5CUr2OLkwLA8bhiz3mfNU7FsJMJkxswIRR4p16o0tdoRluAn9wOmxUQHVFG29KxU
+nKutA/YGEmKBBgb/xMlZW7OfARYM3ZWGT3YxKNewp3UO5bt6vwg8aRHbGPET1NfA
+CVmcl6oScIrrlR+ADkKO2wKBgFE7HeuY53gwZbTmZLwYgTx9YcZr9vEl2AmV2fxb
+LyKx96dz0JP2WzYN1leZLfNnGI0vvq5RJKS1zWfH1NrvDgtmw+9qkNAS2sreU73e
+4mhJRh2r9UjRNq3V7EFFL3pj77UmqpI8QhMIVDgTmqxk42q8mDLYi4kjTLV0IiMy
+WPdHAoGBAJkJAhQ1JGSUAY+3QAKBWre8QwabKZdZIzDFq9DdQfnwiHkluueVUI63
+YY5U+wbff0dIAPBpeFGap56XYN8qy3/i6UkRNTTYji5kj6XqVWbyn2xU1IX8/KcC
+7AqeEsg04ArqGP0eDAw3gfSe4fgJ5Zoc5ZOkARcb/ajMJi+zA2+W
+-----END RSA PRIVATE KEY-----
diff --git a/api/privkeys/86220f3c-9e87-4a75-85f6-39fe38067858/private.pem b/api/privkeys/86220f3c-9e87-4a75-85f6-39fe38067858/private.pem
new file mode 100644
index 0000000..058b8ec
--- /dev/null
+++ b/api/privkeys/86220f3c-9e87-4a75-85f6-39fe38067858/private.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA6GsVZmXAF+XkytRj9c+5tJP2YlWdYLQMo0HXfprVKobLUI5N
++VMrCSreTCARTpsr2KtPV21zSgwVsRzA3zx9RgnAvHzDkJZtkSS1OHGKkA2CAU2T
+bJmpZWDEw5L/wOxx0QKA0tWBZzlWvRtXQjGqte/yNYF18TuxCOty6cIPUEQlVcYq
+QCwIeDfxGS94GI5ibwynvp7A8QfocR7DxYUZQdo8RSOlBz7d5ra/KVpIRb7I6fsV
+4U4qEYsx2GFFXZeZ6HWH7a+deC7Selv9Eycw9cvERWLQVE+FtGyDygbTHpwG7lPl
+8D9Yaf2NkXgibsxqHroK6OKyHIr0CkjlxfX1bQIDAQABAoIBACBSVAWLfO1V4T17
+z/LtUmwUb505Psul/mPt0iQfMCnb2QZ448saj8+UkJmRlBaUacKWAFCuPew8Rf/9
+ea0R4nINBSqxRxkiclZO/oy87YIe/sdjnG7r56zbikGQfdS8jQ9+A6BOZNKQHMnr
+tXTVJ2Jp3gsm19oWbQZKiA6OGEcXDyikRVipDoavDPBGoTBniJzUNwqD+JyasqdX
+QoUIqyJPLLTvXNN6pij8MnK+N86RccEVHdd/NdCDUGyh9ej4vs0dkg8BLTT+3fuw
+GR6WSwxZ7qFWl7PD0NhcrJfVQo2X1JNHm4BZFo5kNTJiWkKX+uqEp5QNAZmcXXXK
+N6owt9kCgYEA9vBZAE6JKvKBj+wNWeAvUGI/W5KTbYuk8NbPFoYzsqFaseewr0ei
+Iq4yzp31fmbIBbyx3iYEIuW2sdxMTEg9ZLi1yqh4qxn3aOhN0/dLkAFZlnBNsJVA
+izNsdFDtwy9EIT8vg4Tl1byC+ZzvT2cpP5PYVF4auD1DVUP3Zxet6wMCgYEA8PJV
+y18O6smWJPkgDfS2rbUHnP2dBJ6JznrauDGTzDlnd9LNL/sQBG4ZN/nDbo+M2++w
+84PeaWB+IQvpweQfZYC/CEA8gJqpQZzlL0TiRJTOAFlm45IEkY9IY9ZM2M0QfbmW
+Alt9uCxOQ/+O0TSg7s/hJgjFO7HVU1L+0TGc+s8CgYEA1vm6obe9VnQ0MvVPUjUH
+O7Wsbq4WRsHRYBHBy1wd2Z768/I+MPntvr9kX9fIBri33ba+KiVyaGcPO5wLmEUz
+nWHocXtlQZ+jceL7DlM1pzJlqcAvAlGNFSI5grGJq+iUKVV2qcqixAYPB/uFotyu
+Xjj5lcku/cHnwm0fDtLgh70CgYBeIg8quSSWzdL+9uVzDlwgWU10JBEoMNgd9xlk
+RNo9O2AVDCJl0GxdjrYDjGyx0RtzAZ3cRXSrLquYNZNJ0NoDSd1YV+BLTiE6JRXU
+9dCAgrJIqKTt26o1RAlAGAVF3jfHJq5YlW30ejrJjho52ZnWMxj/RwXnYH67Yv1y
+tTNjOQKBgH57/cRMpvuQ/kuLNYu1IS+EEZJ5WlDjEC0lmM2E54+Lb4D1UBMj+Y7V
+EZa9r+UQYm5DnsD4BQjiI1PWY/Iu39Cq3hlkxitOcTOds307xHKbivXancdwlwwx
+G+K1nGpNnAHSYCf+qaGdQgfG1LU9REKeLiPkIyt2zOtk6tZ4hmNq
+-----END RSA PRIVATE KEY-----
diff --git a/docs/api/README.md b/docs/api/README.md
new file mode 100644
index 0000000..c347cb8
--- /dev/null
+++ b/docs/api/README.md
@@ -0,0 +1,54 @@
+# Dify Admin API Documentation
+
+## Overview
+This documentation covers the core API modules of the Dify Admin system. Each module provides specific functionality for managing the administration platform.
+
+## Module Documentation
+
+### [Account Management](account_manager.md)
+- User account creation and management
+- Password hashing and verification
+- Tenant association
+
+### [Tenant Management](tenant_manager.md)
+- Workspace/tenant creation
+- RSA key pair generation
+- Tenant search and retrieval
+
+### [Model Management](model_manager.md)
+- AI model configuration
+- Model encryption and storage
+- Bulk operations
+
+### [Provider Management](provider_manager.md)
+- AI service provider management
+- API key encryption
+- Provider configuration
+
+### [Database Operations](database.md)
+- Connection pooling
+- SQL execution helpers
+- Database initialization
+
+### [Operation Logging](operation_logger.md)
+- Audit trail recording
+- Log querying
+- Log maintenance
+
+### [Encryption Services](encryption.md)
+- Hybrid encryption (RSA + AES)
+- Key management
+- API key protection
+
+## Getting Started
+To use these APIs, import the required module and instantiate the appropriate class:
+
+```python
+from api.account_manager import AccountManager
+account_mgr = AccountManager()
+```
+
+## Security Notes
+- All sensitive operations use encryption
+- API keys are never stored in plaintext
+- Detailed logging for audit purposes
diff --git a/docs/api/account_manager.md b/docs/api/account_manager.md
new file mode 100644
index 0000000..3f9c87e
--- /dev/null
+++ b/docs/api/account_manager.md
@@ -0,0 +1,97 @@
+# Account Manager API Documentation
+
+## Overview
+The `AccountManager` class provides functionality for managing user accounts, including:
+- Account creation and authentication
+- Password management (hashing, verification, reset)
+- Account search and retrieval
+- Tenant association management
+
+## Class Methods
+
+### `hash_password(password, salt=None)`
+Generates a hashed password and salt for secure storage.
+
+**Parameters:**
+- `password` (str): Plain text password to hash
+- `salt` (bytes, optional): Optional salt value. If None, generates new salt.
+
+**Returns:**
+- Tuple of (base64_password_hashed, base64_salt)
+
+**Example:**
+```python
+hashed_pw, salt = AccountManager.hash_password("mysecurepassword")
+```
+
+### `create_account(username, email, password)`
+Creates a new user account.
+
+**Parameters:**
+- `username` (str): Unique username
+- `email` (str): User email address
+- `password` (str): Plain text password
+
+**Returns:**
+- Dictionary with created account details:
+ ```python
+ {
+ "id": UUID,
+ "username": str,
+ "email": str,
+ "created_at": datetime
+ }
+ ```
+
+### `get_user_by_username(username)`
+Retrieves user information by username.
+
+**Parameters:**
+- `username` (str): Username to search for
+
+**Returns:**
+- User dictionary or None if not found
+
+### `search_accounts(search=None, page=1, page_size=10)`
+Searches accounts with pagination.
+
+**Parameters:**
+- `search` (str): Optional search term
+- `page` (int): Page number (1-based)
+- `page_size` (int): Items per page
+
+**Returns:**
+```python
+{
+ "data": [user_dicts],
+ "total": int
+}
+```
+
+### `verify_password(plain_password, hashed_password, salt)`
+Verifies a password against stored hash.
+
+**Parameters:**
+- `plain_password` (str): Password to verify
+- `hashed_password` (str): Stored password hash
+- `salt` (str): Password salt
+
+**Returns:**
+- bool: True if password matches
+
+### Password Management
+- `update_password(username, email, new_password)`
+- `reset_password(account_id)`
+
+### Tenant Association
+- `associate_with_tenant(account_id, tenant_id, role, invited_by, current)`
+- `get_tenant_accounts(tenant_id)`
+- `get_account_tenants(account_id)`
+
+## Error Handling
+All methods raise exceptions on failure and log errors using the module logger.
+
+## Security Notes
+- Uses PBKDF2 with SHA-256 for password hashing
+- Generates random salts for each password
+- All sensitive operations are logged
diff --git a/docs/api/database.md b/docs/api/database.md
new file mode 100644
index 0000000..1f29e83
--- /dev/null
+++ b/docs/api/database.md
@@ -0,0 +1,81 @@
+# Database API Documentation
+
+## Overview
+The database module provides database connection management and basic operations for both PostgreSQL and SQLite databases. Key features include:
+- Connection pooling for PostgreSQL
+- Context managers for safe connection handling
+- Unified interface for both database types
+- SQL execution helpers
+
+## Connection Management
+
+### `get_db_connection(db_type='postgres')`
+Context manager for database connections.
+
+**Parameters:**
+- `db_type`: 'postgres' or 'sqlite' (default: 'postgres')
+
+**Usage:**
+```python
+with get_db_connection() as conn:
+ # Use connection
+```
+
+### `get_db_cursor(cursor_factory=None, db_type='postgres')`
+Context manager for database cursors with automatic commit/rollback.
+
+**Parameters:**
+- `cursor_factory`: Optional cursor factory (e.g., psycopg2.extras.DictCursor)
+- `db_type`: 'postgres' or 'sqlite' (default: 'postgres')
+
+**Usage:**
+```python
+with get_db_cursor() as cursor:
+ cursor.execute("SELECT * FROM table")
+```
+
+## SQL Execution Helpers
+
+### `execute_query(query, params=None, cursor_factory=None, fetch_one=False, db_type='postgres')`
+Executes a query and returns results.
+
+**Parameters:**
+- `query`: SQL query string
+- `params`: Query parameters (tuple/dict)
+- `cursor_factory`: Optional cursor factory
+- `fetch_one`: Return single row if True
+- `db_type`: Database type
+
+**Returns:**
+- Query results (list or single row)
+
+### `execute_update(query, params=None, db_type='postgres')`
+Executes an update/insert/delete query.
+
+**Parameters:**
+- `query`: SQL query string
+- `params`: Query parameters (tuple/dict)
+- `db_type`: Database type
+
+**Returns:**
+- Number of affected rows
+
+## Initialization
+
+### `init_sqlite_db()`
+Initializes SQLite database tables (api_endpoints, api_logs, api_users, api_operations).
+
+## Configuration
+Module uses configuration from:
+- `DB_CONFIG` for PostgreSQL
+- `SQLITE_CONFIG` for SQLite
+
+## Error Handling
+- All database operations are wrapped in try/except blocks
+- Errors are logged with detailed context
+- Connections are automatically returned to pool (PostgreSQL) or closed (SQLite)
+
+## Best Practices
+- Always use context managers (`with` statements) for connections/cursors
+- For PostgreSQL, prefer connection pooling for better performance
+- For complex transactions, use explicit commit/rollback
diff --git a/docs/api/encryption.md b/docs/api/encryption.md
new file mode 100644
index 0000000..3e23ac8
--- /dev/null
+++ b/docs/api/encryption.md
@@ -0,0 +1,51 @@
+# Encryption API Documentation
+
+## Overview
+The `Encryption` class provides cryptographic functions including:
+- RSA key pair generation and management
+- Hybrid encryption (RSA + AES)
+- API key encryption
+- Secure key storage
+
+## Class Methods
+
+### Key Management
+- `load_public_key(public_key_path_or_content)`
+ - Loads public key from file or content
+- `load_private_key(private_key_path)`
+ - Loads private key from file
+
+### Encryption/Decryption
+- `encrypt(text, public_key)`
+ - Encrypts text using hybrid RSA+AES approach
+ - Returns: Encrypted data with "HYBRID:" prefix
+- `decrypt(encrypted_text, private_key)`
+ - Decrypts hybrid encrypted data
+ - Returns: Original plaintext
+
+### Specialized Methods
+- `encrypt_api_key(public_key_pem, api_key)`
+ - Encrypts API keys with base64 encoding
+ - Returns: base64 encoded encrypted key
+
+## Security Features
+- Uses 2048-bit RSA keys
+- AES-256 for symmetric encryption
+- Random key generation for each operation
+- Secure key storage practices
+- Detailed error logging
+
+## Error Handling
+- Validates all inputs
+- Raises exceptions for invalid operations
+- Logs all errors with context
+
+## Example Usage
+```python
+# Encrypt data
+public_key = Encryption.load_public_key("public.pem")
+encrypted = Encryption.encrypt("secret data", public_key)
+
+# Decrypt data
+private_key = Encryption.load_private_key("private.pem")
+decrypted = Encryption.decrypt(encrypted, private_key)
diff --git a/docs/api/model_manager.md b/docs/api/model_manager.md
new file mode 100644
index 0000000..6cf1400
--- /dev/null
+++ b/docs/api/model_manager.md
@@ -0,0 +1,75 @@
+# Model Manager API Documentation
+
+## Overview
+The `ModelManager` class provides functionality for managing AI models, including:
+- Adding models to tenants (both standard and Volc models)
+- Removing models
+- Querying model information
+- Bulk operations for all tenants
+
+## Class Methods
+
+### Model Addition
+- `add_model_for_tenant(tenant_id, public_key_pem, model_config)`
+ - Adds a standard model to a tenant
+ - Encrypts API keys using tenant's public key
+ - Supports different model types (text-generation, embeddings, etc.)
+
+- `add_volc_model_for_tenant(tenant_id, public_key_pem, model_config)`
+ - Adds a Volc engine model to a tenant
+ - Special handling for Volc-specific parameters
+
+**Common Parameters:**
+- `tenant_id`: Target tenant UUID
+- `public_key_pem`: Tenant's public key for encryption
+- `model_config`: Dictionary containing model configuration
+
+**Required Fields in model_config:**
+```python
+{
+ "model_name": str, # Unique model name
+ "provider_name": str, # Provider identifier
+ "model_type": str, # Type of model
+ "api_key": str # API key to encrypt (or volc_api_key for Volc models)
+}
+```
+
+### Bulk Operations
+- `add_models_for_all_tenants(config_path)`
+- `add_volc_models_for_all_tenants(config_path)`
+- `add_models_for_tenant(tenant_name, config_path)`
+- `add_volc_models_for_tenant(tenant_name, config_path)`
+
+### Model Removal
+- `delete_model_for_tenant(tenant_id, model_name)`
+- `delete_models_for_tenant(tenant_id)`
+- `delete_specific_model_for_all_tenants(model_name)`
+
+### Query Methods
+- `get_tenant_models(tenant_id)`
+ - Returns all models for a tenant
+ - Format:
+ ```python
+ {
+ "tenant_id": str,
+ "models": [{
+ "id": str,
+ "provider_name": str,
+ "model_name": str,
+ "model_type": str,
+ "encrypted_config": dict,
+ "is_valid": bool,
+ "created_at": datetime,
+ "updated_at": datetime
+ }]
+ }
+ ```
+
+## Security Considerations
+- All API keys are encrypted using tenant's public key
+- Supports different encryption configurations per model type
+- Detailed logging of all operations
+
+## Error Handling
+- Raises exceptions for invalid configurations
+- Logs all errors with detailed context
diff --git a/docs/api/operation_logger.md b/docs/api/operation_logger.md
new file mode 100644
index 0000000..a7c9aa6
--- /dev/null
+++ b/docs/api/operation_logger.md
@@ -0,0 +1,65 @@
+# Operation Logger API Documentation
+
+## Overview
+The `OperationLogger` class provides functionality for recording and managing operation logs, including:
+- Logging API operations
+- Querying operation logs with filters
+- Cleaning up old logs
+
+## Class Methods
+
+### `log_operation(user_id, operation_type, endpoint, parameters=None, status="SUCCESS")`
+Records an API operation in the database.
+
+**Parameters:**
+- `user_id` (int): ID of the user performing the operation
+- `operation_type` (str): Type of operation (e.g., "CREATE", "UPDATE")
+- `endpoint` (str): API endpoint accessed
+- `parameters` (str, optional): Operation parameters in string format
+- `status` (str): Operation status (default: "SUCCESS")
+
+**Returns:**
+- int: ID of the created log record
+
+**Example:**
+```python
+logger.log_operation(123, "LOGIN", "/api/auth/login", "username=test", "SUCCESS")
+```
+
+### `get_operations(user_id=None, start_time=None, end_time=None, limit=100)`
+Queries operation logs with optional filters.
+
+**Parameters:**
+- `user_id` (int, optional): Filter by user ID
+- `start_time` (datetime, optional): Earliest log time
+- `end_time` (datetime, optional): Latest log time
+- `limit` (int): Maximum number of logs to return (default: 100)
+
+**Returns:**
+- List of log records with fields:
+ - id
+ - user_id
+ - operation_type
+ - endpoint
+ - parameters
+ - status
+ - created_at
+
+### `clean_old_logs(days=30)`
+Deletes logs older than specified number of days.
+
+**Parameters:**
+- `days` (int): Delete logs older than this many days (default: 30)
+
+**Returns:**
+- int: Number of logs deleted
+
+## Error Handling
+- Raises `OperationLogError` for all failures
+- Detailed error logging through module logger
+
+## Best Practices
+- Log all critical operations for audit trail
+- Regularly clean old logs to maintain performance
+- Use appropriate status values ("SUCCESS", "FAILED", etc.)
+- Include relevant parameters for debugging
diff --git a/docs/api/provider_manager.md b/docs/api/provider_manager.md
new file mode 100644
index 0000000..9f78358
--- /dev/null
+++ b/docs/api/provider_manager.md
@@ -0,0 +1,61 @@
+# Provider Manager API Documentation
+
+## Overview
+The `ProviderManager` class provides functionality for managing AI service providers, including:
+- Adding providers to tenants
+- Removing providers
+- Querying provider information
+- Bulk operations for all tenants
+
+## Class Methods
+
+### Provider Addition
+- `add_provider_for_tenant(tenant_id, public_key_pem, provider_config)`
+ - Adds a provider to a tenant
+ - Encrypts API keys using tenant's public key
+ - Supports different provider types
+
+**Parameters:**
+- `tenant_id`: Target tenant UUID
+- `public_key_pem`: Tenant's public key for encryption
+- `provider_config`: Dictionary containing provider configuration
+
+**Required Fields in provider_config:**
+```python
+{
+ "provider_name": str, # Unique provider name
+ "config": dict # Provider configuration including API keys
+}
+```
+
+### Bulk Operations
+- `add_providers_for_all_tenants(config_path)`
+- `add_providers_for_tenant(tenant_name, config_path)`
+
+### Provider Removal
+- `delete_provider_for_tenant(tenant_id, provider_name)`
+- `delete_providers_for_tenant(tenant_id)`
+
+### Query Methods
+- `get_providers_for_tenant(tenant_id)`
+ - Returns all providers for a tenant
+ - Format:
+ ```python
+ [
+ {
+ "id": str,
+ "provider_name": str,
+ "provider_type": str,
+ "is_valid": bool
+ }
+ ]
+ ```
+
+## Security Considerations
+- API keys are encrypted using tenant's public key
+- Detailed logging of all operations
+- Validation of required fields
+
+## Error Handling
+- Raises exceptions for invalid configurations
+- Logs all errors with detailed context
diff --git a/docs/api/tenant_manager.md b/docs/api/tenant_manager.md
new file mode 100644
index 0000000..a8c879c
--- /dev/null
+++ b/docs/api/tenant_manager.md
@@ -0,0 +1,70 @@
+# Tenant Manager API Documentation
+
+## Overview
+The `TenantManager` class provides functionality for managing tenants (workspaces), including:
+- Tenant creation with RSA key pair generation
+- Key management (generation, storage)
+- Tenant search and retrieval
+
+## Class Methods
+
+### `generate_rsa_key_pair()`
+Generates a new RSA key pair for tenant encryption.
+
+**Returns:**
+- Tuple of (public_key_pem, private_key)
+ - public_key_pem: PEM formatted public key string
+ - private_key: RSA private key object
+
+**Example:**
+```python
+public_key, private_key = TenantManager.generate_rsa_key_pair()
+```
+
+### `save_private_key(tenant_id, private_key)`
+Securely stores a private key for a tenant.
+
+**Parameters:**
+- `tenant_id` (UUID): Tenant identifier
+- `private_key`: RSA private key object
+
+**Returns:**
+- Path to stored private key file
+
+### `create_tenant(workspace_name)`
+Creates a new tenant with cryptographic keys.
+
+**Parameters:**
+- `workspace_name` (str): Name for the new tenant/workspace
+
+**Returns:**
+- UUID of created tenant
+
+**Process:**
+1. Generates RSA key pair
+2. Stores private key securely
+3. Creates tenant record with public key
+
+### Query Methods
+- `get_tenant_by_name(workspace_name)`: Retrieves tenant by name
+- `get_all_tenants()`: Lists all tenants
+- `search_tenants(search_term)`: Searches tenants by name
+
+**Return Format:**
+```python
+{
+ "id": str/UUID,
+ "name": str,
+ "encrypt_public_key": str,
+ "created_at": datetime
+}
+```
+
+## Security Considerations
+- Uses 2048-bit RSA keys for encryption
+- Private keys stored in secure directory structure
+- Public keys stored in database for encryption
+- All operations are logged
+
+## Error Handling
+Methods raise exceptions on failure and log errors using the module logger.
diff --git a/docs/architecture/overview.md b/docs/architecture/overview.md
new file mode 100644
index 0000000..932b0a7
--- /dev/null
+++ b/docs/architecture/overview.md
@@ -0,0 +1,48 @@
+# Dify Admin System Architecture
+
+## Overall Architecture
+```mermaid
+graph TD
+ A[Frontend] -->|API Calls| B[Backend]
+ B --> C[Database]
+ B --> D[External Services]
+ C --> E[(PostgreSQL)]
+ C --> F[(SQLite)]
+```
+
+## Core Components
+
+### Frontend
+- **Framework**: Vue 3 + TypeScript
+- **State Management**: Pinia
+- **UI Library**: Element Plus
+- **Routing**: Vue Router
+
+### Backend
+- **API Services**:
+ - Account Management
+ - Tenant Management
+ - Model Management
+ - Provider Management
+- **Core Modules**:
+ - Database Access
+ - Encryption
+ - Operation Logging
+
+## Data Flow
+1. User actions trigger API calls
+2. Backend processes requests with business logic
+3. Data persisted to database
+4. Responses returned to frontend
+5. Frontend updates state and UI
+
+## Security Architecture
+- JWT Authentication
+- RSA Encryption for sensitive data
+- Role-based Access Control
+- Audit logging
+
+## Deployment
+- Frontend: Static hosting (Vite)
+- Backend: Containerized microservices
+- Database: PostgreSQL (primary), SQLite (logging)
diff --git a/docs/web/README.md b/docs/web/README.md
new file mode 100644
index 0000000..2643436
--- /dev/null
+++ b/docs/web/README.md
@@ -0,0 +1,31 @@
+# Web Frontend Documentation
+
+## Technology Stack
+- **Framework**: Vue 3 (Composition API)
+- **UI Library**: Element Plus
+- **State Management**: Pinia
+- **Routing**: Vue Router
+- **HTTP Client**: Axios
+
+## Core Architecture
+
+### Application Initialization
+1. Creates Vue app instance
+2. Configures router and store
+3. Initializes Element Plus components
+4. Checks for existing auth token
+5. Mounts to DOM element (#app)
+
+### Key Files
+- `main.ts`: Application entry point
+- `App.vue`: Root component
+- `router/index.ts`: Route configuration
+- `store/index.ts`: State management setup
+
+## Module Structure
+- `api/`: API service layer
+- `axios/`: HTTP client configuration
+- `router/`: Navigation logic
+- `store/`: Global state management
+- `utils/`: Helper functions
+- `views/`: Page components
diff --git a/docs/web/api.md b/docs/web/api.md
new file mode 100644
index 0000000..f45a295
--- /dev/null
+++ b/docs/web/api.md
@@ -0,0 +1,48 @@
+# API Service Documentation
+
+## Architecture
+- **HTTP Client**: Axios with custom wrapper
+- **Modular Structure**: Feature-based organization
+- **Type Safety**: TypeScript interfaces
+
+## Auth Module
+
+### Methods
+- `login(data)`: User authentication
+ - Parameters: `{username, password}`
+ - Returns: `{access_token}`
+ - Content-Type: `application/json`
+
+- `register(formData)`: User registration
+ - Parameters: FormData
+ - Returns: `{user_id}`
+ - Content-Type: `multipart/form-data`
+
+- `getPublicKey()`: Gets RSA public key
+ - Returns: Public key string
+ - Error Handling: Custom error messages
+
+- `refreshToken()`: Refreshes access token
+ - Returns: New `{access_token}`
+
+## Request Wrapper
+Located in `axios/service.ts`:
+- Base URL configuration
+- Request/response interceptors
+- Error handling
+- Type definitions
+
+## Type Definitions
+Each module has corresponding type definitions:
+```typescript
+// Example from auth/types.ts
+interface LoginParams {
+ username: string
+ password: string
+}
+```
+
+## Error Handling
+- Custom error messages
+- Type-safe error responses
+- Console logging for debugging
diff --git a/docs/web/router.md b/docs/web/router.md
new file mode 100644
index 0000000..53bf8c3
--- /dev/null
+++ b/docs/web/router.md
@@ -0,0 +1,37 @@
+# Router Documentation
+
+## Route Configuration
+
+### Public Routes
+- `/login`: Login page
+- `/register`: Registration page
+
+### Authenticated Routes (Nested under Layout)
+- `/dashboard`: Main dashboard
+- `/user`: User management
+- `/account`: Account settings
+- `/model`: Model management
+
+## Route Meta Fields
+- `requiresAuth`: Boolean indicating if authentication is required
+
+## Route Guards
+### Authentication Check
+1. Checks for `access_token` in localStorage
+2. Redirects to `/login` if:
+ - Route requires auth (`meta.requiresAuth`)
+ - No valid token found
+
+## Technical Details
+- **Mode**: HTML5 History Mode
+- **Component Loading**: Dynamic imports (code splitting)
+- **Base Path**: Project root (`/`)
+
+## Example Usage
+```javascript
+// Adding a new route
+{
+ path: 'new-route',
+ component: () => import('../views/NewRoute.vue'),
+ meta: { requiresAuth: true }
+}
diff --git a/docs/web/store.md b/docs/web/store.md
new file mode 100644
index 0000000..0d2b196
--- /dev/null
+++ b/docs/web/store.md
@@ -0,0 +1,36 @@
+# State Management Documentation
+
+## Architecture
+- **Library**: Pinia (Vue 3 recommended state management)
+- **Structure**: Modular stores
+- **Reactivity**: Composition API style
+
+## User Store
+
+### State Properties
+- `token`: Authentication token
+- `userInfo`: User profile data
+
+### Methods
+- `setToken(token)`: Updates token in store and localStorage
+- `setUserInfo(info)`: Updates user profile
+- `login(params)`: Handles login flow
+ - Parameters: `{username, password}`
+ - Returns: `{access_token}`
+- `getUserInfo()`: Returns current user info
+
+### Persistence
+- Token is automatically synced with localStorage
+- Uses `utils/storage` helper methods
+
+## Usage Example
+```javascript
+import { useUserStore } from '@/store'
+
+const userStore = useUserStore()
+
+// Login
+await userStore.login({username: 'test', password: '123'})
+
+// Get user info
+const user = userStore.getUserInfo()
diff --git a/web/src/api/account/index.ts b/web/src/api/account/index.ts
index a102139..2cde96b 100644
--- a/web/src/api/account/index.ts
+++ b/web/src/api/account/index.ts
@@ -46,14 +46,19 @@ export const toggleAccountStatus = (id: string) =>
url: `/api/accounts/${id}/toggle-status`
})
-export const createAccount = (data: { username: string }) =>
+export const createAccount = (data: { username: string; email: string; password?: string }) =>
request<{
- message: string
- account: AccountItem
+ user_id: string
+ username: string
+ email: string
+ created_at: string
}>({
method: 'POST',
- url: '/api/accounts',
- data
+ url: '/api/accounts/',
+ data: {
+ ...data,
+ password: data.password || 'TempPassword123!' // Default password
+ }
})
// Dify账号相关API
diff --git a/web/src/views/Account/components/CreateAccountDialog.vue b/web/src/views/Account/components/CreateAccountDialog.vue
new file mode 100644
index 0000000..f1413a4
--- /dev/null
+++ b/web/src/views/Account/components/CreateAccountDialog.vue
@@ -0,0 +1,58 @@
+
+
+
+
+ formData.username = val"
+ placeholder="4-20位字母数字或下划线"
+ />
+
+
+ formData.email = val"
+ placeholder="请输入有效邮箱地址"
+ />
+
+
+
+ 取消
+ 确定
+
+
+
+
+
diff --git a/web/src/views/Account/components/CreateAccountForm.vue b/web/src/views/Account/components/CreateAccountForm.vue
new file mode 100644
index 0000000..68ba960
--- /dev/null
+++ b/web/src/views/Account/components/CreateAccountForm.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web/src/views/Account/index.vue b/web/src/views/Account/index.vue
index d4de586..f6b0979 100644
--- a/web/src/views/Account/index.vue
+++ b/web/src/views/Account/index.vue
@@ -91,17 +91,20 @@
+
+