From 553f62d268f0f1784095ba76f7e0db8b3193bfa7 Mon Sep 17 00:00:00 2001
From: shinnosuke <tantao@1hoper.com>
Date: 星期四, 06 八月 2026 21:52:06 +0800
Subject: [PATCH] fix(admin): 保护超级管理员账号 (bug #24022)

---
 talent-card-server/src/main/java/com/talentcard/server/business/admin/AdminManagementService.java |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/talent-card-server/src/main/java/com/talentcard/server/business/admin/AdminManagementService.java b/talent-card-server/src/main/java/com/talentcard/server/business/admin/AdminManagementService.java
index 9aac12c..70c549f 100644
--- a/talent-card-server/src/main/java/com/talentcard/server/business/admin/AdminManagementService.java
+++ b/talent-card-server/src/main/java/com/talentcard/server/business/admin/AdminManagementService.java
@@ -28,11 +28,12 @@
 
     public List<Map<String, Object>> staff() { return rows("select id,account,display_name,mobile,role_code,position_name,customer_wechat,status,created_at from admin_operator where deleted=0 order by id"); }
     @Transactional public Map<String, Object> createStaff(AdminStaffRequest request) { if (request.password() == null || request.password().isBlank()) throw new BusinessException(ErrorCode.BAD_REQUEST, "A password is required for a new staff account"); jdbc.update("insert into admin_operator(account,password_hash,display_name,mobile,role_code,position_name,customer_wechat,status) values (?,?,?,?,?,?,?,?)", request.account().trim(), MerchantPasswordHasher.encode(request.password()), request.displayName().trim(), blankToNull(request.mobile()), request.roleCode(), request.positionName().trim(), blankToNull(request.customerWechat()), request.status()); return staffOne("last_insert_id()"); }
-    @Transactional public Map<String, Object> updateStaff(Long id, AdminStaffRequest request) { String sql = request.password() == null || request.password().isBlank() ? "update admin_operator set account=?,display_name=?,mobile=?,role_code=?,position_name=?,customer_wechat=?,status=? where id=?" : "update admin_operator set account=?,password_hash=?,display_name=?,mobile=?,role_code=?,position_name=?,customer_wechat=?,status=? where id=?"; int updated = request.password() == null || request.password().isBlank() ? jdbc.update(sql, request.account().trim(), request.displayName().trim(), blankToNull(request.mobile()), request.roleCode(), request.positionName().trim(), blankToNull(request.customerWechat()), request.status(), id) : jdbc.update(sql, request.account().trim(), MerchantPasswordHasher.encode(request.password()), request.displayName().trim(), blankToNull(request.mobile()), request.roleCode(), request.positionName().trim(), blankToNull(request.customerWechat()), request.status(), id); if (updated == 0) throw new BusinessException(ErrorCode.NOT_FOUND, "Staff account does not exist"); return staffOne("?", id); }
+    @Transactional public Map<String, Object> updateStaff(Long id, AdminStaffRequest request) { if (request.status() == 0 && isDefaultAdmin(id)) throw new BusinessException(ErrorCode.CONFLICT, "超级管理员不可禁用"); String sql = request.password() == null || request.password().isBlank() ? "update admin_operator set account=?,display_name=?,mobile=?,role_code=?,position_name=?,customer_wechat=?,status=? where id=?" : "update admin_operator set account=?,password_hash=?,display_name=?,mobile=?,role_code=?,position_name=?,customer_wechat=?,status=? where id=?"; int updated = request.password() == null || request.password().isBlank() ? jdbc.update(sql, request.account().trim(), request.displayName().trim(), blankToNull(request.mobile()), request.roleCode(), request.positionName().trim(), blankToNull(request.customerWechat()), request.status(), id) : jdbc.update(sql, request.account().trim(), MerchantPasswordHasher.encode(request.password()), request.displayName().trim(), blankToNull(request.mobile()), request.roleCode(), request.positionName().trim(), blankToNull(request.customerWechat()), request.status(), id); if (updated == 0) throw new BusinessException(ErrorCode.NOT_FOUND, "Staff account does not exist"); return staffOne("?", id); }
     @Transactional public Map<String, Object> resetStaffPassword(Long id, String password) { if (password == null || password.length() < 6 || password.length() > 64) throw new BusinessException(ErrorCode.BAD_REQUEST, "Password must be 6-64 characters"); int updated = jdbc.update("update admin_operator set password_hash=?, login_failed_count=0, locked_until=null where id=? and deleted=0", MerchantPasswordHasher.encode(password), id); if (updated == 0) throw new BusinessException(ErrorCode.NOT_FOUND, "Staff account does not exist"); return Map.of("id", id, "reset", true); }
     @Transactional public Map<String, Object> deleteStaff(Long id) { int updated = jdbc.update("update admin_operator set deleted=1, status=0 where id=? and deleted=0 and account <> 'admin'", id); if (updated == 0) throw new BusinessException(ErrorCode.CONFLICT, "The account cannot be deleted or does not exist"); return Map.of("id", id, "deleted", true); }
 
     private String roleCode(String supplied) { return supplied == null || supplied.isBlank() ? "role_" + System.currentTimeMillis() : supplied.trim(); }
+    private boolean isDefaultAdmin(Long id) { return Boolean.TRUE.equals(jdbc.queryForObject("select exists(select 1 from admin_operator where id=? and deleted=0 and account='admin')", Boolean.class, id)); }
     private Map<String, Object> staffOne(String where, Object... args) { return one("select id,account,display_name,mobile,role_code,position_name,customer_wechat,status,created_at from admin_operator where id=" + where, args); }
     private String blankToNull(String value) { return value == null || value.isBlank() ? null : value.trim(); }
     private String existingRoleCode(Long id) { List<Map<String, Object>> result = rows("select role_code from admin_role where id=?", id); if (result.isEmpty()) throw new BusinessException(ErrorCode.NOT_FOUND, "Role does not exist"); return String.valueOf(result.get(0).get("roleCode")); }

--
Gitblit v1.7.1