396 lines
9.7 KiB
Go
396 lines
9.7 KiB
Go
package handler
|
|
|
|
import (
|
|
"errors"
|
|
"git.infra.nkode.tech/dkelly/nkode-core/api"
|
|
"git.infra.nkode.tech/dkelly/nkode-core/config"
|
|
"git.infra.nkode.tech/dkelly/nkode-core/entities"
|
|
"git.infra.nkode.tech/dkelly/nkode-core/models"
|
|
"git.infra.nkode.tech/dkelly/nkode-core/security"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
"log"
|
|
"strings"
|
|
)
|
|
|
|
type NkodeHandler struct {
|
|
API api.NKodeAPI
|
|
Logger *log.Logger
|
|
}
|
|
|
|
const (
|
|
malformedCustomerId = "malformed customer id"
|
|
malformedUserEmail = "malformed user email"
|
|
malformedSessionId = "malformed session id"
|
|
invalidKeypadDimensions = "invalid keypad dimensions"
|
|
)
|
|
|
|
func (h *NkodeHandler) RegisterRoutes(r *gin.Engine) {
|
|
r.Group("/v1/nkode")
|
|
{
|
|
r.POST("/create-new-customer", h.CreateNewCustomerHandler)
|
|
r.POST("/signup", h.SignupHandler)
|
|
r.POST("/set-nkode", h.SetNKodeHandler)
|
|
r.POST("/confirm-nkode", h.ConfirmNKodeHandler)
|
|
r.POST("/get-login-interface", h.GetLoginInterfaceHandler)
|
|
r.POST("/login", h.LoginHandler)
|
|
r.POST("/renew-attributes", h.RenewAttributesHandler)
|
|
r.POST("/random-svg-interface", h.RandomSvgInterfaceHandler)
|
|
r.POST("/refresh-token", h.RefreshTokenHandler)
|
|
r.POST("/forgot-nkode", h.ForgotNKodeHandler)
|
|
r.POST("/signout", h.SignoutHandler)
|
|
r.POST("/reset", h.ResetHandler)
|
|
}
|
|
}
|
|
|
|
func (h *NkodeHandler) CreateNewCustomerHandler(c *gin.Context) {
|
|
var newCustomerPost entities.NKodePolicy
|
|
if err := c.ShouldBind(&newCustomerPost); err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
|
|
customerId, err := h.API.CreateNewCustomer(newCustomerPost)
|
|
if err != nil {
|
|
c.String(500, "Internal Server Error")
|
|
return
|
|
}
|
|
h.Logger.Println("create new customer")
|
|
c.JSON(200, gin.H{"customer_id": entities.CustomerIdToString(*customerId)})
|
|
}
|
|
|
|
func (h *NkodeHandler) SignupHandler(c *gin.Context) {
|
|
h.Logger.Println("generate signup reset interface")
|
|
var postBody models.SignupPostBody
|
|
if err := c.ShouldBind(&postBody); err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
kp := entities.KeypadDimension{
|
|
AttrsPerKey: postBody.AttrsPerKey,
|
|
NumbOfKeys: postBody.NumbOfKeys,
|
|
}
|
|
|
|
if err := kp.IsValidKeypadDimension(); err != nil {
|
|
c.String(400, invalidKeypadDimensions)
|
|
return
|
|
}
|
|
|
|
customerId, err := uuid.Parse(postBody.CustomerId)
|
|
if err != nil {
|
|
c.String(400, malformedCustomerId)
|
|
return
|
|
}
|
|
|
|
userEmail, err := entities.ParseEmail(postBody.UserEmail)
|
|
if err != nil {
|
|
c.String(400, malformedUserEmail)
|
|
return
|
|
}
|
|
|
|
resp, err := h.API.GenerateSignupResetInterface(userEmail, entities.CustomerId(customerId), kp, false)
|
|
if err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
|
|
c.JSON(200, resp)
|
|
}
|
|
|
|
func (h *NkodeHandler) SetNKodeHandler(c *gin.Context) {
|
|
h.Logger.Println("set nkode")
|
|
var postBody models.SetNKodePost
|
|
if err := c.ShouldBindJSON(&postBody); err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
customerId, err := uuid.Parse(postBody.CustomerId)
|
|
if err != nil {
|
|
c.String(400, malformedCustomerId)
|
|
return
|
|
}
|
|
sessionId, err := uuid.Parse(postBody.SessionId)
|
|
if err != nil {
|
|
c.String(400, malformedSessionId)
|
|
return
|
|
}
|
|
|
|
confirmInterface, err := h.API.SetNKode(entities.CustomerId(customerId), entities.SessionId(sessionId), postBody.KeySelection)
|
|
if err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
resp := models.SetNKodeResp{UserInterface: confirmInterface}
|
|
c.JSON(200, resp)
|
|
}
|
|
|
|
func (h *NkodeHandler) ConfirmNKodeHandler(c *gin.Context) {
|
|
h.Logger.Println("confirm nkode")
|
|
var postBody models.ConfirmNKodePost
|
|
if err := c.ShouldBindJSON(&postBody); err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
customerId, err := uuid.Parse(postBody.CustomerId)
|
|
if err != nil {
|
|
c.String(400, malformedCustomerId)
|
|
return
|
|
}
|
|
sessionId, err := uuid.Parse(postBody.SessionId)
|
|
if err != nil {
|
|
c.String(400, malformedSessionId)
|
|
return
|
|
}
|
|
if err := h.API.ConfirmNKode(entities.CustomerId(customerId), entities.SessionId(sessionId), postBody.KeySelection); err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
c.Status(200)
|
|
}
|
|
|
|
func (h *NkodeHandler) GetLoginInterfaceHandler(c *gin.Context) {
|
|
h.Logger.Println("get login interface")
|
|
var loginInterfacePost models.LoginInterfacePost
|
|
if err := c.ShouldBind(&loginInterfacePost); err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
|
|
customerId, err := uuid.Parse(loginInterfacePost.CustomerId)
|
|
if err != nil {
|
|
c.String(400, malformedCustomerId)
|
|
return
|
|
}
|
|
|
|
userEmail, err := entities.ParseEmail(loginInterfacePost.UserEmail)
|
|
if err != nil {
|
|
c.String(400, malformedUserEmail)
|
|
return
|
|
}
|
|
postBody, err := h.API.GetLoginInterface(userEmail, entities.CustomerId(customerId))
|
|
if err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
c.JSON(200, postBody)
|
|
}
|
|
|
|
func (h *NkodeHandler) LoginHandler(c *gin.Context) {
|
|
h.Logger.Println("login")
|
|
|
|
var loginPost models.LoginPost
|
|
if err := c.ShouldBindJSON(&loginPost); err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
customerId, err := uuid.Parse(loginPost.CustomerId)
|
|
if err != nil {
|
|
c.String(400, malformedCustomerId)
|
|
return
|
|
}
|
|
|
|
userEmail, err := entities.ParseEmail(loginPost.UserEmail)
|
|
if err != nil {
|
|
c.String(400, malformedUserEmail)
|
|
return
|
|
}
|
|
jwtToken, err := h.API.Login(entities.CustomerId(customerId), userEmail, loginPost.KeySelection)
|
|
if err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
c.JSON(200, jwtToken)
|
|
}
|
|
|
|
func (h *NkodeHandler) RenewAttributesHandler(c *gin.Context) {
|
|
h.Logger.Println("renew attributes")
|
|
|
|
var renewAttributesPost models.RenewAttributesPost
|
|
if err := c.ShouldBind(&renewAttributesPost); err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
|
|
customerId, err := uuid.Parse(renewAttributesPost.CustomerId)
|
|
if err != nil {
|
|
c.String(400, malformedCustomerId)
|
|
return
|
|
}
|
|
|
|
if err := h.API.RenewAttributes(entities.CustomerId(customerId)); err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
c.Status(200)
|
|
}
|
|
|
|
func (h *NkodeHandler) RandomSvgInterfaceHandler(c *gin.Context) {
|
|
h.Logger.Println("random svg interface")
|
|
svgs, err := h.API.RandomSvgInterface()
|
|
if err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
resp := models.RandomSvgInterfaceResp{Svgs: svgs}
|
|
c.JSON(200, resp)
|
|
}
|
|
|
|
func (h *NkodeHandler) RefreshTokenHandler(c *gin.Context) {
|
|
h.Logger.Println("refresh token")
|
|
refreshToken, err := getBearerToken(c)
|
|
if err != nil {
|
|
c.String(403, "forbidden")
|
|
return
|
|
}
|
|
refreshClaims, err := security.ParseRegisteredClaimToken(refreshToken)
|
|
customerId, err := uuid.Parse(refreshClaims.Issuer)
|
|
if err != nil {
|
|
c.String(400, malformedCustomerId)
|
|
return
|
|
}
|
|
userEmail, err := entities.ParseEmail(refreshClaims.Subject)
|
|
if err != nil {
|
|
c.String(400, malformedUserEmail)
|
|
return
|
|
}
|
|
accessToken, err := h.API.RefreshToken(userEmail, entities.CustomerId(customerId), refreshToken)
|
|
if err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
c.JSON(200, gin.H{"access_token": accessToken})
|
|
}
|
|
|
|
func (h *NkodeHandler) ForgotNKodeHandler(c *gin.Context) {
|
|
h.Logger.Println("forgot nkode")
|
|
var forgotNKodePost models.ForgotNKodePost
|
|
if err := c.ShouldBind(&forgotNKodePost); err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
customerId, err := uuid.Parse(forgotNKodePost.CustomerId)
|
|
if err != nil {
|
|
c.String(400, malformedCustomerId)
|
|
return
|
|
}
|
|
userEmail, err := entities.ParseEmail(forgotNKodePost.UserEmail)
|
|
if err != nil {
|
|
c.String(400, malformedUserEmail)
|
|
return
|
|
}
|
|
|
|
if err := h.API.ForgotNKode(userEmail, entities.CustomerId(customerId)); err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
c.Status(200)
|
|
}
|
|
|
|
func (h *NkodeHandler) SignoutHandler(c *gin.Context) {
|
|
h.Logger.Println("signout")
|
|
token, err := getBearerToken(c)
|
|
if err != nil {
|
|
c.String(403, "forbidden")
|
|
return
|
|
}
|
|
accessClaims, err := security.ParseRegisteredClaimToken(token)
|
|
if err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
customerId, err := uuid.Parse(accessClaims.Issuer)
|
|
if err != nil {
|
|
c.String(400, malformedCustomerId)
|
|
return
|
|
}
|
|
userEmail, err := entities.ParseEmail(accessClaims.Subject)
|
|
if err != nil {
|
|
c.String(400, malformedUserEmail)
|
|
return
|
|
}
|
|
if err = h.API.Signout(userEmail, entities.CustomerId(customerId)); err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
c.Status(200)
|
|
}
|
|
|
|
func (h *NkodeHandler) ResetHandler(c *gin.Context) {
|
|
h.Logger.Println("reset")
|
|
|
|
token, err := getBearerToken(c)
|
|
if err != nil {
|
|
c.String(403, "forbidden")
|
|
return
|
|
}
|
|
resetClaims, err := security.ParseRestNKodeToken(token)
|
|
if err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
var postBody models.SignupPostBody
|
|
if err = c.ShouldBind(&postBody); err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
customerId, err := uuid.Parse(postBody.CustomerId)
|
|
if err != nil {
|
|
c.String(400, malformedCustomerId)
|
|
return
|
|
}
|
|
userEmail, err := entities.ParseEmail(postBody.UserEmail)
|
|
if err != nil {
|
|
c.String(400, malformedUserEmail)
|
|
return
|
|
}
|
|
if postBody.UserEmail != resetClaims.Subject ||
|
|
postBody.CustomerId != resetClaims.Issuer {
|
|
c.String(403, "forbidden")
|
|
return
|
|
}
|
|
|
|
kp := entities.KeypadDimension{
|
|
AttrsPerKey: postBody.AttrsPerKey,
|
|
NumbOfKeys: postBody.NumbOfKeys,
|
|
}
|
|
|
|
if err := kp.IsValidKeypadDimension(); err != nil {
|
|
c.String(400, invalidKeypadDimensions)
|
|
return
|
|
}
|
|
resp, err := h.API.GenerateSignupResetInterface(userEmail, entities.CustomerId(customerId), kp, true)
|
|
if err != nil {
|
|
handleError(c, err)
|
|
return
|
|
}
|
|
|
|
c.JSON(200, resp)
|
|
|
|
}
|
|
|
|
func handleError(c *gin.Context, err error) {
|
|
log.Print("handling error: ", err)
|
|
statusCode, _ := config.HttpErrMap[err]
|
|
switch statusCode {
|
|
case 400:
|
|
c.String(400, err.Error())
|
|
case 403:
|
|
c.String(403, err.Error())
|
|
case 500:
|
|
c.String(500, "Internal Server Error")
|
|
default:
|
|
log.Print("unknown error: ", err)
|
|
c.String(500, "Internal Server Error")
|
|
}
|
|
}
|
|
|
|
func getBearerToken(c *gin.Context) (string, error) {
|
|
authHeader := c.GetHeader("Authorization")
|
|
// Check if the Authorization header is present and starts with "Bearer "
|
|
if authHeader == "" || !strings.HasPrefix(authHeader, "Bearer ") {
|
|
return "", errors.New("forbidden")
|
|
}
|
|
token := strings.TrimPrefix(authHeader, "Bearer ")
|
|
return token, nil
|
|
}
|