feat: implement user authentication and permission-based data filtering
Add user login system with role-based access control: - Admin users see all data and can filter by any manager - Regular users only see records where ManagerName matches their username New components: - BIPUsersDAO: user authentication and management - SessionManager: singleton session state management - LoginDialog: modal login UI for app startup - init_users.sql: initial user setup script Permission enforcement: - Material validation tab: hide manager filter for non-admin, force filter by current user - Material type management: hide filter UI for non-admin, filter at database level - Window title and status bar display current user info Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -131,16 +131,18 @@ class CheckboxTreeview(ttk.Treeview):
|
||||
class MaterialValidationTab(ttk.Frame):
|
||||
"""物料校验标签页"""
|
||||
|
||||
def __init__(self, parent, config: ConfigManager):
|
||||
def __init__(self, parent, config: ConfigManager, session_manager):
|
||||
"""
|
||||
初始化物料校验标签页
|
||||
|
||||
Args:
|
||||
parent: 父容器
|
||||
config: 配置管理器
|
||||
session_manager: SessionManager 实例,用于权限控制
|
||||
"""
|
||||
super().__init__(parent)
|
||||
self.config = config
|
||||
self.session_manager = session_manager
|
||||
self.validating = False
|
||||
self.validation_results = None
|
||||
self.material_records_cache = None # 缓存完整的物料记录
|
||||
@@ -421,7 +423,17 @@ class MaterialValidationTab(ttk.Frame):
|
||||
widget.destroy()
|
||||
self.manager_checkboxes.clear()
|
||||
|
||||
# 从两个表获取负责人列表并合并去重
|
||||
# PERMISSION CHECK: 非管理员用户只能看到自己的数据
|
||||
if not self.session_manager.is_admin():
|
||||
self.managers = [self.session_manager.get_username()]
|
||||
# 不显示复选框,直接显示提示信息
|
||||
ttk.Label(
|
||||
self.filter_frame,
|
||||
text=f"仅显示您的数据(负责人:{self.session_manager.get_username()})"
|
||||
).pack(anchor="w")
|
||||
return
|
||||
|
||||
# 管理员:从两个表获取负责人列表并合并去重
|
||||
from db.materials_to_be_deleted_records_dao import MaterialsToBeDeletedDAO
|
||||
|
||||
record_dao = MaterialsToBeDeletedDAO()
|
||||
@@ -501,7 +513,11 @@ class MaterialValidationTab(ttk.Frame):
|
||||
if not self.material_records_cache:
|
||||
return
|
||||
|
||||
selected_managers = self._get_selected_managers()
|
||||
# PERMISSION CHECK: 非管理员用户强制筛选到当前用户
|
||||
if not self.session_manager.is_admin():
|
||||
selected_managers = [self.session_manager.get_username()]
|
||||
else:
|
||||
selected_managers = self._get_selected_managers()
|
||||
|
||||
if not selected_managers:
|
||||
# 没有选中任何负责人,清空表格
|
||||
@@ -541,7 +557,12 @@ class MaterialValidationTab(ttk.Frame):
|
||||
# 从数据库获取已标记删除的记录
|
||||
from db.materials_to_be_deleted_records_dao import MaterialsToBeDeletedDAO
|
||||
record_dao = MaterialsToBeDeletedDAO()
|
||||
marked_records = record_dao.get_all_records()
|
||||
|
||||
# PERMISSION CHECK: 非管理员用户只获取自己的记录
|
||||
if not self.session_manager.is_admin():
|
||||
marked_records = record_dao.get_materials_by_manager(self.session_manager.get_username())
|
||||
else:
|
||||
marked_records = record_dao.get_all_records()
|
||||
|
||||
# Build dictionary: MaterialCode -> ManagerName
|
||||
marked_codes_dict = {
|
||||
@@ -795,7 +816,12 @@ class MaterialValidationTab(ttk.Frame):
|
||||
# 从数据库获取已标记删除的 MaterialCode -> ManagerName 映射
|
||||
from db.materials_to_be_deleted_records_dao import MaterialsToBeDeletedDAO
|
||||
record_dao = MaterialsToBeDeletedDAO()
|
||||
marked_records = record_dao.get_all_records()
|
||||
|
||||
# PERMISSION CHECK: 非管理员用户只获取自己的记录
|
||||
if not self.session_manager.is_admin():
|
||||
marked_records = record_dao.get_materials_by_manager(self.session_manager.get_username())
|
||||
else:
|
||||
marked_records = record_dao.get_all_records()
|
||||
|
||||
# Build dictionary: MaterialCode -> ManagerName
|
||||
marked_codes_dict = {
|
||||
@@ -1067,4 +1093,4 @@ class MaterialValidationTab(ttk.Frame):
|
||||
|
||||
def open_type_management(self):
|
||||
"""打开类型管理窗口"""
|
||||
dialog = MaterialTypeManagementDialog(self, title="物料类型管理")
|
||||
dialog = MaterialTypeManagementDialog(self, self.session_manager, title="物料类型管理")
|
||||
|
||||
Reference in New Issue
Block a user