dev: rbac
This commit is contained in:
parent
9e8a47a7c6
commit
58fae2e090
9
internal/sqlType/error.go
Normal file
9
internal/sqlType/error.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package sqlType
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrConvertScanVal = errors.New("convert scan val to str err")
|
||||||
|
ErrInvalidScanVal = errors.New("scan val invalid")
|
||||||
|
ErrConvertVal = errors.New("convert err")
|
||||||
|
)
|
76
internal/sqlType/jsonb.go
Normal file
76
internal/sqlType/jsonb.go
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package sqlType
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql/driver"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/jackc/pgtype"
|
||||||
|
)
|
||||||
|
|
||||||
|
type JSONB struct {
|
||||||
|
Val pgtype.JSONB
|
||||||
|
Valid bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewJSONB(v interface{}) JSONB {
|
||||||
|
j := new(JSONB)
|
||||||
|
j.Val = pgtype.JSONB{}
|
||||||
|
if err := j.Val.Set(v); err == nil {
|
||||||
|
j.Valid = true
|
||||||
|
return *j
|
||||||
|
}
|
||||||
|
|
||||||
|
return *j
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *JSONB) Set(value interface{}) error {
|
||||||
|
if err := j.Val.Set(value); err != nil {
|
||||||
|
j.Valid = false
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
j.Valid = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *JSONB) Bind(model interface{}) error {
|
||||||
|
return j.Val.AssignTo(model)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *JSONB) Scan(value interface{}) error {
|
||||||
|
j.Val = pgtype.JSONB{}
|
||||||
|
if value == nil {
|
||||||
|
j.Valid = false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
j.Valid = true
|
||||||
|
|
||||||
|
return j.Val.Scan(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j JSONB) Value() (driver.Value, error) {
|
||||||
|
if j.Valid {
|
||||||
|
return j.Val.Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j JSONB) MarshalJSON() ([]byte, error) {
|
||||||
|
if j.Valid {
|
||||||
|
return j.Val.MarshalJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *JSONB) UnmarshalJSON(b []byte) error {
|
||||||
|
if string(b) == "null" {
|
||||||
|
j.Valid = false
|
||||||
|
return j.Val.UnmarshalJSON(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
return j.Val.UnmarshalJSON(b)
|
||||||
|
}
|
71
internal/sqlType/num_slice.go
Normal file
71
internal/sqlType/num_slice.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package sqlType
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql/driver"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cast"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NumSlice[T ~int | ~int64 | ~uint | ~uint64] []T
|
||||||
|
|
||||||
|
func (n *NumSlice[T]) Scan(val interface{}) error {
|
||||||
|
str, ok := val.(string)
|
||||||
|
if !ok {
|
||||||
|
return ErrConvertScanVal
|
||||||
|
}
|
||||||
|
|
||||||
|
length := len(str)
|
||||||
|
|
||||||
|
if length <= 0 {
|
||||||
|
*n = make(NumSlice[T], 0)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if str[0] != '{' || str[length-1] != '}' {
|
||||||
|
return ErrInvalidScanVal
|
||||||
|
}
|
||||||
|
|
||||||
|
str = str[1 : length-1]
|
||||||
|
if len(str) == 0 {
|
||||||
|
*n = make(NumSlice[T], 0)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
numStrs := strings.Split(str, ",")
|
||||||
|
nums := make([]T, len(numStrs))
|
||||||
|
|
||||||
|
for idx := range numStrs {
|
||||||
|
num, err := cast.ToInt64E(strings.TrimSpace(numStrs[idx]))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%w: can't convert to %T", ErrConvertVal, T(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
nums[idx] = T(num)
|
||||||
|
}
|
||||||
|
|
||||||
|
*n = nums
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n NumSlice[T]) Value() (driver.Value, error) {
|
||||||
|
if n == nil {
|
||||||
|
return "{}", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(n) == 0 {
|
||||||
|
return "{}", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ss := make([]string, 0, len(n))
|
||||||
|
for idx := range n {
|
||||||
|
ss = append(ss, strconv.Itoa(int(n[idx])))
|
||||||
|
}
|
||||||
|
|
||||||
|
s := strings.Join(ss, ", ")
|
||||||
|
|
||||||
|
return fmt.Sprintf("{%s}", s), nil
|
||||||
|
}
|
107
internal/sqlType/string_slice.go
Normal file
107
internal/sqlType/string_slice.go
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package sqlType
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"database/sql/driver"
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StrSlice []string
|
||||||
|
|
||||||
|
func (s *StrSlice) Scan(val interface{}) error {
|
||||||
|
|
||||||
|
str, ok := val.(string)
|
||||||
|
if !ok {
|
||||||
|
return ErrConvertScanVal
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(str) < 2 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
bs := make([]byte, 0, 128)
|
||||||
|
bss := make([]byte, 0, 2*len(str))
|
||||||
|
|
||||||
|
quoteCount := 0
|
||||||
|
|
||||||
|
for idx := 1; idx < len(str)-1; idx++ {
|
||||||
|
quote := str[idx]
|
||||||
|
switch quote {
|
||||||
|
case 44:
|
||||||
|
if quote == 44 && str[idx-1] != 92 && quoteCount == 0 {
|
||||||
|
if len(bs) > 0 {
|
||||||
|
if !(bs[0] == 34 && bs[len(bs)-1] == 34) {
|
||||||
|
bs = append([]byte{34}, bs...)
|
||||||
|
bs = append(bs, 34)
|
||||||
|
}
|
||||||
|
|
||||||
|
bss = append(bss, bs...)
|
||||||
|
bss = append(bss, 44)
|
||||||
|
}
|
||||||
|
bs = bs[:0]
|
||||||
|
} else {
|
||||||
|
bs = append(bs, quote)
|
||||||
|
}
|
||||||
|
case 34:
|
||||||
|
if str[idx-1] != 92 {
|
||||||
|
quoteCount = (quoteCount + 1) % 2
|
||||||
|
}
|
||||||
|
bs = append(bs, quote)
|
||||||
|
default:
|
||||||
|
bs = append(bs, quote)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(bs) > 0 {
|
||||||
|
if !(bs[0] == 34 && bs[len(bs)-1] == 34) {
|
||||||
|
bs = append([]byte{34}, bs...)
|
||||||
|
bs = append(bs, 34)
|
||||||
|
}
|
||||||
|
|
||||||
|
bss = append(bss, bs...)
|
||||||
|
} else {
|
||||||
|
if len(bss) > 2 {
|
||||||
|
bss = bss[:len(bss)-2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bss = append([]byte{'['}, append(bss, ']')...)
|
||||||
|
|
||||||
|
if err := json.Unmarshal(bss, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s StrSlice) Value() (driver.Value, error) {
|
||||||
|
if s == nil {
|
||||||
|
return "{}", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s) == 0 {
|
||||||
|
return "{}", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
|
||||||
|
encoder := json.NewEncoder(buf)
|
||||||
|
encoder.SetEscapeHTML(false)
|
||||||
|
|
||||||
|
if err := encoder.Encode(s); err != nil {
|
||||||
|
return "{}", err
|
||||||
|
}
|
||||||
|
|
||||||
|
bs := buf.Bytes()
|
||||||
|
|
||||||
|
bs[0] = '{'
|
||||||
|
|
||||||
|
if bs[len(bs)-1] == 10 {
|
||||||
|
bs = bs[:len(bs)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
bs[len(bs)-1] = '}'
|
||||||
|
|
||||||
|
return string(bs), nil
|
||||||
|
}
|
11
model/privilege.go
Normal file
11
model/privilege.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type Privilege struct {
|
||||||
|
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"`
|
||||||
|
Code string `json:"code" gorm:"column:code;primaryKey"`
|
||||||
|
Label string `json:"label" gorm:"column:label"`
|
||||||
|
Parent string `json:"parent" gorm:"column:parent"`
|
||||||
|
Scope string `json:"scope" gorm:"column:scope"`
|
||||||
|
}
|
13
model/role.go
Normal file
13
model/role.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import "uauth/internal/sqlType"
|
||||||
|
|
||||||
|
type Role struct {
|
||||||
|
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"`
|
||||||
|
Code string `json:"code" gorm:"primaryKey;column:code"`
|
||||||
|
Label string `json:"label" gorm:"column:label"`
|
||||||
|
Parent string `json:"parent" gorm:"column:parent"`
|
||||||
|
PrivilegeCodes sqlType.StrSlice `json:"privilege_codes" gorm:"column:privilege_codes"`
|
||||||
|
}
|
11
model/scope.go
Normal file
11
model/scope.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
// 用户权限作用域
|
||||||
|
type Scope struct {
|
||||||
|
Code string `json:"code" gorm:"column:code;type:varchar(8);not null;primaryKey"`
|
||||||
|
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"`
|
||||||
|
Label string `json:"label" gorm:"column:label;type:varchar(64)"`
|
||||||
|
Parent string `json:"parent" gorm:"column:parent;type:varchar(8)"`
|
||||||
|
}
|
@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/loveuer/nf/nft/log"
|
"github.com/loveuer/nf/nft/log"
|
||||||
"time"
|
"time"
|
||||||
"uauth/internal/opt"
|
"uauth/internal/opt"
|
||||||
|
"uauth/internal/sqlType"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Status int64
|
type Status int64
|
||||||
@ -29,6 +30,9 @@ type User struct {
|
|||||||
CreatedByName string `json:"created_by_name" gorm:"column:created_by_name;type:varchar(64)"`
|
CreatedByName string `json:"created_by_name" gorm:"column:created_by_name;type:varchar(64)"`
|
||||||
|
|
||||||
LoginAt int64 `json:"login_at" gorm:"-"`
|
LoginAt int64 `json:"login_at" gorm:"-"`
|
||||||
|
|
||||||
|
Roles []*Role `json:"-" gorm:"-"`
|
||||||
|
RoleNames sqlType.StrSlice `json:"role_names" column:"role_names"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) JwtEncode() (token string, err error) {
|
func (u *User) JwtEncode() (token string, err error) {
|
||||||
@ -40,6 +44,7 @@ func (u *User) JwtEncode() (token string, err error) {
|
|||||||
"username": u.Username,
|
"username": u.Username,
|
||||||
"nickname": u.Nickname,
|
"nickname": u.Nickname,
|
||||||
"status": u.Status,
|
"status": u.Status,
|
||||||
|
"avatar": u.Avatar,
|
||||||
"login_at": now.UnixMilli(),
|
"login_at": now.UnixMilli(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user