Added:
- Endpoint for patch verification file(s) Fix: - Rename in verification models and repository
This commit is contained in:
parent
47d0563d07
commit
cd30886afb
@ -1,4 +1,4 @@
|
|||||||
openapi: 3.0.1
|
openapi: 3.0.3
|
||||||
info:
|
info:
|
||||||
title: Сервис логики верификации аккаунта пользователя
|
title: Сервис логики верификации аккаунта пользователя
|
||||||
description: |-
|
description: |-
|
||||||
@ -19,13 +19,13 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- verification
|
- verification
|
||||||
responses:
|
responses:
|
||||||
'200':
|
"200":
|
||||||
description: успешное получение данных
|
description: успешное получение данных
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/Verification'
|
$ref: "#/components/schemas/Verification"
|
||||||
'401':
|
"401":
|
||||||
description: Неавторизован
|
description: Неавторизован
|
||||||
/verification:
|
/verification:
|
||||||
get:
|
get:
|
||||||
@ -33,13 +33,13 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- verification
|
- verification
|
||||||
responses:
|
responses:
|
||||||
'200':
|
"200":
|
||||||
description: успешное получение данных
|
description: успешное получение данных
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/Verification'
|
$ref: "#/components/schemas/Verification"
|
||||||
'401':
|
"401":
|
||||||
description: Неавторизован
|
description: Неавторизован
|
||||||
post:
|
post:
|
||||||
description: метод подания запроса на верификацию. При получении запроса отправить сообщение в канал телеграмма. Айдишник канала и токен бота передавать через переменные окружения. Файл с шаблоном сообщения встраивать в приложение. В тексте сообщения должно быть место для вставки урла для получения страницы админки с этим запросом, вида https://admin.pena.digital/user/{Id}/verification
|
description: метод подания запроса на верификацию. При получении запроса отправить сообщение в канал телеграмма. Айдишник канала и токен бота передавать через переменные окружения. Файл с шаблоном сообщения встраивать в приложение. В тексте сообщения должно быть место для вставки урла для получения страницы админки с этим запросом, вида https://admin.pena.digital/user/{Id}/verification
|
||||||
@ -52,32 +52,28 @@ paths:
|
|||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
status:
|
status:
|
||||||
$ref: '#/components/schemas/Status'
|
$ref: "#/components/schemas/Status"
|
||||||
inn:
|
inn:
|
||||||
type: file
|
type: string
|
||||||
contentMediaType: application/pdf
|
format: base64
|
||||||
contentEncoding: base64
|
|
||||||
rule:
|
rule:
|
||||||
type: file
|
type: string
|
||||||
contentMediaType: application/pdf
|
format: base64
|
||||||
contentEncoding: base64
|
|
||||||
egrule:
|
egrule:
|
||||||
type: file
|
type: string
|
||||||
contentMediaType: application/pdf
|
format: base64
|
||||||
contentEncoding: base64
|
|
||||||
certificate:
|
certificate:
|
||||||
type: file
|
type: string
|
||||||
description: только для status == nko
|
description: только для status == nko
|
||||||
contentMediaType: application/pdf
|
format: base64
|
||||||
contentEncoding: base64
|
|
||||||
responses:
|
responses:
|
||||||
'200':
|
"200":
|
||||||
description: успешный запрос на верификацию
|
description: успешный запрос на верификацию
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/Verification'
|
$ref: "#/components/schemas/Verification"
|
||||||
'401':
|
"401":
|
||||||
description: Неавторизован
|
description: Неавторизован
|
||||||
patch:
|
patch:
|
||||||
description: метод подтверждения или отклонения верификации. При подтверждении надо передать статус верификации в customer сервис. Эндпоинт для этого получить из переменных окружения. Документация для этого эндпоинта - https://penahub.gitlab.yandexcloud.net/pena-services/customer/-/blob/dev/openapi.yaml PATCH /account/{userId}. Слать запрос туда лучше через воркер, сохраняя задачи на отправку запросов в базу, чтобы не потерялись при перезагрузке сервиса.
|
description: метод подтверждения или отклонения верификации. При подтверждении надо передать статус верификации в customer сервис. Эндпоинт для этого получить из переменных окружения. Документация для этого эндпоинта - https://penahub.gitlab.yandexcloud.net/pena-services/customer/-/blob/dev/openapi.yaml PATCH /account/{userId}. Слать запрос туда лучше через воркер, сохраняя задачи на отправку запросов в базу, чтобы не потерялись при перезагрузке сервиса.
|
||||||
@ -93,15 +89,44 @@ paths:
|
|||||||
type: string
|
type: string
|
||||||
description: айдишник юзера
|
description: айдишник юзера
|
||||||
status:
|
status:
|
||||||
$ref: '#/components/schemas/Status'
|
$ref: "#/components/schemas/Status"
|
||||||
comment:
|
comment:
|
||||||
type: string
|
type: string
|
||||||
accepted:
|
accepted:
|
||||||
type: boolean
|
type: boolean
|
||||||
responses:
|
responses:
|
||||||
'200':
|
"200":
|
||||||
description: успешное подтверждение или отклонение верификации
|
description: успешное подтверждение или отклонение верификации
|
||||||
'401':
|
"401":
|
||||||
|
description: Неавторизован
|
||||||
|
/verification/file:
|
||||||
|
patch:
|
||||||
|
description: "метод для обновления файла/файлов верификации"
|
||||||
|
tags:
|
||||||
|
- verification
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
multipart/form-data:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
inn:
|
||||||
|
type: string
|
||||||
|
format: base64
|
||||||
|
rule:
|
||||||
|
type: string
|
||||||
|
format: base64
|
||||||
|
egrule:
|
||||||
|
type: string
|
||||||
|
format: base64
|
||||||
|
certificate:
|
||||||
|
type: string
|
||||||
|
description: только для status == nko
|
||||||
|
format: base64
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: успешно
|
||||||
|
"401":
|
||||||
description: Неавторизован
|
description: Неавторизован
|
||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
@ -114,7 +139,7 @@ components:
|
|||||||
accepted:
|
accepted:
|
||||||
type: boolean
|
type: boolean
|
||||||
status:
|
status:
|
||||||
$ref: '#/components/schemas/Status'
|
$ref: "#/components/schemas/Status"
|
||||||
updated_at:
|
updated_at:
|
||||||
type: string
|
type: string
|
||||||
format: "date-time"
|
format: "date-time"
|
||||||
@ -123,7 +148,7 @@ components:
|
|||||||
files:
|
files:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/File'
|
$ref: "#/components/schemas/File"
|
||||||
File:
|
File:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"penahub.gitlab.yandexcloud.net/backend/verification/internal/models"
|
"penahub.gitlab.yandexcloud.net/backend/verification/internal/models"
|
||||||
"reflect"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var validate = validator.New()
|
var validate = validator.New()
|
||||||
@ -16,7 +17,7 @@ type Route struct {
|
|||||||
Handler fiber.Handler
|
Handler fiber.Handler
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateStruct - возвращает строку с ошибкой, если структура не прошла валидацию
|
// validateStruct - возвращает строку с ошибкой, если структура не прошла валидацию.
|
||||||
func validateStruct(s any) []*models.RespErrorValidate {
|
func validateStruct(s any) []*models.RespErrorValidate {
|
||||||
err := validate.Struct(s)
|
err := validate.Struct(s)
|
||||||
|
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gofiber/fiber/v2"
|
"errors"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
|
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/valyala/fasthttp"
|
||||||
"penahub.gitlab.yandexcloud.net/backend/verification/internal/client"
|
"penahub.gitlab.yandexcloud.net/backend/verification/internal/client"
|
||||||
"penahub.gitlab.yandexcloud.net/backend/verification/internal/models"
|
"penahub.gitlab.yandexcloud.net/backend/verification/internal/models"
|
||||||
"penahub.gitlab.yandexcloud.net/backend/verification/internal/repository"
|
"penahub.gitlab.yandexcloud.net/backend/verification/internal/repository"
|
||||||
@ -23,6 +26,7 @@ func (r *VerificationController) GetRoutes() []Route {
|
|||||||
{"GET", "/verification/:userID", "GetVerification", r.GetVerification},
|
{"GET", "/verification/:userID", "GetVerification", r.GetVerification},
|
||||||
{"POST", "/verification", "CreateVerification", r.CreateVerification},
|
{"POST", "/verification", "CreateVerification", r.CreateVerification},
|
||||||
{"PATCH", "/verification", "SetVerificationStatus", r.SetVerificationStatus},
|
{"PATCH", "/verification", "SetVerificationStatus", r.SetVerificationStatus},
|
||||||
|
{Method: "PATCH", Path: "/verification/file", Name: "SetVerificationFile", Handler: r.SetVerificationFile},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +40,7 @@ func (r *VerificationController) GetVerification(c *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := r.repository.GetByUserId(c.Context(), userID)
|
resp, err := r.repository.GetByUserID(c.Context(), userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(fiber.StatusInternalServerError).SendString(err.Error())
|
return c.Status(fiber.StatusInternalServerError).SendString(err.Error())
|
||||||
}
|
}
|
||||||
@ -156,3 +160,30 @@ func (r *VerificationController) SetVerificationStatus(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
return c.SendStatus(fiber.StatusOK)
|
return c.SendStatus(fiber.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *VerificationController) SetVerificationFile(c *fiber.Ctx) error {
|
||||||
|
userID := c.Params("userID")
|
||||||
|
|
||||||
|
if userID == "" {
|
||||||
|
userID = c.Locals("userID").(string)
|
||||||
|
if userID == "" {
|
||||||
|
return fiber.NewError(fiber.StatusUnauthorized)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
availableFiles := []string{"inn", "rule", "egrule", "certificate"}
|
||||||
|
|
||||||
|
for _, fileName := range availableFiles {
|
||||||
|
fileHeader, err := c.FormFile(fileName)
|
||||||
|
|
||||||
|
if err != nil && !errors.Is(err, fasthttp.ErrMissingFile) {
|
||||||
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := r.repository.UpdateFile(c.Context(), userID, fileName, fileHeader); err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.SendStatus(fiber.StatusOK)
|
||||||
|
}
|
||||||
|
@ -10,7 +10,7 @@ type VerificationTestSuite struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
//func (suite *VerificationTestSuite) SetupSuite() {
|
// func (suite *VerificationTestSuite) SetupSuite() {
|
||||||
// cfg, err := config.NewConfig("test.env")
|
// cfg, err := config.NewConfig("test.env")
|
||||||
// suite.NoError(err)
|
// suite.NoError(err)
|
||||||
//
|
//
|
||||||
|
@ -9,10 +9,10 @@ type Verification struct {
|
|||||||
Status string `json:"status" bson:"status,omitempty"`
|
Status string `json:"status" bson:"status,omitempty"`
|
||||||
UpdatedAt time.Time `json:"updated_at" bson:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at" bson:"updated_at"`
|
||||||
Comment string `json:"comment" bson:"comment,omitempty"`
|
Comment string `json:"comment" bson:"comment,omitempty"`
|
||||||
Files []VerificationFiles `json:"files" bson:"files,omitempty"`
|
Files []VerificationFile `json:"files" bson:"files,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type VerificationFiles struct {
|
type VerificationFile struct {
|
||||||
Name string `json:"name" bson:"name"`
|
Name string `json:"name" bson:"name"`
|
||||||
Url string `json:"url" bson:"url"`
|
Url string `json:"url" bson:"url"`
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/minio/minio-go/v7"
|
"github.com/minio/minio-go/v7"
|
||||||
@ -100,7 +101,6 @@ func (r *VerificationRepository) Init(ctx context.Context) error {
|
|||||||
if r.err(err) {
|
if r.err(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -160,7 +160,7 @@ func (r *VerificationRepository) Insert(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
record.Files = []models.VerificationFiles{
|
record.Files = []models.VerificationFile{
|
||||||
{
|
{
|
||||||
Name: "certificate",
|
Name: "certificate",
|
||||||
Url: fmt.Sprintf("%s/%s/%s/%s", VerificationEndpointURL, VerificationBucket, userID, certFH.Filename),
|
Url: fmt.Sprintf("%s/%s/%s/%s", VerificationEndpointURL, VerificationBucket, userID, certFH.Filename),
|
||||||
@ -169,7 +169,7 @@ func (r *VerificationRepository) Insert(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Insert to MongoDB
|
// Insert to MongoDB
|
||||||
record.Files = append(record.Files, []models.VerificationFiles{
|
record.Files = append(record.Files, []models.VerificationFile{
|
||||||
{
|
{
|
||||||
Name: "inn",
|
Name: "inn",
|
||||||
Url: fmt.Sprintf("%s/%s/%s/%s", VerificationEndpointURL, VerificationBucket, userID, innFH.Filename),
|
Url: fmt.Sprintf("%s/%s/%s/%s", VerificationEndpointURL, VerificationBucket, userID, innFH.Filename),
|
||||||
@ -193,7 +193,7 @@ func (r *VerificationRepository) Insert(
|
|||||||
return record, nil
|
return record, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *VerificationRepository) GetByUserId(ctx context.Context, userID string) (*models.Verification, error) {
|
func (r *VerificationRepository) GetByUserID(ctx context.Context, userID string) (*models.Verification, error) {
|
||||||
if userID == "" {
|
if userID == "" {
|
||||||
err := errors.New("userID cannot be empty")
|
err := errors.New("userID cannot be empty")
|
||||||
r.logger.Error("VerificationRepositoryError", zap.Error(err))
|
r.logger.Error("VerificationRepositoryError", zap.Error(err))
|
||||||
@ -254,6 +254,57 @@ func (r *VerificationRepository) Update(ctx context.Context, record *models.Veri
|
|||||||
|
|
||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *VerificationRepository) UpdateFile(ctx context.Context, userID, fileName string, fileHeader *multipart.FileHeader) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// put file
|
||||||
|
fileReader, err := fileHeader.Open()
|
||||||
|
if r.err(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.s3.PutObject(ctx, VerificationBucket, fmt.Sprintf("%s/%s", userID, fileHeader.Filename), fileReader, fileHeader.Size, minio.PutObjectOptions{})
|
||||||
|
if r.err(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fileUrl := fmt.Sprintf("%s/%s/%s/%s", VerificationEndpointURL, VerificationBucket, userID, fileHeader.Filename)
|
||||||
|
|
||||||
|
// remove old file
|
||||||
|
verification, err := r.GetByUserID(ctx, userID)
|
||||||
|
if r.err(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
found := false
|
||||||
|
for iterator, file := range verification.Files {
|
||||||
|
if file.Name != fileName {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
objectName := strings.ReplaceAll(file.Name, fmt.Sprintf("%v/%v/", VerificationEndpointURL, VerificationBucket), "")
|
||||||
|
if err = r.s3.RemoveObject(ctx, VerificationBucket, objectName, minio.RemoveObjectOptions{}); r.err(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
verification.Files[iterator] = models.VerificationFile{Name: file.Name, Url: fileUrl}
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
verification.Files = append(verification.Files, models.VerificationFile{Name: fileName, Url: fileUrl})
|
||||||
|
}
|
||||||
|
|
||||||
|
// update in mongodb
|
||||||
|
_, err = r.Update(ctx, &models.Verification{ID: verification.ID, Files: verification.Files})
|
||||||
|
if r.err(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *VerificationRepository) err(err error) bool {
|
func (r *VerificationRepository) err(err error) bool {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.logger.Error("VerificationRepositoryError", zap.Error(err))
|
r.logger.Error("VerificationRepositoryError", zap.Error(err))
|
||||||
|
@ -32,23 +32,22 @@ func NewHTTP(cfg *config.Config, logger *zap.Logger) *HTTP {
|
|||||||
return &HTTP{fiber: srv, cfg: cfg, logger: logger}
|
return &HTTP{fiber: srv, cfg: cfg, logger: logger}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register - автоматически регистрирует все контроллеры
|
// Register - автоматически регистрирует все контроллеры.
|
||||||
func (srv *HTTP) Register(controllers ...initialize.Controller) *HTTP {
|
func (srv *HTTP) Register(controllers ...initialize.Controller) *HTTP {
|
||||||
for _, controller := range controllers {
|
for _, controller := range controllers {
|
||||||
for _, route := range controller.GetRoutes() {
|
for _, route := range controller.GetRoutes() {
|
||||||
srv.fiber.Add(route.Method, route.Path, route.Handler).Name(route.Name)
|
srv.fiber.Add(route.Method, route.Path, route.Handler).Name(route.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return srv
|
return srv
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start - запускает http сервер
|
// Start - запускает http сервер.
|
||||||
func (srv *HTTP) Start() error {
|
func (srv *HTTP) Start() error {
|
||||||
return srv.fiber.Listen(srv.cfg.HttpAddress)
|
return srv.fiber.Listen(srv.cfg.HttpAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop - останавливает http сервер
|
// Stop - останавливает http сервер.
|
||||||
func (srv *HTTP) Stop() error {
|
func (srv *HTTP) Stop() error {
|
||||||
return srv.fiber.Shutdown()
|
return srv.fiber.Shutdown()
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"penahub.gitlab.yandexcloud.net/backend/penahub_common/jwt_adapter"
|
"penahub.gitlab.yandexcloud.net/backend/penahub_common/jwt_adapter"
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user