add docs
This commit is contained in:
parent
e5c3b3786d
commit
33d0c25397
@ -28,9 +28,11 @@ paths:
|
|||||||
requestBody:
|
requestBody:
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/x-www-form-urlencoded:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
|
required:
|
||||||
|
- email
|
||||||
properties:
|
properties:
|
||||||
email:
|
email:
|
||||||
type: string
|
type: string
|
||||||
@ -257,6 +259,60 @@ paths:
|
|||||||
error:
|
error:
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
|
/promocode/fastlink:
|
||||||
|
post:
|
||||||
|
summary: Создать быструю ссылку для промокода
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
description: ID промокода, для которого нужно создать быструю ссылку
|
||||||
|
responses:
|
||||||
|
'201':
|
||||||
|
description: Быстрая ссылка для промокода успешно создана
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
fastlink:
|
||||||
|
type: string
|
||||||
|
description: Быстрая ссылка для активации промокода
|
||||||
|
'400':
|
||||||
|
description: Неверный запрос, отсутствует идентификатор промокода
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
error:
|
||||||
|
type: string
|
||||||
|
'404':
|
||||||
|
description: Промокод не найден
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
error:
|
||||||
|
type: string
|
||||||
|
'500':
|
||||||
|
description: Внутренняя ошибка сервера
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
error:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
|
||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
@ -436,12 +492,13 @@ components:
|
|||||||
|
|
||||||
ActivateReq:
|
ActivateReq:
|
||||||
type: object
|
type: object
|
||||||
required:
|
|
||||||
- codeword
|
|
||||||
properties:
|
properties:
|
||||||
codeword:
|
codeword:
|
||||||
type: string
|
type: string
|
||||||
description: Кодовое слово промокода, которое требуется активировать
|
description: Кодовое слово промокода, которое требуется активировать
|
||||||
|
fastLink:
|
||||||
|
type: string
|
||||||
|
description: Быстрая ссылка для активации промокода
|
||||||
|
|
||||||
ActivateResp:
|
ActivateResp:
|
||||||
type: object
|
type: object
|
||||||
|
|||||||
@ -26,6 +26,12 @@ func Run(ctx context.Context, cfg initialize.Config, logger *zap.Logger) error {
|
|||||||
cancel()
|
cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = initialize.InitDatabaseIndexes(ctx, mdb, logger); err != nil {
|
||||||
|
logger.Error("Failed to initialize db indexes", zap.Error(err))
|
||||||
|
cancel()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
rdb, err := initialize.Redis(ctx, cfg)
|
rdb, err := initialize.Redis(ctx, cfg)
|
||||||
encrypt := initialize.Encrypt(cfg)
|
encrypt := initialize.Encrypt(cfg)
|
||||||
|
|
||||||
|
|||||||
@ -135,9 +135,8 @@ func (p *PromoCodeController) Delete(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
// todo затестить и добавить в opnapi
|
// todo затестить и добавить в opnapi
|
||||||
func (p *PromoCodeController) CreateFastLink(c *fiber.Ctx) error {
|
func (p *PromoCodeController) CreateFastLink(c *fiber.Ctx) error {
|
||||||
// нужно что-то получать из Localstorage например id или codeword
|
|
||||||
var req struct {
|
var req struct {
|
||||||
PromoCodeID string `json:"promoCodeID"`
|
PromoCodeID string `json:"id"`
|
||||||
}
|
}
|
||||||
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"})
|
||||||
|
|||||||
@ -2,10 +2,8 @@ package recovery
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"codeword/internal/models"
|
"codeword/internal/models"
|
||||||
"codeword/internal/repository"
|
|
||||||
"codeword/internal/services"
|
"codeword/internal/services"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
@ -57,14 +55,10 @@ func (r *RecoveryController) HandleRecoveryRequest(c *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
user, err := r.service.FindUserByEmail(c.Context(), req.Email)
|
user, err := r.service.FindUserByEmail(c.Context(), req.Email)
|
||||||
if err != nil {
|
if err != nil || user == nil {
|
||||||
r.logger.Error("Failed to find user by email", zap.Error(err))
|
r.logger.Error("Failed to find user by email", zap.Error(err))
|
||||||
|
|
||||||
if errors.Is(err, repository.ErrPromoUserNotFound) {
|
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "User not found"})
|
||||||
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "User not found"})
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
key, err := r.service.GenerateKey()
|
key, err := r.service.GenerateKey()
|
||||||
@ -96,20 +90,16 @@ func (r *RecoveryController) HandleRecoveryRequest(c *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *RecoveryController) HandleRecoveryLink(c *fiber.Ctx) error {
|
func (r *RecoveryController) HandleRecoveryLink(c *fiber.Ctx) error {
|
||||||
var req models.RecoveryLinkRequest
|
sign := c.Params("sign")
|
||||||
if err := c.BodyParser(&req); err != nil {
|
|
||||||
r.logger.Error("Failed to parse recovery link request", zap.Error(err))
|
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Bad Request"})
|
|
||||||
}
|
|
||||||
|
|
||||||
record, err := r.service.GetRecoveryRecord(c.Context(), req.Sign)
|
record, err := r.service.GetRecoveryRecord(c.Context(), sign)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Error("Failed to get recovery record", zap.Error(err))
|
r.logger.Error("Failed to get 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"})
|
||||||
}
|
}
|
||||||
|
|
||||||
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", req.Sign))
|
r.logger.Error("Recovery link expired", zap.String("signature", sign))
|
||||||
return c.Status(fiber.StatusNotAcceptable).JSON(fiber.Map{"error": "Recovery link expired"})
|
return c.Status(fiber.StatusNotAcceptable).JSON(fiber.Map{"error": "Recovery link expired"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
package initialize
|
package initialize
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"codeword/internal/repository"
|
||||||
mdb "codeword/pkg/mongo"
|
mdb "codeword/pkg/mongo"
|
||||||
"context"
|
"context"
|
||||||
"go.mongodb.org/mongo-driver/mongo"
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.uber.org/zap"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,7 +19,7 @@ func MongoDB(ctx context.Context, cfg Config) (*mongo.Database, error) {
|
|||||||
MongoAuth: cfg.MongoAuth,
|
MongoAuth: cfg.MongoAuth,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
newCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
mongoDeps := &mdb.ConnectDeps{
|
mongoDeps := &mdb.ConnectDeps{
|
||||||
@ -25,15 +27,24 @@ func MongoDB(ctx context.Context, cfg Config) (*mongo.Database, error) {
|
|||||||
Timeout: 10 * time.Second,
|
Timeout: 10 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
db, err := mdb.Connect(ctx, mongoDeps)
|
db, err := mdb.Connect(newCtx, mongoDeps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = db.Client().Ping(ctx, nil)
|
err = db.Client().Ping(newCtx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return db, nil
|
return db, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func InitDatabaseIndexes(ctx context.Context, mdb *mongo.Database, logger *zap.Logger) error {
|
||||||
|
if err := repository.InitPromoCodeIndexes(ctx, mdb.Collection("promoCodes")); err != nil {
|
||||||
|
logger.Error("Failed to initialize promoCodes indexes", zap.Error(err))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@ -27,7 +27,10 @@ type PromoCodeRepository struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewPromoCodeRepository(mdb *mongo.Collection) *PromoCodeRepository {
|
func NewPromoCodeRepository(mdb *mongo.Collection) *PromoCodeRepository {
|
||||||
// todo заменить паники вроде как в роде не круто их юзать
|
return &PromoCodeRepository{mdb: mdb}
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitPromoCodeIndexes(ctx context.Context, mdb *mongo.Collection) error {
|
||||||
uniqueIndexModel := mongo.IndexModel{
|
uniqueIndexModel := mongo.IndexModel{
|
||||||
Keys: bson.D{
|
Keys: bson.D{
|
||||||
{Key: "codeword", Value: 1},
|
{Key: "codeword", Value: 1},
|
||||||
@ -35,9 +38,9 @@ func NewPromoCodeRepository(mdb *mongo.Collection) *PromoCodeRepository {
|
|||||||
},
|
},
|
||||||
Options: options.Index().SetUnique(true).SetPartialFilterExpression(bson.M{"delete": false}),
|
Options: options.Index().SetUnique(true).SetPartialFilterExpression(bson.M{"delete": false}),
|
||||||
}
|
}
|
||||||
_, err := mdb.Indexes().CreateOne(context.Background(), uniqueIndexModel)
|
_, err := mdb.Indexes().CreateOne(ctx, uniqueIndexModel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
textIndexModel := mongo.IndexModel{
|
textIndexModel := mongo.IndexModel{
|
||||||
@ -48,17 +51,20 @@ func NewPromoCodeRepository(mdb *mongo.Collection) *PromoCodeRepository {
|
|||||||
},
|
},
|
||||||
Options: options.Index().SetName("TextIndex"),
|
Options: options.Index().SetName("TextIndex"),
|
||||||
}
|
}
|
||||||
_, err = mdb.Indexes().CreateOne(context.Background(), textIndexModel)
|
_, err = mdb.Indexes().CreateOne(ctx, textIndexModel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &PromoCodeRepository{mdb: mdb}
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *PromoCodeRepository) CreatePromoCode(ctx context.Context, req *models.PromoCode) (*models.PromoCode, error) {
|
func (r *PromoCodeRepository) CreatePromoCode(ctx context.Context, req *models.PromoCode) (*models.PromoCode, error) {
|
||||||
req.CreatedAt = time.Now()
|
req.CreatedAt = time.Now()
|
||||||
req.ID = primitive.NewObjectID()
|
req.ID = primitive.NewObjectID()
|
||||||
|
if req.FastLinks == nil {
|
||||||
|
req.FastLinks = []string{}
|
||||||
|
}
|
||||||
|
|
||||||
_, err := r.mdb.InsertOne(ctx, req)
|
_, err := r.mdb.InsertOne(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user