优化结构

This commit is contained in:
Yvan
2026-08-28 15:37:40 +08:00
parent a4ed3a02df
commit 9b1daaf3f6
17 changed files with 100 additions and 64 deletions
+5
View File
@@ -10,6 +10,7 @@ import (
"net/http"
"path/filepath"
"strings"
"sync"
"time"
"github.com/google/uuid"
@@ -46,6 +47,8 @@ type MediaUsecase struct {
settings RuntimeSettings
}
var mediaDeleteMu sync.Mutex
var ErrMediaTooLarge = errors.New("文件超过大小上限")
func NewMediaUsecase(repo MediaRepo, files FileStorage, settings RuntimeSettings) *MediaUsecase {
@@ -119,6 +122,8 @@ func (uc *MediaUsecase) Upload(ctx context.Context, userID uint, name, suppliedM
}
func (uc *MediaUsecase) Delete(ctx context.Context, id uint) error {
mediaDeleteMu.Lock()
defer mediaDeleteMu.Unlock()
media, err := uc.FindMedia(ctx, id)
if err != nil {
return err
@@ -156,6 +156,7 @@ func (r *integrationConfigRepo) SaveIntegrationConfig(ctx context.Context, confi
err := db.Where("kind = ? AND provider = ?", config.Kind, config.Provider).First(&row).Error
values := integrationObject(config.Values)
if errors.Is(err, gorm.ErrRecordNotFound) {
mergeIntegrationSecrets(config.Kind, config.Provider, values, map[string]any{})
if config.Enabled {
if err = integrationbiz.ValidateIntegrationConfig(config.Kind, config.Provider, values); err != nil {
return err
@@ -233,6 +234,13 @@ func maskIntegrationSecrets(kind, provider string, values map[string]any) {
if nested, ok := value.(map[string]any); ok {
maskIntegrationSecrets(kind, provider, nested)
}
if nested, ok := value.([]any); ok {
for _, item := range nested {
if child, ok := item.(map[string]any); ok {
maskIntegrationSecrets(kind, provider, child)
}
}
}
}
}
+4 -4
View File
@@ -116,18 +116,18 @@ func (r *mediaRepo) ListChunks(ctx context.Context, uploadID uint) ([]*system.Up
return out, nil
}
func (r *mediaRepo) DeleteChunks(ctx context.Context, uploadID uint) error {
return r.data.DB().WithContext(ctx).Where("upload_id = ?", uploadID).Delete(&uploadChunkPO{}).Error
return r.data.DB().WithContext(ctx).Unscoped().Where("upload_id = ?", uploadID).Delete(&uploadChunkPO{}).Error
}
func (r *mediaRepo) StaleUploadSessionIDs(ctx context.Context, before time.Time) ([]uint, error) {
var ids []uint
err := r.data.DB().WithContext(ctx).Model(&uploadSessionPO{}).Where("status IN ? AND updated_at < ?", []string{"uploading", "failed", "merging"}, before).Pluck("id", &ids).Error
err := r.data.DB().WithContext(ctx).Model(&uploadSessionPO{}).Where("(status IN ? AND updated_at < ?) OR (status = ? AND updated_at < ?)", []string{"uploading", "failed"}, before, "merging", before.Add(-time.Hour)).Pluck("id", &ids).Error
return ids, err
}
func (r *mediaRepo) DeleteUploadData(ctx context.Context, uploadID uint) error {
return r.data.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
if err := tx.Where("upload_id = ?", uploadID).Delete(&uploadChunkPO{}).Error; err != nil {
if err := tx.Unscoped().Where("upload_id = ?", uploadID).Delete(&uploadChunkPO{}).Error; err != nil {
return err
}
return tx.Delete(&uploadSessionPO{}, uploadID).Error
return tx.Unscoped().Delete(&uploadSessionPO{}, uploadID).Error
})
}
+1 -1
View File
@@ -59,7 +59,7 @@ func (t *ConnectivityTester) restoreMaskedSecrets(kind, provider string, values
}
masked := make(map[string]struct{})
for _, field := range definition.Fields {
if field.Secret {
if field.Secret || integrationbiz.IsIntegrationSecretKey(field.Key) {
masked[field.Key] = struct{}{}
}
}
+1 -1
View File
@@ -115,7 +115,7 @@ var routes = map[string]routeValue{
"GET /sysOperationRecord/findSysOperationRecord": {group: "操作记录", description: "根据ID获取操作记录"},
"GET /sysOperationRecord/getSysOperationRecordList": {group: "操作记录", description: "获取操作记录列表"},
"GET /sysParams/findSysParams": {group: "参数管理", description: "根据ID获取参数"},
"GET /sysParams/getSysParam": {group: "参数管理", description: "获取参数列表"},
"GET /sysParams/getSysParam": {group: "参数管理", description: "按键获取参数"},
"GET /sysParams/getSysParamsList": {group: "参数管理", description: "获取参数列表"},
"GET /sysVersion/downloadVersionJson": {group: "版本控制", description: "下载版本json"},
"GET /sysVersion/findSysVersion": {group: "版本控制", description: "获取单一版本"},
+1 -1
View File
@@ -65,7 +65,7 @@ func NewGinEngineWithRuntime(runtime *config.Store, access *systemservice.Access
if snapshot != nil && snapshot.Admin != nil && snapshot.Admin.App != nil {
env = strings.ToLower(strings.TrimSpace(snapshot.Admin.App.Env))
}
if env != "production" && env != "prod" && env != "live" && env != "staging" {
if env == "" || env == "development" || env == "dev" || env == "test" || env == "local" {
registerSwagger(engine, prefix, version, logger)
}
staticfiles.Register(engine, runtime)
+5
View File
@@ -53,6 +53,11 @@ func sanitizeFailureMessage(message string) string {
if strings.Contains(message, "失败:") {
return strings.TrimSpace(strings.SplitN(message, "失败:", 2)[0]) + "失败"
}
for _, marker := range []string{"参数", "不能为空", "无效", "不存在", "权限", "未登录", "验证码", "密码", "重复", "不支持", "超出", "分片", "上传", "文件", "名称", "令牌", "token"} {
if strings.Contains(message, marker) {
return message
}
}
return message
}
+2 -1
View File
@@ -97,7 +97,6 @@ func AccessLog(runtime *config.Store, logger *slog.Logger, version string) gin.H
requestText = redactJSON(requestBody, c.GetHeader("Content-Type"), logLimit)
}
c.Set(ctxReqBodyKey, requestText)
c.Set(ctxRespTruncatedKey, writer.Truncated())
if paymentCallback {
// Callback acknowledgements and provider payloads must not flow into
// the generic response/error audit pipeline.
@@ -108,6 +107,7 @@ func AccessLog(runtime *config.Store, logger *slog.Logger, version string) gin.H
if !requestReadFailed {
c.Next()
}
c.Set(ctxRespTruncatedKey, writer.Truncated())
if logger == nil {
return
}
@@ -118,6 +118,7 @@ func AccessLog(runtime *config.Store, logger *slog.Logger, version string) gin.H
if paymentCallback {
responseText = "[支付回调响应已省略]"
}
c.Set(ctxRespTextKey, responseText)
userID, authorityID := uint(0), uint(0)
if claims := Claims(c); claims != nil {
userID, authorityID = claims.ID, claims.AuthorityID
+5 -4
View File
@@ -73,7 +73,9 @@ func OperationAudit(runtime *config.Store, recorder *systemservice.AuditRecorder
requestID, _ := c.Get("request_id")
status := c.Writer.Status()
responseBody := ""
if value, ok := c.Get(ctxRespBufferKey); ok {
if value, ok := c.Get(ctxRespTextKey); ok {
responseBody = stringValue(value)
} else if value, ok := c.Get(ctxRespBufferKey); ok {
if body, bok := value.(*bytes.Buffer); bok {
responseBody = redactJSON(body.Bytes(), c.Writer.Header().Get("Content-Type"), maxBytes)
}
@@ -91,10 +93,9 @@ func OperationAudit(runtime *config.Store, recorder *systemservice.AuditRecorder
// second time.
operationBody = stringValue(value)
capturedBody = true
} else {
operationBody = operationRequestBody(requestBody, c.GetHeader("Content-Type"), maxBytes)
}
} else {
}
if !capturedBody {
operationBody = operationRequestBody(requestBody, c.GetHeader("Content-Type"), maxBytes)
}
if !capturedBody && routecatalog.BodyPolicyFor(c.Request.Method, path) == routecatalog.BodyPolicyPaymentConfig {
+3
View File
@@ -15,6 +15,7 @@ const (
ctxReqBodyKey = "kra_req_body"
ctxRespBufferKey = "kra_resp_buffer"
ctxRespTruncatedKey = "kra_resp_truncated"
ctxRespTextKey = "kra_resp_text"
)
type captureWriter struct {
@@ -37,6 +38,8 @@ func (w *captureWriter) Write(data []byte) (int, error) {
} else {
_, _ = w.body.Write(data)
}
} else if len(data) > 0 {
w.truncated = true
}
return w.ResponseWriter.Write(data)
}
+3 -1
View File
@@ -22,7 +22,9 @@ func ErrorAudit(logger *slog.Logger) gin.HandlerFunc {
// already recorded by the handler with the underlying filesystem error;
// emitting again from the response envelope would duplicate both the
// classified error file and the sys_error row.
if auditPersistFailed != true && (strings.Contains(c.Request.URL.Path, "/sysError/") || strings.Contains(c.Request.URL.Path, "/logViewer/") || c.Writer.Status() >= 300 && c.Writer.Status() < 500) {
isSelfAudit := strings.Contains(c.Request.URL.Path, "/sysError/") || strings.Contains(c.Request.URL.Path, "/logViewer/")
isClientFailure := c.Writer.Status() >= 300 && c.Writer.Status() < 500
if auditPersistFailed != true && (isSelfAudit || isClientFailure) {
return
}
var response httpx.Response
+1 -1
View File
@@ -45,7 +45,7 @@ func SecurityRateLimit(settings *systemservice.SecurityService) gin.HandlerFunc
return
}
if int(count) > config.LimitCount {
c.JSON(200, gin.H{"code": httpx.CodeError, "msg": "请求太过频繁,请稍后再试"})
c.JSON(http.StatusOK, gin.H{"code": httpx.CodeError, "msg": "请求太过频繁,请稍后再试"})
c.Abort()
return
}
@@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
integrationbiz "kra/internal/biz/integration"
"kra/internal/config"
"kra/internal/service/dto"
)
@@ -76,7 +77,9 @@ func redactIntegrationJSON(raw json.RawMessage) json.RawMessage {
case map[string]any:
for k, item := range x {
if integrationbiz.IsIntegrationSecretKey(k) {
x[k] = "******"
if text, ok := item.(string); ok && text != "" {
x[k] = config.MaskedSecret
}
} else {
walk(item)
}