From 1828c37fca59742e55100d3aace094170057fa40 Mon Sep 17 00:00:00 2001 From: Chuyaoyuan Date: Fri, 8 May 2026 19:20:49 +0800 Subject: [PATCH] Update admin --- .github/copilot-instructions.md | 44 +++++++++++++++++++ .../java/com/yaoyuan/jiscuss/common/Node.java | 2 +- .../jiscuss/common/PostCommonUtil.java | 2 +- .../controller/AdminSystemController.java | 14 +++--- .../jiscuss/controller/BaseController.java | 2 +- .../jiscuss/controller/UserMsgController.java | 2 +- .../controller/UserOtherController.java | 2 +- .../controller/UserPageController.java | 2 +- .../controller/UserPostController.java | 2 +- .../controller/UserSystemController.java | 2 +- .../yaoyuan/jiscuss/entity/LikeCollect.java | 2 +- .../com/yaoyuan/jiscuss/entity/UserInfo.java | 2 +- .../entity/custom/DiscussionCustom.java | 2 +- .../jiscuss/entity/custom/PostCustom.java | 2 +- .../jiscuss/entity/custom/TagCustom.java | 2 +- .../com/yaoyuan/jiscuss/util/DelTagsUtil.java | 2 +- ...words.sql => V3__reset_seed_passwords.sql} | 0 ...console.sql => V4__rbac_admin_console.sql} | 2 +- ...2.0.3__audit_log.sql => V5__audit_log.sql} | 2 +- .../resources/templates/admin/admin-shell.ftl | 2 +- .../resources/templates/admin/audit-logs.ftl | 2 +- .../resources/templates/admin/discussions.ftl | 2 +- src/main/resources/templates/admin/home.ftl | 2 +- .../resources/templates/admin/plugins.ftl | 2 +- src/main/resources/templates/admin/posts.ftl | 6 +-- src/main/resources/templates/admin/themes.ftl | 2 +- .../templates/admin/upgrade-logs.ftl | 2 +- src/main/resources/templates/admin/users.ftl | 4 +- 28 files changed, 79 insertions(+), 35 deletions(-) create mode 100644 .github/copilot-instructions.md rename src/main/resources/db/migration/{V2.0.1__reset_seed_passwords.sql => V3__reset_seed_passwords.sql} (100%) rename src/main/resources/db/migration/{V2.0.2__rbac_admin_console.sql => V4__rbac_admin_console.sql} (96%) rename src/main/resources/db/migration/{V2.0.3__audit_log.sql => V5__audit_log.sql} (88%) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..81bbf4e --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,44 @@ +# Copilot Instructions for Jiscuss + +## Build, test, and run commands + +This repository is a Maven Spring Boot project (Java 17+). + +- Full compile: `mvn -DskipTests compile` +- Full test suite: `mvn test` +- Run one test class: `mvn -Dtest=ClassName test` +- Run one test method: `mvn -Dtest=ClassName#methodName test` +- Run app (default H2 profile): `mvn spring-boot:run` +- Run app (MySQL profile): `mvn spring-boot:run -Dspring-boot.run.profiles=mysql` +- Run app on a non-80 port: `mvn spring-boot:run -Dspring-boot.run.arguments="--server.port=8080"` + +There is currently no dedicated lint plugin configured in `pom.xml` (no Checkstyle/SpotBugs/PMD task). + +## High-level architecture + +Jiscuss is a Spring Boot monolith with a server-rendered web UI plus REST APIs: + +- **Web MVC + templates**: `controller/` classes return FreeMarker views from `src/main/resources/templates/`, with frontend assets under `src/main/resources/static/` (Semantic UI + custom JS). +- **REST APIs**: `controller/api/` exposes JSON endpoints (`/user_api/**`, `/other_api/**`) and is documented by SpringDoc OpenAPI (`/swagger-ui.html`, `/v3/api-docs`). +- **Domain and persistence**: `entity/` models map to relational tables; `repository/` uses Spring Data JPA (plus a few native queries); `service/impl/` contains business logic and transaction boundaries. +- **Security and RBAC**: `WebSecurityConfig` wires Spring Security 6; auth uses `UserDetailServiceImpl`; path checks delegate to `RbacPermission`; roles come from `rbac_role` / `rbac_user_role` (Flyway migration `V4__rbac_admin_console.sql`). +- **Admin console and auditing**: `/admin/**` endpoints in `AdminSystemController` manage users/roles/content and write operation history via `AuditLogService`. +- **Database lifecycle**: Flyway owns schema/data evolution (`src/main/resources/db/migration/*`), with profile-specific datasource config in `application-h2.yml` and `application-mysql.yml`. + +## Key repository conventions + +- **Flyway is the source of truth for DDL**: keep schema changes in new migration files; do not reintroduce `schema.sql`/`data.sql` initialization paths. +- **Boot 3 / Jakarta imports only**: use `jakarta.*` APIs (not legacy `javax.*` servlet/validation/persistence types). +- **Password handling is BCrypt-only**: DB passwords are expected to be BCrypt hashes (`UserDetailServiceImpl`, migration notes in `V2__security_updates.sql`); do not add plaintext comparisons in SQL/repositories. +- **Role naming convention**: security authorities are `ROLE_*`; database role codes are plain (`ADMIN`, `USER`) and are prefixed in the auth layer. +- **Controller split matters**: + - `controller/` for page flows and model population + - `controller/api/` for REST endpoints + - `AdminSystemController` for admin workflows under `/admin/**` +- **Current user lookup pattern**: controllers extending `BaseController` use `getUserInfo(HttpServletRequest)` (reads `SPRING_SECURITY_CONTEXT` from session). +- **Response wrappers are mixed**: newer global exception flow returns `ApiResponse`; legacy endpoints still return entities or `ResponseResult`. Keep changes consistent with the style already used in the touched controller package. +- **Caching is selective**: user read paths in `UsersServiceImpl` use cache names (`user`, `userList`) backed by Ehcache JCache (`ehcache3.xml`). +- **Profile behavior**: + - default/dev flow is H2 profile + - MySQL requires explicit profile activation and datasource credentials + - admin-only tooling endpoints include `/admin/**`, `/actuator/**`, `/druid/**` (and H2 console when enabled) diff --git a/src/main/java/com/yaoyuan/jiscuss/common/Node.java b/src/main/java/com/yaoyuan/jiscuss/common/Node.java index 7939139..f49c3fc 100644 --- a/src/main/java/com/yaoyuan/jiscuss/common/Node.java +++ b/src/main/java/com/yaoyuan/jiscuss/common/Node.java @@ -10,7 +10,7 @@ import java.util.Date; import java.util.List; /** - * @author yaoyuan2.chu + * @author Chuyaoyuan * @Title: * @Package com.yaoyuan.jiscuss.common * @Description: diff --git a/src/main/java/com/yaoyuan/jiscuss/common/PostCommonUtil.java b/src/main/java/com/yaoyuan/jiscuss/common/PostCommonUtil.java index 17436d9..5ce0626 100644 --- a/src/main/java/com/yaoyuan/jiscuss/common/PostCommonUtil.java +++ b/src/main/java/com/yaoyuan/jiscuss/common/PostCommonUtil.java @@ -13,7 +13,7 @@ import java.util.List; import java.util.Map; /** - * @author yaoyuan2.chu + * @author Chuyaoyuan * @Title: 工具类 * @Package com.yaoyuan.jiscuss.common * @Description: 通用工具类 diff --git a/src/main/java/com/yaoyuan/jiscuss/controller/AdminSystemController.java b/src/main/java/com/yaoyuan/jiscuss/controller/AdminSystemController.java index 1649d29..08d25b1 100644 --- a/src/main/java/com/yaoyuan/jiscuss/controller/AdminSystemController.java +++ b/src/main/java/com/yaoyuan/jiscuss/controller/AdminSystemController.java @@ -40,7 +40,7 @@ import java.util.Set; import java.util.stream.Collectors; /** - * @author yaoyuan2.chu + * @author Chuyaoyuan * 后台系统控制器 */ @Controller @@ -98,9 +98,9 @@ public class AdminSystemController extends BaseController { List users = usersRepository.findAll(Sort.by(Sort.Direction.ASC, "id")); List roles = roleRepository.findAllByOrderByIdAsc(); - Map> userRoleIds = new HashMap<>(); + Map> userRoleIds = new HashMap<>(); for (UserRole ur : userRoleRepository.findAll()) { - userRoleIds.computeIfAbsent(ur.getUserId(), key -> new HashSet<>()).add(ur.getRoleId()); + userRoleIds.computeIfAbsent(String.valueOf(ur.getUserId()), key -> new HashSet<>()).add(ur.getRoleId()); } map.put("users", users); @@ -222,10 +222,10 @@ public class AdminSystemController extends BaseController { Set userIds = posts.stream().map(Post::getCreateId).filter(v -> v != null).collect(Collectors.toSet()); Set discussionIds = posts.stream().map(Post::getDiscussionId).filter(v -> v != null).collect(Collectors.toSet()); - Map userNames = usersRepository.findAllById(userIds).stream() - .collect(Collectors.toMap(User::getId, User::getUsername)); - Map discussionNames = discussionsRepository.findAllById(discussionIds).stream() - .collect(Collectors.toMap(Discussion::getId, Discussion::getTitle)); + Map userNames = usersRepository.findAllById(userIds).stream() + .collect(Collectors.toMap(user -> String.valueOf(user.getId()), User::getUsername)); + Map discussionNames = discussionsRepository.findAllById(discussionIds).stream() + .collect(Collectors.toMap(discussion -> String.valueOf(discussion.getId()), Discussion::getTitle)); map.put("userNames", userNames); map.put("discussionNames", discussionNames); diff --git a/src/main/java/com/yaoyuan/jiscuss/controller/BaseController.java b/src/main/java/com/yaoyuan/jiscuss/controller/BaseController.java index 1979486..8a50653 100644 --- a/src/main/java/com/yaoyuan/jiscuss/controller/BaseController.java +++ b/src/main/java/com/yaoyuan/jiscuss/controller/BaseController.java @@ -9,7 +9,7 @@ import org.springframework.security.core.context.SecurityContext; /** * Base controller exposing helpers shared by web controllers. * - * @author yaoyuan2.chu + * @author Chuyaoyuan */ public class BaseController { diff --git a/src/main/java/com/yaoyuan/jiscuss/controller/UserMsgController.java b/src/main/java/com/yaoyuan/jiscuss/controller/UserMsgController.java index 7aff4bc..673aad6 100644 --- a/src/main/java/com/yaoyuan/jiscuss/controller/UserMsgController.java +++ b/src/main/java/com/yaoyuan/jiscuss/controller/UserMsgController.java @@ -3,7 +3,7 @@ package com.yaoyuan.jiscuss.controller; import org.springframework.stereotype.Controller; /** - * @author yaoyuan2.chu + * @author Chuyaoyuan * 用户消息控制器 */ @Controller diff --git a/src/main/java/com/yaoyuan/jiscuss/controller/UserOtherController.java b/src/main/java/com/yaoyuan/jiscuss/controller/UserOtherController.java index 926ab69..adc64d4 100644 --- a/src/main/java/com/yaoyuan/jiscuss/controller/UserOtherController.java +++ b/src/main/java/com/yaoyuan/jiscuss/controller/UserOtherController.java @@ -3,7 +3,7 @@ package com.yaoyuan.jiscuss.controller; import org.springframework.stereotype.Controller; /** - * @author yaoyuan2.chu + * @author Chuyaoyuan * 其他控制器——积分/权限等 */ @Controller diff --git a/src/main/java/com/yaoyuan/jiscuss/controller/UserPageController.java b/src/main/java/com/yaoyuan/jiscuss/controller/UserPageController.java index 724660f..c9ea434 100644 --- a/src/main/java/com/yaoyuan/jiscuss/controller/UserPageController.java +++ b/src/main/java/com/yaoyuan/jiscuss/controller/UserPageController.java @@ -15,7 +15,7 @@ import org.springframework.web.bind.annotation.RequestParam; import jakarta.servlet.http.HttpServletRequest; /** - * @author yaoyuan2.chu + * @author Chuyaoyuan * @Title: * @Package com.yaoyuan.jiscuss.controller * @Description: diff --git a/src/main/java/com/yaoyuan/jiscuss/controller/UserPostController.java b/src/main/java/com/yaoyuan/jiscuss/controller/UserPostController.java index c411c9f..09bdd59 100644 --- a/src/main/java/com/yaoyuan/jiscuss/controller/UserPostController.java +++ b/src/main/java/com/yaoyuan/jiscuss/controller/UserPostController.java @@ -33,7 +33,7 @@ import java.util.List; import java.util.Map; /** - * @author yaoyuan2.chu + * @author Chuyaoyuan * 主题帖子评论控制器 */ @Controller diff --git a/src/main/java/com/yaoyuan/jiscuss/controller/UserSystemController.java b/src/main/java/com/yaoyuan/jiscuss/controller/UserSystemController.java index abfdf34..c052e41 100644 --- a/src/main/java/com/yaoyuan/jiscuss/controller/UserSystemController.java +++ b/src/main/java/com/yaoyuan/jiscuss/controller/UserSystemController.java @@ -34,7 +34,7 @@ import java.util.Set; import java.util.stream.Collectors; /** - * @author yaoyuan2.chu + * @author Chuyaoyuan * 首页页面系统控制器 */ @Controller diff --git a/src/main/java/com/yaoyuan/jiscuss/entity/LikeCollect.java b/src/main/java/com/yaoyuan/jiscuss/entity/LikeCollect.java index 4f3acde..584ab13 100644 --- a/src/main/java/com/yaoyuan/jiscuss/entity/LikeCollect.java +++ b/src/main/java/com/yaoyuan/jiscuss/entity/LikeCollect.java @@ -12,7 +12,7 @@ import java.io.Serializable; import java.util.Date; /** - * @author yaoyuan2.chu + * @author Chuyaoyuan */ @Data @Entity diff --git a/src/main/java/com/yaoyuan/jiscuss/entity/UserInfo.java b/src/main/java/com/yaoyuan/jiscuss/entity/UserInfo.java index 631ad31..3fcab82 100644 --- a/src/main/java/com/yaoyuan/jiscuss/entity/UserInfo.java +++ b/src/main/java/com/yaoyuan/jiscuss/entity/UserInfo.java @@ -7,7 +7,7 @@ import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; /** - * @author yaoyuan2.chu + * @author Chuyaoyuan * @Title: * @Package com.yaoyuan.jiscuss.entity * @Description: diff --git a/src/main/java/com/yaoyuan/jiscuss/entity/custom/DiscussionCustom.java b/src/main/java/com/yaoyuan/jiscuss/entity/custom/DiscussionCustom.java index 5a586d7..c11a445 100644 --- a/src/main/java/com/yaoyuan/jiscuss/entity/custom/DiscussionCustom.java +++ b/src/main/java/com/yaoyuan/jiscuss/entity/custom/DiscussionCustom.java @@ -8,7 +8,7 @@ import lombok.Setter; import java.util.List; /** - * @author yaoyuan2.chu + * @author Chuyaoyuan * @Title: * @Package com.yaoyuan.jiscuss.entity.custom * @Description: diff --git a/src/main/java/com/yaoyuan/jiscuss/entity/custom/PostCustom.java b/src/main/java/com/yaoyuan/jiscuss/entity/custom/PostCustom.java index 4fac8eb..976c8eb 100644 --- a/src/main/java/com/yaoyuan/jiscuss/entity/custom/PostCustom.java +++ b/src/main/java/com/yaoyuan/jiscuss/entity/custom/PostCustom.java @@ -8,7 +8,7 @@ import lombok.Setter; import java.util.List; /** - * @author yaoyuan2.chu + * @author Chuyaoyuan * @Title: * @Package com.yaoyuan.jiscuss.entity.custom * @Description: diff --git a/src/main/java/com/yaoyuan/jiscuss/entity/custom/TagCustom.java b/src/main/java/com/yaoyuan/jiscuss/entity/custom/TagCustom.java index cc3340f..57cd7d7 100644 --- a/src/main/java/com/yaoyuan/jiscuss/entity/custom/TagCustom.java +++ b/src/main/java/com/yaoyuan/jiscuss/entity/custom/TagCustom.java @@ -7,7 +7,7 @@ import lombok.Setter; import jakarta.persistence.Column; /** - * @author yaoyuan2.chu + * @author Chuyaoyuan * @Title: * @Package com.yaoyuan.jiscuss.entity.custom * @Description: diff --git a/src/main/java/com/yaoyuan/jiscuss/util/DelTagsUtil.java b/src/main/java/com/yaoyuan/jiscuss/util/DelTagsUtil.java index 2bb8f38..046056b 100644 --- a/src/main/java/com/yaoyuan/jiscuss/util/DelTagsUtil.java +++ b/src/main/java/com/yaoyuan/jiscuss/util/DelTagsUtil.java @@ -1,7 +1,7 @@ package com.yaoyuan.jiscuss.util; /** - * @author yaoyuan2.chu + * @author Chuyaoyuan * @Title: 去除内容页代码里的HTML标签 * @Package com.yaoyuan.jiscuss.util * @Description: diff --git a/src/main/resources/db/migration/V2.0.1__reset_seed_passwords.sql b/src/main/resources/db/migration/V3__reset_seed_passwords.sql similarity index 100% rename from src/main/resources/db/migration/V2.0.1__reset_seed_passwords.sql rename to src/main/resources/db/migration/V3__reset_seed_passwords.sql diff --git a/src/main/resources/db/migration/V2.0.2__rbac_admin_console.sql b/src/main/resources/db/migration/V4__rbac_admin_console.sql similarity index 96% rename from src/main/resources/db/migration/V2.0.2__rbac_admin_console.sql rename to src/main/resources/db/migration/V4__rbac_admin_console.sql index fe569d0..89debb6 100644 --- a/src/main/resources/db/migration/V2.0.2__rbac_admin_console.sql +++ b/src/main/resources/db/migration/V4__rbac_admin_console.sql @@ -1,4 +1,4 @@ --- V2.0.2: RBAC foundation + admin upgrade logs (Spring Boot 3 optimization) +-- V4: RBAC foundation + admin upgrade logs (Spring Boot 3 optimization) CREATE TABLE IF NOT EXISTS rbac_role ( diff --git a/src/main/resources/db/migration/V2.0.3__audit_log.sql b/src/main/resources/db/migration/V5__audit_log.sql similarity index 88% rename from src/main/resources/db/migration/V2.0.3__audit_log.sql rename to src/main/resources/db/migration/V5__audit_log.sql index 937b5e0..838b4e6 100644 --- a/src/main/resources/db/migration/V2.0.3__audit_log.sql +++ b/src/main/resources/db/migration/V5__audit_log.sql @@ -1,4 +1,4 @@ --- V2.0.3: Audit log for admin operations (Spring Boot 3 optimization) +-- V5: Audit log for admin operations (Spring Boot 3 optimization) CREATE TABLE IF NOT EXISTS audit_log ( diff --git a/src/main/resources/templates/admin/admin-shell.ftl b/src/main/resources/templates/admin/admin-shell.ftl index 8a46d3d..b27731e 100644 --- a/src/main/resources/templates/admin/admin-shell.ftl +++ b/src/main/resources/templates/admin/admin-shell.ftl @@ -7,7 +7,7 @@ ${title} - <#include "admin-commjs.ftl"/> + <#include "admin/admin-commjs.ftl"/>