mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-10 17:26:38 +08:00
质量优化
This commit is contained in:
@@ -118,7 +118,11 @@ func getSQLiteOverview(gormDB *gorm.DB) (DBOverviewResponse, error) {
|
||||
|
||||
var sizeStr string
|
||||
if fi, err := os.Stat(name); err == nil {
|
||||
sizeStr = formatBytes(uint64(fi.Size()))
|
||||
size := fi.Size()
|
||||
if size < 0 {
|
||||
size = 0
|
||||
}
|
||||
sizeStr = formatBytes(uint64(size))
|
||||
} else {
|
||||
sizeStr = "0 B"
|
||||
}
|
||||
@@ -160,7 +164,11 @@ func getPostgresOverview(gormDB *gorm.DB) (DBOverviewResponse, error) {
|
||||
var sizeStr string
|
||||
var sizeBytes sql.NullInt64
|
||||
if err := gormDB.Raw("SELECT pg_database_size(current_database())").Scan(&sizeBytes).Error; err == nil && sizeBytes.Valid {
|
||||
sizeStr = formatBytes(uint64(sizeBytes.Int64))
|
||||
size := sizeBytes.Int64
|
||||
if size < 0 {
|
||||
size = 0
|
||||
}
|
||||
sizeStr = formatBytes(uint64(size))
|
||||
} else {
|
||||
sizeStr = "0 B"
|
||||
}
|
||||
|
||||
@@ -147,9 +147,12 @@ func GetSystemStatus(c *gin.Context) {
|
||||
numGoroutine := runtime.NumGoroutine()
|
||||
|
||||
var lastGCTime string
|
||||
if m.LastGC > 0 {
|
||||
switch {
|
||||
case m.LastGC > 0 && m.LastGC <= math.MaxInt64:
|
||||
lastGCTime = formatDuration(time.Since(time.Unix(0, int64(m.LastGC))))
|
||||
} else {
|
||||
case m.LastGC > 0:
|
||||
lastGCTime = "未知"
|
||||
default:
|
||||
lastGCTime = "无"
|
||||
}
|
||||
|
||||
@@ -286,7 +289,7 @@ func exportSQLite(c *gin.Context) {
|
||||
path = "./data/wavelet.db"
|
||||
}
|
||||
|
||||
f, err := os.Open(path)
|
||||
f, err := os.Open(path) //nolint:gosec // path is loaded from server startup configuration, not user input
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, util.Err("无法打开数据库文件: "+err.Error()))
|
||||
return
|
||||
@@ -329,7 +332,7 @@ func exportPostgres(c *gin.Context) {
|
||||
dbCfg.Database,
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(c.Request.Context(), pgDumpPath, args...)
|
||||
cmd := exec.CommandContext(c.Request.Context(), pgDumpPath, args...) //nolint:gosec // pgDumpPath is a looked up command path, args are from database configuration
|
||||
if dbCfg.Password != "" {
|
||||
cmd.Env = append(os.Environ(), "PGPASSWORD="+dbCfg.Password)
|
||||
} else {
|
||||
|
||||
@@ -275,7 +275,7 @@ func TestSMTP(c *gin.Context) {
|
||||
<p>If you received this message, your SMTP configuration is correct and mail sending is working properly.</p>
|
||||
<p>Sent from Wavelet.</p>`
|
||||
|
||||
logs, err := mail.SendMailWithLog(cfg, req.To, subject, body)
|
||||
logs, err := mail.SendMailWithLog(c.Request.Context(), cfg, req.To, subject, body)
|
||||
resp := TestSMTPResponse{
|
||||
Success: err == nil,
|
||||
Log: logs,
|
||||
|
||||
@@ -14,6 +14,6 @@ const (
|
||||
deleteUserFailed = "删除用户失败"
|
||||
usernameExists = "用户名已存在"
|
||||
usernameRequired = "用户名不能为空"
|
||||
passwordTooShort = "密码长度不能少于 8 位"
|
||||
passwordTooShort = "密码长度不能少于 8 位" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
|
||||
createUserFailed = "创建用户失败"
|
||||
)
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
package cap
|
||||
|
||||
const (
|
||||
errCapTokenMissing = "验证码验证失败,缺少验证码凭证"
|
||||
errCapTokenInvalidOrExpired = "验证码校验失败或已过期,请重试"
|
||||
errCapTokenMissing = "验证码验证失败,缺少验证码凭证" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
|
||||
errCapTokenInvalidOrExpired = "验证码校验失败或已过期,请重试" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@ package oauth
|
||||
// OAuth 认证相关错误消息
|
||||
const (
|
||||
InvalidState = "非法登录请求"
|
||||
IDTokenVerifyFailed = "ID Token 验证失败"
|
||||
IDTokenVerifyFailed = "ID Token 验证失败" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
|
||||
IDTokenVerifyFailedFormat = "%s: %w"
|
||||
NonceMismatch = "nonce 不匹配,可能存在重放攻击"
|
||||
NoActiveAuthSource = "未配置可用认证源"
|
||||
|
||||
@@ -469,7 +469,7 @@ func handleCallbackBind(ctx context.Context, c *gin.Context, source *model.AuthS
|
||||
c.JSON(http.StatusInternalServerError, util.Err(err.Error()))
|
||||
return
|
||||
}
|
||||
if err := model.BindExternalAccount(&model.ExternalAccount{
|
||||
if err := model.BindExternalAccount(ctx, &model.ExternalAccount{
|
||||
AuthSourceID: source.ID,
|
||||
UserID: user.ID,
|
||||
ExternalID: userInfo.Sub,
|
||||
@@ -488,7 +488,7 @@ func handleCallbackBind(ctx context.Context, c *gin.Context, source *model.AuthS
|
||||
func handleCallbackLogin(ctx context.Context, c *gin.Context, source *model.AuthSource, userInfo *model.OAuthUserInfo) {
|
||||
var user model.User
|
||||
|
||||
account, err := model.FindExternalAccount(source.ID, userInfo.Sub)
|
||||
account, err := model.FindExternalAccount(ctx, source.ID, userInfo.Sub)
|
||||
switch {
|
||||
case err == nil:
|
||||
if err := db.DB(ctx).First(&user, "id = ?", account.UserID).Error; err != nil {
|
||||
@@ -549,7 +549,7 @@ func handleCallbackRegister(ctx context.Context, c *gin.Context, source *model.A
|
||||
c.JSON(http.StatusInternalServerError, util.Err(err.Error()))
|
||||
return model.User{}, false
|
||||
}
|
||||
if err := model.BindExternalAccount(&model.ExternalAccount{
|
||||
if err := model.BindExternalAccount(ctx, &model.ExternalAccount{
|
||||
AuthSourceID: source.ID,
|
||||
UserID: user.ID,
|
||||
ExternalID: userInfo.Sub,
|
||||
|
||||
@@ -60,6 +60,14 @@ func RiskControlMiddleware() gin.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
const maxHTTPStatus = 999
|
||||
status := c.Writer.Status()
|
||||
if status < 0 {
|
||||
status = 0
|
||||
} else if status > maxHTTPStatus {
|
||||
status = maxHTTPStatus
|
||||
}
|
||||
|
||||
logItem := &UserAccessLog{
|
||||
ID: idgen.NextUint64ID(),
|
||||
UserID: userObj.ID, // 直接从 Context 获取已登录用户ID,避免数据库查询
|
||||
@@ -68,7 +76,7 @@ func RiskControlMiddleware() gin.HandlerFunc {
|
||||
IP: c.ClientIP(),
|
||||
UserAgent: c.Request.UserAgent(),
|
||||
Headers: headersStr,
|
||||
Status: int32(c.Writer.Status()),
|
||||
Status: int32(status),
|
||||
Latency: latency,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
@@ -499,7 +499,7 @@ func tryInstantUpload(ctx context.Context, c *gin.Context, currUser *model.User,
|
||||
|
||||
if err := db.DB(ctx).Create(&newUpload).Error; err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(ErrSaveUploadRecordFailed))
|
||||
return true, nil
|
||||
return true, err
|
||||
}
|
||||
|
||||
logger.InfoF(ctx, "文件触发秒传成功! ID: %d, Path: %s", id, existing.FilePath)
|
||||
|
||||
+12
-12
@@ -7,21 +7,21 @@ package user
|
||||
const (
|
||||
errBindParamsFailed = "参数绑定失败"
|
||||
errInvalidParams = "无效的参数"
|
||||
errPasswordLoginDisabled = "管理员关闭了密码登录"
|
||||
errUsernameOrPasswordWrong = "用户名或密码错误"
|
||||
errPasswordLoginDisabled = "管理员关闭了密码登录" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
|
||||
errUsernameOrPasswordWrong = "用户名或密码错误" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
|
||||
errLoginEmailMissing = "该账号未绑定邮箱,请联系管理员绑定邮箱后再登录"
|
||||
errNeedEmailCodePrefix = "need_email_code:"
|
||||
errEmailCodeInvalidOrExpired = "验证码错误或已过期"
|
||||
errPasswordUpgradeFailed = "升级密码安全算法失败,请重试"
|
||||
errPasswordUpgradeFailed = "升级密码安全算法失败,请重试" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
|
||||
errSaveSessionFailed = "无法保存会话信息,请重试"
|
||||
errRegistrationDisabled = "管理员关闭了注册"
|
||||
errPasswordTooShort = "密码长度不能少于 8 位"
|
||||
errPasswordTooShort = "密码长度不能少于 8 位" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
|
||||
errEmailOrCodeRequired = "邮箱或验证码未填写"
|
||||
errNewPasswordTooShort = "新密码长度不能少于 8 位"
|
||||
errNewPasswordTooShort = "新密码长度不能少于 8 位" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
|
||||
errLoginRequired = "请先登录"
|
||||
errUserNotFound = "未找到该用户"
|
||||
errOldPasswordIncorrect = "原密码不正确"
|
||||
errPasswordEncryptFailed = "密码加密失败,请重试"
|
||||
errOldPasswordIncorrect = "原密码不正确" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
|
||||
errPasswordEncryptFailed = "密码加密失败,请重试" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
|
||||
errEmailRequired = "邮箱地址不能为空"
|
||||
errUnsupportedEmailScene = "不支持的验证场景"
|
||||
errEmailAlreadyRegistered = "该邮箱已被注册"
|
||||
@@ -31,11 +31,11 @@ const (
|
||||
errRenderEmailTemplateFailed = "渲染验证邮件模板失败:%w"
|
||||
errGenerateEmailCodeFailed = "生成验证码失败,请重试"
|
||||
errDispatchEmailTaskFailed = "投递验证邮件发送任务失败,请重试"
|
||||
errTokenNameRequired = "令牌名称不能为空"
|
||||
errAccessTokenLimitReached = "已达到访问令牌最大创建数量限制"
|
||||
errGenerateTokenFailed = "生成令牌失败"
|
||||
errInvalidTokenID = "无效的令牌ID"
|
||||
errTokenNotFoundOrForbidden = "令牌不存在或无权操作"
|
||||
errTokenNameRequired = "令牌名称不能为空" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
|
||||
errAccessTokenLimitReached = "已达到访问令牌最大创建数量限制" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
|
||||
errGenerateTokenFailed = "生成令牌失败" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
|
||||
errInvalidTokenID = "无效的令牌ID" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
|
||||
errTokenNotFoundOrForbidden = "令牌不存在或无权操作" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
|
||||
errTaskPayloadRequired = "任务参数不能为空"
|
||||
errInvalidJSONFormat = "无效的 JSON 格式: %w"
|
||||
errEmailTaskFieldsRequired = "to、subject、body 不能为空"
|
||||
|
||||
@@ -28,16 +28,16 @@ type sendEmailCodeRequest struct {
|
||||
Scene string `json:"scene" binding:"required"`
|
||||
}
|
||||
|
||||
func isEmailLoginVerificationEnabled() bool {
|
||||
enabled, err := model.GetBoolByKey(context.Background(), model.ConfigKeyEmailLoginVerificationEnabled)
|
||||
func isEmailLoginVerificationEnabled(ctx context.Context) bool {
|
||||
enabled, err := model.GetBoolByKey(ctx, model.ConfigKeyEmailLoginVerificationEnabled)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return enabled
|
||||
}
|
||||
|
||||
func isEmailRegisterVerificationEnabled() bool {
|
||||
enabled, err := model.GetBoolByKey(context.Background(), model.ConfigKeyEmailRegisterVerificationEnabled)
|
||||
func isEmailRegisterVerificationEnabled(ctx context.Context) bool {
|
||||
enabled, err := model.GetBoolByKey(ctx, model.ConfigKeyEmailRegisterVerificationEnabled)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
@@ -215,7 +215,7 @@ func SendEmailCode(c *gin.Context) {
|
||||
}
|
||||
|
||||
func validateRegisterEmailVerification(ctx context.Context, req *registerRequest) error {
|
||||
if !isEmailRegisterVerificationEnabled() {
|
||||
if !isEmailRegisterVerificationEnabled(ctx) {
|
||||
return nil
|
||||
}
|
||||
if req.Email == "" || req.Code == "" {
|
||||
@@ -228,7 +228,7 @@ func validateRegisterEmailVerification(ctx context.Context, req *registerRequest
|
||||
}
|
||||
|
||||
// completePendingOAuthBinding 完成登录后的 OAuth 待绑定绑定流程
|
||||
func completePendingOAuthBinding(session sessions.Session, user *model.User) {
|
||||
func completePendingOAuthBinding(ctx context.Context, session sessions.Session, user *model.User) {
|
||||
pendingSourceID := session.Get(oauth.PendingOAuthSourceIDKey)
|
||||
pendingExternalID := session.Get(oauth.PendingOAuthExternalIDKey)
|
||||
pendingExternalUsername := session.Get(oauth.PendingOAuthExternalUsernameKey)
|
||||
@@ -243,16 +243,20 @@ func completePendingOAuthBinding(session sessions.Session, user *model.User) {
|
||||
case uint64:
|
||||
sourceID = v
|
||||
case int:
|
||||
sourceID = uint64(v)
|
||||
if v >= 0 {
|
||||
sourceID = uint64(v)
|
||||
}
|
||||
case float64:
|
||||
sourceID = uint64(v)
|
||||
if v >= 0 && v <= 18446744073709551615.0 {
|
||||
sourceID = uint64(v)
|
||||
}
|
||||
}
|
||||
externalID, _ := pendingExternalID.(string)
|
||||
externalUsername, _ := pendingExternalUsername.(string)
|
||||
email, _ := pendingEmail.(string)
|
||||
|
||||
if sourceID != 0 && externalID != "" {
|
||||
_ = model.BindExternalAccount(&model.ExternalAccount{
|
||||
_ = model.BindExternalAccount(ctx, &model.ExternalAccount{
|
||||
AuthSourceID: sourceID,
|
||||
UserID: user.ID,
|
||||
ExternalID: externalID,
|
||||
|
||||
@@ -114,7 +114,7 @@ func Login(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if isEmailLoginVerificationEnabled() {
|
||||
if isEmailLoginVerificationEnabled(ctx) {
|
||||
if emailErr := handleLoginEmailVerification(ctx, c, &req, &user); emailErr != nil {
|
||||
return
|
||||
}
|
||||
@@ -140,7 +140,7 @@ func Login(c *gin.Context) {
|
||||
}
|
||||
|
||||
// 检查是否有未完成 of OAuth/OIDC 绑定
|
||||
completePendingOAuthBinding(session, &user)
|
||||
completePendingOAuthBinding(ctx, session, &user)
|
||||
|
||||
c.JSON(http.StatusOK, util.OK(oauth.BuildBasicUserInfo(&user, needChangePassword)))
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ func (h *SendEmailHandler) Execute(ctx context.Context, payload []byte) (*task.T
|
||||
task.AppendLog(ctx, "连接 SMTP 服务器: %s:%d, 用户名: %s", smtpHost, smtpPort, smtpUsername)
|
||||
|
||||
// 调用 SendMailHTML 执行邮件发送,这里会有 5s 拨号超时和 10s 读写限制
|
||||
err = mail.SendMailHTML(cfg, req.To, req.Subject, req.Body)
|
||||
err = mail.SendMailHTML(ctx, cfg, req.To, req.Subject, req.Body)
|
||||
if err != nil {
|
||||
task.AppendLog(ctx, "邮件发送失败: %v", err)
|
||||
return nil, fmt.Errorf(errSendMailFailed, err)
|
||||
|
||||
Reference in New Issue
Block a user