Files
go-nkode/core/nkode/customer.go
2024-08-26 13:10:34 -05:00

201 lines
5.6 KiB
Go

package nkode
import (
"errors"
"fmt"
"github.com/google/uuid"
m "go-nkode/core/model"
"go-nkode/hashset"
py "go-nkode/py-builtin"
"go-nkode/util"
)
type Customer struct {
Id m.CustomerId
NKodePolicy m.NKodePolicy
Attributes CustomerAttributes
}
func NewCustomer(nkodePolicy m.NKodePolicy) (*Customer, error) {
customerAttrs, err := NewCustomerAttributes()
if err != nil {
return nil, err
}
customer := Customer{
Id: m.CustomerId(uuid.New()),
NKodePolicy: nkodePolicy,
Attributes: *customerAttrs,
}
return &customer, nil
}
//func (c *Customer) AddNewUser(username m.Username, passcodeIdx []int, ui UserInterface, kp m.KeypadDimension) error {
// _, exists := c.Users[username]
// if exists {
// return errors.New(fmt.Sprintf("User %s already exists for customer %+v exists", username, c.Id))
// }
// setVals, err := c.Attributes.SetVals(kp)
// if err != nil {
// return err
// }
// newKeys, err := NewUserCipherKeys(&kp, setVals, c.NKodePolicy.MaxNkodeLen)
// if err != nil {
// return err
// }
// encipheredNKode, err := newKeys.EncipherNKode(passcodeIdx, c.Attributes)
// if err != nil {
// return err
// }
// newUser := User{
// Id: m.UserId(uuid.New()),
// Username: username,
// EncipheredPasscode: *encipheredNKode,
// UserKeys: *newKeys,
// Interface: ui,
// Kp: kp,
// }
// c.Users[username] = newUser
// return nil
//}
//func (c *Customer) ValidKeyEntry(username m.Username, selectedKeys []int) ([]int, error) {
// user, exists := c.Users[username]
// if !exists {
// return nil, errors.New(fmt.Sprintf("user %s does not exist for customer %+v", username, c.Id))
// }
//
// validKeys := py.All[int](selectedKeys, func(idx int) bool {
// return 0 <= idx && idx < user.Kp.NumbOfKeys
// })
// if !validKeys {
// return nil, errors.New(fmt.Sprintf("one or more keys not in range 0-%d", user.Kp.NumbOfKeys-1))
// }
// presumedAttrIdxVals, err := c.getPresumedAttributeIdxVals(user, selectedKeys)
// if err != nil {
// return nil, err
// }
// err = c.IsValidNKode(user.Kp, presumedAttrIdxVals)
// if err != nil {
// return nil, err
// }
// attrVals, err := c.Attributes.AttrVals(user.Kp)
// if err != nil {
// return nil, err
// }
// err = user.UserKeys.ValidPassword(user.EncipheredPasscode.Code, presumedAttrIdxVals, attrVals)
// if err != nil {
// return nil, err
// }
//
// return presumedAttrIdxVals, nil
//}
//func (c *Customer) getPresumedAttributeIdxVals(user User, selectedKeys []int) ([]int, error) {
//
// passcodeLen := len(selectedKeys)
// if passcodeLen < c.NKodePolicy.MinNkodeLen || passcodeLen > c.NKodePolicy.MaxNkodeLen {
// return nil, errors.New(fmt.Sprintf("Invalid passcode length of %d. Passcode length must be in range %d-%d", passcodeLen, c.NKodePolicy.MinNkodeLen, c.NKodePolicy.MaxNkodeLen))
// }
//
// setVals, err := c.Attributes.SetVals(user.Kp)
// if err != nil {
// return nil, err
// }
// passcodeSetVals, err := user.DecipherMask(setVals, passcodeLen)
// if err != nil {
// return nil, err
// }
// presumedAttrIdxVals := make([]int, passcodeLen)
//
// for idx := range presumedAttrIdxVals {
// keyNumb := selectedKeys[idx]
// setIdx, err := c.Attributes.IndexOfSet(passcodeSetVals[idx])
// if err != nil {
// return nil, err
// }
// selectedAttrIdx, err := user.Interface.GetAttrIdxByKeyNumbSetIdx(setIdx, keyNumb)
// if err != nil {
// return nil, err
// }
// presumedAttrIdxVals[idx] = selectedAttrIdx
// }
// return presumedAttrIdxVals, nil
//}
func (c *Customer) IsValidNKode(kp m.KeypadDimension, passcodeAttrIdx []int) error {
nkodeLen := len(passcodeAttrIdx)
if nkodeLen < c.NKodePolicy.MinNkodeLen {
return errors.New(fmt.Sprintf("NKode length %d is too short. Minimum nKode length is %d", nkodeLen, c.NKodePolicy.MinNkodeLen))
}
validIdx := py.All[int](passcodeAttrIdx, func(i int) bool {
return i >= 0 && i < kp.TotalAttrs()
})
if !validIdx {
return errors.New(fmt.Sprintf("One or more idx out of range 0-%d in IsValidNKode", kp.TotalAttrs()-1))
}
passcodeSetVals := make(hashset.Set[uint64])
passcodeAttrVals := make(hashset.Set[uint64])
attrVals, err := c.Attributes.AttrVals(kp)
if err != nil {
return err
}
for idx := 0; idx < nkodeLen; idx++ {
attrVal := attrVals[passcodeAttrIdx[idx]]
setVal, err := c.Attributes.GetAttrSetVal(attrVal, kp)
if err != nil {
return err
}
passcodeSetVals.Add(setVal)
passcodeAttrVals.Add(attrVal)
}
if passcodeSetVals.Size() < c.NKodePolicy.DistinctSets {
return errors.New(fmt.Sprintf("passcode has two few distinct sets min %d, has %d", c.NKodePolicy.DistinctSets, passcodeSetVals.Size()))
}
if passcodeAttrVals.Size() < c.NKodePolicy.DistinctAttributes {
return errors.New(fmt.Sprintf("passcode has two few distinct attributes min %d, has %d", c.NKodePolicy.DistinctAttributes, passcodeAttrVals.Size()))
}
return nil
}
func (c *Customer) RenewKeys() ([]uint64, []uint64) {
oldAttrs := make([]uint64, m.KeypadMax.TotalAttrs())
oldSets := make([]uint64, m.KeypadMax.AttrsPerKey)
allAttrVals, err := c.Attributes.AttrVals(m.KeypadMax)
if err != nil {
panic(err)
}
allSetVals, err := c.Attributes.AttrVals(m.KeypadMax)
if err != nil {
panic(err)
}
copy(oldAttrs, allAttrVals)
copy(oldSets, allSetVals)
err = c.Attributes.Renew()
if err != nil {
panic(err)
}
allAttrVals, err = c.Attributes.AttrVals(m.KeypadMax)
if err != nil {
panic(err)
}
allSetVals, err = c.Attributes.SetVals(m.KeypadMax)
if err != nil {
panic(err)
}
attrsXor, err := util.XorLists(oldAttrs, allAttrVals)
if err != nil {
panic(err)
}
setXor, err := util.XorLists(oldSets, allSetVals)
if err != nil {
panic(err)
}
return setXor, attrsXor
}