🎉: init project
This commit is contained in:
87
internal/model/init.go
Normal file
87
internal/model/init.go
Normal file
@ -0,0 +1,87 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/loveuer/nf/nft/log"
|
||||
"gorm.io/gorm"
|
||||
"strings"
|
||||
"ultone/internal/opt"
|
||||
"ultone/internal/sqlType"
|
||||
)
|
||||
|
||||
func Init(db *gorm.DB) error {
|
||||
var err error
|
||||
|
||||
if err = initModel(db); err != nil {
|
||||
return fmt.Errorf("model.MustInit: init models err=%v", err)
|
||||
}
|
||||
|
||||
log.Info("MustInitModels: auto_migrate privilege model success")
|
||||
|
||||
if err = initData(db); err != nil {
|
||||
return fmt.Errorf("model.MustInit: init datas err=%v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func initModel(client *gorm.DB) error {
|
||||
if err := client.AutoMigrate(
|
||||
&User{},
|
||||
&OpLog{},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info("InitModels: auto_migrate user model success")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func initData(client *gorm.DB) error {
|
||||
var (
|
||||
err error
|
||||
)
|
||||
|
||||
{
|
||||
count := 0
|
||||
|
||||
if err = client.Model(&User{}).Select("count(id)").Take(&count).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if count < len(initUsers) {
|
||||
log.Warn("mustInitDatas: user count = 0, start init...")
|
||||
for _, user := range initUsers {
|
||||
if err = client.Model(&User{}).Create(user).Error; err != nil {
|
||||
if !strings.Contains(err.Error(), "SQLSTATE 23505") {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if opt.Cfg.DB.Type == "postgresql" {
|
||||
if err = client.Exec(`SELECT setval('users_id_seq', (SELECT MAX(id) FROM users))`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("InitDatas: creat init users success")
|
||||
} else {
|
||||
ps := make(sqlType.NumSlice[Privilege], 0)
|
||||
for _, item := range Privilege(0).All() {
|
||||
ps = append(ps, item.(Privilege))
|
||||
}
|
||||
if err = client.Model(&User{}).Where("id = ?", initUsers[0].Id).
|
||||
Updates(map[string]any{
|
||||
"privileges": ps,
|
||||
}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info("initDatas: update init users success")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
17
internal/model/interface.go
Normal file
17
internal/model/interface.go
Normal file
@ -0,0 +1,17 @@
|
||||
package model
|
||||
|
||||
type Enum interface {
|
||||
Value() int64
|
||||
Code() string
|
||||
Label() string
|
||||
|
||||
MarshalJSON() ([]byte, error)
|
||||
|
||||
All() []Enum
|
||||
}
|
||||
|
||||
type OpLogger interface {
|
||||
Enum
|
||||
Render(content map[string]any) (string, error)
|
||||
Template() string
|
||||
}
|
294
internal/model/oplog.go
Normal file
294
internal/model/oplog.go
Normal file
@ -0,0 +1,294 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"github.com/spf13/cast"
|
||||
"github.com/tdewolff/minify/v2"
|
||||
"github.com/tdewolff/minify/v2/html"
|
||||
"html/template"
|
||||
"time"
|
||||
"ultone/internal/sqlType"
|
||||
)
|
||||
|
||||
var (
|
||||
FuncMap = template.FuncMap{
|
||||
"time_format": func(mil any, format string) string {
|
||||
return time.UnixMilli(cast.ToInt64(mil)).Format(format)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
_ OpLogger = (*OpLogType)(nil)
|
||||
)
|
||||
|
||||
type OpLogType uint64
|
||||
|
||||
const (
|
||||
OpLogTypeLogin OpLogType = iota + 1
|
||||
OpLogTypeLogout
|
||||
OpLogTypeCreateUser
|
||||
OpLogTypeUpdateUser
|
||||
OpLogTypeDeleteUser
|
||||
|
||||
// todo: 添加自己的操作日志 分类
|
||||
)
|
||||
|
||||
func (o OpLogType) Value() int64 {
|
||||
return int64(o)
|
||||
}
|
||||
|
||||
func (o OpLogType) Code() string {
|
||||
switch o {
|
||||
case OpLogTypeLogin:
|
||||
return "login"
|
||||
case OpLogTypeLogout:
|
||||
return "logout"
|
||||
case OpLogTypeCreateUser:
|
||||
return "create_user"
|
||||
case OpLogTypeUpdateUser:
|
||||
return "update_user"
|
||||
case OpLogTypeDeleteUser:
|
||||
return "delete_user"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func (o OpLogType) Label() string {
|
||||
switch o {
|
||||
case OpLogTypeLogin:
|
||||
return "登入"
|
||||
case OpLogTypeLogout:
|
||||
return "登出"
|
||||
case OpLogTypeCreateUser:
|
||||
return "创建用户"
|
||||
case OpLogTypeUpdateUser:
|
||||
return "修改用户"
|
||||
case OpLogTypeDeleteUser:
|
||||
return "删除用户"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
func (o OpLogType) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(map[string]any{
|
||||
"value": o.Value(),
|
||||
"code": o.Code(),
|
||||
"label": o.Label(),
|
||||
})
|
||||
}
|
||||
|
||||
func (o OpLogType) All() []Enum {
|
||||
return []Enum{
|
||||
OpLogTypeLogin,
|
||||
OpLogTypeLogout,
|
||||
OpLogTypeCreateUser,
|
||||
OpLogTypeUpdateUser,
|
||||
OpLogTypeDeleteUser,
|
||||
}
|
||||
}
|
||||
|
||||
func _trimHTML(v []byte) string {
|
||||
return base64.StdEncoding.EncodeToString(v)
|
||||
}
|
||||
|
||||
var (
|
||||
_mini = minify.New()
|
||||
)
|
||||
|
||||
func init() {
|
||||
_mini.AddFunc("text/html", html.Minify)
|
||||
}
|
||||
|
||||
func (o OpLogType) Render(content map[string]any) (string, error) {
|
||||
var (
|
||||
err error
|
||||
render *template.Template
|
||||
buf bytes.Buffer
|
||||
bs []byte
|
||||
)
|
||||
|
||||
if render, err = template.New(o.Code()).
|
||||
Funcs(FuncMap).
|
||||
Parse(o.Template()); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = render.Execute(&buf, content); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if bs, err = _mini.Bytes("text/html", buf.Bytes()); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return _trimHTML(bs), nil
|
||||
}
|
||||
|
||||
const (
|
||||
oplogTemplateLogin = `
|
||||
<div class="nf-op-log">
|
||||
用户
|
||||
<span
|
||||
class="nf-op-log-user nf-op-log-keyword"
|
||||
nf-op-log-user="{{ .user_id }}"
|
||||
>{{ .username }}
|
||||
</span>
|
||||
于
|
||||
<span
|
||||
class="nf-op-log-time nf-op-log-keyword"
|
||||
nf-op-log-time="{{ .time }}"
|
||||
>{{ time_format .time "2006-01-02 15:04:05" }}
|
||||
</span>
|
||||
在
|
||||
<span
|
||||
class="nf-op-log-ip nf-op-log-keyword"
|
||||
>{{ .ip }}
|
||||
</span>
|
||||
上
|
||||
<span
|
||||
class="nf-op-log-op nf-op-log-keyword"
|
||||
>
|
||||
登入
|
||||
</span>
|
||||
了系统
|
||||
</div>
|
||||
`
|
||||
oplogTemplateLogout = `
|
||||
<div class="nf-op-log">
|
||||
用户
|
||||
<span
|
||||
class="nf-op-log-user nf-op-log-keyword"
|
||||
nf-op-log-user="{{ .user_id }}"
|
||||
>{{ .username }}
|
||||
</span>
|
||||
于
|
||||
<span
|
||||
class="nf-op-log-time nf-op-log-keyword"
|
||||
nf-op-log-time="{{ .time }}"
|
||||
>{{ time_format .time "2006-01-02 15:04:05" }}
|
||||
</span>
|
||||
在
|
||||
<span
|
||||
class="nf-op-log-ip nf-op-log-keyword"
|
||||
>{{ .ip }}
|
||||
</span>
|
||||
上
|
||||
<span
|
||||
class="nf-op-log-op nf-op-log-keyword"
|
||||
>
|
||||
登出
|
||||
</span>
|
||||
了系统
|
||||
</div>
|
||||
`
|
||||
oplogTemplateCreateUser = `
|
||||
<div class="nf-op-log">
|
||||
用户
|
||||
<span
|
||||
class="nf-op-log-user nf-op-log-keyword"
|
||||
nf-op-log-user="{{ .user_id }}"
|
||||
>{{ .username }}
|
||||
</span>
|
||||
于
|
||||
<span
|
||||
class="nf-op-log-time nf-op-log-keyword"
|
||||
nf-op-log-time="{{ .time }}"
|
||||
>{{ time_format .time "2006-01-02 15:04:05" }}
|
||||
</span>
|
||||
<span class="nf-op-log-keyword">
|
||||
创建
|
||||
</span>
|
||||
了用户
|
||||
<span
|
||||
class="nf-op-log-target nf-op-log-keyword"
|
||||
nf-op-log-target="{{ .target_id }}"
|
||||
>{{ .target_username }}
|
||||
</span>
|
||||
</div>
|
||||
`
|
||||
oplogTemplateUpdateUser = `
|
||||
<div class="nf-op-log">
|
||||
用户
|
||||
<span
|
||||
class="nf-op-log-user nf-op-log-keyword"
|
||||
nf-op-log-user='{{ .user_id }}'
|
||||
>{{ .username }}
|
||||
</span>
|
||||
于
|
||||
<span
|
||||
class="nf-op-log-time nf-op-log-keyword"
|
||||
nf-op-log-time='{{ .time }}'
|
||||
>{{ time_format .time "2006-01-02 15:04:05" }}
|
||||
</span>
|
||||
<span class="nf-op-log-keyword">
|
||||
编辑
|
||||
</span>
|
||||
了用户
|
||||
<span
|
||||
class="nf-op-log-target nf-op-log-keyword"
|
||||
nf-op-log-target="{{ .target_id }}"
|
||||
>{{ .target_username }}
|
||||
</span>
|
||||
</div>
|
||||
`
|
||||
oplogTemplateDeleteUser = `
|
||||
<div class="nf-op-log">
|
||||
用户
|
||||
<span
|
||||
class="nf-op-log-user nf-op-log-keyword"
|
||||
nf-op-log-user="{{ .user_id }}"
|
||||
>{{ .username }}
|
||||
</span>
|
||||
于
|
||||
<span
|
||||
class="nf-op-log-time nf-op-log-keyword"
|
||||
nf-op-log-time="{{ .time }}"
|
||||
>{{ time_format .time "2006-01-02 15:04:05" }}
|
||||
</span>
|
||||
<span class="nf-op-log-keyword">
|
||||
删除
|
||||
</span>
|
||||
了用户
|
||||
<span
|
||||
class="nf-op-log-target nf-op-log-keyword"
|
||||
nf-op-log-target="{{ .target_id }}"
|
||||
>{{ .target_username }}
|
||||
</span>
|
||||
</div>
|
||||
`
|
||||
)
|
||||
|
||||
func (o OpLogType) Template() string {
|
||||
switch o {
|
||||
case OpLogTypeLogin:
|
||||
return oplogTemplateLogin
|
||||
case OpLogTypeLogout:
|
||||
return oplogTemplateLogout
|
||||
case OpLogTypeCreateUser:
|
||||
return oplogTemplateCreateUser
|
||||
case OpLogTypeUpdateUser:
|
||||
return oplogTemplateUpdateUser
|
||||
case OpLogTypeDeleteUser:
|
||||
return oplogTemplateDeleteUser
|
||||
default:
|
||||
return `<div>错误的日志类型</div>`
|
||||
}
|
||||
}
|
||||
|
||||
type OpLog 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"`
|
||||
|
||||
UserId uint64 `json:"user_id" gorm:"column:user_id"`
|
||||
Username string `json:"username" gorm:"column:username;varchar(128)"`
|
||||
Type OpLogType `json:"type" gorm:"column:type;type:varchar(128)"`
|
||||
Content sqlType.JSONB `json:"content" gorm:"column:content;type:jsonb"`
|
||||
HTML string `json:"html" gorm:"-"`
|
||||
}
|
61
internal/model/privilege.go
Normal file
61
internal/model/privilege.go
Normal file
@ -0,0 +1,61 @@
|
||||
package model
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type Privilege uint64
|
||||
|
||||
type _privilege struct {
|
||||
Value int64 `json:"value"`
|
||||
Code string `json:"code"`
|
||||
Label string `json:"label"`
|
||||
}
|
||||
|
||||
const (
|
||||
PrivilegeUserManage Privilege = iota + 1
|
||||
PrivilegeOpLog
|
||||
)
|
||||
|
||||
func (p Privilege) Value() int64 {
|
||||
return int64(p)
|
||||
}
|
||||
|
||||
func (p Privilege) Code() string {
|
||||
switch p {
|
||||
case PrivilegeUserManage:
|
||||
return "user_manage"
|
||||
case PrivilegeOpLog:
|
||||
return "oplog"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func (p Privilege) Label() string {
|
||||
switch p {
|
||||
case PrivilegeUserManage:
|
||||
return "用户管理"
|
||||
case PrivilegeOpLog:
|
||||
return "操作日志"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
func (p Privilege) MarshalJSON() ([]byte, error) {
|
||||
_p := &_privilege{
|
||||
Value: int64(p),
|
||||
Code: p.Code(),
|
||||
Label: p.Label(),
|
||||
}
|
||||
|
||||
return json.Marshal(_p)
|
||||
}
|
||||
|
||||
func (p Privilege) All() []Enum {
|
||||
return []Enum{
|
||||
PrivilegeUserManage,
|
||||
PrivilegeOpLog,
|
||||
}
|
||||
}
|
||||
|
||||
var _ Enum = (*Privilege)(nil)
|
85
internal/model/role.go
Normal file
85
internal/model/role.go
Normal file
@ -0,0 +1,85 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"gorm.io/gorm"
|
||||
"ultone/internal/opt"
|
||||
)
|
||||
|
||||
type _role struct {
|
||||
Value uint8 `json:"value"`
|
||||
Code string `json:"code"`
|
||||
Label string `json:"label"`
|
||||
}
|
||||
|
||||
type Role uint8
|
||||
|
||||
var _ Enum = Role(0)
|
||||
|
||||
func (u Role) MarshalJSON() ([]byte, error) {
|
||||
m := _role{
|
||||
Value: uint8(u),
|
||||
Code: u.Code(),
|
||||
Label: u.Label(),
|
||||
}
|
||||
return json.Marshal(m)
|
||||
}
|
||||
|
||||
const (
|
||||
RoleRoot Role = 255
|
||||
RoleAdmin Role = 254
|
||||
RoleUser Role = 100
|
||||
)
|
||||
|
||||
func (u Role) Code() string {
|
||||
switch u {
|
||||
case RoleRoot:
|
||||
return "root"
|
||||
case RoleAdmin:
|
||||
return "admin"
|
||||
case RoleUser:
|
||||
return "user"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func (u Role) Label() string {
|
||||
switch u {
|
||||
case RoleRoot:
|
||||
return "根用户"
|
||||
case RoleAdmin:
|
||||
return "管理员"
|
||||
case RoleUser:
|
||||
return "用户"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
func (u Role) Value() int64 {
|
||||
return int64(u)
|
||||
}
|
||||
|
||||
func (u Role) All() []Enum {
|
||||
return []Enum{
|
||||
RoleAdmin,
|
||||
RoleUser,
|
||||
}
|
||||
}
|
||||
|
||||
func (u Role) Where(db *gorm.DB) *gorm.DB {
|
||||
if opt.RoleMustLess {
|
||||
return db.Where("users.role < ?", u.Value())
|
||||
} else {
|
||||
return db.Where("users.role <= ?", u.Value())
|
||||
}
|
||||
}
|
||||
|
||||
func (u Role) CanOP(op *User) bool {
|
||||
if opt.RoleMustLess {
|
||||
return op.Role > u
|
||||
}
|
||||
|
||||
return op.Role >= u
|
||||
}
|
226
internal/model/user.go
Normal file
226
internal/model/user.go
Normal file
@ -0,0 +1,226 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/loveuer/nf/nft/log"
|
||||
"github.com/samber/lo"
|
||||
"github.com/spf13/cast"
|
||||
"strings"
|
||||
"time"
|
||||
"ultone/internal/opt"
|
||||
"ultone/internal/sqlType"
|
||||
"ultone/internal/tool"
|
||||
)
|
||||
|
||||
var (
|
||||
initUsers = []*User{
|
||||
{
|
||||
Id: 1,
|
||||
Username: "admin",
|
||||
Password: tool.NewPassword("123456"),
|
||||
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(),
|
||||
},
|
||||
}
|
||||
|
||||
_ 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)
|
||||
log.Error(err.Error())
|
||||
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 {
|
||||
log.Error("jwt parse err: %v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
if !pt.Valid {
|
||||
log.Warn("parsed jwt invalid")
|
||||
return nil
|
||||
}
|
||||
|
||||
if claims, ok = pt.Claims.(jwt.MapClaims); !ok {
|
||||
log.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,
|
||||
})
|
||||
}
|
Reference in New Issue
Block a user