Files
nkode-core/handler/handler_test.go
2025-01-30 11:33:16 -06:00

293 lines
7.8 KiB
Go

package handler
import (
"bytes"
"context"
"encoding/json"
"fmt"
"git.infra.nkode.tech/dkelly/nkode-core/api"
"git.infra.nkode.tech/dkelly/nkode-core/email"
"git.infra.nkode.tech/dkelly/nkode-core/entities"
"git.infra.nkode.tech/dkelly/nkode-core/models"
"git.infra.nkode.tech/dkelly/nkode-core/repository"
"git.infra.nkode.tech/dkelly/nkode-core/security"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"log"
"net/http"
"net/http/httptest"
"os"
"testing"
)
func TestNkodeAPI(t *testing.T) {
tr := NewTestRouter()
tr.Start()
defer func(tr *TestRouter) {
err := tr.Stop()
assert.NoError(t, err)
}(tr)
// *** Create New Customer ***
customerID, status, err := tr.CreateNewCustomerDefaultPolicy()
assert.NoError(t, err)
assert.Equal(t, 200, status)
attrPerKey := 9
numKeys := 6
userEmail := "test_username" + security.GenerateRandomString(12) + "@example.com"
reset := false
// *** Signup ***
resp, status, err := tr.Signup(customerID, attrPerKey, numKeys, userEmail, reset)
assert.NoError(t, err)
assert.Equal(t, 200, status)
passcodeLen := 4
userPasscode := resp.UserIdxInterface[:passcodeLen]
kpSet := entities.KeypadDimension{
AttrsPerKey: numKeys,
NumbOfKeys: numKeys,
}
setKeySelection, err := entities.SelectKeyByAttrIdx(resp.UserIdxInterface, userPasscode, kpSet)
assert.NoError(t, err)
// *** Set nKode ***
confirmInterface, status, err := tr.SetNKode(customerID, setKeySelection, resp.SessionId)
assert.NoError(t, err)
assert.Equal(t, 200, status)
confirmKeySelection, err := entities.SelectKeyByAttrIdx(confirmInterface, userPasscode, kpSet)
assert.NoError(t, err)
// *** Confirm nKode ***
status, err = tr.ConfirmNKode(customerID, confirmKeySelection, resp.SessionId)
assert.NoError(t, err)
assert.Equal(t, 200, status)
// *** Get Login Interface ***
loginInterface, status, err := tr.GetLoginInterface(userEmail, customerID)
assert.NoError(t, err)
assert.Equal(t, 200, status)
kp := entities.KeypadDimension{
AttrsPerKey: attrPerKey,
NumbOfKeys: numKeys,
}
loginKeySelection, err := entities.SelectKeyByAttrIdx(loginInterface.UserIdxInterface, userPasscode, kp)
assert.NoError(t, err)
// *** Login ***
tokens, status, err := tr.Login(customerID, userEmail, loginKeySelection)
assert.NoError(t, err)
assert.Equal(t, 200, status)
assert.NotEmpty(t, tokens.AccessToken)
assert.NotEmpty(t, tokens.RefreshToken)
// *** Renew Attributes ***
}
type TestRouter struct {
Router *gin.Engine
EmailQueue *email.Queue
Repo *repository.SqliteRepository
Handler *NkodeHandler
}
func NewTestRouter() *TestRouter {
gin.SetMode(gin.TestMode)
router := gin.Default()
logger := log.Default()
ctx := context.Background()
dbPath := os.Getenv("TEST_DB")
repo, err := repository.NewSqliteRepository(ctx, dbPath)
if err != nil {
log.Fatal(err)
}
sesClient := email.NewSESClient()
emailQueue := email.NewEmailQueue(email.EmailQueueBufferSize, email.MaxEmailsPerSecond, &sesClient)
nkodeAPI := api.NewNKodeAPI(repo, emailQueue)
h := NkodeHandler{
API: nkodeAPI,
Logger: logger,
}
h.RegisterRoutes(router)
return &TestRouter{
Handler: &h,
Router: router,
EmailQueue: emailQueue,
Repo: repo,
}
}
func (r *TestRouter) Start() {
r.Repo.Start()
r.EmailQueue.Start()
}
func (r *TestRouter) Stop() error {
r.EmailQueue.Stop()
return r.Repo.Stop()
}
func (r *TestRouter) CreateNewCustomerDefaultPolicy() (string, int, error) {
p := entities.NewDefaultNKodePolicy()
body := bytes.NewBufferString(fmt.Sprintf(
"max_nkode_len=%d&min_nkode_len=%d&distinct_sets=%d&distinct_attributes=%d&lock_out=%d&expiration=%d",
p.MaxNkodeLen,
p.MinNkodeLen,
p.DistinctSets,
p.DistinctAttributes,
p.LockOut,
p.Expiration,
))
req := httptest.NewRequest(http.MethodPost, "/create-new-customer", body)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
rec := httptest.NewRecorder()
r.Router.ServeHTTP(rec, req)
var resp struct {
CustomerID string `json:"customer_id"`
}
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
return "", rec.Code, err
}
return resp.CustomerID, rec.Code, nil
}
func (r *TestRouter) Signup(
customerID string,
attrsPerKey int,
numberOfKeys int,
userEmail string,
reset bool,
) (*entities.SignupResetInterface, int, error) {
body := bytes.NewBufferString(fmt.Sprintf(
"customer_id=%s&attrs_per_key=%d&numb_of_keys=%d&email=%s&reset=%t",
customerID,
attrsPerKey,
numberOfKeys,
userEmail,
reset,
))
req := httptest.NewRequest(http.MethodPost, "/signup", body)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
rec := httptest.NewRecorder()
r.Router.ServeHTTP(rec, req)
var resp entities.SignupResetInterface
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
return nil, rec.Code, err
}
return &resp, rec.Code, nil
}
func (r *TestRouter) SetNKode(
customerID string,
selection []int,
sessionID string,
) ([]int, int, error) {
data := models.SetNKodePost{
CustomerId: customerID,
KeySelection: selection,
SessionId: sessionID,
}
body, err := json.Marshal(data)
if err != nil {
return nil, 0, err
}
req := httptest.NewRequest(http.MethodPost, "/set-nkode", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
rec := httptest.NewRecorder()
r.Router.ServeHTTP(rec, req)
var resp struct {
UserInterface []int `json:"user_interface"`
}
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
return nil, rec.Code, err
}
return resp.UserInterface, rec.Code, nil
}
func (r *TestRouter) ConfirmNKode(
customerID string,
selection entities.KeySelection,
sessionID string,
) (int, error) {
data := models.ConfirmNKodePost{
CustomerId: customerID,
KeySelection: selection,
SessionId: sessionID,
}
body, err := json.Marshal(data)
if err != nil {
return 0, err
}
req := httptest.NewRequest(http.MethodPost, "/confirm-nkode", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
rec := httptest.NewRecorder()
r.Router.ServeHTTP(rec, req)
return rec.Code, nil
}
func (r *TestRouter) GetLoginInterface(
userEmail string,
customerID string,
) (entities.LoginInterface, int, error) {
body := bytes.NewBufferString(fmt.Sprintf(
"email=%s&customer_id=%s",
userEmail,
customerID,
))
req := httptest.NewRequest(http.MethodPost, "/get-login-interface", body)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
rec := httptest.NewRecorder()
r.Router.ServeHTTP(rec, req)
var resp entities.LoginInterface
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
return entities.LoginInterface{}, rec.Code, err
}
return resp, rec.Code, nil
}
func (r *TestRouter) Login(
customerID string,
userEmail string,
selection []int,
) (security.AuthenticationTokens, int, error) {
data := models.LoginPost{
CustomerId: customerID,
UserEmail: userEmail,
KeySelection: selection,
}
body, err := json.Marshal(data)
if err != nil {
return security.AuthenticationTokens{}, 0, err
}
req := httptest.NewRequest(http.MethodPost, "/login", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
rec := httptest.NewRecorder()
r.Router.ServeHTTP(rec, req)
var resp security.AuthenticationTokens
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
return security.AuthenticationTokens{}, rec.Code, err
}
return resp, rec.Code, nil
}
func (r *TestRouter) RenewAttributes(
customerID string,
) (int, error) {
data := models.RenewAttributesPost{
CustomerId: customerID,
}
body, err := json.Marshal(data)
if err != nil {
return 0, err
}
req := httptest.NewRequest(http.MethodPost, "/renew-attributes", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
rec := httptest.NewRecorder()
r.Router.ServeHTTP(rec, req)
return rec.Code, nil
}