more refactoring

This commit is contained in:
2024-11-27 09:41:31 -06:00
parent 35039bf494
commit c0b785ca8d
21 changed files with 167 additions and 151 deletions

1
.env.test.example Normal file
View File

@@ -0,0 +1 @@
TEST_DB=/path/to/test.db

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go-nkode/internal/api" "go-nkode/internal/api"
"go-nkode/internal/entities"
"go-nkode/internal/models" "go-nkode/internal/models"
"go-nkode/internal/security" "go-nkode/internal/security"
"io" "io"
@@ -19,7 +20,7 @@ func TestApi(t *testing.T) {
newCustomerBody := models.NewCustomerPost{ newCustomerBody := models.NewCustomerPost{
NKodePolicy: models.NewDefaultNKodePolicy(), NKodePolicy: models.NewDefaultNKodePolicy(),
} }
kp := models.KeypadDimension{ kp := entities.KeypadDimension{
AttrsPerKey: 14, AttrsPerKey: 14,
NumbOfKeys: 10, NumbOfKeys: 10,
} }
@@ -40,8 +41,8 @@ func TestApi(t *testing.T) {
passcodeLen := 4 passcodeLen := 4
setInterface := signupInterfaceResp.UserIdxInterface setInterface := signupInterfaceResp.UserIdxInterface
userPasscode := setInterface[:passcodeLen] userPasscode := setInterface[:passcodeLen]
kpSet := models.KeypadDimension{NumbOfKeys: kp.NumbOfKeys, AttrsPerKey: kp.NumbOfKeys} kpSet := entities.KeypadDimension{NumbOfKeys: kp.NumbOfKeys, AttrsPerKey: kp.NumbOfKeys}
setKeySelection, err := models.SelectKeyByAttrIdx(setInterface, userPasscode, kpSet) setKeySelection, err := entities.SelectKeyByAttrIdx(setInterface, userPasscode, kpSet)
assert.NoError(t, err) assert.NoError(t, err)
setNKodeBody := models.SetNKodePost{ setNKodeBody := models.SetNKodePost{
CustomerId: customerResp.CustomerId, CustomerId: customerResp.CustomerId,
@@ -51,7 +52,7 @@ func TestApi(t *testing.T) {
var setNKodeResp models.SetNKodeResp var setNKodeResp models.SetNKodeResp
testApiPost(t, base+api.SetNKode, setNKodeBody, &setNKodeResp) testApiPost(t, base+api.SetNKode, setNKodeBody, &setNKodeResp)
confirmInterface := setNKodeResp.UserInterface confirmInterface := setNKodeResp.UserInterface
confirmKeySelection, err := models.SelectKeyByAttrIdx(confirmInterface, userPasscode, kpSet) confirmKeySelection, err := entities.SelectKeyByAttrIdx(confirmInterface, userPasscode, kpSet)
assert.NoError(t, err) assert.NoError(t, err)
confirmNKodeBody := models.ConfirmNKodePost{ confirmNKodeBody := models.ConfirmNKodePost{
CustomerId: customerResp.CustomerId, CustomerId: customerResp.CustomerId,
@@ -69,7 +70,7 @@ func TestApi(t *testing.T) {
testApiPost(t, base+api.GetLoginInterface, loginInterfaceBody, &loginInterfaceResp) testApiPost(t, base+api.GetLoginInterface, loginInterfaceBody, &loginInterfaceResp)
assert.Equal(t, loginInterfaceResp.AttrsPerKey, kp.AttrsPerKey) assert.Equal(t, loginInterfaceResp.AttrsPerKey, kp.AttrsPerKey)
assert.Equal(t, loginInterfaceResp.NumbOfKeys, kp.NumbOfKeys) assert.Equal(t, loginInterfaceResp.NumbOfKeys, kp.NumbOfKeys)
loginKeySelection, err := models.SelectKeyByAttrIdx(loginInterfaceResp.UserIdxInterface, userPasscode, kp) loginKeySelection, err := entities.SelectKeyByAttrIdx(loginInterfaceResp.UserIdxInterface, userPasscode, kp)
assert.NoError(t, err) assert.NoError(t, err)
loginBody := models.LoginPost{ loginBody := models.LoginPost{
CustomerId: customerResp.CustomerId, CustomerId: customerResp.CustomerId,
@@ -86,7 +87,7 @@ func TestApi(t *testing.T) {
renewBody := models.RenewAttributesPost{CustomerId: customerResp.CustomerId} renewBody := models.RenewAttributesPost{CustomerId: customerResp.CustomerId}
testApiPost(t, base+api.RenewAttributes, renewBody, nil) testApiPost(t, base+api.RenewAttributes, renewBody, nil)
loginKeySelection, err = models.SelectKeyByAttrIdx(loginInterfaceResp.UserIdxInterface, userPasscode, kp) loginKeySelection, err = entities.SelectKeyByAttrIdx(loginInterfaceResp.UserIdxInterface, userPasscode, kp)
assert.NoError(t, err) assert.NoError(t, err)
loginBody = models.LoginPost{ loginBody = models.LoginPost{
CustomerId: customerResp.CustomerId, CustomerId: customerResp.CustomerId,
@@ -98,7 +99,7 @@ func TestApi(t *testing.T) {
var randomSvgInterfaceResp models.RandomSvgInterfaceResp var randomSvgInterfaceResp models.RandomSvgInterfaceResp
testApiGet(t, base+api.RandomSvgInterface, &randomSvgInterfaceResp, "") testApiGet(t, base+api.RandomSvgInterface, &randomSvgInterfaceResp, "")
assert.Equal(t, models.KeypadMax.TotalAttrs(), len(randomSvgInterfaceResp.Svgs)) assert.Equal(t, entities.KeypadMax.TotalAttrs(), len(randomSvgInterfaceResp.Svgs))
var refreshTokenResp models.RefreshTokenResp var refreshTokenResp models.RefreshTokenResp

View File

@@ -1,20 +0,0 @@
package api
import (
"go-nkode/internal/models"
)
type DbAccessor interface {
GetCustomer(models.CustomerId) (*models.Customer, error)
GetUser(models.UserEmail, models.CustomerId) (*models.User, error)
WriteNewCustomer(models.Customer) error
WriteNewUser(models.User) error
UpdateUserNKode(models.User) error
UpdateUserInterface(models.UserId, models.UserInterface) error
UpdateUserRefreshToken(models.UserId, string) error
Renew(models.CustomerId) error
RefreshUserPasscode(models.User, []int, models.CustomerAttributes) error
RandomSvgInterface(models.KeypadDimension) ([]string, error)
RandomSvgIdxInterface(models.KeypadDimension) (models.SvgIdInterface, error)
GetSvgStringInterface(models.SvgIdInterface) ([]string, error)
}

View File

@@ -5,6 +5,7 @@ import (
"errors" "errors"
"github.com/google/uuid" "github.com/google/uuid"
"go-nkode/config" "go-nkode/config"
"go-nkode/internal/entities"
"go-nkode/internal/models" "go-nkode/internal/models"
"go-nkode/internal/security" "go-nkode/internal/security"
"log" "log"
@@ -108,7 +109,7 @@ func (h *NKodeHandler) GenerateSignupResetInterfaceHandler(w http.ResponseWriter
return return
} }
kp := models.KeypadDimension{ kp := entities.KeypadDimension{
AttrsPerKey: signupResetPost.AttrsPerKey, AttrsPerKey: signupResetPost.AttrsPerKey,
NumbOfKeys: signupResetPost.NumbOfKeys, NumbOfKeys: signupResetPost.NumbOfKeys,
} }

View File

@@ -5,7 +5,9 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
"github.com/patrickmn/go-cache" "github.com/patrickmn/go-cache"
"go-nkode/config" "go-nkode/config"
"go-nkode/internal/db"
"go-nkode/internal/email" "go-nkode/internal/email"
"go-nkode/internal/entities"
"go-nkode/internal/models" "go-nkode/internal/models"
"go-nkode/internal/security" "go-nkode/internal/security"
"log" "log"
@@ -19,12 +21,12 @@ const (
) )
type NKodeAPI struct { type NKodeAPI struct {
Db DbAccessor Db db.CustomerUserRepository
SignupSessionCache *cache.Cache SignupSessionCache *cache.Cache
EmailQueue *email.EmailQueue EmailQueue *email.Queue
} }
func NewNKodeAPI(db DbAccessor, queue *email.EmailQueue) NKodeAPI { func NewNKodeAPI(db db.CustomerUserRepository, queue *email.Queue) NKodeAPI {
return NKodeAPI{ return NKodeAPI{
Db: db, Db: db,
EmailQueue: queue, EmailQueue: queue,
@@ -33,7 +35,7 @@ func NewNKodeAPI(db DbAccessor, queue *email.EmailQueue) NKodeAPI {
} }
func (n *NKodeAPI) CreateNewCustomer(nkodePolicy models.NKodePolicy, id *models.CustomerId) (*models.CustomerId, error) { func (n *NKodeAPI) CreateNewCustomer(nkodePolicy models.NKodePolicy, id *models.CustomerId) (*models.CustomerId, error) {
newCustomer, err := models.NewCustomer(nkodePolicy) newCustomer, err := entities.NewCustomer(nkodePolicy)
if id != nil { if id != nil {
newCustomer.Id = *id newCustomer.Id = *id
} }
@@ -48,7 +50,7 @@ func (n *NKodeAPI) CreateNewCustomer(nkodePolicy models.NKodePolicy, id *models.
return &newCustomer.Id, nil return &newCustomer.Id, nil
} }
func (n *NKodeAPI) GenerateSignupResetInterface(userEmail models.UserEmail, customerId models.CustomerId, kp models.KeypadDimension, reset bool) (*models.GenerateSignupResetInterfaceResp, error) { func (n *NKodeAPI) GenerateSignupResetInterface(userEmail models.UserEmail, customerId models.CustomerId, kp entities.KeypadDimension, reset bool) (*models.GenerateSignupResetInterfaceResp, error) {
user, err := n.Db.GetUser(userEmail, customerId) user, err := n.Db.GetUser(userEmail, customerId)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -61,7 +63,7 @@ func (n *NKodeAPI) GenerateSignupResetInterface(userEmail models.UserEmail, cust
if err != nil { if err != nil {
return nil, err return nil, err
} }
signupSession, err := models.NewSignupResetSession(userEmail, kp, customerId, svgIdxInterface, reset) signupSession, err := entities.NewSignupResetSession(userEmail, kp, customerId, svgIdxInterface, reset)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -94,7 +96,7 @@ func (n *NKodeAPI) SetNKode(customerId models.CustomerId, sessionId models.Sessi
log.Printf("session id does not exist %s", sessionId) log.Printf("session id does not exist %s", sessionId)
return nil, config.ErrSignupSessionDNE return nil, config.ErrSignupSessionDNE
} }
userSession, ok := session.(models.UserSignSession) userSession, ok := session.(entities.UserSignSession)
if !ok { if !ok {
// handle the case where the type assertion fails // handle the case where the type assertion fails
return nil, config.ErrSignupSessionDNE return nil, config.ErrSignupSessionDNE
@@ -113,7 +115,7 @@ func (n *NKodeAPI) ConfirmNKode(customerId models.CustomerId, sessionId models.S
log.Printf("session id does not exist %s", sessionId) log.Printf("session id does not exist %s", sessionId)
return config.ErrSignupSessionDNE return config.ErrSignupSessionDNE
} }
userSession, ok := session.(models.UserSignSession) userSession, ok := session.(entities.UserSignSession)
if !ok { if !ok {
// handle the case where the type assertion fails // handle the case where the type assertion fails
return config.ErrSignupSessionDNE return config.ErrSignupSessionDNE
@@ -129,7 +131,7 @@ func (n *NKodeAPI) ConfirmNKode(customerId models.CustomerId, sessionId models.S
if err = customer.IsValidNKode(userSession.Kp, passcode); err != nil { if err = customer.IsValidNKode(userSession.Kp, passcode); err != nil {
return err return err
} }
user, err := models.NewUser(*customer, string(userSession.UserEmail), passcode, userSession.LoginUserInterface, userSession.Kp) user, err := entities.NewUser(*customer, string(userSession.UserEmail), passcode, userSession.LoginUserInterface, userSession.Kp)
if err != nil { if err != nil {
return err return err
} }
@@ -186,7 +188,7 @@ func (n *NKodeAPI) Login(customerId models.CustomerId, userEmail models.UserEmai
log.Printf("user %s for customer %s dne", userEmail, customerId) log.Printf("user %s for customer %s dne", userEmail, customerId)
return nil, config.ErrUserForCustomerDNE return nil, config.ErrUserForCustomerDNE
} }
passcode, err := models.ValidKeyEntry(*user, *customer, keySelection) passcode, err := entities.ValidKeyEntry(*user, *customer, keySelection)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -213,7 +215,7 @@ func (n *NKodeAPI) RenewAttributes(customerId models.CustomerId) error {
} }
func (n *NKodeAPI) RandomSvgInterface() ([]string, error) { func (n *NKodeAPI) RandomSvgInterface() ([]string, error) {
return n.Db.RandomSvgInterface(models.KeypadMax) return n.Db.RandomSvgInterface(entities.KeypadMax)
} }
func (n *NKodeAPI) RefreshToken(userEmail models.UserEmail, customerId models.CustomerId, refreshToken string) (string, error) { func (n *NKodeAPI) RefreshToken(userEmail models.UserEmail, customerId models.CustomerId, refreshToken string) (string, error) {

View File

@@ -4,6 +4,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go-nkode/internal/db" "go-nkode/internal/db"
"go-nkode/internal/email" "go-nkode/internal/email"
"go-nkode/internal/entities"
"go-nkode/internal/models" "go-nkode/internal/models"
"go-nkode/internal/security" "go-nkode/internal/security"
"os" "os"
@@ -28,7 +29,7 @@ func TestNKodeAPI(t *testing.T) {
//} //}
} }
func testNKodeAPI(t *testing.T, db DbAccessor) { func testNKodeAPI(t *testing.T, db db.CustomerUserRepository) {
bufferSize := 100 bufferSize := 100
emailsPerSec := 14 emailsPerSec := 14
testClient := email.TestEmailClient{} testClient := email.TestEmailClient{}
@@ -41,7 +42,7 @@ func testNKodeAPI(t *testing.T, db DbAccessor) {
userEmail := models.UserEmail("test_username" + security.GenerateRandomString(12) + "@example.com") userEmail := models.UserEmail("test_username" + security.GenerateRandomString(12) + "@example.com")
passcodeLen := 4 passcodeLen := 4
nkodePolicy := models.NewDefaultNKodePolicy() nkodePolicy := models.NewDefaultNKodePolicy()
keypadSize := models.KeypadDimension{AttrsPerKey: attrsPerKey, NumbOfKeys: numbOfKeys} keypadSize := entities.KeypadDimension{AttrsPerKey: attrsPerKey, NumbOfKeys: numbOfKeys}
nkodeApi := NewNKodeAPI(db, queue) nkodeApi := NewNKodeAPI(db, queue)
customerId, err := nkodeApi.CreateNewCustomer(nkodePolicy, nil) customerId, err := nkodeApi.CreateNewCustomer(nkodePolicy, nil)
assert.NoError(t, err) assert.NoError(t, err)
@@ -51,20 +52,20 @@ func testNKodeAPI(t *testing.T, db DbAccessor) {
sessionIdStr := signupResponse.SessionId sessionIdStr := signupResponse.SessionId
sessionId, err := models.SessionIdFromString(sessionIdStr) sessionId, err := models.SessionIdFromString(sessionIdStr)
assert.NoError(t, err) assert.NoError(t, err)
keypadSize = models.KeypadDimension{AttrsPerKey: numbOfKeys, NumbOfKeys: numbOfKeys} keypadSize = entities.KeypadDimension{AttrsPerKey: numbOfKeys, NumbOfKeys: numbOfKeys}
userPasscode := setInterface[:passcodeLen] userPasscode := setInterface[:passcodeLen]
setKeySelect, err := models.SelectKeyByAttrIdx(setInterface, userPasscode, keypadSize) setKeySelect, err := entities.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 := models.SelectKeyByAttrIdx(confirmInterface, userPasscode, keypadSize) confirmKeySelect, err := entities.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 = models.KeypadDimension{AttrsPerKey: attrsPerKey, NumbOfKeys: numbOfKeys} keypadSize = entities.KeypadDimension{AttrsPerKey: attrsPerKey, NumbOfKeys: numbOfKeys}
loginInterface, err := nkodeApi.GetLoginInterface(userEmail, *customerId) loginInterface, err := nkodeApi.GetLoginInterface(userEmail, *customerId)
assert.NoError(t, err) assert.NoError(t, err)
loginKeySelection, err := models.SelectKeyByAttrIdx(loginInterface.UserIdxInterface, userPasscode, keypadSize) loginKeySelection, err := entities.SelectKeyByAttrIdx(loginInterface.UserIdxInterface, userPasscode, keypadSize)
assert.NoError(t, err) assert.NoError(t, err)
_, err = nkodeApi.Login(*customerId, userEmail, loginKeySelection) _, err = nkodeApi.Login(*customerId, userEmail, loginKeySelection)
assert.NoError(t, err) assert.NoError(t, err)
@@ -74,34 +75,34 @@ func testNKodeAPI(t *testing.T, db DbAccessor) {
loginInterface, err = nkodeApi.GetLoginInterface(userEmail, *customerId) loginInterface, err = nkodeApi.GetLoginInterface(userEmail, *customerId)
assert.NoError(t, err) assert.NoError(t, err)
loginKeySelection, err = models.SelectKeyByAttrIdx(loginInterface.UserIdxInterface, userPasscode, keypadSize) loginKeySelection, err = entities.SelectKeyByAttrIdx(loginInterface.UserIdxInterface, userPasscode, keypadSize)
assert.NoError(t, err) assert.NoError(t, err)
_, err = nkodeApi.Login(*customerId, userEmail, loginKeySelection) _, err = nkodeApi.Login(*customerId, userEmail, loginKeySelection)
assert.NoError(t, err) assert.NoError(t, err)
/// Reset nKode /// Reset nKode
attrsPerKey = 6 attrsPerKey = 6
keypadSize = models.KeypadDimension{AttrsPerKey: attrsPerKey, NumbOfKeys: numbOfKeys} keypadSize = entities.KeypadDimension{AttrsPerKey: attrsPerKey, NumbOfKeys: numbOfKeys}
resetResponse, err := nkodeApi.GenerateSignupResetInterface(userEmail, *customerId, keypadSize, true) resetResponse, err := nkodeApi.GenerateSignupResetInterface(userEmail, *customerId, keypadSize, true)
assert.NoError(t, err) assert.NoError(t, err)
setInterface = resetResponse.UserIdxInterface setInterface = resetResponse.UserIdxInterface
sessionIdStr = resetResponse.SessionId sessionIdStr = resetResponse.SessionId
sessionId, err = models.SessionIdFromString(sessionIdStr) sessionId, err = models.SessionIdFromString(sessionIdStr)
assert.NoError(t, err) assert.NoError(t, err)
keypadSize = models.KeypadDimension{AttrsPerKey: numbOfKeys, NumbOfKeys: numbOfKeys} keypadSize = entities.KeypadDimension{AttrsPerKey: numbOfKeys, NumbOfKeys: numbOfKeys}
userPasscode = setInterface[:passcodeLen] userPasscode = setInterface[:passcodeLen]
setKeySelect, err = models.SelectKeyByAttrIdx(setInterface, userPasscode, keypadSize) setKeySelect, err = entities.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 = models.SelectKeyByAttrIdx(confirmInterface, userPasscode, keypadSize) confirmKeySelect, err = entities.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 = models.KeypadDimension{AttrsPerKey: attrsPerKey, NumbOfKeys: numbOfKeys} keypadSize = entities.KeypadDimension{AttrsPerKey: attrsPerKey, NumbOfKeys: numbOfKeys}
loginInterface2, err := nkodeApi.GetLoginInterface(userEmail, *customerId) loginInterface2, err := nkodeApi.GetLoginInterface(userEmail, *customerId)
assert.NoError(t, err) assert.NoError(t, err)
loginKeySelection, err = models.SelectKeyByAttrIdx(loginInterface2.UserIdxInterface, userPasscode, keypadSize) loginKeySelection, err = entities.SelectKeyByAttrIdx(loginInterface2.UserIdxInterface, userPasscode, keypadSize)
assert.NoError(t, err) assert.NoError(t, err)
_, err = nkodeApi.Login(*customerId, userEmail, loginKeySelection) _, err = nkodeApi.Login(*customerId, userEmail, loginKeySelection)
assert.NoError(t, err) assert.NoError(t, err)

View File

@@ -0,0 +1,21 @@
package db
import (
"go-nkode/internal/entities"
"go-nkode/internal/models"
)
type CustomerUserRepository interface {
GetCustomer(models.CustomerId) (*entities.Customer, error)
GetUser(models.UserEmail, models.CustomerId) (*entities.User, error)
WriteNewCustomer(entities.Customer) error
WriteNewUser(entities.User) error
UpdateUserNKode(entities.User) error
UpdateUserInterface(models.UserId, entities.UserInterface) error
UpdateUserRefreshToken(models.UserId, string) error
Renew(models.CustomerId) error
RefreshUserPasscode(entities.User, []int, entities.CustomerAttributes) error
RandomSvgInterface(entities.KeypadDimension) ([]string, error)
RandomSvgIdxInterface(entities.KeypadDimension) (models.SvgIdInterface, error)
GetSvgStringInterface(models.SvgIdInterface) ([]string, error)
}

View File

@@ -3,24 +3,25 @@ package db
import ( import (
"errors" "errors"
"fmt" "fmt"
"go-nkode/internal/entities"
"go-nkode/internal/models" "go-nkode/internal/models"
) )
type InMemoryDb struct { type InMemoryDb struct {
Customers map[models.CustomerId]models.Customer Customers map[models.CustomerId]entities.Customer
Users map[models.UserId]models.User Users map[models.UserId]entities.User
userIdMap map[string]models.UserId userIdMap map[string]models.UserId
} }
func NewInMemoryDb() InMemoryDb { func NewInMemoryDb() InMemoryDb {
return InMemoryDb{ return InMemoryDb{
Customers: make(map[models.CustomerId]models.Customer), Customers: make(map[models.CustomerId]entities.Customer),
Users: make(map[models.UserId]models.User), Users: make(map[models.UserId]entities.User),
userIdMap: make(map[string]models.UserId), userIdMap: make(map[string]models.UserId),
} }
} }
func (db *InMemoryDb) GetCustomer(id models.CustomerId) (*models.Customer, error) { func (db *InMemoryDb) GetCustomer(id models.CustomerId) (*entities.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 +29,7 @@ func (db *InMemoryDb) GetCustomer(id models.CustomerId) (*models.Customer, error
return &customer, nil return &customer, nil
} }
func (db *InMemoryDb) GetUser(username models.UserEmail, customerId models.CustomerId) (*models.User, error) { func (db *InMemoryDb) GetUser(username models.UserEmail, customerId models.CustomerId) (*entities.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 +42,7 @@ func (db *InMemoryDb) GetUser(username models.UserEmail, customerId models.Custo
return &user, nil return &user, nil
} }
func (db *InMemoryDb) WriteNewCustomer(customer models.Customer) error { func (db *InMemoryDb) WriteNewCustomer(customer entities.Customer) error {
_, exists := db.Customers[customer.Id] _, exists := db.Customers[customer.Id]
if exists { if exists {
@@ -51,7 +52,7 @@ func (db *InMemoryDb) WriteNewCustomer(customer models.Customer) error {
return nil return nil
} }
func (db *InMemoryDb) WriteNewUser(user models.User) error { func (db *InMemoryDb) WriteNewUser(user entities.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.Email, user.CustomerId)) return errors.New(fmt.Sprintf("can't add user %s to customer %s: customer dne", user.Email, user.CustomerId))
@@ -67,11 +68,11 @@ func (db *InMemoryDb) WriteNewUser(user models.User) error {
return nil return nil
} }
func (db *InMemoryDb) UpdateUserNKode(user models.User) error { func (db *InMemoryDb) UpdateUserNKode(user entities.User) error {
return errors.ErrUnsupported return errors.ErrUnsupported
} }
func (db *InMemoryDb) UpdateUserInterface(userId models.UserId, ui models.UserInterface) error { func (db *InMemoryDb) UpdateUserInterface(userId models.UserId, ui entities.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))
@@ -107,7 +108,7 @@ func (db *InMemoryDb) Renew(id models.CustomerId) error {
return nil return nil
} }
func (db *InMemoryDb) RefreshUserPasscode(user models.User, passocode []int, customerAttr models.CustomerAttributes) error { func (db *InMemoryDb) RefreshUserPasscode(user entities.User, passocode []int, customerAttr entities.CustomerAttributes) error {
err := user.RefreshPasscode(passocode, customerAttr) err := user.RefreshPasscode(passocode, customerAttr)
if err != nil { if err != nil {
return err return err
@@ -116,11 +117,11 @@ func (db *InMemoryDb) RefreshUserPasscode(user models.User, passocode []int, cus
return nil return nil
} }
func (db *InMemoryDb) RandomSvgInterface(kp models.KeypadDimension) ([]string, error) { func (db *InMemoryDb) RandomSvgInterface(kp entities.KeypadDimension) ([]string, error) {
return make([]string, kp.TotalAttrs()), nil return make([]string, kp.TotalAttrs()), nil
} }
func (db *InMemoryDb) RandomSvgIdxInterface(kp models.KeypadDimension) (models.SvgIdInterface, error) { func (db *InMemoryDb) RandomSvgIdxInterface(kp entities.KeypadDimension) (models.SvgIdInterface, error) {
svgs := make(models.SvgIdInterface, kp.TotalAttrs()) svgs := make(models.SvgIdInterface, kp.TotalAttrs())
for idx := range svgs { for idx := range svgs {
svgs[idx] = idx svgs[idx] = idx

View File

@@ -6,6 +6,7 @@ import (
"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
"go-nkode/config" "go-nkode/config"
"go-nkode/internal/entities"
"go-nkode/internal/models" "go-nkode/internal/models"
"go-nkode/internal/security" "go-nkode/internal/security"
"log" "log"
@@ -60,7 +61,7 @@ func (d *SqliteDB) CloseDb() {
} }
} }
func (d *SqliteDB) WriteNewCustomer(c models.Customer) error { func (d *SqliteDB) WriteNewCustomer(c entities.Customer) error {
query := ` query := `
INSERT INTO customer ( INSERT INTO customer (
id id
@@ -85,7 +86,7 @@ VALUES (?,?,?,?,?,?,?,?,?,?,?)
return d.addWriteTx(query, args) return d.addWriteTx(query, args)
} }
func (d *SqliteDB) WriteNewUser(u models.User) error { func (d *SqliteDB) WriteNewUser(u entities.User) error {
query := ` query := `
INSERT INTO user ( INSERT INTO user (
id id
@@ -128,7 +129,7 @@ VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
return d.addWriteTx(query, args) return d.addWriteTx(query, args)
} }
func (d *SqliteDB) UpdateUserNKode(u models.User) error { func (d *SqliteDB) UpdateUserNKode(u entities.User) error {
query := ` query := `
UPDATE user UPDATE user
SET renew = ? SET renew = ?
@@ -158,7 +159,7 @@ WHERE email = ? AND customer_id = ?
return d.addWriteTx(query, args) return d.addWriteTx(query, args)
} }
func (d *SqliteDB) UpdateUserInterface(id models.UserId, ui models.UserInterface) error { func (d *SqliteDB) UpdateUserInterface(id models.UserId, ui entities.UserInterface) error {
query := ` query := `
UPDATE user SET idx_interface = ?, last_login = ? WHERE id = ? UPDATE user SET idx_interface = ?, last_login = ? WHERE id = ?
` `
@@ -219,20 +220,20 @@ WHERE customer_id = ?
if err != nil { if err != nil {
return err return err
} }
user := models.User{ user := entities.User{
Id: models.UserId{}, Id: models.UserId{},
CustomerId: models.CustomerId{}, CustomerId: models.CustomerId{},
Email: "", Email: "",
EncipheredPasscode: models.EncipheredNKode{}, EncipheredPasscode: models.EncipheredNKode{},
Kp: models.KeypadDimension{ Kp: entities.KeypadDimension{
AttrsPerKey: attrsPerKey, AttrsPerKey: attrsPerKey,
NumbOfKeys: numbOfKeys, NumbOfKeys: numbOfKeys,
}, },
CipherKeys: models.UserCipherKeys{ CipherKeys: entities.UserCipherKeys{
AlphaKey: security.ByteArrToUint64Arr(alphaBytes), AlphaKey: security.ByteArrToUint64Arr(alphaBytes),
SetKey: security.ByteArrToUint64Arr(setBytes), SetKey: security.ByteArrToUint64Arr(setBytes),
}, },
Interface: models.UserInterface{}, Interface: entities.UserInterface{},
Renew: false, Renew: false,
} }
err = user.RenewKeys(setXor, attrXor) err = user.RenewKeys(setXor, attrXor)
@@ -255,7 +256,7 @@ WHERE id = ?;
return d.addWriteTx(renewQuery, renewArgs) return d.addWriteTx(renewQuery, renewArgs)
} }
func (d *SqliteDB) RefreshUserPasscode(user models.User, passcodeIdx []int, customerAttr models.CustomerAttributes) error { func (d *SqliteDB) RefreshUserPasscode(user entities.User, passcodeIdx []int, customerAttr entities.CustomerAttributes) error {
err := user.RefreshPasscode(passcodeIdx, customerAttr) err := user.RefreshPasscode(passcodeIdx, customerAttr)
if err != nil { if err != nil {
return err return err
@@ -276,7 +277,7 @@ WHERE id = ?;
args := []any{user.RefreshToken, 0, user.EncipheredPasscode.Code, user.EncipheredPasscode.Mask, security.Uint64ArrToByteArr(user.CipherKeys.AlphaKey), security.Uint64ArrToByteArr(user.CipherKeys.SetKey), security.Uint64ArrToByteArr(user.CipherKeys.PassKey), security.Uint64ArrToByteArr(user.CipherKeys.MaskKey), user.CipherKeys.Salt, uuid.UUID(user.Id).String()} args := []any{user.RefreshToken, 0, user.EncipheredPasscode.Code, user.EncipheredPasscode.Mask, security.Uint64ArrToByteArr(user.CipherKeys.AlphaKey), security.Uint64ArrToByteArr(user.CipherKeys.SetKey), security.Uint64ArrToByteArr(user.CipherKeys.PassKey), security.Uint64ArrToByteArr(user.CipherKeys.MaskKey), user.CipherKeys.Salt, uuid.UUID(user.Id).String()}
return d.addWriteTx(query, args) return d.addWriteTx(query, args)
} }
func (d *SqliteDB) GetCustomer(id models.CustomerId) (*models.Customer, error) { func (d *SqliteDB) GetCustomer(id models.CustomerId) (*entities.Customer, error) {
tx, err := d.db.Begin() tx, err := d.db.Begin()
if err != nil { if err != nil {
return nil, err return nil, err
@@ -324,7 +325,7 @@ WHERE id = ?
if err != nil { if err != nil {
return nil, err return nil, err
} }
customer := models.Customer{ customer := entities.Customer{
Id: id, Id: id,
NKodePolicy: models.NKodePolicy{ NKodePolicy: models.NKodePolicy{
MaxNkodeLen: maxNKodeLen, MaxNkodeLen: maxNKodeLen,
@@ -334,7 +335,7 @@ WHERE id = ?
LockOut: lockOut, LockOut: lockOut,
Expiration: expiration, Expiration: expiration,
}, },
Attributes: models.NewCustomerAttributesFromBytes(attributeValues, setValues), Attributes: entities.NewCustomerAttributesFromBytes(attributeValues, setValues),
} }
if err = tx.Commit(); err != nil { if err = tx.Commit(); err != nil {
return nil, err return nil, err
@@ -342,7 +343,7 @@ WHERE id = ?
return &customer, nil return &customer, nil
} }
func (d *SqliteDB) GetUser(email models.UserEmail, customerId models.CustomerId) (*models.User, error) { func (d *SqliteDB) GetUser(email models.UserEmail, customerId models.CustomerId) (*entities.User, error) {
tx, err := d.db.Begin() tx, err := d.db.Begin()
if err != nil { if err != nil {
return nil, err return nil, err
@@ -401,7 +402,7 @@ WHERE user.email = ? AND user.customer_id = ?
renew = true renew = true
} }
user := models.User{ user := entities.User{
Id: models.UserId(userId), Id: models.UserId(userId),
CustomerId: customerId, CustomerId: customerId,
Email: email, Email: email,
@@ -409,11 +410,11 @@ WHERE user.email = ? AND user.customer_id = ?
Code: code, Code: code,
Mask: mask, Mask: mask,
}, },
Kp: models.KeypadDimension{ Kp: entities.KeypadDimension{
AttrsPerKey: attrsPerKey, AttrsPerKey: attrsPerKey,
NumbOfKeys: numbOfKeys, NumbOfKeys: numbOfKeys,
}, },
CipherKeys: models.UserCipherKeys{ CipherKeys: entities.UserCipherKeys{
AlphaKey: security.ByteArrToUint64Arr(alphaKey), AlphaKey: security.ByteArrToUint64Arr(alphaKey),
SetKey: security.ByteArrToUint64Arr(setKey), SetKey: security.ByteArrToUint64Arr(setKey),
PassKey: security.ByteArrToUint64Arr(passKey), PassKey: security.ByteArrToUint64Arr(passKey),
@@ -422,7 +423,7 @@ WHERE user.email = ? AND user.customer_id = ?
MaxNKodeLen: maxNKodeLen, MaxNKodeLen: maxNKodeLen,
Kp: nil, Kp: nil,
}, },
Interface: models.UserInterface{ Interface: entities.UserInterface{
IdxInterface: security.ByteArrToIntArr(idxInterface), IdxInterface: security.ByteArrToIntArr(idxInterface),
SvgId: security.ByteArrToIntArr(svgIdInterface), SvgId: security.ByteArrToIntArr(svgIdInterface),
Kp: nil, Kp: nil,
@@ -438,7 +439,7 @@ WHERE user.email = ? AND user.customer_id = ?
return &user, nil return &user, nil
} }
func (d *SqliteDB) RandomSvgInterface(kp models.KeypadDimension) ([]string, error) { func (d *SqliteDB) RandomSvgInterface(kp entities.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
@@ -446,7 +447,7 @@ func (d *SqliteDB) RandomSvgInterface(kp models.KeypadDimension) ([]string, erro
return d.getSvgsById(ids) return d.getSvgsById(ids)
} }
func (d *SqliteDB) RandomSvgIdxInterface(kp models.KeypadDimension) (models.SvgIdInterface, error) { func (d *SqliteDB) RandomSvgIdxInterface(kp entities.KeypadDimension) (models.SvgIdInterface, error) {
return d.getRandomIds(kp.TotalAttrs()) return d.getRandomIds(kp.TotalAttrs())
} }

View File

@@ -2,7 +2,7 @@ package db
import ( import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go-nkode/internal/api" "go-nkode/internal/entities"
"go-nkode/internal/models" "go-nkode/internal/models"
"os" "os"
"testing" "testing"
@@ -24,9 +24,9 @@ func TestNewSqliteDB(t *testing.T) {
// } // }
} }
func testSignupLoginRenew(t *testing.T, db api.DbAccessor) { func testSignupLoginRenew(t *testing.T, db CustomerUserRepository) {
nkodePolicy := models.NewDefaultNKodePolicy() nkodePolicy := models.NewDefaultNKodePolicy()
customerOrig, err := models.NewCustomer(nkodePolicy) customerOrig, err := entities.NewCustomer(nkodePolicy)
assert.NoError(t, err) assert.NoError(t, err)
err = db.WriteNewCustomer(*customerOrig) err = db.WriteNewCustomer(*customerOrig)
assert.NoError(t, err) assert.NoError(t, err)
@@ -34,12 +34,12 @@ func testSignupLoginRenew(t *testing.T, db api.DbAccessor) {
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, customerOrig, customer) assert.Equal(t, customerOrig, customer)
username := "test_user@example.com" username := "test_user@example.com"
kp := models.KeypadDefault kp := entities.KeypadDefault
passcodeIdx := []int{0, 1, 2, 3} passcodeIdx := []int{0, 1, 2, 3}
mockSvgInterface := make(models.SvgIdInterface, kp.TotalAttrs()) mockSvgInterface := make(models.SvgIdInterface, kp.TotalAttrs())
ui, err := models.NewUserInterface(&kp, mockSvgInterface) ui, err := entities.NewUserInterface(&kp, mockSvgInterface)
assert.NoError(t, err) assert.NoError(t, err)
userOrig, err := models.NewUser(*customer, username, passcodeIdx, *ui, kp) userOrig, err := entities.NewUser(*customer, username, passcodeIdx, *ui, kp)
assert.NoError(t, err) assert.NoError(t, err)
err = db.WriteNewUser(*userOrig) err = db.WriteNewUser(*userOrig)
assert.NoError(t, err) assert.NoError(t, err)
@@ -52,8 +52,8 @@ func testSignupLoginRenew(t *testing.T, db api.DbAccessor) {
} }
func testSqliteDBRandomSvgInterface(t *testing.T, db api.DbAccessor) { func testSqliteDBRandomSvgInterface(t *testing.T, db CustomerUserRepository) {
kp := models.KeypadMax kp := entities.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

@@ -14,7 +14,7 @@ import (
"time" "time"
) )
type EmailClient interface { type Client interface {
SendEmail(Email) error SendEmail(Email) error
} }
@@ -103,22 +103,22 @@ func (s *SESClient) SendEmail(email Email) error {
return nil return nil
} }
// EmailQueue represents the email queue with rate limiting // Queue represents the email queue with rate limiting
type EmailQueue struct { type Queue struct {
stop bool stop bool
emailQueue chan Email // Email queue emailQueue chan Email // Email queue
rateLimit <-chan time.Time // Rate limiter rateLimit <-chan time.Time // Rate limiter
client EmailClient // SES client to send emails client Client // SES client to send emails
wg sync.WaitGroup // To wait for all emails to be processed wg sync.WaitGroup // To wait for all emails to be processed
FailedSendCount int FailedSendCount int
} }
// NewEmailQueue creates a new rate-limited email queue // NewEmailQueue creates a new rate-limited email queue
func NewEmailQueue(bufferSize int, emailsPerSecond int, client EmailClient) *EmailQueue { func NewEmailQueue(bufferSize int, emailsPerSecond int, client Client) *Queue {
// Create a ticker that ticks every second to limit the rate of sending emails // Create a ticker that ticks every second to limit the rate of sending emails
rateLimit := time.Tick(time.Second / time.Duration(emailsPerSecond)) rateLimit := time.Tick(time.Second / time.Duration(emailsPerSecond))
return &EmailQueue{ return &Queue{
stop: false, stop: false,
emailQueue: make(chan Email, bufferSize), emailQueue: make(chan Email, bufferSize),
rateLimit: rateLimit, rateLimit: rateLimit,
@@ -128,7 +128,7 @@ func NewEmailQueue(bufferSize int, emailsPerSecond int, client EmailClient) *Ema
} }
// AddEmail queues a new email to be sent // AddEmail queues a new email to be sent
func (q *EmailQueue) AddEmail(email Email) { func (q *Queue) AddEmail(email Email) {
if q.stop { if q.stop {
log.Printf("email %s with subject %s not add. Stopping queue", email.Recipient, email.Subject) log.Printf("email %s with subject %s not add. Stopping queue", email.Recipient, email.Subject)
return return
@@ -138,7 +138,7 @@ func (q *EmailQueue) AddEmail(email Email) {
} }
// Start begins processing the email queue with rate limiting // Start begins processing the email queue with rate limiting
func (q *EmailQueue) Start() { func (q *Queue) Start() {
q.stop = false q.stop = false
// Worker goroutine that processes emails from the queue // Worker goroutine that processes emails from the queue
go func() { go func() {
@@ -151,7 +151,7 @@ func (q *EmailQueue) Start() {
} }
// sendEmail sends an email using the SES client // sendEmail sends an email using the SES client
func (q *EmailQueue) sendEmail(email Email) { func (q *Queue) sendEmail(email Email) {
if err := q.client.SendEmail(email); err != nil { if err := q.client.SendEmail(email); err != nil {
q.FailedSendCount += 1 q.FailedSendCount += 1
log.Printf("Failed to send email to %s: %v\n", email.Recipient, err) log.Printf("Failed to send email to %s: %v\n", email.Recipient, err)
@@ -159,7 +159,7 @@ func (q *EmailQueue) sendEmail(email Email) {
} }
// Stop stops the queue after all emails have been processed // Stop stops the queue after all emails have been processed
func (q *EmailQueue) Stop() { func (q *Queue) Stop() {
q.stop = true q.stop = true
// Wait for all emails to be processed // Wait for all emails to be processed
q.wg.Wait() q.wg.Wait()

View File

@@ -1,25 +1,26 @@
package models package entities
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
"go-nkode/config" "go-nkode/config"
"go-nkode/internal/models"
"go-nkode/internal/security" "go-nkode/internal/security"
"go-nkode/internal/utils" "go-nkode/internal/utils"
) )
type Customer struct { type Customer struct {
Id CustomerId Id models.CustomerId
NKodePolicy NKodePolicy NKodePolicy models.NKodePolicy
Attributes CustomerAttributes Attributes CustomerAttributes
} }
func NewCustomer(nkodePolicy NKodePolicy) (*Customer, error) { func NewCustomer(nkodePolicy models.NKodePolicy) (*Customer, error) {
customerAttrs, err := NewCustomerAttributes() customerAttrs, err := NewCustomerAttributes()
if err != nil { if err != nil {
return nil, err return nil, err
} }
customer := Customer{ customer := Customer{
Id: CustomerId(uuid.New()), Id: models.CustomerId(uuid.New()),
NKodePolicy: nkodePolicy, NKodePolicy: nkodePolicy,
Attributes: *customerAttrs, Attributes: *customerAttrs,
} }

View File

@@ -1,4 +1,4 @@
package models package entities
import ( import (
"go-nkode/internal/security" "go-nkode/internal/security"

View File

@@ -1,7 +1,8 @@
package models package entities
import ( import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go-nkode/internal/models"
"testing" "testing"
) )
@@ -18,10 +19,10 @@ func testNewCustomerAttributes(t *testing.T) {
func testCustomerValidKeyEntry(t *testing.T) { func testCustomerValidKeyEntry(t *testing.T) {
kp := KeypadDimension{AttrsPerKey: 10, NumbOfKeys: 9} kp := KeypadDimension{AttrsPerKey: 10, NumbOfKeys: 9}
nkodePolicy := NewDefaultNKodePolicy() nkodePolicy := models.NewDefaultNKodePolicy()
customer, err := NewCustomer(nkodePolicy) customer, err := NewCustomer(nkodePolicy)
assert.NoError(t, err) assert.NoError(t, err)
mockSvgInterface := make(SvgIdInterface, kp.TotalAttrs()) mockSvgInterface := make(models.SvgIdInterface, kp.TotalAttrs())
userInterface, err := NewUserInterface(&kp, mockSvgInterface) userInterface, err := NewUserInterface(&kp, mockSvgInterface)
assert.NoError(t, err) assert.NoError(t, err)
userEmail := "testing@example.com" userEmail := "testing@example.com"
@@ -42,10 +43,10 @@ func testCustomerValidKeyEntry(t *testing.T) {
func testCustomerIsValidNKode(t *testing.T) { func testCustomerIsValidNKode(t *testing.T) {
kp := KeypadDimension{AttrsPerKey: 10, NumbOfKeys: 7} kp := KeypadDimension{AttrsPerKey: 10, NumbOfKeys: 7}
nkodePolicy := NewDefaultNKodePolicy() nkodePolicy := models.NewDefaultNKodePolicy()
customer, err := NewCustomer(nkodePolicy) customer, err := NewCustomer(nkodePolicy)
assert.NoError(t, err) assert.NoError(t, err)
mockSvgInterface := make(SvgIdInterface, kp.TotalAttrs()) mockSvgInterface := make(models.SvgIdInterface, kp.TotalAttrs())
userInterface, err := NewUserInterface(&kp, mockSvgInterface) userInterface, err := NewUserInterface(&kp, mockSvgInterface)
assert.NoError(t, err) assert.NoError(t, err)
userEmail := "testing123@example.com" userEmail := "testing123@example.com"

View File

@@ -1,4 +1,4 @@
package models package entities
import ( import (
"go-nkode/config" "go-nkode/config"

View File

@@ -1,4 +1,4 @@
package models package entities
import ( import (
"errors" "errors"

View File

@@ -1,17 +1,18 @@
package models package entities
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
"go-nkode/config" "go-nkode/config"
"go-nkode/internal/models"
"go-nkode/internal/security" "go-nkode/internal/security"
"log" "log"
) )
type User struct { type User struct {
Id UserId Id models.UserId
CustomerId CustomerId CustomerId models.CustomerId
Email UserEmail Email models.UserEmail
EncipheredPasscode EncipheredNKode EncipheredPasscode models.EncipheredNKode
Kp KeypadDimension Kp KeypadDimension
CipherKeys UserCipherKeys CipherKeys UserCipherKeys
Interface UserInterface Interface UserInterface
@@ -116,7 +117,7 @@ func ValidKeyEntry(user User, customer Customer, selectedKeys []int) ([]int, err
} }
func NewUser(customer Customer, userEmail string, passcodeIdx []int, ui UserInterface, kp KeypadDimension) (*User, error) { func NewUser(customer Customer, userEmail string, passcodeIdx []int, ui UserInterface, kp KeypadDimension) (*User, error) {
_, err := ParseEmail(userEmail) _, err := models.ParseEmail(userEmail)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -133,8 +134,8 @@ func NewUser(customer Customer, userEmail string, passcodeIdx []int, ui UserInte
return nil, err return nil, err
} }
newUser := User{ newUser := User{
Id: UserId(uuid.New()), Id: models.UserId(uuid.New()),
Email: UserEmail(userEmail), Email: models.UserEmail(userEmail),
EncipheredPasscode: *encipheredNKode, EncipheredPasscode: *encipheredNKode,
CipherKeys: *newKeys, CipherKeys: *newKeys,
Interface: ui, Interface: ui,

View File

@@ -1,9 +1,10 @@
package models package entities
import ( import (
"crypto/sha256" "crypto/sha256"
"errors" "errors"
"go-nkode/config" "go-nkode/config"
"go-nkode/internal/models"
"go-nkode/internal/security" "go-nkode/internal/security"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
) )
@@ -166,7 +167,7 @@ func (u *UserCipherKeys) DecipherMask(mask string, setVals []uint64, passcodeLen
return passcodeSet, nil return passcodeSet, nil
} }
func (u *UserCipherKeys) EncipherNKode(passcodeAttrIdx []int, customerAttrs CustomerAttributes) (*EncipheredNKode, error) { func (u *UserCipherKeys) EncipherNKode(passcodeAttrIdx []int, customerAttrs CustomerAttributes) (*models.EncipheredNKode, error) {
attrVals, err := customerAttrs.AttrValsForKp(*u.Kp) attrVals, err := customerAttrs.AttrValsForKp(*u.Kp)
code, err := u.EncipherSaltHashCode(passcodeAttrIdx, attrVals) code, err := u.EncipherSaltHashCode(passcodeAttrIdx, attrVals)
if err != nil { if err != nil {
@@ -185,7 +186,7 @@ func (u *UserCipherKeys) EncipherNKode(passcodeAttrIdx []int, customerAttrs Cust
if err != nil { if err != nil {
return nil, err return nil, err
} }
encipheredCode := EncipheredNKode{ encipheredCode := models.EncipheredNKode{
Code: code, Code: code,
Mask: mask, Mask: mask,
} }

View File

@@ -1,19 +1,20 @@
package models package entities
import ( import (
"go-nkode/config" "go-nkode/config"
"go-nkode/internal/models"
"go-nkode/internal/security" "go-nkode/internal/security"
"go-nkode/internal/utils" "go-nkode/internal/utils"
"log" "log"
) )
type UserInterface struct { type UserInterface struct {
IdxInterface IdxInterface IdxInterface models.IdxInterface
SvgId SvgIdInterface SvgId models.SvgIdInterface
Kp *KeypadDimension Kp *KeypadDimension
} }
func NewUserInterface(kp *KeypadDimension, svgId SvgIdInterface) (*UserInterface, error) { func NewUserInterface(kp *KeypadDimension, svgId models.SvgIdInterface) (*UserInterface, error) {
idxInterface := security.IdentityArray(kp.TotalAttrs()) idxInterface := security.IdentityArray(kp.TotalAttrs())
userInterface := UserInterface{ userInterface := UserInterface{
IdxInterface: idxInterface, IdxInterface: idxInterface,

View File

@@ -1,8 +1,9 @@
package models package entities
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
"go-nkode/config" "go-nkode/config"
"go-nkode/internal/models"
"go-nkode/internal/security" "go-nkode/internal/security"
py "go-nkode/internal/utils" py "go-nkode/internal/utils"
"log" "log"
@@ -10,20 +11,20 @@ import (
) )
type UserSignSession struct { type UserSignSession struct {
Id SessionId Id models.SessionId
CustomerId CustomerId CustomerId models.CustomerId
LoginUserInterface UserInterface LoginUserInterface UserInterface
Kp KeypadDimension Kp KeypadDimension
SetIdxInterface IdxInterface SetIdxInterface models.IdxInterface
ConfirmIdxInterface IdxInterface ConfirmIdxInterface models.IdxInterface
SetKeySelection KeySelection SetKeySelection models.KeySelection
UserEmail UserEmail UserEmail models.UserEmail
Reset bool Reset bool
Expire int Expire int
Colors []RGBColor Colors []models.RGBColor
} }
func NewSignupResetSession(userEmail UserEmail, kp KeypadDimension, customerId CustomerId, svgInterface SvgIdInterface, reset bool) (*UserSignSession, error) { func NewSignupResetSession(userEmail models.UserEmail, kp KeypadDimension, customerId models.CustomerId, svgInterface models.SvgIdInterface, reset bool) (*UserSignSession, error) {
loginInterface, err := NewUserInterface(&kp, svgInterface) loginInterface, err := NewUserInterface(&kp, svgInterface)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -33,7 +34,7 @@ func NewSignupResetSession(userEmail UserEmail, kp KeypadDimension, customerId C
return nil, err return nil, err
} }
session := UserSignSession{ session := UserSignSession{
Id: SessionId(uuid.New()), Id: models.SessionId(uuid.New()),
CustomerId: customerId, CustomerId: customerId,
LoginUserInterface: *loginInterface, LoginUserInterface: *loginInterface,
SetIdxInterface: signupInterface.IdxInterface, SetIdxInterface: signupInterface.IdxInterface,
@@ -48,7 +49,7 @@ func NewSignupResetSession(userEmail UserEmail, kp KeypadDimension, customerId C
return &session, nil return &session, nil
} }
func (s *UserSignSession) DeducePasscode(confirmKeyEntry KeySelection) ([]int, error) { func (s *UserSignSession) DeducePasscode(confirmKeyEntry models.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
}) })
@@ -109,7 +110,7 @@ func (s *UserSignSession) DeducePasscode(confirmKeyEntry KeySelection) ([]int, e
return passcode, nil return passcode, nil
} }
func (s *UserSignSession) SetUserNKode(keySelection KeySelection) (IdxInterface, error) { func (s *UserSignSession) SetUserNKode(keySelection models.KeySelection) (models.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
}) })
@@ -129,7 +130,7 @@ func (s *UserSignSession) SetUserNKode(keySelection KeySelection) (IdxInterface,
return s.ConfirmIdxInterface, nil return s.ConfirmIdxInterface, nil
} }
func (s *UserSignSession) getSelectedKeyVals(keySelections KeySelection, userInterface []int) ([][]int, error) { func (s *UserSignSession) getSelectedKeyVals(keySelections models.KeySelection, userInterface []int) ([][]int, error) {
signupKp := s.SignupKeypad() signupKp := s.SignupKeypad()
keypadInterface, err := security.ListToMatrix(userInterface, signupKp.AttrsPerKey) keypadInterface, err := security.ListToMatrix(userInterface, signupKp.AttrsPerKey)
if err != nil { if err != nil {
@@ -143,7 +144,7 @@ func (s *UserSignSession) getSelectedKeyVals(keySelections KeySelection, userInt
return keyVals, nil return keyVals, nil
} }
func signupInterface(baseUserInterface UserInterface, kp KeypadDimension) (*UserInterface, []RGBColor, error) { func signupInterface(baseUserInterface UserInterface, kp KeypadDimension) (*UserInterface, []models.RGBColor, error) {
// This method randomly drops sets from the base user interface so it is a square and dispersable matrix // This method randomly drops sets from the base user interface so it is a square and dispersable matrix
if kp.IsDispersable() { if kp.IsDispersable() {
return nil, nil, config.ErrKeypadIsNotDispersible return nil, nil, config.ErrKeypadIsNotDispersible
@@ -170,11 +171,11 @@ func signupInterface(baseUserInterface UserInterface, kp KeypadDimension) (*User
setIdxs = setIdxs[:kp.NumbOfKeys] setIdxs = setIdxs[:kp.NumbOfKeys]
sort.Ints(setIdxs) sort.Ints(setIdxs)
selectedSets := make([][]int, kp.NumbOfKeys) selectedSets := make([][]int, kp.NumbOfKeys)
selectedColors := make([]RGBColor, kp.NumbOfKeys) selectedColors := make([]models.RGBColor, kp.NumbOfKeys)
for idx, setIdx := range setIdxs { for idx, setIdx := range setIdxs {
selectedSets[idx] = attrSetView[setIdx] selectedSets[idx] = attrSetView[setIdx]
selectedColors[idx] = SetColors[setIdx] selectedColors[idx] = models.SetColors[setIdx]
} }
// convert set view back into key view // convert set view back into key view
selectedSets, err = security.MatrixTranspose(selectedSets) selectedSets, err = security.MatrixTranspose(selectedSets)

View File

@@ -1,7 +1,8 @@
package models package entities
import ( import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go-nkode/internal/models"
py "go-nkode/internal/utils" py "go-nkode/internal/utils"
"testing" "testing"
) )
@@ -64,7 +65,7 @@ func TestUserInterface_RandomShuffle(t *testing.T) {
AttrsPerKey: 10, AttrsPerKey: 10,
NumbOfKeys: 8, NumbOfKeys: 8,
} }
mockSvgInterface := make(SvgIdInterface, kp.TotalAttrs()) mockSvgInterface := make(models.SvgIdInterface, kp.TotalAttrs())
userInterface, err := NewUserInterface(&kp, mockSvgInterface) userInterface, err := NewUserInterface(&kp, mockSvgInterface)
assert.NoError(t, err) assert.NoError(t, err)
userInterfaceCopy := make([]int, len(userInterface.IdxInterface)) userInterfaceCopy := make([]int, len(userInterface.IdxInterface))
@@ -87,7 +88,7 @@ func TestUserInterface_DisperseInterface(t *testing.T) {
for idx := 0; idx < 10000; idx++ { for idx := 0; idx < 10000; idx++ {
kp := KeypadDimension{AttrsPerKey: 7, NumbOfKeys: 10} kp := KeypadDimension{AttrsPerKey: 7, NumbOfKeys: 10}
mockSvgInterface := make(SvgIdInterface, kp.TotalAttrs()) mockSvgInterface := make(models.SvgIdInterface, kp.TotalAttrs())
userInterface, err := NewUserInterface(&kp, mockSvgInterface) userInterface, err := NewUserInterface(&kp, mockSvgInterface)
assert.NoError(t, err) assert.NoError(t, err)
preDispersion, err := userInterface.AttributeAdjacencyGraph() preDispersion, err := userInterface.AttributeAdjacencyGraph()
@@ -106,7 +107,7 @@ func TestUserInterface_DisperseInterface(t *testing.T) {
func TestUserInterface_PartialInterfaceShuffle(t *testing.T) { func TestUserInterface_PartialInterfaceShuffle(t *testing.T) {
kp := KeypadDimension{AttrsPerKey: 7, NumbOfKeys: 10} kp := KeypadDimension{AttrsPerKey: 7, NumbOfKeys: 10}
mockSvgInterface := make(SvgIdInterface, kp.TotalAttrs()) mockSvgInterface := make(models.SvgIdInterface, kp.TotalAttrs())
userInterface, err := NewUserInterface(&kp, mockSvgInterface) userInterface, err := NewUserInterface(&kp, mockSvgInterface)
assert.NoError(t, err) assert.NoError(t, err)
preShuffle := userInterface.IdxInterface preShuffle := userInterface.IdxInterface