mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-29 22:06:38 +08:00
4f50f6a8f9
Wire plugin services through Bind/InjectFrom and AppContext so HTTP and workers resolve dependencies after Apply. Register TaskHandler objects with persisted results, and implement send_email_code, mail:send, cleanup_inactive_users, and dispatch_bot_msg.
145 lines
4.6 KiB
Go
145 lines
4.6 KiB
Go
// Copyright 2026 Arctel.net
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package user
|
|
|
|
import (
|
|
"Wavelet/pkg/util"
|
|
"errors"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// AccessToken 个人访问令牌实体
|
|
type AccessToken struct {
|
|
ID uint64 `json:"id" gorm:"primaryKey;autoIncrement"`
|
|
UserID uint64 `json:"user_id" gorm:"index;not null"`
|
|
Name string `json:"name" gorm:"size:128;not null"`
|
|
TokenHash string `json:"-" gorm:"size:64;uniqueIndex;not null"`
|
|
MaskedToken string `json:"masked_token" gorm:"size:64;not null"`
|
|
IsAdmin bool `json:"is_admin" gorm:"default:false"`
|
|
CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"`
|
|
UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"`
|
|
}
|
|
|
|
// TableName 表名
|
|
func (AccessToken) TableName() string {
|
|
return "w_access_tokens"
|
|
}
|
|
|
|
// User 用户表实体
|
|
type User struct {
|
|
ID uint64 `json:"id,string" gorm:"primaryKey;not null"`
|
|
Username string `json:"username" gorm:"size:64;uniqueIndex"`
|
|
Password string `json:"password,omitempty" gorm:"size:255"`
|
|
Nickname string `json:"nickname" gorm:"size:255"`
|
|
Email string `json:"email" gorm:"size:255;index"`
|
|
AvatarURL string `json:"avatar_url" gorm:"size:255"`
|
|
IsActive bool `json:"is_active" gorm:"default:true;index"`
|
|
IsAdmin bool `json:"is_admin" gorm:"default:false"`
|
|
NeedChangePassword bool `json:"need_change_password,omitempty" gorm:"-"`
|
|
Bio string `json:"bio" gorm:"size:500"`
|
|
Phone string `json:"phone" gorm:"size:32"`
|
|
Gender string `json:"gender" gorm:"size:16"`
|
|
Website string `json:"website" gorm:"size:255"`
|
|
Location string `json:"location" gorm:"size:255"`
|
|
LastLoginAt time.Time `json:"last_login_at" gorm:"index"`
|
|
CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime;index"`
|
|
UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime;index"`
|
|
}
|
|
|
|
// TableName 表名
|
|
func (User) TableName() string {
|
|
return "w_users"
|
|
}
|
|
|
|
// IsPlaintextPassword 检查当前密码是否为未加密的明文密码(如初始默认密码)
|
|
func (u *User) IsPlaintextPassword() bool {
|
|
if u.Password == "" {
|
|
return false
|
|
}
|
|
return !strings.HasPrefix(u.Password, "$2a$") &&
|
|
!strings.HasPrefix(u.Password, "$2b$") &&
|
|
!strings.HasPrefix(u.Password, "$2y$") &&
|
|
!strings.HasPrefix(u.Password, "$2x$")
|
|
}
|
|
|
|
// SetEncryptedPassword 设置加密密码
|
|
func (u *User) SetEncryptedPassword(password string) error {
|
|
trimmed := strings.TrimSpace(password)
|
|
if trimmed == "" {
|
|
return errors.New(errPasswordEmpty)
|
|
}
|
|
hash, err := util.HashPassword(trimmed)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
u.Password = hash
|
|
return nil
|
|
}
|
|
|
|
// CheckPassword 校验密码(支持 bcrypt 哈希校验与初始明文密码校验)
|
|
func (u *User) CheckPassword(password string) bool {
|
|
if u.Password == "" {
|
|
util.DummyCheckPassword(password)
|
|
return false
|
|
}
|
|
if !u.IsPlaintextPassword() {
|
|
return util.CheckPasswordHash(u.Password, password)
|
|
}
|
|
|
|
// 明文密码兼容比对(识别初始默认密码向用户警告修改密码)
|
|
if u.Password == password {
|
|
u.NeedChangePassword = true
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// loginRequest 登录请求参数
|
|
type loginRequest struct {
|
|
Username string `json:"username" binding:"required"`
|
|
Password string `json:"password" binding:"required"`
|
|
}
|
|
|
|
// registerRequest 注册请求参数
|
|
type registerRequest struct {
|
|
Username string `json:"username" binding:"required"`
|
|
Password string `json:"password" binding:"required"`
|
|
Email string `json:"email"`
|
|
}
|
|
|
|
type sendEmailCodeRequest struct {
|
|
Email string `json:"email" binding:"required"`
|
|
}
|
|
|
|
// changePasswordRequest 修改密码请求参数
|
|
type changePasswordRequest struct {
|
|
OldPassword string `json:"old_password" binding:"required"`
|
|
NewPassword string `json:"new_password" binding:"required"`
|
|
}
|
|
|
|
// updateProfileRequest 资料更新请求参数
|
|
type updateProfileRequest struct {
|
|
Nickname string `json:"nickname"`
|
|
AvatarURL string `json:"avatar_url"`
|
|
Bio string `json:"bio"`
|
|
Phone string `json:"phone"`
|
|
Gender string `json:"gender"`
|
|
Website string `json:"website"`
|
|
Location string `json:"location"`
|
|
}
|
|
|
|
// createAccessTokenRequest 创建访问令牌请求参数
|
|
type createAccessTokenRequest struct {
|
|
Name string `json:"name" binding:"required"`
|
|
ExpiresAt *time.Time `json:"expires_at"`
|
|
IsAdmin bool `json:"is_admin"`
|
|
}
|
|
|
|
// userAdminFlags 用户写操作前置校验所需的最小列投影
|
|
type userAdminFlags struct {
|
|
ID uint64
|
|
IsAdmin bool
|
|
}
|