mirror of
				https://github.com/cloudreve/cloudreve.git
				synced 2025-10-31 08:39:10 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			121 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package model
 | |
| 
 | |
| import (
 | |
| 	"cloudreve/pkg/util"
 | |
| 	"crypto/sha1"
 | |
| 	"encoding/hex"
 | |
| 	"encoding/json"
 | |
| 	"github.com/jinzhu/gorm"
 | |
| 	"github.com/pkg/errors"
 | |
| 	"strings"
 | |
| 	"time"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	// Active 账户正常状态
 | |
| 	Active = iota
 | |
| 	// NotActivicated 未激活
 | |
| 	NotActivicated
 | |
| 	// Baned 被封禁
 | |
| 	Baned
 | |
| )
 | |
| 
 | |
| // User 用户模型
 | |
| type User struct {
 | |
| 	gorm.Model
 | |
| 	Email             string `gorm:"type:varchar(100);unique_index"`
 | |
| 	Nick              string `gorm:"size:50"`
 | |
| 	Password          string `json:"-"`
 | |
| 	Status            int
 | |
| 	Group             int
 | |
| 	PrimaryGroup      int
 | |
| 	ActivationKey     string `json:"-"`
 | |
| 	Storage           int64
 | |
| 	LastNotify        *time.Time
 | |
| 	OpenID            string `json:"-"`
 | |
| 	TwoFactor         string `json:"-"`
 | |
| 	Delay             int
 | |
| 	Avatar            string
 | |
| 	Options           string     `json:"-",gorm:"size:4096"`
 | |
| 	OptionsSerialized UserOption `gorm:"-"`
 | |
| }
 | |
| 
 | |
| // UserOption 用户个性化配置字段
 | |
| type UserOption struct {
 | |
| 	ProfileOn int    `json:"profile_on"`
 | |
| 	WebDAVKey string `json:"webdav_key"`
 | |
| }
 | |
| 
 | |
| // GetUserByID 用ID获取用户
 | |
| func GetUserByID(ID interface{}) (User, error) {
 | |
| 	var user User
 | |
| 	result := DB.First(&user, ID)
 | |
| 	return user, result.Error
 | |
| }
 | |
| 
 | |
| // GetUserByEmail 用Email获取用户
 | |
| func GetUserByEmail(email string) (User, error) {
 | |
| 	var user User
 | |
| 	result := DB.Where("email = ?", email).First(&user)
 | |
| 	return user, result.Error
 | |
| }
 | |
| 
 | |
| // NewUser 返回一个新的空 User
 | |
| func NewUser() User {
 | |
| 	options := UserOption{
 | |
| 		ProfileOn: 1,
 | |
| 	}
 | |
| 	optionsValue, _ := json.Marshal(&options)
 | |
| 	return User{
 | |
| 		Avatar:  "default",
 | |
| 		Options: string(optionsValue),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // AfterFind 找到用户后的钩子
 | |
| func (user *User) AfterFind() (err error) {
 | |
| 	// 解析用户设置到OptionsSerialized
 | |
| 	err = json.Unmarshal([]byte(user.Options), &user.OptionsSerialized)
 | |
| 	return err
 | |
| }
 | |
| 
 | |
| // CheckPassword 根据明文校验密码
 | |
| func (user *User) CheckPassword(password string) (bool, error) {
 | |
| 
 | |
| 	// 根据存储密码拆分为 Salt 和 Digest
 | |
| 	passwordStore := strings.Split(user.Password, ":")
 | |
| 	if len(passwordStore) != 2 {
 | |
| 		return false, errors.New("Unknown password type")
 | |
| 	}
 | |
| 
 | |
| 	// todo 兼容V2/V1密码
 | |
| 	//计算 Salt 和密码组合的SHA1摘要
 | |
| 	hash := sha1.New()
 | |
| 	_, err := hash.Write([]byte(password + passwordStore[0]))
 | |
| 	bs := hex.EncodeToString(hash.Sum(nil))
 | |
| 	if err != nil {
 | |
| 		return false, err
 | |
| 	}
 | |
| 
 | |
| 	return bs == passwordStore[1], nil
 | |
| }
 | |
| 
 | |
| // SetPassword 根据给定明文设定 User 的 Password 字段
 | |
| func (user *User) SetPassword(password string) error {
 | |
| 	//生成16位 Salt
 | |
| 	salt := util.RandStringRunes(16)
 | |
| 
 | |
| 	//计算 Salt 和密码组合的SHA1摘要
 | |
| 	hash := sha1.New()
 | |
| 	_, err := hash.Write([]byte(password + salt))
 | |
| 	bs := hex.EncodeToString(hash.Sum(nil))
 | |
| 
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	//存储 Salt 值和摘要, ":"分割
 | |
| 	user.Password = salt + ":" + string(bs)
 | |
| 	return nil
 | |
| }
 | 
