user signup sessions
This commit is contained in:
77
customer.go
77
customer.go
@@ -37,42 +37,55 @@ func NewCustomer(keypadSize m.KeypadSize, nkodePolicy m.NKodePolicy) (*Customer,
|
|||||||
return &customer, nil
|
return &customer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Customer) AddNewUser(user User) error {
|
func (c *Customer) AddNewUser(username string, passcodeIdx []int, userInterface UserInterface) error {
|
||||||
_, exists := c.Users[user.Username]
|
_, exists := c.Users[username]
|
||||||
if exists {
|
if exists {
|
||||||
return errors.New(fmt.Sprintf("user: %s exists", user.Username))
|
return errors.New(fmt.Sprintf("User %s already exists for customer %s exists", username, c.CustomerId.String()))
|
||||||
}
|
}
|
||||||
c.Users[user.Username] = user
|
newKeys, err := NewUserCipherKeys(c.Attributes.KeypadSize, c.Attributes.SetVals, c.NKodePolicy.MaxNkodeLen)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
encipheredNKode, err := newKeys.EncipherNKode(passcodeIdx, c.Attributes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
newUser := User{
|
||||||
|
Username: username,
|
||||||
|
EncipheredPasscode: *encipheredNKode,
|
||||||
|
UserKeys: *newKeys,
|
||||||
|
Interface: userInterface,
|
||||||
|
}
|
||||||
|
c.Users[username] = newUser
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Customer) ValidKeyEntryAndRenew(username string, selectedKeys []int) error {
|
func (c *Customer) ValidKeyEntry(username string, selectedKeys []int) ([]int, error) {
|
||||||
user, exists := c.Users[username]
|
user, exists := c.Users[username]
|
||||||
if !exists {
|
if !exists {
|
||||||
return errors.New(fmt.Sprintf("user %s does not exist for customer %s", username, c.CustomerId.String()))
|
return nil, errors.New(fmt.Sprintf("user %s does not exist for customer %s", username, c.CustomerId.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
validKeys := py.All[int](selectedKeys, func(idx int) bool {
|
validKeys := py.All[int](selectedKeys, func(idx int) bool {
|
||||||
return 0 <= idx && idx < c.Attributes.keypadSize.NumbOfKeys
|
return 0 <= idx && idx < c.Attributes.KeypadSize.NumbOfKeys
|
||||||
})
|
})
|
||||||
if !validKeys {
|
if !validKeys {
|
||||||
return errors.New(fmt.Sprintf("one or more keys not in range 0-%d", c.Attributes.keypadSize.NumbOfKeys-1))
|
return nil, errors.New(fmt.Sprintf("one or more keys not in range 0-%d", c.Attributes.KeypadSize.NumbOfKeys-1))
|
||||||
}
|
}
|
||||||
presumedAttrIdxVals, err := c.getPresumedAttributeIdxVals(user, selectedKeys)
|
presumedAttrIdxVals, err := c.getPresumedAttributeIdxVals(user, selectedKeys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
|
}
|
||||||
|
err = c.IsValidNKode(presumedAttrIdxVals)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = user.UserKeys.ValidPassword(user.EncipheredPasscode.Code, presumedAttrIdxVals, c.Attributes)
|
err = user.UserKeys.ValidPassword(user.EncipheredPasscode.Code, presumedAttrIdxVals, c.Attributes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.Renew {
|
return presumedAttrIdxVals, nil
|
||||||
// renew
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Customer) getPresumedAttributeIdxVals(user User, selectedKeys []int) ([]int, error) {
|
func (c *Customer) getPresumedAttributeIdxVals(user User, selectedKeys []int) ([]int, error) {
|
||||||
@@ -107,5 +120,37 @@ func (c *Customer) IsValidNKode(passcodeAttrIdx []int) error {
|
|||||||
if nkodeLen < c.NKodePolicy.MinNkodeLen {
|
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))
|
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 < c.Attributes.KeypadSize.TotalAttrs()
|
||||||
|
})
|
||||||
|
|
||||||
|
if !validIdx {
|
||||||
|
return errors.New(fmt.Sprintf("One or more idx out of range 0-%d in IsValidNKode", c.Attributes.KeypadSize.TotalAttrs()-1))
|
||||||
|
}
|
||||||
|
passcodeSetVals := make([]uint64, nkodeLen)
|
||||||
|
var err error
|
||||||
|
for idx := range passcodeSetVals {
|
||||||
|
attrVal := c.Attributes.AttrVals[passcodeAttrIdx[idx]]
|
||||||
|
passcodeSetVals[idx], err = c.Attributes.GetAttrSetVal(attrVal)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Customer) GetLoginInterface(username string) ([]int, error) {
|
||||||
|
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.String()))
|
||||||
|
}
|
||||||
|
err := user.Interface.PartialInterfaceShuffle()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.Users[username] = user
|
||||||
|
return user.Interface.IdxInterface, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
type CustomerAttributes struct {
|
type CustomerAttributes struct {
|
||||||
AttrVals []uint64
|
AttrVals []uint64
|
||||||
SetVals []uint64
|
SetVals []uint64
|
||||||
keypadSize models.KeypadSize
|
KeypadSize models.KeypadSize
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCustomerAttributes(keypadSize models.KeypadSize) (*CustomerAttributes, error) {
|
func NewCustomerAttributes(keypadSize models.KeypadSize) (*CustomerAttributes, error) {
|
||||||
@@ -31,17 +31,17 @@ func NewCustomerAttributes(keypadSize models.KeypadSize) (*CustomerAttributes, e
|
|||||||
customerAttrs := CustomerAttributes{
|
customerAttrs := CustomerAttributes{
|
||||||
AttrVals: attrVals,
|
AttrVals: attrVals,
|
||||||
SetVals: setVals,
|
SetVals: setVals,
|
||||||
keypadSize: keypadSize,
|
KeypadSize: keypadSize,
|
||||||
}
|
}
|
||||||
return &customerAttrs, nil
|
return &customerAttrs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CustomerAttributes) Renew() error {
|
func (c *CustomerAttributes) Renew() error {
|
||||||
attrVals, errAttr := util.GenerateRandomNonRepeatingUint64(c.keypadSize.TotalAttrs())
|
attrVals, errAttr := util.GenerateRandomNonRepeatingUint64(c.KeypadSize.TotalAttrs())
|
||||||
if errAttr != nil {
|
if errAttr != nil {
|
||||||
return errAttr
|
return errAttr
|
||||||
}
|
}
|
||||||
setVals, errSet := util.GenerateRandomNonRepeatingUint64(c.keypadSize.AttrsPerKey)
|
setVals, errSet := util.GenerateRandomNonRepeatingUint64(c.KeypadSize.AttrsPerKey)
|
||||||
if errSet != nil {
|
if errSet != nil {
|
||||||
return errSet
|
return errSet
|
||||||
}
|
}
|
||||||
@@ -69,6 +69,6 @@ func (c *CustomerAttributes) GetAttrSetVal(attrVal uint64) (uint64, error) {
|
|||||||
if indexOfAttr == -1 {
|
if indexOfAttr == -1 {
|
||||||
return 0, errors.New(fmt.Sprintf("No attribute %d", attrVal))
|
return 0, errors.New(fmt.Sprintf("No attribute %d", attrVal))
|
||||||
}
|
}
|
||||||
setIdx := indexOfAttr % c.keypadSize.AttrsPerKey
|
setIdx := indexOfAttr % c.KeypadSize.AttrsPerKey
|
||||||
return c.SetVals[setIdx], nil
|
return c.SetVals[setIdx], nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,67 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"go-nkode/models"
|
"go-nkode/models"
|
||||||
|
"go-nkode/util"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func SelectKeyByAttrIdx(interfaceUser []int, passcodeIdxs []int, keypadSize models.KeypadSize) ([]int, error) {
|
||||||
|
selectedKeys := make([]int, len(passcodeIdxs))
|
||||||
|
for idx := range passcodeIdxs {
|
||||||
|
attrIdx := util.IndexOf[int](interfaceUser, passcodeIdxs[idx])
|
||||||
|
keyNumb := attrIdx / keypadSize.AttrsPerKey
|
||||||
|
if keyNumb < 0 || keyNumb >= keypadSize.NumbOfKeys {
|
||||||
|
return nil, errors.New(fmt.Sprintf("index key number: %d out of range 0-%d", keyNumb, keypadSize.NumbOfKeys-1))
|
||||||
|
}
|
||||||
|
selectedKeys[idx] = keyNumb
|
||||||
|
}
|
||||||
|
return selectedKeys, nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestNewCustomerAttributes(t *testing.T) {
|
func TestNewCustomerAttributes(t *testing.T) {
|
||||||
keypad := models.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 5}
|
keypad := models.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 5}
|
||||||
_, nil := NewCustomerAttributes(keypad)
|
_, nil := NewCustomerAttributes(keypad)
|
||||||
assert.NoError(t, nil)
|
assert.NoError(t, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCustomer_ValidKeyEntry(t *testing.T) {
|
||||||
|
keypadSize := models.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 7}
|
||||||
|
nkodePolicy := models.NewDefaultNKodePolicy()
|
||||||
|
customer, err := NewCustomer(keypadSize, nkodePolicy)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
newUserInterface, err := NewUserInterface(customer.Attributes.KeypadSize)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
username := "testing123"
|
||||||
|
passcodeIdx := []int{0, 1, 2, 3}
|
||||||
|
err = customer.AddNewUser(username, passcodeIdx, *newUserInterface)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
userLoginInterface, err := customer.GetLoginInterface(username)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
selectedKeys, err := SelectKeyByAttrIdx(userLoginInterface, passcodeIdx, keypadSize)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
validatedPasscode, err := customer.ValidKeyEntry(username, selectedKeys)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, len(validatedPasscode), len(passcodeIdx))
|
||||||
|
for idx := range validatedPasscode {
|
||||||
|
assert.Equal(t, validatedPasscode[idx], passcodeIdx[idx])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCustomer_IsValidNKode(t *testing.T) {
|
||||||
|
keypadSize := models.KeypadSize{AttrsPerKey: 10, NumbOfKeys: 7}
|
||||||
|
nkodePolicy := models.NewDefaultNKodePolicy()
|
||||||
|
customer, err := NewCustomer(keypadSize, nkodePolicy)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
newUserInterface, err := NewUserInterface(customer.Attributes.KeypadSize)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
username := "testing123"
|
||||||
|
passcodeIdx := []int{0, 1, 2, 3}
|
||||||
|
err = customer.AddNewUser(username, passcodeIdx, *newUserInterface)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = customer.IsValidNKode(passcodeIdx)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|||||||
@@ -51,3 +51,13 @@ func (s *Set[T]) IsDisjoint(otherSet Set[T]) bool {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Set[T]) Intersect(otherSet Set[T]) Set[T] {
|
||||||
|
intersect := make(Set[T])
|
||||||
|
for val, _ := range *s {
|
||||||
|
if otherSet.Contains(val) {
|
||||||
|
intersect.Add(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return intersect
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,12 +17,3 @@ type EncipheredNKode struct {
|
|||||||
Code string
|
Code string
|
||||||
Mask string
|
Mask string
|
||||||
}
|
}
|
||||||
|
|
||||||
type NKodePolicy struct {
|
|
||||||
MaxNkodeLen int
|
|
||||||
MinNkodeLen int
|
|
||||||
DistinctSets int
|
|
||||||
DistinctAttributes int
|
|
||||||
LockOut int
|
|
||||||
Expiration int // seconds, -1 no expiration
|
|
||||||
}
|
|
||||||
|
|||||||
21
models/nkode_policy.go
Normal file
21
models/nkode_policy.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
type NKodePolicy struct {
|
||||||
|
MaxNkodeLen int
|
||||||
|
MinNkodeLen int
|
||||||
|
DistinctSets int
|
||||||
|
DistinctAttributes int
|
||||||
|
LockOut int
|
||||||
|
Expiration int // seconds, -1 no expiration
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDefaultNKodePolicy() NKodePolicy {
|
||||||
|
return NKodePolicy{
|
||||||
|
MinNkodeLen: 4,
|
||||||
|
MaxNkodeLen: 10,
|
||||||
|
DistinctSets: 0,
|
||||||
|
DistinctAttributes: 4,
|
||||||
|
LockOut: 5,
|
||||||
|
Expiration: -1,
|
||||||
|
}
|
||||||
|
}
|
||||||
66
nkode_api.go
Normal file
66
nkode_api.go
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"go-nkode/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NKodeAPI struct {
|
||||||
|
Customers map[uuid.UUID]Customer
|
||||||
|
SignupSessions map[uuid.UUID]UserSignSession
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNKodeAPI() NKodeAPI {
|
||||||
|
return NKodeAPI{
|
||||||
|
Customers: make(map[uuid.UUID]Customer),
|
||||||
|
SignupSessions: make(map[uuid.UUID]UserSignSession),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NKodeAPI) CreateNewCustomer(keypadSize models.KeypadSize, nkodePolicy models.NKodePolicy) (*uuid.UUID, error) {
|
||||||
|
newCustomer, err := NewCustomer(keypadSize, nkodePolicy)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
n.Customers[newCustomer.CustomerId] = *newCustomer
|
||||||
|
return &newCustomer.CustomerId, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NKodeAPI) GenerateSignupInterface(customerId uuid.UUID) (*uuid.UUID, []int, error) {
|
||||||
|
customer, exists := n.Customers[customerId]
|
||||||
|
if !exists {
|
||||||
|
return nil, nil, errors.New(fmt.Sprintf("customer doesnt exists: %s", customerId.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
signupSession, err := NewSignupSession(customer.Attributes.KeypadSize, customer.CustomerId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
n.SignupSessions[signupSession.SessionId] = *signupSession
|
||||||
|
return &signupSession.SessionId, signupSession.SetInterface, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NKodeAPI) SetNKode(username string, customerId uuid.UUID, keySelection []int, sessionId uuid.UUID) ([]int, error) {
|
||||||
|
customer, exists := n.Customers[customerId]
|
||||||
|
if !exists {
|
||||||
|
return nil, errors.New(fmt.Sprintf("set nkode customer id does not exist %s", customerId.String()))
|
||||||
|
}
|
||||||
|
_, exists = customer.Users[username]
|
||||||
|
if exists {
|
||||||
|
return nil, errors.New(fmt.Sprintf("user already exists %s", username))
|
||||||
|
}
|
||||||
|
|
||||||
|
session, exists := n.SignupSessions[sessionId]
|
||||||
|
if !exists {
|
||||||
|
return nil, errors.New(fmt.Sprintf("session id does not exist %s", sessionId.String()))
|
||||||
|
}
|
||||||
|
confirmInterface, err := session.SetUserNKode(username, keySelection)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return confirmInterface, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NKodeAPI) ConfirmNKode(username string, customerId uuid.UUID, confirmKeyEntry []int)
|
||||||
164
user_signup_session.go
Normal file
164
user_signup_session.go
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"go-nkode/hashset"
|
||||||
|
"go-nkode/models"
|
||||||
|
py_builtin "go-nkode/py-builtin"
|
||||||
|
"go-nkode/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserSignSession struct {
|
||||||
|
SessionId uuid.UUID
|
||||||
|
CustomerId uuid.UUID
|
||||||
|
LoginInterface UserInterface
|
||||||
|
KeypadSize models.KeypadSize
|
||||||
|
SetInterface []int
|
||||||
|
ConfirmInterface []int
|
||||||
|
SetKeyEntry []int
|
||||||
|
Username string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSignupSession(keypadSize models.KeypadSize, customerId uuid.UUID) (*UserSignSession, error) {
|
||||||
|
loginInterface, err := NewUserInterface(keypadSize)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
signupInter, err := signupInterface(*loginInterface)
|
||||||
|
session := UserSignSession{
|
||||||
|
SessionId: uuid.New(),
|
||||||
|
CustomerId: customerId,
|
||||||
|
LoginInterface: *loginInterface,
|
||||||
|
SetInterface: signupInter.IdxInterface,
|
||||||
|
ConfirmInterface: nil,
|
||||||
|
SetKeyEntry: nil,
|
||||||
|
Username: "",
|
||||||
|
KeypadSize: signupInter.KeypadSize,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &session, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *UserSignSession) DeducePasscode(confirmKeyEntry []int) ([]int, error) {
|
||||||
|
validEntry := py_builtin.All[int](confirmKeyEntry, func(i int) bool {
|
||||||
|
return 0 <= i && i < s.LoginInterface.KeypadSize.NumbOfKeys
|
||||||
|
})
|
||||||
|
|
||||||
|
if !validEntry {
|
||||||
|
return nil, errors.New(fmt.Sprintf("Invalid Key entry. One or more key index: %#v, not in range 0-%d", confirmKeyEntry, s.LoginInterface.KeypadSize.NumbOfKeys))
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.SetInterface == nil {
|
||||||
|
return nil, errors.New("signup session set interface is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.ConfirmInterface == nil {
|
||||||
|
return nil, errors.New("signup session confirm interface is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.SetKeyEntry == nil {
|
||||||
|
return nil, errors.New("signup session set key entry is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Username == "" {
|
||||||
|
return nil, errors.New("signup session username is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(confirmKeyEntry) == len(s.SetKeyEntry) {
|
||||||
|
return nil, errors.New(fmt.Sprintf("confirm and set key entry lenght mismatch %d != %d", len(confirmKeyEntry), len(s.SetKeyEntry)))
|
||||||
|
}
|
||||||
|
|
||||||
|
passcodeLen := len(confirmKeyEntry)
|
||||||
|
setKeyVals, err := s.getSelectedKeyVals(s.SetKeyEntry, s.SetInterface)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
confirmKeyVals, err := s.getSelectedKeyVals(confirmKeyEntry, s.ConfirmInterface)
|
||||||
|
passcode := make([]int, passcodeLen)
|
||||||
|
|
||||||
|
for idx := 0; idx < passcodeLen; idx++ {
|
||||||
|
setKey := hashset.NewSetFromSlice[int](setKeyVals[idx])
|
||||||
|
confirmKey := hashset.NewSetFromSlice[int](confirmKeyVals[idx])
|
||||||
|
intersection := setKey.Intersect(confirmKey)
|
||||||
|
if intersection.Size() < 1 {
|
||||||
|
return nil, errors.New(fmt.Sprintf("set and confirm do not intersect at index %d", idx))
|
||||||
|
}
|
||||||
|
if intersection.Size() > 1 {
|
||||||
|
return nil, errors.New(fmt.Sprintf("set and confirm intersect at more than one point at index %d", idx))
|
||||||
|
}
|
||||||
|
intersectionSlice := intersection.ToSlice()
|
||||||
|
passcode[idx] = intersectionSlice[0]
|
||||||
|
}
|
||||||
|
return passcode, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *UserSignSession) SetUserNKode(username string, keySelection []int) ([]int, error) {
|
||||||
|
validKeySelection := py_builtin.All[int](keySelection, func(i int) bool {
|
||||||
|
return 0 <= i && i < s.KeypadSize.NumbOfKeys
|
||||||
|
})
|
||||||
|
if !validKeySelection {
|
||||||
|
return nil, errors.New(fmt.Sprintf("one or key selection is out of range 0-%d", s.KeypadSize.NumbOfKeys-1))
|
||||||
|
}
|
||||||
|
|
||||||
|
s.SetKeyEntry = keySelection
|
||||||
|
s.Username = username
|
||||||
|
|
||||||
|
setInterface := UserInterface{IdxInterface: s.SetInterface, KeypadSize: s.KeypadSize}
|
||||||
|
err := setInterface.DisperseInterface()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
s.ConfirmInterface = setInterface.IdxInterface
|
||||||
|
return s.ConfirmInterface, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *UserSignSession) getSelectedKeyVals(keySelections []int, userInterface []int) ([][]int, error) {
|
||||||
|
keypadInterface, err := util.ListToMatrix(userInterface, s.KeypadSize.AttrsPerKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
keyVals := make([][]int, len(keySelections))
|
||||||
|
|
||||||
|
for idx, keyIdx := range keySelections {
|
||||||
|
keyVals[idx] = keypadInterface[keyIdx]
|
||||||
|
}
|
||||||
|
return keyVals, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func signupInterface(baseUserInterface UserInterface) (*UserInterface, error) {
|
||||||
|
if baseUserInterface.KeypadSize.IsDispersable() {
|
||||||
|
return nil, errors.New("keypad is dispersable, can't use signupInterface")
|
||||||
|
}
|
||||||
|
err := baseUserInterface.RandomShuffle()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
interfaceMatrix, err := baseUserInterface.InterfaceMatrix()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
attrSetView, err := util.MatrixTranspose(interfaceMatrix)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = util.FisherYatesShuffle[[]int](&attrSetView)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
numbOfKeys := baseUserInterface.KeypadSize.NumbOfKeys
|
||||||
|
attrSetView = attrSetView[:numbOfKeys]
|
||||||
|
attrSetView, err = util.MatrixTranspose(attrSetView)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
signupUserInterface := UserInterface{
|
||||||
|
IdxInterface: util.MatrixToList(attrSetView),
|
||||||
|
KeypadSize: models.KeypadSize{
|
||||||
|
AttrsPerKey: numbOfKeys,
|
||||||
|
NumbOfKeys: numbOfKeys,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return &signupUserInterface, nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user