Добавил монгу, кеширование

This commit is contained in:
urec56 2025-03-16 12:02:08 +03:00
parent 217a691264
commit ecc3dfa980
49 changed files with 2124 additions and 833 deletions

View file

@ -18,7 +18,7 @@ migrate.create:
TEST_PKGS := $(shell go list ./... | grep -v "/cmd/" | grep -v "/mocks")
test:
test: test.mock
go test -v -short -count=1 -race -coverprofile=coverage.out $(TEST_PKGS)
test.many:

View file

@ -3,6 +3,7 @@ package main
import (
"context"
"errors"
"github.com/sirupsen/logrus"
"net/http"
"os"
"os/signal"
@ -18,23 +19,22 @@ import (
)
func main() {
logrus.Info("app is starting...")
cfg := config.GetConfig()
log := logger.NewLogger(cfg)
db, err := database.InitPostgres(cfg.Psql)
db, rdb, mc, closeDBs, err := database.New(cfg, log)
if err != nil {
log.Fatalf("error occurred while database initialization: %s", err.Error())
}
defer func() {
if err = db.Close(); err != nil {
log.Error(err)
}
}()
defer closeDBs()
mdb := mc.Database(cfg.Mongo.DB)
domain.Init(log)
repo := repository.NewRepository(db, log)
serv := service.NewService(repo, cfg, log)
repo := repository.NewRepository(db, log, mdb)
serv := service.NewService(repo, cfg, log, rdb)
srv := rest.NewServer(serv, log, cfg)
go func() {

View file

@ -16,7 +16,7 @@ func main() {
log := logger.NewLogger(cfg)
db, err := database.InitPostgresSql(cfg.Psql)
db, err := database.NewPostgresSql(cfg.Psql)
if err != nil {
log.Fatalf("error occurred while database initialization: %s", err.Error())
}

View file

@ -16,7 +16,7 @@ func main() {
log := logger.NewLogger(cfg)
db, err := database.InitPostgresSql(cfg.Psql)
db, err := database.NewPostgresSql(cfg.Psql)
if err != nil {
log.Fatalf("error occurred while database initialization: %s", err.Error())
}

View file

@ -6,11 +6,13 @@ import (
)
type Config struct {
Psql Postgres
JWT JWT
Srv Server `yaml:"server"`
Mig Migrations `yaml:"migrations"`
Mode string `env:"MODE"`
Psql Postgres
Redis Redis
Mongo Mongo
JWT JWT
Srv Server `yaml:"server"`
Mig Migrations `yaml:"migrations"`
Mode string `env:"MODE"`
}
type Postgres struct {
@ -22,6 +24,19 @@ type Postgres struct {
Sslmode string `env:"DB_SSLMODE"`
}
type Redis struct {
Host string `env:"REDIS_HOST"`
Port int `env:"REDIS_PORT"`
Password string `env:"REDIS_PASS"`
DB int `env:"REDIS_DB"`
}
type Mongo struct {
Host string `env:"MONGO_HOST"`
Port int `env:"MONGO_PORT"`
DB string `env:"MONGO_DB"`
}
type JWT struct {
SecretKey []byte `env:"JWT_SECRET_KEY"`
}

11
go.mod
View file

@ -7,32 +7,43 @@ require (
github.com/go-playground/validator/v10 v10.24.0
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/golang-migrate/migrate/v4 v4.18.2
github.com/google/uuid v1.6.0
github.com/ilyakaznacheev/cleanenv v1.5.0
github.com/jackc/pgx/v5 v5.7.2
github.com/jmoiron/sqlx v1.4.0
github.com/redis/go-redis/v9 v9.7.1
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.10.0
github.com/urec56/pathparams v0.0.6
go.mongodb.org/mongo-driver/v2 v2.1.0
go.uber.org/mock v0.5.0
golang.org/x/crypto v0.33.0
)
require (
github.com/BurntSushi/toml v1.2.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
go.opentelemetry.io/otel/metric v1.32.0 // indirect
go.opentelemetry.io/otel/trace v1.32.0 // indirect
go.uber.org/atomic v1.9.0 // indirect

52
go.sum
View file

@ -8,11 +8,19 @@ github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7Oputl
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dhui/dktest v0.4.4 h1:+I4s6JRE1yGuqflzwqG+aIaMdgXIorCf5P98JnaAWa8=
github.com/dhui/dktest v0.4.4/go.mod h1:4+22R4lgsdAXrDyaH4Nqx2JEz2hLp49MqQmm9HLCQhM=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
@ -47,6 +55,12 @@ github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17w
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-migrate/migrate/v4 v4.18.2 h1:2VSCMz7x7mjyTXx3m2zPokOY82LTRgxK1yQYKo6wWQ8=
github.com/golang-migrate/migrate/v4 v4.18.2/go.mod h1:2CM6tJvn2kqPXwnXO/d3rAQYiyoIm180VsO8PRX6Rpk=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@ -67,6 +81,8 @@ github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE=
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@ -93,6 +109,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/redis/go-redis/v9 v9.7.1 h1:4LhKRCIduqXqtvCUlaq9c8bdHOkICjDMrr1+Zb3osAc=
github.com/redis/go-redis/v9 v9.7.1/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
@ -105,6 +123,17 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/urec56/pathparams v0.0.6 h1:OuCbamKVdfVtprL+arL5QUuy84R909haBHLburAAp1c=
github.com/urec56/pathparams v0.0.6/go.mod h1:EymabShlKrvvNckqTZ6zVki6wEYTQmcg41nxFtd7G8Y=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.mongodb.org/mongo-driver/v2 v2.1.0 h1:/ELnVNjmfUKDsoBisXxuJL0noR9CfeUIrP7Yt3R+egg=
go.mongodb.org/mongo-driver/v2 v2.1.0/go.mod h1:AWiLRShSrk5RHQS3AEn3RL19rqOzVq49MCpWQ3x/huI=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8=
go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
@ -117,17 +146,40 @@ go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

View file

@ -0,0 +1,48 @@
package database
import (
"github.com/jmoiron/sqlx"
"github.com/redis/go-redis/v9"
"go.mongodb.org/mongo-driver/v2/mongo"
"git.urec56.ru/urec/chat_back_go/config"
"git.urec56.ru/urec/chat_back_go/internal/logger"
)
func New(cfg config.Config, log *logger.Logger) (*sqlx.DB, *redis.Client, *mongo.Client, func(), error) {
db, err := NewPostgres(cfg.Psql)
if err != nil {
return nil, nil, nil, nil, err
}
log.Info("postgres initialized")
rdb, err := NewRedis(cfg.Redis)
if err != nil {
return nil, nil, nil, nil, err
}
log.Info("redis initialized")
mc, err := NewMongo(cfg.Mongo)
if err != nil {
return nil, nil, nil, nil, err
}
log.Info("mongo initialized")
closeDBs := func() {
if err := db.Close(); err != nil {
log.Error(err)
}
if err = rdb.Close(); err != nil {
log.Error(err)
}
if err = mc.Disconnect(nil); err != nil {
log.Error(err)
}
log.Info("dbs closed")
}
return db, rdb, mc, closeDBs, nil
}

View file

@ -1,4 +1,4 @@
package database
package mock_database
import (
"github.com/DATA-DOG/go-sqlmock"

View file

@ -0,0 +1,25 @@
package database
import (
"fmt"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
"git.urec56.ru/urec/chat_back_go/config"
)
func NewMongo(cfg config.Mongo) (*mongo.Client, error) {
opt := options.Client().ApplyURI(fmt.Sprintf("mongodb://%s:%d", cfg.Host, cfg.Port))
client, err := mongo.Connect(opt)
if err != nil {
return nil, err
}
err = client.Ping(nil, nil)
if err != nil {
return nil, err
}
return client, nil
}

View file

@ -15,7 +15,7 @@ const IntegrityErrorCode = "23505"
var IntegrityError = &pgconn.PgError{Code: IntegrityErrorCode}
func InitPostgres(cfg config.Postgres) (*sqlx.DB, error) {
func NewPostgres(cfg config.Postgres) (*sqlx.DB, error) {
db, err := sqlx.Connect(
"pgx", fmt.Sprintf(
"host=%s port=%d user=%s password=%s dbname=%s sslmode=%s",
@ -33,7 +33,7 @@ func InitPostgres(cfg config.Postgres) (*sqlx.DB, error) {
return db, nil
}
func InitPostgresSql(cfg config.Postgres) (*sql.DB, error) {
func NewPostgresSql(cfg config.Postgres) (*sql.DB, error) {
db, err := sql.Open(
"pgx", fmt.Sprintf(
"host=%s port=%d user=%s password=%s dbname=%s sslmode=%s",

View file

@ -0,0 +1,23 @@
package database
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
"git.urec56.ru/urec/chat_back_go/config"
)
func NewRedis(cfg config.Redis) (*redis.Client, error) {
rdb := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", cfg.Host, cfg.Port),
Password: cfg.Password,
DB: cfg.DB,
})
if err := rdb.Ping(context.Background()).Err(); err != nil {
return nil, err
}
return rdb, nil
}

View file

@ -5,11 +5,13 @@ import (
)
var (
UnverifiedUserError = errors.New("user is not verified")
UserNotFoundError = errors.New("user not found")
InternalServerError = errors.New("internal server error")
UserAlreadyExistsError = errors.New("user already exists")
TokenError = errors.New("invalid auth token")
HashingError = errors.New("error during password hashing")
AnyError = errors.New("any error") // for tests
UnverifiedUserError = errors.New("user is not verified")
UserNotFoundError = errors.New("user not found")
InternalServerError = errors.New("internal server error")
UserAlreadyExistsError = errors.New("user already exists")
TokenError = errors.New("invalid auth token")
HashingError = errors.New("error during password hashing")
NoKeyFoundError = errors.New("no key found")
MessageAlreadyPinnedError = errors.New("message already pinned")
AnyError = errors.New("any error") // for tests
)

View file

@ -4,8 +4,8 @@ import (
"git.urec56.ru/urec/chat_back_go/internal/logger"
)
var log logger.Log
var log *logger.Logger
func Init(l logger.Log) {
func Init(l *logger.Logger) {
log = l
}

View file

@ -5,13 +5,14 @@ import (
"go.uber.org/mock/gomock"
"testing"
mock_logger "git.urec56.ru/urec/chat_back_go/internal/logger/mocks"
"git.urec56.ru/urec/chat_back_go/config"
"git.urec56.ru/urec/chat_back_go/internal/logger"
)
func Test_Init(t *testing.T) {
c := gomock.NewController(t)
defer c.Finish()
l := mock_logger.NewMockLog(c)
l := logger.NewLogger(config.Config{Mode: "TEST"})
Init(l)

View file

@ -0,0 +1,63 @@
package domain
import (
"time"
)
type MessageRaw struct {
ID UUID `bson:"id"`
Message string `bson:"message,omitempty"`
ImageUrl string `bson:"image_url,omitempty"`
ChatID int `bson:"chat_id"`
UserID int `bson:"user_id"`
CreatedAt time.Time `bson:"created_at"`
AnswerID UUID `bson:"answer_id,omitempty"`
AnswerMessage string `bson:"answer_message,omitempty"`
AnswerImageUrl string `bson:"answer_image_url,omitempty"`
}
type Message struct {
ID UUID `json:"id"`
Message string `json:"message,omitempty"`
ImageUrl string `json:"image_url,omitempty"`
ChatID int `json:"chat_id"`
UserID int `json:"user_id"`
Username string `json:"username"`
AvatarImage string `json:"avatar_image"`
CreatedAt time.Time `json:"created_at"`
AnswerID UUID `json:"answer_id,omitempty"`
AnswerMessage string `json:"answer_message,omitempty"`
AnswerImageUrl string `json:"answer_image_url,omitempty"`
}
type SendMessage struct {
Flag string `json:"flag"`
Message string `json:"message"`
ImageUrl string `json:"image_url,omitempty"`
Answer UUID `json:"answer,omitempty"`
}
type DeleteMessage struct {
Flag string `json:"flag"`
UserID int `json:"user_id"`
ID UUID `json:"id"`
}
type EditMessage struct {
Flag string `json:"flag"`
UserID int `json:"user_id"`
ID UUID `json:"id"`
NewMessage string `json:"new_message,omitempty"`
NewImageUrl string `json:"new_image_url,omitempty"`
}
type PinMessage struct {
Flag string `json:"flag"`
ID UUID `json:"id"`
UserID int `json:"user_id"`
}
type UnpinMessage struct {
Flag string `json:"flag"`
ID UUID `json:"id"`
}

View file

@ -25,17 +25,12 @@ type User struct {
DateOfRegistration CustomDate `json:"date_of_registration" db:"date_of_registration"`
}
func (u User) MarshalJSON() ([]byte, error) {
uMap := make(map[string]any)
uMap["id"] = u.ID
uMap["username"] = u.Username
uMap["email"] = u.Email
uMap["avatar_image"] = u.AvatarImage
uMap["black_phoenix"] = u.BlackPhoenix
uMap["date_of_birth"] = u.DateOfBirth.Format(time.DateOnly)
uMap["date_of_registration"] = u.DateOfRegistration.Format(time.DateOnly)
func (u *User) UnmarshalBinary(b []byte) error {
return json.Unmarshal(b, u)
}
return json.Marshal(uMap)
func (u User) MarshalBinary() ([]byte, error) {
return json.Marshal(u)
}
type UserFilter struct {

View file

@ -32,7 +32,7 @@ func assertJSONEqual(t *testing.T, expected string, actual []byte) {
}
}
func TestUserMarshalJSON(t *testing.T) {
func TestUser_MarshalBinary(t *testing.T) {
validDate := CustomDate{Time: time.Date(1990, time.July, 10, 0, 0, 0, 0, time.UTC)}
regDate := CustomDate{Time: time.Date(2023, time.March, 15, 0, 0, 0, 0, time.UTC)}
@ -97,7 +97,7 @@ func TestUserMarshalJSON(t *testing.T) {
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
result, err := json.Marshal(tc.user)
result, err := tc.user.MarshalBinary()
if err != nil {
t.Fatalf("Ошибка сериализации: %v", err)
}
@ -107,6 +107,73 @@ func TestUserMarshalJSON(t *testing.T) {
}
}
func TestUser_UnmarshalBinary(t *testing.T) {
validDate := CustomDate{Time: time.Date(1990, time.July, 10, 0, 0, 0, 0, time.UTC)}
regDate := CustomDate{Time: time.Date(2023, time.March, 15, 0, 0, 0, 0, time.UTC)}
testTable := []struct {
name string
data string
user User
expectedUser User
}{
{
name: "ok",
data: `{
"id": 42,
"username": "alice",
"email": "alice@example.com",
"avatar_image": "https://example.com/avatar.png",
"black_phoenix": true,
"date_of_birth": "1990-07-10",
"date_of_registration": "2023-03-15"
}`,
expectedUser: User{
ID: 42,
Username: "alice",
Email: "alice@example.com",
AvatarImage: "https://example.com/avatar.png",
BlackPhoenix: true,
DateOfBirth: validDate,
DateOfRegistration: regDate,
},
},
{
name: "zero_values",
data: `{}`,
},
{
name: "special_characters",
data: `{
"id": 1,
"username": "test\"user",
"email": "test@example.com\nnewline",
"avatar_image": "https://example.com/avatar.png",
"black_phoenix": false,
"date_of_birth": "0001-01-01",
"date_of_registration": "0001-01-01"
}`,
expectedUser: User{
ID: 1,
Username: `test"user`,
Email: "test@example.com\nnewline",
AvatarImage: `https://example.com/avatar.png`,
},
},
}
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
err := tc.user.UnmarshalBinary([]byte(tc.data))
if err != nil {
t.Fatalf("Ошибка сериализации: %v", err)
}
assert.Equal(t, tc.expectedUser, tc.user)
})
}
}
func TestCustomDate_UnmarshalJSON(t *testing.T) {
testTable := []struct {
name string

61
internal/domain/uuid.go Normal file
View file

@ -0,0 +1,61 @@
package domain
import (
"github.com/google/uuid"
"go.mongodb.org/mongo-driver/v2/bson"
)
type UUID struct {
uuid.NullUUID
}
func (u UUID) IsZero() bool {
return !u.Valid
}
func (u UUID) MarshalBSONValue() (byte, []byte, error) {
if !u.Valid {
return byte(bson.TypeString), nil, nil
}
metaLen := 4
uuidWithEndLen := 37
b := make([]byte, 0, metaLen+uuidWithEndLen)
b = append(b, byte(uuidWithEndLen), 0, 0, 0)
b = append(b, u.UUID.String()...)
b = append(b, 0)
return byte(bson.TypeString), b, nil
}
func (u *UUID) UnmarshalBSONValue(_ byte, data []byte) error {
if len(data) == 0 {
u.Valid = false
return nil
}
parsed, err := uuid.ParseBytes(data[4:40]) // Удаляем метаданные строки - 4 байта длины в начале и байт конца строки в конце
if err != nil {
u.Valid = false
return err
}
u.UUID = parsed
u.Valid = true
return nil
}
func (u UUID) String() string {
if !u.Valid {
return "<nil>"
}
return u.UUID.String()
}
func GenerateUUID() UUID {
return UUID{NullUUID: uuid.NullUUID{
UUID: uuid.New(),
Valid: true,
}}
}

View file

@ -0,0 +1,133 @@
package domain
import (
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/v2/bson"
"testing"
)
func TestUUID_IsZero(t *testing.T) {
testTable := []struct {
name string
uuid UUID
expected bool
}{
{
name: "zero",
expected: true,
},
{
name: "non_zero",
uuid: UUID{NullUUID: uuid.NullUUID{Valid: true}},
expected: false,
},
}
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
res := tc.uuid.IsZero()
assert.Equal(t, tc.expected, res)
})
}
}
func TestUUID_MarshalBSONValue(t *testing.T) {
testTable := []struct {
name string
uuid UUID
expectedUuid []byte
}{
{
name: "zero",
},
{
name: "non_zero",
uuid: UUID{NullUUID: uuid.NullUUID{
UUID: [16]byte{183, 27, 35, 52, 27, 195, 79, 180, 160, 72, 9, 103, 64, 182, 247, 131},
Valid: true,
}},
expectedUuid: []byte{37, 0, 0, 0, 98, 55, 49, 98, 50, 51, 51, 52, 45, 49, 98, 99, 51, 45, 52, 102, 98, 52, 45, 97, 48, 52, 56, 45, 48, 57, 54, 55, 52, 48, 98, 54, 102, 55, 56, 51, 0},
},
}
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
typ, uid, err := tc.uuid.MarshalBSONValue()
assert.Equal(t, byte(bson.TypeString), typ)
assert.Equal(t, tc.expectedUuid, uid)
assert.Equal(t, nil, err)
})
}
}
func TestUUID_UnmarshalBSONValue(t *testing.T) {
testTable := []struct {
name string
data []byte
expectedUuid UUID
expectingErr bool
}{
{
name: "zero",
},
{
name: "valid_not_zero",
data: []byte{37, 0, 0, 0, 98, 55, 49, 98, 50, 51, 51, 52, 45, 49, 98, 99, 51, 45, 52, 102, 98, 52, 45, 97, 48, 52, 56, 45, 48, 57, 54, 55, 52, 48, 98, 54, 102, 55, 56, 51, 0},
expectedUuid: UUID{NullUUID: uuid.NullUUID{
UUID: [16]byte{183, 27, 35, 52, 27, 195, 79, 180, 160, 72, 9, 103, 64, 182, 247, 131},
Valid: true,
}},
},
{
name: "parsing_error",
data: []byte{37, 0, 0, 0, 98, 3, 55, 49, 98, 50, 51, 51, 52, 45, 49, 98, 99, 51, 45, 52, 102, 98, 52, 45, 97, 48, 52, 56, 45, 48, 57, 54, 55, 52, 48, 98, 54, 102, 55, 56, 51, 0},
expectingErr: true,
},
}
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
var uid UUID
err := uid.UnmarshalBSONValue(0, tc.data)
assert.Equal(t, tc.expectedUuid, uid)
assert.Equal(t, err != nil, tc.expectingErr)
})
}
}
func TestUUID_String(t *testing.T) {
testTable := []struct {
name string
uuid UUID
expectedUuid string
}{
{
name: "zero",
expectedUuid: "<nil>",
},
{
name: "non_zero",
uuid: UUID{NullUUID: uuid.NullUUID{
UUID: [16]byte{183, 27, 35, 52, 27, 195, 79, 180, 160, 72, 9, 103, 64, 182, 247, 131},
Valid: true,
}},
expectedUuid: "b71b2334-1bc3-4fb4-a048-096740b6f783",
},
}
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
uid := tc.uuid.String()
assert.Equal(t, tc.expectedUuid, uid)
})
}
}
func Test_GenerateUUID(t *testing.T) {
_ = GenerateUUID()
}

View file

@ -2,28 +2,25 @@ package logger
import (
log "github.com/sirupsen/logrus"
"io"
"os"
"git.urec56.ru/urec/chat_back_go/config"
)
//go:generate mockgen -source=logger.go -destination=mocks/mock.go
type Log interface {
log.FieldLogger
}
type Logger struct {
*log.Logger
}
func NewLogger(cfg config.Config) *Logger {
logger := &Logger{Logger: log.New()}
configureLogger(cfg, logger)
return logger
}
var logger *Logger
func NewLogger(cfg config.Config) *Logger {
if logger != nil {
return logger
}
logger = &Logger{Logger: log.New()}
func configureLogger(cfg config.Config, logger *Logger) {
switch cfg.Mode {
case "PROD":
logger.SetFormatter(&log.JSONFormatter{})
@ -38,10 +35,12 @@ func configureLogger(cfg config.Config, logger *Logger) {
logger.SetOutput(os.Stdout)
logger.SetLevel(log.DebugLevel)
case "TEST":
logger.SetFormatter(&log.TextFormatter{})
logger.SetOutput(os.Stdout)
logger.SetLevel(log.DebugLevel)
logger.SetOutput(io.Discard)
logger.SetLevel(log.PanicLevel)
default:
logger.Fatal("incorrect MODE was specified")
}
logger.Infof("logger initialized")
return logger
}

View file

@ -2,7 +2,6 @@ package logger
import (
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"io"
"os"
"testing"
@ -43,83 +42,16 @@ func Test_NewLogger(t *testing.T) {
name: "test",
mode: "TEST",
expectedFormatter: &log.TextFormatter{},
expectedOut: os.Stdout,
expectedLevel: log.DebugLevel,
expectedOut: io.Discard,
expectedLevel: log.PanicLevel,
},
}
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
l := NewLogger(config.Config{Mode: tc.mode})
logger := NewLogger(config.Config{Mode: tc.mode})
assert.Equal(t, tc.expectedFormatter, logger.Formatter)
assert.Equal(t, tc.expectedOut, logger.Out)
assert.Equal(t, tc.expectedLevel, logger.Level)
})
}
}
func Test_configureLogger(t *testing.T) {
testTable := []struct {
name string
mode string
expectedFormatter log.Formatter
expectedOut io.Writer
expectedLevel log.Level
exitCalled bool
}{
{
name: "prod",
mode: "PROD",
expectedFormatter: &log.JSONFormatter{},
expectedOut: os.Stdout,
expectedLevel: log.WarnLevel,
},
{
name: "stage",
mode: "STAGE",
expectedFormatter: &log.TextFormatter{},
expectedOut: os.Stdout,
expectedLevel: log.InfoLevel,
},
{
name: "dev",
mode: "DEV",
expectedFormatter: &log.TextFormatter{},
expectedOut: os.Stdout,
expectedLevel: log.DebugLevel,
},
{
name: "test",
mode: "TEST",
expectedFormatter: &log.TextFormatter{},
expectedOut: os.Stdout,
expectedLevel: log.DebugLevel,
},
{
name: "incorrect_mode",
expectedFormatter: &log.TextFormatter{},
expectedOut: os.Stderr,
expectedLevel: log.InfoLevel,
exitCalled: true,
},
}
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
logger := &Logger{Logger: log.New()}
exitCalled := false
logger.ExitFunc = func(i int) {
exitCalled = true
}
configureLogger(config.Config{Mode: tc.mode}, logger)
assert.EqualExportedValues(t, tc.expectedFormatter, logger.Formatter)
assert.EqualExportedValues(t, tc.expectedOut, logger.Out)
assert.EqualExportedValues(t, tc.expectedLevel, logger.Level)
assert.Equal(t, tc.exitCalled, exitCalled)
_ = l
})
}
}

View file

@ -1,475 +0,0 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: logger.go
//
// Generated by this command:
//
// mockgen -source=logger.go -destination=mocks/mock.go
//
// Package mock_logger is a generated GoMock package.
package mock_logger
import (
reflect "reflect"
logrus "github.com/sirupsen/logrus"
gomock "go.uber.org/mock/gomock"
)
// MockLog is a mock of Log interface.
type MockLog struct {
ctrl *gomock.Controller
recorder *MockLogMockRecorder
isgomock struct{}
}
// MockLogMockRecorder is the mock recorder for MockLog.
type MockLogMockRecorder struct {
mock *MockLog
}
// NewMockLog creates a new mock instance.
func NewMockLog(ctrl *gomock.Controller) *MockLog {
mock := &MockLog{ctrl: ctrl}
mock.recorder = &MockLogMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockLog) EXPECT() *MockLogMockRecorder {
return m.recorder
}
// Debug mocks base method.
func (m *MockLog) Debug(args ...any) {
m.ctrl.T.Helper()
varargs := []any{}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Debug", varargs...)
}
// Debug indicates an expected call of Debug.
func (mr *MockLogMockRecorder) Debug(args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Debug", reflect.TypeOf((*MockLog)(nil).Debug), args...)
}
// Debugf mocks base method.
func (m *MockLog) Debugf(format string, args ...any) {
m.ctrl.T.Helper()
varargs := []any{format}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Debugf", varargs...)
}
// Debugf indicates an expected call of Debugf.
func (mr *MockLogMockRecorder) Debugf(format any, args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]any{format}, args...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Debugf", reflect.TypeOf((*MockLog)(nil).Debugf), varargs...)
}
// Debugln mocks base method.
func (m *MockLog) Debugln(args ...any) {
m.ctrl.T.Helper()
varargs := []any{}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Debugln", varargs...)
}
// Debugln indicates an expected call of Debugln.
func (mr *MockLogMockRecorder) Debugln(args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Debugln", reflect.TypeOf((*MockLog)(nil).Debugln), args...)
}
// Error mocks base method.
func (m *MockLog) Error(args ...any) {
m.ctrl.T.Helper()
varargs := []any{}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Error", varargs...)
}
// Error indicates an expected call of Error.
func (mr *MockLogMockRecorder) Error(args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Error", reflect.TypeOf((*MockLog)(nil).Error), args...)
}
// Errorf mocks base method.
func (m *MockLog) Errorf(format string, args ...any) {
m.ctrl.T.Helper()
varargs := []any{format}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Errorf", varargs...)
}
// Errorf indicates an expected call of Errorf.
func (mr *MockLogMockRecorder) Errorf(format any, args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]any{format}, args...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Errorf", reflect.TypeOf((*MockLog)(nil).Errorf), varargs...)
}
// Errorln mocks base method.
func (m *MockLog) Errorln(args ...any) {
m.ctrl.T.Helper()
varargs := []any{}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Errorln", varargs...)
}
// Errorln indicates an expected call of Errorln.
func (mr *MockLogMockRecorder) Errorln(args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Errorln", reflect.TypeOf((*MockLog)(nil).Errorln), args...)
}
// Fatal mocks base method.
func (m *MockLog) Fatal(args ...any) {
m.ctrl.T.Helper()
varargs := []any{}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Fatal", varargs...)
}
// Fatal indicates an expected call of Fatal.
func (mr *MockLogMockRecorder) Fatal(args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Fatal", reflect.TypeOf((*MockLog)(nil).Fatal), args...)
}
// Fatalf mocks base method.
func (m *MockLog) Fatalf(format string, args ...any) {
m.ctrl.T.Helper()
varargs := []any{format}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Fatalf", varargs...)
}
// Fatalf indicates an expected call of Fatalf.
func (mr *MockLogMockRecorder) Fatalf(format any, args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]any{format}, args...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Fatalf", reflect.TypeOf((*MockLog)(nil).Fatalf), varargs...)
}
// Fatalln mocks base method.
func (m *MockLog) Fatalln(args ...any) {
m.ctrl.T.Helper()
varargs := []any{}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Fatalln", varargs...)
}
// Fatalln indicates an expected call of Fatalln.
func (mr *MockLogMockRecorder) Fatalln(args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Fatalln", reflect.TypeOf((*MockLog)(nil).Fatalln), args...)
}
// Info mocks base method.
func (m *MockLog) Info(args ...any) {
m.ctrl.T.Helper()
varargs := []any{}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Info", varargs...)
}
// Info indicates an expected call of Info.
func (mr *MockLogMockRecorder) Info(args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Info", reflect.TypeOf((*MockLog)(nil).Info), args...)
}
// Infof mocks base method.
func (m *MockLog) Infof(format string, args ...any) {
m.ctrl.T.Helper()
varargs := []any{format}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Infof", varargs...)
}
// Infof indicates an expected call of Infof.
func (mr *MockLogMockRecorder) Infof(format any, args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]any{format}, args...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Infof", reflect.TypeOf((*MockLog)(nil).Infof), varargs...)
}
// Infoln mocks base method.
func (m *MockLog) Infoln(args ...any) {
m.ctrl.T.Helper()
varargs := []any{}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Infoln", varargs...)
}
// Infoln indicates an expected call of Infoln.
func (mr *MockLogMockRecorder) Infoln(args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Infoln", reflect.TypeOf((*MockLog)(nil).Infoln), args...)
}
// Panic mocks base method.
func (m *MockLog) Panic(args ...any) {
m.ctrl.T.Helper()
varargs := []any{}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Panic", varargs...)
}
// Panic indicates an expected call of Panic.
func (mr *MockLogMockRecorder) Panic(args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Panic", reflect.TypeOf((*MockLog)(nil).Panic), args...)
}
// Panicf mocks base method.
func (m *MockLog) Panicf(format string, args ...any) {
m.ctrl.T.Helper()
varargs := []any{format}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Panicf", varargs...)
}
// Panicf indicates an expected call of Panicf.
func (mr *MockLogMockRecorder) Panicf(format any, args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]any{format}, args...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Panicf", reflect.TypeOf((*MockLog)(nil).Panicf), varargs...)
}
// Panicln mocks base method.
func (m *MockLog) Panicln(args ...any) {
m.ctrl.T.Helper()
varargs := []any{}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Panicln", varargs...)
}
// Panicln indicates an expected call of Panicln.
func (mr *MockLogMockRecorder) Panicln(args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Panicln", reflect.TypeOf((*MockLog)(nil).Panicln), args...)
}
// Print mocks base method.
func (m *MockLog) Print(args ...any) {
m.ctrl.T.Helper()
varargs := []any{}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Print", varargs...)
}
// Print indicates an expected call of Print.
func (mr *MockLogMockRecorder) Print(args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Print", reflect.TypeOf((*MockLog)(nil).Print), args...)
}
// Printf mocks base method.
func (m *MockLog) Printf(format string, args ...any) {
m.ctrl.T.Helper()
varargs := []any{format}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Printf", varargs...)
}
// Printf indicates an expected call of Printf.
func (mr *MockLogMockRecorder) Printf(format any, args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]any{format}, args...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Printf", reflect.TypeOf((*MockLog)(nil).Printf), varargs...)
}
// Println mocks base method.
func (m *MockLog) Println(args ...any) {
m.ctrl.T.Helper()
varargs := []any{}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Println", varargs...)
}
// Println indicates an expected call of Println.
func (mr *MockLogMockRecorder) Println(args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Println", reflect.TypeOf((*MockLog)(nil).Println), args...)
}
// Warn mocks base method.
func (m *MockLog) Warn(args ...any) {
m.ctrl.T.Helper()
varargs := []any{}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Warn", varargs...)
}
// Warn indicates an expected call of Warn.
func (mr *MockLogMockRecorder) Warn(args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Warn", reflect.TypeOf((*MockLog)(nil).Warn), args...)
}
// Warnf mocks base method.
func (m *MockLog) Warnf(format string, args ...any) {
m.ctrl.T.Helper()
varargs := []any{format}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Warnf", varargs...)
}
// Warnf indicates an expected call of Warnf.
func (mr *MockLogMockRecorder) Warnf(format any, args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]any{format}, args...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Warnf", reflect.TypeOf((*MockLog)(nil).Warnf), varargs...)
}
// Warning mocks base method.
func (m *MockLog) Warning(args ...any) {
m.ctrl.T.Helper()
varargs := []any{}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Warning", varargs...)
}
// Warning indicates an expected call of Warning.
func (mr *MockLogMockRecorder) Warning(args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Warning", reflect.TypeOf((*MockLog)(nil).Warning), args...)
}
// Warningf mocks base method.
func (m *MockLog) Warningf(format string, args ...any) {
m.ctrl.T.Helper()
varargs := []any{format}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Warningf", varargs...)
}
// Warningf indicates an expected call of Warningf.
func (mr *MockLogMockRecorder) Warningf(format any, args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]any{format}, args...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Warningf", reflect.TypeOf((*MockLog)(nil).Warningf), varargs...)
}
// Warningln mocks base method.
func (m *MockLog) Warningln(args ...any) {
m.ctrl.T.Helper()
varargs := []any{}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Warningln", varargs...)
}
// Warningln indicates an expected call of Warningln.
func (mr *MockLogMockRecorder) Warningln(args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Warningln", reflect.TypeOf((*MockLog)(nil).Warningln), args...)
}
// Warnln mocks base method.
func (m *MockLog) Warnln(args ...any) {
m.ctrl.T.Helper()
varargs := []any{}
for _, a := range args {
varargs = append(varargs, a)
}
m.ctrl.Call(m, "Warnln", varargs...)
}
// Warnln indicates an expected call of Warnln.
func (mr *MockLogMockRecorder) Warnln(args ...any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Warnln", reflect.TypeOf((*MockLog)(nil).Warnln), args...)
}
// WithError mocks base method.
func (m *MockLog) WithError(err error) *logrus.Entry {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "WithError", err)
ret0, _ := ret[0].(*logrus.Entry)
return ret0
}
// WithError indicates an expected call of WithError.
func (mr *MockLogMockRecorder) WithError(err any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WithError", reflect.TypeOf((*MockLog)(nil).WithError), err)
}
// WithField mocks base method.
func (m *MockLog) WithField(key string, value any) *logrus.Entry {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "WithField", key, value)
ret0, _ := ret[0].(*logrus.Entry)
return ret0
}
// WithField indicates an expected call of WithField.
func (mr *MockLogMockRecorder) WithField(key, value any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WithField", reflect.TypeOf((*MockLog)(nil).WithField), key, value)
}
// WithFields mocks base method.
func (m *MockLog) WithFields(fields logrus.Fields) *logrus.Entry {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "WithFields", fields)
ret0, _ := ret[0].(*logrus.Entry)
return ret0
}
// WithFields indicates an expected call of WithFields.
func (mr *MockLogMockRecorder) WithFields(fields any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WithFields", reflect.TypeOf((*MockLog)(nil).WithFields), fields)
}

View file

@ -0,0 +1,181 @@
package repository
import (
"errors"
"github.com/jmoiron/sqlx"
"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
"time"
"git.urec56.ru/urec/chat_back_go/internal/database"
"git.urec56.ru/urec/chat_back_go/internal/domain"
"git.urec56.ru/urec/chat_back_go/internal/logger"
)
type messageRepository struct {
db *sqlx.DB
mc *mongo.Collection
l *logger.Logger
}
type SendMessage struct {
ID domain.UUID `bson:"id"`
Message string `bson:"message,omitempty"`
ImageUrl string `bson:"image_url,omitempty"`
ChatID int `bson:"chat_id"`
UserID int `bson:"user_id"`
CreatedAt time.Time `bson:"created_at"`
AnswerID domain.UUID `bson:"answer_id,omitempty"`
AnswerMessage string `bson:"answer_message,omitempty"`
AnswerImageUrl string `bson:"answer_image_url,omitempty"`
Visibility bool `bson:"visibility"`
}
type EditMessage struct {
ID domain.UUID
Message, ImageUrl string
}
type PinMessage struct {
ChatID, UserID int
MessageID domain.UUID
}
type UnpinMessage struct {
ChatID int
MessageID domain.UUID
}
type GetSome struct {
ChatID, MessageNumberFrom, MessagesToGet int
}
func newMessageRepo(db *sqlx.DB, mdb *mongo.Database, l *logger.Logger) *messageRepository {
return &messageRepository{db: db, mc: mdb.Collection("message"), l: l}
}
func (r *messageRepository) Get(ID domain.UUID) (domain.MessageRaw, error) {
var msg domain.MessageRaw
res := r.mc.FindOne(nil, bson.M{"id": ID})
if err := res.Decode(&msg); err != nil {
r.l.Errorf("getting message: %s", err.Error())
return domain.MessageRaw{}, domain.InternalServerError
}
return msg, nil
}
func (r *messageRepository) GetByIDs(IDs []domain.UUID) ([]domain.MessageRaw, error) {
var messages []domain.MessageRaw
res, err := r.mc.Find(nil, bson.M{"visibility": true, "id": bson.M{"$in": IDs}})
if err != nil {
r.l.Errorf("getting messages by ids: %s", err.Error())
return nil, domain.InternalServerError
}
if err = res.All(nil, &messages); err != nil {
r.l.Errorf("decoding messages by ids: %s", err.Error())
return nil, domain.InternalServerError
}
return messages, nil
}
func (r *messageRepository) GetSome(messagesInfo GetSome) ([]domain.MessageRaw, error) {
var messages []domain.MessageRaw
findOptions := options.Find().SetSort(bson.M{"created_at": -1}).SetLimit(int64(messagesInfo.MessagesToGet)).SetSkip(int64(messagesInfo.MessageNumberFrom))
res, err := r.mc.Find(nil, bson.M{"visibility": true, "chat_id": messagesInfo.ChatID}, findOptions)
if err != nil {
r.l.Errorf("getting some messages: %s", err.Error())
return nil, domain.InternalServerError
}
if err = res.All(nil, &messages); err != nil {
r.l.Errorf("decoding some messages: %s", err.Error())
return nil, domain.InternalServerError
}
return messages, nil
}
func (r *messageRepository) Send(message SendMessage) (domain.UUID, error) {
message.ID = domain.GenerateUUID()
message.CreatedAt = time.Now()
message.Visibility = true
_, err := r.mc.InsertOne(nil, message)
if err != nil {
r.l.Errorf("inserting message: %s", err.Error())
return domain.UUID{}, domain.InternalServerError
}
return message.ID, nil
}
func (r *messageRepository) Delete(ID domain.UUID) error {
if _, err := r.mc.UpdateOne(nil, bson.M{"id": ID}, bson.M{"$set": bson.M{"visibility": false}}); err != nil {
r.l.Errorf("deleting message: %s", err.Error())
return domain.InternalServerError
}
_, err := r.mc.UpdateMany(nil, bson.M{"answer_id": ID}, bson.M{"$set": bson.M{"answer_message": nil, "answer_image_url": nil}})
if err != nil {
r.l.Errorf("deleting message: %s", err.Error())
return domain.InternalServerError
}
return nil
}
func (r *messageRepository) Edit(newMessage EditMessage) error {
_, err := r.mc.UpdateOne(nil, bson.M{"id": newMessage.ID}, bson.M{"$set": bson.M{"message": newMessage.Message, "image_url": newMessage.ImageUrl}})
if err != nil {
r.l.Errorf("edditing message: %s", err.Error())
return domain.InternalServerError
}
_, err = r.mc.UpdateMany(nil, bson.M{"answer_id": newMessage.ID}, bson.M{"$set": bson.M{"answer_message": newMessage.Message, "answer_image_url": newMessage.ImageUrl}})
if err != nil {
r.l.Errorf("edditing message: %s", err.Error())
return domain.InternalServerError
}
return nil
}
func (r *messageRepository) Pin(msg PinMessage) error {
query := `INSERT INTO pinned_message (chat_id, message_id, user_id) VALUES ($1, $2, $3)`
if _, err := r.db.Exec(query, msg.ChatID, msg.MessageID, msg.UserID); err != nil {
if errors.Is(err, database.IntegrityError) {
return domain.MessageAlreadyPinnedError
}
r.l.Errorf("pining message: %s", err.Error())
return domain.InternalServerError
}
return nil
}
func (r *messageRepository) Unpin(msg UnpinMessage) error {
query := `DELETE FROM pinned_message WHERE chat_id = $1 AND message_id = $2`
if _, err := r.db.Exec(query, msg.ChatID, msg.MessageID); err != nil {
r.l.Errorf("unpining message: %s", err.Error())
return domain.InternalServerError
}
return nil
}
func (r *messageRepository) GetPinnedIDs(chatID int) ([]domain.UUID, error) {
var IDs []domain.UUID
query := `SELECT message_id FROM pinned_message WHERE chat_id = $1`
if err := r.db.Select(&IDs, query, chatID); err != nil {
r.l.Errorf("getting pinned ids: %s", err.Error())
return []domain.UUID{}, domain.InternalServerError
}
return IDs, nil
}

View file

@ -0,0 +1,32 @@
package repository
import (
"github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
"go.uber.org/mock/gomock"
"testing"
"git.urec56.ru/urec/chat_back_go/config"
mock_database "git.urec56.ru/urec/chat_back_go/internal/database/mocks"
"git.urec56.ru/urec/chat_back_go/internal/logger"
)
func Test_newMessageRepo(t *testing.T) {
c := gomock.NewController(t)
defer c.Finish()
db, _, dbClose := mock_database.GetMockDBx(t)
defer dbClose()
_ = db
mc, _ := mongo.Connect(options.Client())
mdb := mc.Database("test_db")
log := logger.NewLogger(config.Config{Mode: "TEST"})
repo := newMessageRepo(db, mdb, log)
assert.Equal(t, &messageRepository{db: db, mc: mdb.Collection("message"), l: log}, repo)
}

View file

@ -14,6 +14,7 @@ import (
time "time"
domain "git.urec56.ru/urec/chat_back_go/internal/domain"
repository "git.urec56.ru/urec/chat_back_go/internal/repository"
gomock "go.uber.org/mock/gomock"
)
@ -125,6 +126,161 @@ func (m *MockChat) EXPECT() *MockChatMockRecorder {
return m.recorder
}
// MockMessage is a mock of Message interface.
type MockMessage struct {
ctrl *gomock.Controller
recorder *MockMessageMockRecorder
isgomock struct{}
}
// MockMessageMockRecorder is the mock recorder for MockMessage.
type MockMessageMockRecorder struct {
mock *MockMessage
}
// NewMockMessage creates a new mock instance.
func NewMockMessage(ctrl *gomock.Controller) *MockMessage {
mock := &MockMessage{ctrl: ctrl}
mock.recorder = &MockMessageMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockMessage) EXPECT() *MockMessageMockRecorder {
return m.recorder
}
// Delete mocks base method.
func (m *MockMessage) Delete(ID domain.UUID) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Delete", ID)
ret0, _ := ret[0].(error)
return ret0
}
// Delete indicates an expected call of Delete.
func (mr *MockMessageMockRecorder) Delete(ID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockMessage)(nil).Delete), ID)
}
// Edit mocks base method.
func (m *MockMessage) Edit(newMessage repository.EditMessage) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Edit", newMessage)
ret0, _ := ret[0].(error)
return ret0
}
// Edit indicates an expected call of Edit.
func (mr *MockMessageMockRecorder) Edit(newMessage any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Edit", reflect.TypeOf((*MockMessage)(nil).Edit), newMessage)
}
// Get mocks base method.
func (m *MockMessage) Get(ID domain.UUID) (domain.MessageRaw, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Get", ID)
ret0, _ := ret[0].(domain.MessageRaw)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Get indicates an expected call of Get.
func (mr *MockMessageMockRecorder) Get(ID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockMessage)(nil).Get), ID)
}
// GetByIDs mocks base method.
func (m *MockMessage) GetByIDs(IDs []domain.UUID) ([]domain.MessageRaw, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetByIDs", IDs)
ret0, _ := ret[0].([]domain.MessageRaw)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetByIDs indicates an expected call of GetByIDs.
func (mr *MockMessageMockRecorder) GetByIDs(IDs any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByIDs", reflect.TypeOf((*MockMessage)(nil).GetByIDs), IDs)
}
// GetPinnedIDs mocks base method.
func (m *MockMessage) GetPinnedIDs(chatID int) ([]domain.UUID, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetPinnedIDs", chatID)
ret0, _ := ret[0].([]domain.UUID)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetPinnedIDs indicates an expected call of GetPinnedIDs.
func (mr *MockMessageMockRecorder) GetPinnedIDs(chatID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPinnedIDs", reflect.TypeOf((*MockMessage)(nil).GetPinnedIDs), chatID)
}
// GetSome mocks base method.
func (m *MockMessage) GetSome(messagesInfo repository.GetSome) ([]domain.MessageRaw, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetSome", messagesInfo)
ret0, _ := ret[0].([]domain.MessageRaw)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetSome indicates an expected call of GetSome.
func (mr *MockMessageMockRecorder) GetSome(messagesInfo any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSome", reflect.TypeOf((*MockMessage)(nil).GetSome), messagesInfo)
}
// Pin mocks base method.
func (m *MockMessage) Pin(msg repository.PinMessage) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Pin", msg)
ret0, _ := ret[0].(error)
return ret0
}
// Pin indicates an expected call of Pin.
func (mr *MockMessageMockRecorder) Pin(msg any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Pin", reflect.TypeOf((*MockMessage)(nil).Pin), msg)
}
// Send mocks base method.
func (m *MockMessage) Send(message repository.SendMessage) (domain.UUID, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Send", message)
ret0, _ := ret[0].(domain.UUID)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Send indicates an expected call of Send.
func (mr *MockMessageMockRecorder) Send(message any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Send", reflect.TypeOf((*MockMessage)(nil).Send), message)
}
// Unpin mocks base method.
func (m *MockMessage) Unpin(msg repository.UnpinMessage) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Unpin", msg)
ret0, _ := ret[0].(error)
return ret0
}
// Unpin indicates an expected call of Unpin.
func (mr *MockMessageMockRecorder) Unpin(msg any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unpin", reflect.TypeOf((*MockMessage)(nil).Unpin), msg)
}
// MockRepo is a mock of Repo interface.
type MockRepo struct {
ctrl *gomock.Controller
@ -149,6 +305,34 @@ func (m *MockRepo) EXPECT() *MockRepoMockRecorder {
return m.recorder
}
// Delete mocks base method.
func (m *MockRepo) Delete(ID domain.UUID) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Delete", ID)
ret0, _ := ret[0].(error)
return ret0
}
// Delete indicates an expected call of Delete.
func (mr *MockRepoMockRecorder) Delete(ID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockRepo)(nil).Delete), ID)
}
// Edit mocks base method.
func (m *MockRepo) Edit(newMessage repository.EditMessage) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Edit", newMessage)
ret0, _ := ret[0].(error)
return ret0
}
// Edit indicates an expected call of Edit.
func (mr *MockRepoMockRecorder) Edit(newMessage any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Edit", reflect.TypeOf((*MockRepo)(nil).Edit), newMessage)
}
// FindOne mocks base method.
func (m *MockRepo) FindOne(username, email string) (domain.User, error) {
m.ctrl.T.Helper()
@ -164,6 +348,21 @@ func (mr *MockRepoMockRecorder) FindOne(username, email any) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockRepo)(nil).FindOne), username, email)
}
// Get mocks base method.
func (m *MockRepo) Get(ID domain.UUID) (domain.MessageRaw, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Get", ID)
ret0, _ := ret[0].(domain.MessageRaw)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Get indicates an expected call of Get.
func (mr *MockRepoMockRecorder) Get(ID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockRepo)(nil).Get), ID)
}
// GetAll mocks base method.
func (m *MockRepo) GetAll(username string) ([]domain.User, error) {
m.ctrl.T.Helper()
@ -194,6 +393,65 @@ func (mr *MockRepoMockRecorder) GetByID(userID any) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockRepo)(nil).GetByID), userID)
}
// GetByIDs mocks base method.
func (m *MockRepo) GetByIDs(IDs []domain.UUID) ([]domain.MessageRaw, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetByIDs", IDs)
ret0, _ := ret[0].([]domain.MessageRaw)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetByIDs indicates an expected call of GetByIDs.
func (mr *MockRepoMockRecorder) GetByIDs(IDs any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByIDs", reflect.TypeOf((*MockRepo)(nil).GetByIDs), IDs)
}
// GetPinnedIDs mocks base method.
func (m *MockRepo) GetPinnedIDs(chatID int) ([]domain.UUID, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetPinnedIDs", chatID)
ret0, _ := ret[0].([]domain.UUID)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetPinnedIDs indicates an expected call of GetPinnedIDs.
func (mr *MockRepoMockRecorder) GetPinnedIDs(chatID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPinnedIDs", reflect.TypeOf((*MockRepo)(nil).GetPinnedIDs), chatID)
}
// GetSome mocks base method.
func (m *MockRepo) GetSome(messagesInfo repository.GetSome) ([]domain.MessageRaw, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetSome", messagesInfo)
ret0, _ := ret[0].([]domain.MessageRaw)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetSome indicates an expected call of GetSome.
func (mr *MockRepoMockRecorder) GetSome(messagesInfo any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSome", reflect.TypeOf((*MockRepo)(nil).GetSome), messagesInfo)
}
// Pin mocks base method.
func (m *MockRepo) Pin(msg repository.PinMessage) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Pin", msg)
ret0, _ := ret[0].(error)
return ret0
}
// Pin indicates an expected call of Pin.
func (mr *MockRepoMockRecorder) Pin(msg any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Pin", reflect.TypeOf((*MockRepo)(nil).Pin), msg)
}
// Register mocks base method.
func (m *MockRepo) Register(email, hashedPassword, username string, dateOfBirth time.Time) (domain.User, error) {
m.ctrl.T.Helper()
@ -208,3 +466,32 @@ func (mr *MockRepoMockRecorder) Register(email, hashedPassword, username, dateOf
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Register", reflect.TypeOf((*MockRepo)(nil).Register), email, hashedPassword, username, dateOfBirth)
}
// Send mocks base method.
func (m *MockRepo) Send(message repository.SendMessage) (domain.UUID, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Send", message)
ret0, _ := ret[0].(domain.UUID)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Send indicates an expected call of Send.
func (mr *MockRepoMockRecorder) Send(message any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Send", reflect.TypeOf((*MockRepo)(nil).Send), message)
}
// Unpin mocks base method.
func (m *MockRepo) Unpin(msg repository.UnpinMessage) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Unpin", msg)
ret0, _ := ret[0].(error)
return ret0
}
// Unpin indicates an expected call of Unpin.
func (mr *MockRepoMockRecorder) Unpin(msg any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unpin", reflect.TypeOf((*MockRepo)(nil).Unpin), msg)
}

View file

@ -2,6 +2,7 @@ package repository
import (
"github.com/jmoiron/sqlx"
"go.mongodb.org/mongo-driver/v2/mongo"
"time"
"git.urec56.ru/urec/chat_back_go/internal/domain"
@ -19,18 +20,33 @@ type User interface {
type Chat interface{}
type Message interface {
Get(ID domain.UUID) (domain.MessageRaw, error)
GetByIDs(IDs []domain.UUID) ([]domain.MessageRaw, error)
GetSome(messagesInfo GetSome) ([]domain.MessageRaw, error)
Send(message SendMessage) (domain.UUID, error)
Delete(ID domain.UUID) error
Edit(newMessage EditMessage) error
Pin(msg PinMessage) error
Unpin(msg UnpinMessage) error
GetPinnedIDs(chatID int) ([]domain.UUID, error)
}
type Repo interface {
User
Chat
Message
}
type Repository struct {
User
Chat
Message
}
func NewRepository(db *sqlx.DB, l logger.Log) *Repository {
func NewRepository(db *sqlx.DB, l *logger.Logger, mdb *mongo.Database) *Repository {
return &Repository{
User: newUser(db, l),
User: newUserRepo(db, l),
Message: newMessageRepo(db, mdb, l),
}
}

View file

@ -2,22 +2,35 @@ package repository
import (
"github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
"go.uber.org/mock/gomock"
"testing"
"git.urec56.ru/urec/chat_back_go/internal/database"
mock_logger "git.urec56.ru/urec/chat_back_go/internal/logger/mocks"
"git.urec56.ru/urec/chat_back_go/config"
mock_database "git.urec56.ru/urec/chat_back_go/internal/database/mocks"
"git.urec56.ru/urec/chat_back_go/internal/logger"
)
func Test_NewRepository(t *testing.T) {
c := gomock.NewController(t)
defer c.Finish()
db, _, dbClose := database.GetMockDBx(t)
db, _, dbClose := mock_database.GetMockDBx(t)
defer dbClose()
log := mock_logger.NewMockLog(c)
repo := NewRepository(db, log)
log := logger.NewLogger(config.Config{Mode: "TEST"})
assert.Equal(t, &Repository{User: &userRepository{db: db, l: log}}, repo)
mc, _ := mongo.Connect(options.Client())
mdb := mc.Database("test_db")
repo := NewRepository(db, log, mdb)
expected := &Repository{
User: &userRepository{db: db, l: log},
Message: &messageRepository{db: db, mc: mdb.Collection("message"), l: log},
}
assert.Equal(t, expected, repo)
}

View file

@ -16,10 +16,10 @@ import (
type userRepository struct {
db *sqlx.DB
l logger.Log
l *logger.Logger
}
func newUser(db *sqlx.DB, l logger.Log) *userRepository {
func newUserRepo(db *sqlx.DB, l *logger.Logger) *userRepository {
return &userRepository{db: db, l: l}
}

View file

@ -10,20 +10,22 @@ import (
"testing"
"time"
"git.urec56.ru/urec/chat_back_go/config"
"git.urec56.ru/urec/chat_back_go/internal/database"
mock_database "git.urec56.ru/urec/chat_back_go/internal/database/mocks"
"git.urec56.ru/urec/chat_back_go/internal/domain"
mock_logger "git.urec56.ru/urec/chat_back_go/internal/logger/mocks"
"git.urec56.ru/urec/chat_back_go/internal/logger"
)
func Test_newUser(t *testing.T) {
c := gomock.NewController(t)
defer c.Finish()
db, _, dbClose := database.GetMockDBx(t)
db, _, dbClose := mock_database.GetMockDBx(t)
defer dbClose()
log := mock_logger.NewMockLog(c)
repo := newUser(db, log)
log := logger.NewLogger(config.Config{Mode: "TEST"})
repo := newUserRepo(db, log)
assert.Equal(t, &userRepository{db: db, l: log}, repo)
}
@ -129,7 +131,7 @@ func TestUserRepository_GetByID(t *testing.T) {
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
db, mock, dbClose := database.GetMockDBx(t)
db, mock, dbClose := mock_database.GetMockDBx(t)
defer dbClose()
tc.mockBehavior(mock, tc.userID, tc.dbRows.AddRow(
@ -157,13 +159,11 @@ func TestUserRepository_GetByID(t *testing.T) {
func TestUserRepository_GetAll(t *testing.T) {
type mockBehavior func(mock sqlmock.Sqlmock, username string, rows *sqlmock.Rows, err error)
type logBehavior func(l *mock_logger.MockLog, err error)
testTable := []struct {
name string
username string
mockBehavior mockBehavior
logBehavior logBehavior
dbRows *sqlmock.Rows
dbErr error
ud domain.User
@ -175,7 +175,6 @@ func TestUserRepository_GetAll(t *testing.T) {
mockBehavior: func(mock sqlmock.Sqlmock, username string, rows *sqlmock.Rows, err error) {
mock.ExpectQuery(fmt.Sprintf(`SELECT \* FROM users WHERE username ILIKE \$1 AND role != %d`, domain.AdminUser)).WithArgs(username).WillReturnRows(rows)
},
logBehavior: func(l *mock_logger.MockLog, err error) {},
dbRows: sqlmock.NewRows(
[]string{
"id",
@ -219,9 +218,6 @@ func TestUserRepository_GetAll(t *testing.T) {
mockBehavior: func(mock sqlmock.Sqlmock, username string, rows *sqlmock.Rows, err error) {
mock.ExpectQuery(fmt.Sprintf(`SELECT \* FROM users WHERE username ILIKE \$1 AND role != %d`, domain.AdminUser)).WithArgs(username).WillReturnError(err)
},
logBehavior: func(l *mock_logger.MockLog, err error) {
l.EXPECT().Errorf("getting users: %s", err.Error())
},
dbRows: sqlmock.NewRows(
[]string{
"id",
@ -245,9 +241,8 @@ func TestUserRepository_GetAll(t *testing.T) {
c := gomock.NewController(t)
defer c.Finish()
db, mock, dbClose := database.GetMockDBx(t)
db, mock, dbClose := mock_database.GetMockDBx(t)
defer dbClose()
log := mock_logger.NewMockLog(c)
username := fmt.Sprint("%", tc.username, "%")
@ -262,7 +257,7 @@ func TestUserRepository_GetAll(t *testing.T) {
tc.ud.DateOfBirth,
tc.ud.DateOfRegistration,
), tc.dbErr)
tc.logBehavior(log, tc.dbErr)
log := logger.NewLogger(config.Config{Mode: "TEST"})
repo := &userRepository{db: db, l: log}
@ -376,7 +371,7 @@ func TestUserRepository_FindOne(t *testing.T) {
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
db, mock, dbClose := database.GetMockDBx(t)
db, mock, dbClose := mock_database.GetMockDBx(t)
defer dbClose()
tc.mockBehavior(mock, tc.username, tc.email, tc.dbRows.AddRow(
@ -412,7 +407,6 @@ func TestUserRepository_Register(t *testing.T) {
err error
}
type mockBehavior func(p mockParams)
type logBehavior func(log *mock_logger.MockLog, err error)
dbRows := sqlmock.NewRows([]string{
"id",
@ -430,7 +424,6 @@ func TestUserRepository_Register(t *testing.T) {
name string
mockParams mockParams
mockBehavior mockBehavior
logBehavior logBehavior
ud domain.User
expectedUser domain.User
expectedErr error
@ -450,7 +443,6 @@ func TestUserRepository_Register(t *testing.T) {
).WithArgs(p.userID, p.avatarImage).WillReturnResult(sqlmock.NewResult(1, 1))
p.mock.ExpectCommit()
},
logBehavior: func(log *mock_logger.MockLog, err error) {},
ud: domain.User{
ID: 1,
Role: 1,
@ -487,7 +479,6 @@ func TestUserRepository_Register(t *testing.T) {
).WithArgs(p.email, p.hashedPassword, p.username, p.dateOfBirth).WillReturnError(p.err)
p.mock.ExpectRollback()
},
logBehavior: func(log *mock_logger.MockLog, err error) {},
ud: domain.User{
ID: 1,
Role: 1,
@ -510,9 +501,6 @@ func TestUserRepository_Register(t *testing.T) {
mockBehavior: func(p mockParams) {
p.mock.ExpectBegin().WillReturnError(p.err)
},
logBehavior: func(log *mock_logger.MockLog, err error) {
log.EXPECT().Errorf("user registration: tx begin: %s", err.Error())
},
ud: domain.User{
ID: 1,
Role: 1,
@ -539,9 +527,6 @@ func TestUserRepository_Register(t *testing.T) {
).WithArgs(p.email, p.hashedPassword, p.username, p.dateOfBirth).WillReturnError(p.err)
p.mock.ExpectRollback()
},
logBehavior: func(log *mock_logger.MockLog, err error) {
log.EXPECT().Errorf("user registration: %s", err.Error())
},
ud: domain.User{
ID: 1,
Role: 1,
@ -571,9 +556,6 @@ func TestUserRepository_Register(t *testing.T) {
).WithArgs(p.userID, p.avatarImage).WillReturnError(p.err)
p.mock.ExpectRollback()
},
logBehavior: func(log *mock_logger.MockLog, err error) {
log.EXPECT().Errorf("user registration: %s", err.Error())
},
ud: domain.User{
ID: 1,
Role: 1,
@ -605,9 +587,6 @@ func TestUserRepository_Register(t *testing.T) {
// p.mock.ExpectRollback().WillReturnError(sql.ErrTxDone) // с ним падает тест тк вызов роллбека не доходит
// до драйвера и он его не регистрирует
},
logBehavior: func(log *mock_logger.MockLog, err error) {
log.EXPECT().Errorf("user registration: %s", err.Error())
},
ud: domain.User{
ID: 1,
Role: 1,
@ -634,9 +613,6 @@ func TestUserRepository_Register(t *testing.T) {
).WithArgs(p.email, p.hashedPassword, p.username, p.dateOfBirth).WillReturnError(p.err)
p.mock.ExpectRollback().WillReturnError(p.err)
},
logBehavior: func(log *mock_logger.MockLog, err error) {
log.EXPECT().Errorf("user registration: tx rollback: %s", err.Error())
},
ud: domain.User{
ID: 1,
Role: 1,
@ -657,9 +633,10 @@ func TestUserRepository_Register(t *testing.T) {
c := gomock.NewController(t)
defer c.Finish()
db, mock, dbClose := database.GetMockDBx(t)
db, mock, dbClose := mock_database.GetMockDBx(t)
defer dbClose()
log := mock_logger.NewMockLog(c)
log := logger.NewLogger(config.Config{Mode: "TEST"})
tc.mockParams.mock = mock
tc.mockParams.rows.AddRow(
@ -681,7 +658,6 @@ func TestUserRepository_Register(t *testing.T) {
tc.mockParams.userID = tc.ud.ID
tc.mockBehavior(tc.mockParams)
tc.logBehavior(log, tc.mockParams.err)
repo := &userRepository{db: db, l: log}

View file

@ -19,10 +19,10 @@ const maxBcryptPasswordLen = 72
type authService struct {
cfg config.JWT
parser Parser
l logger.Log
l *logger.Logger
}
func newAuthService(cfg config.JWT, l logger.Log) *authService {
func newAuthService(cfg config.JWT, l *logger.Logger) *authService {
return &authService{cfg: cfg, parser: jwt.NewParser(), l: l}
}

View file

@ -10,7 +10,6 @@ import (
"git.urec56.ru/urec/chat_back_go/config"
"git.urec56.ru/urec/chat_back_go/internal/domain"
"git.urec56.ru/urec/chat_back_go/internal/logger"
mock_logger "git.urec56.ru/urec/chat_back_go/internal/logger/mocks"
mock_service "git.urec56.ru/urec/chat_back_go/internal/service/mocks"
)
@ -19,7 +18,7 @@ func Test_newAuthService(t *testing.T) {
defer c.Finish()
cfg := config.JWT{}
log := mock_logger.NewMockLog(c)
log := logger.NewLogger(config.Config{Mode: "TEST"})
serv := newAuthService(cfg, log)

48
internal/service/cache.go Normal file
View file

@ -0,0 +1,48 @@
package service
import (
"context"
"encoding"
"errors"
"github.com/redis/go-redis/v9"
"time"
"git.urec56.ru/urec/chat_back_go/internal/domain"
"git.urec56.ru/urec/chat_back_go/internal/logger"
)
type cacheService struct {
l *logger.Logger
r redis.UniversalClient
}
func newCacheService(r redis.UniversalClient, l *logger.Logger) *cacheService {
return &cacheService{r: r, l: l}
}
func (c *cacheService) Get(key string, v encoding.BinaryUnmarshaler) error {
return c.GetCtx(context.Background(), key, v)
}
func (c *cacheService) GetCtx(ctx context.Context, key string, v encoding.BinaryUnmarshaler) error {
err := c.r.Get(ctx, key).Scan(v)
if err != nil {
if errors.Is(err, redis.Nil) {
return domain.NoKeyFoundError
}
c.l.Errorf("getting key %s: %s", key, err.Error())
return domain.InternalServerError
}
return nil
}
func (c *cacheService) Set(key string, v encoding.BinaryMarshaler, ex time.Duration) error {
return c.SetCtx(context.Background(), key, v, ex)
}
func (c *cacheService) SetCtx(ctx context.Context, key string, v encoding.BinaryMarshaler, ex time.Duration) error {
if err := c.r.SetEx(ctx, key, v, ex).Err(); err != nil {
return err
}
return nil
}

View file

@ -7,9 +7,9 @@ import (
type chatService struct {
repo repository.Chat
l logger.Log
l *logger.Logger
}
func newChatService(repo repository.Chat, l logger.Log) *chatService {
func newChatService(repo repository.Chat, l *logger.Logger) *chatService {
return &chatService{repo: repo, l: l}
}

View file

@ -5,7 +5,8 @@ import (
"go.uber.org/mock/gomock"
"testing"
mock_logger "git.urec56.ru/urec/chat_back_go/internal/logger/mocks"
"git.urec56.ru/urec/chat_back_go/config"
"git.urec56.ru/urec/chat_back_go/internal/logger"
mock_repository "git.urec56.ru/urec/chat_back_go/internal/repository/mocks"
)
@ -14,7 +15,7 @@ func Test_newChatService(t *testing.T) {
defer c.Finish()
repo := mock_repository.NewMockChat(c)
log := mock_logger.NewMockLog(c)
log := logger.NewLogger(config.Config{Mode: "TEST"})
serv := newChatService(repo, log)

View file

@ -0,0 +1,201 @@
package service
import (
"errors"
"git.urec56.ru/urec/chat_back_go/internal/domain"
"git.urec56.ru/urec/chat_back_go/internal/logger"
"git.urec56.ru/urec/chat_back_go/internal/repository"
)
type messageService struct {
repo repository.Message
u User
l *logger.Logger
}
func newMessageService(repo repository.Message, u User, l *logger.Logger) *messageService {
return &messageService{repo: repo, u: u, l: l}
}
func (s *messageService) AddAvatarImageAndUsernameToMessage(msgRaw domain.MessageRaw) (domain.Message, error) {
u, err := s.u.GetCachedUser(msgRaw.UserID)
if err != nil {
return domain.Message{}, domain.InternalServerError
}
return domain.Message{
ID: msgRaw.ID,
Message: msgRaw.Message,
ImageUrl: msgRaw.ImageUrl,
ChatID: msgRaw.ChatID,
UserID: msgRaw.UserID,
Username: u.Username,
AvatarImage: u.AvatarImage,
CreatedAt: msgRaw.CreatedAt,
AnswerID: msgRaw.AnswerID,
AnswerMessage: msgRaw.AnswerMessage,
AnswerImageUrl: msgRaw.AnswerImageUrl,
}, nil
}
func (s *messageService) AddAvatarImageAndUsernameToMessages(msgsRaw []domain.MessageRaw) []domain.Message {
msgs := make([]domain.Message, 0, len(msgsRaw))
for _, v := range msgsRaw {
msg, err := s.AddAvatarImageAndUsernameToMessage(v)
if err != nil {
continue
}
msgs = append(msgs, msg)
}
return msgs
}
func (s *messageService) GetMessage(ID domain.UUID) (domain.Message, error) {
rawMessage, err := s.GetRaw(ID)
if err != nil {
s.l.Infof("error getting message: %s", err.Error())
return domain.Message{}, domain.InternalServerError
}
newMessage, err := s.AddAvatarImageAndUsernameToMessage(rawMessage)
if err != nil {
return domain.Message{}, domain.InternalServerError
}
return newMessage, nil
}
func (s *messageService) GetRaw(ID domain.UUID) (domain.MessageRaw, error) {
rawMessage, err := s.repo.Get(ID)
if err != nil {
s.l.Infof("error getting message: %s", err.Error())
return domain.MessageRaw{}, domain.InternalServerError
}
return rawMessage, nil
}
func (s *messageService) GetPinned(chatID int) ([]domain.Message, error) {
IDs, err := s.repo.GetPinnedIDs(chatID)
if err != nil {
s.l.Infof("error getting pinned ids: %s", err.Error())
return nil, domain.InternalServerError
}
rawMessages, err := s.repo.GetByIDs(IDs)
if err != nil {
s.l.Infof("error messages by ids: %s", err.Error())
return nil, domain.InternalServerError
}
messages := s.AddAvatarImageAndUsernameToMessages(rawMessages)
return messages, nil
}
func (s *messageService) GetSome(chatID, messageNumberFrom, messagesToGet int) ([]domain.Message, error) {
messagesRaw, err := s.repo.GetSome(repository.GetSome{ChatID: chatID, MessageNumberFrom: messageNumberFrom, MessagesToGet: messagesToGet})
if err != nil {
s.l.Infof("error getting some messages: %s", err.Error())
return nil, err
}
messages := s.AddAvatarImageAndUsernameToMessages(messagesRaw)
return messages, nil
}
func (s *messageService) SendMessage(userID, chatID int, message domain.SendMessage) (domain.Message, error) {
var messageID domain.UUID
var err error
if message.Answer.IsZero() {
messageID, err = s.repo.Send(repository.SendMessage{
Message: message.Message,
ImageUrl: message.ImageUrl,
ChatID: chatID,
UserID: userID,
})
if err != nil {
s.l.Infof("error sending message: %s", err.Error())
return domain.Message{}, domain.InternalServerError
}
} else {
answerMessage, err := s.GetRaw(message.Answer)
if err != nil {
s.l.Infof("error getting message: %s", err.Error())
return domain.Message{}, domain.InternalServerError
}
messageID, err = s.repo.Send(repository.SendMessage{
Message: message.Message,
ImageUrl: message.ImageUrl,
ChatID: chatID,
UserID: userID,
AnswerID: message.Answer,
AnswerMessage: answerMessage.Message,
AnswerImageUrl: answerMessage.ImageUrl,
})
if err != nil {
s.l.Infof("error sending message: %s", err.Error())
return domain.Message{}, domain.InternalServerError
}
}
newMessage, err := s.GetMessage(messageID)
if err != nil {
s.l.Infof("error getting message: %s", err.Error())
return domain.Message{}, domain.InternalServerError
}
return newMessage, nil
}
func (s *messageService) Delete(ID domain.UUID) error {
if err := s.repo.Delete(ID); err != nil {
s.l.Infof("error deleting message: %s", err.Error())
return domain.InternalServerError
}
return nil
}
func (s *messageService) Edit(ID domain.UUID, newMessage, newImageUrl string) error {
if err := s.repo.Edit(repository.EditMessage{ID: ID, Message: newMessage, ImageUrl: newImageUrl}); err != nil {
s.l.Infof("error editing message: %s", err.Error())
return domain.InternalServerError
}
return nil
}
func (s *messageService) Pin(chatID, userID int, messageID domain.UUID) (domain.Message, error) {
err := s.repo.Pin(repository.PinMessage{ChatID: chatID, UserID: userID, MessageID: messageID})
if err != nil {
if errors.Is(err, domain.MessageAlreadyPinnedError) {
return domain.Message{}, err
}
s.l.Infof("error pinning message: %s", err.Error())
return domain.Message{}, domain.InternalServerError
}
message, err := s.GetMessage(messageID)
if err != nil {
s.l.Infof("error getting message: %s", err.Error())
return domain.Message{}, domain.InternalServerError
}
return message, nil
}
func (s *messageService) Unpin(chatID int, messageID domain.UUID) error {
err := s.repo.Unpin(repository.UnpinMessage{ChatID: chatID, MessageID: messageID})
if err != nil {
s.l.Infof("error unpinning message: %s", err.Error())
return domain.InternalServerError
}
return nil
}

View file

@ -10,8 +10,11 @@
package mock_service
import (
context "context"
encoding "encoding"
http "net/http"
reflect "reflect"
time "time"
domain "git.urec56.ru/urec/chat_back_go/internal/domain"
jwt "github.com/golang-jwt/jwt/v5"
@ -87,6 +90,21 @@ func (mr *MockUserMockRecorder) GetAll(username any) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAll", reflect.TypeOf((*MockUser)(nil).GetAll), username)
}
// GetCachedUser mocks base method.
func (m *MockUser) GetCachedUser(userID int) (domain.User, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetCachedUser", userID)
ret0, _ := ret[0].(domain.User)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetCachedUser indicates an expected call of GetCachedUser.
func (mr *MockUserMockRecorder) GetCachedUser(userID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCachedUser", reflect.TypeOf((*MockUser)(nil).GetCachedUser), userID)
}
// GetVerificated mocks base method.
func (m *MockUser) GetVerificated(userID int) (domain.User, error) {
m.ctrl.T.Helper()
@ -117,6 +135,18 @@ func (mr *MockUserMockRecorder) Register(userData any) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Register", reflect.TypeOf((*MockUser)(nil).Register), userData)
}
// SetCachedUser mocks base method.
func (m *MockUser) SetCachedUser(u domain.User) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetCachedUser", u)
}
// SetCachedUser indicates an expected call of SetCachedUser.
func (mr *MockUserMockRecorder) SetCachedUser(u any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetCachedUser", reflect.TypeOf((*MockUser)(nil).SetCachedUser), u)
}
// MockAuth is a mock of Auth interface.
type MockAuth struct {
ctrl *gomock.Controller
@ -239,6 +269,271 @@ func (m *MockChat) EXPECT() *MockChatMockRecorder {
return m.recorder
}
// MockMessages is a mock of Messages interface.
type MockMessages struct {
ctrl *gomock.Controller
recorder *MockMessagesMockRecorder
isgomock struct{}
}
// MockMessagesMockRecorder is the mock recorder for MockMessages.
type MockMessagesMockRecorder struct {
mock *MockMessages
}
// NewMockMessages creates a new mock instance.
func NewMockMessages(ctrl *gomock.Controller) *MockMessages {
mock := &MockMessages{ctrl: ctrl}
mock.recorder = &MockMessagesMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockMessages) EXPECT() *MockMessagesMockRecorder {
return m.recorder
}
// AddAvatarImageAndUsernameToMessage mocks base method.
func (m *MockMessages) AddAvatarImageAndUsernameToMessage(msgRaw domain.MessageRaw) (domain.Message, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddAvatarImageAndUsernameToMessage", msgRaw)
ret0, _ := ret[0].(domain.Message)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// AddAvatarImageAndUsernameToMessage indicates an expected call of AddAvatarImageAndUsernameToMessage.
func (mr *MockMessagesMockRecorder) AddAvatarImageAndUsernameToMessage(msgRaw any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddAvatarImageAndUsernameToMessage", reflect.TypeOf((*MockMessages)(nil).AddAvatarImageAndUsernameToMessage), msgRaw)
}
// AddAvatarImageAndUsernameToMessages mocks base method.
func (m *MockMessages) AddAvatarImageAndUsernameToMessages(msgsRaw []domain.MessageRaw) []domain.Message {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddAvatarImageAndUsernameToMessages", msgsRaw)
ret0, _ := ret[0].([]domain.Message)
return ret0
}
// AddAvatarImageAndUsernameToMessages indicates an expected call of AddAvatarImageAndUsernameToMessages.
func (mr *MockMessagesMockRecorder) AddAvatarImageAndUsernameToMessages(msgsRaw any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddAvatarImageAndUsernameToMessages", reflect.TypeOf((*MockMessages)(nil).AddAvatarImageAndUsernameToMessages), msgsRaw)
}
// Delete mocks base method.
func (m *MockMessages) Delete(ID domain.UUID) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Delete", ID)
ret0, _ := ret[0].(error)
return ret0
}
// Delete indicates an expected call of Delete.
func (mr *MockMessagesMockRecorder) Delete(ID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockMessages)(nil).Delete), ID)
}
// Edit mocks base method.
func (m *MockMessages) Edit(ID domain.UUID, newMessage, newImageUrl string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Edit", ID, newMessage, newImageUrl)
ret0, _ := ret[0].(error)
return ret0
}
// Edit indicates an expected call of Edit.
func (mr *MockMessagesMockRecorder) Edit(ID, newMessage, newImageUrl any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Edit", reflect.TypeOf((*MockMessages)(nil).Edit), ID, newMessage, newImageUrl)
}
// GetMessage mocks base method.
func (m *MockMessages) GetMessage(ID domain.UUID) (domain.Message, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetMessage", ID)
ret0, _ := ret[0].(domain.Message)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetMessage indicates an expected call of GetMessage.
func (mr *MockMessagesMockRecorder) GetMessage(ID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMessage", reflect.TypeOf((*MockMessages)(nil).GetMessage), ID)
}
// GetPinned mocks base method.
func (m *MockMessages) GetPinned(chatID int) ([]domain.Message, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetPinned", chatID)
ret0, _ := ret[0].([]domain.Message)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetPinned indicates an expected call of GetPinned.
func (mr *MockMessagesMockRecorder) GetPinned(chatID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPinned", reflect.TypeOf((*MockMessages)(nil).GetPinned), chatID)
}
// GetRaw mocks base method.
func (m *MockMessages) GetRaw(ID domain.UUID) (domain.MessageRaw, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetRaw", ID)
ret0, _ := ret[0].(domain.MessageRaw)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetRaw indicates an expected call of GetRaw.
func (mr *MockMessagesMockRecorder) GetRaw(ID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRaw", reflect.TypeOf((*MockMessages)(nil).GetRaw), ID)
}
// GetSome mocks base method.
func (m *MockMessages) GetSome(chatID, messageNumberFrom, messagesToGet int) ([]domain.Message, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetSome", chatID, messageNumberFrom, messagesToGet)
ret0, _ := ret[0].([]domain.Message)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetSome indicates an expected call of GetSome.
func (mr *MockMessagesMockRecorder) GetSome(chatID, messageNumberFrom, messagesToGet any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSome", reflect.TypeOf((*MockMessages)(nil).GetSome), chatID, messageNumberFrom, messagesToGet)
}
// Pin mocks base method.
func (m *MockMessages) Pin(chatID, userID int, messageID domain.UUID) (domain.Message, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Pin", chatID, userID, messageID)
ret0, _ := ret[0].(domain.Message)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Pin indicates an expected call of Pin.
func (mr *MockMessagesMockRecorder) Pin(chatID, userID, messageID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Pin", reflect.TypeOf((*MockMessages)(nil).Pin), chatID, userID, messageID)
}
// SendMessage mocks base method.
func (m *MockMessages) SendMessage(userID, chatID int, message domain.SendMessage) (domain.Message, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SendMessage", userID, chatID, message)
ret0, _ := ret[0].(domain.Message)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SendMessage indicates an expected call of SendMessage.
func (mr *MockMessagesMockRecorder) SendMessage(userID, chatID, message any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMessage", reflect.TypeOf((*MockMessages)(nil).SendMessage), userID, chatID, message)
}
// Unpin mocks base method.
func (m *MockMessages) Unpin(chatID int, messageID domain.UUID) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Unpin", chatID, messageID)
ret0, _ := ret[0].(error)
return ret0
}
// Unpin indicates an expected call of Unpin.
func (mr *MockMessagesMockRecorder) Unpin(chatID, messageID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unpin", reflect.TypeOf((*MockMessages)(nil).Unpin), chatID, messageID)
}
// MockCache is a mock of Cache interface.
type MockCache struct {
ctrl *gomock.Controller
recorder *MockCacheMockRecorder
isgomock struct{}
}
// MockCacheMockRecorder is the mock recorder for MockCache.
type MockCacheMockRecorder struct {
mock *MockCache
}
// NewMockCache creates a new mock instance.
func NewMockCache(ctrl *gomock.Controller) *MockCache {
mock := &MockCache{ctrl: ctrl}
mock.recorder = &MockCacheMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockCache) EXPECT() *MockCacheMockRecorder {
return m.recorder
}
// Get mocks base method.
func (m *MockCache) Get(key string, v encoding.BinaryUnmarshaler) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Get", key, v)
ret0, _ := ret[0].(error)
return ret0
}
// Get indicates an expected call of Get.
func (mr *MockCacheMockRecorder) Get(key, v any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockCache)(nil).Get), key, v)
}
// GetCtx mocks base method.
func (m *MockCache) GetCtx(ctx context.Context, key string, v encoding.BinaryUnmarshaler) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetCtx", ctx, key, v)
ret0, _ := ret[0].(error)
return ret0
}
// GetCtx indicates an expected call of GetCtx.
func (mr *MockCacheMockRecorder) GetCtx(ctx, key, v any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCtx", reflect.TypeOf((*MockCache)(nil).GetCtx), ctx, key, v)
}
// Set mocks base method.
func (m *MockCache) Set(key string, v encoding.BinaryMarshaler, ex time.Duration) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Set", key, v, ex)
ret0, _ := ret[0].(error)
return ret0
}
// Set indicates an expected call of Set.
func (mr *MockCacheMockRecorder) Set(key, v, ex any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockCache)(nil).Set), key, v, ex)
}
// SetCtx mocks base method.
func (m *MockCache) SetCtx(ctx context.Context, key string, v encoding.BinaryMarshaler, ex time.Duration) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SetCtx", ctx, key, v, ex)
ret0, _ := ret[0].(error)
return ret0
}
// SetCtx indicates an expected call of SetCtx.
func (mr *MockCacheMockRecorder) SetCtx(ctx, key, v, ex any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetCtx", reflect.TypeOf((*MockCache)(nil).SetCtx), ctx, key, v, ex)
}
// MockParser is a mock of Parser interface.
type MockParser struct {
ctrl *gomock.Controller
@ -462,6 +757,35 @@ func (m *MockServ) EXPECT() *MockServMockRecorder {
return m.recorder
}
// AddAvatarImageAndUsernameToMessage mocks base method.
func (m *MockServ) AddAvatarImageAndUsernameToMessage(msgRaw domain.MessageRaw) (domain.Message, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddAvatarImageAndUsernameToMessage", msgRaw)
ret0, _ := ret[0].(domain.Message)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// AddAvatarImageAndUsernameToMessage indicates an expected call of AddAvatarImageAndUsernameToMessage.
func (mr *MockServMockRecorder) AddAvatarImageAndUsernameToMessage(msgRaw any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddAvatarImageAndUsernameToMessage", reflect.TypeOf((*MockServ)(nil).AddAvatarImageAndUsernameToMessage), msgRaw)
}
// AddAvatarImageAndUsernameToMessages mocks base method.
func (m *MockServ) AddAvatarImageAndUsernameToMessages(msgsRaw []domain.MessageRaw) []domain.Message {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddAvatarImageAndUsernameToMessages", msgsRaw)
ret0, _ := ret[0].([]domain.Message)
return ret0
}
// AddAvatarImageAndUsernameToMessages indicates an expected call of AddAvatarImageAndUsernameToMessages.
func (mr *MockServMockRecorder) AddAvatarImageAndUsernameToMessages(msgsRaw any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddAvatarImageAndUsernameToMessages", reflect.TypeOf((*MockServ)(nil).AddAvatarImageAndUsernameToMessages), msgsRaw)
}
// DecodeAuthToken mocks base method.
func (m *MockServ) DecodeAuthToken(token string) (int, error) {
m.ctrl.T.Helper()
@ -477,6 +801,34 @@ func (mr *MockServMockRecorder) DecodeAuthToken(token any) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DecodeAuthToken", reflect.TypeOf((*MockServ)(nil).DecodeAuthToken), token)
}
// Delete mocks base method.
func (m *MockServ) Delete(ID domain.UUID) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Delete", ID)
ret0, _ := ret[0].(error)
return ret0
}
// Delete indicates an expected call of Delete.
func (mr *MockServMockRecorder) Delete(ID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockServ)(nil).Delete), ID)
}
// Edit mocks base method.
func (m *MockServ) Edit(ID domain.UUID, newMessage, newImageUrl string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Edit", ID, newMessage, newImageUrl)
ret0, _ := ret[0].(error)
return ret0
}
// Edit indicates an expected call of Edit.
func (mr *MockServMockRecorder) Edit(ID, newMessage, newImageUrl any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Edit", reflect.TypeOf((*MockServ)(nil).Edit), ID, newMessage, newImageUrl)
}
// EncodeAuthToken mocks base method.
func (m *MockServ) EncodeAuthToken(userID int) (string, error) {
m.ctrl.T.Helper()
@ -552,6 +904,81 @@ func (mr *MockServMockRecorder) GetAll(username any) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAll", reflect.TypeOf((*MockServ)(nil).GetAll), username)
}
// GetCachedUser mocks base method.
func (m *MockServ) GetCachedUser(userID int) (domain.User, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetCachedUser", userID)
ret0, _ := ret[0].(domain.User)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetCachedUser indicates an expected call of GetCachedUser.
func (mr *MockServMockRecorder) GetCachedUser(userID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCachedUser", reflect.TypeOf((*MockServ)(nil).GetCachedUser), userID)
}
// GetMessage mocks base method.
func (m *MockServ) GetMessage(ID domain.UUID) (domain.Message, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetMessage", ID)
ret0, _ := ret[0].(domain.Message)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetMessage indicates an expected call of GetMessage.
func (mr *MockServMockRecorder) GetMessage(ID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMessage", reflect.TypeOf((*MockServ)(nil).GetMessage), ID)
}
// GetPinned mocks base method.
func (m *MockServ) GetPinned(chatID int) ([]domain.Message, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetPinned", chatID)
ret0, _ := ret[0].([]domain.Message)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetPinned indicates an expected call of GetPinned.
func (mr *MockServMockRecorder) GetPinned(chatID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPinned", reflect.TypeOf((*MockServ)(nil).GetPinned), chatID)
}
// GetRaw mocks base method.
func (m *MockServ) GetRaw(ID domain.UUID) (domain.MessageRaw, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetRaw", ID)
ret0, _ := ret[0].(domain.MessageRaw)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetRaw indicates an expected call of GetRaw.
func (mr *MockServMockRecorder) GetRaw(ID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRaw", reflect.TypeOf((*MockServ)(nil).GetRaw), ID)
}
// GetSome mocks base method.
func (m *MockServ) GetSome(chatID, messageNumberFrom, messagesToGet int) ([]domain.Message, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetSome", chatID, messageNumberFrom, messagesToGet)
ret0, _ := ret[0].([]domain.Message)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetSome indicates an expected call of GetSome.
func (mr *MockServMockRecorder) GetSome(chatID, messageNumberFrom, messagesToGet any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSome", reflect.TypeOf((*MockServ)(nil).GetSome), chatID, messageNumberFrom, messagesToGet)
}
// GetVerificated mocks base method.
func (m *MockServ) GetVerificated(userID int) (domain.User, error) {
m.ctrl.T.Helper()
@ -582,6 +1009,21 @@ func (mr *MockServMockRecorder) HashPassword(p any) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HashPassword", reflect.TypeOf((*MockServ)(nil).HashPassword), p)
}
// Pin mocks base method.
func (m *MockServ) Pin(chatID, userID int, messageID domain.UUID) (domain.Message, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Pin", chatID, userID, messageID)
ret0, _ := ret[0].(domain.Message)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Pin indicates an expected call of Pin.
func (mr *MockServMockRecorder) Pin(chatID, userID, messageID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Pin", reflect.TypeOf((*MockServ)(nil).Pin), chatID, userID, messageID)
}
// Register mocks base method.
func (m *MockServ) Register(userData domain.UserRegister) (string, error) {
m.ctrl.T.Helper()
@ -597,6 +1039,47 @@ func (mr *MockServMockRecorder) Register(userData any) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Register", reflect.TypeOf((*MockServ)(nil).Register), userData)
}
// SendMessage mocks base method.
func (m *MockServ) SendMessage(userID, chatID int, message domain.SendMessage) (domain.Message, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SendMessage", userID, chatID, message)
ret0, _ := ret[0].(domain.Message)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SendMessage indicates an expected call of SendMessage.
func (mr *MockServMockRecorder) SendMessage(userID, chatID, message any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMessage", reflect.TypeOf((*MockServ)(nil).SendMessage), userID, chatID, message)
}
// SetCachedUser mocks base method.
func (m *MockServ) SetCachedUser(u domain.User) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetCachedUser", u)
}
// SetCachedUser indicates an expected call of SetCachedUser.
func (mr *MockServMockRecorder) SetCachedUser(u any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetCachedUser", reflect.TypeOf((*MockServ)(nil).SetCachedUser), u)
}
// Unpin mocks base method.
func (m *MockServ) Unpin(chatID int, messageID domain.UUID) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Unpin", chatID, messageID)
ret0, _ := ret[0].(error)
return ret0
}
// Unpin indicates an expected call of Unpin.
func (mr *MockServMockRecorder) Unpin(chatID, messageID any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unpin", reflect.TypeOf((*MockServ)(nil).Unpin), chatID, messageID)
}
// VerifyHashedPassword mocks base method.
func (m *MockServ) VerifyHashedPassword(p, hp string) bool {
m.ctrl.T.Helper()

View file

@ -1,8 +1,12 @@
package service
import (
"context"
"encoding"
"github.com/golang-jwt/jwt/v5"
"github.com/redis/go-redis/v9"
"net/http"
"time"
"git.urec56.ru/urec/chat_back_go/config"
"git.urec56.ru/urec/chat_back_go/internal/domain"
@ -13,6 +17,8 @@ import (
//go:generate mockgen -source=service.go -destination=mocks/mock.go
type User interface {
GetCachedUser(userID int) (domain.User, error)
SetCachedUser(u domain.User)
Get(userID int) (domain.User, error)
GetVerificated(userID int) (domain.User, error)
GetAll(username string) ([]domain.User, error)
@ -28,7 +34,27 @@ type Auth interface {
VerifyHashedPassword(p, hp string) bool
}
type Chat interface {
type Chat interface{}
type Messages interface {
AddAvatarImageAndUsernameToMessage(msgRaw domain.MessageRaw) (domain.Message, error)
AddAvatarImageAndUsernameToMessages(msgsRaw []domain.MessageRaw) []domain.Message
GetMessage(ID domain.UUID) (domain.Message, error)
GetRaw(ID domain.UUID) (domain.MessageRaw, error)
GetPinned(chatID int) ([]domain.Message, error)
GetSome(chatID, messageNumberFrom, messagesToGet int) ([]domain.Message, error)
SendMessage(userID, chatID int, message domain.SendMessage) (domain.Message, error)
Delete(ID domain.UUID) error
Edit(ID domain.UUID, newMessage, newImageUrl string) error
Pin(chatID, userID int, messageID domain.UUID) (domain.Message, error)
Unpin(chatID int, messageID domain.UUID) error
}
type Cache interface {
Get(key string, v encoding.BinaryUnmarshaler) error
GetCtx(ctx context.Context, key string, v encoding.BinaryUnmarshaler) error
Set(key string, v encoding.BinaryMarshaler, ex time.Duration) error
SetCtx(ctx context.Context, key string, v encoding.BinaryMarshaler, ex time.Duration) error
}
type Parser interface {
@ -44,19 +70,24 @@ type Service struct {
User
Auth
Chat
Messages
}
type Serv interface {
User
Auth
Chat
Messages
}
func NewService(repo repository.Repo, cfg config.Config, l logger.Log) *Service {
func NewService(repo repository.Repo, cfg config.Config, l *logger.Logger, rdb redis.UniversalClient) *Service {
c := newCacheService(rdb, l)
auth := newAuthService(cfg.JWT, l)
user := newUserService(repo, auth, l, c)
return &Service{
User: newUserService(repo, auth, l),
Auth: auth,
Chat: newChatService(repo, l),
User: user,
Auth: auth,
Chat: newChatService(repo, l),
Messages: newMessageService(repo, user, l),
}
}

View file

@ -2,12 +2,14 @@ package service
import (
"github.com/golang-jwt/jwt/v5"
"github.com/redis/go-redis/v9"
"github.com/stretchr/testify/assert"
"go.uber.org/mock/gomock"
"sync"
"testing"
"git.urec56.ru/urec/chat_back_go/config"
mock_logger "git.urec56.ru/urec/chat_back_go/internal/logger/mocks"
"git.urec56.ru/urec/chat_back_go/internal/logger"
mock_repository "git.urec56.ru/urec/chat_back_go/internal/repository/mocks"
)
@ -16,16 +18,20 @@ func Test_NewService(t *testing.T) {
defer c.Finish()
repo := mock_repository.NewMockRepo(c)
log := mock_logger.NewMockLog(c)
log := logger.NewLogger(config.Config{Mode: "TEST"})
cfg := config.Config{}
rdb := &redis.Client{}
serv := NewService(repo, cfg, log)
serv := NewService(repo, cfg, log, rdb)
cache := &cacheService{l: log, r: rdb}
auth := &authService{cfg: cfg.JWT, parser: jwt.NewParser(), l: log}
user := &userService{ur: repo, auth: auth, l: log, cache: cache, m: &sync.Map{}}
expectedServ := &Service{
User: &userService{ur: repo, auth: auth, l: log},
Auth: auth,
Chat: &chatService{repo: repo, l: log},
User: user,
Auth: auth,
Chat: &chatService{repo: repo, l: log},
Messages: &messageService{repo: repo, u: user, l: log},
}
assert.Equal(t, expectedServ, serv)
assert.EqualValues(t, expectedServ, serv)
}

View file

@ -2,6 +2,9 @@ package service
import (
"errors"
"fmt"
"sync"
"time"
"git.urec56.ru/urec/chat_back_go/internal/domain"
"git.urec56.ru/urec/chat_back_go/internal/logger"
@ -9,18 +12,61 @@ import (
)
type userService struct {
ur repository.User
auth Auth
l logger.Log
cache Cache
m *sync.Map
ur repository.User
auth Auth
l *logger.Logger
}
func newUserService(user repository.User, auth Auth, l logger.Log) *userService {
return &userService{ur: user, auth: auth, l: l}
type userCache struct {
u domain.User
expiresAt time.Time
}
func newUserService(user repository.User, auth Auth, l *logger.Logger, cache Cache) *userService {
return &userService{ur: user, auth: auth, l: l, cache: cache, m: &sync.Map{}}
}
func (s *userService) GetCachedUser(userID int) (domain.User, error) {
item, ok := s.m.Load(userID)
if ok {
if userData, ok := item.(userCache); ok && userData.expiresAt.After(time.Now()) {
return userData.u, nil
}
}
u, err := s.Get(userID)
if err != nil {
s.l.Infof("error getting user by id: %s", err.Error())
return domain.User{}, domain.UserNotFoundError
}
s.SetCachedUser(u)
return u, nil
}
func (s *userService) SetCachedUser(u domain.User) {
s.m.Store(u.ID, userCache{u: u, expiresAt: time.Now().Add(time.Minute)})
}
func (s *userService) Get(userID int) (domain.User, error) {
u, err := s.ur.GetByID(userID)
return u, err
u := domain.User{}
err := s.cache.Get(fmt.Sprintf("user: {'id': %d}", userID), &u)
if err == nil {
return u, nil
}
s.l.Infof("error getting user from cache: %s", err.Error())
u, err = s.ur.GetByID(userID)
if err != nil {
return u, err
}
if err = s.cache.Set(fmt.Sprintf("user: {'id': %d}", userID), u, time.Second*20); err != nil {
s.l.Infof("error setting user to cache: %s", err.Error())
}
return u, nil
}
func (s *userService) GetVerificated(userID int) (domain.User, error) {
@ -28,6 +74,7 @@ func (s *userService) GetVerificated(userID int) (domain.User, error) {
if err != nil {
return u, err
}
if u.Role < domain.VerificatedUser {
return u, domain.UnverifiedUserError
}

View file

@ -1,14 +1,17 @@
package service
import (
"encoding"
"errors"
"github.com/stretchr/testify/assert"
"go.uber.org/mock/gomock"
"sync"
"testing"
"time"
"git.urec56.ru/urec/chat_back_go/config"
"git.urec56.ru/urec/chat_back_go/internal/domain"
mock_logger "git.urec56.ru/urec/chat_back_go/internal/logger/mocks"
"git.urec56.ru/urec/chat_back_go/internal/logger"
mock_repository "git.urec56.ru/urec/chat_back_go/internal/repository/mocks"
mock_service "git.urec56.ru/urec/chat_back_go/internal/service/mocks"
)
@ -19,49 +22,147 @@ func Test_newUserService(t *testing.T) {
repo := mock_repository.NewMockUser(c)
auth := mock_service.NewMockAuth(c)
log := mock_logger.NewMockLog(c)
log := logger.NewLogger(config.Config{Mode: "TEST"})
cache := mock_service.NewMockCache(c)
serv := newUserService(repo, auth, log)
serv := newUserService(repo, auth, log, cache)
assert.Equal(t, &userService{ur: repo, auth: auth, l: log}, serv)
assert.EqualValues(t, &userService{ur: repo, auth: auth, l: log, cache: cache, m: &sync.Map{}}, serv)
}
func TestUserService_Get(t *testing.T) {
type mockBehavior func(r *mock_repository.MockUser, userID int, user domain.User, err error)
type repoBehavior func(r *mock_repository.MockUser, userID int, user domain.User, err error)
type cacheGetBehavior func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error)
type cacheSetBehavior func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error)
type cacheGetData struct {
container *domain.User
err error
}
type cacheSetData struct {
value domain.User
duration time.Duration
err error
}
testTable := []struct {
name string
mockBehavior mockBehavior
userID int
expectedUser domain.User
repoErr error
expectedErr error
name string
repoBehavior repoBehavior
cacheGetBehavior cacheGetBehavior
cacheSetBehavior cacheSetBehavior
cacheKey string
cacheGetData cacheGetData
cacheSetData cacheSetData
userID int
repoUser domain.User
repoErr error
logErr1 error
logErr2 error
expectedUser domain.User
expectedErr error
}{
{
name: "ok",
mockBehavior: func(r *mock_repository.MockUser, userID int, user domain.User, err error) {
name: "user_in_cache",
repoBehavior: func(r *mock_repository.MockUser, userID int, user domain.User, err error) {},
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
c.EXPECT().Get(key, gomock.Any()).DoAndReturn(
func(key string, v encoding.BinaryUnmarshaler) error { return v.UnmarshalBinary([]byte(`{"id": 1}`)) },
)
},
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {},
cacheKey: "user: {'id': 1}",
cacheGetData: cacheGetData{container: &domain.User{}},
userID: 1,
expectedUser: domain.User{ID: 1},
},
{
name: "no_user_in_cache",
repoBehavior: func(r *mock_repository.MockUser, userID int, user domain.User, err error) {
r.EXPECT().GetByID(userID).Return(user, err)
},
userID: 1,
expectedUser: domain.User{
ID: 1,
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
c.EXPECT().Get(key, gomock.Any()).Return(err)
},
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {
c.EXPECT().Set(key, v, ex).Return(err)
},
cacheKey: "user: {'id': 1}",
cacheGetData: cacheGetData{container: &domain.User{}, err: domain.NoKeyFoundError},
cacheSetData: cacheSetData{value: domain.User{ID: 1}, duration: time.Second * 20},
logErr1: domain.NoKeyFoundError,
userID: 1,
repoUser: domain.User{ID: 1},
expectedUser: domain.User{ID: 1},
},
{
name: "user_not_found",
mockBehavior: func(r *mock_repository.MockUser, userID int, user domain.User, err error) {
repoBehavior: func(r *mock_repository.MockUser, userID int, user domain.User, err error) {
r.EXPECT().GetByID(userID).Return(user, err)
},
repoErr: domain.UserNotFoundError,
expectedErr: domain.UserNotFoundError,
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
c.EXPECT().Get(key, gomock.Any()).Return(err)
},
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {},
cacheKey: "user: {'id': 1}",
cacheGetData: cacheGetData{container: &domain.User{}, err: domain.NoKeyFoundError},
logErr1: domain.NoKeyFoundError,
userID: 1,
repoErr: domain.UserNotFoundError,
expectedErr: domain.UserNotFoundError,
},
{
name: "internal_error",
mockBehavior: func(r *mock_repository.MockUser, userID int, user domain.User, err error) {
name: "cache_get_error",
repoBehavior: func(r *mock_repository.MockUser, userID int, user domain.User, err error) {
r.EXPECT().GetByID(userID).Return(user, err)
},
repoErr: domain.InternalServerError,
expectedErr: domain.InternalServerError,
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
c.EXPECT().Get(key, gomock.Any()).Return(err)
},
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {
c.EXPECT().Set(key, v, ex).Return(err)
},
cacheKey: "user: {'id': 1}",
cacheGetData: cacheGetData{container: &domain.User{}, err: domain.InternalServerError},
cacheSetData: cacheSetData{value: domain.User{ID: 1}, duration: time.Second * 20},
logErr1: domain.InternalServerError,
userID: 1,
repoUser: domain.User{ID: 1},
expectedUser: domain.User{ID: 1},
},
{
name: "cache_set_error",
repoBehavior: func(r *mock_repository.MockUser, userID int, user domain.User, err error) {
r.EXPECT().GetByID(userID).Return(user, err)
},
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
c.EXPECT().Get(key, gomock.Any()).Return(err)
},
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {
c.EXPECT().Set(key, v, ex).Return(err)
},
cacheKey: "user: {'id': 1}",
cacheGetData: cacheGetData{container: &domain.User{}, err: domain.NoKeyFoundError},
cacheSetData: cacheSetData{value: domain.User{ID: 1}, duration: time.Second * 20, err: domain.InternalServerError},
logErr1: domain.NoKeyFoundError,
logErr2: domain.InternalServerError,
userID: 1,
repoUser: domain.User{ID: 1},
expectedUser: domain.User{ID: 1},
},
{
name: "repo_error",
repoBehavior: func(r *mock_repository.MockUser, userID int, user domain.User, err error) {
r.EXPECT().GetByID(userID).Return(user, err)
},
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
c.EXPECT().Get(key, gomock.Any()).Return(err)
},
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {},
cacheKey: "user: {'id': 1}",
cacheGetData: cacheGetData{container: &domain.User{}, err: domain.NoKeyFoundError},
logErr1: domain.NoKeyFoundError,
userID: 1,
repoErr: domain.InternalServerError,
expectedErr: domain.InternalServerError,
},
}
@ -71,9 +172,13 @@ func TestUserService_Get(t *testing.T) {
defer c.Finish()
repo := mock_repository.NewMockUser(c)
serv := userService{ur: repo}
cache := mock_service.NewMockCache(c)
log := logger.NewLogger(config.Config{Mode: "TEST"})
serv := userService{ur: repo, l: log, cache: cache}
tc.mockBehavior(repo, tc.userID, tc.expectedUser, tc.repoErr)
tc.repoBehavior(repo, tc.userID, tc.repoUser, tc.repoErr)
tc.cacheGetBehavior(cache, tc.cacheKey, tc.cacheGetData.container, tc.cacheGetData.err)
tc.cacheSetBehavior(cache, tc.cacheKey, tc.cacheSetData.value, tc.cacheSetData.duration, tc.cacheSetData.err)
u, err := serv.Get(tc.userID)
@ -341,8 +446,7 @@ func TestUserService_Register(t *testing.T) {
repo := mock_repository.NewMockUser(c)
auth := mock_service.NewMockAuth(c)
log := mock_logger.NewMockLog(c)
serv := userService{ur: repo, auth: auth, l: log}
serv := userService{ur: repo, auth: auth}
tc.hashMockBehavior(auth, tc.ud.Password, tc.hp, tc.hashErr)
tc.repoMockBehavior(repo, tc.ud.Email, tc.hp, tc.ud.Username, tc.ud.DateOfBirth.Time, tc.repoUser, tc.repoErr)

View file

@ -7,9 +7,9 @@ import (
type Handler struct {
serv service.Serv
l logger.Log
l *logger.Logger
}
func NewHandler(serv service.Serv, l logger.Log) *Handler {
func NewHandler(serv service.Serv, l *logger.Logger) *Handler {
return &Handler{serv: serv, l: l}
}

View file

@ -5,7 +5,8 @@ import (
"go.uber.org/mock/gomock"
"testing"
mock_logger "git.urec56.ru/urec/chat_back_go/internal/logger/mocks"
"git.urec56.ru/urec/chat_back_go/config"
"git.urec56.ru/urec/chat_back_go/internal/logger"
mock_service "git.urec56.ru/urec/chat_back_go/internal/service/mocks"
)
@ -14,7 +15,7 @@ func Test_NewHandler(t *testing.T) {
defer c.Finish()
serv := mock_service.NewMockServ(c)
log := mock_logger.NewMockLog(c)
log := logger.NewLogger(config.Config{Mode: "TEST"})
h := NewHandler(serv, log)

View file

@ -13,22 +13,21 @@ import (
"testing"
"time"
"git.urec56.ru/urec/chat_back_go/config"
"git.urec56.ru/urec/chat_back_go/internal/domain"
mock_logger "git.urec56.ru/urec/chat_back_go/internal/logger/mocks"
"git.urec56.ru/urec/chat_back_go/internal/logger"
mock_service "git.urec56.ru/urec/chat_back_go/internal/service/mocks"
mock_http "git.urec56.ru/urec/chat_back_go/internal/transport/rest/handler/mocks"
)
func TestHandler_GetUsers(t *testing.T) {
type servBehavior func(s *mock_service.MockServ, username string, users []domain.User, err error)
type logBehavior func(l *mock_logger.MockLog, path string, err error)
testTable := []struct {
name string
username string
servBehavior servBehavior
servUsers []domain.User
servErr error
logBehavior logBehavior
logErr error
writeErr error
expectedUsers map[string][]domain.User
@ -51,7 +50,6 @@ func TestHandler_GetUsers(t *testing.T) {
DateOfRegistration: domain.CustomDate{Time: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC)},
},
},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {},
expectedUsers: map[string][]domain.User{
"users": {
{
@ -83,7 +81,6 @@ func TestHandler_GetUsers(t *testing.T) {
DateOfRegistration: domain.CustomDate{Time: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC)},
},
},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {},
expectedUsers: map[string][]domain.User{
"users": {
{
@ -104,10 +101,7 @@ func TestHandler_GetUsers(t *testing.T) {
servBehavior: func(s *mock_service.MockServ, username string, users []domain.User, err error) {
s.EXPECT().GetAll(username).Return(users, err)
},
servErr: domain.AnyError,
logBehavior: func(l *mock_logger.MockLog, path string, err error) {
l.EXPECT().Infof("[%s] getting users: %s", path, err.Error())
},
servErr: domain.AnyError,
logErr: domain.AnyError,
expectedStatusCode: http.StatusInternalServerError,
},
@ -116,9 +110,6 @@ func TestHandler_GetUsers(t *testing.T) {
servBehavior: func(s *mock_service.MockServ, username string, users []domain.User, err error) {
s.EXPECT().GetAll(username).Return(users, err)
},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {
l.EXPECT().Errorf("[%s] writing response: %s", path, err.Error())
},
logErr: domain.AnyError,
writeErr: domain.AnyError,
expectedStatusCode: http.StatusInternalServerError,
@ -131,10 +122,9 @@ func TestHandler_GetUsers(t *testing.T) {
defer c.Finish()
reqPath := "/users"
log := mock_logger.NewMockLog(c)
log := logger.NewLogger(config.Config{Mode: "TEST"})
serv := mock_service.NewMockServ(c)
tc.logBehavior(log, reqPath, tc.logErr)
tc.servBehavior(serv, tc.username, tc.servUsers, tc.servErr)
req := httptest.NewRequest(http.MethodGet, reqPath, nil)
@ -167,12 +157,10 @@ func TestHandler_GetUsers(t *testing.T) {
func TestHandler_CheckExisting(t *testing.T) {
type servBehavior func(s *mock_service.MockServ, username, email string, user domain.User, err error)
type logBehavior func(l *mock_logger.MockLog, path string, err error)
testTable := []struct {
name string
reqBody domain.UserFilter
servBehavior servBehavior
logBehavior logBehavior
servUser domain.User
servErr error
logErr error
@ -185,23 +173,18 @@ func TestHandler_CheckExisting(t *testing.T) {
servBehavior: func(s *mock_service.MockServ, username, email string, user domain.User, err error) {
s.EXPECT().FindOne(username, email).Return(user, err)
},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {},
expectedStatusCode: http.StatusOK,
},
{
name: "decoding_body_error",
servBehavior: func(s *mock_service.MockServ, username, email string, user domain.User, err error) {},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {},
isDecodeError: true,
expectedStatusCode: http.StatusUnprocessableEntity,
},
{
name: "validation_error",
reqBody: domain.UserFilter{Username: "u"},
servBehavior: func(s *mock_service.MockServ, username, email string, user domain.User, err error) {},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {
l.EXPECT().Infof("[%s] validation: %s", path, err.Error())
},
name: "validation_error",
reqBody: domain.UserFilter{Username: "u"},
servBehavior: func(s *mock_service.MockServ, username, email string, user domain.User, err error) {},
logErr: errors.New("Key: 'UserFilter.Username' Error:Field validation for 'Username' failed on the 'min' tag"),
expectedStatusCode: http.StatusUnprocessableEntity,
},
@ -211,9 +194,6 @@ func TestHandler_CheckExisting(t *testing.T) {
servBehavior: func(s *mock_service.MockServ, username, email string, user domain.User, err error) {
s.EXPECT().FindOne(username, email).Return(user, err)
},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {
l.EXPECT().Infof("[%s] serv.FindOne error: %s", path, err.Error())
},
servErr: domain.AnyError,
logErr: domain.AnyError,
expectedStatusCode: http.StatusInternalServerError,
@ -225,7 +205,6 @@ func TestHandler_CheckExisting(t *testing.T) {
servBehavior: func(s *mock_service.MockServ, username, email string, user domain.User, err error) {
s.EXPECT().FindOne(username, email).Return(user, err)
},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {},
expectedStatusCode: http.StatusConflict,
},
}
@ -236,10 +215,9 @@ func TestHandler_CheckExisting(t *testing.T) {
defer c.Finish()
reqPath := "/check_existing_user"
log := mock_logger.NewMockLog(c)
log := logger.NewLogger(config.Config{Mode: "TEST"})
serv := mock_service.NewMockServ(c)
tc.logBehavior(log, reqPath, tc.logErr)
tc.servBehavior(serv, tc.reqBody.Username, tc.reqBody.Email, tc.servUser, tc.servErr)
var body []byte
@ -279,12 +257,10 @@ func TestHandler_CheckExistingPassword(t *testing.T) {
func TestHandler_Register(t *testing.T) {
type servBehavior func(s *mock_service.MockServ, userData domain.UserRegister, token string, err error)
type logBehavior func(l *mock_logger.MockLog, path string, err error)
testTable := []struct {
name string
reqBody domain.UserRegister
servBehavior servBehavior
logBehavior logBehavior
servToken string
servErr error
logErr error
@ -305,7 +281,6 @@ func TestHandler_Register(t *testing.T) {
servBehavior: func(s *mock_service.MockServ, userData domain.UserRegister, token string, err error) {
s.EXPECT().Register(userData).Return(token, err)
},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {},
servToken: "token",
expectedStatusCode: http.StatusCreated,
expectedBody: map[string]string{"authorization": "Bearer token"},
@ -322,14 +297,12 @@ func TestHandler_Register(t *testing.T) {
servBehavior: func(s *mock_service.MockServ, userData domain.UserRegister, token string, err error) {
s.EXPECT().Register(userData).Return(token, err)
},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {},
servErr: domain.UserAlreadyExistsError,
expectedStatusCode: http.StatusConflict,
},
{
name: "decoding_body_error",
servBehavior: func(s *mock_service.MockServ, userData domain.UserRegister, token string, err error) {},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {},
isDecodeError: true,
expectedStatusCode: http.StatusUnprocessableEntity,
},
@ -341,10 +314,7 @@ func TestHandler_Register(t *testing.T) {
Password2: "password",
DateOfBirth: domain.CustomDate{Time: time.Date(2002, time.February, 2, 0, 0, 0, 0, time.UTC)},
},
servBehavior: func(s *mock_service.MockServ, userData domain.UserRegister, token string, err error) {},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {
l.EXPECT().Infof("[%s] validation: %s", path, err.Error())
},
servBehavior: func(s *mock_service.MockServ, userData domain.UserRegister, token string, err error) {},
logErr: errors.New("Key: 'UserRegister.Username' Error:Field validation for 'Username' failed on the 'min' tag"),
expectedStatusCode: http.StatusUnprocessableEntity,
},
@ -360,9 +330,6 @@ func TestHandler_Register(t *testing.T) {
servBehavior: func(s *mock_service.MockServ, userData domain.UserRegister, token string, err error) {
s.EXPECT().Register(userData).Return(token, err)
},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {
l.EXPECT().Infof("[%s] serv.Register: %s", path, err.Error())
},
servErr: domain.AnyError,
logErr: domain.AnyError,
expectedStatusCode: http.StatusInternalServerError,
@ -379,9 +346,6 @@ func TestHandler_Register(t *testing.T) {
servBehavior: func(s *mock_service.MockServ, userData domain.UserRegister, token string, err error) {
s.EXPECT().Register(userData).Return(token, err)
},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {
l.EXPECT().Errorf("[%s] writing response: %s", path, err.Error())
},
writeErr: domain.AnyError,
logErr: domain.AnyError,
expectedStatusCode: http.StatusCreated,
@ -394,10 +358,9 @@ func TestHandler_Register(t *testing.T) {
defer c.Finish()
reqPath := "/register"
log := mock_logger.NewMockLog(c)
log := logger.NewLogger(config.Config{Mode: "TEST"})
serv := mock_service.NewMockServ(c)
tc.logBehavior(log, reqPath, tc.logErr)
tc.servBehavior(serv, tc.reqBody, tc.servToken, tc.servErr)
var body []byte
@ -438,7 +401,7 @@ func TestHandler_ResendEmailVerification(t *testing.T) {
c := gomock.NewController(t)
defer c.Finish()
log := mock_logger.NewMockLog(c)
log := logger.NewLogger(config.Config{Mode: "TEST"})
serv := mock_service.NewMockServ(c)
req := httptest.NewRequest("", "/chats", nil)
@ -455,7 +418,7 @@ func TestHandler_EmailVerification(t *testing.T) {
c := gomock.NewController(t)
defer c.Finish()
log := mock_logger.NewMockLog(c)
log := logger.NewLogger(config.Config{Mode: "TEST"})
serv := mock_service.NewMockServ(c)
req := httptest.NewRequest("", "/chats", nil)
@ -472,7 +435,7 @@ func TestHandler_Login(t *testing.T) {
c := gomock.NewController(t)
defer c.Finish()
log := mock_logger.NewMockLog(c)
log := logger.NewLogger(config.Config{Mode: "TEST"})
serv := mock_service.NewMockServ(c)
req := httptest.NewRequest("", "/chats", nil)
@ -486,12 +449,10 @@ func TestHandler_Login(t *testing.T) {
}
func TestHandler_Get(t *testing.T) {
type logBehavior func(l *mock_logger.MockLog, path string, err error)
testTable := []struct {
name string
ctxUser domain.User
addingCtxUser bool
logBehavior logBehavior
logErr error
writeErr error
expectedUser domain.User
@ -509,7 +470,6 @@ func TestHandler_Get(t *testing.T) {
DateOfRegistration: domain.CustomDate{Time: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC)},
},
addingCtxUser: true,
logBehavior: func(l *mock_logger.MockLog, path string, err error) {},
expectedUser: domain.User{
ID: 1,
Username: "urec",
@ -522,10 +482,7 @@ func TestHandler_Get(t *testing.T) {
expectedStatusCode: http.StatusOK,
},
{
name: "incorrect_user_in_ctx",
logBehavior: func(l *mock_logger.MockLog, path string, err error) {
l.EXPECT().Errorf("[%s] extracting user from ctx", path)
},
name: "incorrect_user_in_ctx",
expectedStatusCode: http.StatusInternalServerError,
},
{
@ -539,10 +496,7 @@ func TestHandler_Get(t *testing.T) {
DateOfBirth: domain.CustomDate{Time: time.Date(2002, time.February, 2, 0, 0, 0, 0, time.UTC)},
DateOfRegistration: domain.CustomDate{Time: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC)},
},
addingCtxUser: true,
logBehavior: func(l *mock_logger.MockLog, path string, err error) {
l.EXPECT().Errorf("[%s] writing response: %s", path, err.Error())
},
addingCtxUser: true,
logErr: domain.AnyError,
writeErr: domain.AnyError,
expectedStatusCode: http.StatusInternalServerError,
@ -555,8 +509,7 @@ func TestHandler_Get(t *testing.T) {
defer c.Finish()
reqPath := "/users/me"
log := mock_logger.NewMockLog(c)
tc.logBehavior(log, reqPath, tc.logErr)
log := logger.NewLogger(config.Config{Mode: "TEST"})
req := httptest.NewRequest(http.MethodGet, reqPath, nil)
w := mock_http.NewRecorder(tc.writeErr)
@ -591,7 +544,7 @@ func TestHandler_GetAvatarsHistory(t *testing.T) {
c := gomock.NewController(t)
defer c.Finish()
log := mock_logger.NewMockLog(c)
log := logger.NewLogger(config.Config{Mode: "TEST"})
serv := mock_service.NewMockServ(c)
req := httptest.NewRequest("", "/chats", nil)
@ -608,7 +561,7 @@ func TestHandler_SendConfirmationCode(t *testing.T) {
c := gomock.NewController(t)
defer c.Finish()
log := mock_logger.NewMockLog(c)
log := logger.NewLogger(config.Config{Mode: "TEST"})
serv := mock_service.NewMockServ(c)
req := httptest.NewRequest("", "/chats", nil)
@ -625,7 +578,7 @@ func TestHandler_ChangeUserData(t *testing.T) {
c := gomock.NewController(t)
defer c.Finish()
log := mock_logger.NewMockLog(c)
log := logger.NewLogger(config.Config{Mode: "TEST"})
serv := mock_service.NewMockServ(c)
req := httptest.NewRequest("", "/chats", nil)

View file

@ -8,8 +8,9 @@ import (
"testing"
"time"
"git.urec56.ru/urec/chat_back_go/config"
"git.urec56.ru/urec/chat_back_go/internal/domain"
mock_logger "git.urec56.ru/urec/chat_back_go/internal/logger/mocks"
"git.urec56.ru/urec/chat_back_go/internal/logger"
mock_service "git.urec56.ru/urec/chat_back_go/internal/service/mocks"
)
@ -17,14 +18,12 @@ func TestMiddleware_Auth(t *testing.T) {
type extractBehavior func(s *mock_service.MockServ, r *http.Request, token string, err error)
type decodeBehavior func(s *mock_service.MockServ, token string, userID int, err error)
type getBehavior func(s *mock_service.MockServ, userID int, user domain.User, err error)
type logBehavior func(l *mock_logger.MockLog, path string, err error)
testTable := []struct {
name string
extractBehavior extractBehavior
decodeBehavior decodeBehavior
getBehavior getBehavior
logBehavior logBehavior
reqToken string
extractToken string
extractErr error
@ -47,7 +46,6 @@ func TestMiddleware_Auth(t *testing.T) {
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {
s.EXPECT().Get(userID).Return(user, err)
},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {},
reqToken: "Bearer token",
extractToken: "token",
decodeUserID: 1,
@ -86,7 +84,6 @@ func TestMiddleware_Auth(t *testing.T) {
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {
s.EXPECT().Get(userID).Return(user, err)
},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {},
reqToken: "Bearer token",
extractToken: "token",
getErr: domain.UserNotFoundError,
@ -97,11 +94,8 @@ func TestMiddleware_Auth(t *testing.T) {
extractBehavior: func(s *mock_service.MockServ, r *http.Request, token string, err error) {
s.EXPECT().ExtractAuthToken(r).Return(token, err)
},
decodeBehavior: func(s *mock_service.MockServ, token string, userID int, err error) {},
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {
l.EXPECT().Infof("[%s] error extracting token: %s", path, err.Error())
},
decodeBehavior: func(s *mock_service.MockServ, token string, userID int, err error) {},
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {},
extractErr: domain.AnyError,
logErr: domain.AnyError,
expectedStatusCode: http.StatusUnauthorized,
@ -114,10 +108,7 @@ func TestMiddleware_Auth(t *testing.T) {
decodeBehavior: func(s *mock_service.MockServ, token string, userID int, err error) {
s.EXPECT().DecodeAuthToken(token).Return(userID, err)
},
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {
l.EXPECT().Infof("[%s] error decoding token: %s", path, err.Error())
},
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {},
decodeErr: domain.AnyError,
logErr: domain.AnyError,
expectedStatusCode: http.StatusUnauthorized,
@ -133,9 +124,6 @@ func TestMiddleware_Auth(t *testing.T) {
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {
s.EXPECT().Get(userID).Return(user, err)
},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {
l.EXPECT().Infof("[%s] error resolving user: %s", path, err.Error())
},
getErr: domain.AnyError,
logErr: domain.AnyError,
expectedStatusCode: http.StatusInternalServerError,
@ -147,7 +135,7 @@ func TestMiddleware_Auth(t *testing.T) {
c := gomock.NewController(t)
defer c.Finish()
log := mock_logger.NewMockLog(c)
log := logger.NewLogger(config.Config{Mode: "TEST"})
serv := mock_service.NewMockServ(c)
reqPath := "/"
@ -159,7 +147,6 @@ func TestMiddleware_Auth(t *testing.T) {
tc.extractBehavior(serv, req, tc.extractToken, tc.extractErr)
tc.decodeBehavior(serv, tc.extractToken, tc.decodeUserID, tc.decodeErr)
tc.getBehavior(serv, tc.decodeUserID, tc.getUser, tc.getErr)
tc.logBehavior(log, reqPath, tc.logErr)
m := &Middleware{serv: serv, l: log}
@ -181,14 +168,12 @@ func TestMiddleware_VerificatedAuth(t *testing.T) {
type extractBehavior func(s *mock_service.MockServ, r *http.Request, token string, err error)
type decodeBehavior func(s *mock_service.MockServ, token string, userID int, err error)
type getBehavior func(s *mock_service.MockServ, userID int, user domain.User, err error)
type logBehavior func(l *mock_logger.MockLog, path string, err error)
testTable := []struct {
name string
extractBehavior extractBehavior
decodeBehavior decodeBehavior
getBehavior getBehavior
logBehavior logBehavior
reqToken string
extractToken string
extractErr error
@ -211,7 +196,6 @@ func TestMiddleware_VerificatedAuth(t *testing.T) {
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {
s.EXPECT().GetVerificated(userID).Return(user, err)
},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {},
reqToken: "Bearer token",
extractToken: "token",
decodeUserID: 1,
@ -250,7 +234,6 @@ func TestMiddleware_VerificatedAuth(t *testing.T) {
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {
s.EXPECT().GetVerificated(userID).Return(user, err)
},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {},
reqToken: "Bearer token",
extractToken: "token",
getErr: domain.UnverifiedUserError,
@ -267,7 +250,6 @@ func TestMiddleware_VerificatedAuth(t *testing.T) {
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {
s.EXPECT().GetVerificated(userID).Return(user, err)
},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {},
reqToken: "Bearer token",
extractToken: "token",
getErr: domain.UserNotFoundError,
@ -278,11 +260,8 @@ func TestMiddleware_VerificatedAuth(t *testing.T) {
extractBehavior: func(s *mock_service.MockServ, r *http.Request, token string, err error) {
s.EXPECT().ExtractAuthToken(r).Return(token, err)
},
decodeBehavior: func(s *mock_service.MockServ, token string, userID int, err error) {},
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {
l.EXPECT().Infof("[%s] error extracting token: %s", path, err.Error())
},
decodeBehavior: func(s *mock_service.MockServ, token string, userID int, err error) {},
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {},
extractErr: domain.AnyError,
logErr: domain.AnyError,
expectedStatusCode: http.StatusUnauthorized,
@ -295,10 +274,7 @@ func TestMiddleware_VerificatedAuth(t *testing.T) {
decodeBehavior: func(s *mock_service.MockServ, token string, userID int, err error) {
s.EXPECT().DecodeAuthToken(token).Return(userID, err)
},
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {
l.EXPECT().Infof("[%s] error decoding token: %s", path, err.Error())
},
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {},
decodeErr: domain.AnyError,
logErr: domain.AnyError,
expectedStatusCode: http.StatusUnauthorized,
@ -314,9 +290,6 @@ func TestMiddleware_VerificatedAuth(t *testing.T) {
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {
s.EXPECT().GetVerificated(userID).Return(user, err)
},
logBehavior: func(l *mock_logger.MockLog, path string, err error) {
l.EXPECT().Infof("[%s] error resolving user: %s", path, err.Error())
},
getErr: domain.AnyError,
logErr: domain.AnyError,
expectedStatusCode: http.StatusInternalServerError,
@ -328,7 +301,7 @@ func TestMiddleware_VerificatedAuth(t *testing.T) {
c := gomock.NewController(t)
defer c.Finish()
log := mock_logger.NewMockLog(c)
log := logger.NewLogger(config.Config{Mode: "TEST"})
serv := mock_service.NewMockServ(c)
reqPath := "/"
@ -340,7 +313,6 @@ func TestMiddleware_VerificatedAuth(t *testing.T) {
tc.extractBehavior(serv, req, tc.extractToken, tc.extractErr)
tc.decodeBehavior(serv, tc.extractToken, tc.decodeUserID, tc.decodeErr)
tc.getBehavior(serv, tc.decodeUserID, tc.getUser, tc.getErr)
tc.logBehavior(log, reqPath, tc.logErr)
m := &Middleware{serv: serv, l: log}

View file

@ -7,44 +7,33 @@ import (
"net/http/httptest"
"testing"
mock_logger "git.urec56.ru/urec/chat_back_go/internal/logger/mocks"
"git.urec56.ru/urec/chat_back_go/config"
"git.urec56.ru/urec/chat_back_go/internal/logger"
)
func TestMiddleware_Log(t *testing.T) {
type logBehavior func(l *mock_logger.MockLog, requestID any, method, url string)
testTable := []struct {
name string
requestMethod string
requestUrl string
requestID any
logBehavior logBehavior
}{
{
name: "ok_1",
requestMethod: http.MethodGet,
requestUrl: "/users",
requestID: 1,
logBehavior: func(l *mock_logger.MockLog, requestID any, method, url string) {
l.EXPECT().Infof("[%s] \"%s %s\"", requestID, method, url)
},
},
{
name: "ok_2",
requestMethod: http.MethodPost,
requestUrl: "/chat",
requestID: 10031,
logBehavior: func(l *mock_logger.MockLog, requestID any, method, url string) {
l.EXPECT().Infof("[%s] \"%s %s\"", requestID, method, url)
},
},
{
name: "ok_3",
requestMethod: http.MethodPost,
requestUrl: "/chat",
logBehavior: func(l *mock_logger.MockLog, requestID any, method, url string) {
l.EXPECT().Infof("[%s] \"%s %s\"", requestID, method, url)
},
},
}
@ -53,8 +42,7 @@ func TestMiddleware_Log(t *testing.T) {
c := gomock.NewController(t)
defer c.Finish()
log := mock_logger.NewMockLog(c)
tc.logBehavior(log, tc.requestID, tc.requestMethod, tc.requestUrl)
log := logger.NewLogger(config.Config{Mode: "TEST"})
req := httptest.NewRequest(tc.requestMethod, tc.requestUrl, nil)
w := httptest.NewRecorder()

View file

@ -8,11 +8,11 @@ import (
type Middleware struct {
serv service.Serv
l logger.Log
l *logger.Logger
cfg config.Server
reqID uint64 // 0
}
func NewMiddleware(serv service.Serv, l logger.Log, cfg config.Server) *Middleware {
func NewMiddleware(serv service.Serv, l *logger.Logger, cfg config.Server) *Middleware {
return &Middleware{serv: serv, l: l, cfg: cfg}
}

View file

@ -6,7 +6,7 @@ import (
"testing"
"git.urec56.ru/urec/chat_back_go/config"
mock_logger "git.urec56.ru/urec/chat_back_go/internal/logger/mocks"
"git.urec56.ru/urec/chat_back_go/internal/logger"
mock_service "git.urec56.ru/urec/chat_back_go/internal/service/mocks"
)
@ -15,7 +15,7 @@ func Test_NewMiddleware(t *testing.T) {
defer c.Finish()
serv := mock_service.NewMockServ(c)
log := mock_logger.NewMockLog(c)
log := logger.NewLogger(config.Config{Mode: "TEST"})
cfg := config.Server{}
m := NewMiddleware(serv, log, cfg)

View file

@ -19,7 +19,7 @@ type Server struct {
h *handler.Handler
}
func NewServer(serv service.Serv, l logger.Log, cfg config.Config) *Server {
func NewServer(serv service.Serv, l *logger.Logger, cfg config.Config) *Server {
return &Server{m: middleware.NewMiddleware(serv, l, cfg.Srv), h: handler.NewHandler(serv, l)}
}