2023-03-16 12:21:41 +07:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql"
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
)
|
|
|
|
|
|
|
|
type renewAccessRequest struct {
|
|
|
|
RefreshToken string `json:"refresh_token" binding:"required"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type renewAccessResponse struct {
|
|
|
|
AccesToken string `json:"access_token"`
|
|
|
|
AccessTokenExpiresAt time.Time `json:"access_token_expires_at"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (server *Server) renewAccessToken(ctx *gin.Context) {
|
|
|
|
var req renewAccessRequest
|
|
|
|
if err := ctx.ShouldBindJSON(&req); err != nil {
|
2023-03-22 12:06:09 +07:00
|
|
|
ctx.JSON(http.StatusBadRequest, errorResponse(err, ""))
|
2023-03-16 12:21:41 +07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
refreshPayload, err := server.tokenMaker.VerifyToken(req.RefreshToken)
|
|
|
|
if err != nil {
|
2023-03-22 12:06:09 +07:00
|
|
|
ctx.JSON(http.StatusUnauthorized, errorResponse(err, ""))
|
2023-03-16 12:21:41 +07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
session, err := server.store.GetSession(ctx, refreshPayload.ID)
|
|
|
|
if err != nil {
|
|
|
|
if err == sql.ErrNoRows {
|
2023-03-22 12:06:09 +07:00
|
|
|
ctx.JSON(http.StatusNotFound, errorResponse(err, ""))
|
2023-03-16 12:21:41 +07:00
|
|
|
return
|
|
|
|
}
|
2023-03-22 12:06:09 +07:00
|
|
|
ctx.JSON(http.StatusInternalServerError, errorResponse(err, ""))
|
2023-03-16 12:21:41 +07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if session.IsBlocked {
|
|
|
|
err := fmt.Errorf("blocked session")
|
2023-03-22 12:06:09 +07:00
|
|
|
ctx.JSON(http.StatusUnauthorized, errorResponse(err, ""))
|
2023-03-16 12:21:41 +07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if session.Email != refreshPayload.Email {
|
|
|
|
err := fmt.Errorf("incorrect session user")
|
2023-03-22 12:06:09 +07:00
|
|
|
ctx.JSON(http.StatusUnauthorized, errorResponse(err, ""))
|
2023-03-16 12:21:41 +07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if session.RefreshToken != req.RefreshToken {
|
|
|
|
err := fmt.Errorf("mismatched session token")
|
2023-03-22 12:06:09 +07:00
|
|
|
ctx.JSON(http.StatusUnauthorized, errorResponse(err, ""))
|
2023-03-16 12:21:41 +07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if time.Now().After(refreshPayload.ExpiredAt) {
|
2023-09-08 12:37:39 +07:00
|
|
|
err := fmt.Errorf("Expired session")
|
2023-03-22 12:06:09 +07:00
|
|
|
ctx.JSON(http.StatusUnauthorized, errorResponse(err, ""))
|
2023-03-16 12:21:41 +07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
user, err := server.store.GetUserByEmail(ctx, refreshPayload.Email)
|
|
|
|
if err != nil {
|
|
|
|
if err == sql.ErrNoRows {
|
2023-03-22 12:06:09 +07:00
|
|
|
ctx.JSON(http.StatusNotFound, errorResponse(err, ""))
|
2023-03-16 12:21:41 +07:00
|
|
|
return
|
|
|
|
}
|
2023-03-22 12:06:09 +07:00
|
|
|
ctx.JSON(http.StatusInternalServerError, errorResponse(err, ""))
|
2023-03-16 12:21:41 +07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
merchant, err := server.store.GetMerchantByUserId(ctx, user.ID)
|
|
|
|
if err != nil {
|
2023-03-22 12:06:09 +07:00
|
|
|
ctx.JSON(http.StatusInternalServerError, errorResponse(err, ""))
|
2023-03-16 12:21:41 +07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
accessToken, accessPayload, err := server.tokenMaker.CreateToken(
|
|
|
|
refreshPayload.Email,
|
|
|
|
merchant.ID.String(),
|
|
|
|
server.config.TokenDuration,
|
|
|
|
)
|
|
|
|
|
|
|
|
if err != nil {
|
2023-03-22 12:06:09 +07:00
|
|
|
ctx.JSON(http.StatusInternalServerError, errorResponse(err, ""))
|
2023-03-16 12:21:41 +07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
res := renewAccessResponse{
|
|
|
|
AccesToken: accessToken,
|
|
|
|
AccessTokenExpiresAt: accessPayload.ExpiredAt,
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.JSON(http.StatusOK, res)
|
|
|
|
}
|