Files
license/sdk/licence/types.go
2026-07-31 16:59:55 +08:00

140 lines
3.3 KiB
Go

package licence
import (
"bytes"
"encoding/json"
"errors"
"time"
)
const dateLayout = "2006-01-02"
var (
shanghaiLocation, shanghaiLocationErr = time.LoadLocationFromTZData("Asia/Shanghai", shanghaiTZData[:])
)
type Subject struct {
PlatformName string `json:"platform_name"`
Workspace string `json:"workspace"`
}
type Quotas struct {
MaxDatabase int64 `json:"max_database"`
MaxMiddleware int64 `json:"max_middleware"`
MaxNetworkDevice int64 `json:"max_network_device"`
MaxSecurity int64 `json:"max_security"`
MaxStorage int64 `json:"max_storage"`
MaxPC int64 `json:"max_pc"`
MaxServer int64 `json:"max_server"`
MaxUser int64 `json:"max_user"`
MaxRole int64 `json:"max_role"`
MaxPermission int64 `json:"max_permission"`
MaxMenu int64 `json:"max_menu"`
}
// Date 表示 Asia/Shanghai 时区内的一个自然日。
type Date struct {
value string
}
func ParseDate(value string) (Date, error) {
if _, err := parseDateTime(value); err != nil {
return Date{}, err
}
return Date{value: value}, nil
}
func NewDate(value time.Time) (Date, error) {
location, err := locationShanghai()
if err != nil {
return Date{}, err
}
return ParseDate(value.In(location).Format(dateLayout))
}
func (d Date) String() string {
return d.value
}
func (d Date) Time() (time.Time, error) {
return parseDateTime(d.value)
}
func (d Date) MarshalJSON() ([]byte, error) {
if _, err := d.Time(); err != nil {
return nil, err
}
return json.Marshal(d.value)
}
func (d *Date) UnmarshalJSON(data []byte) error {
if d == nil {
return errors.New("日期接收者不能为空")
}
if bytes.Equal(bytes.TrimSpace(data), []byte("null")) {
return errors.New("日期必须是字符串")
}
var value string
if err := json.Unmarshal(data, &value); err != nil {
return errors.New("日期必须是字符串")
}
parsed, err := ParseDate(value)
if err != nil {
return err
}
*d = parsed
return nil
}
func locationShanghai() (*time.Location, error) {
if shanghaiLocationErr != nil {
return nil, errors.New("加载 Asia/Shanghai 时区失败")
}
return shanghaiLocation, nil
}
func parseDateTime(value string) (time.Time, error) {
if len(value) != len(dateLayout) || value[4] != '-' || value[7] != '-' {
return time.Time{}, errors.New("日期格式必须为 YYYY-MM-DD")
}
for index := range value {
if index == 4 || index == 7 {
continue
}
if value[index] < '0' || value[index] > '9' {
return time.Time{}, errors.New("日期格式必须为 YYYY-MM-DD")
}
}
location, err := locationShanghai()
if err != nil {
return time.Time{}, err
}
parsed, err := time.ParseInLocation(dateLayout, value, location)
if err != nil || parsed.Year() < 1 || parsed.Format(dateLayout) != value {
return time.Time{}, errors.New("日期不是有效的自然日")
}
return parsed, nil
}
type Claims struct {
ID string `json:"id"`
PlatformName string `json:"platform_name"`
Workspace string `json:"workspace"`
IssuedOn Date `json:"issued_on"`
ValidFrom Date `json:"valid_from"`
ExpiresOn Date `json:"expires_on"`
Quotas Quotas `json:"quotas"`
SigningKeyID string `json:"signing_key_id"`
}
type Licence struct {
ID string
Subject Subject
IssuedOn time.Time
ValidFrom time.Time
ExpiresOn time.Time
Quotas Quotas
}