feat: 管理员跨租户管理 + 注册开关

- 管理员可管理任意用户笔记(读取/修改/删除/回收站/标签/图谱/FTS 全平台)
- 普通用户仍数据隔离, 越权返回404
- 新增注册开关: 管理员后台⚙设置可开/关, 支持REGISTRATION_ENABLED环境变量
- 注册关闭时前台/登录页隐藏注册入口, 注册接口返回400
- 冒烟测试扩展到91用例全过
This commit is contained in:
Your Name
2026-08-11 13:07:56 +08:00
parent d9793300f9
commit 13c53fea0a
12 changed files with 741 additions and 89 deletions
+51 -2
View File
@@ -11,15 +11,37 @@ import (
// UserService 用户/账号业务逻辑(多租户认证)
type UserService struct {
userRepo *repository.UserRepository
// registrationEnabled 以 env 为准的注册默认开关;DB 设置项可覆盖(运行时切换)
registrationDefault string
}
// NewUserService 创建用户服务
func NewUserService(userRepo *repository.UserRepository) *UserService {
return &UserService{userRepo: userRepo}
return &UserService{userRepo: userRepo, registrationDefault: "true"}
}
// SetRegistrationDefault 设置注册开关的默认值(来自环境变量)
func (s *UserService) SetRegistrationDefault(v string) {
s.registrationDefault = v
}
// RegistrationEnabled 当前注册开关是否开启
func (s *UserService) RegistrationEnabled() bool {
val := s.userRepo.GetSetting("registration_enabled", s.registrationDefault)
return val == "1" || val == "true"
}
// SetRegistrationEnabled 切换注册开关(持久化到 DB)
func (s *UserService) SetRegistrationEnabled(on bool) error {
v := "false"
if on {
v = "true"
}
return s.userRepo.SetSetting("registration_enabled", v)
}
// Register 注册新用户
// 说明:第一个注册的用户自动成为 admin(拥有平台管理权限);其余为普通 user。
// 说明:个注册的用户自动成为 admin(拥有平台管理权限);其余为普通 user。
// 同时把历史遗留(user_id=0)的笔记迁移给首位注册用户。
func (s *UserService) Register(username, password, displayName string) (*model.User, error) {
username = strings.TrimSpace(strings.ToLower(username))
@@ -30,6 +52,9 @@ func (s *UserService) Register(username, password, displayName string) (*model.U
if len(password) < 6 {
return nil, errors.New("密码至少 6 位")
}
if !s.RegistrationEnabled() {
return nil, errors.New("注册功能已关闭")
}
if _, err := s.userRepo.GetByUsername(username); err == nil {
return nil, errors.New("用户名已存在")
}
@@ -66,6 +91,30 @@ func (s *UserService) Register(username, password, displayName string) (*model.U
return u, nil
}
// IsAdmin 判断用户是否为管理员
func (s *UserService) IsAdmin(userID uint) bool {
if userID == 0 {
return false
}
u, err := s.userRepo.GetByID(userID)
if err != nil || u == nil {
return false
}
return u.Role == "admin"
}
// GetRole 返回用户角色(admin/user/空)
func (s *UserService) GetRole(userID uint) string {
if userID == 0 {
return ""
}
u, err := s.userRepo.GetByID(userID)
if err != nil || u == nil {
return ""
}
return u.Role
}
// Login 校验用户名密码,返回用户
func (s *UserService) Login(username, password string) (*model.User, error) {
username = strings.TrimSpace(strings.ToLower(username))