diff --git a/README.md b/README.md index 7249adff..366d272f 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,7 @@ youlai-boot/ | **📖 完整文档站** | [docs.youlai.tech](https://www.youlai.tech/docs/admin/) | | **🖥️ 在线预览(前端)** | [vue.youlai.tech](https://vue.youlai.tech) | | **📱 在线预览(移动端)** | [app.youlai.tech](https://app.youlai.tech) | -| **🔗 接口文档** | 启动后访问 `/doc.html` | +| **🔗 接口文档** | 启动后访问 [http://localhost:8000/doc.html](http://localhost:8000/doc.html) | ## 📊 项目统计 diff --git a/src/main/java/com/youlai/boot/codegen/service/impl/CodegenServiceImpl.java b/src/main/java/com/youlai/boot/codegen/service/impl/CodegenServiceImpl.java index ee6be504..cd9a9e1a 100644 --- a/src/main/java/com/youlai/boot/codegen/service/impl/CodegenServiceImpl.java +++ b/src/main/java/com/youlai/boot/codegen/service/impl/CodegenServiceImpl.java @@ -323,6 +323,7 @@ public class CodegenServiceImpl implements CodegenService { bindMap.put("entityKebab", entityKebab); bindMap.put("entityUpperSnake", entityUpperSnake); bindMap.put("businessName", genTable.getBusinessName()); + bindMap.put("entityComment", genTable.getBusinessName()); bindMap.put("fieldConfigs", fieldConfigs); boolean hasLocalDateTime = false; diff --git a/src/main/java/com/youlai/boot/framework/security/token/RedisTokenManager.java b/src/main/java/com/youlai/boot/framework/security/token/RedisTokenManager.java index f054243f..1616bbee 100644 --- a/src/main/java/com/youlai/boot/framework/security/token/RedisTokenManager.java +++ b/src/main/java/com/youlai/boot/framework/security/token/RedisTokenManager.java @@ -168,18 +168,18 @@ public class RedisTokenManager implements TokenManager { } /** - * 使访问令牌失效 + * Make access token invalid + *

+ * Only deletes the current token, not all sessions for the user. + * This ensures single-device logout doesn't affect other devices when allowMultiLogin=true. * - * @param token 访问令牌 + * @param token Access token */ @Override public void invalidateToken(String token) { String cleanToken = cleanBearerPrefix(token); - Object value = redisTemplate.opsForValue().get(formatTokenKey(cleanToken)); - if (value instanceof UserSession userSession) { - Long userId = userSession.getUserId(); - invalidateUserSessions(userId); - } + // Only delete the current token, not all user sessions + redisTemplate.delete(formatTokenKey(cleanToken)); } /** diff --git a/src/main/java/com/youlai/boot/system/controller/UserController.java b/src/main/java/com/youlai/boot/system/controller/UserController.java index 27f427f3..528c1e20 100644 --- a/src/main/java/com/youlai/boot/system/controller/UserController.java +++ b/src/main/java/com/youlai/boot/system/controller/UserController.java @@ -23,6 +23,7 @@ import com.youlai.boot.system.model.vo.CurrentUserVO; import com.youlai.boot.system.model.vo.UserPageVO; import com.youlai.boot.system.model.vo.UserProfileVO; import com.youlai.boot.system.service.UserService; +import com.youlai.boot.framework.security.token.TokenManager; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -54,6 +55,8 @@ import java.util.List; @RequiredArgsConstructor public class UserController { + private final TokenManager tokenManager; + private final UserService userService; @Operation(summary = "用户列表") @@ -122,6 +125,10 @@ public class UserController { .eq(SysUser::getId, userId) .set(SysUser::getStatus, status) ); + // 用户禁用时立即失效其会话 + if (result && status == 0) { + tokenManager.invalidateUserSessions(userId); + } return Result.judge(result); } diff --git a/src/main/java/com/youlai/boot/system/service/impl/RoleServiceImpl.java b/src/main/java/com/youlai/boot/system/service/impl/RoleServiceImpl.java index de6e5423..0c55e54f 100644 --- a/src/main/java/com/youlai/boot/system/service/impl/RoleServiceImpl.java +++ b/src/main/java/com/youlai/boot/system/service/impl/RoleServiceImpl.java @@ -215,6 +215,14 @@ public class RoleServiceImpl extends ServiceImpl implements Ro if (result) { // 刷新角色的权限缓存 roleMenuService.refreshRolePermsCache(role.getCode()); + + // When role is disabled, invalidate sessions of all users with this role + if (status == 0) { + List userIds = userRoleService.listUserIdsByRoleId(roleId); + for (Long userId : userIds) { + tokenManager.invalidateUserSessions(userId); + } + } } return result; } diff --git a/src/main/resources/templates/codegen/backend/controller.java.vm b/src/main/resources/templates/codegen/backend/controller.java.vm index 8ae9f9e9..e79be4f3 100644 --- a/src/main/resources/templates/codegen/backend/controller.java.vm +++ b/src/main/resources/templates/codegen/backend/controller.java.vm @@ -8,8 +8,8 @@ import ${packageName}.${moduleName}.model.form.${entityName}Form; import ${packageName}.${moduleName}.model.query.${entityName}Query; import ${packageName}.${moduleName}.model.vo.${entityName}Vo; import com.baomidou.mybatisplus.core.metadata.IPage; -import com.youlai.boot.common.result.PageResult; -import com.youlai.boot.common.result.Result; +import ${packageName}.common.result.PageResult; +import ${packageName}.common.result.Result; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Operation; diff --git a/src/main/resources/templates/codegen/backend/entity.java.vm b/src/main/resources/templates/codegen/backend/entity.java.vm index 2f6b2cbf..15a8dd43 100644 --- a/src/main/resources/templates/codegen/backend/entity.java.vm +++ b/src/main/resources/templates/codegen/backend/entity.java.vm @@ -9,7 +9,7 @@ import java.time.LocalDateTime; import java.math.BigDecimal; #end import com.baomidou.mybatisplus.annotation.TableName; -import com.youlai.boot.common.base.BaseEntity; +import ${packageName}.common.base.BaseEntity; /** * $!{businessName}实体对象 diff --git a/src/main/resources/templates/codegen/backend/query.java.vm b/src/main/resources/templates/codegen/backend/query.java.vm index 23c8ed93..ee06df4a 100644 --- a/src/main/resources/templates/codegen/backend/query.java.vm +++ b/src/main/resources/templates/codegen/backend/query.java.vm @@ -1,6 +1,6 @@ package ${packageName}.${moduleName}.${subpackageName}; -import com.youlai.boot.common.base.BaseQuery; +import ${packageName}.common.base.BaseQuery; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.Setter; diff --git a/src/main/resources/templates/codegen/backend/vo.java.vm b/src/main/resources/templates/codegen/backend/vo.java.vm index 46081562..30f3a126 100644 --- a/src/main/resources/templates/codegen/backend/vo.java.vm +++ b/src/main/resources/templates/codegen/backend/vo.java.vm @@ -2,7 +2,6 @@ package ${packageName}.${moduleName}.model.vo; import java.io.Serial; import java.io.Serializable; -import java.time.LocalDateTime; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.Setter;