This commit implements multi-database support, allowing the system to switch
between SQL Server and MySQL databases seamlessly.
## New Features
- Database type selection (SQL Server or MySQL) via configuration
- Automatic table name conversion between formats ([dbo].[table] → dbo_table)
- Automatic parameter placeholder handling (? for SQL Server, %s for MySQL)
- GUI settings tab now includes database type dropdown and MySQL configuration
## Database Abstraction Layer
- db/base_connection.py: Abstract base class for database connections
- db/sqlserver_connection.py: SQL Server implementation
- db/mysql_connection.py: MySQL implementation using mysql-connector-python
- db/connection_factory.py: Factory pattern for creating connections
- db/table_name_converter.py: Table name format conversion utility
## DAO Base Class
- db/base_dao.py: Base DAO with helper methods for SQL conversion and placeholders
## Updated Components
- config/schema.py: Extended with DatabaseType enum and MySQL/SQLServer config classes
- config/defaults.py: Added MySQL default configuration
- config/loader.py: Updated to handle new database structure
- db/connection.py: Refactored to use factory pattern and load user config
- All DAO files: Updated to inherit from BaseDAO with automatic conversion
## Dependencies
- Added mysql-connector-python>=8.0.0 to requirements.txt
## Configuration
To use MySQL, set db_type to "mysql" in config/user_settings.json:
{
"database": {
"db_type": "mysql",
"mysql": {
"host": "192.168.31.83",
"port": 3306,
"database": "BLD_DB",
"username": "remote_user",
"password": "3.1415926Beeke"
}
}
}
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
255 lines
7.8 KiB
Python
255 lines
7.8 KiB
Python
"""
|
|
BIPUsers DAO - Data access object for user authentication and management
|
|
"""
|
|
from typing import Optional, Dict, Any, List
|
|
from db.base_dao import BaseDAO
|
|
from db.connection import get_connection
|
|
from config.schema import DatabaseType
|
|
|
|
|
|
class BIPUsersDAO(BaseDAO):
|
|
"""Data access object for BIPUsers table"""
|
|
|
|
def authenticate(self, username: str, password: str) -> Optional[Dict[str, Any]]:
|
|
"""
|
|
Authenticate a user with username and password
|
|
|
|
Args:
|
|
username: The username to authenticate
|
|
password: The password to verify
|
|
|
|
Returns:
|
|
Dict with user info if authentication successful, None otherwise
|
|
Returns: {id, username, user_type}
|
|
"""
|
|
table_name = self._convert_sql('[dbo].[BIPUsers]')
|
|
placeholder = self._get_placeholder()
|
|
|
|
# 根据数据库类型选择列名格式
|
|
if self._db_type == DatabaseType.MYSQL:
|
|
sql = f"""
|
|
SELECT ID, UserName, UserType
|
|
FROM {table_name}
|
|
WHERE UserName = {placeholder} AND Password = {placeholder}
|
|
"""
|
|
else:
|
|
sql = f"""
|
|
SELECT [ID], [UserName], [UserType]
|
|
FROM {table_name}
|
|
WHERE [UserName] = {placeholder} AND [Password] = {placeholder}
|
|
"""
|
|
|
|
with get_connection() as db:
|
|
results = db.execute_query(sql, (username, password))
|
|
if results:
|
|
return {
|
|
'id': results[0]['ID'],
|
|
'username': results[0]['UserName'],
|
|
'user_type': results[0]['UserType']
|
|
}
|
|
return None
|
|
|
|
def get_all_users(self) -> List[Dict[str, Any]]:
|
|
"""
|
|
Get all users from the database
|
|
|
|
Returns:
|
|
List of user dictionaries: [{id, username, user_type, create_time}]
|
|
"""
|
|
table_name = self._convert_sql('[dbo].[BIPUsers]')
|
|
|
|
# 根据数据库类型选择列名格式
|
|
if self._db_type == DatabaseType.MYSQL:
|
|
sql = f"""
|
|
SELECT ID, UserName, UserType, CreateTime
|
|
FROM {table_name}
|
|
ORDER BY UserName
|
|
"""
|
|
else:
|
|
sql = f"""
|
|
SELECT [ID], [UserName], [UserType], [CreateTime]
|
|
FROM {table_name}
|
|
ORDER BY [UserName]
|
|
"""
|
|
|
|
with get_connection() as db:
|
|
results = db.execute_query(sql)
|
|
return [
|
|
{
|
|
'id': row['ID'],
|
|
'username': row['UserName'],
|
|
'user_type': row['UserType'],
|
|
'create_time': row['CreateTime']
|
|
}
|
|
for row in results
|
|
]
|
|
|
|
def create_user(self, username: str, password: str, user_type: str) -> bool:
|
|
"""
|
|
Create a new user
|
|
|
|
Args:
|
|
username: The username (must be unique)
|
|
password: The password (plain text for internal tool)
|
|
user_type: User type ('Admin', 'User', or 'Guest')
|
|
|
|
Returns:
|
|
True if successful, False otherwise
|
|
"""
|
|
table_name = self._convert_sql('[dbo].[BIPUsers]')
|
|
placeholder = self._get_placeholder()
|
|
|
|
# 根据数据库类型选择列名格式
|
|
if self._db_type == DatabaseType.MYSQL:
|
|
sql = f"""
|
|
INSERT INTO {table_name} (UserName, Password, UserType)
|
|
VALUES ({placeholder}, {placeholder}, {placeholder})
|
|
"""
|
|
else:
|
|
sql = f"""
|
|
INSERT INTO {table_name} ([UserName], [Password], [UserType])
|
|
VALUES ({placeholder}, {placeholder}, {placeholder})
|
|
"""
|
|
|
|
try:
|
|
with get_connection() as db:
|
|
db.execute_update(sql, (username, password, user_type))
|
|
return True
|
|
except Exception as e:
|
|
print(f"Error creating user: {e}")
|
|
return False
|
|
|
|
def update_user_type(self, username: str, user_type: str) -> bool:
|
|
"""
|
|
Update a user's type
|
|
|
|
Args:
|
|
username: The username to update
|
|
user_type: New user type ('Admin', 'User', or 'Guest')
|
|
|
|
Returns:
|
|
True if successful, False otherwise
|
|
"""
|
|
table_name = self._convert_sql('[dbo].[BIPUsers]')
|
|
placeholder = self._get_placeholder()
|
|
|
|
# 根据数据库类型选择列名格式
|
|
if self._db_type == DatabaseType.MYSQL:
|
|
sql = f"""
|
|
UPDATE {table_name}
|
|
SET UserType = {placeholder}
|
|
WHERE UserName = {placeholder}
|
|
"""
|
|
else:
|
|
sql = f"""
|
|
UPDATE {table_name}
|
|
SET [UserType] = {placeholder}
|
|
WHERE [UserName] = {placeholder}
|
|
"""
|
|
|
|
try:
|
|
with get_connection() as db:
|
|
db.execute_update(sql, (user_type, username))
|
|
return True
|
|
except Exception as e:
|
|
print(f"Error updating user type: {e}")
|
|
return False
|
|
|
|
def update_password(self, username: str, new_password: str) -> bool:
|
|
"""
|
|
Update a user's password
|
|
|
|
Args:
|
|
username: The username to update
|
|
new_password: The new password (plain text for internal tool)
|
|
|
|
Returns:
|
|
True if successful, False otherwise
|
|
"""
|
|
table_name = self._convert_sql('[dbo].[BIPUsers]')
|
|
placeholder = self._get_placeholder()
|
|
|
|
# 根据数据库类型选择列名格式
|
|
if self._db_type == DatabaseType.MYSQL:
|
|
sql = f"""
|
|
UPDATE {table_name}
|
|
SET Password = {placeholder}
|
|
WHERE UserName = {placeholder}
|
|
"""
|
|
else:
|
|
sql = f"""
|
|
UPDATE {table_name}
|
|
SET [Password] = {placeholder}
|
|
WHERE [UserName] = {placeholder}
|
|
"""
|
|
|
|
try:
|
|
with get_connection() as db:
|
|
db.execute_update(sql, (new_password, username))
|
|
return True
|
|
except Exception as e:
|
|
print(f"Error updating password: {e}")
|
|
return False
|
|
|
|
def delete_user(self, username: str) -> bool:
|
|
"""
|
|
Delete a user
|
|
|
|
Args:
|
|
username: The username to delete
|
|
|
|
Returns:
|
|
True if successful, False otherwise
|
|
"""
|
|
table_name = self._convert_sql('[dbo].[BIPUsers]')
|
|
placeholder = self._get_placeholder()
|
|
|
|
# 根据数据库类型选择列名格式
|
|
if self._db_type == DatabaseType.MYSQL:
|
|
sql = f"""
|
|
DELETE FROM {table_name}
|
|
WHERE UserName = {placeholder}
|
|
"""
|
|
else:
|
|
sql = f"""
|
|
DELETE FROM {table_name}
|
|
WHERE [UserName] = {placeholder}
|
|
"""
|
|
|
|
try:
|
|
with get_connection() as db:
|
|
db.execute_update(sql, (username,))
|
|
return True
|
|
except Exception as e:
|
|
print(f"Error deleting user: {e}")
|
|
return False
|
|
|
|
def user_exists(self, username: str) -> bool:
|
|
"""
|
|
Check if a username already exists
|
|
|
|
Args:
|
|
username: The username to check
|
|
|
|
Returns:
|
|
True if username exists, False otherwise
|
|
"""
|
|
table_name = self._convert_sql('[dbo].[BIPUsers]')
|
|
placeholder = self._get_placeholder()
|
|
|
|
# 根据数据库类型选择列名格式
|
|
if self._db_type == DatabaseType.MYSQL:
|
|
sql = f"""
|
|
SELECT COUNT(*) as count FROM {table_name}
|
|
WHERE UserName = {placeholder}
|
|
"""
|
|
else:
|
|
sql = f"""
|
|
SELECT COUNT(*) as count FROM {table_name}
|
|
WHERE [UserName] = {placeholder}
|
|
"""
|
|
|
|
with get_connection() as db:
|
|
results = db.execute_query(sql, (username,))
|
|
return results[0]['count'] > 0 if results else False
|