// Copyright (C) 2023 Marius Schellenberger package schema import ( "cmp" "encoding/hex" "errors" "fmt" "slices" "git.giftfish.de/ston1th/keyctl/pkg/api/types" "git.giftfish.de/ston1th/keyctl/pkg/core" ) const ( Version = "v1" KeyName = "key" ReqName = "req" KeyPath = "/" + Version + "/" + KeyName ReqPath = "/" + Version + "/" + ReqName ) type NewKey struct { Name string `json:"name"` Existing string `json:"existing,omitempty"` Size int `json:"size"` Encoding core.Encoding `json:"encoding"` Type core.Type `json:"type"` } var ( ErrEmptyKeyName = errors.New("empty key name") ErrExistingKeyType = errors.New("invalid key type for existing key") ErrExistingKeyEncoding = errors.New("invalid key encoding for existing key") ErrInvalidKeyName = errors.New("invalid key name") ErrInvalidKeySize = errors.New("invalid key size") ) const ( MinKeySize = 1 MaxKeySize = 1024 ) func (nk NewKey) Validate() error { if nk.Name == "" { return ErrEmptyKeyName } if nk.Existing != "" { if nk.Type == core.Xor { return ErrExistingKeyType } _, err := hex.DecodeString(nk.Existing) if err != nil { return ErrExistingKeyEncoding } } if core.NameRe.MatchString(nk.Name) { return ErrInvalidKeyName } if nk.Size > MaxKeySize || nk.Size < MinKeySize { return ErrInvalidKeySize } return nil } func ApproveURL(id, aid string) string { return KeyPath + "/" + id + "/" + aid } type Key struct { ID string `json:"id"` Name string `json:"name"` Size int `json:"size"` Encoding core.Encoding `json:"encoding"` Type core.Type `json:"type"` Key string `json:"key,omitempty"` } func (k Key) Print(share string) (string, error) { switch k.Type { case core.Shamir: part1, err := k.Encoding.Decode(k.Key) if err != nil { return "", err } part2, err := hex.DecodeString(share) if err != nil { return "", err } dec, err := k.Type.Decode(append(part1, part2...)) if err != nil { return "", err } return k.Encoding.EncodeToString(dec), nil } return k.Key, nil } type Keys []Key func (Keys) Less(a, b Key) int { return cmp.Compare(a.Name, b.Name) } func (k Keys) Sort() { slices.SortStableFunc(k, k.Less) } func (k Keys) Len() int { return len(k) } func (k Keys) Fields() string { return "Key ID\t Name\t Size\t Encoding\t Type" } func (k Keys) Values() []string { vals := make([]string, len(k)) for i, v := range k { vals[i] = fmt.Sprintf("%s\t %s\t %d\t %s\t %s", v.ID, v.Name, v.Size, v.Encoding, v.Type, ) } return vals } func NewKeys(keys core.Keys) (k Keys) { for _, key := range keys { k = append(k, Key(key)) } k.Sort() return } type Approval struct { ID string `json:"id"` AID string `json:"aid"` Name string `json:"name"` IP string `json:"ip"` Status types.Status `json:"status"` } type Approvals []Approval func (Approvals) Less(a, b Approval) int { return cmp.Compare(a.Name, b.Name) } func (a Approvals) Sort() { slices.SortStableFunc(a, a.Less) } func (a Approvals) Len() int { return len(a) } func (a Approvals) Fields() string { return "Key ID\t Approval ID\t Name\t Status\t IP" } func (a Approvals) Values() []string { vals := make([]string, len(a)) for i, v := range a { vals[i] = fmt.Sprintf("%s\t %s\t %s\t %s\t %s", v.ID, v.AID, v.Name, v.Status, v.IP, ) } return vals } func NewApprovals(m types.ApprovalMap) (a Approvals) { for k, v := range m { a = append(a, Approval{ ID: v.ID, AID: k, Name: v.Name, IP: v.IP, Status: v.Status, }) } a.Sort() return }