258 lines
5.9 KiB
Go
258 lines
5.9 KiB
Go
package model
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"github.com/golang-jwt/jwt/v5"
|
|
"github.com/loveuer/nfflow/internal/opt"
|
|
"github.com/loveuer/nfflow/internal/sqlType"
|
|
"github.com/loveuer/nfflow/internal/util"
|
|
"github.com/samber/lo"
|
|
"github.com/sirupsen/logrus"
|
|
"github.com/spf13/cast"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
initUsers = []*User{
|
|
{
|
|
Id: 1,
|
|
Username: "root",
|
|
Password: util.NewPassword("404@Ro0t"),
|
|
Nickname: "admin",
|
|
Role: RoleRoot,
|
|
//Privileges: sqlType.NumSlice[Privilege]{
|
|
// PrivilegeUserManage,
|
|
//},
|
|
Privileges: lo.Map(Privilege(0).All(), func(item Enum, index int) Privilege {
|
|
return item.(Privilege)
|
|
}),
|
|
CreatedById: 1,
|
|
CreatedByName: "admin",
|
|
ActiveAt: time.Now().UnixMilli(),
|
|
Deadline: time.Now().AddDate(100, 0, 0).UnixMilli(),
|
|
},
|
|
{
|
|
Id: 2,
|
|
Username: "admin",
|
|
Password: util.NewPassword("Foobar123"),
|
|
Nickname: "admin",
|
|
Role: RoleAdmin,
|
|
Privileges: lo.Map(Privilege(0).All(), func(item Enum, index int) Privilege {
|
|
return item.(Privilege)
|
|
}),
|
|
CreatedById: 1,
|
|
CreatedByName: "admin",
|
|
ActiveAt: time.Now().UnixMilli(),
|
|
Deadline: time.Now().AddDate(100, 0, 0).UnixMilli(),
|
|
},
|
|
{
|
|
Id: 3,
|
|
Username: "user",
|
|
Password: util.NewPassword("Foobar123"),
|
|
Nickname: "user",
|
|
Role: RoleUser,
|
|
Privileges: sqlType.NumSlice[Privilege]{
|
|
PrivilegeOpLog,
|
|
},
|
|
CreatedById: 2,
|
|
CreatedByName: "admin",
|
|
ActiveAt: time.Now().UnixMilli(),
|
|
Deadline: time.Now().AddDate(100, 0, 0).UnixMilli(),
|
|
},
|
|
}
|
|
|
|
_ Enum = Status(0)
|
|
)
|
|
|
|
type Status uint64
|
|
|
|
const (
|
|
StatusNormal Status = iota
|
|
StatusFrozen
|
|
)
|
|
|
|
func (s Status) Value() int64 {
|
|
return int64(s)
|
|
}
|
|
|
|
func (s Status) Code() string {
|
|
switch s {
|
|
case StatusNormal:
|
|
return "normal"
|
|
case StatusFrozen:
|
|
return "frozen"
|
|
default:
|
|
return "unknown"
|
|
}
|
|
}
|
|
|
|
func (s Status) Label() string {
|
|
switch s {
|
|
case StatusNormal:
|
|
return "正常"
|
|
case StatusFrozen:
|
|
return "冻结"
|
|
default:
|
|
return "异常"
|
|
}
|
|
}
|
|
|
|
func (s Status) All() []Enum {
|
|
return []Enum{
|
|
StatusNormal,
|
|
StatusFrozen,
|
|
}
|
|
}
|
|
|
|
func (s Status) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(map[string]any{
|
|
"value": s.Value(),
|
|
"code": s.Code(),
|
|
"label": s.Label(),
|
|
})
|
|
}
|
|
|
|
type User struct {
|
|
Id uint64 `json:"id" gorm:"primaryKey;column:id"`
|
|
CreatedAt int64 `json:"created_at" gorm:"column:created_at;autoCreateTime:milli"`
|
|
UpdatedAt int64 `json:"updated_at" gorm:"column:updated_at;autoUpdateTime:milli"`
|
|
DeletedAt int64 `json:"deleted_at" gorm:"index;column:deleted_at;default:0"`
|
|
|
|
Username string `json:"username" gorm:"column:username;type:varchar(64);unique"`
|
|
Password string `json:"-" gorm:"column:password;type:varchar(256)"`
|
|
|
|
Status Status `json:"status" gorm:"column:status;default:0"`
|
|
|
|
Nickname string `json:"nickname" gorm:"column:nickname;type:varchar(64)"`
|
|
Comment string `json:"comment" gorm:"column:comment"`
|
|
|
|
Role Role `json:"role" gorm:"column:role"`
|
|
Privileges sqlType.NumSlice[Privilege] `json:"privileges" gorm:"column:privileges;type:bigint[]"`
|
|
|
|
CreatedById uint64 `json:"created_by_id" gorm:"column:created_by_id"`
|
|
CreatedByName string `json:"created_by_name" gorm:"column:created_by_name;type:varchar(64)"`
|
|
|
|
ActiveAt int64 `json:"active_at" gorm:"column:active_at"`
|
|
Deadline int64 `json:"deadline" gorm:"column:deadline"`
|
|
|
|
LoginAt int64 `json:"login_at" gorm:"-"`
|
|
}
|
|
|
|
func (u *User) CheckStatus(mustOk bool) error {
|
|
switch u.Status {
|
|
case StatusNormal:
|
|
case StatusFrozen:
|
|
if mustOk {
|
|
return errors.New("用户被冻结")
|
|
}
|
|
default:
|
|
return errors.New("用户状态未知")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (u *User) IsValid(mustOk bool) error {
|
|
now := time.Now()
|
|
|
|
if now.UnixMilli() >= u.Deadline {
|
|
return errors.New("用户已过期")
|
|
}
|
|
|
|
if now.UnixMilli() < u.ActiveAt {
|
|
return errors.New("用户未启用")
|
|
}
|
|
|
|
if u.DeletedAt > 0 {
|
|
return errors.New("用户不存在")
|
|
}
|
|
|
|
return u.CheckStatus(mustOk)
|
|
}
|
|
|
|
func (u *User) JwtEncode() (token string, err error) {
|
|
|
|
now := time.Now()
|
|
|
|
jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{
|
|
"id": u.Id,
|
|
"username": u.Username,
|
|
"status": u.Status,
|
|
"deadline": u.Deadline,
|
|
"login_at": now.UnixMilli(),
|
|
})
|
|
|
|
if token, err = jwtToken.SignedString([]byte(opt.JwtTokenSecret)); err != nil {
|
|
err = fmt.Errorf("JwtEncode: jwt token signed secret err: %v", err)
|
|
logrus.Error(err)
|
|
return "", nil
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (u *User) FromJwt(token string) *User {
|
|
var (
|
|
ok bool
|
|
err error
|
|
pt *jwt.Token
|
|
claims jwt.MapClaims
|
|
)
|
|
|
|
token = strings.TrimPrefix(token, "Bearer ")
|
|
|
|
if pt, err = jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {
|
|
if _, ok = t.Method.(*jwt.SigningMethodHMAC); !ok {
|
|
return nil, fmt.Errorf("unexpected signing method: %v", t.Header["alg"])
|
|
}
|
|
|
|
return []byte(opt.JwtTokenSecret), nil
|
|
}); err != nil {
|
|
logrus.Errorf("jwt parse err: %v", err)
|
|
return nil
|
|
}
|
|
|
|
if !pt.Valid {
|
|
logrus.Warn("parsed jwt invalid")
|
|
return nil
|
|
}
|
|
|
|
if claims, ok = pt.Claims.(jwt.MapClaims); !ok {
|
|
logrus.Error("convert jwt claims err")
|
|
return nil
|
|
}
|
|
|
|
u.Id = cast.ToUint64(claims["user_id"])
|
|
u.Username = cast.ToString(claims["username"])
|
|
u.Status = Status(cast.ToInt64(claims["status"]))
|
|
u.Deadline = cast.ToInt64(claims["deadline"])
|
|
u.LoginAt = cast.ToInt64(claims["login_at"])
|
|
|
|
return u
|
|
}
|
|
|
|
func (u User) MarshalBinary() ([]byte, error) {
|
|
return json.Marshal(map[string]any{
|
|
"id": u.Id,
|
|
"created_at": u.CreatedAt,
|
|
"updated_at": u.UpdatedAt,
|
|
"deleted_at": u.DeletedAt,
|
|
"username": u.Username,
|
|
"status": u.Status.Value(),
|
|
"nickname": u.Nickname,
|
|
"comment": u.Comment,
|
|
"role": uint8(u.Role),
|
|
"privileges": lo.Map(u.Privileges, func(item Privilege, index int) int64 {
|
|
return item.Value()
|
|
}),
|
|
"created_by_id": u.CreatedById,
|
|
"created_by_name": u.CreatedByName,
|
|
"active_at": u.ActiveAt,
|
|
"deadline": u.Deadline,
|
|
"login_at": u.LoginAt,
|
|
})
|
|
}
|