implement and test forget and reset nkode
This commit is contained in:
@@ -258,7 +258,7 @@ func (n *NKodeAPI) ForgotNKode(userEmail entities.UserEmail, customerId entities
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
nkodeResetJwt, err := security.ResetNKodeToken(string(userEmail), uuid.UUID(customerId))
|
nkodeResetJwt, err := security.ResetNKodeToken(string(userEmail), uuid.UUID(customerId).String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,11 +39,13 @@ func (h *NkodeHandler) RegisterRoutes(r *gin.Engine) {
|
|||||||
r.POST("/refresh-token", h.RefreshTokenHandler)
|
r.POST("/refresh-token", h.RefreshTokenHandler)
|
||||||
r.POST("/forgot-nkode", h.ForgotNKodeHandler)
|
r.POST("/forgot-nkode", h.ForgotNKodeHandler)
|
||||||
r.POST("/signout", h.SignoutHandler)
|
r.POST("/signout", h.SignoutHandler)
|
||||||
r.POST("/reset", h.ResetHandler)
|
r.POST("/reset-nkode", h.ResetHandler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *NkodeHandler) CreateNewCustomerHandler(c *gin.Context) {
|
func (h *NkodeHandler) CreateNewCustomerHandler(c *gin.Context) {
|
||||||
|
h.Logger.Println("create new customer")
|
||||||
|
|
||||||
var newCustomerPost entities.NKodePolicy
|
var newCustomerPost entities.NKodePolicy
|
||||||
if err := c.ShouldBind(&newCustomerPost); err != nil {
|
if err := c.ShouldBind(&newCustomerPost); err != nil {
|
||||||
handleError(c, err)
|
handleError(c, err)
|
||||||
@@ -217,7 +219,7 @@ func (h *NkodeHandler) RenewAttributesHandler(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.API.RenewAttributes(entities.CustomerId(customerId)); err != nil {
|
if err = h.API.RenewAttributes(entities.CustomerId(customerId)); err != nil {
|
||||||
handleError(c, err)
|
handleError(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNkodeAPI(t *testing.T) {
|
func TestNKodeAPI(t *testing.T) {
|
||||||
tr := NewTestRouter()
|
tr := NewTestRouter()
|
||||||
tr.Start()
|
tr.Start()
|
||||||
defer func(tr *TestRouter) {
|
defer func(tr *TestRouter) {
|
||||||
@@ -34,10 +34,9 @@ func TestNkodeAPI(t *testing.T) {
|
|||||||
attrPerKey := 9
|
attrPerKey := 9
|
||||||
numKeys := 6
|
numKeys := 6
|
||||||
userEmail := "test_username" + security.GenerateRandomString(12) + "@example.com"
|
userEmail := "test_username" + security.GenerateRandomString(12) + "@example.com"
|
||||||
reset := false
|
|
||||||
|
|
||||||
// *** Signup ***
|
// *** Signup ***
|
||||||
resp, status, err := tr.Signup(customerID, attrPerKey, numKeys, userEmail, reset)
|
resp, status, err := tr.Signup(customerID, attrPerKey, numKeys, userEmail)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 200, status)
|
assert.Equal(t, 200, status)
|
||||||
|
|
||||||
@@ -82,7 +81,54 @@ func TestNkodeAPI(t *testing.T) {
|
|||||||
assert.NotEmpty(t, tokens.RefreshToken)
|
assert.NotEmpty(t, tokens.RefreshToken)
|
||||||
|
|
||||||
// *** Renew Attributes ***
|
// *** Renew Attributes ***
|
||||||
|
status, err = tr.RenewAttributes(customerID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 200, status)
|
||||||
|
loginInterface, status, err = tr.GetLoginInterface(userEmail, customerID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
loginKeySelection, err = entities.SelectKeyByAttrIdx(loginInterface.UserIdxInterface, userPasscode, kp)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
tokens, status, err = tr.Login(customerID, userEmail, loginKeySelection)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// *** Test Forgot nKode ***
|
||||||
|
status, err = tr.ForgotNKode(customerID, userEmail)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 200, status)
|
||||||
|
|
||||||
|
// *** Test Reset nKode ***
|
||||||
|
nkodeResetJwt, err := security.ResetNKodeToken(userEmail, customerID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
resetResp, status, err := tr.Reset(customerID, attrPerKey, numKeys, userEmail, nkodeResetJwt)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 200, status)
|
||||||
|
assert.NotEmpty(t, resetResp.SessionId)
|
||||||
|
userPasscode = resetResp.UserIdxInterface[:passcodeLen]
|
||||||
|
setKeySelection, err = entities.SelectKeyByAttrIdx(resetResp.UserIdxInterface, userPasscode, kpSet)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
confirmInterface, status, err = tr.SetNKode(customerID, setKeySelection, resetResp.SessionId)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 200, status)
|
||||||
|
confirmKeySelection, err = entities.SelectKeyByAttrIdx(confirmInterface, userPasscode, kpSet)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
status, err = tr.ConfirmNKode(customerID, confirmKeySelection, resetResp.SessionId)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 200, status)
|
||||||
|
loginInterface, status, err = tr.GetLoginInterface(userEmail, customerID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, 200, status)
|
||||||
|
loginKeySelection, err = entities.SelectKeyByAttrIdx(loginInterface.UserIdxInterface, userPasscode, kp)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
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)
|
||||||
|
|
||||||
|
// *** Test Reset nKode with invalid token ***
|
||||||
|
_, status, err = tr.Reset(customerID, attrPerKey, numKeys, userEmail, "invalid token")
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Equal(t, 403, status)
|
||||||
}
|
}
|
||||||
|
|
||||||
type TestRouter struct {
|
type TestRouter struct {
|
||||||
@@ -102,8 +148,8 @@ func NewTestRouter() *TestRouter {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
sesClient := email.NewSESClient()
|
emailClient := email.TestEmailClient{}
|
||||||
emailQueue := email.NewEmailQueue(email.EmailQueueBufferSize, email.MaxEmailsPerSecond, &sesClient)
|
emailQueue := email.NewEmailQueue(email.EmailQueueBufferSize, email.MaxEmailsPerSecond, &emailClient)
|
||||||
nkodeAPI := api.NewNKodeAPI(repo, emailQueue)
|
nkodeAPI := api.NewNKodeAPI(repo, emailQueue)
|
||||||
h := NkodeHandler{
|
h := NkodeHandler{
|
||||||
API: nkodeAPI,
|
API: nkodeAPI,
|
||||||
@@ -157,15 +203,13 @@ func (r *TestRouter) Signup(
|
|||||||
attrsPerKey int,
|
attrsPerKey int,
|
||||||
numberOfKeys int,
|
numberOfKeys int,
|
||||||
userEmail string,
|
userEmail string,
|
||||||
reset bool,
|
|
||||||
) (*entities.SignupResetInterface, int, error) {
|
) (*entities.SignupResetInterface, int, error) {
|
||||||
body := bytes.NewBufferString(fmt.Sprintf(
|
body := bytes.NewBufferString(fmt.Sprintf(
|
||||||
"customer_id=%s&attrs_per_key=%d&numb_of_keys=%d&email=%s&reset=%t",
|
"customer_id=%s&attrs_per_key=%d&numb_of_keys=%d&email=%s",
|
||||||
customerID,
|
customerID,
|
||||||
attrsPerKey,
|
attrsPerKey,
|
||||||
numberOfKeys,
|
numberOfKeys,
|
||||||
userEmail,
|
userEmail,
|
||||||
reset,
|
|
||||||
))
|
))
|
||||||
req := httptest.NewRequest(http.MethodPost, "/signup", body)
|
req := httptest.NewRequest(http.MethodPost, "/signup", body)
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
@@ -290,3 +334,48 @@ func (r *TestRouter) RenewAttributes(
|
|||||||
r.Router.ServeHTTP(rec, req)
|
r.Router.ServeHTTP(rec, req)
|
||||||
return rec.Code, nil
|
return rec.Code, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *TestRouter) ForgotNKode(
|
||||||
|
customerID string,
|
||||||
|
userEmail string,
|
||||||
|
) (int, error) {
|
||||||
|
data := models.ForgotNKodePost{
|
||||||
|
CustomerId: customerID,
|
||||||
|
UserEmail: userEmail,
|
||||||
|
}
|
||||||
|
body, err := json.Marshal(data)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
req := httptest.NewRequest(http.MethodPost, "/forgot-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) Reset(
|
||||||
|
customerID string,
|
||||||
|
attrsPerKey int,
|
||||||
|
numberOfKeys int,
|
||||||
|
userEmail string,
|
||||||
|
resetAuthToken string,
|
||||||
|
) (*entities.SignupResetInterface, int, error) {
|
||||||
|
body := bytes.NewBufferString(fmt.Sprintf(
|
||||||
|
"customer_id=%s&attrs_per_key=%d&numb_of_keys=%d&email=%s",
|
||||||
|
customerID,
|
||||||
|
attrsPerKey,
|
||||||
|
numberOfKeys,
|
||||||
|
userEmail,
|
||||||
|
))
|
||||||
|
req := httptest.NewRequest(http.MethodPost, "/reset-nkode", body)
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
req.Header.Set("Authorization", "Bearer "+resetAuthToken)
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -40,9 +40,9 @@ type LoginInterfacePost struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type LoginPost struct {
|
type LoginPost struct {
|
||||||
CustomerId string `json:"customer_id" binding:"required"`
|
CustomerId string `form:"customer_id" binding:"required"`
|
||||||
UserEmail string `json:"email" binding:"required"`
|
UserEmail string `form:"email" binding:"required"`
|
||||||
KeySelection entities.KeySelection `json:"key_selection" binding:"required"`
|
KeySelection entities.KeySelection `form:"key_selection" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RenewAttributesPost struct {
|
type RenewAttributesPost struct {
|
||||||
|
|||||||
@@ -115,12 +115,12 @@ func ClaimExpired(claims jwt.RegisteredClaims) error {
|
|||||||
return config.ErrClaimExpOrNil
|
return config.ErrClaimExpOrNil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ResetNKodeToken(userEmail string, customerId uuid.UUID) (string, error) {
|
func ResetNKodeToken(userEmail string, customerId string) (string, error) {
|
||||||
resetClaims := ResetNKodeClaims{
|
resetClaims := ResetNKodeClaims{
|
||||||
true,
|
true,
|
||||||
jwt.RegisteredClaims{
|
jwt.RegisteredClaims{
|
||||||
Subject: userEmail,
|
Subject: userEmail,
|
||||||
Issuer: customerId.String(),
|
Issuer: customerId,
|
||||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(resetNKodeTokenExp)),
|
ExpiresAt: jwt.NewNumericDate(time.Now().Add(resetNKodeTokenExp)),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func TestJwtClaims(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, refreshToken.Subject, email)
|
assert.Equal(t, refreshToken.Subject, email)
|
||||||
assert.NoError(t, ClaimExpired(*refreshToken))
|
assert.NoError(t, ClaimExpired(*refreshToken))
|
||||||
resetNKode, err := ResetNKodeToken(email, customerId)
|
resetNKode, err := ResetNKodeToken(email, customerId.String())
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
resetToken, err := ParseRestNKodeToken(resetNKode)
|
resetToken, err := ParseRestNKodeToken(resetNKode)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|||||||
@@ -48,3 +48,9 @@ type User struct {
|
|||||||
LastLogin interface{}
|
LastLogin interface{}
|
||||||
CreatedAt sql.NullString
|
CreatedAt sql.NullString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserPermission struct {
|
||||||
|
ID int64
|
||||||
|
UserID string
|
||||||
|
Permission string
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user