feat: 创作者账号体系(后台开号 → 登录即进创作者中心)+ 创作者中心菜单只给创作者
为什么:创作者此前根本无法登录 —— creator.admin_user_id 只有实体字段、没有任何接口会写它,
C 端申请入驻也没做,等于整条账号链路缺入口。这批先把"后台手工建主体 → 审核 → 开号 → 登录落地"打通;
同时按用户口径收窄菜单:只要不是创作者,就不显示创作者中心。
- 手工建主体:POST /admin/creators(编号可传可自动生成 CR+日期+序号)+ 审核页「新增创作者」
- 开通账号:POST /admin/creators/{id}/account —— 仅 approved 可开(否则 200003)、已开通幂等返回
(created=false、不回明文)、用户名默认 creator.code 小写且冲突报 200001、随机 10 位初始密码一次性返回、
建 sys_admin_user + 绑 creator.admin_user_id + 授 creator 角色
- 重置密码:POST /admin/creators/{id}/account/reset-password(同样一次性明文,旧密码立即失效)
- 首登强制改密:sys_admin_user 加 must_change_password 列(幂等 ALTER;不新建表、不复用 two_factor 是因为
这个标记要能直接驱动登录响应与前端拦截),开号/重置置 1,自助改密后清 0
- 菜单收窄:26-30 从超管收回(sys_role_menu delete);另外发现超管的菜单是"全量兜底"、根本不看角色-菜单表,
光收授权无效,所以加 sys_menu.super_admin_visible,这几条置 0 —— 超管侧边栏不再出现创作者中心
(代看代码保留,只是没有入口了,见回执)
- 权限点 creator:account(只授超管);creator:list 之外的读接口未变
实测:未审核开号 200003 / 重复开号幂等 / 用户名冲突 200001 / 重置后旧密码失效新密码可登录 /
新账号只能看到自己的作品;创作者登录直接落 /creator-center/workspace 并弹出首登改密。
This commit is contained in:
1 parent
efeb9fcfaf
commit
414d9fd482
15 files changed
+377
-8
No files matched your search
+2
@@ -25,6 +25,8 @@ public class AdminUser {
|
||||
private Integer status;
|
||||
private String ipWhitelist;
|
||||
private Integer twoFactor;
|
||||
/** 1 = 首登强制改密(后台开号 / 重置密码后置位) */
|
||||
private Integer mustChangePassword;
|
||||
private LocalDateTime lastLoginAt;
|
||||
private String lastLoginIp;
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@@ -28,6 +28,8 @@ public class Menu {
|
||||
private Integer affix;
|
||||
private Integer sort;
|
||||
private Integer visible;
|
||||
/** 0 = 不给超管显示(角色专属菜单;超管菜单是全量兜底,不看 sys_role_menu) */
|
||||
private Integer superAdminVisible;
|
||||
private Integer status;
|
||||
private LocalDateTime createdAt;
|
||||
/** updated_at 交给数据库的 ON UPDATE CURRENT_TIMESTAMP 维护 */
|
||||
|
||||
+35
@@ -73,6 +73,14 @@ public class AdminUserService {
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long create(AdminUserSaveReqVO req) {
|
||||
return create(req, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 建后台账号。mustChangePassword=true 用于"后台开号/重置密码"场景:
|
||||
* 初始密码是转达给使用者的,登录后必须先改密。
|
||||
*/
|
||||
public Long create(AdminUserSaveReqVO req, boolean mustChangePassword) {
|
||||
if (!StringUtils.hasText(req.getUsername())) {
|
||||
throw new ServiceException(ErrorCode.BAD_REQUEST, "请输入登录账号");
|
||||
}
|
||||
@@ -91,6 +99,7 @@ public class AdminUserService {
|
||||
user.setStatus(req.getStatus() == null ? 1 : req.getStatus());
|
||||
user.setIpWhitelist(req.getIpWhitelist() == null ? "" : req.getIpWhitelist());
|
||||
user.setTwoFactor(req.getTwoFactor() == null ? 0 : req.getTwoFactor());
|
||||
user.setMustChangePassword(mustChangePassword ? 1 : 0);
|
||||
user.setMobile("");
|
||||
user.setEmail("");
|
||||
user.setAvatar("");
|
||||
@@ -148,15 +157,41 @@ public class AdminUserService {
|
||||
throw new ServiceException(ErrorCode.BAD_REQUEST, "新密码长度不能少于 6 位");
|
||||
}
|
||||
user.setPassword(passwordEncoder.encode(newPassword));
|
||||
user.setMustChangePassword(1);
|
||||
adminUserMapper.updateById(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* 运营重置创作者账号密码:直接置新密码并标记"下次登录必须改密"。
|
||||
* 与 resetPassword 的区别是这里接受调用方生成的一次性明文(后台展示后即作废)。
|
||||
*/
|
||||
public void resetPasswordTo(Long id, String rawPassword, boolean mustChangePassword) {
|
||||
AdminUser user = getExisting(id);
|
||||
if (!StringUtils.hasText(rawPassword)) {
|
||||
throw new ServiceException(ErrorCode.BAD_REQUEST, "请输入新密码");
|
||||
}
|
||||
user.setPassword(passwordEncoder.encode(rawPassword));
|
||||
user.setMustChangePassword(mustChangePassword ? 1 : 0);
|
||||
adminUserMapper.updateById(user);
|
||||
}
|
||||
|
||||
/** 改完密码(含首登强制改密)后清掉标记 */
|
||||
public void clearMustChangePassword(Long id) {
|
||||
AdminUser user = getExisting(id);
|
||||
if (user.getMustChangePassword() != null && user.getMustChangePassword() == 1) {
|
||||
user.setMustChangePassword(0);
|
||||
adminUserMapper.updateById(user);
|
||||
}
|
||||
}
|
||||
|
||||
public void changePassword(Long id, String oldPassword, String newPassword) {
|
||||
AdminUser user = getExisting(id);
|
||||
if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
|
||||
throw new ServiceException(ErrorCode.BAD_REQUEST, "原密码不正确");
|
||||
}
|
||||
user.setPassword(passwordEncoder.encode(newPassword));
|
||||
// 自己改过密码就不再要求改密(首登强制改密也走这条)
|
||||
user.setMustChangePassword(0);
|
||||
adminUserMapper.updateById(user);
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -50,6 +50,7 @@ public class AuthService {
|
||||
.roleName(role == null ? null : role.getName())
|
||||
.roleId(role == null ? null : role.getId())
|
||||
.permissions(permissions)
|
||||
.mustChangePassword(user.getMustChangePassword() != null && user.getMustChangePassword() == 1)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -71,6 +72,7 @@ public class AuthService {
|
||||
.roleName(role == null ? null : role.getName())
|
||||
.roleId(role == null ? null : role.getId())
|
||||
.permissions(permissions)
|
||||
.mustChangePassword(user.getMustChangePassword() != null && user.getMustChangePassword() == 1)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -31,7 +31,11 @@ public class MenuService {
|
||||
}
|
||||
List<Menu> all = listEnabled();
|
||||
if (RoleService.SUPER_ADMIN_CODE.equals(role.getCode())) {
|
||||
return buildTree(all);
|
||||
// 超管默认看全量,但 super_admin_visible=0 的"角色专属菜单"(如创作者中心)要排除,
|
||||
// 否则对超管收窄 sys_role_menu 是无效的
|
||||
return buildTree(all.stream()
|
||||
.filter(menu -> menu.getSuperAdminVisible() == null || menu.getSuperAdminVisible() != 0)
|
||||
.toList());
|
||||
}
|
||||
List<String> codes = roleService.listCodesByRoleId(role.getId());
|
||||
return buildTree(all.stream()
|
||||
|
||||
@@ -19,4 +19,6 @@ public class LoginRespVO {
|
||||
private String roleName;
|
||||
private Long roleId;
|
||||
private List<String> permissions;
|
||||
/** 首登强制改密:前端据此弹出改密对话框 */
|
||||
private Boolean mustChangePassword;
|
||||
}
|
||||
@@ -21,4 +21,6 @@ public class ProfileRespVO {
|
||||
private String roleName;
|
||||
private Long roleId;
|
||||
private List<String> permissions;
|
||||
/** 首登强制改密:刷新页面后仍然要能拦住 */
|
||||
private Boolean mustChangePassword;
|
||||
}
|
||||
Reference in new issue
Block a user