customer/internal/interface/controller/http/account_client/controllers.go
Pasha 34a88a3a70
Some checks failed
Lint / Lint (push) Failing after 1m2s
rename go.mod
2024-11-18 21:44:09 +00:00

237 lines
6.6 KiB
Go

package account_client
import (
"bufio"
"context"
"encoding/json"
"fmt"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/backend/penahub_common/log_mw"
qutils "penahub.gitlab.yandexcloud.net/backend/quiz/common.git/utils"
"gitea.pena/PenaSide/customer/internal/errors"
"gitea.pena/PenaSide/customer/internal/interface/client"
"gitea.pena/PenaSide/customer/internal/interface/controller/http"
"gitea.pena/PenaSide/customer/internal/interface/repository"
"gitea.pena/PenaSide/customer/internal/models"
"time"
)
type Deps struct {
MiddleWare *http.MiddleWare
AccountRepo *repository.AccountRepository
Logger *zap.Logger
Encrypt *qutils.Encrypt
AuthClient *client.AuthClient
}
type AccountController struct {
middleWare *http.MiddleWare
accountRepo *repository.AccountRepository
logger *zap.Logger
encrypt *qutils.Encrypt
authClient *client.AuthClient
}
func NewAccountController(deps Deps) *AccountController {
return &AccountController{
middleWare: deps.MiddleWare,
accountRepo: deps.AccountRepo,
logger: deps.Logger,
encrypt: deps.Encrypt,
authClient: deps.AuthClient,
}
}
func (receiver *AccountController) Delete(ctx *fiber.Ctx) error {
userID, ok := receiver.middleWare.ExtractUserID(ctx)
if !ok || userID == "" {
return receiver.middleWare.NoAuth(ctx)
}
account, err := receiver.accountRepo.Remove(ctx.Context(), userID)
if err != nil {
return receiver.middleWare.ErrorOld(ctx, err)
}
return ctx.Status(fiber.StatusOK).JSON(account)
}
func (receiver *AccountController) Update(ctx *fiber.Ctx) error {
userID, ok := receiver.middleWare.ExtractUserID(ctx)
if !ok || userID == "" {
return receiver.middleWare.NoAuth(ctx)
}
var request models.Name
if err := ctx.BodyParser(&request); err != nil {
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "failed to bind json", err)
}
account, err := receiver.accountRepo.UpdateName(ctx.Context(), userID, &request)
if err != nil {
return receiver.middleWare.ErrorOld(ctx, err)
}
return ctx.Status(fiber.StatusOK).JSON(account)
}
func (receiver *AccountController) SetVerificationStatus(ctx *fiber.Ctx) error {
userID := ctx.Params("userId")
if userID == "" {
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "invalid format for parameter userId")
}
var request models.SetAccountStatus
if err := ctx.BodyParser(&request); err != nil {
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "failed to bind json", err)
}
account, err := receiver.accountRepo.SetStatus(ctx.Context(), userID, request.Status)
if err != nil {
receiver.logger.Error("failed to set status on <SetVerificationStatus> of <AccountService>", zap.Error(err))
return receiver.middleWare.ErrorOld(ctx, err)
}
return ctx.Status(fiber.StatusOK).JSON(account)
}
func (receiver *AccountController) Get(ctx *fiber.Ctx) error {
userID, ok := receiver.middleWare.ExtractUserID(ctx)
if !ok || userID == "" {
return receiver.middleWare.NoAuth(ctx)
}
hlogger := log_mw.ExtractLogger(ctx)
account, err := receiver.accountRepo.FindByUserID(ctx.Context(), userID)
if err != nil {
if err.Type() == errors.ErrNotFound {
return receiver.middleWare.Error(ctx, fiber.StatusNotFound, "no account", err)
}
return receiver.middleWare.ErrorOld(ctx, err)
}
hlogger.Emit(models.InfoGetAccount{
CtxUserID: userID,
CtxAccountID: account.ID,
})
return ctx.Status(fiber.StatusOK).JSON(account)
}
func (receiver *AccountController) Create(ctx *fiber.Ctx) error {
userID, ok := receiver.middleWare.ExtractUserID(ctx)
if !ok || userID == "" {
return receiver.middleWare.NoAuth(ctx)
}
hlogger := log_mw.ExtractLogger(ctx)
var er error
quizFrom := ctx.Cookies("quizFrom")
quizUser := ctx.Cookies("quizUser")
if quizUser != "" {
quizUser, er = receiver.encrypt.DecryptStr([]byte(quizUser))
if er != nil {
return receiver.middleWare.ErrorOld(ctx, er)
}
}
account, err := receiver.accountRepo.FindByUserID(ctx.Context(), userID)
if err != nil && err.Type() != errors.ErrNotFound {
return receiver.middleWare.ErrorOld(ctx, err)
}
if account != nil {
return receiver.middleWare.Error(ctx, fiber.StatusBadRequest, "account exists")
}
user, err := receiver.authClient.GetUser(ctx.Context(), userID)
if err != nil {
return receiver.middleWare.ErrorOld(ctx, err)
}
account, err = receiver.accountRepo.Insert(ctx.Context(), &models.Account{
UserID: user.ID, Wallet: models.Wallet{Currency: models.DefaultCurrency}, From: quizFrom, Partner: quizUser})
if err != nil {
return receiver.middleWare.ErrorOld(ctx, err)
}
quiz := ""
if quizFrom != "" {
quiz = "quiz"
}
hlogger.Emit(models.InfoCreateAccount{
CtxUserID: userID,
CtxAccountID: account.ID,
KeyFromSource: quiz,
KeyFromID: quizFrom,
KeyFromPartner: quizUser,
CtxLogin: user.Login,
CtxEmail: user.Email,
CtxPhone: user.PhoneNumber,
KeyCurrency: account.Wallet.Currency,
})
return ctx.Status(fiber.StatusOK).JSON(account)
}
func (receiver *AccountController) AccountPipe(ctx *fiber.Ctx) error {
userID, ok := receiver.middleWare.ExtractUserID(ctx)
if !ok || userID == "" {
return receiver.middleWare.NoAuth(ctx)
}
ctx.Set(fiber.HeaderContentType, "text/event-stream")
ctx.Set("Cache-Control", "no-cache")
ctx.Set("Connection", "keep-alive")
ctx.Set("Transfer-Encoding", "chunked")
accountCh := make(chan map[string]interface{})
cancelCtx, cancel := context.WithCancel(ctx.Context())
go func(ctx context.Context) {
defer close(accountCh)
if err := receiver.accountRepo.AccountPipe(ctx, userID, accountCh); err != nil {
receiver.logger.Error("error in account pipe repo method", zap.Error(err))
}
}(cancelCtx)
ctx.Status(fiber.StatusOK).Context().SetBodyStreamWriter(func(w *bufio.Writer) {
pingTicker := time.NewTicker(5 * time.Second)
defer pingTicker.Stop()
for {
select {
case accountData, ok := <-accountCh:
if !ok {
return
}
accountJSON, err := json.Marshal(accountData)
if err != nil {
//receiver.logger.Error("error marshal account JSON", zap.Error(err))
continue
}
fmt.Fprintf(w, "data: %s\n\n", accountJSON)
if err := w.Flush(); err != nil {
receiver.logger.Error("error flushing", zap.Error(err))
cancel()
receiver.logger.Info("Close connection Account Pipe sse")
return
}
case <-pingTicker.C:
fmt.Fprintf(w, "data: %s\n\n", `{"event": "ping"}`)
if err := w.Flush(); err != nil {
receiver.logger.Error("error sending ping Account Pipe sse, close connection", zap.Error(err))
cancel()
return
}
}
}
})
return nil
}