verification/internal/repository/verification.go

324 lines
8.6 KiB
Go
Raw Normal View History

2023-06-12 14:19:10 +00:00
package repository
import (
"context"
"errors"
"fmt"
"mime/multipart"
"strings"
"time"
2023-06-12 14:19:10 +00:00
"github.com/minio/minio-go/v7"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/backend/verification/internal/models"
2023-06-12 14:19:10 +00:00
)
type VerificationRepository struct {
logger *zap.Logger
mongo *mongo.Collection
s3 *minio.Client
}
const (
VerificationEndpointURL = "https://hub.pena.digital"
VerificationBucket = "verification1"
VerificationCollection = "verification"
2023-06-12 14:19:10 +00:00
)
func NewVerificationRepository(logger *zap.Logger, mongoDb *mongo.Database, s3 *minio.Client) *VerificationRepository {
return &VerificationRepository{
logger: logger,
mongo: mongoDb.Collection(VerificationCollection),
s3: s3,
}
}
func (r *VerificationRepository) Init(ctx context.Context) error {
2024-02-09 16:38:56 +00:00
//ok, err := r.s3.BucketExists(ctx, VerificationBucket)
//if r.err(err) {
// return err
//}
//
//if !ok {
// err = r.s3.MakeBucket(ctx, VerificationBucket, minio.MakeBucketOptions{ObjectLocking: false})
// if r.err(err) {
// return err
// }
//
// policyConsoleStatement := policy.Statement{
// Actions: set.CreateStringSet("*"),
// Conditions: policy.ConditionMap{
// "StringLike": policy.ConditionKeyMap{
// "aws:referer": set.CreateStringSet(fmt.Sprintf("https://console.cloud.yandex.*/folders/*/storage/buckets/%s*", VerificationBucket)),
// },
// },
// Effect: "Allow",
// Principal: policy.User{AWS: set.CreateStringSet("*")},
// Resources: set.CreateStringSet(fmt.Sprintf("arn:aws:s3:::%s/*", VerificationBucket),
// fmt.Sprintf("arn:aws:s3:::%s", VerificationBucket)),
// Sid: "console-statement",
// }
//
// policyServiceAccount := policy.Statement{
// Actions: set.CreateStringSet("*"),
// Conditions: nil,
// Effect: "Allow",
// Principal: policy.User{CanonicalUser: set.CreateStringSet("ajelmc4tjbct675tjdh9")},
// Resources: set.CreateStringSet(fmt.Sprintf("arn:aws:s3:::%s/*", VerificationBucket),
// fmt.Sprintf("arn:aws:s3:::%s", VerificationBucket)),
// Sid: "service-account-statement",
// }
//
// policySharingBucket := policy.Statement{
// Actions: set.CreateStringSet("s3:GetObject"),
// Conditions: nil,
// Effect: "Allow",
// Principal: policy.User{AWS: set.CreateStringSet("*")},
// Resources: set.CreateStringSet(fmt.Sprintf("arn:aws:s3:::%s/*", VerificationBucket),
// fmt.Sprintf("arn:aws:s3:::%s", VerificationBucket)),
// Sid: "sharing-bucket",
// }
//
// p := policy.BucketAccessPolicy{Version: "2012-10-17", Statements: []policy.Statement{
// policyConsoleStatement,
// policyServiceAccount,
// policySharingBucket,
// }}
//
// outPolicy, err := json.Marshal(&p)
// if r.err(err) {
// return err
// }
//
// err = r.s3.SetBucketPolicy(ctx, VerificationBucket, string(outPolicy))
// if r.err(err) {
// return err
// }
//}
2023-06-12 14:19:10 +00:00
return nil
}
func (r *VerificationRepository) Insert(
ctx context.Context,
userID string,
record *models.Verification,
innFH, ruleFH, egruleFH, certFH *multipart.FileHeader) (*models.Verification, error) {
now := time.Now()
record.ID = primitive.NewObjectIDFromTimestamp(now).Hex()
record.UpdatedAt = now
// Put inn file
inn, err := innFH.Open()
if r.err(err) {
return nil, err
}
_, err = r.s3.PutObject(ctx, VerificationBucket, fmt.Sprintf("%s/%s", userID, innFH.Filename), inn, innFH.Size, minio.PutObjectOptions{})
if r.err(err) {
return nil, err
}
rule, err := ruleFH.Open()
if r.err(err) {
return nil, err
}
// Put rule file
_, err = r.s3.PutObject(ctx, VerificationBucket, fmt.Sprintf("%s/%s", userID, ruleFH.Filename), rule, ruleFH.Size, minio.PutObjectOptions{})
if r.err(err) {
return nil, err
}
// Put egrule file
egrule, err := egruleFH.Open()
if r.err(err) {
return nil, err
}
_, err = r.s3.PutObject(ctx, VerificationBucket, fmt.Sprintf("%s/%s", userID, egruleFH.Filename), egrule, egruleFH.Size, minio.PutObjectOptions{})
if r.err(err) {
return nil, err
}
// Put certificate file
if certFH != nil {
cert, err := certFH.Open()
if r.err(err) {
return nil, err
}
_, err = r.s3.PutObject(ctx, VerificationBucket, fmt.Sprintf("%s/%s", userID, certFH.Filename), cert, certFH.Size, minio.PutObjectOptions{})
if r.err(err) {
return nil, err
}
record.Files = []models.VerificationFile{
2023-06-12 14:19:10 +00:00
{
Name: "certificate",
Url: fmt.Sprintf("%s/%s/%s/%s", VerificationEndpointURL, VerificationBucket, userID, certFH.Filename),
2023-06-12 14:19:10 +00:00
},
}
}
// Insert to MongoDB
record.Files = append(record.Files, []models.VerificationFile{
2023-06-12 14:19:10 +00:00
{
Name: "inn",
Url: fmt.Sprintf("%s/%s/%s/%s", VerificationEndpointURL, VerificationBucket, userID, innFH.Filename),
2023-06-12 14:19:10 +00:00
},
{
Name: "rule",
Url: fmt.Sprintf("%s/%s/%s/%s", VerificationEndpointURL, VerificationBucket, userID, ruleFH.Filename),
2023-06-12 14:19:10 +00:00
},
{
Name: "egrule",
Url: fmt.Sprintf("%s/%s/%s/%s", VerificationEndpointURL, VerificationBucket, userID, egruleFH.Filename),
2023-06-12 14:19:10 +00:00
},
}...)
result, err := r.mongo.InsertOne(ctx, record)
if r.err(err) {
return nil, err
}
record.ID = result.InsertedID.(string)
return record, nil
}
func (r *VerificationRepository) GetByUserID(ctx context.Context, userID string) (*models.Verification, error) {
2023-06-12 14:19:10 +00:00
if userID == "" {
err := errors.New("userID cannot be empty")
r.logger.Error("VerificationRepositoryError", zap.Error(err))
return nil, err
}
filter := bson.M{
"user_id": userID,
}
opts := options.FindOne().SetSort(bson.D{{Key: "updated_at", Value: -1}})
2023-06-12 14:19:10 +00:00
var result models.Verification
err := r.mongo.FindOne(ctx, filter, opts).Decode(&result)
2023-06-12 14:19:10 +00:00
if err != nil {
if err == mongo.ErrNoDocuments {
return nil, nil
}
r.logger.Error("VerificationRepositoryError", zap.Error(err))
return nil, err
}
return &result, nil
}
func (r *VerificationRepository) Get(ctx context.Context, id string) (*models.Verification, error) {
if id == "" {
err := errors.New("_id cannot be empty")
r.logger.Error("VerificationRepositoryError", zap.Error(err))
return nil, err
}
filter := bson.M{
"_id": id,
}
var result models.Verification
err := r.mongo.FindOne(ctx, filter).Decode(&result)
if err != nil {
if err == mongo.ErrNoDocuments {
return nil, nil
}
r.logger.Error("VerificationRepositoryError", zap.Error(err))
return nil, err
}
return &result, nil
}
func (r *VerificationRepository) Update(ctx context.Context, record *models.Verification) (*models.Verification, error) {
record.UpdatedAt = time.Now()
2024-02-11 13:03:28 +00:00
test := models.VerificationUpdate{
2024-02-09 16:38:56 +00:00
UserID: record.UserID,
Accepted: record.Accepted,
Status: record.Status,
UpdatedAt: record.UpdatedAt,
Comment: record.Comment,
Files: record.Files,
TaxNumber: record.TaxNumber,
}
2024-02-11 13:03:28 +00:00
objId, _ := primitive.ObjectIDFromHex(record.ID)
2024-02-09 16:38:56 +00:00
2023-06-12 14:19:10 +00:00
var result models.Verification
2024-02-11 13:03:28 +00:00
err := r.mongo.FindOneAndUpdate(ctx, bson.M{"_id": objId}, bson.M{"$set": test}, options.FindOneAndUpdate().SetReturnDocument(options.After)).Decode(&result)
2023-06-12 14:19:10 +00:00
if r.err(err) {
2024-02-09 16:38:56 +00:00
fmt.Println(err)
2023-06-12 14:19:10 +00:00
return nil, err
}
return &result, nil
}
func (r *VerificationRepository) UpdateFile(ctx context.Context, userID, fileName string, fileHeader *multipart.FileHeader) (*models.Verification, error) {
var err error
// put file
fileReader, err := fileHeader.Open()
if r.err(err) {
return nil, err
}
_, err = r.s3.PutObject(ctx, VerificationBucket, fmt.Sprintf("%s/%s", userID, fileHeader.Filename), fileReader, fileHeader.Size, minio.PutObjectOptions{})
if r.err(err) {
return nil, 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 nil, err
}
found := false
for iterator, file := range verification.Files {
if file.Name != fileName {
continue
}
objectName := strings.ReplaceAll(file.Url, fmt.Sprintf("%v/%v/", VerificationEndpointURL, VerificationBucket), "")
if err = r.s3.RemoveObject(ctx, VerificationBucket, objectName, minio.RemoveObjectOptions{}); r.err(err) {
return nil, 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
result, err := r.Update(ctx, &models.Verification{ID: verification.ID, Files: verification.Files})
if r.err(err) {
return nil, err
}
return result, nil
}
2023-06-12 14:19:10 +00:00
func (r *VerificationRepository) err(err error) bool {
if err != nil {
r.logger.Error("VerificationRepositoryError", zap.Error(err))
return true
}
return false
}