refactor code to fewer files; remove unused code

This commit is contained in:
2024-09-21 11:04:09 -05:00
parent b7a4a5cf4c
commit 2b3abb8fb2
29 changed files with 486 additions and 557 deletions

View File

@@ -1,12 +0,0 @@
package api
const (
CreateNewCustomer = "/create-new-customer"
GenerateSignupInterface = "/generate-signup-interface"
SetNKode = "/set-nkode"
ConfirmNKode = "/confirm-nkode"
GetLoginInterface = "/get-login-interface"
Login = "/login"
RenewAttributes = "/renew-attributes"
RandomSvgInterface = "/random-svg-interface"
)

View File

@@ -1,4 +1,4 @@
package model package core
import ( import (
"errors" "errors"

View File

@@ -1,4 +1,4 @@
package model package core
import ( import (
"errors" "errors"

View File

@@ -1,8 +1,7 @@
package nkode package core
import ( import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go-nkode/core/model"
"testing" "testing"
) )
@@ -13,26 +12,25 @@ func TestCustomer(t *testing.T) {
} }
func testNewCustomerAttributes(t *testing.T) { func testNewCustomerAttributes(t *testing.T) {
// keypad := m.KeypadDimension{AttrsPerKey: 10, NumbOfKeys: 5} _, nil := NewCustomerAttributes()
_, nil := model.NewCustomerAttributes()
assert.NoError(t, nil) assert.NoError(t, nil)
} }
func testCustomerValidKeyEntry(t *testing.T) { func testCustomerValidKeyEntry(t *testing.T) {
kp := model.KeypadDimension{AttrsPerKey: 10, NumbOfKeys: 9} kp := KeypadDimension{AttrsPerKey: 10, NumbOfKeys: 9}
nkodePolicy := model.NewDefaultNKodePolicy() nkodePolicy := NewDefaultNKodePolicy()
customer, err := model.NewCustomer(nkodePolicy) customer, err := NewCustomer(nkodePolicy)
assert.NoError(t, err) assert.NoError(t, err)
mockSvgInterface := make(model.SvgIdInterface, kp.TotalAttrs()) mockSvgInterface := make(SvgIdInterface, kp.TotalAttrs())
userInterface, err := model.NewUserInterface(&kp, mockSvgInterface) userInterface, err := NewUserInterface(&kp, mockSvgInterface)
assert.NoError(t, err) assert.NoError(t, err)
username := model.Username("testing123") username := Username("testing123")
passcodeIdx := []int{0, 1, 2, 3} passcodeIdx := []int{0, 1, 2, 3}
user, err := NewUser(*customer, username, passcodeIdx, *userInterface, kp) user, err := NewUser(*customer, username, passcodeIdx, *userInterface, kp)
assert.NoError(t, err) assert.NoError(t, err)
userLoginInterface, err := user.GetLoginInterface() userLoginInterface, err := user.GetLoginInterface()
assert.NoError(t, err) assert.NoError(t, err)
selectedKeys, err := model.SelectKeyByAttrIdx(userLoginInterface, passcodeIdx, kp) selectedKeys, err := SelectKeyByAttrIdx(userLoginInterface, passcodeIdx, kp)
assert.NoError(t, err) assert.NoError(t, err)
validatedPasscode, err := ValidKeyEntry(*user, *customer, selectedKeys) validatedPasscode, err := ValidKeyEntry(*user, *customer, selectedKeys)
assert.NoError(t, err) assert.NoError(t, err)
@@ -43,14 +41,14 @@ func testCustomerValidKeyEntry(t *testing.T) {
} }
func testCustomerIsValidNKode(t *testing.T) { func testCustomerIsValidNKode(t *testing.T) {
kp := model.KeypadDimension{AttrsPerKey: 10, NumbOfKeys: 7} kp := KeypadDimension{AttrsPerKey: 10, NumbOfKeys: 7}
nkodePolicy := model.NewDefaultNKodePolicy() nkodePolicy := NewDefaultNKodePolicy()
customer, err := model.NewCustomer(nkodePolicy) customer, err := NewCustomer(nkodePolicy)
assert.NoError(t, err) assert.NoError(t, err)
mockSvgInterface := make(model.SvgIdInterface, kp.TotalAttrs()) mockSvgInterface := make(SvgIdInterface, kp.TotalAttrs())
userInterface, err := model.NewUserInterface(&kp, mockSvgInterface) userInterface, err := NewUserInterface(&kp, mockSvgInterface)
assert.NoError(t, err) assert.NoError(t, err)
username := model.Username("testing123") username := Username("testing123")
passcodeIdx := []int{0, 1, 2, 3} passcodeIdx := []int{0, 1, 2, 3}
user, err := NewUser(*customer, username, passcodeIdx, *userInterface, kp) user, err := NewUser(*customer, username, passcodeIdx, *userInterface, kp)
assert.NoError(t, err) assert.NoError(t, err)

View File

@@ -1,26 +1,25 @@
package nkode package core
import ( import (
"errors" "errors"
"fmt" "fmt"
m "go-nkode/core/model"
) )
type InMemoryDb struct { type InMemoryDb struct {
Customers map[m.CustomerId]m.Customer Customers map[CustomerId]Customer
Users map[m.UserId]m.User Users map[UserId]User
userIdMap map[string]m.UserId userIdMap map[string]UserId
} }
func NewInMemoryDb() InMemoryDb { func NewInMemoryDb() InMemoryDb {
return InMemoryDb{ return InMemoryDb{
Customers: make(map[m.CustomerId]m.Customer), Customers: make(map[CustomerId]Customer),
Users: make(map[m.UserId]m.User), Users: make(map[UserId]User),
userIdMap: make(map[string]m.UserId), userIdMap: make(map[string]UserId),
} }
} }
func (db *InMemoryDb) GetCustomer(id m.CustomerId) (*m.Customer, error) { func (db *InMemoryDb) GetCustomer(id CustomerId) (*Customer, error) {
customer, exists := db.Customers[id] customer, exists := db.Customers[id]
if !exists { if !exists {
return nil, errors.New(fmt.Sprintf("customer %s dne", customer.Id)) return nil, errors.New(fmt.Sprintf("customer %s dne", customer.Id))
@@ -28,7 +27,7 @@ func (db *InMemoryDb) GetCustomer(id m.CustomerId) (*m.Customer, error) {
return &customer, nil return &customer, nil
} }
func (db *InMemoryDb) GetUser(username m.Username, customerId m.CustomerId) (*m.User, error) { func (db *InMemoryDb) GetUser(username Username, customerId CustomerId) (*User, error) {
key := userIdKey(customerId, username) key := userIdKey(customerId, username)
userId, exists := db.userIdMap[key] userId, exists := db.userIdMap[key]
if !exists { if !exists {
@@ -41,7 +40,7 @@ func (db *InMemoryDb) GetUser(username m.Username, customerId m.CustomerId) (*m.
return &user, nil return &user, nil
} }
func (db *InMemoryDb) WriteNewCustomer(customer m.Customer) error { func (db *InMemoryDb) WriteNewCustomer(customer Customer) error {
_, exists := db.Customers[customer.Id] _, exists := db.Customers[customer.Id]
if exists { if exists {
@@ -51,7 +50,7 @@ func (db *InMemoryDb) WriteNewCustomer(customer m.Customer) error {
return nil return nil
} }
func (db *InMemoryDb) WriteNewUser(user m.User) error { func (db *InMemoryDb) WriteNewUser(user User) error {
_, exists := db.Customers[user.CustomerId] _, exists := db.Customers[user.CustomerId]
if !exists { if !exists {
return errors.New(fmt.Sprintf("can't add user %s to customer %s: customer dne", user.Username, user.CustomerId)) return errors.New(fmt.Sprintf("can't add user %s to customer %s: customer dne", user.Username, user.CustomerId))
@@ -67,16 +66,17 @@ func (db *InMemoryDb) WriteNewUser(user m.User) error {
return nil return nil
} }
func (db *InMemoryDb) UpdateUserInterface(userId m.UserId, ui m.UserInterface) error { func (db *InMemoryDb) UpdateUserInterface(userId UserId, ui UserInterface) error {
user, exists := db.Users[userId] user, exists := db.Users[userId]
if !exists { if !exists {
return errors.New(fmt.Sprintf("can't update user %s, dne", user.Id)) return errors.New(fmt.Sprintf("can't update user %s, dne", user.Id))
} }
user.Interface = ui user.Interface = ui
db.Users[userId] = user
return nil return nil
} }
func (db *InMemoryDb) Renew(id m.CustomerId) error { func (db *InMemoryDb) Renew(id CustomerId) error {
customer, exists := db.Customers[id] customer, exists := db.Customers[id]
if !exists { if !exists {
return errors.New(fmt.Sprintf("customer %s does not exist", id)) return errors.New(fmt.Sprintf("customer %s does not exist", id))
@@ -88,7 +88,7 @@ func (db *InMemoryDb) Renew(id m.CustomerId) error {
if user.CustomerId == id { if user.CustomerId == id {
err = user.RenewKeys(setXor, attrsXor) err = user.RenewKeys(setXor, attrsXor)
if err != nil { if err != nil {
panic(err) return err
} }
db.Users[user.Id] = user db.Users[user.Id] = user
} }
@@ -96,7 +96,7 @@ func (db *InMemoryDb) Renew(id m.CustomerId) error {
return nil return nil
} }
func (db *InMemoryDb) RefreshUser(user m.User, passocode []int, customerAttr m.CustomerAttributes) error { func (db *InMemoryDb) RefreshUser(user User, passocode []int, customerAttr CustomerAttributes) error {
err := user.RefreshPasscode(passocode, customerAttr) err := user.RefreshPasscode(passocode, customerAttr)
if err != nil { if err != nil {
return err return err
@@ -105,19 +105,23 @@ func (db *InMemoryDb) RefreshUser(user m.User, passocode []int, customerAttr m.C
return nil return nil
} }
func (db *InMemoryDb) RandomSvgInterface(kp m.KeypadDimension) ([]string, error) { func (db *InMemoryDb) RandomSvgInterface(kp KeypadDimension) ([]string, error) {
return nil, errors.ErrUnsupported return make([]string, kp.TotalAttrs()), nil
} }
func (db *InMemoryDb) RandomSvgIdxInterface(kp m.KeypadDimension) (m.SvgIdInterface, error) { func (db *InMemoryDb) RandomSvgIdxInterface(kp KeypadDimension) (SvgIdInterface, error) {
return nil, errors.ErrUnsupported svgs := make(SvgIdInterface, kp.TotalAttrs())
for idx := range svgs {
svgs[idx] = idx
}
return svgs, nil
} }
func (db InMemoryDb) GetSvgStringInterface(idxs m.SvgIdInterface) ([]string, error) { func (db InMemoryDb) GetSvgStringInterface(idxs SvgIdInterface) ([]string, error) {
return nil, errors.ErrUnsupported return make([]string, len(idxs)), nil
} }
func userIdKey(customerId m.CustomerId, username m.Username) string { func userIdKey(customerId CustomerId, username Username) string {
key := fmt.Sprintf("%s:%s", customerId, username) key := fmt.Sprintf("%s:%s", customerId, username)
return key return key
} }

View File

@@ -1,4 +1,4 @@
package model package core
import "errors" import "errors"
@@ -29,8 +29,8 @@ var (
} }
KeypadMin = KeypadDimension{ KeypadMin = KeypadDimension{
AttrsPerKey: 6, AttrsPerKey: 5,
NumbOfKeys: 5, NumbOfKeys: 4,
} }
KeypadDefault = KeypadDimension{ KeypadDefault = KeypadDimension{

View File

@@ -1,58 +0,0 @@
package model
import (
"go-nkode/util"
)
type User struct {
Id UserId
CustomerId CustomerId
Username Username
EncipheredPasscode EncipheredNKode
Kp KeypadDimension
CipherKeys UserCipherKeys
Interface UserInterface
Renew bool
}
func (u *User) DecipherMask(setVals []uint64, passcodeLen int) ([]uint64, error) {
return u.CipherKeys.DecipherMask(u.EncipheredPasscode.Mask, setVals, passcodeLen)
}
func (u *User) RenewKeys(setXor []uint64, attrXor []uint64) error {
u.Renew = true
var err error
u.CipherKeys.SetKey, err = util.XorLists(setXor[:u.Kp.AttrsPerKey], u.CipherKeys.SetKey)
if err != nil {
panic(err)
}
u.CipherKeys.AlphaKey, err = util.XorLists(attrXor[:u.Kp.TotalAttrs()], u.CipherKeys.AlphaKey)
return err
}
func (u *User) RefreshPasscode(passcodeAttrIdx []int, customerAttributes CustomerAttributes) error {
setVals, err := customerAttributes.SetValsForKp(u.Kp)
newKeys, err := NewUserCipherKeys(&u.Kp, setVals, u.CipherKeys.MaxNKodeLen)
if err != nil {
return err
}
encipheredPasscode, err := newKeys.EncipherNKode(passcodeAttrIdx, customerAttributes)
if err != nil {
return err
}
u.CipherKeys = *newKeys
u.EncipheredPasscode = *encipheredPasscode
u.Renew = false
return nil
}
func (u *User) GetLoginInterface() ([]int, error) {
err := u.Interface.PartialInterfaceShuffle()
if err != nil {
return nil, err
}
return u.Interface.IdxInterface, nil
}

View File

@@ -1,89 +0,0 @@
package nkode
import (
"errors"
"github.com/google/uuid"
m "go-nkode/core/model"
py "go-nkode/py-builtin"
)
var KeyIndexOutOfRange = errors.New("one or more keys is out of range")
func ValidKeyEntry(user m.User, customer m.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.SetValsForKp(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.AttrValsForKp(user.Kp)
if err != nil {
panic(err)
}
err = user.CipherKeys.ValidPassword(user.EncipheredPasscode.Code, presumedAttrIdxVals, attrVals)
if err != nil {
return nil, err
}
return presumedAttrIdxVals, nil
}
func NewUser(customer m.Customer, username m.Username, passcodeIdx []int, ui m.UserInterface, kp m.KeypadDimension) (*m.User, error) {
setVals, err := customer.Attributes.SetValsForKp(kp)
if err != nil {
return nil, err
}
newKeys, err := m.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 := m.User{
Id: m.UserId(uuid.New()),
Username: username,
EncipheredPasscode: *encipheredNKode,
CipherKeys: *newKeys,
Interface: ui,
Kp: kp,
CustomerId: customer.Id,
}
return &newUser, nil
}

View File

@@ -1,18 +0,0 @@
package nkode
import (
"go-nkode/core/model"
)
type DbAccessor interface {
GetCustomer(model.CustomerId) (*model.Customer, error)
GetUser(model.Username, model.CustomerId) (*model.User, error)
WriteNewCustomer(model.Customer) error
WriteNewUser(model.User) error
UpdateUserInterface(model.UserId, model.UserInterface) error
Renew(model.CustomerId) error
RefreshUser(model.User, []int, model.CustomerAttributes) error
RandomSvgInterface(model.KeypadDimension) ([]string, error)
RandomSvgIdxInterface(model.KeypadDimension) (model.SvgIdInterface, error)
GetSvgStringInterface(model.SvgIdInterface) ([]string, error)
}

View File

@@ -1,26 +1,25 @@
package nkode package core
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/google/uuid" "github.com/google/uuid"
m "go-nkode/core/model"
) )
type NKodeAPI struct { type NKodeAPI struct {
Db DbAccessor Db DbAccessor
SignupSessions map[m.SessionId]UserSignSession SignupSessions map[SessionId]UserSignSession
} }
func NewNKodeAPI(db DbAccessor) NKodeAPI { func NewNKodeAPI(db DbAccessor) NKodeAPI {
return NKodeAPI{ return NKodeAPI{
Db: db, Db: db,
SignupSessions: make(map[m.SessionId]UserSignSession), SignupSessions: make(map[SessionId]UserSignSession),
} }
} }
func (n *NKodeAPI) CreateNewCustomer(nkodePolicy m.NKodePolicy, id *m.CustomerId) (*m.CustomerId, error) { func (n *NKodeAPI) CreateNewCustomer(nkodePolicy NKodePolicy, id *CustomerId) (*CustomerId, error) {
newCustomer, err := m.NewCustomer(nkodePolicy) newCustomer, err := NewCustomer(nkodePolicy)
if id != nil { if id != nil {
newCustomer.Id = *id newCustomer.Id = *id
} }
@@ -35,7 +34,7 @@ func (n *NKodeAPI) CreateNewCustomer(nkodePolicy m.NKodePolicy, id *m.CustomerId
return &newCustomer.Id, nil return &newCustomer.Id, nil
} }
func (n *NKodeAPI) GenerateSignupInterface(username m.Username, customerId m.CustomerId, kp m.KeypadDimension) (*m.GenerateSignupInterfaceResp, error) { func (n *NKodeAPI) GenerateSignupInterface(username Username, customerId CustomerId, kp KeypadDimension) (*GenerateSignupInterfaceResp, error) {
svgIdxInterface, err := n.Db.RandomSvgIdxInterface(kp) svgIdxInterface, err := n.Db.RandomSvgIdxInterface(kp)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -49,7 +48,7 @@ func (n *NKodeAPI) GenerateSignupInterface(username m.Username, customerId m.Cus
if err != nil { if err != nil {
return nil, err return nil, err
} }
resp := m.GenerateSignupInterfaceResp{ resp := GenerateSignupInterfaceResp{
UserIdxInterface: signupSession.SetIdxInterface, UserIdxInterface: signupSession.SetIdxInterface,
SvgInterface: svgInterface, SvgInterface: svgInterface,
SessionId: uuid.UUID(signupSession.Id).String(), SessionId: uuid.UUID(signupSession.Id).String(),
@@ -57,7 +56,7 @@ func (n *NKodeAPI) GenerateSignupInterface(username m.Username, customerId m.Cus
return &resp, nil return &resp, nil
} }
func (n *NKodeAPI) SetNKode(customerId m.CustomerId, sessionId m.SessionId, keySelection m.KeySelection) (m.IdxInterface, error) { func (n *NKodeAPI) SetNKode(customerId CustomerId, sessionId SessionId, keySelection KeySelection) (IdxInterface, error) {
_, err := n.Db.GetCustomer(customerId) _, err := n.Db.GetCustomer(customerId)
if err != nil { if err != nil {
@@ -75,7 +74,7 @@ func (n *NKodeAPI) SetNKode(customerId m.CustomerId, sessionId m.SessionId, keyS
return confirmInterface, nil return confirmInterface, nil
} }
func (n *NKodeAPI) ConfirmNKode(customerId m.CustomerId, sessionId m.SessionId, keySelection m.KeySelection) error { func (n *NKodeAPI) ConfirmNKode(customerId CustomerId, sessionId SessionId, keySelection KeySelection) error {
session, exists := n.SignupSessions[sessionId] session, exists := n.SignupSessions[sessionId]
if !exists { if !exists {
return errors.New(fmt.Sprintf("session id does not exist %s", sessionId)) return errors.New(fmt.Sprintf("session id does not exist %s", sessionId))
@@ -101,7 +100,7 @@ func (n *NKodeAPI) ConfirmNKode(customerId m.CustomerId, sessionId m.SessionId,
return err return err
} }
func (n *NKodeAPI) GetLoginInterface(username m.Username, customerId m.CustomerId) (*m.GetLoginInterfaceResp, error) { func (n *NKodeAPI) GetLoginInterface(username Username, customerId CustomerId) (*GetLoginInterfaceResp, error) {
user, err := n.Db.GetUser(username, customerId) user, err := n.Db.GetUser(username, customerId)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -118,43 +117,50 @@ func (n *NKodeAPI) GetLoginInterface(username m.Username, customerId m.CustomerI
if err != nil { if err != nil {
return nil, err return nil, err
} }
resp := m.GetLoginInterfaceResp{ resp := GetLoginInterfaceResp{
UserIdxInterface: user.Interface.IdxInterface, UserIdxInterface: user.Interface.IdxInterface,
SvgInterface: svgInterface, SvgInterface: svgInterface,
NumbOfKeys: user.Kp.NumbOfKeys,
AttrsPerKey: user.Kp.AttrsPerKey,
} }
return &resp, nil return &resp, nil
} }
func (n *NKodeAPI) Login(customerId m.CustomerId, username m.Username, keySelection m.KeySelection) error { func (n *NKodeAPI) Login(customerId CustomerId, username Username, keySelection KeySelection) (string, error) {
customer, err := n.Db.GetCustomer(customerId) customer, err := n.Db.GetCustomer(customerId)
if err != nil { if err != nil {
return err return "", err
} }
user, err := n.Db.GetUser(username, customerId) user, err := n.Db.GetUser(username, customerId)
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("user dne %s", username)) return "", errors.New(fmt.Sprintf("user dne %s", username))
} }
passcode, err := ValidKeyEntry(*user, *customer, keySelection) passcode, err := ValidKeyEntry(*user, *customer, keySelection)
if err != nil { if err != nil {
return err return "", err
} }
if user.Renew { if user.Renew {
err = n.Db.RefreshUser(*user, passcode, customer.Attributes) err = n.Db.RefreshUser(*user, passcode, customer.Attributes)
if err != nil { if err != nil {
return err return "", err
} }
} }
return nil return "", nil
} }
func (n *NKodeAPI) RenewAttributes(customerId m.CustomerId) error { func (n *NKodeAPI) RenewAttributes(customerId CustomerId) error {
return n.Db.Renew(customerId) return n.Db.Renew(customerId)
} }
func (n *NKodeAPI) RandomSvgInterface() ([]string, error) { func (n *NKodeAPI) RandomSvgInterface() ([]string, error) {
return n.Db.RandomSvgInterface(m.KeypadMax) return n.Db.RandomSvgInterface(KeypadMax)
} }
func (n *NKodeAPI) GetSvgStringInterface(svgId m.SvgIdInterface) ([]string, error) { func (n *NKodeAPI) GetSvgStringInterface(svgId SvgIdInterface) ([]string, error) {
return n.Db.GetSvgStringInterface(svgId) return n.Db.GetSvgStringInterface(svgId)
} }
func (n *NKodeAPI) RefreshToken(jwt string) (string, error) {
return "", nil
}

View File

@@ -1,22 +1,20 @@
package nkode package core
import ( import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
m "go-nkode/core/model"
"go-nkode/util" "go-nkode/util"
"testing" "testing"
) )
func TestNKodeAPI(t *testing.T) { func TestNKodeAPI(t *testing.T) {
//db1 := NewInMemoryDb() db1 := NewInMemoryDb()
//1testNKodeAPI(t, &db1) testNKodeAPI(t, &db1)
dbFile := "../../test.db" //dbFile := "../../test.db"
// sql_driver.MakeTables(dbFile) //db2 := NewSqliteDB(dbFile)
db2 := NewSqliteDB(dbFile) //defer db2.CloseDb()
defer db2.CloseDb() //testNKodeAPI(t, db2)
testNKodeAPI(t, db2)
// if _, err := os.Stat(dbFile); err == nil { // if _, err := os.Stat(dbFile); err == nil {
// err = os.Remove(dbFile) // err = os.Remove(dbFile)
@@ -27,35 +25,38 @@ func TestNKodeAPI(t *testing.T) {
} }
func testNKodeAPI(t *testing.T, db DbAccessor) { func testNKodeAPI(t *testing.T, db DbAccessor) {
attrsPerKey := 5
numbOfKeys := 4
for idx := 0; idx < 1; idx++ { for idx := 0; idx < 1; idx++ {
username := m.Username("test_username" + util.GenerateRandomString(12)) username := Username("test_username" + util.GenerateRandomString(12))
passcodeLen := 4 passcodeLen := 4
nkodePolicy := m.NewDefaultNKodePolicy() nkodePolicy := NewDefaultNKodePolicy()
keypadSize := m.KeypadDimension{AttrsPerKey: 10, NumbOfKeys: 8} keypadSize := KeypadDimension{AttrsPerKey: attrsPerKey, NumbOfKeys: numbOfKeys}
nkodeApi := NewNKodeAPI(db) nkodeApi := NewNKodeAPI(db)
customerId, err := nkodeApi.CreateNewCustomer(nkodePolicy, nil) customerId, err := nkodeApi.CreateNewCustomer(nkodePolicy, nil)
assert.NoError(t, err) assert.NoError(t, err)
signupResponse, err := nkodeApi.GenerateSignupInterface(username, *customerId, keypadSize) signupResponse, err := nkodeApi.GenerateSignupInterface(username, *customerId, keypadSize)
assert.NoError(t, err) assert.NoError(t, err)
setInterface := signupResponse.UserIdxInterface setInterface := signupResponse.UserIdxInterface
sessionId := signupResponse.SessionId sessionIdStr := signupResponse.SessionId
keypadSize = m.KeypadDimension{AttrsPerKey: 8, NumbOfKeys: 8} sessionId, err := SessionIdFromString(sessionIdStr)
assert.NoError(t, err)
keypadSize = KeypadDimension{AttrsPerKey: numbOfKeys, NumbOfKeys: numbOfKeys}
userPasscode := setInterface[:passcodeLen] userPasscode := setInterface[:passcodeLen]
setKeySelect, err := m.SelectKeyByAttrIdx(setInterface, userPasscode, keypadSize) setKeySelect, err := SelectKeyByAttrIdx(setInterface, userPasscode, keypadSize)
assert.NoError(t, err) assert.NoError(t, err)
confirmInterface, err := nkodeApi.SetNKode(*customerId, sessionId, setKeySelect) confirmInterface, err := nkodeApi.SetNKode(*customerId, sessionId, setKeySelect)
assert.NoError(t, err) assert.NoError(t, err)
confirmKeySelect, err := m.SelectKeyByAttrIdx(confirmInterface, userPasscode, keypadSize) confirmKeySelect, err := SelectKeyByAttrIdx(confirmInterface, userPasscode, keypadSize)
err = nkodeApi.ConfirmNKode(*customerId, sessionId, confirmKeySelect) err = nkodeApi.ConfirmNKode(*customerId, sessionId, confirmKeySelect)
assert.NoError(t, err) assert.NoError(t, err)
keypadSize = m.KeypadDimension{AttrsPerKey: 10, NumbOfKeys: 8} keypadSize = KeypadDimension{AttrsPerKey: attrsPerKey, NumbOfKeys: numbOfKeys}
loginInterface, err := nkodeApi.GetLoginInterface(username, *customerId) loginInterface, err := nkodeApi.GetLoginInterface(username, *customerId)
assert.NoError(t, err) assert.NoError(t, err)
loginKeySelection, err := m.SelectKeyByAttrIdx(loginInterface.UserIdxInterface, userPasscode, keypadSize) loginKeySelection, err := SelectKeyByAttrIdx(loginInterface.UserIdxInterface, userPasscode, keypadSize)
assert.NoError(t, err) assert.NoError(t, err)
err = nkodeApi.Login(*customerId, username, loginKeySelection) _, err = nkodeApi.Login(*customerId, username, loginKeySelection)
assert.NoError(t, err) assert.NoError(t, err)
err = nkodeApi.RenewAttributes(*customerId) err = nkodeApi.RenewAttributes(*customerId)
@@ -63,9 +64,9 @@ func testNKodeAPI(t *testing.T, db DbAccessor) {
loginInterface, err = nkodeApi.GetLoginInterface(username, *customerId) loginInterface, err = nkodeApi.GetLoginInterface(username, *customerId)
assert.NoError(t, err) assert.NoError(t, err)
loginKeySelection, err = m.SelectKeyByAttrIdx(loginInterface.UserIdxInterface, userPasscode, keypadSize) loginKeySelection, err = SelectKeyByAttrIdx(loginInterface.UserIdxInterface, userPasscode, keypadSize)
assert.NoError(t, err) assert.NoError(t, err)
err = nkodeApi.Login(*customerId, username, loginKeySelection) _, err = nkodeApi.Login(*customerId, username, loginKeySelection)
assert.NoError(t, err) assert.NoError(t, err)
} }

View File

@@ -1,36 +1,49 @@
package model package core
import ( import (
"encoding/json" "encoding/json"
"errors" "errors"
"github.com/google/uuid" "github.com/google/uuid"
"go-nkode/core/api"
"log" "log"
"net/http" "net/http"
) )
type NKodeHandler struct { type NKodeHandler struct {
Api NKodeAPIInterface Api NKodeAPI
} }
const (
CreateNewCustomer = "/create-new-customer"
GenerateSignupInterface = "/generate-signup-interface"
SetNKode = "/set-nkode"
ConfirmNKode = "/confirm-nkode"
GetLoginInterface = "/get-login-interface"
Login = "/login"
RenewAttributes = "/renew-attributes"
RandomSvgInterface = "/random-svg-interface"
RefreshToken = "refresh-token"
)
func (h *NKodeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h *NKodeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path { switch r.URL.Path {
case api.CreateNewCustomer: case CreateNewCustomer:
h.CreateNewCustomerHandler(w, r) h.CreateNewCustomerHandler(w, r)
case api.GenerateSignupInterface: case GenerateSignupInterface:
h.GenerateSignupInterfaceHandler(w, r) h.GenerateSignupInterfaceHandler(w, r)
case api.SetNKode: case SetNKode:
h.SetNKodeHandler(w, r) h.SetNKodeHandler(w, r)
case api.ConfirmNKode: case ConfirmNKode:
h.ConfirmNKodeHandler(w, r) h.ConfirmNKodeHandler(w, r)
case api.GetLoginInterface: case GetLoginInterface:
h.GetLoginInterfaceHandler(w, r) h.GetLoginInterfaceHandler(w, r)
case api.Login: case Login:
h.LoginHandler(w, r) h.LoginHandler(w, r)
case api.RenewAttributes: case RenewAttributes:
h.RenewAttributesHandler(w, r) h.RenewAttributesHandler(w, r)
case api.RandomSvgInterface: case RandomSvgInterface:
h.RandomSvgInterfaceHandler(w, r) h.RandomSvgInterfaceHandler(w, r)
case RefreshToken:
h.RefreshTokenHandler(w, r)
default: default:
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
_, err := w.Write([]byte("404 not found")) _, err := w.Write([]byte("404 not found"))
@@ -273,7 +286,7 @@ func (h *NKodeHandler) LoginHandler(w http.ResponseWriter, r *http.Request) {
log.Println(err) log.Println(err)
return return
} }
err = h.Api.Login(CustomerId(customerId), loginPost.Username, loginPost.KeySelection) _, err = h.Api.Login(CustomerId(customerId), loginPost.Username, loginPost.KeySelection)
if err != nil { if err != nil {
internalServerErrorHandler(w) internalServerErrorHandler(w)
log.Println(err) log.Println(err)
@@ -340,6 +353,10 @@ func (h *NKodeHandler) RandomSvgInterfaceHandler(w http.ResponseWriter, r *http.
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
} }
func (h *NKodeHandler) RefreshTokenHandler(w http.ResponseWriter, r *http.Request) {
}
func decodeJson(w http.ResponseWriter, r *http.Request, post any) error { func decodeJson(w http.ResponseWriter, r *http.Request, post any) error {
if r.Body == nil { if r.Body == nil {
invalidJson(w) invalidJson(w)

View File

@@ -1,4 +1,4 @@
package model package core
import ( import (
"errors" "errors"

View File

@@ -1,4 +1,4 @@
package nkode package core
import ( import (
"database/sql" "database/sql"
@@ -6,7 +6,6 @@ import (
"fmt" "fmt"
"github.com/google/uuid" "github.com/google/uuid"
_ "github.com/mattn/go-sqlite3" // Import the SQLite3 driver _ "github.com/mattn/go-sqlite3" // Import the SQLite3 driver
m "go-nkode/core/model"
"go-nkode/util" "go-nkode/util"
"log" "log"
) )
@@ -32,7 +31,7 @@ func (d *SqliteDB) CloseDb() {
} }
} }
func (d *SqliteDB) WriteNewCustomer(c m.Customer) error { func (d *SqliteDB) WriteNewCustomer(c Customer) error {
tx, err := d.db.Begin() tx, err := d.db.Begin()
if err != nil { if err != nil {
return err return err
@@ -60,7 +59,7 @@ VALUES (?,?,?,?,?,?,?,?,?)
return nil return nil
} }
func (d *SqliteDB) WriteNewUser(u m.User) error { func (d *SqliteDB) WriteNewUser(u User) error {
tx, err := d.db.Begin() tx, err := d.db.Begin()
if err != nil { if err != nil {
return err return err
@@ -95,7 +94,7 @@ VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
return nil return nil
} }
func (d *SqliteDB) GetCustomer(id m.CustomerId) (*m.Customer, error) { func (d *SqliteDB) GetCustomer(id CustomerId) (*Customer, error) {
selectCustomer := `SELECT max_nkode_len, min_nkode_len, distinct_sets, distinct_attributes, lock_out, expiration, attribute_values, set_values FROM customer WHERE id = ?` selectCustomer := `SELECT max_nkode_len, min_nkode_len, distinct_sets, distinct_attributes, lock_out, expiration, attribute_values, set_values FROM customer WHERE id = ?`
rows, err := d.db.Query(selectCustomer, uuid.UUID(id)) rows, err := d.db.Query(selectCustomer, uuid.UUID(id))
@@ -119,9 +118,9 @@ func (d *SqliteDB) GetCustomer(id m.CustomerId) (*m.Customer, error) {
if rows.Next() { if rows.Next() {
return nil, errors.New(fmt.Sprintf("too many rows for customer %s", id)) return nil, errors.New(fmt.Sprintf("too many rows for customer %s", id))
} }
customer := m.Customer{ customer := Customer{
Id: id, Id: id,
NKodePolicy: m.NKodePolicy{ NKodePolicy: NKodePolicy{
MaxNkodeLen: maxNKodeLen, MaxNkodeLen: maxNKodeLen,
MinNkodeLen: minNKodeLen, MinNkodeLen: minNKodeLen,
DistinctSets: distinctSets, DistinctSets: distinctSets,
@@ -129,13 +128,13 @@ func (d *SqliteDB) GetCustomer(id m.CustomerId) (*m.Customer, error) {
LockOut: lockOut, LockOut: lockOut,
Expiration: expiration, Expiration: expiration,
}, },
Attributes: m.NewCustomerAttributesFromBytes(attributeValues, setValues), Attributes: NewCustomerAttributesFromBytes(attributeValues, setValues),
} }
return &customer, nil return &customer, nil
} }
func (d *SqliteDB) GetUser(username m.Username, customerId m.CustomerId) (*m.User, error) { func (d *SqliteDB) GetUser(username Username, customerId CustomerId) (*User, error) {
userSelect := ` userSelect := `
SELECT id, renew, code, mask, attributes_per_key, number_of_keys, alpha_key, set_key, pass_key, mask_key, salt, max_nkode_len, idx_interface, svg_id_interface FROM user SELECT id, renew, code, mask, attributes_per_key, number_of_keys, alpha_key, set_key, pass_key, mask_key, salt, max_nkode_len, idx_interface, svg_id_interface FROM user
WHERE user.username = ? AND user.customer_id = ? WHERE user.username = ? AND user.customer_id = ?
@@ -175,19 +174,19 @@ WHERE user.username = ? AND user.customer_id = ?
renew = true renew = true
} }
user := m.User{ user := User{
Id: m.UserId(userId), Id: UserId(userId),
CustomerId: customerId, CustomerId: customerId,
Username: username, Username: username,
EncipheredPasscode: m.EncipheredNKode{ EncipheredPasscode: EncipheredNKode{
Code: code, Code: code,
Mask: mask, Mask: mask,
}, },
Kp: m.KeypadDimension{ Kp: KeypadDimension{
AttrsPerKey: attrsPerKey, AttrsPerKey: attrsPerKey,
NumbOfKeys: numbOfKeys, NumbOfKeys: numbOfKeys,
}, },
CipherKeys: m.UserCipherKeys{ CipherKeys: UserCipherKeys{
AlphaKey: util.ByteArrToUint64Arr(alphaKey), AlphaKey: util.ByteArrToUint64Arr(alphaKey),
SetKey: util.ByteArrToUint64Arr(setKey), SetKey: util.ByteArrToUint64Arr(setKey),
PassKey: util.ByteArrToUint64Arr(passKey), PassKey: util.ByteArrToUint64Arr(passKey),
@@ -196,7 +195,7 @@ WHERE user.username = ? AND user.customer_id = ?
MaxNKodeLen: maxNKodeLen, MaxNKodeLen: maxNKodeLen,
Kp: nil, Kp: nil,
}, },
Interface: m.UserInterface{ Interface: UserInterface{
IdxInterface: util.ByteArrToIntArr(idxInterface), IdxInterface: util.ByteArrToIntArr(idxInterface),
SvgId: util.ByteArrToIntArr(svgIdInterface), SvgId: util.ByteArrToIntArr(svgIdInterface),
Kp: nil, Kp: nil,
@@ -209,7 +208,7 @@ WHERE user.username = ? AND user.customer_id = ?
return &user, nil return &user, nil
} }
func (d *SqliteDB) UpdateUserInterface(id m.UserId, ui m.UserInterface) error { func (d *SqliteDB) UpdateUserInterface(id UserId, ui UserInterface) error {
updateUserInterface := ` updateUserInterface := `
UPDATE user SET idx_interface = ? WHERE id = ? UPDATE user SET idx_interface = ? WHERE id = ?
` `
@@ -218,7 +217,7 @@ UPDATE user SET idx_interface = ? WHERE id = ?
return err return err
} }
func (d *SqliteDB) Renew(id m.CustomerId) error { func (d *SqliteDB) Renew(id CustomerId) error {
customer, err := d.GetCustomer(id) customer, err := d.GetCustomer(id)
if err != nil { if err != nil {
return err return err
@@ -246,20 +245,20 @@ SELECT id, alpha_key, set_key, attributes_per_key, number_of_keys FROM user WHER
if err != nil { if err != nil {
return err return err
} }
user := m.User{ user := User{
Id: m.UserId{}, Id: UserId{},
CustomerId: m.CustomerId{}, CustomerId: CustomerId{},
Username: "", Username: "",
EncipheredPasscode: m.EncipheredNKode{}, EncipheredPasscode: EncipheredNKode{},
Kp: m.KeypadDimension{ Kp: KeypadDimension{
AttrsPerKey: attrsPerKey, AttrsPerKey: attrsPerKey,
NumbOfKeys: numbOfKeys, NumbOfKeys: numbOfKeys,
}, },
CipherKeys: m.UserCipherKeys{ CipherKeys: UserCipherKeys{
AlphaKey: util.ByteArrToUint64Arr(alphaBytes), AlphaKey: util.ByteArrToUint64Arr(alphaBytes),
SetKey: util.ByteArrToUint64Arr(setBytes), SetKey: util.ByteArrToUint64Arr(setBytes),
}, },
Interface: m.UserInterface{}, Interface: UserInterface{},
Renew: false, Renew: false,
} }
err = user.RenewKeys(setXor, attrXor) err = user.RenewKeys(setXor, attrXor)
@@ -277,7 +276,7 @@ COMMIT;
return err return err
} }
func (d *SqliteDB) RefreshUser(user m.User, passcodeIdx []int, customerAttr m.CustomerAttributes) error { func (d *SqliteDB) RefreshUser(user User, passcodeIdx []int, customerAttr CustomerAttributes) error {
err := user.RefreshPasscode(passcodeIdx, customerAttr) err := user.RefreshPasscode(passcodeIdx, customerAttr)
if err != nil { if err != nil {
return err return err
@@ -289,7 +288,7 @@ UPDATE user SET renew = ?, code = ?, mask = ?, alpha_key = ?, set_key = ?, pass_
return err return err
} }
func (d *SqliteDB) RandomSvgInterface(kp m.KeypadDimension) ([]string, error) { func (d *SqliteDB) RandomSvgInterface(kp KeypadDimension) ([]string, error) {
ids, err := d.getRandomIds(kp.TotalAttrs()) ids, err := d.getRandomIds(kp.TotalAttrs())
if err != nil { if err != nil {
return nil, err return nil, err
@@ -297,11 +296,11 @@ func (d *SqliteDB) RandomSvgInterface(kp m.KeypadDimension) ([]string, error) {
return d.getSvgsById(ids) return d.getSvgsById(ids)
} }
func (d *SqliteDB) RandomSvgIdxInterface(kp m.KeypadDimension) (m.SvgIdInterface, error) { func (d *SqliteDB) RandomSvgIdxInterface(kp KeypadDimension) (SvgIdInterface, error) {
return d.getRandomIds(kp.TotalAttrs()) return d.getRandomIds(kp.TotalAttrs())
} }
func (d *SqliteDB) GetSvgStringInterface(idxs m.SvgIdInterface) ([]string, error) { func (d *SqliteDB) GetSvgStringInterface(idxs SvgIdInterface) ([]string, error) {
return d.getSvgsById(idxs) return d.getSvgsById(idxs)
} }

View File

@@ -1,13 +1,12 @@
package nkode package core
import ( import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
m "go-nkode/core/model"
"testing" "testing"
) )
func TestNewSqliteDB(t *testing.T) { func TestNewSqliteDB(t *testing.T) {
dbFile := "../../test.db" dbFile := "../test.db"
// sql_driver.MakeTables(dbFile) // sql_driver.MakeTables(dbFile)
db := NewSqliteDB(dbFile) db := NewSqliteDB(dbFile)
defer db.CloseDb() defer db.CloseDb()
@@ -23,19 +22,19 @@ func TestNewSqliteDB(t *testing.T) {
} }
func testSignupLoginRenew(t *testing.T, db DbAccessor) { func testSignupLoginRenew(t *testing.T, db DbAccessor) {
nkode_policy := m.NewDefaultNKodePolicy() nkode_policy := NewDefaultNKodePolicy()
customerOrig, err := m.NewCustomer(nkode_policy) customerOrig, err := NewCustomer(nkode_policy)
assert.NoError(t, err) assert.NoError(t, err)
err = db.WriteNewCustomer(*customerOrig) err = db.WriteNewCustomer(*customerOrig)
assert.NoError(t, err) assert.NoError(t, err)
customer, err := db.GetCustomer(customerOrig.Id) customer, err := db.GetCustomer(customerOrig.Id)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, customerOrig, customer) assert.Equal(t, customerOrig, customer)
username := m.Username("test_user") username := Username("test_user")
kp := m.KeypadDefault kp := KeypadDefault
passcodeIdx := []int{0, 1, 2, 3} passcodeIdx := []int{0, 1, 2, 3}
mockSvgInterface := make(m.SvgIdInterface, kp.TotalAttrs()) mockSvgInterface := make(SvgIdInterface, kp.TotalAttrs())
ui, err := m.NewUserInterface(&kp, mockSvgInterface) ui, err := NewUserInterface(&kp, mockSvgInterface)
assert.NoError(t, err) assert.NoError(t, err)
userOrig, err := NewUser(*customer, username, passcodeIdx, *ui, kp) userOrig, err := NewUser(*customer, username, passcodeIdx, *ui, kp)
assert.NoError(t, err) assert.NoError(t, err)
@@ -51,7 +50,7 @@ func testSignupLoginRenew(t *testing.T, db DbAccessor) {
} }
func testSqliteDBRandomSvgInterface(t *testing.T, db DbAccessor) { func testSqliteDBRandomSvgInterface(t *testing.T, db DbAccessor) {
kp := m.KeypadMax kp := KeypadMax
svgs, err := db.RandomSvgInterface(kp) svgs, err := db.RandomSvgInterface(kp)
assert.NoError(t, err) assert.NoError(t, err)
assert.Len(t, svgs, kp.TotalAttrs()) assert.Len(t, svgs, kp.TotalAttrs())

View File

@@ -1,58 +0,0 @@
package svg_icon
import (
"database/sql"
"go-nkode/util"
)
type SvgIcon struct {
Id int
Svg string
}
type SvgIconDb struct {
path string
}
func (d *SvgIconDb) GetSvgsById(ids []int) ([]string, error) {
db, err := sql.Open("sqlite3", d.path)
if err != nil {
return nil, err
}
defer db.Close()
selectId := "SELECT svg FROM svg_icon where id = ?"
svgs := make([]string, len(ids))
for idx, id := range ids {
rows, err := db.Query(selectId, id)
if err != nil {
return nil, err
}
err = rows.Scan(&svgs[idx])
if err != nil {
return nil, err
}
}
return svgs, nil
}
func (d *SvgIconDb) GetRandomIds(count int) ([]int, error) {
db, err := sql.Open("sqlite3", d.path)
if err != nil {
return nil, err
}
defer db.Close()
rows, err := db.Query("SELECT COUNT(*) FROM svg_icon;")
if err != nil {
return nil, err
}
var tableLen int
err = rows.Scan(&tableLen)
if err != nil {
return nil, err
}
perm, err := util.RandomPermutation(tableLen)
if err != nil {
return nil, err
}
return perm[:count], nil
}

View File

@@ -1,4 +1,4 @@
package model package core
import ( import (
"errors" "errors"

View File

@@ -1,4 +1,4 @@
package model package core
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
@@ -63,6 +63,8 @@ type GenerateSignupInterfaceResp struct {
type GetLoginInterfaceResp struct { type GetLoginInterfaceResp struct {
UserIdxInterface IdxInterface `json:"user_interface"` UserIdxInterface IdxInterface `json:"user_interface"`
SvgInterface []string `json:"svg_interface"` SvgInterface []string `json:"svg_interface"`
AttrsPerKey int `json:"attrs_per_key"`
NumbOfKeys int `json:"numb_of_keys"`
} }
type KeySelection []int type KeySelection []int
@@ -74,19 +76,29 @@ type Username string
type IdxInterface []int type IdxInterface []int
type SvgIdInterface []int type SvgIdInterface []int
type NKodeAPIInterface interface { func SessionIdFromString(sessionId string) (SessionId, error) {
CreateNewCustomer(NKodePolicy, *CustomerId) (*CustomerId, error) id, err := uuid.Parse(sessionId)
GenerateSignupInterface(Username, CustomerId, KeypadDimension) (*GenerateSignupInterfaceResp, error) if err != nil {
SetNKode(CustomerId, SessionId, KeySelection) (IdxInterface, error) return SessionId{}, err
ConfirmNKode(CustomerId, SessionId, KeySelection) error }
GetLoginInterface(Username, CustomerId) (*GetLoginInterfaceResp, error)
Login(CustomerId, Username, KeySelection) error return SessionId(id), nil
RenewAttributes(CustomerId) error
RandomSvgInterface() ([]string, error)
GetSvgStringInterface(idInterface SvgIdInterface) ([]string, error)
} }
type EncipheredNKode struct { type EncipheredNKode struct {
Code string Code string
Mask string Mask string
} }
type DbAccessor interface {
GetCustomer(CustomerId) (*Customer, error)
GetUser(Username, CustomerId) (*User, error)
WriteNewCustomer(Customer) error
WriteNewUser(User) error
UpdateUserInterface(UserId, UserInterface) error
Renew(CustomerId) error
RefreshUser(User, []int, CustomerAttributes) error
RandomSvgInterface(KeypadDimension) ([]string, error)
RandomSvgIdxInterface(KeypadDimension) (SvgIdInterface, error)
GetSvgStringInterface(SvgIdInterface) ([]string, error)
}

142
core/user.go Normal file
View File

@@ -0,0 +1,142 @@
package core
import (
"errors"
"github.com/google/uuid"
"go-nkode/py-builtin"
"go-nkode/util"
)
type User struct {
Id UserId
CustomerId CustomerId
Username Username
EncipheredPasscode EncipheredNKode
Kp KeypadDimension
CipherKeys UserCipherKeys
Interface UserInterface
Renew bool
}
func (u *User) DecipherMask(setVals []uint64, passcodeLen int) ([]uint64, error) {
return u.CipherKeys.DecipherMask(u.EncipheredPasscode.Mask, setVals, passcodeLen)
}
func (u *User) RenewKeys(setXor []uint64, attrXor []uint64) error {
u.Renew = true
var err error
u.CipherKeys.SetKey, err = util.XorLists(setXor[:u.Kp.AttrsPerKey], u.CipherKeys.SetKey)
if err != nil {
return err
}
u.CipherKeys.AlphaKey, err = util.XorLists(attrXor[:u.Kp.TotalAttrs()], u.CipherKeys.AlphaKey)
return err
}
func (u *User) RefreshPasscode(passcodeAttrIdx []int, customerAttributes CustomerAttributes) error {
setVals, err := customerAttributes.SetValsForKp(u.Kp)
newKeys, err := NewUserCipherKeys(&u.Kp, setVals, u.CipherKeys.MaxNKodeLen)
if err != nil {
return err
}
encipheredPasscode, err := newKeys.EncipherNKode(passcodeAttrIdx, customerAttributes)
if err != nil {
return err
}
u.CipherKeys = *newKeys
u.EncipheredPasscode = *encipheredPasscode
u.Renew = false
return nil
}
func (u *User) GetLoginInterface() ([]int, error) {
err := u.Interface.PartialInterfaceShuffle()
if err != nil {
return nil, err
}
return u.Interface.IdxInterface, nil
}
var KeyIndexOutOfRange = errors.New("one or more keys is out of range")
func ValidKeyEntry(user User, customer Customer, selectedKeys []int) ([]int, error) {
validKeys := py_builtin.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.SetValsForKp(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 {
return nil, err
}
attrVals, err := customer.Attributes.AttrValsForKp(user.Kp)
if err != nil {
return nil, err
}
err = user.CipherKeys.ValidPassword(user.EncipheredPasscode.Code, presumedAttrIdxVals, attrVals)
if err != nil {
return nil, err
}
return presumedAttrIdxVals, nil
}
func NewUser(customer Customer, username Username, passcodeIdx []int, ui UserInterface, kp KeypadDimension) (*User, error) {
setVals, err := customer.Attributes.SetValsForKp(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: UserId(uuid.New()),
Username: username,
EncipheredPasscode: *encipheredNKode,
CipherKeys: *newKeys,
Interface: ui,
Kp: kp,
CustomerId: customer.Id,
}
return &newUser, nil
}

View File

@@ -1,4 +1,4 @@
package model package core
import ( import (
"crypto/sha256" "crypto/sha256"
@@ -31,12 +31,12 @@ func NewUserCipherKeys(kp *KeypadDimension, setVals []uint64, maxNKodeLen int) (
return nil, err return nil, err
} }
alphakey, _ := util.GenerateRandomNonRepeatingUint64(kp.TotalAttrs()) alphaKey, _ := util.GenerateRandomNonRepeatingUint64(kp.TotalAttrs())
passKey, _ := util.GenerateRandomNonRepeatingUint64(maxNKodeLen) passKey, _ := util.GenerateRandomNonRepeatingUint64(maxNKodeLen)
maskKey, _ := util.GenerateRandomNonRepeatingUint64(maxNKodeLen) maskKey, _ := util.GenerateRandomNonRepeatingUint64(maxNKodeLen)
salt, _ := util.RandomBytes(10) salt, _ := util.RandomBytes(10)
userCipherKeys := UserCipherKeys{ userCipherKeys := UserCipherKeys{
AlphaKey: alphakey, AlphaKey: alphaKey,
PassKey: passKey, PassKey: passKey,
MaskKey: maskKey, MaskKey: maskKey,
SetKey: setKey, SetKey: setKey,
@@ -62,11 +62,8 @@ func (u *UserCipherKeys) PadUserMask(userMask []uint64, setVals []uint64) ([]uin
func (u *UserCipherKeys) ValidPassword(hashedPassword string, passcodeAttrIdx []int, attrVals []uint64) error { func (u *UserCipherKeys) ValidPassword(hashedPassword string, passcodeAttrIdx []int, attrVals []uint64) error {
hashBytes := []byte(hashedPassword) hashBytes := []byte(hashedPassword)
passcodeCipher := u.encipherCode(passcodeAttrIdx, attrVals) passcodeCipher := u.encipherCode(passcodeAttrIdx, attrVals)
passwordDigest, err := u.saltAndDigest(passcodeCipher) passwordDigest := u.saltAndDigest(passcodeCipher)
if err != nil { err := bcrypt.CompareHashAndPassword(hashBytes, passwordDigest)
return err
}
err = bcrypt.CompareHashAndPassword(hashBytes, passwordDigest)
if err != nil { if err != nil {
return err return err
} }
@@ -76,10 +73,7 @@ func (u *UserCipherKeys) ValidPassword(hashedPassword string, passcodeAttrIdx []
func (u *UserCipherKeys) EncipherSaltHashCode(passcodeAttrIdx []int, attrVals []uint64) (string, error) { func (u *UserCipherKeys) EncipherSaltHashCode(passcodeAttrIdx []int, attrVals []uint64) (string, error) {
passcodeCipher := u.encipherCode(passcodeAttrIdx, attrVals) passcodeCipher := u.encipherCode(passcodeAttrIdx, attrVals)
passcodeDigest, err := u.saltAndDigest(passcodeCipher) passcodeDigest := u.saltAndDigest(passcodeCipher)
if err != nil {
return "", err
}
passcodeBytes, err := u.hashPasscode(passcodeDigest) passcodeBytes, err := u.hashPasscode(passcodeDigest)
if err != nil { if err != nil {
return "", err return "", err
@@ -91,37 +85,33 @@ func (u *UserCipherKeys) encipherCode(passcodeAttrIdx []int, attrVals []uint64)
passcodeLen := len(passcodeAttrIdx) passcodeLen := len(passcodeAttrIdx)
passcodeCipher := make([]uint64, u.MaxNKodeLen) passcodeCipher := make([]uint64, u.MaxNKodeLen)
for idx := 0; idx < passcodeLen; idx++ { for idx := 0; idx < passcodeLen; idx++ {
attrIdx := passcodeAttrIdx[idx] attrIdx := passcodeAttrIdx[idx]
alpha := u.AlphaKey[attrIdx] alpha := u.AlphaKey[attrIdx]
attrVal := attrVals[idx] attrVal := attrVals[attrIdx]
pass := u.PassKey[idx] pass := u.PassKey[idx]
passcodeCipher[idx] = alpha ^ pass ^ attrVal passcodeCipher[idx] = alpha ^ pass ^ attrVal
} }
return passcodeCipher return passcodeCipher
} }
func (u *UserCipherKeys) saltAndDigest(passcode []uint64) ([]byte, error) { func (u *UserCipherKeys) saltAndDigest(passcode []uint64) []byte {
passcodeBytes := util.Uint64ArrToByteArr(passcode) passcodeBytes := util.Uint64ArrToByteArr(passcode)
passcodeBytes = append(passcodeBytes, u.Salt...) passcodeBytes = append(passcodeBytes, u.Salt...)
h := sha256.New() h := sha256.New()
passcodeSha, err := h.Write(passcodeBytes) h.Write(passcodeBytes)
if err != nil {
return nil, err return h.Sum(nil)
}
passcodeDigest := uint64(passcodeSha)
return util.Uint64ArrToByteArr([]uint64{passcodeDigest}), nil
} }
func (u *UserCipherKeys) hashPasscode(passcodeDigest []byte) ([]byte, error) { func (u *UserCipherKeys) hashPasscode(passcodeDigest []byte) ([]byte, error) {
hashedPassword, err := bcrypt.GenerateFromPassword(passcodeDigest, bcrypt.DefaultCost) hashedPassword, err := bcrypt.GenerateFromPassword(passcodeDigest, bcrypt.DefaultCost)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return hashedPassword, nil return hashedPassword, nil
} }
func (u *UserCipherKeys) EncipherMask(passcodeSet []uint64, customerAttrs CustomerAttributes, userKp KeypadDimension) (string, error) { func (u *UserCipherKeys) EncipherMask(passcodeSet []uint64, customerAttrs CustomerAttributes, userKp KeypadDimension) (string, error) {
setVals, err := customerAttrs.SetValsForKp(userKp) setVals, err := customerAttrs.SetValsForKp(userKp)
if err != nil { if err != nil {

View File

@@ -1,4 +1,4 @@
package model package core
import ( import (
"errors" "errors"

View File

@@ -1,29 +1,28 @@
package nkode package core
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/google/uuid" "github.com/google/uuid"
m "go-nkode/core/model"
"go-nkode/hashset" "go-nkode/hashset"
py "go-nkode/py-builtin" py "go-nkode/py-builtin"
"go-nkode/util" "go-nkode/util"
) )
type UserSignSession struct { type UserSignSession struct {
Id m.SessionId Id SessionId
CustomerId m.CustomerId CustomerId CustomerId
LoginUserInterface m.UserInterface LoginUserInterface UserInterface
Kp m.KeypadDimension Kp KeypadDimension
SetIdxInterface m.IdxInterface SetIdxInterface IdxInterface
ConfirmIdxInterface m.IdxInterface ConfirmIdxInterface IdxInterface
SetKeySelection m.KeySelection SetKeySelection KeySelection
Username m.Username Username Username
Expire int Expire int
} }
func NewSignupSession(username m.Username, kp m.KeypadDimension, customerId m.CustomerId, svgInterface m.SvgIdInterface) (*UserSignSession, error) { func NewSignupSession(username Username, kp KeypadDimension, customerId CustomerId, svgInterface SvgIdInterface) (*UserSignSession, error) {
loginInterface, err := m.NewUserInterface(&kp, svgInterface) loginInterface, err := NewUserInterface(&kp, svgInterface)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -32,7 +31,7 @@ func NewSignupSession(username m.Username, kp m.KeypadDimension, customerId m.Cu
return nil, err return nil, err
} }
session := UserSignSession{ session := UserSignSession{
Id: m.SessionId(uuid.New()), Id: SessionId(uuid.New()),
CustomerId: customerId, CustomerId: customerId,
LoginUserInterface: *loginInterface, LoginUserInterface: *loginInterface,
SetIdxInterface: signupInterface.IdxInterface, SetIdxInterface: signupInterface.IdxInterface,
@@ -45,7 +44,7 @@ func NewSignupSession(username m.Username, kp m.KeypadDimension, customerId m.Cu
return &session, nil return &session, nil
} }
func (s *UserSignSession) DeducePasscode(confirmKeyEntry m.KeySelection) ([]int, error) { func (s *UserSignSession) DeducePasscode(confirmKeyEntry KeySelection) ([]int, error) {
validEntry := py.All[int](confirmKeyEntry, func(i int) bool { validEntry := py.All[int](confirmKeyEntry, func(i int) bool {
return 0 <= i && i < s.Kp.NumbOfKeys return 0 <= i && i < s.Kp.NumbOfKeys
}) })
@@ -98,7 +97,7 @@ func (s *UserSignSession) DeducePasscode(confirmKeyEntry m.KeySelection) ([]int,
return passcode, nil return passcode, nil
} }
func (s *UserSignSession) SetUserNKode(keySelection m.KeySelection) (m.IdxInterface, error) { func (s *UserSignSession) SetUserNKode(keySelection KeySelection) (IdxInterface, error) {
validKeySelection := py.All[int](keySelection, func(i int) bool { validKeySelection := py.All[int](keySelection, func(i int) bool {
return 0 <= i && i < s.Kp.NumbOfKeys return 0 <= i && i < s.Kp.NumbOfKeys
}) })
@@ -108,7 +107,7 @@ func (s *UserSignSession) SetUserNKode(keySelection m.KeySelection) (m.IdxInterf
s.SetKeySelection = keySelection s.SetKeySelection = keySelection
setKp := s.SignupKeypad() setKp := s.SignupKeypad()
setInterface := m.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
@@ -117,7 +116,7 @@ func (s *UserSignSession) SetUserNKode(keySelection m.KeySelection) (m.IdxInterf
return s.ConfirmIdxInterface, nil return s.ConfirmIdxInterface, nil
} }
func (s *UserSignSession) getSelectedKeyVals(keySelections m.KeySelection, userInterface []int) ([][]int, error) { func (s *UserSignSession) getSelectedKeyVals(keySelections KeySelection, userInterface []int) ([][]int, error) {
signupKp := s.SignupKeypad() signupKp := s.SignupKeypad()
keypadInterface, err := util.ListToMatrix(userInterface, signupKp.AttrsPerKey) keypadInterface, err := util.ListToMatrix(userInterface, signupKp.AttrsPerKey)
if err != nil { if err != nil {
@@ -131,7 +130,7 @@ func (s *UserSignSession) getSelectedKeyVals(keySelections m.KeySelection, userI
return keyVals, nil return keyVals, nil
} }
func signupInterface(baseUserInterface m.UserInterface, kp m.KeypadDimension) (*m.UserInterface, error) { func signupInterface(baseUserInterface UserInterface, kp KeypadDimension) (*UserInterface, error) {
if kp.IsDispersable() { if kp.IsDispersable() {
return nil, errors.New("keypad is dispersable, can't use signupInterface") return nil, errors.New("keypad is dispersable, can't use signupInterface")
} }
@@ -157,9 +156,9 @@ func signupInterface(baseUserInterface m.UserInterface, kp m.KeypadDimension) (*
if err != nil { if err != nil {
return nil, err return nil, err
} }
signupUserInterface := m.UserInterface{ signupUserInterface := UserInterface{
IdxInterface: util.MatrixToList(attrSetView), IdxInterface: util.MatrixToList(attrSetView),
Kp: &m.KeypadDimension{ Kp: &KeypadDimension{
AttrsPerKey: numbOfKeys, AttrsPerKey: numbOfKeys,
NumbOfKeys: numbOfKeys, NumbOfKeys: numbOfKeys,
}, },
@@ -167,8 +166,8 @@ func signupInterface(baseUserInterface m.UserInterface, kp m.KeypadDimension) (*
return &signupUserInterface, nil return &signupUserInterface, nil
} }
func (s *UserSignSession) SignupKeypad() m.KeypadDimension { func (s *UserSignSession) SignupKeypad() KeypadDimension {
return m.KeypadDimension{ return KeypadDimension{
AttrsPerKey: s.Kp.NumbOfKeys, AttrsPerKey: s.Kp.NumbOfKeys,
NumbOfKeys: s.Kp.NumbOfKeys, NumbOfKeys: s.Kp.NumbOfKeys,
} }

View File

@@ -1,4 +1,4 @@
package model package core
import ( import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@@ -22,6 +22,11 @@ func TestUserCipherKeys_EncipherSaltHashCode(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
err = newUser.ValidPassword(encipher0, passcodeIdx, attrVals) err = newUser.ValidPassword(encipher0, passcodeIdx, attrVals)
assert.NoError(t, err) assert.NoError(t, err)
passcodeIdxInvalid := []int{1, 0, 3, 2}
assert.NoError(t, err)
err = newUser.ValidPassword(encipher0, passcodeIdxInvalid, attrVals)
assert.Error(t, err)
} }
func TestUserCipherKeys_EncipherDecipherMask(t *testing.T) { func TestUserCipherKeys_EncipherDecipherMask(t *testing.T) {

1
go.mod
View File

@@ -14,6 +14,7 @@ require (
require ( require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

2
go.sum
View File

@@ -1,5 +1,7 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=

32
main.go
View File

@@ -3,29 +3,27 @@ package main
import ( import (
"fmt" "fmt"
"github.com/google/uuid" "github.com/google/uuid"
"go-nkode/core/api" "go-nkode/core"
"go-nkode/core/model"
"go-nkode/core/nkode"
"log" "log"
"net/http" "net/http"
) )
func main() { func main() {
//db := nkode.NewInMemoryDb() //db := nkode.NewInMemoryDb()
db := nkode.NewSqliteDB("nkode.db") db := core.NewSqliteDB("nkode.db")
defer db.CloseDb() defer db.CloseDb()
nkodeApi := nkode.NewNKodeAPI(db) nkodeApi := core.NewNKodeAPI(db)
AddDefaultCustomer(nkodeApi) AddDefaultCustomer(nkodeApi)
handler := model.NKodeHandler{Api: &nkodeApi} handler := core.NKodeHandler{Api: nkodeApi}
mux := http.NewServeMux() mux := http.NewServeMux()
mux.Handle(api.CreateNewCustomer, &handler) mux.Handle(core.CreateNewCustomer, &handler)
mux.Handle(api.GenerateSignupInterface, &handler) mux.Handle(core.GenerateSignupInterface, &handler)
mux.Handle(api.SetNKode, &handler) mux.Handle(core.SetNKode, &handler)
mux.Handle(api.ConfirmNKode, &handler) mux.Handle(core.ConfirmNKode, &handler)
mux.Handle(api.GetLoginInterface, &handler) mux.Handle(core.GetLoginInterface, &handler)
mux.Handle(api.Login, &handler) mux.Handle(core.Login, &handler)
mux.Handle(api.RenewAttributes, &handler) mux.Handle(core.RenewAttributes, &handler)
mux.Handle(api.RandomSvgInterface, &handler) mux.Handle(core.RandomSvgInterface, &handler)
fmt.Println("Running on localhost:8080...") fmt.Println("Running on localhost:8080...")
log.Fatal(http.ListenAndServe("localhost:8080", corsMiddleware(mux))) log.Fatal(http.ListenAndServe("localhost:8080", corsMiddleware(mux)))
} }
@@ -48,13 +46,13 @@ func corsMiddleware(next http.Handler) http.Handler {
}) })
} }
func AddDefaultCustomer(api nkode.NKodeAPI) { func AddDefaultCustomer(api core.NKodeAPI) {
newId, err := uuid.Parse("ed9ed6e0-082c-4b57-8d8c-f00ed6493457") newId, err := uuid.Parse("ed9ed6e0-082c-4b57-8d8c-f00ed6493457")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
customerId := model.CustomerId(newId) customerId := core.CustomerId(newId)
nkode_policy := model.NewDefaultNKodePolicy() nkode_policy := core.NewDefaultNKodePolicy()
_, err = api.CreateNewCustomer(nkode_policy, &customerId) _, err = api.CreateNewCustomer(nkode_policy, &customerId)
if err != nil { if err != nil {
log.Print(err) log.Print(err)

View File

@@ -4,8 +4,7 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go-nkode/core/api" "go-nkode/core"
m "go-nkode/core/model"
"io" "io"
"net/http" "net/http"
"testing" "testing"
@@ -13,84 +12,84 @@ import (
func TestApi(t *testing.T) { func TestApi(t *testing.T) {
base := "http://localhost:8080" base := "http://localhost:8080"
newCustomerBody := m.NewCustomerPost{ newCustomerBody := core.NewCustomerPost{
NKodePolicy: m.NewDefaultNKodePolicy(), NKodePolicy: core.NewDefaultNKodePolicy(),
} }
kp := m.KeypadDimension{ kp := core.KeypadDimension{
AttrsPerKey: 14, AttrsPerKey: 14,
NumbOfKeys: 10, NumbOfKeys: 10,
} }
var customerResp m.CreateNewCustomerResp var customerResp core.CreateNewCustomerResp
testApiPost(t, base+api.CreateNewCustomer, newCustomerBody, &customerResp) testApiPost(t, base+core.CreateNewCustomer, newCustomerBody, &customerResp)
username := m.Username("test_username") username := core.Username("test_username")
signupInterfaceBody := m.GenerateSignupInterfacePost{ signupInterfaceBody := core.GenerateSignupInterfacePost{
CustomerId: customerResp.CustomerId, CustomerId: customerResp.CustomerId,
AttrsPerKey: kp.AttrsPerKey, AttrsPerKey: kp.AttrsPerKey,
NumbOfKeys: kp.NumbOfKeys, NumbOfKeys: kp.NumbOfKeys,
Username: username, Username: username,
} }
var signupInterfaceResp m.GenerateSignupInterfaceResp var signupInterfaceResp core.GenerateSignupInterfaceResp
testApiPost(t, base+api.GenerateSignupInterface, signupInterfaceBody, &signupInterfaceResp) testApiPost(t, base+core.GenerateSignupInterface, signupInterfaceBody, &signupInterfaceResp)
assert.Len(t, signupInterfaceResp.SvgInterface, kp.TotalAttrs()) assert.Len(t, signupInterfaceResp.SvgInterface, kp.TotalAttrs())
passcodeLen := 4 passcodeLen := 4
setInterface := signupInterfaceResp.UserIdxInterface setInterface := signupInterfaceResp.UserIdxInterface
userPasscode := setInterface[:passcodeLen] userPasscode := setInterface[:passcodeLen]
kp_set := m.KeypadDimension{NumbOfKeys: kp.NumbOfKeys, AttrsPerKey: kp.NumbOfKeys} kp_set := core.KeypadDimension{NumbOfKeys: kp.NumbOfKeys, AttrsPerKey: kp.NumbOfKeys}
setKeySelection, err := m.SelectKeyByAttrIdx(setInterface, userPasscode, kp_set) setKeySelection, err := core.SelectKeyByAttrIdx(setInterface, userPasscode, kp_set)
assert.NoError(t, err) assert.NoError(t, err)
setNKodeBody := m.SetNKodePost{ setNKodeBody := core.SetNKodePost{
CustomerId: customerResp.CustomerId, CustomerId: customerResp.CustomerId,
SessionId: signupInterfaceResp.SessionId, SessionId: signupInterfaceResp.SessionId,
KeySelection: setKeySelection, KeySelection: setKeySelection,
} }
var setNKodeResp m.SetNKodeResp var setNKodeResp core.SetNKodeResp
testApiPost(t, base+api.SetNKode, setNKodeBody, &setNKodeResp) testApiPost(t, base+core.SetNKode, setNKodeBody, &setNKodeResp)
confirmInterface := setNKodeResp.UserInterface confirmInterface := setNKodeResp.UserInterface
confirmKeySelection, err := m.SelectKeyByAttrIdx(confirmInterface, userPasscode, kp_set) confirmKeySelection, err := core.SelectKeyByAttrIdx(confirmInterface, userPasscode, kp_set)
assert.NoError(t, err) assert.NoError(t, err)
confirmNKodeBody := m.ConfirmNKodePost{ confirmNKodeBody := core.ConfirmNKodePost{
CustomerId: customerResp.CustomerId, CustomerId: customerResp.CustomerId,
KeySelection: confirmKeySelection, KeySelection: confirmKeySelection,
SessionId: signupInterfaceResp.SessionId, SessionId: signupInterfaceResp.SessionId,
} }
testApiPost(t, base+api.ConfirmNKode, confirmNKodeBody, nil) testApiPost(t, base+core.ConfirmNKode, confirmNKodeBody, nil)
loginInterfaceBody := m.GetLoginInterfacePost{ loginInterfaceBody := core.GetLoginInterfacePost{
CustomerId: customerResp.CustomerId, CustomerId: customerResp.CustomerId,
Username: username, Username: username,
} }
var loginInterfaceResp m.GetLoginInterfaceResp var loginInterfaceResp core.GetLoginInterfaceResp
testApiPost(t, base+api.GetLoginInterface, loginInterfaceBody, &loginInterfaceResp) testApiPost(t, base+core.GetLoginInterface, loginInterfaceBody, &loginInterfaceResp)
assert.Equal(t, loginInterfaceResp.AttrsPerKey, kp.AttrsPerKey)
loginKeySelection, err := m.SelectKeyByAttrIdx(loginInterfaceResp.UserIdxInterface, userPasscode, kp) assert.Equal(t, loginInterfaceResp.NumbOfKeys, kp.NumbOfKeys)
loginKeySelection, err := core.SelectKeyByAttrIdx(loginInterfaceResp.UserIdxInterface, userPasscode, kp)
assert.NoError(t, err) assert.NoError(t, err)
loginBody := m.LoginPost{ loginBody := core.LoginPost{
CustomerId: customerResp.CustomerId, CustomerId: customerResp.CustomerId,
Username: username, Username: username,
KeySelection: loginKeySelection, KeySelection: loginKeySelection,
} }
testApiPost(t, base+api.Login, loginBody, nil) testApiPost(t, base+core.Login, loginBody, nil)
renewBody := m.RenewAttributesPost{CustomerId: customerResp.CustomerId} renewBody := core.RenewAttributesPost{CustomerId: customerResp.CustomerId}
testApiPost(t, base+api.RenewAttributes, renewBody, nil) testApiPost(t, base+core.RenewAttributes, renewBody, nil)
loginKeySelection, err = m.SelectKeyByAttrIdx(loginInterfaceResp.UserIdxInterface, userPasscode, kp) loginKeySelection, err = core.SelectKeyByAttrIdx(loginInterfaceResp.UserIdxInterface, userPasscode, kp)
assert.NoError(t, err) assert.NoError(t, err)
loginBody = m.LoginPost{ loginBody = core.LoginPost{
CustomerId: customerResp.CustomerId, CustomerId: customerResp.CustomerId,
Username: username, Username: username,
KeySelection: loginKeySelection, KeySelection: loginKeySelection,
} }
testApiPost(t, base+api.Login, loginBody, nil) testApiPost(t, base+core.Login, loginBody, nil)
var randomSvgInterfaceResp m.RandomSvgInterfaceResp
testApiGet(t, base+api.RandomSvgInterface, &randomSvgInterfaceResp)
assert.Equal(t, m.KeypadMax.TotalAttrs(), len(randomSvgInterfaceResp.Svgs))
var randomSvgInterfaceResp core.RandomSvgInterfaceResp
testApiGet(t, base+core.RandomSvgInterface, &randomSvgInterfaceResp)
assert.Equal(t, core.KeypadMax.TotalAttrs(), len(randomSvgInterfaceResp.Svgs))
} }
func Unmarshal(t *testing.T, resp *http.Response, data any) { func Unmarshal(t *testing.T, resp *http.Response, data any) {

View File

@@ -1,71 +0,0 @@
package sql_driver
import (
"database/sql"
_ "github.com/mattn/go-sqlite3" // Import the SQLite3 driver
"log"
)
func MakeTables(dbPath string) {
db, err := sql.Open("sqlite3", dbPath)
if err != nil {
log.Fatal(err)
}
defer db.Close()
createTable := `
PRAGMA journal_mode=WAL;
PRAGMA foreign_keys = ON;
CREATE TABLE IF NOT EXISTS customer (
id TEXT NOT NULL PRIMARY KEY,
max_nkode_len INTEGER NOT NULL,
min_nkode_len INTEGER NOT NULL,
distinct_sets INTEGER NOT NULL,
distinct_attributes INTEGER NOT NULL,
lock_out INTEGER NOT NULL,
expiration INTEGER NOT NULL,
attribute_values BLOB NOT NULL,
set_values BLOB NOT NULL
);
CREATE TABLE IF NOT EXISTS user (
id TEXT NOT NULL PRIMARY KEY,
username TEXT NOT NULL,
renew INT NOT NULL,
customer_id TEXT NOT NULL,
-- Enciphered Passcode
code TEXT NOT NULL,
mask TEXT NOT NULL,
-- Keypad Dimensions
attributes_per_key INT NOT NULL,
number_of_keys INT NOT NULL,
-- User Keys
alpha_key BLOB NOT NULL,
set_key BLOB NOT NULL,
pass_key BLOB NOT NULL,
mask_key BLOB NOT NULL,
salt BLOB NOT NULL,
max_nkode_len INT NOT NULL,
-- User Interface
idx_interface BLOB NOT NULL,
svg_id_interface BLOB NOT NULL,
FOREIGN KEY (customer_id) REFERENCES customers(id),
UNIQUE(customer_id, username)
);
CREATE TABLE IF NOT EXISTS svg_icon (
id INTEGER PRIMARY KEY AUTOINCREMENT,
svg TEXT NOT NULL
);
`
_, err = db.Exec(createTable)
if err != nil {
log.Fatal(err)
}
}

View File

@@ -5,7 +5,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
_ "github.com/mattn/go-sqlite3" // Import the SQLite3 driver _ "github.com/mattn/go-sqlite3" // Import the SQLite3 driver
"go-nkode/sql-driver"
"io/ioutil" "io/ioutil"
"log" "log"
"path/filepath" "path/filepath"
@@ -28,7 +27,7 @@ func main() {
dbPaths := []string{"test.db", "nkode.db"} dbPaths := []string{"test.db", "nkode.db"}
outputStr := MakeSvgFiles() outputStr := MakeSvgFiles()
for _, path := range dbPaths { for _, path := range dbPaths {
sql_driver.MakeTables(path) MakeTables(path)
SaveToSqlite(path, outputStr) SaveToSqlite(path, outputStr)
} }
} }
@@ -136,3 +135,67 @@ func LoadJson(filename string) (*Root, error) {
return &root, nil return &root, nil
} }
func MakeTables(dbPath string) {
db, err := sql.Open("sqlite3", dbPath)
if err != nil {
log.Fatal(err)
}
defer db.Close()
createTable := `
PRAGMA journal_mode=WAL;
PRAGMA foreign_keys = ON;
CREATE TABLE IF NOT EXISTS customer (
id TEXT NOT NULL PRIMARY KEY,
max_nkode_len INTEGER NOT NULL,
min_nkode_len INTEGER NOT NULL,
distinct_sets INTEGER NOT NULL,
distinct_attributes INTEGER NOT NULL,
lock_out INTEGER NOT NULL,
expiration INTEGER NOT NULL,
attribute_values BLOB NOT NULL,
set_values BLOB NOT NULL
);
CREATE TABLE IF NOT EXISTS user (
id TEXT NOT NULL PRIMARY KEY,
username TEXT NOT NULL,
renew INT NOT NULL,
customer_id TEXT NOT NULL,
-- Enciphered Passcode
code TEXT NOT NULL,
mask TEXT NOT NULL,
-- Keypad Dimensions
attributes_per_key INT NOT NULL,
number_of_keys INT NOT NULL,
-- User Keys
alpha_key BLOB NOT NULL,
set_key BLOB NOT NULL,
pass_key BLOB NOT NULL,
mask_key BLOB NOT NULL,
salt BLOB NOT NULL,
max_nkode_len INT NOT NULL,
-- User Interface
idx_interface BLOB NOT NULL,
svg_id_interface BLOB NOT NULL,
FOREIGN KEY (customer_id) REFERENCES customers(id),
UNIQUE(customer_id, username)
);
CREATE TABLE IF NOT EXISTS svg_icon (
id INTEGER PRIMARY KEY AUTOINCREMENT,
svg TEXT NOT NULL
);
`
_, err = db.Exec(createTable)
if err != nil {
log.Fatal(err)
}
}