package data import ( "crypto/rand" "encoding/base64" "encoding/json" "errors" "nixcn-cms/internal/cryptography" "strings" "github.com/google/uuid" "github.com/spf13/viper" "gorm.io/datatypes" ) type Client struct { Id uint `json:"id" gorm:"primaryKey;autoIncrement"` UUID uuid.UUID `json:"uuid" gorm:"type:uuid;uniqueIndex;not null"` ClientId string `json:"client_id" gorm:"type:varchar(255);uniqueIndex;not null"` ClientSecret string `json:"client_secret" gorm:"type:varchar(255);not null"` ClientName string `json:"client_name" gorm:"type:varchar(255);uniqueIndex;not null"` RedirectUri datatypes.JSON `json:"redirect_uri" gorm:"type:json;not null"` } func (self *Client) GetClientByClientId(clientId string) (*Client, error) { var client Client if err := Database. Where("client_id = ?", clientId). First(&client).Error; err != nil { return nil, err } return &client, nil } func (self *Client) GetDecryptedSecret() (string, error) { secretKey := viper.GetString("secrets.client_secret_key") secret, err := cryptography.AESCBCDecrypt(self.ClientSecret, []byte(secretKey)) return string(secret), err } type ClientParams struct { ClientId string ClientName string RedirectUri []string } func (self *Client) Create(params *ClientParams) (*Client, error) { jsonRedirectUri, err := json.Marshal(params.RedirectUri) if err != nil { return nil, err } encKey := viper.GetString("secrets.client_secret_key") b := make([]byte, 32) if _, err := rand.Read(b); err != nil { return nil, err } clientSecret := base64.RawURLEncoding.EncodeToString(b) encryptedSecret, err := cryptography.AESCBCEncrypt([]byte(clientSecret), []byte(encKey)) if err != nil { return nil, err } client := &Client{ UUID: uuid.New(), ClientId: params.ClientId, ClientSecret: encryptedSecret, ClientName: params.ClientName, RedirectUri: jsonRedirectUri, } if err := Database.Create(&client).Error; err != nil { return nil, err } return client, nil } func (self *Client) ValidateRedirectURI(redirectURI string) error { var uris []string if err := json.Unmarshal(self.RedirectUri, &uris); err != nil { return err } for _, prefix := range uris { if strings.HasPrefix(redirectURI, prefix) { return nil } } return errors.New("redirect uri not match") }