refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
// Package database 负责数据库连接初始化、自动迁移与种子数据。
|
|
|
|
|
|
//
|
|
|
|
|
|
// 这些引导职责从 model 包拆分而来:model 包应只包含纯数据结构定义与
|
|
|
|
|
|
// GORM 钩子,不应依赖 config 或持有启动逻辑。本包依赖 config + model,
|
|
|
|
|
|
// 方向合法(引导层 → 模型层 / 配置层)。
|
|
|
|
|
|
package database
|
2026-03-09 21:28:58 +08:00
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"fmt"
|
|
|
|
|
|
"log"
|
|
|
|
|
|
"os"
|
|
|
|
|
|
"time"
|
|
|
|
|
|
|
2026-03-17 00:47:17 +08:00
|
|
|
|
"go.uber.org/zap"
|
2026-03-09 21:28:58 +08:00
|
|
|
|
"gorm.io/driver/postgres"
|
|
|
|
|
|
"gorm.io/driver/sqlite"
|
|
|
|
|
|
"gorm.io/gorm"
|
|
|
|
|
|
"gorm.io/gorm/logger"
|
2026-05-15 14:44:40 +08:00
|
|
|
|
"gorm.io/plugin/dbresolver"
|
2026-03-09 21:28:58 +08:00
|
|
|
|
|
2026-04-22 16:01:59 +08:00
|
|
|
|
"with_you/internal/config"
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
"with_you/internal/model"
|
2026-03-09 21:28:58 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
2026-03-13 09:38:18 +08:00
|
|
|
|
// NewDB 创建数据库连接(用于 Wire 依赖注入)
|
|
|
|
|
|
func NewDB(cfg *config.DatabaseConfig) (*gorm.DB, error) {
|
2026-03-09 21:28:58 +08:00
|
|
|
|
var err error
|
|
|
|
|
|
var db *gorm.DB
|
|
|
|
|
|
gormLogger := logger.New(
|
|
|
|
|
|
log.New(os.Stdout, "\r\n", log.LstdFlags),
|
|
|
|
|
|
logger.Config{
|
|
|
|
|
|
SlowThreshold: time.Duration(cfg.SlowThresholdMs) * time.Millisecond,
|
|
|
|
|
|
LogLevel: parseGormLogLevel(cfg.LogLevel),
|
|
|
|
|
|
IgnoreRecordNotFoundError: cfg.IgnoreRecordNotFound,
|
|
|
|
|
|
ParameterizedQueries: cfg.ParameterizedQueries,
|
|
|
|
|
|
Colorful: false,
|
|
|
|
|
|
},
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// 根据数据库类型选择驱动
|
|
|
|
|
|
switch cfg.Type {
|
|
|
|
|
|
case "sqlite":
|
|
|
|
|
|
db, err = gorm.Open(sqlite.Open(cfg.SQLite.Path), &gorm.Config{
|
|
|
|
|
|
Logger: gormLogger,
|
|
|
|
|
|
})
|
|
|
|
|
|
case "postgres", "postgresql":
|
|
|
|
|
|
dsn := cfg.Postgres.DSN()
|
|
|
|
|
|
db, err = gorm.Open(postgres.Open(dsn), &gorm.Config{
|
|
|
|
|
|
Logger: gormLogger,
|
|
|
|
|
|
})
|
|
|
|
|
|
default:
|
|
|
|
|
|
// 默认使用PostgreSQL
|
|
|
|
|
|
dsn := cfg.Postgres.DSN()
|
|
|
|
|
|
db, err = gorm.Open(postgres.Open(dsn), &gorm.Config{
|
|
|
|
|
|
Logger: gormLogger,
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
2026-03-13 09:38:18 +08:00
|
|
|
|
return nil, fmt.Errorf("failed to connect to database: %w", err)
|
2026-03-09 21:28:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 配置连接池(SQLite不支持连接池配置,跳过)
|
|
|
|
|
|
if cfg.Type != "sqlite" {
|
2026-03-13 09:38:18 +08:00
|
|
|
|
sqlDB, err := db.DB()
|
2026-03-09 21:28:58 +08:00
|
|
|
|
if err != nil {
|
2026-03-13 09:38:18 +08:00
|
|
|
|
return nil, fmt.Errorf("failed to get database instance: %w", err)
|
2026-03-09 21:28:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
sqlDB.SetMaxIdleConns(cfg.MaxIdleConns)
|
|
|
|
|
|
sqlDB.SetMaxOpenConns(cfg.MaxOpenConns)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-15 14:44:40 +08:00
|
|
|
|
// 配置读写分离(仅 PostgreSQL 且配置了读副本时生效)
|
|
|
|
|
|
if (cfg.Type == "postgres" || cfg.Type == "postgresql") && cfg.HasReplica() {
|
|
|
|
|
|
allReplicas := cfg.AllReplicas()
|
|
|
|
|
|
replicaDialectors := make([]gorm.Dialector, len(allReplicas))
|
|
|
|
|
|
for i, replica := range allReplicas {
|
|
|
|
|
|
replicaDialectors[i] = postgres.Open(replica.DSN())
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
replicaMaxIdle := cfg.ReplicaMaxIdle
|
|
|
|
|
|
if replicaMaxIdle == 0 {
|
|
|
|
|
|
replicaMaxIdle = cfg.MaxIdleConns
|
|
|
|
|
|
}
|
|
|
|
|
|
replicaMaxOpen := cfg.ReplicaMaxOpen
|
|
|
|
|
|
if replicaMaxOpen == 0 {
|
|
|
|
|
|
replicaMaxOpen = cfg.MaxOpenConns
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
resolver := dbresolver.Register(dbresolver.Config{
|
|
|
|
|
|
Replicas: replicaDialectors,
|
|
|
|
|
|
}).
|
|
|
|
|
|
SetMaxIdleConns(replicaMaxIdle).
|
|
|
|
|
|
SetMaxOpenConns(replicaMaxOpen).
|
|
|
|
|
|
SetConnMaxLifetime(time.Hour)
|
|
|
|
|
|
|
|
|
|
|
|
if err := db.Use(resolver); err != nil {
|
|
|
|
|
|
return nil, fmt.Errorf("failed to register dbresolver plugin: %w", err)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
zap.L().Info("Database read/write splitting configured",
|
|
|
|
|
|
zap.String("type", cfg.Type),
|
|
|
|
|
|
zap.Int("replica_count", len(allReplicas)),
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-09 21:28:58 +08:00
|
|
|
|
// 自动迁移
|
2026-03-13 09:38:18 +08:00
|
|
|
|
if err := autoMigrate(db); err != nil {
|
|
|
|
|
|
return nil, fmt.Errorf("failed to auto migrate: %w", err)
|
2026-03-09 21:28:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-17 00:47:17 +08:00
|
|
|
|
zap.L().Info("Database connected and migrated successfully",
|
|
|
|
|
|
zap.String("type", cfg.Type),
|
|
|
|
|
|
)
|
2026-03-13 09:38:18 +08:00
|
|
|
|
return db, nil
|
2026-03-09 21:28:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func parseGormLogLevel(level string) logger.LogLevel {
|
|
|
|
|
|
switch level {
|
|
|
|
|
|
case "silent":
|
|
|
|
|
|
return logger.Silent
|
|
|
|
|
|
case "error":
|
|
|
|
|
|
return logger.Error
|
|
|
|
|
|
case "warn":
|
|
|
|
|
|
return logger.Warn
|
|
|
|
|
|
case "info":
|
|
|
|
|
|
return logger.Info
|
|
|
|
|
|
default:
|
|
|
|
|
|
return logger.Warn
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// autoMigrate 自动迁移数据库表
|
|
|
|
|
|
func autoMigrate(db *gorm.DB) error {
|
|
|
|
|
|
err := db.AutoMigrate(
|
|
|
|
|
|
// 用户相关
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.User{},
|
2026-03-09 21:28:58 +08:00
|
|
|
|
|
|
|
|
|
|
// 帖子相关
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.Post{},
|
|
|
|
|
|
&model.PostImage{},
|
|
|
|
|
|
&model.Channel{},
|
2026-03-09 21:28:58 +08:00
|
|
|
|
|
|
|
|
|
|
// 评论相关
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.Comment{},
|
|
|
|
|
|
&model.CommentLike{},
|
2026-03-09 21:28:58 +08:00
|
|
|
|
|
|
|
|
|
|
// 消息相关(使用雪花算法ID和seq机制)
|
|
|
|
|
|
// 已读位置存储在 ConversationParticipant.LastReadSeq 中
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.Conversation{},
|
|
|
|
|
|
&model.ConversationParticipant{},
|
|
|
|
|
|
&model.Message{},
|
2026-03-09 21:28:58 +08:00
|
|
|
|
|
|
|
|
|
|
// 系统通知(独立表,每个用户只能看到自己的通知)
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.SystemNotification{},
|
2026-03-09 21:28:58 +08:00
|
|
|
|
|
|
|
|
|
|
// 通知
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.Notification{},
|
2026-03-09 21:28:58 +08:00
|
|
|
|
|
|
|
|
|
|
// 推送中心相关
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.PushRecord{}, // 推送记录
|
|
|
|
|
|
&model.DeviceToken{}, // 设备Token
|
2026-03-09 21:28:58 +08:00
|
|
|
|
|
|
|
|
|
|
// 社交
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.Follow{},
|
|
|
|
|
|
&model.UserBlock{},
|
|
|
|
|
|
&model.PostLike{},
|
|
|
|
|
|
&model.Favorite{},
|
2026-03-09 21:28:58 +08:00
|
|
|
|
|
|
|
|
|
|
// 投票
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.VoteOption{},
|
|
|
|
|
|
&model.UserVote{},
|
2026-03-09 21:28:58 +08:00
|
|
|
|
|
|
|
|
|
|
// 敏感词和审核
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.SensitiveWord{},
|
|
|
|
|
|
// &model.AuditLog{}, // TODO: define AuditLog model
|
2026-03-09 21:28:58 +08:00
|
|
|
|
|
2026-03-29 20:18:36 +08:00
|
|
|
|
// 举报
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.Report{},
|
2026-03-29 20:18:36 +08:00
|
|
|
|
|
2026-03-19 19:43:37 +08:00
|
|
|
|
// 日志相关
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.OperationLog{}, // 操作日志
|
|
|
|
|
|
&model.LoginLog{}, // 登录日志
|
|
|
|
|
|
&model.DataChangeLog{}, // 数据变更日志
|
2026-03-19 19:43:37 +08:00
|
|
|
|
|
2026-03-09 21:28:58 +08:00
|
|
|
|
// 群组相关
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.Group{},
|
|
|
|
|
|
&model.GroupMember{},
|
|
|
|
|
|
&model.GroupAnnouncement{},
|
|
|
|
|
|
&model.GroupJoinRequest{},
|
2026-03-09 21:28:58 +08:00
|
|
|
|
|
|
|
|
|
|
// 自定义表情
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.UserSticker{},
|
2026-03-12 08:38:14 +08:00
|
|
|
|
|
|
|
|
|
|
// 课表
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.ScheduleCourse{},
|
2026-03-14 02:09:38 +08:00
|
|
|
|
|
2026-05-12 01:28:18 +08:00
|
|
|
|
// 成绩与考试
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.Grade{},
|
|
|
|
|
|
&model.GpaSummary{},
|
|
|
|
|
|
&model.Exam{},
|
|
|
|
|
|
&model.EmptyClassroom{},
|
2026-05-12 01:28:18 +08:00
|
|
|
|
|
2026-03-14 02:09:38 +08:00
|
|
|
|
// 用户活跃相关
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.UserActiveLog{},
|
|
|
|
|
|
&model.UserActivityStat{},
|
2026-03-14 02:09:38 +08:00
|
|
|
|
|
|
|
|
|
|
// 角色和权限相关
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.Role{},
|
|
|
|
|
|
&model.UserRole{},
|
|
|
|
|
|
&model.CasbinRule{},
|
2026-03-25 20:44:12 +08:00
|
|
|
|
|
|
|
|
|
|
// 学习资料相关
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.MaterialSubject{},
|
|
|
|
|
|
&model.MaterialFile{},
|
2026-03-27 01:54:34 +08:00
|
|
|
|
|
|
|
|
|
|
// 通话相关
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.CallSession{},
|
|
|
|
|
|
&model.CallParticipant{},
|
2026-04-05 20:27:03 +08:00
|
|
|
|
|
|
|
|
|
|
// 身份认证相关
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.VerificationRecord{},
|
2026-04-15 11:50:47 +08:00
|
|
|
|
|
|
|
|
|
|
// 用户资料审核相关
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.UserProfileAudit{},
|
2026-04-26 00:37:20 +08:00
|
|
|
|
|
|
|
|
|
|
// 帖子内链引用关系
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.PostReference{},
|
feat(trade): implement second-hand trading/flea market feature
Add complete trade functionality including:
- TradeItem, TradeImage, TradeFavorite models with auto-migration
- TradeRepository with CRUD and favorite operations
- TradeService with business logic for listing, creating, updating, status management
- TradeHandler with RESTful endpoints for trade operations
- DTOs and converters for request/response handling
Routes include: list, get by id, create, update, delete, status update, view recording, favorite/unfavorite.
2026-04-26 15:20:26 +08:00
|
|
|
|
|
|
|
|
|
|
// 二手交易相关
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
&model.TradeItem{},
|
|
|
|
|
|
&model.TradeImage{},
|
|
|
|
|
|
&model.TradeFavorite{},
|
2026-06-17 20:41:55 +08:00
|
|
|
|
|
|
|
|
|
|
// 文件上传记录(用于聊天文件 TTL 过期清理)
|
|
|
|
|
|
&model.UploadedFile{},
|
feat(auth): implement session-based token management with revocation support
Add Session model, SessionService, and SessionRepository to track user login
sessions and enable token revocation on auth-critical events.
- Introduce explicit TokenType (access/refresh) in JWT claims to prevent
refresh token misuse via access token endpoints
- Add SessionID field to JWT claims, enabling stateless JWT validation
against revoked sessions
- Replace legacy Auth middleware with RequireAuth/OptionalAuth pipeline
that validates token type, account status, and session validity
- Implement session revocation on password change, reset, user ban/inactive,
and explicit logout
- Add Principal cache with active invalidation for banned/role-changed users
- Fix IDOR vulnerability: GetMessagesByCursor now validates currentUserID
is conversation participant via GetParticipantStrict
- Add group member visibility checks: announcements, group info, member list
now require group membership
- Simplify Casbin policy: remove g grouping, use r.sub == p.sub matcher
with globMatch; user_roles table is single source of truth for roles
- Add migration logic to clean legacy casbin g rules and migrate old p rules
from path-style to admin/<domain> resource naming
2026-07-05 18:28:08 +08:00
|
|
|
|
|
|
|
|
|
|
// 会话(令牌撤销支持)
|
|
|
|
|
|
&model.Session{},
|
2026-03-09 21:28:58 +08:00
|
|
|
|
)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-24 05:18:30 +08:00
|
|
|
|
// AutoMigrate 不会删除列:清理已废弃的 posts.hot_score
|
|
|
|
|
|
if err := dropPostsHotScoreColumnIfExists(db); err != nil {
|
|
|
|
|
|
return fmt.Errorf("drop legacy posts.hot_score: %w", err)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-14 18:01:55 +08:00
|
|
|
|
// 初始化角色种子数据
|
|
|
|
|
|
if err := seedRoles(db); err != nil {
|
|
|
|
|
|
return fmt.Errorf("failed to seed roles: %w", err)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化权限策略种子数据
|
|
|
|
|
|
if err := seedPermissions(db); err != nil {
|
|
|
|
|
|
return fmt.Errorf("failed to seed permissions: %w", err)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
feat(auth): implement session-based token management with revocation support
Add Session model, SessionService, and SessionRepository to track user login
sessions and enable token revocation on auth-critical events.
- Introduce explicit TokenType (access/refresh) in JWT claims to prevent
refresh token misuse via access token endpoints
- Add SessionID field to JWT claims, enabling stateless JWT validation
against revoked sessions
- Replace legacy Auth middleware with RequireAuth/OptionalAuth pipeline
that validates token type, account status, and session validity
- Implement session revocation on password change, reset, user ban/inactive,
and explicit logout
- Add Principal cache with active invalidation for banned/role-changed users
- Fix IDOR vulnerability: GetMessagesByCursor now validates currentUserID
is conversation participant via GetParticipantStrict
- Add group member visibility checks: announcements, group info, member list
now require group membership
- Simplify Casbin policy: remove g grouping, use r.sub == p.sub matcher
with globMatch; user_roles table is single source of truth for roles
- Add migration logic to clean legacy casbin g rules and migrate old p rules
from path-style to admin/<domain> resource naming
2026-07-05 18:28:08 +08:00
|
|
|
|
// 清理历史 Casbin g 分组规则(真源已统一为 user_roles 表,Casbin 仅保留 p 策略)。
|
|
|
|
|
|
// 幂等:仅在 casbin_rule 中存在 ptype='g' 记录时删除。
|
|
|
|
|
|
if err := cleanupLegacyCasbinGRules(db); err != nil {
|
|
|
|
|
|
return fmt.Errorf("failed to cleanup legacy casbin g rules: %w", err)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-24 22:27:53 +08:00
|
|
|
|
// 初始化频道配置种子数据
|
|
|
|
|
|
if err := seedChannels(db); err != nil {
|
|
|
|
|
|
return fmt.Errorf("failed to seed channels: %w", err)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-25 20:44:12 +08:00
|
|
|
|
// 初始化学习资料学科种子数据
|
|
|
|
|
|
if err := seedMaterialSubjects(db); err != nil {
|
|
|
|
|
|
return fmt.Errorf("failed to seed material subjects: %w", err)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-14 18:01:55 +08:00
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-24 05:18:30 +08:00
|
|
|
|
// postWithHotScore 仅用于 Migrator 检测/删除旧列(Post 模型已移除 HotScore)
|
|
|
|
|
|
type postWithHotScore struct {
|
|
|
|
|
|
HotScore float64 `gorm:"column:hot_score"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (postWithHotScore) TableName() string { return "posts" }
|
|
|
|
|
|
|
|
|
|
|
|
func dropPostsHotScoreColumnIfExists(db *gorm.DB) error {
|
|
|
|
|
|
m := db.Migrator()
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
if !m.HasTable(&model.Post{}) {
|
2026-03-24 05:18:30 +08:00
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
if !m.HasColumn(&postWithHotScore{}, "HotScore") {
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
return m.DropColumn(&postWithHotScore{}, "HotScore")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
feat(auth): implement session-based token management with revocation support
Add Session model, SessionService, and SessionRepository to track user login
sessions and enable token revocation on auth-critical events.
- Introduce explicit TokenType (access/refresh) in JWT claims to prevent
refresh token misuse via access token endpoints
- Add SessionID field to JWT claims, enabling stateless JWT validation
against revoked sessions
- Replace legacy Auth middleware with RequireAuth/OptionalAuth pipeline
that validates token type, account status, and session validity
- Implement session revocation on password change, reset, user ban/inactive,
and explicit logout
- Add Principal cache with active invalidation for banned/role-changed users
- Fix IDOR vulnerability: GetMessagesByCursor now validates currentUserID
is conversation participant via GetParticipantStrict
- Add group member visibility checks: announcements, group info, member list
now require group membership
- Simplify Casbin policy: remove g grouping, use r.sub == p.sub matcher
with globMatch; user_roles table is single source of truth for roles
- Add migration logic to clean legacy casbin g rules and migrate old p rules
from path-style to admin/<domain> resource naming
2026-07-05 18:28:08 +08:00
|
|
|
|
// cleanupLegacyCasbinGRules 清理历史 Casbin g 分组规则。
|
|
|
|
|
|
//
|
|
|
|
|
|
// 真源策略变更后:user_roles 表为用户-角色唯一真源,Casbin 仅保留 p, role, resource, action 策略。
|
|
|
|
|
|
// 旧的 g, user, role 记录不再被 matcher 使用(model.conf 已移除 g 依赖),保留只会造成管理后台误解。
|
|
|
|
|
|
// 幂等:仅删除 ptype='g' 的记录;若不存在则无操作。
|
|
|
|
|
|
func cleanupLegacyCasbinGRules(db *gorm.DB) error {
|
|
|
|
|
|
if !db.Migrator().HasTable(&model.CasbinRule{}) {
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
result := db.Where("ptype = ?", "g").Delete(&model.CasbinRule{})
|
|
|
|
|
|
if result.Error != nil {
|
|
|
|
|
|
return result.Error
|
|
|
|
|
|
}
|
|
|
|
|
|
if result.RowsAffected > 0 {
|
|
|
|
|
|
zap.L().Info("Cleaned up legacy casbin g rules",
|
|
|
|
|
|
zap.Int64("count", result.RowsAffected),
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-14 18:01:55 +08:00
|
|
|
|
// seedRoles 初始化角色种子数据
|
|
|
|
|
|
func seedRoles(db *gorm.DB) error {
|
|
|
|
|
|
// 检查是否已有角色数据
|
|
|
|
|
|
var count int64
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
if err := db.Model(&model.Role{}).Count(&count).Error; err != nil {
|
2026-03-14 18:01:55 +08:00
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果已有数据,跳过种子初始化
|
|
|
|
|
|
if count > 0 {
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 预定义角色数据
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
roles := []model.Role{
|
2026-03-14 18:01:55 +08:00
|
|
|
|
{
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
Name: model.RoleSuperAdmin,
|
2026-03-14 18:01:55 +08:00
|
|
|
|
DisplayName: "超级管理员",
|
|
|
|
|
|
Description: "拥有系统最高权限,可以管理所有用户和内容",
|
|
|
|
|
|
Priority: 100,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
Name: model.RoleAdmin,
|
2026-03-14 18:01:55 +08:00
|
|
|
|
DisplayName: "管理员",
|
|
|
|
|
|
Description: "系统管理员,可以管理用户和内容",
|
|
|
|
|
|
Priority: 80,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
Name: model.RoleModerator,
|
2026-03-14 18:01:55 +08:00
|
|
|
|
DisplayName: "版主",
|
|
|
|
|
|
Description: "内容审核员,可以审核和管理内容",
|
|
|
|
|
|
Priority: 60,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
Name: model.RoleUser,
|
2026-03-14 18:01:55 +08:00
|
|
|
|
DisplayName: "普通用户",
|
|
|
|
|
|
Description: "注册用户,拥有基本权限",
|
|
|
|
|
|
Priority: 40,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
Name: model.RoleBanned,
|
2026-03-14 18:01:55 +08:00
|
|
|
|
DisplayName: "被封禁用户",
|
|
|
|
|
|
Description: "被禁止访问的用户",
|
|
|
|
|
|
Priority: 0,
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 批量插入角色
|
|
|
|
|
|
if err := db.Create(&roles).Error; err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-17 00:47:17 +08:00
|
|
|
|
zap.L().Info("Seeded roles successfully",
|
|
|
|
|
|
zap.Int("count", len(roles)),
|
|
|
|
|
|
)
|
2026-03-14 18:01:55 +08:00
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// seedPermissions 初始化权限策略种子数据
|
feat(auth): implement session-based token management with revocation support
Add Session model, SessionService, and SessionRepository to track user login
sessions and enable token revocation on auth-critical events.
- Introduce explicit TokenType (access/refresh) in JWT claims to prevent
refresh token misuse via access token endpoints
- Add SessionID field to JWT claims, enabling stateless JWT validation
against revoked sessions
- Replace legacy Auth middleware with RequireAuth/OptionalAuth pipeline
that validates token type, account status, and session validity
- Implement session revocation on password change, reset, user ban/inactive,
and explicit logout
- Add Principal cache with active invalidation for banned/role-changed users
- Fix IDOR vulnerability: GetMessagesByCursor now validates currentUserID
is conversation participant via GetParticipantStrict
- Add group member visibility checks: announcements, group info, member list
now require group membership
- Simplify Casbin policy: remove g grouping, use r.sub == p.sub matcher
with globMatch; user_roles table is single source of truth for roles
- Add migration logic to clean legacy casbin g rules and migrate old p rules
from path-style to admin/<domain> resource naming
2026-07-05 18:28:08 +08:00
|
|
|
|
//
|
|
|
|
|
|
// 真源策略:user_roles 表为用户-角色真源,Casbin 仅维护 p, role, resource, action 策略。
|
|
|
|
|
|
// 资源命名约定:admin/<domain>[/<sub>](路径式,配合 globMatch 中 * 不跨 /、** 跨 / 的语义)。
|
|
|
|
|
|
//
|
|
|
|
|
|
// 升级兼容:旧版本以 URL 路径式资源(如 /api/v1/admin/*、/*)作为 Casbin 策略,
|
|
|
|
|
|
// 新版本改为 admin/<domain> 资源命名后,存量部署需要迁移。本函数检测到任何 v1 以 '/' 开头的
|
|
|
|
|
|
// 旧策略时,将其视为旧版本部署:清空所有 p 策略并按新约定重新 seed。
|
|
|
|
|
|
// 新部署无此条件不触发,幂等(admin/<domain> 不以 '/' 开头,不会误判为新旧迁移)。
|
2026-03-14 18:01:55 +08:00
|
|
|
|
func seedPermissions(db *gorm.DB) error {
|
|
|
|
|
|
// 检查是否已有权限策略数据
|
|
|
|
|
|
var count int64
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
if err := db.Model(&model.CasbinRule{}).Where("ptype = ?", "p").Count(&count).Error; err != nil {
|
2026-03-14 18:01:55 +08:00
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if count > 0 {
|
feat(auth): implement session-based token management with revocation support
Add Session model, SessionService, and SessionRepository to track user login
sessions and enable token revocation on auth-critical events.
- Introduce explicit TokenType (access/refresh) in JWT claims to prevent
refresh token misuse via access token endpoints
- Add SessionID field to JWT claims, enabling stateless JWT validation
against revoked sessions
- Replace legacy Auth middleware with RequireAuth/OptionalAuth pipeline
that validates token type, account status, and session validity
- Implement session revocation on password change, reset, user ban/inactive,
and explicit logout
- Add Principal cache with active invalidation for banned/role-changed users
- Fix IDOR vulnerability: GetMessagesByCursor now validates currentUserID
is conversation participant via GetParticipantStrict
- Add group member visibility checks: announcements, group info, member list
now require group membership
- Simplify Casbin policy: remove g grouping, use r.sub == p.sub matcher
with globMatch; user_roles table is single source of truth for roles
- Add migration logic to clean legacy casbin g rules and migrate old p rules
from path-style to admin/<domain> resource naming
2026-07-05 18:28:08 +08:00
|
|
|
|
// 检测是否存在旧版本路径式策略(v1 以 '/' 开头)。
|
|
|
|
|
|
// 旧策略例如:{p, super_admin, /*, *} / {p, admin, /api/v1/admin/*, *} 等。
|
|
|
|
|
|
// 新约定资源形如 admin/users(不以 '/' 开头),不会被本条件误命中。
|
|
|
|
|
|
// 旧策略在新 model.conf 的 admin/<domain> 命名下永远不会匹配,保留只会让管理后台权限全断。
|
|
|
|
|
|
var legacyCount int64
|
|
|
|
|
|
if err := db.Model(&model.CasbinRule{}).
|
|
|
|
|
|
Where("ptype = ? AND v1 LIKE '/%'", "p").
|
|
|
|
|
|
Count(&legacyCount).Error; err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
if legacyCount == 0 {
|
|
|
|
|
|
// 已是新版本策略,无需重复 seed。
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 命中旧策略:迁移。先 dump 待删除策略到日志便于回查,再删除全部 p 策略。
|
|
|
|
|
|
zap.L().Info("Migrating legacy path-based casbin p rules to admin/<domain> resource naming",
|
|
|
|
|
|
zap.Int64("legacy_count", legacyCount),
|
|
|
|
|
|
zap.Int64("total_p_count", count),
|
|
|
|
|
|
)
|
|
|
|
|
|
var legacyRules []model.CasbinRule
|
|
|
|
|
|
if err := db.Where("ptype = ?", "p").Find(&legacyRules).Error; err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
for _, r := range legacyRules {
|
|
|
|
|
|
zap.L().Debug("legacy casbin p rule will be removed",
|
|
|
|
|
|
zap.String("v0", r.V0),
|
|
|
|
|
|
zap.String("v1", r.V1),
|
|
|
|
|
|
zap.String("v2", r.V2),
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
if err := db.Where("ptype = ?", "p").Delete(&model.CasbinRule{}).Error; err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
// 注意:count > 0 分支到此已清空所有 p 策略,下面统一重新 seed。
|
2026-03-14 18:01:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 预定义权限策略数据
|
|
|
|
|
|
// p = sub, obj, act (角色, 资源, 操作)
|
feat(auth): implement session-based token management with revocation support
Add Session model, SessionService, and SessionRepository to track user login
sessions and enable token revocation on auth-critical events.
- Introduce explicit TokenType (access/refresh) in JWT claims to prevent
refresh token misuse via access token endpoints
- Add SessionID field to JWT claims, enabling stateless JWT validation
against revoked sessions
- Replace legacy Auth middleware with RequireAuth/OptionalAuth pipeline
that validates token type, account status, and session validity
- Implement session revocation on password change, reset, user ban/inactive,
and explicit logout
- Add Principal cache with active invalidation for banned/role-changed users
- Fix IDOR vulnerability: GetMessagesByCursor now validates currentUserID
is conversation participant via GetParticipantStrict
- Add group member visibility checks: announcements, group info, member list
now require group membership
- Simplify Casbin policy: remove g grouping, use r.sub == p.sub matcher
with globMatch; user_roles table is single source of truth for roles
- Add migration logic to clean legacy casbin g rules and migrate old p rules
from path-style to admin/<domain> resource naming
2026-07-05 18:28:08 +08:00
|
|
|
|
//
|
|
|
|
|
|
// 资源命名约定:admin/<domain>[/<sub>](路径式),动作:read / write / *。
|
|
|
|
|
|
// super_admin 通过 admin/** 通配获得所有管理能力(globMatch 中 ** 跨 '/');
|
|
|
|
|
|
// admin 仅获得业务管理能力,角色与权限管理(admin/roles/*、admin/users/roles/*)
|
|
|
|
|
|
// 与日志导出(admin/logs/export)仅 super_admin 拥有(admin/logs 单层匹配不跨 /)。
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
permissions := []model.CasbinRule{
|
feat(auth): implement session-based token management with revocation support
Add Session model, SessionService, and SessionRepository to track user login
sessions and enable token revocation on auth-critical events.
- Introduce explicit TokenType (access/refresh) in JWT claims to prevent
refresh token misuse via access token endpoints
- Add SessionID field to JWT claims, enabling stateless JWT validation
against revoked sessions
- Replace legacy Auth middleware with RequireAuth/OptionalAuth pipeline
that validates token type, account status, and session validity
- Implement session revocation on password change, reset, user ban/inactive,
and explicit logout
- Add Principal cache with active invalidation for banned/role-changed users
- Fix IDOR vulnerability: GetMessagesByCursor now validates currentUserID
is conversation participant via GetParticipantStrict
- Add group member visibility checks: announcements, group info, member list
now require group membership
- Simplify Casbin policy: remove g grouping, use r.sub == p.sub matcher
with globMatch; user_roles table is single source of truth for roles
- Add migration logic to clean legacy casbin g rules and migrate old p rules
from path-style to admin/<domain> resource naming
2026-07-05 18:28:08 +08:00
|
|
|
|
// 超级管理员 - 通配所有 admin 资源(globMatch:** 跨 '/' 分隔的多级资源)
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleSuperAdmin, V1: "admin/**", V2: "*"},
|
|
|
|
|
|
|
|
|
|
|
|
// 管理员 - 业务管理能力(不含角色/权限管理与日志导出)
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleAdmin, V1: "admin/users", V2: "read"},
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleAdmin, V1: "admin/users/status", V2: "write"},
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleAdmin, V1: "admin/users/devices", V2: "read"},
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleAdmin, V1: "admin/posts", V2: "*"},
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleAdmin, V1: "admin/comments", V2: "*"},
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleAdmin, V1: "admin/groups", V2: "*"},
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleAdmin, V1: "admin/channels", V2: "*"},
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleAdmin, V1: "admin/dashboard", V2: "read"},
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleAdmin, V1: "admin/reports", V2: "*"},
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleAdmin, V1: "admin/verifications", V2: "*"},
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleAdmin, V1: "admin/profile_audits", V2: "*"},
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleAdmin, V1: "admin/materials", V2: "*"},
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleAdmin, V1: "admin/logs", V2: "read"},
|
|
|
|
|
|
|
|
|
|
|
|
// 版主 - 内容审核
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleModerator, V1: "admin/posts", V2: "read"},
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleModerator, V1: "admin/posts", V2: "write"},
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleModerator, V1: "admin/comments", V2: "read"},
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleModerator, V1: "admin/comments", V2: "write"},
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleModerator, V1: "admin/reports", V2: "read"},
|
|
|
|
|
|
{Ptype: "p", V0: model.RoleModerator, V1: "admin/reports", V2: "write"},
|
|
|
|
|
|
|
|
|
|
|
|
// 普通用户与被封禁用户:admin 路由外的资源由路由层中间件保障,Casbin 不维护。
|
2026-03-14 18:01:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 批量插入权限策略
|
|
|
|
|
|
if err := db.Create(&permissions).Error; err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-17 00:47:17 +08:00
|
|
|
|
zap.L().Info("Seeded permissions successfully",
|
|
|
|
|
|
zap.Int("count", len(permissions)),
|
|
|
|
|
|
)
|
2026-03-09 21:28:58 +08:00
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-25 20:44:12 +08:00
|
|
|
|
// seedChannels 初始化频道种子数据(仅在表为空时)
|
2026-03-24 22:27:53 +08:00
|
|
|
|
func seedChannels(db *gorm.DB) error {
|
2026-03-25 20:44:12 +08:00
|
|
|
|
// 检查是否已有频道数据
|
|
|
|
|
|
var count int64
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
if err := db.Model(&model.Channel{}).Count(&count).Error; err != nil {
|
2026-03-25 20:44:12 +08:00
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
if count > 0 {
|
|
|
|
|
|
zap.L().Info("Channels already exist, skipping seed", zap.Int64("count", count))
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
defaultChannels := []model.Channel{
|
2026-03-24 22:27:53 +08:00
|
|
|
|
{Name: "跳蚤市场", Slug: "market", Description: "二手交易与闲置发布", SortOrder: 10, IsActive: true},
|
|
|
|
|
|
{Name: "课程交流", Slug: "courses", Description: "课程资料、选课与学习讨论", SortOrder: 20, IsActive: true},
|
|
|
|
|
|
{Name: "工作实习", Slug: "jobs", Description: "实习、内推与求职信息", SortOrder: 30, IsActive: true},
|
|
|
|
|
|
{Name: "考研考公", Slug: "exam", Description: "备考经验、资料与互助", SortOrder: 40, IsActive: true},
|
|
|
|
|
|
{Name: "保研出国", Slug: "graduate-abroad", Description: "保研、留学申请与经验分享", SortOrder: 50, IsActive: true},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-25 20:44:12 +08:00
|
|
|
|
if err := db.Create(&defaultChannels).Error; err != nil {
|
|
|
|
|
|
return err
|
2026-03-24 22:27:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
zap.L().Info("Seeded channels successfully", zap.Int("count", len(defaultChannels)))
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-25 20:44:12 +08:00
|
|
|
|
// seedMaterialSubjects 初始化学习资料学科种子数据(仅在表为空时)
|
|
|
|
|
|
func seedMaterialSubjects(db *gorm.DB) error {
|
|
|
|
|
|
// 检查是否已有数据
|
|
|
|
|
|
var count int64
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
if err := db.Model(&model.MaterialSubject{}).Count(&count).Error; err != nil {
|
2026-03-25 20:44:12 +08:00
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
if count > 0 {
|
|
|
|
|
|
zap.L().Info("Material subjects already exist, skipping seed", zap.Int64("count", count))
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion.
- Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects.
- Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management.
- Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering.
- Improve database initialization by moving it from `internal/model` to `internal/database`.
- Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool.
- Enhance error handling and security by implementing fail-fast checks for encryption key length during startup.
- Clean up unused code, including the `avatar` package and several unused DTOs.
2026-06-15 03:41:59 +08:00
|
|
|
|
defaultSubjects := []model.MaterialSubject{
|
2026-03-25 20:44:12 +08:00
|
|
|
|
{Name: "数学", Icon: "calculator-variant", Color: "#FF6B6B", Description: "高等数学、线性代数、概率论等", SortOrder: 10, IsActive: true},
|
|
|
|
|
|
{Name: "英语", Icon: "translate", Color: "#4ECDC4", Description: "四六级、考研英语、托福雅思等", SortOrder: 20, IsActive: true},
|
|
|
|
|
|
{Name: "物理", Icon: "atom", Color: "#45B7D1", Description: "大学物理、电磁学、力学等", SortOrder: 30, IsActive: true},
|
|
|
|
|
|
{Name: "化学", Icon: "flask", Color: "#96CEB4", Description: "有机化学、无机化学、分析化学等", SortOrder: 40, IsActive: true},
|
|
|
|
|
|
{Name: "计算机", Icon: "laptop", Color: "#FFEAA7", Description: "数据结构、算法、操作系统等", SortOrder: 50, IsActive: true},
|
|
|
|
|
|
{Name: "经济管理", Icon: "chart-line", Color: "#DDA0DD", Description: "微观经济学、宏观经济学、管理学等", SortOrder: 60, IsActive: true},
|
|
|
|
|
|
{Name: "法学", Icon: "scale-balance", Color: "#F39C12", Description: "民法、刑法、宪法等", SortOrder: 70, IsActive: true},
|
|
|
|
|
|
{Name: "语文文学", Icon: "book-open-page-variant", Color: "#3498DB", Description: "古代文学、现代文学、写作等", SortOrder: 80, IsActive: true},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := db.Create(&defaultSubjects).Error; err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
zap.L().Info("Seeded material subjects successfully", zap.Int("count", len(defaultSubjects)))
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|