refactor db accessor
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
package m
|
package m
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
type NKodePolicy struct {
|
type NKodePolicy struct {
|
||||||
MaxNkodeLen int `json:"max_nkode_len"`
|
MaxNkodeLen int `json:"max_nkode_len"`
|
||||||
MinNkodeLen int `json:"min_nkode_len"`
|
MinNkodeLen int `json:"min_nkode_len"`
|
||||||
@@ -19,3 +23,13 @@ func NewDefaultNKodePolicy() NKodePolicy {
|
|||||||
Expiration: -1,
|
Expiration: -1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var InvalidNKodeLen = errors.New("invalid nkode length")
|
||||||
|
|
||||||
|
func (p *NKodePolicy) ValidLength(nkodeLen int) error {
|
||||||
|
|
||||||
|
if nkodeLen < p.MinNkodeLen || nkodeLen > p.MaxNkodeLen {
|
||||||
|
return InvalidNKodeLen
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ type GetLoginInterfaceResp struct {
|
|||||||
type KeySelection []int
|
type KeySelection []int
|
||||||
type CustomerId uuid.UUID
|
type CustomerId uuid.UUID
|
||||||
type SessionId uuid.UUID
|
type SessionId uuid.UUID
|
||||||
|
type UserId uuid.UUID
|
||||||
|
|
||||||
type Username string
|
type Username string
|
||||||
type IdxInterface []int
|
type IdxInterface []int
|
||||||
|
|
||||||
|
|||||||
89
core/nkode/common.go
Normal file
89
core/nkode/common.go
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
package nkode
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
m "go-nkode/core/model"
|
||||||
|
py "go-nkode/py-builtin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var KeyIndexOutOfRange error = errors.New("one or more keys is out of range")
|
||||||
|
|
||||||
|
func ValidKeyEntry(user User, customer Customer, selectedKeys []int) ([]int, error) {
|
||||||
|
validKeys := py.All[int](selectedKeys, func(idx int) bool {
|
||||||
|
return 0 <= idx && idx < user.Kp.NumbOfKeys
|
||||||
|
})
|
||||||
|
if !validKeys {
|
||||||
|
panic(KeyIndexOutOfRange)
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
passcodeLen := len(selectedKeys)
|
||||||
|
err = customer.NKodePolicy.ValidLength(passcodeLen)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
setVals, err := customer.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 := customer.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
|
||||||
|
}
|
||||||
|
err = customer.IsValidNKode(user.Kp, presumedAttrIdxVals)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
attrVals, err := customer.Attributes.AttrVals(user.Kp)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = user.UserKeys.ValidPassword(user.EncipheredPasscode.Code, presumedAttrIdxVals, attrVals)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return presumedAttrIdxVals, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUser(customer Customer, username m.Username, passcodeIdx []int, ui UserInterface, kp m.KeypadDimension) (*User, error) {
|
||||||
|
setVals, err := customer.Attributes.SetVals(kp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
newKeys, err := NewUserCipherKeys(&kp, setVals, customer.NKodePolicy.MaxNkodeLen)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
encipheredNKode, err := newKeys.EncipherNKode(passcodeIdx, customer.Attributes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
newUser := User{
|
||||||
|
Id: m.UserId(uuid.New()),
|
||||||
|
Username: username,
|
||||||
|
EncipheredPasscode: *encipheredNKode,
|
||||||
|
UserKeys: *newKeys,
|
||||||
|
Interface: ui,
|
||||||
|
Kp: kp,
|
||||||
|
CustomerId: customer.Id,
|
||||||
|
}
|
||||||
|
return &newUser, nil
|
||||||
|
}
|
||||||
@@ -11,10 +11,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Customer struct {
|
type Customer struct {
|
||||||
CustomerId m.CustomerId
|
Id m.CustomerId
|
||||||
NKodePolicy m.NKodePolicy
|
NKodePolicy m.NKodePolicy
|
||||||
Attributes CustomerAttributes
|
Attributes CustomerAttributes
|
||||||
Users map[m.Username]User
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCustomer(nkodePolicy m.NKodePolicy) (*Customer, error) {
|
func NewCustomer(nkodePolicy m.NKodePolicy) (*Customer, error) {
|
||||||
@@ -23,106 +22,106 @@ func NewCustomer(nkodePolicy m.NKodePolicy) (*Customer, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
customer := Customer{
|
customer := Customer{
|
||||||
CustomerId: m.CustomerId(uuid.New()),
|
Id: m.CustomerId(uuid.New()),
|
||||||
NKodePolicy: nkodePolicy,
|
NKodePolicy: nkodePolicy,
|
||||||
Attributes: *customerAttrs,
|
Attributes: *customerAttrs,
|
||||||
Users: make(map[m.Username]User),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &customer, nil
|
return &customer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Customer) AddNewUser(username m.Username, passcodeIdx []int, ui UserInterface, kp m.KeypadDimension) error {
|
//func (c *Customer) AddNewUser(username m.Username, passcodeIdx []int, ui UserInterface, kp m.KeypadDimension) error {
|
||||||
_, exists := c.Users[username]
|
// _, exists := c.Users[username]
|
||||||
if exists {
|
// if exists {
|
||||||
return errors.New(fmt.Sprintf("User %s already exists for customer %+v exists", username, c.CustomerId))
|
// return errors.New(fmt.Sprintf("User %s already exists for customer %+v exists", username, c.Id))
|
||||||
}
|
// }
|
||||||
setVals, err := c.Attributes.SetVals(kp)
|
// setVals, err := c.Attributes.SetVals(kp)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return err
|
// return err
|
||||||
}
|
// }
|
||||||
newKeys, err := NewUserCipherKeys(&kp, setVals, c.NKodePolicy.MaxNkodeLen)
|
// newKeys, err := NewUserCipherKeys(&kp, setVals, c.NKodePolicy.MaxNkodeLen)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return err
|
// return err
|
||||||
}
|
// }
|
||||||
encipheredNKode, err := newKeys.EncipherNKode(passcodeIdx, c.Attributes)
|
// encipheredNKode, err := newKeys.EncipherNKode(passcodeIdx, c.Attributes)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return err
|
// return err
|
||||||
}
|
// }
|
||||||
newUser := User{
|
// newUser := User{
|
||||||
Username: username,
|
// Id: m.UserId(uuid.New()),
|
||||||
EncipheredPasscode: *encipheredNKode,
|
// Username: username,
|
||||||
UserKeys: *newKeys,
|
// EncipheredPasscode: *encipheredNKode,
|
||||||
Interface: ui,
|
// UserKeys: *newKeys,
|
||||||
Kp: kp,
|
// Interface: ui,
|
||||||
}
|
// Kp: kp,
|
||||||
c.Users[username] = newUser
|
// }
|
||||||
return nil
|
// c.Users[username] = newUser
|
||||||
}
|
// return nil
|
||||||
|
//}
|
||||||
|
|
||||||
func (c *Customer) ValidKeyEntry(username m.Username, selectedKeys []int) ([]int, error) {
|
//func (c *Customer) ValidKeyEntry(username m.Username, selectedKeys []int) ([]int, error) {
|
||||||
user, exists := c.Users[username]
|
// user, exists := c.Users[username]
|
||||||
if !exists {
|
// if !exists {
|
||||||
return nil, errors.New(fmt.Sprintf("user %s does not exist for customer %+v", username, c.CustomerId))
|
// 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
|
||||||
|
//}
|
||||||
|
|
||||||
validKeys := py.All[int](selectedKeys, func(idx int) bool {
|
//func (c *Customer) getPresumedAttributeIdxVals(user User, selectedKeys []int) ([]int, error) {
|
||||||
return 0 <= idx && idx < user.Kp.NumbOfKeys
|
//
|
||||||
})
|
// passcodeLen := len(selectedKeys)
|
||||||
if !validKeys {
|
// if passcodeLen < c.NKodePolicy.MinNkodeLen || passcodeLen > c.NKodePolicy.MaxNkodeLen {
|
||||||
return nil, errors.New(fmt.Sprintf("one or more keys not in range 0-%d", user.Kp.NumbOfKeys-1))
|
// 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))
|
||||||
}
|
// }
|
||||||
presumedAttrIdxVals, err := c.getPresumedAttributeIdxVals(user, selectedKeys)
|
//
|
||||||
if err != nil {
|
// setVals, err := c.Attributes.SetVals(user.Kp)
|
||||||
return nil, err
|
// if err != nil {
|
||||||
}
|
// return nil, err
|
||||||
err = c.IsValidNKode(user.Kp, presumedAttrIdxVals)
|
// }
|
||||||
if err != nil {
|
// passcodeSetVals, err := user.DecipherMask(setVals, passcodeLen)
|
||||||
return nil, err
|
// if err != nil {
|
||||||
}
|
// return nil, err
|
||||||
attrVals, err := c.Attributes.AttrVals(user.Kp)
|
// }
|
||||||
if err != nil {
|
// presumedAttrIdxVals := make([]int, passcodeLen)
|
||||||
return nil, err
|
//
|
||||||
}
|
// for idx := range presumedAttrIdxVals {
|
||||||
err = user.UserKeys.ValidPassword(user.EncipheredPasscode.Code, presumedAttrIdxVals, attrVals)
|
// keyNumb := selectedKeys[idx]
|
||||||
if err != nil {
|
// setIdx, err := c.Attributes.IndexOfSet(passcodeSetVals[idx])
|
||||||
return nil, err
|
// if err != nil {
|
||||||
}
|
// return nil, err
|
||||||
|
// }
|
||||||
return presumedAttrIdxVals, nil
|
// selectedAttrIdx, err := user.Interface.GetAttrIdxByKeyNumbSetIdx(setIdx, keyNumb)
|
||||||
}
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
func (c *Customer) getPresumedAttributeIdxVals(user User, selectedKeys []int) ([]int, error) {
|
// }
|
||||||
|
// presumedAttrIdxVals[idx] = selectedAttrIdx
|
||||||
passcodeLen := len(selectedKeys)
|
// }
|
||||||
if passcodeLen < c.NKodePolicy.MinNkodeLen || passcodeLen > c.NKodePolicy.MaxNkodeLen {
|
// return presumedAttrIdxVals, nil
|
||||||
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 {
|
func (c *Customer) IsValidNKode(kp m.KeypadDimension, passcodeAttrIdx []int) error {
|
||||||
nkodeLen := len(passcodeAttrIdx)
|
nkodeLen := len(passcodeAttrIdx)
|
||||||
@@ -163,59 +162,39 @@ func (c *Customer) IsValidNKode(kp m.KeypadDimension, passcodeAttrIdx []int) err
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Customer) GetLoginInterface(username m.Username) ([]int, error) {
|
func (c *Customer) RenewKeys() ([]uint64, []uint64) {
|
||||||
user, exists := c.Users[username]
|
|
||||||
if !exists {
|
|
||||||
return nil, errors.New(fmt.Sprintf("can't get login interface for non-existant user %s in customer %s", username, c.CustomerId))
|
|
||||||
}
|
|
||||||
err := user.Interface.PartialInterfaceShuffle()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
c.Users[username] = user
|
|
||||||
return user.Interface.IdxInterface, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Customer) RenewKeys() error {
|
|
||||||
oldAttrs := make([]uint64, m.KeypadMax.TotalAttrs())
|
oldAttrs := make([]uint64, m.KeypadMax.TotalAttrs())
|
||||||
oldSets := make([]uint64, m.KeypadMax.AttrsPerKey)
|
oldSets := make([]uint64, m.KeypadMax.AttrsPerKey)
|
||||||
allAttrVals, err := c.Attributes.AttrVals(m.KeypadMax)
|
allAttrVals, err := c.Attributes.AttrVals(m.KeypadMax)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
panic(err)
|
||||||
}
|
}
|
||||||
allSetVals, err := c.Attributes.AttrVals(m.KeypadMax)
|
allSetVals, err := c.Attributes.AttrVals(m.KeypadMax)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
panic(err)
|
||||||
}
|
}
|
||||||
copy(oldAttrs, allAttrVals)
|
copy(oldAttrs, allAttrVals)
|
||||||
copy(oldSets, allSetVals)
|
copy(oldSets, allSetVals)
|
||||||
|
|
||||||
err = c.Attributes.Renew()
|
err = c.Attributes.Renew()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
panic(err)
|
||||||
}
|
}
|
||||||
allAttrVals, err = c.Attributes.AttrVals(m.KeypadMax)
|
allAttrVals, err = c.Attributes.AttrVals(m.KeypadMax)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
panic(err)
|
||||||
}
|
}
|
||||||
allSetVals, err = c.Attributes.AttrVals(m.KeypadMax)
|
allSetVals, err = c.Attributes.SetVals(m.KeypadMax)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
panic(err)
|
||||||
}
|
}
|
||||||
attrsXor, err := util.XorLists(oldAttrs, allAttrVals)
|
attrsXor, err := util.XorLists(oldAttrs, allAttrVals)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
panic(err)
|
||||||
}
|
}
|
||||||
setXor, err := util.XorLists(oldSets, allSetVals)
|
setXor, err := util.XorLists(oldSets, allSetVals)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
panic(err)
|
||||||
}
|
}
|
||||||
for _, user := range c.Users {
|
return setXor, attrsXor
|
||||||
err = user.RenewKeys(setXor, attrsXor)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ import (
|
|||||||
"go-nkode/util"
|
"go-nkode/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
var NotDispersableError = errors.New("number of keys must be less than the number of attributes per key to be dispersion resistant")
|
|
||||||
|
|
||||||
type CustomerAttributes struct {
|
type CustomerAttributes struct {
|
||||||
attrVals []uint64
|
attrVals []uint64
|
||||||
setVals []uint64
|
setVals []uint64
|
||||||
|
|||||||
@@ -27,13 +27,13 @@ func testCustomerValidKeyEntry(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
username := m.Username("testing123")
|
username := m.Username("testing123")
|
||||||
passcodeIdx := []int{0, 1, 2, 3}
|
passcodeIdx := []int{0, 1, 2, 3}
|
||||||
err = customer.AddNewUser(username, passcodeIdx, *newUserInterface, kp)
|
user, err := NewUser(*customer, username, passcodeIdx, *newUserInterface, kp)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
userLoginInterface, err := customer.GetLoginInterface(username)
|
userLoginInterface, err := user.GetLoginInterface()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
selectedKeys, err := SelectKeyByAttrIdx(userLoginInterface, passcodeIdx, kp)
|
selectedKeys, err := SelectKeyByAttrIdx(userLoginInterface, passcodeIdx, kp)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
validatedPasscode, err := customer.ValidKeyEntry(username, selectedKeys)
|
validatedPasscode, err := ValidKeyEntry(*user, *customer, selectedKeys)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, len(validatedPasscode), len(passcodeIdx))
|
assert.Equal(t, len(validatedPasscode), len(passcodeIdx))
|
||||||
for idx := range validatedPasscode {
|
for idx := range validatedPasscode {
|
||||||
@@ -50,8 +50,8 @@ func testCustomerIsValidNKode(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
username := m.Username("testing123")
|
username := m.Username("testing123")
|
||||||
passcodeIdx := []int{0, 1, 2, 3}
|
passcodeIdx := []int{0, 1, 2, 3}
|
||||||
err = customer.AddNewUser(username, passcodeIdx, *newUserInterface, kp)
|
user, err := NewUser(*customer, username, passcodeIdx, *newUserInterface, kp)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
err = customer.IsValidNKode(kp, passcodeIdx)
|
err = customer.IsValidNKode(user.Kp, passcodeIdx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|||||||
14
core/nkode/db_accessor.go
Normal file
14
core/nkode/db_accessor.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package nkode
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go-nkode/core/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DbAccessor interface {
|
||||||
|
GetCustomer(m.CustomerId) (*Customer, error)
|
||||||
|
GetUser(m.Username, m.CustomerId) (*User, error)
|
||||||
|
WriteNewCustomer(Customer) error
|
||||||
|
WriteNewUser(User) error
|
||||||
|
UpdateUserInterface(m.UserId, UserInterface) error
|
||||||
|
Renew(m.CustomerId) error
|
||||||
|
}
|
||||||
100
core/nkode/in_memory_db.go
Normal file
100
core/nkode/in_memory_db.go
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
package nkode
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
m "go-nkode/core/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type InMemoryDb struct {
|
||||||
|
Customers map[m.CustomerId]Customer
|
||||||
|
Users map[m.UserId]User
|
||||||
|
userIdMap map[string]m.UserId
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewInMemoryDb() InMemoryDb {
|
||||||
|
return InMemoryDb{
|
||||||
|
Customers: make(map[m.CustomerId]Customer),
|
||||||
|
Users: make(map[m.UserId]User),
|
||||||
|
userIdMap: make(map[string]m.UserId),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *InMemoryDb) GetCustomer(id m.CustomerId) (*Customer, error) {
|
||||||
|
customer, exists := db.Customers[id]
|
||||||
|
if !exists {
|
||||||
|
return nil, errors.New(fmt.Sprintf("customer %s dne", customer.Id))
|
||||||
|
}
|
||||||
|
return &customer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *InMemoryDb) GetUser(username m.Username, customerId m.CustomerId) (*User, error) {
|
||||||
|
key := userIdKey(customerId, username)
|
||||||
|
userId, exists := db.userIdMap[key]
|
||||||
|
if !exists {
|
||||||
|
return nil, errors.New(fmt.Sprintf("customer %s with username %s dne", customerId, username))
|
||||||
|
}
|
||||||
|
user, exists := db.Users[userId]
|
||||||
|
if !exists {
|
||||||
|
panic(fmt.Sprintf("userId %s with customerId %s and username %s with no user", userId, customerId, username))
|
||||||
|
}
|
||||||
|
return &user, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *InMemoryDb) WriteNewCustomer(customer Customer) error {
|
||||||
|
_, exists := db.Customers[customer.Id]
|
||||||
|
|
||||||
|
if exists {
|
||||||
|
return errors.New(fmt.Sprintf("can write customer %s; already exists", customer.Id))
|
||||||
|
}
|
||||||
|
db.Customers[customer.Id] = customer
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *InMemoryDb) WriteNewUser(user User) error {
|
||||||
|
_, exists := db.Customers[user.CustomerId]
|
||||||
|
if !exists {
|
||||||
|
return errors.New(fmt.Sprintf("can't add user %s to customer %s: customer dne", user.Username, user.CustomerId))
|
||||||
|
}
|
||||||
|
userExists, _ := db.GetUser(user.Username, user.CustomerId)
|
||||||
|
|
||||||
|
if userExists != nil {
|
||||||
|
return errors.New(fmt.Sprintf("can't write new user %s, alread exists", user.Username))
|
||||||
|
}
|
||||||
|
key := userIdKey(user.CustomerId, user.Username)
|
||||||
|
db.userIdMap[key] = user.Id
|
||||||
|
db.Users[user.Id] = user
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *InMemoryDb) UpdateUserInterface(userId m.UserId, ui UserInterface) error {
|
||||||
|
user, exists := db.Users[userId]
|
||||||
|
if !exists {
|
||||||
|
return errors.New(fmt.Sprintf("can't update user %s, dne", user.Id))
|
||||||
|
}
|
||||||
|
user.Interface = ui
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *InMemoryDb) Renew(id m.CustomerId) error {
|
||||||
|
customer, exists := db.Customers[id]
|
||||||
|
if !exists {
|
||||||
|
return errors.New(fmt.Sprintf("customer %s does not exist", id))
|
||||||
|
}
|
||||||
|
setXor, attrsXor := customer.RenewKeys()
|
||||||
|
var err error
|
||||||
|
for _, user := range db.Users {
|
||||||
|
if user.CustomerId == id {
|
||||||
|
err = user.RenewKeys(setXor[:user.Kp.AttrsPerKey], attrsXor[:user.Kp.TotalAttrs()])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func userIdKey(customerId m.CustomerId, username m.Username) string {
|
||||||
|
key := fmt.Sprintf("%s:%s", customerId, username)
|
||||||
|
return key
|
||||||
|
}
|
||||||
131
core/nkode/nkode_api.go
Normal file
131
core/nkode/nkode_api.go
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
package nkode
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
m "go-nkode/core/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NKodeAPI struct {
|
||||||
|
Db DbAccessor
|
||||||
|
SignupSessions map[m.SessionId]UserSignSession
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNKodeAPI(db DbAccessor) NKodeAPI {
|
||||||
|
return NKodeAPI{
|
||||||
|
Db: db,
|
||||||
|
SignupSessions: make(map[m.SessionId]UserSignSession),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NKodeAPI) CreateNewCustomer(nkodePolicy m.NKodePolicy) (*m.CustomerId, error) {
|
||||||
|
newCustomer, err := NewCustomer(nkodePolicy)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = n.Db.WriteNewCustomer(*newCustomer)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &newCustomer.Id, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NKodeAPI) GenerateSignupInterface(customerId m.CustomerId, kp m.KeypadDimension) (*m.GenerateSignupInterfaceResp, error) {
|
||||||
|
signupSession, err := NewSignupSession(kp, customerId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
n.SignupSessions[signupSession.Id] = *signupSession
|
||||||
|
resp := m.GenerateSignupInterfaceResp{
|
||||||
|
UserInterface: signupSession.SetIdxInterface,
|
||||||
|
SessionId: signupSession.Id,
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NKodeAPI) SetNKode(username m.Username, customerId m.CustomerId, sessionId m.SessionId, keySelection m.KeySelection) (m.IdxInterface, error) {
|
||||||
|
_, err := n.Db.GetCustomer(customerId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
session, exists := n.SignupSessions[sessionId]
|
||||||
|
if !exists {
|
||||||
|
return nil, errors.New(fmt.Sprintf("session id does not exist %s", sessionId))
|
||||||
|
}
|
||||||
|
confirmInterface, err := session.SetUserNKode(username, keySelection)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
n.SignupSessions[sessionId] = session
|
||||||
|
return confirmInterface, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NKodeAPI) ConfirmNKode(customerId m.CustomerId, sessionId m.SessionId, keySelection m.KeySelection) error {
|
||||||
|
session, exists := n.SignupSessions[sessionId]
|
||||||
|
if !exists {
|
||||||
|
return errors.New(fmt.Sprintf("session id does not exist %s", sessionId))
|
||||||
|
}
|
||||||
|
customer, err := n.Db.GetCustomer(customerId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
passcode, err := session.DeducePasscode(keySelection)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = customer.IsValidNKode(session.Kp, passcode)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
user, err := NewUser(*customer, session.Username, passcode, session.LoginUserInterface, session.Kp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
delete(n.SignupSessions, session.Id)
|
||||||
|
err = n.Db.WriteNewUser(*user)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NKodeAPI) GetLoginInterface(username m.Username, customerId m.CustomerId) (m.IdxInterface, error) {
|
||||||
|
user, err := n.Db.GetUser(username, customerId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = user.Interface.PartialInterfaceShuffle()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = n.Db.UpdateUserInterface(user.Id, user.Interface)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return user.Interface.IdxInterface, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NKodeAPI) Login(customerId m.CustomerId, username m.Username, keySelection m.KeySelection) error {
|
||||||
|
customer, err := n.Db.GetCustomer(customerId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
user, err := n.Db.GetUser(username, customerId)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New(fmt.Sprintf("user dne %s", username))
|
||||||
|
}
|
||||||
|
passcode, err := ValidKeyEntry(*user, *customer, keySelection)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if user.Renew {
|
||||||
|
err = user.RefreshPasscode(passcode, customer.Attributes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NKodeAPI) RenewAttributes(customerId m.CustomerId) error {
|
||||||
|
return n.Db.Renew(customerId)
|
||||||
|
}
|
||||||
@@ -8,11 +8,12 @@ import (
|
|||||||
|
|
||||||
func TestNKodeAPI(t *testing.T) {
|
func TestNKodeAPI(t *testing.T) {
|
||||||
for idx := 0; idx < 10; idx++ {
|
for idx := 0; idx < 10; idx++ {
|
||||||
|
db := NewInMemoryDb()
|
||||||
username := m.Username("test_username")
|
username := m.Username("test_username")
|
||||||
passcodeLen := 4
|
passcodeLen := 4
|
||||||
nkodePolicy := m.NewDefaultNKodePolicy()
|
nkodePolicy := m.NewDefaultNKodePolicy()
|
||||||
keypadSize := m.KeypadDimension{AttrsPerKey: 10, NumbOfKeys: 8}
|
keypadSize := m.KeypadDimension{AttrsPerKey: 10, NumbOfKeys: 8}
|
||||||
nkodeApi := NewNKodeInMemory()
|
nkodeApi := NewNKodeAPI(&db)
|
||||||
customerId, err := nkodeApi.CreateNewCustomer(nkodePolicy)
|
customerId, err := nkodeApi.CreateNewCustomer(nkodePolicy)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
signupResponse, err := nkodeApi.GenerateSignupInterface(*customerId, keypadSize)
|
signupResponse, err := nkodeApi.GenerateSignupInterface(*customerId, keypadSize)
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
package nkode
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
m "go-nkode/core/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
type NKodeInMemory struct {
|
|
||||||
Customers map[m.CustomerId]Customer
|
|
||||||
SignupSessions map[m.SessionId]UserSignSession
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewNKodeInMemory() NKodeInMemory {
|
|
||||||
return NKodeInMemory{
|
|
||||||
Customers: make(map[m.CustomerId]Customer),
|
|
||||||
SignupSessions: make(map[m.SessionId]UserSignSession),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NKodeInMemory) CreateNewCustomer(nkodePolicy m.NKodePolicy) (*m.CustomerId, error) {
|
|
||||||
newCustomer, err := NewCustomer(nkodePolicy)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
n.Customers[newCustomer.CustomerId] = *newCustomer
|
|
||||||
return &newCustomer.CustomerId, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NKodeInMemory) GenerateSignupInterface(customerId m.CustomerId, kp m.KeypadDimension) (*m.GenerateSignupInterfaceResp, error) {
|
|
||||||
customer, exists := n.Customers[customerId]
|
|
||||||
if !exists {
|
|
||||||
return nil, errors.New(fmt.Sprintf("customer doesnt exists: %s", customerId))
|
|
||||||
}
|
|
||||||
|
|
||||||
signupSession, err := NewSignupSession(kp, customer.CustomerId)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
n.SignupSessions[signupSession.SessionId] = *signupSession
|
|
||||||
resp := m.GenerateSignupInterfaceResp{
|
|
||||||
UserInterface: signupSession.SetIdxInterface,
|
|
||||||
SessionId: signupSession.SessionId,
|
|
||||||
}
|
|
||||||
return &resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NKodeInMemory) SetNKode(username m.Username, customerId m.CustomerId, sessionId m.SessionId, keySelection m.KeySelection) (m.IdxInterface, error) {
|
|
||||||
_, exists := n.Customers[customerId]
|
|
||||||
if !exists {
|
|
||||||
return nil, errors.New(fmt.Sprintf("set nkode customer id does not exist %s", customerId))
|
|
||||||
}
|
|
||||||
|
|
||||||
session, exists := n.SignupSessions[sessionId]
|
|
||||||
if !exists {
|
|
||||||
return nil, errors.New(fmt.Sprintf("session id does not exist %s", sessionId))
|
|
||||||
}
|
|
||||||
confirmInterface, err := session.SetUserNKode(username, keySelection)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
n.SignupSessions[sessionId] = session
|
|
||||||
return confirmInterface, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NKodeInMemory) ConfirmNKode(customerId m.CustomerId, sessionId m.SessionId, keySelection m.KeySelection) error {
|
|
||||||
session, exists := n.SignupSessions[sessionId]
|
|
||||||
if !exists {
|
|
||||||
return errors.New(fmt.Sprintf("session id does not exist %s", sessionId))
|
|
||||||
}
|
|
||||||
customer, exists := n.Customers[customerId]
|
|
||||||
passcode, err := session.DeducePasscode(keySelection)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = customer.IsValidNKode(session.Kp, passcode)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = customer.AddNewUser(session.Username, passcode, session.LoginUserInterface, session.Kp)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
delete(n.SignupSessions, session.SessionId)
|
|
||||||
n.Customers[customerId] = customer
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NKodeInMemory) GetLoginInterface(username m.Username, customerId m.CustomerId) (m.IdxInterface, error) {
|
|
||||||
err := n.customerUserExists(username, customerId)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
user := n.Customers[customerId].Users[username]
|
|
||||||
err = user.Interface.PartialInterfaceShuffle()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
n.Customers[customerId].Users[username] = user
|
|
||||||
return user.Interface.IdxInterface, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NKodeInMemory) Login(customerId m.CustomerId, username m.Username, keySelection m.KeySelection) error {
|
|
||||||
customer, exists := n.Customers[customerId]
|
|
||||||
if !exists {
|
|
||||||
return errors.New(fmt.Sprintf("customer %s does not exist", customerId))
|
|
||||||
}
|
|
||||||
user, exists := customer.Users[username]
|
|
||||||
if !exists {
|
|
||||||
return errors.New(fmt.Sprintf("user dne %s", username))
|
|
||||||
}
|
|
||||||
passcode, err := customer.ValidKeyEntry(username, keySelection)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if user.Renew {
|
|
||||||
err = user.RefreshPasscode(passcode, customer.Attributes)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NKodeInMemory) customerUserExists(username m.Username, customerId m.CustomerId) error {
|
|
||||||
customer, exists := n.Customers[customerId]
|
|
||||||
if !exists {
|
|
||||||
return errors.New(fmt.Sprintf("customer %s does not exist", customerId))
|
|
||||||
}
|
|
||||||
_, exists = customer.Users[username]
|
|
||||||
if !exists {
|
|
||||||
return errors.New(fmt.Sprintf("user dne %s", username))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NKodeInMemory) RenewAttributes(customerId m.CustomerId) error {
|
|
||||||
customer, exists := n.Customers[customerId]
|
|
||||||
if !exists {
|
|
||||||
return errors.New(fmt.Sprintf("customer %s does not exist", customerId))
|
|
||||||
}
|
|
||||||
return customer.RenewKeys()
|
|
||||||
}
|
|
||||||
1
core/nkode/sqlite_db.go
Normal file
1
core/nkode/sqlite_db.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package nkode
|
||||||
@@ -6,6 +6,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
|
Id m.UserId
|
||||||
|
CustomerId m.CustomerId
|
||||||
Username m.Username
|
Username m.Username
|
||||||
EncipheredPasscode m.EncipheredNKode
|
EncipheredPasscode m.EncipheredNKode
|
||||||
Kp m.KeypadDimension
|
Kp m.KeypadDimension
|
||||||
@@ -23,10 +25,13 @@ func (u *User) RenewKeys(setXor []uint64, attrXor []uint64) error {
|
|||||||
var err error
|
var err error
|
||||||
u.UserKeys.SetKey, err = util.XorLists(setXor, u.UserKeys.SetKey)
|
u.UserKeys.SetKey, err = util.XorLists(setXor, u.UserKeys.SetKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
panic(err)
|
||||||
}
|
}
|
||||||
u.UserKeys.AlphaKey, err = util.XorLists(attrXor, u.UserKeys.AlphaKey)
|
u.UserKeys.AlphaKey, err = util.XorLists(attrXor, u.UserKeys.AlphaKey)
|
||||||
return err
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) RefreshPasscode(passcodeAttrIdx []int, customerAttributes CustomerAttributes) error {
|
func (u *User) RefreshPasscode(passcodeAttrIdx []int, customerAttributes CustomerAttributes) error {
|
||||||
@@ -46,3 +51,12 @@ func (u *User) RefreshPasscode(passcodeAttrIdx []int, customerAttributes Custome
|
|||||||
u.Renew = false
|
u.Renew = false
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *User) GetLoginInterface() ([]int, error) {
|
||||||
|
err := u.Interface.PartialInterfaceShuffle()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return u.Interface.IdxInterface, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,12 +3,15 @@ package nkode
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"errors"
|
"errors"
|
||||||
|
"github.com/google/uuid"
|
||||||
m "go-nkode/core/model"
|
m "go-nkode/core/model"
|
||||||
"go-nkode/util"
|
"go-nkode/util"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserCipherKeys struct {
|
type UserCipherKeys struct {
|
||||||
|
Id uuid.UUID
|
||||||
|
UserId m.UserId
|
||||||
AlphaKey []uint64
|
AlphaKey []uint64
|
||||||
SetKey []uint64
|
SetKey []uint64
|
||||||
PassKey []uint64
|
PassKey []uint64
|
||||||
@@ -37,6 +40,7 @@ func NewUserCipherKeys(kp *m.KeypadDimension, setVals []uint64, maxNKodeLen int)
|
|||||||
maskKey, _ := util.GenerateRandomNonRepeatingUint64(maxNKodeLen)
|
maskKey, _ := util.GenerateRandomNonRepeatingUint64(maxNKodeLen)
|
||||||
salt, _ := util.RandomBytes(10)
|
salt, _ := util.RandomBytes(10)
|
||||||
userCipherKeys := UserCipherKeys{
|
userCipherKeys := UserCipherKeys{
|
||||||
|
Id: uuid.New(),
|
||||||
AlphaKey: alphakey,
|
AlphaKey: alphakey,
|
||||||
PassKey: passKey,
|
PassKey: passKey,
|
||||||
MaskKey: maskKey,
|
MaskKey: maskKey,
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ import (
|
|||||||
|
|
||||||
type UserInterface struct {
|
type UserInterface struct {
|
||||||
IdxInterface m.IdxInterface
|
IdxInterface m.IdxInterface
|
||||||
kp *m.KeypadDimension
|
Kp *m.KeypadDimension
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUserInterface(kp *m.KeypadDimension) (*UserInterface, error) {
|
func NewUserInterface(kp *m.KeypadDimension) (*UserInterface, error) {
|
||||||
idxInterface := util.IdentityArray(kp.TotalAttrs())
|
idxInterface := util.IdentityArray(kp.TotalAttrs())
|
||||||
userInterface := UserInterface{
|
userInterface := UserInterface{
|
||||||
IdxInterface: idxInterface,
|
IdxInterface: idxInterface,
|
||||||
kp: kp,
|
Kp: kp,
|
||||||
}
|
}
|
||||||
err := userInterface.RandomShuffle()
|
err := userInterface.RandomShuffle()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -55,7 +55,7 @@ func (u *UserInterface) RandomShuffle() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) InterfaceMatrix() ([][]int, error) {
|
func (u *UserInterface) InterfaceMatrix() ([][]int, error) {
|
||||||
return util.ListToMatrix(u.IdxInterface, u.kp.AttrsPerKey)
|
return util.ListToMatrix(u.IdxInterface, u.Kp.AttrsPerKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) SetViewMatrix() ([][]int, error) {
|
func (u *UserInterface) SetViewMatrix() ([][]int, error) {
|
||||||
@@ -67,7 +67,7 @@ func (u *UserInterface) SetViewMatrix() ([][]int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) DisperseInterface() error {
|
func (u *UserInterface) DisperseInterface() error {
|
||||||
if !u.kp.IsDispersable() {
|
if !u.Kp.IsDispersable() {
|
||||||
panic("interface is not dispersable")
|
panic("interface is not dispersable")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ func (u *UserInterface) DisperseInterface() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) shuffleKeys() error {
|
func (u *UserInterface) shuffleKeys() error {
|
||||||
userInterfaceMatrix, err := util.ListToMatrix(u.IdxInterface, u.kp.AttrsPerKey)
|
userInterfaceMatrix, err := util.ListToMatrix(u.IdxInterface, u.Kp.AttrsPerKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -144,11 +144,11 @@ func (u *UserInterface) PartialInterfaceShuffle() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
numbOfSelectedSets := u.kp.AttrsPerKey / 2
|
numbOfSelectedSets := u.Kp.AttrsPerKey / 2
|
||||||
if u.kp.AttrsPerKey&1 == 1 {
|
if u.Kp.AttrsPerKey&1 == 1 {
|
||||||
numbOfSelectedSets += util.Choice[int]([]int{0, 1})
|
numbOfSelectedSets += util.Choice[int]([]int{0, 1})
|
||||||
}
|
}
|
||||||
setIdxs, err := util.RandomPermutation(u.kp.AttrsPerKey)
|
setIdxs, err := util.RandomPermutation(u.Kp.AttrsPerKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -158,7 +158,7 @@ func (u *UserInterface) PartialInterfaceShuffle() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
interfaceBySet := make([][]int, u.kp.AttrsPerKey)
|
interfaceBySet := make([][]int, u.Kp.AttrsPerKey)
|
||||||
for idx, attrs := range keypadSetView {
|
for idx, attrs := range keypadSetView {
|
||||||
if selectedSets.Contains(idx) {
|
if selectedSets.Contains(idx) {
|
||||||
err = util.FisherYatesShuffle[int](&attrs)
|
err = util.FisherYatesShuffle[int](&attrs)
|
||||||
@@ -177,12 +177,12 @@ func (u *UserInterface) PartialInterfaceShuffle() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) GetAttrIdxByKeyNumbSetIdx(setIdx int, keyNumb int) (int, error) {
|
func (u *UserInterface) GetAttrIdxByKeyNumbSetIdx(setIdx int, keyNumb int) (int, error) {
|
||||||
if keyNumb < 0 || u.kp.NumbOfKeys <= keyNumb {
|
if keyNumb < 0 || u.Kp.NumbOfKeys <= keyNumb {
|
||||||
return -1, errors.New(fmt.Sprintf("keyNumb %d is out of range 0-%d", keyNumb, u.kp.NumbOfKeys))
|
return -1, errors.New(fmt.Sprintf("keyNumb %d is out of range 0-%d", keyNumb, u.Kp.NumbOfKeys))
|
||||||
}
|
}
|
||||||
|
|
||||||
if setIdx < 0 || u.kp.AttrsPerKey <= setIdx {
|
if setIdx < 0 || u.Kp.AttrsPerKey <= setIdx {
|
||||||
return -1, errors.New(fmt.Sprintf("setIdx %d is out of range 0-%d", setIdx, u.kp.AttrsPerKey))
|
return -1, errors.New(fmt.Sprintf("setIdx %d is out of range 0-%d", setIdx, u.Kp.AttrsPerKey))
|
||||||
}
|
}
|
||||||
keypadView, err := u.InterfaceMatrix()
|
keypadView, err := u.InterfaceMatrix()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type UserSignSession struct {
|
type UserSignSession struct {
|
||||||
SessionId m.SessionId
|
Id m.SessionId
|
||||||
CustomerId m.CustomerId
|
CustomerId m.CustomerId
|
||||||
LoginUserInterface UserInterface
|
LoginUserInterface UserInterface
|
||||||
Kp m.KeypadDimension
|
Kp m.KeypadDimension
|
||||||
@@ -19,6 +19,7 @@ type UserSignSession struct {
|
|||||||
ConfirmIdxInterface m.IdxInterface
|
ConfirmIdxInterface m.IdxInterface
|
||||||
SetKeySelection m.KeySelection
|
SetKeySelection m.KeySelection
|
||||||
Username m.Username
|
Username m.Username
|
||||||
|
Expire int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSignupSession(kp m.KeypadDimension, customerId m.CustomerId) (*UserSignSession, error) {
|
func NewSignupSession(kp m.KeypadDimension, customerId m.CustomerId) (*UserSignSession, error) {
|
||||||
@@ -31,7 +32,7 @@ func NewSignupSession(kp m.KeypadDimension, customerId m.CustomerId) (*UserSignS
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
session := UserSignSession{
|
session := UserSignSession{
|
||||||
SessionId: m.SessionId(uuid.New()),
|
Id: m.SessionId(uuid.New()),
|
||||||
CustomerId: customerId,
|
CustomerId: customerId,
|
||||||
LoginUserInterface: *loginInterface,
|
LoginUserInterface: *loginInterface,
|
||||||
SetIdxInterface: signupInterface.IdxInterface,
|
SetIdxInterface: signupInterface.IdxInterface,
|
||||||
@@ -108,7 +109,7 @@ func (s *UserSignSession) SetUserNKode(username m.Username, keySelection m.KeySe
|
|||||||
s.SetKeySelection = keySelection
|
s.SetKeySelection = keySelection
|
||||||
s.Username = username
|
s.Username = username
|
||||||
setKp := s.SignupKeypad()
|
setKp := s.SignupKeypad()
|
||||||
setInterface := UserInterface{IdxInterface: s.SetIdxInterface, kp: &setKp}
|
setInterface := UserInterface{IdxInterface: s.SetIdxInterface, Kp: &setKp}
|
||||||
err := setInterface.DisperseInterface()
|
err := setInterface.DisperseInterface()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -159,7 +160,7 @@ func signupInterface(baseUserInterface UserInterface, kp m.KeypadDimension) (*Us
|
|||||||
}
|
}
|
||||||
signupUserInterface := UserInterface{
|
signupUserInterface := UserInterface{
|
||||||
IdxInterface: util.MatrixToList(attrSetView),
|
IdxInterface: util.MatrixToList(attrSetView),
|
||||||
kp: &m.KeypadDimension{
|
Kp: &m.KeypadDimension{
|
||||||
AttrsPerKey: numbOfKeys,
|
AttrsPerKey: numbOfKeys,
|
||||||
NumbOfKeys: numbOfKeys,
|
NumbOfKeys: numbOfKeys,
|
||||||
},
|
},
|
||||||
|
|||||||
3
main.go
3
main.go
@@ -9,7 +9,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
nkodeApi := nkode.NewNKodeInMemory()
|
db := nkode.NewInMemoryDb()
|
||||||
|
nkodeApi := nkode.NewNKodeAPI(&db)
|
||||||
handler := api.NKodeHandler{Api: &nkodeApi}
|
handler := api.NKodeHandler{Api: &nkodeApi}
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
mux.Handle(api.CreateNewCustomer, &handler)
|
mux.Handle(api.CreateNewCustomer, &handler)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package sql_driver
|
|||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/google/uuid"
|
||||||
_ "github.com/mattn/go-sqlite3" // Import the SQLite3 driver
|
_ "github.com/mattn/go-sqlite3" // Import the SQLite3 driver
|
||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
@@ -17,7 +18,7 @@ func InitTables() {
|
|||||||
// Create a table
|
// Create a table
|
||||||
createTableSQL := `
|
createTableSQL := `
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
id TEXT NOT NULL PRIMARY KEY,
|
||||||
name TEXT,
|
name TEXT,
|
||||||
age INTEGER
|
age INTEGER
|
||||||
);
|
);
|
||||||
@@ -28,13 +29,13 @@ func InitTables() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Insert data into the table
|
// Insert data into the table
|
||||||
insertUserSQL := `INSERT INTO users (name, age) VALUES (?, ?)`
|
insertUserSQL := `INSERT INTO users (id, name, age) VALUES (?, ?, ?)`
|
||||||
_, err = db.Exec(insertUserSQL, "Alice", 30)
|
_, err = db.Exec(insertUserSQL, uuid.New(), "Alice", 30)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error inserting data: %s", err)
|
log.Fatalf("Error inserting data: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = db.Exec(insertUserSQL, "Bob", 25)
|
_, err = db.Exec(insertUserSQL, uuid.New(), "Bob", 25)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error inserting data: %s", err)
|
log.Fatalf("Error inserting data: %s", err)
|
||||||
}
|
}
|
||||||
@@ -48,14 +49,14 @@ func InitTables() {
|
|||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var id int
|
var id string
|
||||||
var name string
|
var name string
|
||||||
var age int
|
var age int
|
||||||
err = rows.Scan(&id, &name, &age)
|
err = rows.Scan(&id, &name, &age)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error scanning data: %s", err)
|
log.Fatalf("Error scanning data: %s", err)
|
||||||
}
|
}
|
||||||
fmt.Printf("User: ID=%d, Name=%s, Age=%d\n", id, name, age)
|
fmt.Printf("User: ID=%s, Name=%s, Age=%d\n", id, name, age)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update data
|
// Update data
|
||||||
@@ -74,13 +75,13 @@ func InitTables() {
|
|||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var id int
|
var id string
|
||||||
var name string
|
var name string
|
||||||
var age int
|
var age int
|
||||||
err = rows.Scan(&id, &name, &age)
|
err = rows.Scan(&id, &name, &age)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error scanning data: %s", err)
|
log.Fatalf("Error scanning data: %s", err)
|
||||||
}
|
}
|
||||||
fmt.Printf("User: ID=%d, Name=%s, Age=%d\n", id, name, age)
|
fmt.Printf("User: ID=%s, Name=%s, Age=%d\n", id, name, age)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
7
sql-driver/sql_driver_test.go
Normal file
7
sql-driver/sql_driver_test.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package sql_driver
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestInitTables(t *testing.T) {
|
||||||
|
InitTables()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user