140 lines
3.3 KiB
Go
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
|
||
|
|
}
|