Skip to content

Feat/1.4.0 - #94

Merged
Sealt merged 22 commits into
mainfrom
feat/1.4.0
Jun 26, 2026
Merged

Sealt merged 22 commits into
mainfrom
feat/1.4.0

Conversation

@Sealt

@Sealt Sealt commented Mar 6, 2026

Copy link
Copy Markdown
Member

refactor(auth): 双Token校验
refactor(rbac): 统一散落的rbac常量
refactor(api): 模块化main.go
feat(api): 绑定次数、登陆天数查询、重置个人课表
fix: 放宽选课评价文本长度
docs: 更新接口文档
chore: update gitignore

@Sealt
Sealt requested review from AEnjoy and Copilot March 6, 2026 16:06
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

本次拉取请求主要围绕核心服务架构进行了重大重构和功能扩展。认证系统升级为更安全的双Token机制,并引入了全面的会话管理和用户状态控制功能。应用的启动流程被模块化,提升了代码组织性和可维护性。同时,新增了多项用户API,包括课表绑定次数查询、登录天数统计和个人课表重置,以丰富用户体验。此外,还对RBAC常量进行了统一管理,并调整了部分业务逻辑的参数限制,确保了系统的健壮性和灵活性。

Highlights

  • 认证系统重构: 引入双Token(Access Token和Refresh Token)认证机制,增强了安全性并支持会话管理,包括刷新Token、多设备登录/登出、用户踢下线和封禁/解封功能。
  • 应用启动流程模块化: 将main.go中的应用初始化逻辑(如配置加载、数据库连接、Redis缓存、定时任务和异步工作器启动)重构到internal/bootstrap包中,提高了代码的可维护性和可测试性。
  • 新增API功能: 增加了查询用户课表绑定次数、查询用户登录天数以及重置个人课表等API接口。
  • RBAC常量统一管理: 将散落在各处的RBAC(角色权限控制)相关常量统一移动到pkg/constant包中,减少了重复定义并便于集中管理。
  • 放宽选课评价文本长度: 将选课评价内容的文本长度限制从200字符放宽至500字符,以允许用户提供更详细的反馈。
  • API文档更新: 更新了API文档以反映新增的番茄钟、词典相关接口以及新的数据模型。
Changelog
  • .gitignore
    • 新增了.claude, CLAUDE.md, temp/等文件和目录到忽略列表。
  • cmd/apiserver/main.go
    • 将所有应用启动和关闭逻辑迁移至internal/bootstrap包,main函数现在仅负责调用bootstrap.New().Run()。
  • docs/api.md
    • 新增了番茄钟(Pomodoro)相关的API接口文档,包括增加次数和获取排名。
    • 新增了词典(Dictionary)相关的API接口文档,包括随机获取一个词。
    • 新增了番茄钟排名项(PomodoroRankingItem)和词典单词(Dictionary)的数据模型说明。
  • internal/bootstrap/app.go
    • 新增了App结构体,封装了应用的配置、数据库、调度器和工作器管理器等核心组件。
    • 新增了New函数,负责按依赖顺序初始化所有组件并返回App实例。
    • 新增了Run方法,启动HTTP服务器并处理优雅关闭逻辑。
    • 新增了Shutdown方法,负责按依赖逆序优雅关闭所有组件。
  • internal/bootstrap/redis.go
    • 新增了InitRedisCache函数,用于初始化Redis客户端和缓存连接。
    • 新增了InitProjectRedisData函数,用于将项目相关的热数据预热到Redis中。
    • 新增了initProjectUserSet和initProjectUsageCount辅助函数,用于初始化Redis中的用户集合和刷题次数。
  • internal/bootstrap/worker.go
    • 新增了InitializeWorkers函数,用于创建WorkerManager并注册所有异步任务Worker。
  • internal/config/config.go
    • 新增了RefreshTokenSecret、AccessTokenTTL和RefreshTokenTTL配置字段,支持双Token认证的配置。
  • internal/dto/request/review.go
    • 将CreateReviewRequest中Content字段的最大长度从200增加到500。
  • internal/dto/request/user-auth.go
    • 新增了RefreshTokenRequest结构体,用于刷新Token的请求。
    • 新增了BanUserRequest结构体,用于管理员封禁用户的请求。
    • 更新了MockWechatLoginRequest中TestUser字段支持的测试用户类型,增加了basic, active, verified, operator, admin。
  • internal/dto/response/user.go
    • 修改了WechatLoginResponse结构体,增加了RefreshToken和AccessTokenExpiresAt字段。
    • 新增了AuthSessionSummary结构体,用于表示认证会话的摘要信息。
    • 新增了UserAuthDetailResponse结构体,用于展示用户认证详情,包括封禁信息和设备会话列表。
  • internal/handlers/auth_handler.go
    • 新增了RefreshToken处理器,用于处理Token刷新请求。
    • 新增了Logout处理器,用于处理当前会话登出请求。
    • 新增了LogoutAll处理器,用于处理所有设备登出请求。
    • 新增了KickUser处理器,用于管理员踢用户下线。
    • 新增了BanUser处理器,用于管理员封禁用户。
    • 新增了UnbanUser处理器,用于管理员解封用户。
    • 新增了GetUserDetail处理器,用于管理员获取用户认证详情。
    • 更新了WechatLogin和MockWechatLogin处理器,使其接受userAgent参数并使用新的Token生成逻辑。
    • 移除了Swagger注释,可能已通过其他方式生成或不再需要。
  • internal/handlers/coursetable_handler.go
    • 新增了GetBindCount处理器,用于获取用户课表绑定次数。
    • 新增了ResetSchedule处理器,用于重置用户个人课表。
  • internal/handlers/helper/helper.go
    • 新增了GetAuthSessionID函数,用于从Gin Context中获取认证会话ID。
  • internal/handlers/user_activity_handler.go
    • 新增了UserActivityHandler结构体及其New函数。
    • 新增了GetLoginDays处理器,用于获取用户在过去100天内的登录天数。
  • internal/middleware/middleware.go
    • 重构了AuthMiddleware,实现了双Token认证逻辑,包括Access Token和Refresh Token的验证、会话管理、用户封禁状态检查和会话撤销机制。
    • 优化了Logger中间件,使其日志输出更精简,并增加了对请求ID和用户ID的上下文丰富。
    • 更新了RequestID中间件,确保请求ID被设置到响应头和请求上下文中。
  • internal/models/rbac.go
    • 移除了RoleTag和PermissionTag的常量定义,这些常量已统一到pkg/constant包中。
  • internal/pkg/cache/doc.go
    • 在Cache接口中新增了SMembers、SRem、ZRangeByScore和ZRem方法,以支持更丰富的Redis集合和有序集合操作。
  • internal/pkg/cache/redis.go
    • 在redisCache结构体中实现了SMembers、SRem、ZRangeByScore和ZRem方法。
    • 新增了formatZScoreBound辅助函数,用于格式化有序集合的score边界。
  • internal/router/router.go
    • 更新了NewRouter函数,将AuthMiddleware的初始化参数调整为接收cache.Cache实例。
    • 新增了userActivityService和userActivityHandler的初始化和注册。
    • 新增了/api/v0/auth/refresh路由,用于Token刷新。
    • 新增了/api/v0/auth/logout和/api/v0/auth/logout-all路由,用于用户登出操作。
    • 新增了/api/v0/user/login-days路由,用于查询用户登录天数。
    • 新增了/api/v0/coursetable/bind-count和/api/v0/coursetable/schedule路由,用于课表相关功能。
    • 新增了管理员用户管理路由,包括/admin/users/:id、/admin/users/:id/kick、/admin/users/:id/ban和/admin/users/:id/unban。
    • 将所有权限常量引用更新为pkg/constant包中的定义。
  • internal/services/auth_service.go
    • 对认证服务进行了大规模重构,实现了双Token认证(Access Token和Refresh Token)的生成、验证和管理。
    • 新增了会话存储、检索、撤销和清理的逻辑,支持多设备登录和会话失效。
    • 新增了用户封禁(临时/永久)和踢下线功能,以及对应的状态管理和查询。
    • 更新了WechatLogin和MockWechatLogin方法,使其使用新的双Token生成和会话管理流程。
    • 新增了RefreshToken、Logout、LogoutAll、KickUser、BanUser、UnbanUser和GetUserAuthDetail等方法。
    • 优化了错误日志记录,增加了更多上下文信息。
  • internal/services/contribution_service.go
    • 更新了GetContributions和GetContributionByID方法中RBAC常量引用,使用pkg/constant中的定义。
  • internal/services/coursetable_service.go
    • 新增了GetUserBindCount方法,用于获取用户课表绑定次数。
    • 新增了ResetUserSchedule方法,用于重置用户个人课表数据。
    • 更新了UpdateUserClass方法中RBAC常量引用,使用pkg/constant中的定义。
  • internal/services/notification_service.go
    • 更新了UpdateNotification和generateApprovalSummary方法中RBAC常量引用,使用pkg/constant中的定义。
  • internal/services/rbac_service.go
    • 更新了SeedDefaults和ListRolesWithUsers方法中RBAC常量引用,使用pkg/constant中的定义。
    • 移除了models.RoleTagAdmin等常量在GetUserPermissionSnapshot中的直接引用,统一使用constant包。
  • internal/services/user_activity_service.go
    • 新增了GetUserLoginDays方法,用于查询用户在指定天数内的登录天数。
    • 更新了UpdateActiveUserRoles方法中RBAC常量引用,使用pkg/constant中的定义。
  • pkg/constant/auth.go
    • 新增了auth.go文件,定义了所有认证相关的常量,包括Token类型、封禁类型、客户端/设备类型、Gin Context键、Redis键格式以及默认的Token TTL。
  • pkg/utils/auth.go
    • 重构了JWT生成逻辑,引入TokenClaims结构体,支持Access Token和Refresh Token的独立生成和解析。
    • 新增了ParseToken函数,用于解析Token并返回TokenClaims。
    • 新增了NewSessionID函数,用于生成新的会话ID。
    • 新增了ParseDeviceInfo函数,用于从User-Agent字符串解析设备和客户端信息。
    • 新增了AuthSession和AuthBlockInfo结构体,用于会话和封禁信息的管理。
  • pkg/utils/rbac.go
    • 更新了IsAdmin函数中RBAC常量引用,使用pkg/constant中的定义。
Activity
  • 此拉取请求包含了对认证系统和应用启动流程的重大重构,并引入了多项新功能和管理接口。目前没有外部评审活动或评论的记录。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 主要围绕鉴权体系升级为“双 Token(access/refresh)+ Redis 会话管理”,同时统一 RBAC 常量引用、拆分启动流程,并补充若干用户侧/课表侧新接口。

Changes:

  • 鉴权:新增 access/refresh token、刷新/登出/踢下线/封禁等能力,并在中间件侧接入 Redis 会话校验
  • RBAC:将散落的角色/权限常量统一迁移到 pkg/constant 并全局替换引用
  • API:新增登录天数查询、课表绑定次数查询、重置个人课表;点评内容长度上限放宽到 500;启动流程模块化

Reviewed changes

Copilot reviewed 27 out of 28 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
pkg/utils/rbac.go 管理员角色判断改为使用统一常量
pkg/utils/auth.go 引入 TokenClaims/会话结构、access/refresh token 生成与解析、设备信息解析
pkg/constant/auth.go 新增鉴权相关常量(token 类型、Redis key、TTL 等)
internal/services/user_activity_service.go 新增查询过去 N 天游登录天数方法;RBAC tag 使用统一常量
internal/services/rbac_service.go SeedDefaults/快照判断等改为使用统一常量
internal/services/notification_service.go 运营/管理员角色判断改为使用统一常量
internal/services/coursetable_service.go 新增绑定次数查询与重置个人课表服务方法;权限常量统一
internal/services/contribution_service.go 角色判断改为使用统一常量
internal/services/auth_service.go 双 Token + Redis 会话/撤销/封禁体系落地,新增刷新/登出/封禁等服务能力
internal/router/router.go 注入 cache 到 AuthMiddleware/AuthService;新增 refresh/logout/login-days/bind-count/reset-schedule/admin user auth 管理路由
internal/pkg/cache/redis.go 增补 Set/SortedSet 的 Redis 操作封装(SMembers/SRem/ZRangeByScore/ZRem 等)
internal/pkg/cache/doc.go Cache 接口补齐集合/有序集合新方法定义
internal/models/rbac.go 移除 models 内 RBAC 常量别名,统一由 constant 提供
internal/middleware/middleware.go AuthMiddleware 改为解析 TokenClaims 并基于 Redis 做 blocked/revoked 校验;RequestID 回写响应头并 enrich context
internal/handlers/user_activity_handler.go 新增登录天数查询 handler
internal/handlers/helper/helper.go 新增读取会话 SID 的 helper
internal/handlers/coursetable_handler.go 新增绑定次数查询与重置个人课表 handler
internal/handlers/auth_handler.go 登录/Mock 登录改为传入 UA;新增 refresh/logout/logout-all 与管理员踢下线/封禁/解封/详情接口
internal/dto/response/user.go 登录响应改为返回 refresh token 与 access 过期时间;新增会话/封禁详情响应结构
internal/dto/request/user-auth.go 新增 refresh/ban 请求 DTO;更新 mock 用户类型说明
internal/dto/request/review.go 点评内容最大长度从 200 放宽到 500
internal/config/config.go 新增 refresh secret 与 access/refresh TTL 配置项
internal/bootstrap/worker.go 抽离 worker 初始化逻辑
internal/bootstrap/redis.go 抽离 Redis 初始化与项目热数据预热逻辑
internal/bootstrap/app.go 新增 App 生命周期封装(init/run/shutdown)
docs/api.md 补充 pomodoro/dictionary 文档片段
cmd/apiserver/main.go main.go 简化为 bootstrap 驱动启动
.gitignore 忽略 Claude 相关文件与临时目录

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}

const pastDays = 100
days, err := h.userActivityService.GetUserLoginDays(c, userID, pastDays)

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里调用 service 时传入的是 c(*gin.Context)。项目里多数 handler 都传 c.Request.Context(),并且鉴权中间件会通过 c.Request = c.Request.WithContext(...) 注入结构化字段;继续传 c 可能导致这些 context 信息在下游(DB/日志)不可见或不一致。建议改为 c.Request.Context() 以保持一致性。

Suggested change
days, err := h.userActivityService.GetUserLoginDays(c, userID, pastDays)
days, err := h.userActivityService.GetUserLoginDays(c.Request.Context(), userID, pastDays)

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

其实都一样。。。 c 实现了 context.Context 接口,它也是从c.Request.Context() 返回的context

Comment on lines +192 to +226
count, err := h.courseTableService.GetUserBindCount(c, userID)
if err != nil {
helper.ErrorResponse(c, http.StatusBadRequest, err.Error())
return
}

helper.SuccessResponse(c, gin.H{"bind_count": count})
}

// ResetSchedule 重置用户个人课表
// @Summary 重置个人课表
// @Description 删除当前用户在指定学期的个人编辑课表数据,恢复为班级默认课表
// @Tags 课程表
// @Accept json
// @Produce json
// @Param semester query string true "学期"
// @Success 200 {object} helper.Response
// @Failure 400 {object} helper.Response
// @Failure 401 {object} helper.Response
// @Router /api/v0/coursetable/schedule [delete]
func (h *CourseTableHandler) ResetSchedule(c *gin.Context) {
userID := helper.GetUserID(c)
if userID == 0 {
helper.ErrorResponse(c, http.StatusUnauthorized, "未获取到用户信息")
return
}

semester := c.Query("semester")
if semester == "" {
helper.ValidateResponse(c, "参数验证失败: semester 不能为空")
return
}

if err := h.courseTableService.ResetUserSchedule(c, userID, semester); err != nil {
helper.ErrorResponse(c, http.StatusBadRequest, err.Error())

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetBindCount/ResetSchedule 这里调用 service 传入的是 c(*gin.Context)。当前代码库多数 handler 使用 c.Request.Context(),而且鉴权中间件会 enrich 到 c.Request.Context();建议新接口这里也改为 c.Request.Context(),避免上下游 context 传递不一致。

Copilot uses AI. Check for mistakes.
Comment thread docs/api.md Outdated
Comment on lines +918 to +944
### 番茄钟 (Pomodoro)

#### 增加番茄钟次数 (需认证)
```http
POST /api/v0/pomodoro/increment
Authorization: Bearer <JWT_TOKEN>

Result: { "message": "番茄钟次数已增加" }
```

#### 获取番茄钟排名 (需认证)
```http
GET /api/v0/pomodoro/ranking
Authorization: Bearer <JWT_TOKEN>

Result: []response.PomodoroRankingItem
```

### 词典 / 随机取词 (Dictionary)

#### 随机获取一个词 (需认证)
```http
GET /api/v0/dictionary/word
Authorization: Bearer <JWT_TOKEN>

Result: models.Dictionary
```

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

本次 PR 引入了双 Token(refresh_token、access_token_expires_at)、新增 /api/v0/auth/refresh、/api/v0/auth/logout(-all)、以及点评 content 长度放宽到 500,但文档仍沿用旧的“单 token + <=200”描述。建议在 API 文档中同步更新登录响应结构、刷新/登出/封禁相关接口,以及点评字段长度说明,避免客户端按旧协议实现。

Copilot uses AI. Check for mistakes.
Comment thread pkg/utils/auth.go
Comment on lines +78 to +80
token, err := jwt.ParseWithClaims(tokenString, &TokenClaims{}, func(token *jwt.Token) (any, error) {
return []byte(secret), nil
})

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ParseToken parses JWTs without restricting/validating the signing algorithm (the keyfunc always returns the secret). This reintroduces an alg-confusion class of issues compared to the previous middleware check. Consider enforcing allowed methods (e.g., HS256 only) via jwt.WithValidMethods and/or checking token.Method inside the keyfunc before returning the key.

Suggested change
token, err := jwt.ParseWithClaims(tokenString, &TokenClaims{}, func(token *jwt.Token) (any, error) {
return []byte(secret), nil
})
token, err := jwt.ParseWithClaims(
tokenString,
&TokenClaims{},
func(token *jwt.Token) (any, error) {
// Enforce expected signing method (HS256) to prevent alg confusion
if token.Method != jwt.SigningMethodHS256 {
return nil, jwt.ErrSignatureInvalid
}
return []byte(secret), nil
},
jwt.WithValidMethods([]string{jwt.SigningMethodHS256.Alg()}),
)

Copilot uses AI. Check for mistakes.
Comment on lines +18 to +20
// InitRedisCache 初始化Redis客户端并建立缓存连接。
// 当Redis不可用时会优雅降级,相关功能(幂等性等)将被禁用。
func InitRedisCache(cfg *config.Config) {

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InitRedisCache 注释写的是“Redis 不可用时会优雅降级(幂等性等功能禁用)”,但当前 PR 的鉴权流程(登录/刷新/鉴权中间件)已经强依赖 Redis:Redis 不可用会导致无法登录、所有需认证接口直接 503。建议要么更新这里的降级说明并在启动时将 Redis 视为必需依赖,要么实现真正的降级策略(例如只在双 Token 模式下要求 Redis)。

Copilot uses AI. Check for mistakes.
{PermissionTag: constant.PermissionMaterialCategoryGet, Name: "资料分类查看", Description: ""},
{PermissionTag: constant.PermissionQuestion, Name: "刷题访问", Description: ""},
{PermissionTag: constant.PermissionPomodoro, Name: "番茄钟", Description: ""},
{PermissionTag: constant.PermissionDictionary, Name: "每日一词", Description: ""},

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SeedDefaults 当前创建/绑定的权限列表不包含路由里实际使用的一些 permission tag(例如 statistic.get、chat.study、notification.get.admin、s3.manage 等)。在 InitRbac=true 的新环境中,这会导致这些接口永远无法通过 RequirePermission 校验。建议补齐缺失的 permissionSeeds + roleBindings,或明确说明这些权限不由 SeedDefaults 管理。

Suggested change
{PermissionTag: constant.PermissionDictionary, Name: "每日一词", Description: ""},
{PermissionTag: constant.PermissionDictionary, Name: "每日一词", Description: ""},
{PermissionTag: constant.PermissionStatisticGet, Name: "统计查看", Description: ""},
{PermissionTag: constant.PermissionChatStudy, Name: "学习聊天", Description: ""},
{PermissionTag: constant.PermissionNotificationGetAdmin, Name: "通知后台管理查看", Description: ""},
{PermissionTag: constant.PermissionS3Manage, Name: "对象存储管理", Description: ""},

Copilot uses AI. Check for mistakes.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a significant refactoring of the application's bootstrap and authentication mechanisms, along with new features and administrative capabilities. The core application initialization and shutdown logic has been extracted from cmd/apiserver/main.go into a new internal/bootstrap package, improving modularity. The authentication system has been upgraded to support refresh tokens, session management (logout, logout all, kick user), and user banning/unbanning, leveraging Redis for session and blocklist caching. This involved adding new configuration fields for token TTLs, updating DTOs for login responses and user details, and extensively modifying the AuthMiddleware to incorporate session validation and revocation checks. New API endpoints and documentation were added for Pomodoro, Dictionary, user login activity (login days), and course table management (get bind count, reset schedule). The RBAC system was updated to use constants from pkg/constant instead of internal/models, and the Cache interface and its Redis implementation were extended with new set and sorted set operations to support the enhanced authentication features. Review comments highlight concerns about the KickUser operation's temporary ban duration being too long (2 hours, suggested 5-10 minutes) and the BanUser operation's permanent ban TTL being too short (2 hours, suggested refreshTokenTTL), both potentially leading to premature cache expiration of critical user state. Additionally, an existing GenerateJWT utility function was noted for having a hardcoded 7-day access token TTL, which is inconsistent with the new 2-hour default and poses a security risk if still in use.

}

blockType := constant.AuthBlockTypePermanent
blockTTL := s.accessTokenTTL()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

永久封禁的 Redis 缓存时间过短。对于永久封禁(durationSeconds <= 0),封禁信息的缓存 TTL (blockTTL) 被设置为 accessTokenTTL(默认为2小时)。这可能导致封禁原因等信息在短时间内从 Redis 中丢失。

建议为永久封禁设置一个更长的 TTL,例如 refreshTokenTTL(默认为30天),以确保封禁信息在缓存中能持久存在。

Suggested change
blockTTL := s.accessTokenTTL()
blockTTL := s.refreshTokenTTL()

OperatorUserID: operatorUserID,
ExpiresAt: expiresAt.Unix(),
}
if err := s.setBlockInfo(ctx, targetUserID, blockInfo, s.accessTokenTTL()); err != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

“踢出用户”操作附带的临时封禁时间过长。
KickUser 操作在撤销用户所有会话后,会设置一个 accessTokenTTL(默认为2小时)的临时封禁。通常“踢出”操作意味着立即终止会话,附带的短期封禁是为了防止用户立即重新登录。2小时的封禁时长对于“踢出”操作来说可能过长,更像是一个短期的手动封禁。

建议将此处的封禁时长缩短,例如5-10分钟,或者将其设为可配置项,以更准确地反映“踢出”操作的意图。

Comment thread pkg/utils/auth.go
Comment on lines +124 to 127
func GenerateJWT(userID uint, secret string, role int8) (string, error) {
token, _, err := GenerateAccessToken(userID, secret, role, 7*24*time.Hour, NewSessionID())
return token, err
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

此 GenerateJWT 函数的 TTL 与新的认证策略不一致。
这个函数作为 GenerateAccessToken 的封装,硬编码了7天的超长 Access Token 有效期,而系统其他部分默认的 Access Token 有效期是2小时。

如果此函数仍在项目中使用,它会产生一个生命周期异常长的 Access Token,可能带来安全风险。如果它只是为了向后兼容,建议添加明确的注释说明其用途和风险。如果已经不再使用,建议直接移除,以避免混淆和潜在的误用。

Sealt and others added 17 commits March 7, 2026 18:24
- 新增 OpenAPI 生成脚本与 make openapi 命令,产出 docs/openapi/openapi.json
- 重组并补充 API 文档,新增错误码说明与 OpenAPI 使用说明
- 补充番茄钟次数查询接口、词典表迁移及 RBAC 权限种子
- 拆分幂等与存储相关常量,统一预签名 URL 默认过期时间
- 优化评价创建与课表绑定限制的错误提示
fix: 修复DELETEAT导致获取用户RoleTags重复问题
fix: 刷题在线人数逻辑
test: E2E 问题修复
@Sealt
Sealt merged commit dbf2ad4 into main Jun 26, 2026
4 of 5 checks passed
@Sealt
Sealt deleted the feat/1.4.0 branch June 26, 2026 13:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants