add logging events
This commit is contained in:
parent
9ee582a12e
commit
201b8b4207
@ -10,10 +10,10 @@ import (
|
|||||||
"codeword/internal/server/grpc"
|
"codeword/internal/server/grpc"
|
||||||
httpserver "codeword/internal/server/http"
|
httpserver "codeword/internal/server/http"
|
||||||
"codeword/internal/services"
|
"codeword/internal/services"
|
||||||
|
"codeword/internal/utils/middleware"
|
||||||
"codeword/internal/worker/purge_worker"
|
"codeword/internal/worker/purge_worker"
|
||||||
"codeword/internal/worker/recovery_worker"
|
"codeword/internal/worker/recovery_worker"
|
||||||
"codeword/pkg/closer"
|
"codeword/pkg/closer"
|
||||||
"codeword/utils"
|
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/themakers/hlog"
|
"github.com/themakers/hlog"
|
||||||
@ -126,11 +126,15 @@ func Run(ctx context.Context, cfg initialize.Config, logger *zap.Logger, build B
|
|||||||
DiscountClient: discountRpcClient,
|
DiscountClient: discountRpcClient,
|
||||||
})
|
})
|
||||||
|
|
||||||
jwtUtil := utils.NewJWT(&cfg)
|
jwtUtil := middleware.NewJWT(&cfg)
|
||||||
authMiddleware := utils.NewAuthenticator(jwtUtil)
|
|
||||||
|
|
||||||
recoveryController := recovery.NewRecoveryController(logger, recoveryService, cfg.DefaultRedirectionURL)
|
recoveryController := recovery.NewRecoveryController(recovery.Deps{
|
||||||
promoCodeController := promocode.NewPromoCodeController(promocode.Deps{Logger: logger, PromoCodeService: promoService, AuthMiddleware: authMiddleware})
|
Logger: logger,
|
||||||
|
Service: recoveryService,
|
||||||
|
DefaultURL: cfg.DefaultRedirectionURL,
|
||||||
|
RecoveryURL: cfg.RecoveryUrl,
|
||||||
|
})
|
||||||
|
promoCodeController := promocode.NewPromoCodeController(promocode.Deps{Logger: logger, PromoCodeService: promoService})
|
||||||
controllerRpc := rpc_controllers.InitRpcControllers(promoService)
|
controllerRpc := rpc_controllers.InitRpcControllers(promoService)
|
||||||
|
|
||||||
grpcServer, err := grpc.NewGRPC(logger)
|
grpcServer, err := grpc.NewGRPC(logger)
|
||||||
@ -159,6 +163,7 @@ func Run(ctx context.Context, cfg initialize.Config, logger *zap.Logger, build B
|
|||||||
Logger: logger,
|
Logger: logger,
|
||||||
Controllers: []httpserver.Controller{recoveryController, promoCodeController},
|
Controllers: []httpserver.Controller{recoveryController, promoCodeController},
|
||||||
Hlogger: loggerHlog,
|
Hlogger: loggerHlog,
|
||||||
|
JWT: jwtUtil,
|
||||||
})
|
})
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -4,33 +4,34 @@ import (
|
|||||||
"codeword/internal/models"
|
"codeword/internal/models"
|
||||||
"codeword/internal/repository"
|
"codeword/internal/repository"
|
||||||
"codeword/internal/services"
|
"codeword/internal/services"
|
||||||
|
"codeword/internal/utils/middleware"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Deps struct {
|
type Deps struct {
|
||||||
Logger *zap.Logger
|
Logger *zap.Logger
|
||||||
PromoCodeService *services.PromoCodeService
|
PromoCodeService *services.PromoCodeService
|
||||||
AuthMiddleware func(*fiber.Ctx) error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type PromoCodeController struct {
|
type PromoCodeController struct {
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
promoCodeService *services.PromoCodeService
|
promoCodeService *services.PromoCodeService
|
||||||
authMiddleware func(*fiber.Ctx) error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPromoCodeController(deps Deps) *PromoCodeController {
|
func NewPromoCodeController(deps Deps) *PromoCodeController {
|
||||||
return &PromoCodeController{
|
return &PromoCodeController{
|
||||||
logger: deps.Logger,
|
logger: deps.Logger,
|
||||||
promoCodeService: deps.PromoCodeService,
|
promoCodeService: deps.PromoCodeService,
|
||||||
authMiddleware: deps.AuthMiddleware,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PromoCodeController) CreatePromoCode(c *fiber.Ctx) error {
|
func (p *PromoCodeController) CreatePromoCode(c *fiber.Ctx) error {
|
||||||
|
userID := middleware.ExtractUserID(c)
|
||||||
|
hlogger := middleware.ExtractLogger(c)
|
||||||
var req models.PromoCode
|
var req models.PromoCode
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request payload"})
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request payload"})
|
||||||
@ -53,10 +54,52 @@ func (p *PromoCodeController) CreatePromoCode(c *fiber.Ctx) error {
|
|||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var keyType string
|
||||||
|
var ctxFactor float64
|
||||||
|
var keyTargetType string
|
||||||
|
var ctxTarget string
|
||||||
|
var ctxAmount int64
|
||||||
|
|
||||||
|
if createdPromoCode.Bonus.Privilege.PrivilegeID != "" && createdPromoCode.Bonus.Discount.Layer > 0 {
|
||||||
|
keyType = "privilege,discount"
|
||||||
|
keyTargetType = "privilege,service"
|
||||||
|
ctxTarget = fmt.Sprintf("%s,%s", createdPromoCode.Bonus.Privilege.PrivilegeID, createdPromoCode.Bonus.Discount.Target)
|
||||||
|
ctxAmount = int64(createdPromoCode.Bonus.Privilege.Amount)
|
||||||
|
ctxFactor = createdPromoCode.Bonus.Discount.Factor
|
||||||
|
} else if createdPromoCode.Bonus.Privilege.PrivilegeID != "" {
|
||||||
|
keyType = "privilege"
|
||||||
|
keyTargetType = "privilege"
|
||||||
|
ctxTarget = createdPromoCode.Bonus.Privilege.PrivilegeID
|
||||||
|
ctxAmount = int64(createdPromoCode.Bonus.Privilege.Amount)
|
||||||
|
} else if createdPromoCode.Bonus.Discount.Factor > 0 {
|
||||||
|
keyType = "discount"
|
||||||
|
keyTargetType = "service"
|
||||||
|
ctxFactor = createdPromoCode.Bonus.Discount.Factor
|
||||||
|
ctxTarget = createdPromoCode.Bonus.Discount.Target
|
||||||
|
}
|
||||||
|
|
||||||
|
hlogger.Emit(models.InfoPromocodeCreated{
|
||||||
|
CtxUserIP: c.IP(),
|
||||||
|
CtxUserPort: c.Port(),
|
||||||
|
KeyDomain: strings.Join(c.Subdomains(), "/"),
|
||||||
|
KeyPath: c.Path(),
|
||||||
|
CtxID: createdPromoCode.ID.String(),
|
||||||
|
CtxUserID: userID,
|
||||||
|
KeyType: keyType,
|
||||||
|
CtxFactor: ctxFactor,
|
||||||
|
KeyTargetType: keyTargetType,
|
||||||
|
CtxTarget: ctxTarget,
|
||||||
|
CtxAmount: ctxAmount,
|
||||||
|
CtxCode: createdPromoCode.Codeword,
|
||||||
|
})
|
||||||
|
|
||||||
return c.Status(fiber.StatusOK).JSON(createdPromoCode)
|
return c.Status(fiber.StatusOK).JSON(createdPromoCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PromoCodeController) EditPromoCode(c *fiber.Ctx) error {
|
func (p *PromoCodeController) EditPromoCode(c *fiber.Ctx) error {
|
||||||
|
userID := middleware.ExtractUserID(c)
|
||||||
|
hlogger := middleware.ExtractLogger(c)
|
||||||
|
|
||||||
var req models.ReqEditPromoCode
|
var req models.ReqEditPromoCode
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request payload"})
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request payload"})
|
||||||
@ -79,6 +122,45 @@ func (p *PromoCodeController) EditPromoCode(c *fiber.Ctx) error {
|
|||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var keyType string
|
||||||
|
var ctxFactor float64
|
||||||
|
var keyTargetType string
|
||||||
|
var ctxTarget string
|
||||||
|
var ctxAmount int64
|
||||||
|
|
||||||
|
if editedPromoCode.Bonus.Privilege.PrivilegeID != "" && editedPromoCode.Bonus.Discount.Layer > 0 {
|
||||||
|
keyType = "privilege,discount"
|
||||||
|
keyTargetType = "privilege,service"
|
||||||
|
ctxTarget = fmt.Sprintf("%s,%s", editedPromoCode.Bonus.Privilege.PrivilegeID, editedPromoCode.Bonus.Discount.Target)
|
||||||
|
ctxAmount = int64(editedPromoCode.Bonus.Privilege.Amount)
|
||||||
|
ctxFactor = editedPromoCode.Bonus.Discount.Factor
|
||||||
|
} else if editedPromoCode.Bonus.Privilege.PrivilegeID != "" {
|
||||||
|
keyType = "privilege"
|
||||||
|
keyTargetType = "privilege"
|
||||||
|
ctxTarget = editedPromoCode.Bonus.Privilege.PrivilegeID
|
||||||
|
ctxAmount = int64(editedPromoCode.Bonus.Privilege.Amount)
|
||||||
|
} else if editedPromoCode.Bonus.Discount.Factor > 0 {
|
||||||
|
keyType = "discount"
|
||||||
|
keyTargetType = "service"
|
||||||
|
ctxFactor = editedPromoCode.Bonus.Discount.Factor
|
||||||
|
ctxTarget = editedPromoCode.Bonus.Discount.Target
|
||||||
|
}
|
||||||
|
|
||||||
|
hlogger.Emit(models.InfoPromocodeUpdated{
|
||||||
|
CtxUserIP: c.IP(),
|
||||||
|
CtxUserPort: c.Port(),
|
||||||
|
KeyDomain: strings.Join(c.Subdomains(), "/"),
|
||||||
|
KeyPath: c.Path(),
|
||||||
|
CtxID: editedPromoCode.ID.String(),
|
||||||
|
CtxUserID: userID,
|
||||||
|
KeyType: keyType,
|
||||||
|
CtxFactor: ctxFactor,
|
||||||
|
KeyTargetType: keyTargetType,
|
||||||
|
CtxTarget: ctxTarget,
|
||||||
|
CtxAmount: ctxAmount,
|
||||||
|
CtxCode: editedPromoCode.Codeword,
|
||||||
|
})
|
||||||
|
|
||||||
return c.Status(fiber.StatusOK).JSON(editedPromoCode)
|
return c.Status(fiber.StatusOK).JSON(editedPromoCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,13 +183,8 @@ func (p *PromoCodeController) GetList(c *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *PromoCodeController) Activate(c *fiber.Ctx) error {
|
func (p *PromoCodeController) Activate(c *fiber.Ctx) error {
|
||||||
err := p.authMiddleware(c)
|
userID := middleware.ExtractUserID(c)
|
||||||
fmt.Println("SKER0", err)
|
hlogger := middleware.ExtractLogger(c)
|
||||||
if err != nil {
|
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err})
|
|
||||||
}
|
|
||||||
|
|
||||||
userID := c.Locals(models.AuthJWTDecodedUserIDKey).(string)
|
|
||||||
fmt.Println("SKER1", userID)
|
fmt.Println("SKER1", userID)
|
||||||
if userID == "" {
|
if userID == "" {
|
||||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "failed to get jwt payload"})
|
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "failed to get jwt payload"})
|
||||||
@ -123,7 +200,7 @@ func (p *PromoCodeController) Activate(c *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
fmt.Println("SKER2", req)
|
fmt.Println("SKER2", req)
|
||||||
|
|
||||||
greetings, err := p.promoCodeService.ActivatePromo(c.Context(), &req, userID)
|
promocode, err := p.promoCodeService.ActivatePromo(c.Context(), &req, userID)
|
||||||
fmt.Println("SKER3", err)
|
fmt.Println("SKER3", err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
p.logger.Error("Failed to activate promocode", zap.Error(err))
|
p.logger.Error("Failed to activate promocode", zap.Error(err))
|
||||||
@ -134,20 +211,58 @@ func (p *PromoCodeController) Activate(c *fiber.Ctx) error {
|
|||||||
case errors.Is(err, repository.ErrPromoCodeAlreadyActivated):
|
case errors.Is(err, repository.ErrPromoCodeAlreadyActivated):
|
||||||
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "PromoCode already activated"})
|
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "PromoCode already activated"})
|
||||||
case errors.Is(err, repository.ErrPromoCodeExpired):
|
case errors.Is(err, repository.ErrPromoCodeExpired):
|
||||||
|
hlogger.Emit(models.InfoPromocodeDeadlined{
|
||||||
|
CtxUserIP: c.IP(),
|
||||||
|
CtxUserPort: c.Port(),
|
||||||
|
KeyDomain: strings.Join(c.Subdomains(), "/"),
|
||||||
|
KeyPath: c.Path(),
|
||||||
|
CtxID: promocode.ID.String(),
|
||||||
|
})
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()})
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()})
|
||||||
case errors.Is(err, repository.ErrPromoCodeExhausted):
|
case errors.Is(err, repository.ErrPromoCodeExhausted):
|
||||||
|
hlogger.Emit(models.InfoPromocodeExhausted{
|
||||||
|
CtxUserIP: c.IP(),
|
||||||
|
CtxUserPort: c.Port(),
|
||||||
|
KeyDomain: strings.Join(c.Subdomains(), "/"),
|
||||||
|
KeyPath: c.Path(),
|
||||||
|
CtxID: promocode.ID.String(),
|
||||||
|
})
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "PromoCode exhausted"})
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "PromoCode exhausted"})
|
||||||
default:
|
default:
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Status(fiber.StatusOK).JSON(models.ActivateResp{Greetings: greetings})
|
if req.Codeword != "" {
|
||||||
|
hlogger.Emit(models.InfoPromocodeActivated{
|
||||||
|
CtxUserIP: c.IP(),
|
||||||
|
CtxUserPort: c.Port(),
|
||||||
|
KeyDomain: strings.Join(c.Subdomains(), "/"),
|
||||||
|
KeyPath: c.Path(),
|
||||||
|
CtxID: promocode.ID.String(),
|
||||||
|
CtxUserID: userID,
|
||||||
|
CtxCode: req.Codeword,
|
||||||
|
})
|
||||||
|
} else if req.FastLink != "" {
|
||||||
|
hlogger.Emit(models.InfoFastlinkActivated{
|
||||||
|
CtxUserIP: c.IP(),
|
||||||
|
CtxUserPort: c.Port(),
|
||||||
|
KeyDomain: strings.Join(c.Subdomains(), "/"),
|
||||||
|
KeyPath: c.Path(),
|
||||||
|
CtxID: promocode.ID.String(),
|
||||||
|
CtxUserID: userID,
|
||||||
|
CtxPromocodeID: req.FastLink,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Status(fiber.StatusOK).JSON(models.ActivateResp{Greetings: promocode.Greetings})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PromoCodeController) Delete(c *fiber.Ctx) error {
|
func (p *PromoCodeController) Delete(c *fiber.Ctx) error {
|
||||||
promoCodeID := c.Params("promocodeID")
|
userID := middleware.ExtractUserID(c)
|
||||||
|
hlogger := middleware.ExtractLogger(c)
|
||||||
|
|
||||||
|
promoCodeID := c.Params("promocodeID")
|
||||||
if promoCodeID == "" {
|
if promoCodeID == "" {
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "PromoCode ID is required"})
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "PromoCode ID is required"})
|
||||||
}
|
}
|
||||||
@ -163,10 +278,22 @@ func (p *PromoCodeController) Delete(c *fiber.Ctx) error {
|
|||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hlogger.Emit(models.InfoPromocodeDeleted{
|
||||||
|
CtxUserIP: c.IP(),
|
||||||
|
CtxUserPort: c.Port(),
|
||||||
|
KeyDomain: strings.Join(c.Subdomains(), "/"),
|
||||||
|
KeyPath: c.Path(),
|
||||||
|
CtxID: promoCodeID,
|
||||||
|
CtxUserID: userID,
|
||||||
|
})
|
||||||
|
|
||||||
return c.SendStatus(fiber.StatusOK)
|
return c.SendStatus(fiber.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PromoCodeController) CreateFastLink(c *fiber.Ctx) error {
|
func (p *PromoCodeController) CreateFastLink(c *fiber.Ctx) error {
|
||||||
|
userID := middleware.ExtractUserID(c)
|
||||||
|
hlogger := middleware.ExtractLogger(c)
|
||||||
|
|
||||||
var req struct {
|
var req struct {
|
||||||
PromoCodeID string `json:"id"`
|
PromoCodeID string `json:"id"`
|
||||||
}
|
}
|
||||||
@ -189,6 +316,16 @@ func (p *PromoCodeController) CreateFastLink(c *fiber.Ctx) error {
|
|||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hlogger.Emit(models.InfoFastlinkCreated{
|
||||||
|
CtxUserIP: c.IP(),
|
||||||
|
CtxUserPort: c.Port(),
|
||||||
|
KeyDomain: strings.Join(c.Subdomains(), "/"),
|
||||||
|
KeyPath: c.Path(),
|
||||||
|
CtxID: fastLink,
|
||||||
|
CtxPromocodeID: req.PromoCodeID,
|
||||||
|
CtxUserID: userID,
|
||||||
|
})
|
||||||
|
|
||||||
return c.Status(fiber.StatusCreated).JSON(fiber.Map{"fastlink": fastLink})
|
return c.Status(fiber.StatusCreated).JSON(fiber.Map{"fastlink": fastLink})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,25 +4,36 @@ import (
|
|||||||
"codeword/internal/models"
|
"codeword/internal/models"
|
||||||
"codeword/internal/repository"
|
"codeword/internal/repository"
|
||||||
"codeword/internal/services"
|
"codeword/internal/services"
|
||||||
|
"codeword/internal/utils/middleware"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RecoveryController struct {
|
type Deps struct {
|
||||||
logger *zap.Logger
|
Logger *zap.Logger
|
||||||
service *services.RecoveryService
|
Service *services.RecoveryService
|
||||||
defaultURL string
|
DefaultURL string
|
||||||
|
RecoveryURL string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRecoveryController(logger *zap.Logger, service *services.RecoveryService, defaultRedirectionURL string) *RecoveryController {
|
type RecoveryController struct {
|
||||||
|
logger *zap.Logger
|
||||||
|
service *services.RecoveryService
|
||||||
|
defaultURL string
|
||||||
|
recoveryURL string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRecoveryController(deps Deps) *RecoveryController {
|
||||||
return &RecoveryController{
|
return &RecoveryController{
|
||||||
logger: logger,
|
logger: deps.Logger,
|
||||||
service: service,
|
service: deps.Service,
|
||||||
defaultURL: defaultRedirectionURL,
|
defaultURL: deps.DefaultURL,
|
||||||
|
recoveryURL: deps.RecoveryURL,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,6 +56,7 @@ func (r *RecoveryController) HandlePingDB(c *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *RecoveryController) HandleRecoveryRequest(c *fiber.Ctx) error {
|
func (r *RecoveryController) HandleRecoveryRequest(c *fiber.Ctx) error {
|
||||||
|
hlogger := middleware.ExtractLogger(c)
|
||||||
var req models.RecoveryRequest
|
var req models.RecoveryRequest
|
||||||
if err := c.BodyParser(&req); err != nil {
|
if err := c.BodyParser(&req); err != nil {
|
||||||
r.logger.Error("Failed to parse recovery request", zap.Error(err))
|
r.logger.Error("Failed to parse recovery request", zap.Error(err))
|
||||||
@ -79,11 +91,11 @@ func (r *RecoveryController) HandleRecoveryRequest(c *fiber.Ctx) error {
|
|||||||
sign := base64.URLEncoding.EncodeToString(key)
|
sign := base64.URLEncoding.EncodeToString(key)
|
||||||
|
|
||||||
id, err := r.service.StoreRecoveryRecord(c.Context(), models.StoreRecDeps{
|
id, err := r.service.StoreRecoveryRecord(c.Context(), models.StoreRecDeps{
|
||||||
UserID: user.ID.Hex(),
|
UserID: user.ID.Hex(),
|
||||||
Email: user.Email,
|
Email: user.Email,
|
||||||
Key: sign,
|
Key: sign,
|
||||||
Url: signUrl,
|
Url: signUrl,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Error("Failed to store recovery record", zap.Error(err))
|
r.logger.Error("Failed to store recovery record", zap.Error(err))
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
|
||||||
@ -102,36 +114,48 @@ func (r *RecoveryController) HandleRecoveryRequest(c *fiber.Ctx) error {
|
|||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hlogger.Emit(models.InfoPasswordRestorationRequested{
|
||||||
|
CtxUserIP: c.IP(),
|
||||||
|
CtxUserPort: c.Port(),
|
||||||
|
KeyDomain: strings.Join(c.Subdomains(), "/"),
|
||||||
|
KeyPath: c.Path(),
|
||||||
|
CtxID: id,
|
||||||
|
CtxUserID: user.ID.Hex(),
|
||||||
|
CtxReturnURL: r.recoveryURL + signWithID,
|
||||||
|
CtxEmail: req.Email,
|
||||||
|
})
|
||||||
|
|
||||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{"message": "Recovery email sent successfully"})
|
return c.Status(fiber.StatusOK).JSON(fiber.Map{"message": "Recovery email sent successfully"})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RecoveryController) HandleRecoveryLink(c *fiber.Ctx) error {
|
func (r *RecoveryController) HandleRecoveryLink(c *fiber.Ctx) error {
|
||||||
|
hlogger := middleware.ExtractLogger(c)
|
||||||
sign := c.Params("sign")
|
sign := c.Params("sign")
|
||||||
|
|
||||||
record, err := r.service.GetRecoveryRecord(c.Context(), sign)
|
record, err := r.service.GetRecoveryRecord(c.Context(), sign)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Error("Recovery link expired", zap.String("signature", sign))
|
r.logger.Error("Recovery link expired", zap.String("signature", sign))
|
||||||
return c.Redirect("https://shub.pena.digital/recover/expired")
|
return c.Redirect("https://shub.pena.digital/recover/expired")
|
||||||
}
|
}
|
||||||
|
|
||||||
if time.Since(record.CreatedAt) > 15*time.Minute {
|
if time.Since(record.CreatedAt) > 15*time.Minute {
|
||||||
r.logger.Error("Recovery link expired", zap.String("signature", sign))
|
r.logger.Error("Recovery link expired", zap.String("signature", sign))
|
||||||
return c.Redirect(record.SignUrl+"/expired")
|
return c.Redirect(record.SignUrl + "/expired")
|
||||||
}
|
}
|
||||||
|
|
||||||
tokens, err := r.service.ExchangeForTokens(record.UserID, record.Sign)
|
tokens, err := r.service.ExchangeForTokens(record.UserID, record.Sign)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Error("Failed to exchange recovery link for tokens", zap.Error(err))
|
r.logger.Error("Failed to exchange recovery link for tokens", zap.Error(err))
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
|
||||||
}
|
}
|
||||||
c.Cookie(&fiber.Cookie{
|
c.Cookie(&fiber.Cookie{
|
||||||
Name: "refreshToken",
|
Name: "refreshToken",
|
||||||
Value: tokens["refreshToken"],
|
Value: tokens["refreshToken"],
|
||||||
Domain: ".pena.digital",
|
Domain: ".pena.digital",
|
||||||
Expires: time.Now().Add(30 * 24 * time.Hour),
|
Expires: time.Now().Add(30 * 24 * time.Hour),
|
||||||
Secure: true,
|
Secure: true,
|
||||||
HTTPOnly: true,
|
HTTPOnly: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
c.Cookie(&fiber.Cookie{
|
c.Cookie(&fiber.Cookie{
|
||||||
Name: "refreshToken",
|
Name: "refreshToken",
|
||||||
@ -142,5 +166,14 @@ func (r *RecoveryController) HandleRecoveryLink(c *fiber.Ctx) error {
|
|||||||
HTTPOnly: true,
|
HTTPOnly: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
hlogger.Emit(models.InfoPasswordRestored{
|
||||||
|
CtxUserIP: c.IP(),
|
||||||
|
CtxUserPort: c.Port(),
|
||||||
|
KeyDomain: strings.Join(c.Subdomains(), "/"),
|
||||||
|
KeyPath: c.Path(),
|
||||||
|
CtxID: record.ID.String(),
|
||||||
|
CtxUserID: record.UserID,
|
||||||
|
})
|
||||||
|
|
||||||
return c.Redirect(record.SignUrl + "?auth=" + tokens["accessToken"])
|
return c.Redirect(record.SignUrl + "?auth=" + tokens["accessToken"])
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"codeword/internal/utils/hlogger_mw"
|
"codeword/internal/utils/middleware"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
@ -13,6 +13,7 @@ type ServerConfig struct {
|
|||||||
Logger *zap.Logger
|
Logger *zap.Logger
|
||||||
Controllers []Controller
|
Controllers []Controller
|
||||||
Hlogger hlog.Logger
|
Hlogger hlog.Logger
|
||||||
|
JWT *middleware.JWT
|
||||||
}
|
}
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
@ -23,7 +24,8 @@ type Server struct {
|
|||||||
|
|
||||||
func NewServer(config ServerConfig) *Server {
|
func NewServer(config ServerConfig) *Server {
|
||||||
app := fiber.New()
|
app := fiber.New()
|
||||||
app.Use(hlogger_mw.ContextLogger(config.Hlogger))
|
app.Use(middleware.ContextLogger(config.Hlogger))
|
||||||
|
app.Use("/promocode", middleware.NewAuthenticator(config.JWT))
|
||||||
s := &Server{
|
s := &Server{
|
||||||
Logger: config.Logger,
|
Logger: config.Logger,
|
||||||
Controllers: config.Controllers,
|
Controllers: config.Controllers,
|
||||||
|
@ -93,30 +93,30 @@ func (s *PromoCodeService) GetPromoCodesList(ctx context.Context, req *models.Ge
|
|||||||
// разделяется ли она или они всегда вместе, если разделяются то что-то из этого может быть пустым либо все заполеннное,
|
// разделяется ли она или они всегда вместе, если разделяются то что-то из этого может быть пустым либо все заполеннное,
|
||||||
// соответсвенно надо сделать соответствующие проверки до записи в кафку и до отправки в дискаунт сервис
|
// соответсвенно надо сделать соответствующие проверки до записи в кафку и до отправки в дискаунт сервис
|
||||||
|
|
||||||
func (s *PromoCodeService) ActivatePromo(ctx context.Context, req *models.ActivateReq, userID string) (string, error) {
|
func (s *PromoCodeService) ActivatePromo(ctx context.Context, req *models.ActivateReq, userID string) (*models.PromoCode, error) {
|
||||||
promoCode, err := s.promoCodeRepo.ActivatePromo(ctx, req)
|
promoCode, err := s.promoCodeRepo.ActivatePromo(ctx, req)
|
||||||
fmt.Println("SKER20", err, promoCode, time.Now().Unix())
|
fmt.Println("SKER20", err, promoCode, time.Now().Unix())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Error("Failed to activate promocode", zap.Error(err))
|
s.logger.Error("Failed to activate promocode", zap.Error(err))
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
//todo такая реализация проверок кажется довольно массивной, думаю как то это стоит сделать параллельно обхаживая все условия
|
//todo такая реализация проверок кажется довольно массивной, думаю как то это стоит сделать параллельно обхаживая все условия
|
||||||
if promoCode.DueTo < time.Now().Unix() && promoCode.DueTo > 0 {
|
if promoCode.DueTo < time.Now().Unix() && promoCode.DueTo > 0 {
|
||||||
err := s.promoCodeRepo.IncreaseActivationCount(ctx, promoCode.ID)
|
err := s.promoCodeRepo.IncreaseActivationCount(ctx, promoCode.ID)
|
||||||
fmt.Println("SKER21", err)
|
fmt.Println("SKER21", err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
return "", fmt.Errorf("%w: expired on %s", repository.ErrPromoCodeExpired, time.Unix(promoCode.DueTo, 0).Format(time.RFC3339))
|
return nil, fmt.Errorf("%w: expired on %s", repository.ErrPromoCodeExpired, time.Unix(promoCode.DueTo, 0).Format(time.RFC3339))
|
||||||
}
|
}
|
||||||
|
|
||||||
if promoCode.DueTo == 0 && promoCode.ActivationCount < 0 && promoCode.ActivationLimit != 0 {
|
if promoCode.DueTo == 0 && promoCode.ActivationCount < 0 && promoCode.ActivationLimit != 0 {
|
||||||
err := s.promoCodeRepo.IncreaseActivationCount(ctx, promoCode.ID)
|
err := s.promoCodeRepo.IncreaseActivationCount(ctx, promoCode.ID)
|
||||||
fmt.Println("SKER22", err)
|
fmt.Println("SKER22", err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
return "", repository.ErrPromoCodeExhausted
|
return nil, repository.ErrPromoCodeExhausted
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.statsRepo.UpdateStatistics(ctx, req, promoCode, userID)
|
err = s.statsRepo.UpdateStatistics(ctx, req, promoCode, userID)
|
||||||
@ -125,12 +125,12 @@ func (s *PromoCodeService) ActivatePromo(ctx context.Context, req *models.Activa
|
|||||||
if errors.Is(err, repository.ErrPromoCodeAlreadyActivated) {
|
if errors.Is(err, repository.ErrPromoCodeAlreadyActivated) {
|
||||||
err := s.promoCodeRepo.IncreaseActivationCount(ctx, promoCode.ID)
|
err := s.promoCodeRepo.IncreaseActivationCount(ctx, promoCode.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
return "", repository.ErrPromoCodeAlreadyActivated
|
return nil, repository.ErrPromoCodeAlreadyActivated
|
||||||
}
|
}
|
||||||
s.logger.Error("Failed add in stats", zap.Error(err))
|
s.logger.Error("Failed add in stats", zap.Error(err))
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var postfix string
|
var postfix string
|
||||||
@ -158,7 +158,7 @@ func (s *PromoCodeService) ActivatePromo(ctx context.Context, req *models.Activa
|
|||||||
fmt.Println("SKER24", err)
|
fmt.Println("SKER24", err)
|
||||||
if err := s.kafka.Send(ctx, userID, fakeTariff); err != nil {
|
if err := s.kafka.Send(ctx, userID, fakeTariff); err != nil {
|
||||||
s.logger.Error("Failed to send fake tariff to Kafka", zap.Error(err))
|
s.logger.Error("Failed to send fake tariff to Kafka", zap.Error(err))
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,11 +205,11 @@ func (s *PromoCodeService) ActivatePromo(ctx context.Context, req *models.Activa
|
|||||||
_, err = s.discountClient.CreateDiscount(ctx, discountRequest)
|
_, err = s.discountClient.CreateDiscount(ctx, discountRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Error("Failed to create discount", zap.Error(err))
|
s.logger.Error("Failed to create discount", zap.Error(err))
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return promoCode.Greetings, nil
|
return promoCode, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PromoCodeService) DeletePromoCode(ctx context.Context, promoCodeID string) error {
|
func (s *PromoCodeService) DeletePromoCode(ctx context.Context, promoCodeID string) error {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package utils
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"codeword/internal/models"
|
"codeword/internal/models"
|
||||||
"strings"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
@ -44,3 +44,8 @@ func authenticate(c *fiber.Ctx, jwtUtil *JWT) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExtractUserID(c *fiber.Ctx) string {
|
||||||
|
userID := c.Context().UserValue(models.AuthJWTDecodedUserIDKey).(string)
|
||||||
|
return userID
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package utils
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"codeword/internal/initialize"
|
"codeword/internal/initialize"
|
@ -1,4 +1,4 @@
|
|||||||
package hlogger_mw
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"codeword/internal/models"
|
"codeword/internal/models"
|
||||||
@ -12,3 +12,8 @@ func ContextLogger(logger hlog.Logger) fiber.Handler {
|
|||||||
return c.Next()
|
return c.Next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExtractLogger(c *fiber.Ctx) hlog.Logger {
|
||||||
|
logger := c.Context().UserValue(models.LoggerKey).(hlog.Logger)
|
||||||
|
return logger
|
||||||
|
}
|
@ -2,11 +2,11 @@ package helpers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"codeword/internal/initialize"
|
"codeword/internal/initialize"
|
||||||
"codeword/utils"
|
"codeword/internal/utils/middleware"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitializeJWT() *utils.JWT {
|
func InitializeJWT() *middleware.JWT {
|
||||||
publicKey := strings.Replace(`-----BEGIN PUBLIC KEY-----
|
publicKey := strings.Replace(`-----BEGIN PUBLIC KEY-----
|
||||||
MIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgHgnvr7O2tiApjJfid1orFnIGm69
|
MIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgHgnvr7O2tiApjJfid1orFnIGm69
|
||||||
80fZp+Lpbjo+NC/0whMFga2Biw5b1G2Q/B2u0tpO1Fs/E8z7Lv1nYfr5jx2S8x6B
|
80fZp+Lpbjo+NC/0whMFga2Biw5b1G2Q/B2u0tpO1Fs/E8z7Lv1nYfr5jx2S8x6B
|
||||||
@ -29,7 +29,7 @@ func InitializeJWT() *utils.JWT {
|
|||||||
7McQvEk12dU/JNTX8wJAOlAtSNjp9tVwpMpC0w2St1eKc1L2SknjeohA5ldoBz8sGeZsPhTU3eHSD1neAZXLKN5K68z3zFBr20ubY9nyLw==
|
7McQvEk12dU/JNTX8wJAOlAtSNjp9tVwpMpC0w2St1eKc1L2SknjeohA5ldoBz8sGeZsPhTU3eHSD1neAZXLKN5K68z3zFBr20ubY9nyLw==
|
||||||
-----END RSA PRIVATE KEY-----`, "\t", "", -1)
|
-----END RSA PRIVATE KEY-----`, "\t", "", -1)
|
||||||
|
|
||||||
return utils.NewJWT(&initialize.Config{
|
return middleware.NewJWT(&initialize.Config{
|
||||||
PrivateKey: privateKey,
|
PrivateKey: privateKey,
|
||||||
PublicKey: publicKey,
|
PublicKey: publicKey,
|
||||||
Audience: "pena",
|
Audience: "pena",
|
||||||
|
Loading…
Reference in New Issue
Block a user