feat: 多租户账号体系 + 前台收藏按钮

- 新增 users 表(user_id 数据隔离,bcrypt 密码)
- 认证: 注册/登录(用户名+密码)/会话绑定用户, 首个用户成为管理员并接管旧数据
- 数据隔离: 笔记/分类/标签/回收站/版本/草稿/图谱/FTS 全部按用户隔离
- 前台: 登录/注册弹窗, 登录后★收藏自己的笔记, 游客只读公开笔记
- 后台: 用户名+密码登录, 每人管理自己的工作区, 越权访问返回404
- 冒烟测试重构+新增多租户隔离用例(78/78)
This commit is contained in:
Your Name
2026-08-11 12:58:12 +08:00
parent 2196189791
commit d9793300f9
16 changed files with 1216 additions and 278 deletions
+63
View File
@@ -0,0 +1,63 @@
package repository
import (
"errors"
"gorm.io/gorm"
"note-manager/model"
)
// UserRepository 用户数据访问层(多租户账号)
type UserRepository struct {
db *gorm.DB
}
// NewUserRepository 创建用户仓库(复用已有数据库连接)
func NewUserRepository(db *gorm.DB) *UserRepository {
return &UserRepository{db: db}
}
// AutoMigrate 确保 users 表存在
func (r *UserRepository) AutoMigrate() error {
return r.db.AutoMigrate(&model.User{})
}
// Count 统计用户总数
func (r *UserRepository) Count() (int64, error) {
var n int64
err := r.db.Model(&model.User{}).Count(&n).Error
return n, err
}
// Create 创建用户(用户名冲突返回错误)
func (r *UserRepository) Create(u *model.User) error {
return r.db.Create(u).Error
}
// GetByUsername 通过用户名查询(不分大小写,统一小写存储/匹配)
func (r *UserRepository) GetByUsername(username string) (*model.User, error) {
var u model.User
err := r.db.Where("username = ?", username).First(&u).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("用户不存在")
}
return nil, err
}
return &u, nil
}
// GetByID 通过 ID 查询用户
func (r *UserRepository) GetByID(id uint) (*model.User, error) {
var u model.User
err := r.db.First(&u, id).Error
if err != nil {
return nil, err
}
return &u, nil
}
// GetDB 暴露底层连接(供需要跨表事务/迁移的场景)
func (r *UserRepository) GetDB() *gorm.DB {
return r.db
}