Обновил версию go. Добавил логику в сервис

This commit is contained in:
urec56 2025-04-13 23:43:35 +03:00
parent ecc3dfa980
commit 9108da715d
29 changed files with 2023 additions and 536 deletions

View file

@ -3,12 +3,13 @@ package main
import ( import (
"context" "context"
"errors" "errors"
"github.com/sirupsen/logrus"
"net/http" "net/http"
"os" "os"
"os/signal" "os/signal"
"syscall" "syscall"
"github.com/sirupsen/logrus"
"git.urec56.ru/urec/chat_back_go/config" "git.urec56.ru/urec/chat_back_go/config"
"git.urec56.ru/urec/chat_back_go/internal/database" "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/domain"
@ -26,7 +27,7 @@ func main() {
db, rdb, mc, closeDBs, err := database.New(cfg, log) db, rdb, mc, closeDBs, err := database.New(cfg, log)
if err != nil { if err != nil {
log.Fatalf("error occurred while database initialization: %s", err.Error()) log.Fatalf("error occurred while database initialization: %s", err)
} }
defer closeDBs() defer closeDBs()
@ -39,11 +40,11 @@ func main() {
go func() { go func() {
if err = srv.Run(cfg.Srv.Port); !errors.Is(err, http.ErrServerClosed) { if err = srv.Run(cfg.Srv.Port); !errors.Is(err, http.ErrServerClosed) {
log.Fatalf("error occurred while running rest server: %s", err.Error()) log.Fatalf("error occurred while running rest server: %s", err)
} }
}() }()
log.Infof("starting server on port %s\n", cfg.Srv.Port) log.Infof("starting server on port %d\n", cfg.Srv.Port)
quit := make(chan os.Signal, 1) quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
@ -53,6 +54,6 @@ func main() {
log.Info("shutting down the server") log.Info("shutting down the server")
if err = srv.Shutdown(context.Background()); err != nil { if err = srv.Shutdown(context.Background()); err != nil {
log.Fatalf("error occurred while shutting down rest server: %s", err.Error()) log.Fatalf("error occurred while shutting down rest server: %s", err)
} }
} }

View file

@ -42,9 +42,10 @@ type JWT struct {
} }
type Server struct { type Server struct {
Port string `yaml:"port"` Port int `yaml:"port"`
RequestIDHeader string `yaml:"request_id_header"` RequestIDHeader string `yaml:"request_id_header"`
} }
type Migrations struct { type Migrations struct {
Folder string `yaml:"folder"` Folder string `yaml:"folder"`
} }

58
go.mod
View file

@ -1,11 +1,11 @@
module git.urec56.ru/urec/chat_back_go module git.urec56.ru/urec/chat_back_go
go 1.22.6 go 1.24.2
require ( require (
github.com/DATA-DOG/go-sqlmock v1.5.2 github.com/DATA-DOG/go-sqlmock v1.5.2
github.com/go-playground/validator/v10 v10.24.0 github.com/go-playground/validator/v10 v10.24.0
github.com/golang-jwt/jwt/v5 v5.2.1 github.com/golang-jwt/jwt/v5 v5.2.2
github.com/golang-migrate/migrate/v4 v4.18.2 github.com/golang-migrate/migrate/v4 v4.18.2
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/ilyakaznacheev/cleanenv v1.5.0 github.com/ilyakaznacheev/cleanenv v1.5.0
@ -22,35 +22,87 @@ require (
require ( require (
github.com/BurntSushi/toml v1.2.1 // indirect github.com/BurntSushi/toml v1.2.1 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // 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/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/go-openapi/analysis v0.23.0 // indirect
github.com/go-openapi/errors v0.22.0 // indirect
github.com/go-openapi/inflect v0.21.0 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/loads v0.22.0 // indirect
github.com/go-openapi/runtime v0.28.0 // indirect
github.com/go-openapi/spec v0.21.0 // indirect
github.com/go-openapi/strfmt v0.23.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-openapi/validate v0.24.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-swagger/go-swagger v0.31.0 // indirect
github.com/golang/snappy v0.0.4 // indirect github.com/golang/snappy v0.0.4 // indirect
github.com/gorilla/handlers v1.5.2 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/jessevdk/go-flags v1.5.0 // indirect
github.com/joho/godotenv v1.5.1 // indirect github.com/joho/godotenv v1.5.1 // indirect
github.com/klauspost/compress v1.16.7 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/klauspost/compress v1.17.0 // indirect
github.com/kr/pretty v0.3.1 // indirect github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect
github.com/lib/pq v1.10.9 // indirect github.com/lib/pq v1.10.9 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.18.2 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/toqueteos/webbrowser v1.2.0 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
go.mongodb.org/mongo-driver v1.14.0 // indirect
go.opentelemetry.io/otel/metric v1.32.0 // indirect go.opentelemetry.io/otel/metric v1.32.0 // indirect
go.opentelemetry.io/otel/trace v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect
go.uber.org/atomic v1.9.0 // indirect go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/net v0.34.0 // indirect golang.org/x/net v0.34.0 // indirect
golang.org/x/sync v0.11.0 // indirect golang.org/x/sync v0.11.0 // indirect
golang.org/x/sys v0.30.0 // indirect golang.org/x/sys v0.30.0 // indirect
golang.org/x/text v0.22.0 // indirect golang.org/x/text v0.22.0 // indirect
golang.org/x/tools v0.24.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect
) )
tool github.com/go-swagger/go-swagger/cmd/swagger

127
go.sum
View file

@ -6,8 +6,17 @@ github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= 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/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 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
@ -33,12 +42,38 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w=
github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE=
github.com/go-openapi/inflect v0.21.0 h1:FoBjBTQEcbg2cJUWX6uwL9OyIW8eqc9k4KhN4lfbeYk=
github.com/go-openapi/inflect v0.21.0/go.mod h1:INezMuUu7SJQc2AyR3WO0DqqYUJSj8Kb4hBd7WtjlAw=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco=
github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs=
github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ=
github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc=
github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c=
github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=
github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
@ -49,25 +84,38 @@ github.com/go-playground/validator/v10 v10.24.0 h1:KHQckvo8G6hlWnrPX4NJJ+aBfWNAE
github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus= github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-swagger/go-swagger v0.31.0 h1:H8eOYQnY2u7vNKWDNykv2xJP3pBhRG/R+SOCAmKrLlc=
github.com/go-swagger/go-swagger v0.31.0/go.mod h1:WSigRRWEig8zV6t6Sm8Y+EmUjlzA/HoaZJ5edupq7po=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-migrate/migrate/v4 v4.18.2 h1:2VSCMz7x7mjyTXx3m2zPokOY82LTRgxK1yQYKo6wWQ8= 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-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 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 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 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 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/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 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 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/ilyakaznacheev/cleanenv v1.5.0 h1:0VNZXggJE2OYdXE87bfSSwGxeiGt9moSR2lOrsHHvr4= github.com/ilyakaznacheev/cleanenv v1.5.0 h1:0VNZXggJE2OYdXE87bfSSwGxeiGt9moSR2lOrsHHvr4=
github.com/ilyakaznacheev/cleanenv v1.5.0/go.mod h1:a5aDzaJrLCQZsazHol1w8InnDcOX0OColm64SlIi6gk= github.com/ilyakaznacheev/cleanenv v1.5.0/go.mod h1:a5aDzaJrLCQZsazHol1w8InnDcOX0OColm64SlIi6gk=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
@ -76,13 +124,17 @@ github.com/jackc/pgx/v5 v5.7.2 h1:mLoDLV6sonKlvjIEsV56SkWNCnuNv531l94GaIzO+XI=
github.com/jackc/pgx/v5 v5.7.2/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ= github.com/jackc/pgx/v5 v5.7.2/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE= 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.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@ -91,18 +143,34 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -114,13 +182,42 @@ github.com/redis/go-redis/v9 v9.7.1/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93Ge
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= 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 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ=
github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM=
github.com/urec56/pathparams v0.0.6 h1:OuCbamKVdfVtprL+arL5QUuy84R909haBHLburAAp1c= github.com/urec56/pathparams v0.0.6 h1:OuCbamKVdfVtprL+arL5QUuy84R909haBHLburAAp1c=
github.com/urec56/pathparams v0.0.6/go.mod h1:EymabShlKrvvNckqTZ6zVki6wEYTQmcg41nxFtd7G8Y= 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 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
@ -132,6 +229,8 @@ github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gi
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM= 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/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
go.mongodb.org/mongo-driver/v2 v2.1.0 h1:/ELnVNjmfUKDsoBisXxuJL0noR9CfeUIrP7Yt3R+egg= 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.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 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=
@ -146,14 +245,22 @@ 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/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 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= 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/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 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-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.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= 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/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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -162,27 +269,39 @@ 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/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-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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/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-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-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-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.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= 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/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-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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.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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= 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/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-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.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/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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 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 h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

51
internal/domain/date.go Normal file
View file

@ -0,0 +1,51 @@
package domain
import (
"database/sql/driver"
"fmt"
"time"
)
type CustomDate struct {
time.Time
}
func (ct *CustomDate) UnmarshalJSON(data []byte) error {
str := string(data[1 : len(data)-1])
t, err := time.Parse(time.DateOnly, str)
if err != nil {
return err
}
ct.Time = t
return nil
}
func (ct CustomDate) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf("\"%s\"", ct.Format(time.DateOnly))), nil
}
func (ct CustomDate) String() string {
return ct.Format(time.DateOnly)
}
func (ct *CustomDate) Scan(value any) error {
switch v := value.(type) {
case string:
t, err := time.Parse(time.DateOnly, v)
if err != nil {
return err
}
*ct = CustomDate{Time: t}
case time.Time:
*ct = CustomDate{Time: v}
default:
panic("incorrect time type received")
}
return nil
}
func (ct CustomDate) Value() (driver.Value, error) {
return ct.Time.Format(time.DateOnly), nil
}

View file

@ -0,0 +1,190 @@
package domain
import (
"encoding/json"
"github.com/stretchr/testify/assert"
"testing"
"time"
)
func TestCustomDate_UnmarshalJSON(t *testing.T) {
testTable := []struct {
name string
input string
expectErr bool
expected time.Time
}{
{
name: "ok",
input: `"2024-02-25"`,
expected: time.Date(2024, 2, 25, 0, 0, 0, 0, time.UTC),
},
{
name: "invalid_format",
input: `"25-02-2024"`,
expectErr: true,
},
{
name: "invalid_characters",
input: `"invalid-date"`,
expectErr: true,
},
{
name: "empty_string",
input: `""`,
expectErr: true,
},
{
name: "whitespace",
input: `" "`,
expectErr: true,
},
}
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
var cd CustomDate
err := json.Unmarshal([]byte(tc.input), &cd)
assert.Equal(t, tc.expectErr, err != nil)
assert.True(t, cd.Time.Equal(tc.expected) || tc.expectErr)
})
}
}
func TestCustomDate_MarshalJSON(t *testing.T) {
testTable := []struct {
name string
date CustomDate
expected string
}{
{
name: "ok_1",
date: CustomDate{Time: time.Date(2024, 2, 25, 0, 0, 0, 0, time.UTC)},
expected: `"2024-02-25"`,
},
{
name: "ok_2",
date: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
expected: `"2023-08-10"`,
},
}
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
result, err := json.Marshal(tc.date)
assert.NoError(t, err)
assert.Equal(t, tc.expected, string(result))
})
}
}
func TestCustomDate_String(t *testing.T) {
testTable := []struct {
name string
date CustomDate
expected string
}{
{
name: "ok_1",
date: CustomDate{Time: time.Date(2024, 2, 25, 0, 0, 0, 0, time.UTC)},
expected: "2024-02-25",
},
{
name: "ok_2",
date: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
expected: "2023-08-10",
},
}
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
result := tc.date.String()
assert.Equal(t, tc.expected, result)
})
}
}
func TestCustomDate_Scan(t *testing.T) {
testTable := []struct {
name string
dbValue any
expected CustomDate
expectedErr error
panics bool
}{
{
name: "ok_1",
dbValue: "2023-08-10",
expected: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
},
{
name: "ok_2",
dbValue: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC),
expected: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
},
{
name: "invalid_date",
dbValue: "",
expectedErr: &time.ParseError{},
},
{
name: "invalid_type",
panics: true,
},
}
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
if tc.panics {
defer func() {
if r := recover(); r != nil {
assert.Equal(t, "incorrect time type received", r)
}
}()
}
date := &CustomDate{}
err := date.Scan(tc.dbValue)
if tc.expectedErr != nil {
assert.ErrorAs(t, err, &tc.expectedErr)
} else {
assert.NoError(t, err)
}
assert.Equal(t, tc.expected, *date)
})
}
}
func TestCustomDate_Value(t *testing.T) {
testTable := []struct {
name string
date CustomDate
expected string
}{
{
name: "ok_1",
date: CustomDate{Time: time.Date(2024, 2, 25, 0, 0, 0, 0, time.UTC)},
expected: "2024-02-25",
},
{
name: "ok_2",
date: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
expected: "2023-08-10",
},
}
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
result, err := tc.date.Value()
assert.NoError(t, err)
date, ok := result.(string)
assert.True(t, ok)
assert.Equal(t, tc.expected, date)
})
}
}

View file

@ -4,7 +4,7 @@ import (
"time" "time"
) )
type MessageRaw struct { type RawMessage struct {
ID UUID `bson:"id"` ID UUID `bson:"id"`
Message string `bson:"message,omitempty"` Message string `bson:"message,omitempty"`
ImageUrl string `bson:"image_url,omitempty"` ImageUrl string `bson:"image_url,omitempty"`

View file

@ -1,10 +1,7 @@
package domain package domain
import ( import (
"database/sql/driver"
"encoding/json" "encoding/json"
"fmt"
"time"
) )
const ( const (
@ -29,7 +26,7 @@ func (u *User) UnmarshalBinary(b []byte) error {
return json.Unmarshal(b, u) return json.Unmarshal(b, u)
} }
func (u User) MarshalBinary() ([]byte, error) { func (u *User) MarshalBinary() ([]byte, error) {
return json.Marshal(u) return json.Marshal(u)
} }
@ -49,47 +46,3 @@ type UserRegister struct {
Password2 string `json:"password2" validate:"eqfield=Password"` Password2 string `json:"password2" validate:"eqfield=Password"`
DateOfBirth CustomDate `json:"date_of_birth" validate:"date_of_birth"` DateOfBirth CustomDate `json:"date_of_birth" validate:"date_of_birth"`
} }
type CustomDate struct {
time.Time
}
func (ct *CustomDate) UnmarshalJSON(data []byte) error {
str := string(data[1 : len(data)-1])
t, err := time.Parse(time.DateOnly, str)
if err != nil {
return err
}
ct.Time = t
return nil
}
func (ct CustomDate) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf("\"%s\"", ct.Format(time.DateOnly))), nil
}
func (ct CustomDate) String() string {
return ct.Format(time.DateOnly)
}
func (ct *CustomDate) Scan(value any) error {
switch v := value.(type) {
case string:
t, err := time.Parse(time.DateOnly, v)
if err != nil {
return err
}
*ct = CustomDate{Time: t}
case time.Time:
*ct = CustomDate{Time: v}
default:
panic("incorrect time type received")
}
return nil
}
func (ct CustomDate) Value() (driver.Value, error) {
return ct.Time.Format(time.DateOnly), nil
}

View file

@ -173,185 +173,3 @@ func TestUser_UnmarshalBinary(t *testing.T) {
}) })
} }
} }
func TestCustomDate_UnmarshalJSON(t *testing.T) {
testTable := []struct {
name string
input string
expectErr bool
expected time.Time
}{
{
name: "ok",
input: `"2024-02-25"`,
expected: time.Date(2024, 2, 25, 0, 0, 0, 0, time.UTC),
},
{
name: "invalid_format",
input: `"25-02-2024"`,
expectErr: true,
},
{
name: "invalid_characters",
input: `"invalid-date"`,
expectErr: true,
},
{
name: "empty_string",
input: `""`,
expectErr: true,
},
{
name: "whitespace",
input: `" "`,
expectErr: true,
},
}
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
var cd CustomDate
err := json.Unmarshal([]byte(tc.input), &cd)
assert.Equal(t, tc.expectErr, err != nil)
assert.True(t, cd.Time.Equal(tc.expected) || tc.expectErr)
})
}
}
func TestCustomDate_MarshalJSON(t *testing.T) {
testTable := []struct {
name string
date CustomDate
expected string
}{
{
name: "ok_1",
date: CustomDate{Time: time.Date(2024, 2, 25, 0, 0, 0, 0, time.UTC)},
expected: `"2024-02-25"`,
},
{
name: "ok_2",
date: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
expected: `"2023-08-10"`,
},
}
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
result, err := json.Marshal(tc.date)
assert.NoError(t, err)
assert.Equal(t, tc.expected, string(result))
})
}
}
func TestCustomDate_String(t *testing.T) {
testTable := []struct {
name string
date CustomDate
expected string
}{
{
name: "ok_1",
date: CustomDate{Time: time.Date(2024, 2, 25, 0, 0, 0, 0, time.UTC)},
expected: "2024-02-25",
},
{
name: "ok_2",
date: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
expected: "2023-08-10",
},
}
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
result := tc.date.String()
assert.Equal(t, tc.expected, result)
})
}
}
func TestCustomDate_Scan(t *testing.T) {
testTable := []struct {
name string
dbValue any
expected CustomDate
expectedErr error
panics bool
}{
{
name: "ok_1",
dbValue: "2023-08-10",
expected: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
},
{
name: "ok_2",
dbValue: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC),
expected: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
},
{
name: "invalid_date",
dbValue: "",
expectedErr: &time.ParseError{},
},
{
name: "invalid_type",
panics: true,
},
}
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
if tc.panics {
defer func() {
if r := recover(); r != nil {
assert.Equal(t, "incorrect time type received", r)
}
}()
}
date := &CustomDate{}
err := date.Scan(tc.dbValue)
if tc.expectedErr != nil {
assert.ErrorAs(t, err, &tc.expectedErr)
} else {
assert.NoError(t, err)
}
assert.Equal(t, tc.expected, *date)
})
}
}
func TestCustomDate_Value(t *testing.T) {
testTable := []struct {
name string
date CustomDate
expected string
}{
{
name: "ok_1",
date: CustomDate{Time: time.Date(2024, 2, 25, 0, 0, 0, 0, time.UTC)},
expected: "2024-02-25",
},
{
name: "ok_2",
date: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
expected: "2023-08-10",
},
}
for _, tc := range testTable {
t.Run(tc.name, func(t *testing.T) {
result, err := tc.date.Value()
assert.NoError(t, err)
date, ok := result.(string)
assert.True(t, ok)
assert.Equal(t, tc.expected, date)
})
}
}

View file

@ -5,15 +5,13 @@ import (
"go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/bson"
) )
type UUID struct { type UUID uuid.NullUUID
uuid.NullUUID
}
func (u UUID) IsZero() bool { func (u *UUID) IsZero() bool {
return !u.Valid return !u.Valid
} }
func (u UUID) MarshalBSONValue() (byte, []byte, error) { func (u *UUID) MarshalBSONValue() (byte, []byte, error) {
if !u.Valid { if !u.Valid {
return byte(bson.TypeString), nil, nil return byte(bson.TypeString), nil, nil
} }
@ -46,7 +44,7 @@ func (u *UUID) UnmarshalBSONValue(_ byte, data []byte) error {
return nil return nil
} }
func (u UUID) String() string { func (u *UUID) String() string {
if !u.Valid { if !u.Valid {
return "<nil>" return "<nil>"
} }
@ -54,8 +52,19 @@ func (u UUID) String() string {
} }
func GenerateUUID() UUID { func GenerateUUID() UUID {
return UUID{NullUUID: uuid.NullUUID{ return UUID(
uuid.NullUUID{
UUID: uuid.New(), UUID: uuid.New(),
Valid: true, Valid: true,
}} },
)
}
func GenerateTestUUID() UUID {
return UUID(
uuid.NullUUID{
UUID: uuid.MustParse("5c94e2c5-7615-4fdc-a2e2-00f71ae1e380"),
Valid: true,
},
)
} }

View file

@ -1,10 +1,11 @@
package domain package domain
import ( import (
"testing"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/bson"
"testing"
) )
func TestUUID_IsZero(t *testing.T) { func TestUUID_IsZero(t *testing.T) {
@ -19,7 +20,7 @@ func TestUUID_IsZero(t *testing.T) {
}, },
{ {
name: "non_zero", name: "non_zero",
uuid: UUID{NullUUID: uuid.NullUUID{Valid: true}}, uuid: UUID(uuid.NullUUID{Valid: true}),
expected: false, expected: false,
}, },
} }
@ -44,10 +45,12 @@ func TestUUID_MarshalBSONValue(t *testing.T) {
}, },
{ {
name: "non_zero", name: "non_zero",
uuid: UUID{NullUUID: uuid.NullUUID{ uuid: UUID(
uuid.NullUUID{
UUID: [16]byte{183, 27, 35, 52, 27, 195, 79, 180, 160, 72, 9, 103, 64, 182, 247, 131}, UUID: [16]byte{183, 27, 35, 52, 27, 195, 79, 180, 160, 72, 9, 103, 64, 182, 247, 131},
Valid: true, 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}, 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},
}, },
} }
@ -76,10 +79,12 @@ func TestUUID_UnmarshalBSONValue(t *testing.T) {
{ {
name: "valid_not_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}, 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{ expectedUuid: UUID(
uuid.NullUUID{
UUID: [16]byte{183, 27, 35, 52, 27, 195, 79, 180, 160, 72, 9, 103, 64, 182, 247, 131}, UUID: [16]byte{183, 27, 35, 52, 27, 195, 79, 180, 160, 72, 9, 103, 64, 182, 247, 131},
Valid: true, Valid: true,
}}, },
),
}, },
{ {
name: "parsing_error", name: "parsing_error",
@ -111,10 +116,12 @@ func TestUUID_String(t *testing.T) {
}, },
{ {
name: "non_zero", name: "non_zero",
uuid: UUID{NullUUID: uuid.NullUUID{ uuid: UUID(
uuid.NullUUID{
UUID: [16]byte{183, 27, 35, 52, 27, 195, 79, 180, 160, 72, 9, 103, 64, 182, 247, 131}, UUID: [16]byte{183, 27, 35, 52, 27, 195, 79, 180, 160, 72, 9, 103, 64, 182, 247, 131},
Valid: true, Valid: true,
}}, },
),
expectedUuid: "b71b2334-1bc3-4fb4-a048-096740b6f783", expectedUuid: "b71b2334-1bc3-4fb4-a048-096740b6f783",
}, },
} }
@ -131,3 +138,12 @@ func TestUUID_String(t *testing.T) {
func Test_GenerateUUID(t *testing.T) { func Test_GenerateUUID(t *testing.T) {
_ = GenerateUUID() _ = GenerateUUID()
} }
func Test_GenerateTestUUID(t *testing.T) {
uid1 := GenerateTestUUID()
uid2 := GenerateTestUUID()
uid3 := GenerateTestUUID()
assert.Equal(t, uid1, uid2)
assert.Equal(t, uid1, uid3)
}

View file

@ -38,7 +38,7 @@ func NewLogger(cfg config.Config) *Logger {
logger.SetOutput(io.Discard) logger.SetOutput(io.Discard)
logger.SetLevel(log.PanicLevel) logger.SetLevel(log.PanicLevel)
default: default:
logger.Fatal("incorrect MODE was specified") logger.Fatalf("incorrect MODE was specified: %s", cfg.Mode)
} }
logger.Infof("logger initialized") logger.Infof("logger initialized")

View file

@ -48,82 +48,91 @@ type UnpinMessage struct {
} }
type GetSome struct { type GetSome struct {
ChatID, MessageNumberFrom, MessagesToGet int ChatID, Offset, Limit int
} }
func newMessageRepo(db *sqlx.DB, mdb *mongo.Database, l *logger.Logger) *messageRepository { func newMessageRepo(db *sqlx.DB, mdb *mongo.Database, l *logger.Logger) *messageRepository {
return &messageRepository{db: db, mc: mdb.Collection("message"), l: l} return &messageRepository{db: db, mc: mdb.Collection("message"), l: l}
} }
func (r *messageRepository) Get(ID domain.UUID) (domain.MessageRaw, error) { func (r *messageRepository) Get(ID domain.UUID) (domain.RawMessage, error) {
var msg domain.MessageRaw var msg domain.RawMessage
res := r.mc.FindOne(nil, bson.M{"id": ID}) res := r.mc.FindOne(nil, bson.M{"id": ID})
if err := res.Decode(&msg); err != nil { if err := res.Decode(&msg); err != nil {
r.l.Errorf("getting message: %s", err.Error()) r.l.Errorf("getting message: %s", err)
return domain.MessageRaw{}, domain.InternalServerError return domain.RawMessage{}, domain.InternalServerError
} }
return msg, nil return msg, nil
} }
func (r *messageRepository) GetByIDs(IDs []domain.UUID) ([]domain.MessageRaw, error) { func (r *messageRepository) GetByIDs(IDs []domain.UUID) ([]domain.RawMessage, error) {
var messages []domain.MessageRaw var messages []domain.RawMessage
res, err := r.mc.Find(nil, bson.M{"visibility": true, "id": bson.M{"$in": IDs}}) res, err := r.mc.Find(nil, bson.M{"visibility": true, "id": bson.M{"$in": IDs}})
if err != nil { if err != nil {
r.l.Errorf("getting messages by ids: %s", err.Error()) r.l.Errorf("getting messages by ids: %s", err)
return nil, domain.InternalServerError return nil, domain.InternalServerError
} }
if err = res.All(nil, &messages); err != nil { if err = res.All(nil, &messages); err != nil {
r.l.Errorf("decoding messages by ids: %s", err.Error()) r.l.Errorf("decoding messages by ids: %s", err)
return nil, domain.InternalServerError return nil, domain.InternalServerError
} }
return messages, nil return messages, nil
} }
func (r *messageRepository) GetSome(messagesInfo GetSome) ([]domain.MessageRaw, error) { func (r *messageRepository) GetSome(messagesInfo GetSome) ([]domain.RawMessage, error) {
var messages []domain.MessageRaw var messages []domain.RawMessage
findOptions := options.Find().SetSort(bson.M{"created_at": -1}).SetLimit(int64(messagesInfo.MessagesToGet)).SetSkip(int64(messagesInfo.MessageNumberFrom)) findOptions := options.Find().SetSort(bson.M{"created_at": -1}).SetLimit(int64(messagesInfo.Limit)).SetSkip(int64(messagesInfo.Offset))
res, err := r.mc.Find(nil, bson.M{"visibility": true, "chat_id": messagesInfo.ChatID}, findOptions) res, err := r.mc.Find(nil, bson.M{"visibility": true, "chat_id": messagesInfo.ChatID}, findOptions)
if err != nil { if err != nil {
r.l.Errorf("getting some messages: %s", err.Error()) r.l.Errorf("getting some messages: %s", err)
return nil, domain.InternalServerError return nil, domain.InternalServerError
} }
if err = res.All(nil, &messages); err != nil { if err = res.All(nil, &messages); err != nil {
r.l.Errorf("decoding some messages: %s", err.Error()) r.l.Errorf("decoding some messages: %s", err)
return nil, domain.InternalServerError return nil, domain.InternalServerError
} }
return messages, nil return messages, nil
} }
func (r *messageRepository) Send(message SendMessage) (domain.UUID, error) { func (r *messageRepository) Send(message SendMessage) (domain.RawMessage, error) {
message.ID = domain.GenerateUUID() message.ID = domain.GenerateUUID()
message.CreatedAt = time.Now() message.CreatedAt = time.Now()
message.Visibility = true message.Visibility = true
_, err := r.mc.InsertOne(nil, message) _, err := r.mc.InsertOne(nil, message)
if err != nil { if err != nil {
r.l.Errorf("inserting message: %s", err.Error()) r.l.Errorf("inserting message: %s", err)
return domain.UUID{}, domain.InternalServerError return domain.RawMessage{}, domain.InternalServerError
} }
return message.ID, nil return domain.RawMessage{
ID: message.ID,
Message: message.Message,
ImageUrl: message.ImageUrl,
ChatID: message.ChatID,
UserID: message.UserID,
CreatedAt: message.CreatedAt,
AnswerID: message.AnswerID,
AnswerMessage: message.AnswerMessage,
AnswerImageUrl: message.AnswerImageUrl,
}, nil
} }
func (r *messageRepository) Delete(ID domain.UUID) error { 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 { 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()) r.l.Errorf("deleting message: %s", err)
return domain.InternalServerError 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}}) _, 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 { if err != nil {
r.l.Errorf("deleting message: %s", err.Error()) r.l.Errorf("deleting message: %s", err)
return domain.InternalServerError return domain.InternalServerError
} }
@ -132,13 +141,13 @@ func (r *messageRepository) Delete(ID domain.UUID) error {
func (r *messageRepository) Edit(newMessage EditMessage) error { 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}}) _, 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 { if err != nil {
r.l.Errorf("edditing message: %s", err.Error()) r.l.Errorf("edditing message: %s", err)
return domain.InternalServerError 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}}) _, 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 { if err != nil {
r.l.Errorf("edditing message: %s", err.Error()) r.l.Errorf("edditing message: %s", err)
return domain.InternalServerError return domain.InternalServerError
} }
@ -152,7 +161,7 @@ func (r *messageRepository) Pin(msg PinMessage) error {
return domain.MessageAlreadyPinnedError return domain.MessageAlreadyPinnedError
} }
r.l.Errorf("pining message: %s", err.Error()) r.l.Errorf("pining message: %s", err)
return domain.InternalServerError return domain.InternalServerError
} }
@ -162,7 +171,7 @@ func (r *messageRepository) Pin(msg PinMessage) error {
func (r *messageRepository) Unpin(msg UnpinMessage) error { func (r *messageRepository) Unpin(msg UnpinMessage) error {
query := `DELETE FROM pinned_message WHERE chat_id = $1 AND message_id = $2` 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 { if _, err := r.db.Exec(query, msg.ChatID, msg.MessageID); err != nil {
r.l.Errorf("unpining message: %s", err.Error()) r.l.Errorf("unpining message: %s", err)
return domain.InternalServerError return domain.InternalServerError
} }
@ -173,7 +182,7 @@ func (r *messageRepository) GetPinnedIDs(chatID int) ([]domain.UUID, error) {
var IDs []domain.UUID var IDs []domain.UUID
query := `SELECT message_id FROM pinned_message WHERE chat_id = $1` query := `SELECT message_id FROM pinned_message WHERE chat_id = $1`
if err := r.db.Select(&IDs, query, chatID); err != nil { if err := r.db.Select(&IDs, query, chatID); err != nil {
r.l.Errorf("getting pinned ids: %s", err.Error()) r.l.Errorf("getting pinned ids: %s", err)
return []domain.UUID{}, domain.InternalServerError return []domain.UUID{}, domain.InternalServerError
} }

View file

@ -22,7 +22,6 @@ import (
type MockUser struct { type MockUser struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *MockUserMockRecorder recorder *MockUserMockRecorder
isgomock struct{}
} }
// MockUserMockRecorder is the mock recorder for MockUser. // MockUserMockRecorder is the mock recorder for MockUser.
@ -106,7 +105,6 @@ func (mr *MockUserMockRecorder) Register(email, hashedPassword, username, dateOf
type MockChat struct { type MockChat struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *MockChatMockRecorder recorder *MockChatMockRecorder
isgomock struct{}
} }
// MockChatMockRecorder is the mock recorder for MockChat. // MockChatMockRecorder is the mock recorder for MockChat.
@ -130,7 +128,6 @@ func (m *MockChat) EXPECT() *MockChatMockRecorder {
type MockMessage struct { type MockMessage struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *MockMessageMockRecorder recorder *MockMessageMockRecorder
isgomock struct{}
} }
// MockMessageMockRecorder is the mock recorder for MockMessage. // MockMessageMockRecorder is the mock recorder for MockMessage.
@ -179,10 +176,10 @@ func (mr *MockMessageMockRecorder) Edit(newMessage any) *gomock.Call {
} }
// Get mocks base method. // Get mocks base method.
func (m *MockMessage) Get(ID domain.UUID) (domain.MessageRaw, error) { func (m *MockMessage) Get(ID domain.UUID) (domain.RawMessage, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Get", ID) ret := m.ctrl.Call(m, "Get", ID)
ret0, _ := ret[0].(domain.MessageRaw) ret0, _ := ret[0].(domain.RawMessage)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -194,10 +191,10 @@ func (mr *MockMessageMockRecorder) Get(ID any) *gomock.Call {
} }
// GetByIDs mocks base method. // GetByIDs mocks base method.
func (m *MockMessage) GetByIDs(IDs []domain.UUID) ([]domain.MessageRaw, error) { func (m *MockMessage) GetByIDs(IDs []domain.UUID) ([]domain.RawMessage, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetByIDs", IDs) ret := m.ctrl.Call(m, "GetByIDs", IDs)
ret0, _ := ret[0].([]domain.MessageRaw) ret0, _ := ret[0].([]domain.RawMessage)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -224,10 +221,10 @@ func (mr *MockMessageMockRecorder) GetPinnedIDs(chatID any) *gomock.Call {
} }
// GetSome mocks base method. // GetSome mocks base method.
func (m *MockMessage) GetSome(messagesInfo repository.GetSome) ([]domain.MessageRaw, error) { func (m *MockMessage) GetSome(messagesInfo repository.GetSome) ([]domain.RawMessage, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetSome", messagesInfo) ret := m.ctrl.Call(m, "GetSome", messagesInfo)
ret0, _ := ret[0].([]domain.MessageRaw) ret0, _ := ret[0].([]domain.RawMessage)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -253,10 +250,10 @@ func (mr *MockMessageMockRecorder) Pin(msg any) *gomock.Call {
} }
// Send mocks base method. // Send mocks base method.
func (m *MockMessage) Send(message repository.SendMessage) (domain.UUID, error) { func (m *MockMessage) Send(message repository.SendMessage) (domain.RawMessage, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Send", message) ret := m.ctrl.Call(m, "Send", message)
ret0, _ := ret[0].(domain.UUID) ret0, _ := ret[0].(domain.RawMessage)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -285,7 +282,6 @@ func (mr *MockMessageMockRecorder) Unpin(msg any) *gomock.Call {
type MockRepo struct { type MockRepo struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *MockRepoMockRecorder recorder *MockRepoMockRecorder
isgomock struct{}
} }
// MockRepoMockRecorder is the mock recorder for MockRepo. // MockRepoMockRecorder is the mock recorder for MockRepo.
@ -349,10 +345,10 @@ func (mr *MockRepoMockRecorder) FindOne(username, email any) *gomock.Call {
} }
// Get mocks base method. // Get mocks base method.
func (m *MockRepo) Get(ID domain.UUID) (domain.MessageRaw, error) { func (m *MockRepo) Get(ID domain.UUID) (domain.RawMessage, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Get", ID) ret := m.ctrl.Call(m, "Get", ID)
ret0, _ := ret[0].(domain.MessageRaw) ret0, _ := ret[0].(domain.RawMessage)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -394,10 +390,10 @@ func (mr *MockRepoMockRecorder) GetByID(userID any) *gomock.Call {
} }
// GetByIDs mocks base method. // GetByIDs mocks base method.
func (m *MockRepo) GetByIDs(IDs []domain.UUID) ([]domain.MessageRaw, error) { func (m *MockRepo) GetByIDs(IDs []domain.UUID) ([]domain.RawMessage, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetByIDs", IDs) ret := m.ctrl.Call(m, "GetByIDs", IDs)
ret0, _ := ret[0].([]domain.MessageRaw) ret0, _ := ret[0].([]domain.RawMessage)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -424,10 +420,10 @@ func (mr *MockRepoMockRecorder) GetPinnedIDs(chatID any) *gomock.Call {
} }
// GetSome mocks base method. // GetSome mocks base method.
func (m *MockRepo) GetSome(messagesInfo repository.GetSome) ([]domain.MessageRaw, error) { func (m *MockRepo) GetSome(messagesInfo repository.GetSome) ([]domain.RawMessage, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetSome", messagesInfo) ret := m.ctrl.Call(m, "GetSome", messagesInfo)
ret0, _ := ret[0].([]domain.MessageRaw) ret0, _ := ret[0].([]domain.RawMessage)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -468,10 +464,10 @@ func (mr *MockRepoMockRecorder) Register(email, hashedPassword, username, dateOf
} }
// Send mocks base method. // Send mocks base method.
func (m *MockRepo) Send(message repository.SendMessage) (domain.UUID, error) { func (m *MockRepo) Send(message repository.SendMessage) (domain.RawMessage, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Send", message) ret := m.ctrl.Call(m, "Send", message)
ret0, _ := ret[0].(domain.UUID) ret0, _ := ret[0].(domain.RawMessage)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }

View file

@ -21,10 +21,10 @@ type User interface {
type Chat interface{} type Chat interface{}
type Message interface { type Message interface {
Get(ID domain.UUID) (domain.MessageRaw, error) Get(ID domain.UUID) (domain.RawMessage, error)
GetByIDs(IDs []domain.UUID) ([]domain.MessageRaw, error) GetByIDs(IDs []domain.UUID) ([]domain.RawMessage, error)
GetSome(messagesInfo GetSome) ([]domain.MessageRaw, error) GetSome(messagesInfo GetSome) ([]domain.RawMessage, error)
Send(message SendMessage) (domain.UUID, error) Send(message SendMessage) (domain.RawMessage, error)
Delete(ID domain.UUID) error Delete(ID domain.UUID) error
Edit(newMessage EditMessage) error Edit(newMessage EditMessage) error
Pin(msg PinMessage) error Pin(msg PinMessage) error

View file

@ -42,7 +42,7 @@ func (r *userRepository) GetAll(username string) ([]domain.User, error) {
query := fmt.Sprintf(`SELECT * FROM users WHERE username ILIKE $1 AND role != %d`, domain.AdminUser) query := fmt.Sprintf(`SELECT * FROM users WHERE username ILIKE $1 AND role != %d`, domain.AdminUser)
err := r.db.Select(&users, query, username) err := r.db.Select(&users, query, username)
if err != nil { if err != nil {
r.l.Errorf("getting users: %s", err.Error()) r.l.Errorf("getting users: %s", err)
return nil, domain.InternalServerError return nil, domain.InternalServerError
} }
return users, nil return users, nil
@ -84,18 +84,18 @@ func (r *userRepository) Register(email, hashedPassword, username string, dateOf
tx, err := r.db.Beginx() tx, err := r.db.Beginx()
if err != nil { if err != nil {
r.l.Errorf("user registration: tx begin: %s", err.Error()) r.l.Errorf("user registration: tx begin: %s", err)
return domain.User{}, domain.InternalServerError return domain.User{}, domain.InternalServerError
} }
defer func() { defer func() {
if err != nil { if err != nil {
var pgError *pgconn.PgError var pgError *pgconn.PgError
if !errors.As(err, &pgError) { if !errors.As(err, &pgError) {
r.l.Errorf("user registration: %s", err.Error()) r.l.Errorf("user registration: %s", err)
} }
if err = tx.Rollback(); err != nil && !errors.Is(err, sql.ErrTxDone) { if err = tx.Rollback(); err != nil && !errors.Is(err, sql.ErrTxDone) {
r.l.Errorf("user registration: tx rollback: %s", err.Error()) r.l.Errorf("user registration: tx rollback: %s", err)
} }
} }
}() }()

View file

@ -81,7 +81,7 @@ func (s *authService) EncodeAuthToken(userID int) (string, error) {
func (s *authService) HashPassword(p string) (string, error) { func (s *authService) HashPassword(p string) (string, error) {
hash, err := bcrypt.GenerateFromPassword([]byte(p)[:maxBcryptPasswordLen], bcrypt.DefaultCost) hash, err := bcrypt.GenerateFromPassword([]byte(p)[:maxBcryptPasswordLen], bcrypt.DefaultCost)
if err != nil { if err != nil {
s.l.Errorf("error during password hashing: %s", err.Error()) s.l.Errorf("error during password hashing: %s", err)
return "", domain.HashingError return "", domain.HashingError
} }
return string(hash), nil return string(hash), nil

View file

@ -5,6 +5,7 @@ import (
"encoding" "encoding"
"errors" "errors"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
"sync"
"time" "time"
"git.urec56.ru/urec/chat_back_go/internal/domain" "git.urec56.ru/urec/chat_back_go/internal/domain"
@ -14,23 +15,39 @@ import (
type cacheService struct { type cacheService struct {
l *logger.Logger l *logger.Logger
r redis.UniversalClient r redis.UniversalClient
storage *sync.Map
}
type userCache struct {
u []byte // domain.User
expiresAt time.Time
} }
func newCacheService(r redis.UniversalClient, l *logger.Logger) *cacheService { func newCacheService(r redis.UniversalClient, l *logger.Logger) *cacheService {
return &cacheService{r: r, l: l} return &cacheService{r: r, l: l, storage: &sync.Map{}}
} }
func (c *cacheService) Get(key string, v encoding.BinaryUnmarshaler) error { func (c *cacheService) Get(key string, v encoding.BinaryUnmarshaler, isFast bool) error {
return c.GetCtx(context.Background(), key, v) return c.GetCtx(context.Background(), key, v, isFast)
} }
func (c *cacheService) GetCtx(ctx context.Context, key string, v encoding.BinaryUnmarshaler) error { func (c *cacheService) GetCtx(ctx context.Context, key string, v encoding.BinaryUnmarshaler, isFast bool) error {
if isFast {
item, ok := c.storage.Load(key)
if ok {
if userData, ok := item.(userCache); ok && userData.expiresAt.After(time.Now()) {
err := v.UnmarshalBinary(userData.u)
return err
}
}
}
err := c.r.Get(ctx, key).Scan(v) err := c.r.Get(ctx, key).Scan(v)
if err != nil { if err != nil {
if errors.Is(err, redis.Nil) { if errors.Is(err, redis.Nil) {
return domain.NoKeyFoundError return domain.NoKeyFoundError
} }
c.l.Errorf("getting key %s: %s", key, err.Error()) c.l.Errorf("getting key %s: %s", key, err)
return domain.InternalServerError return domain.InternalServerError
} }
return nil return nil
@ -44,5 +61,12 @@ func (c *cacheService) SetCtx(ctx context.Context, key string, v encoding.Binary
if err := c.r.SetEx(ctx, key, v, ex).Err(); err != nil { if err := c.r.SetEx(ctx, key, v, ex).Err(); err != nil {
return err return err
} }
data, err := v.MarshalBinary()
if err != nil {
return err
}
c.storage.Store(key, userCache{u: data, expiresAt: time.Now().Add(time.Minute)})
return nil return nil
} }

View file

@ -18,9 +18,10 @@ func newMessageService(repo repository.Message, u User, l *logger.Logger) *messa
return &messageService{repo: repo, u: u, l: l} return &messageService{repo: repo, u: u, l: l}
} }
func (s *messageService) AddAvatarImageAndUsernameToMessage(msgRaw domain.MessageRaw) (domain.Message, error) { func (s *messageService) AddAvatarImageAndUsernameToMessage(msgRaw domain.RawMessage) (domain.Message, error) {
u, err := s.u.GetCachedUser(msgRaw.UserID) u, err := s.u.Get(msgRaw.UserID, true)
if err != nil { if err != nil {
s.l.Infof("error adding image and username to message: %s", err)
return domain.Message{}, domain.InternalServerError return domain.Message{}, domain.InternalServerError
} }
@ -39,7 +40,7 @@ func (s *messageService) AddAvatarImageAndUsernameToMessage(msgRaw domain.Messag
}, nil }, nil
} }
func (s *messageService) AddAvatarImageAndUsernameToMessages(msgsRaw []domain.MessageRaw) []domain.Message { func (s *messageService) AddAvatarImageAndUsernameToMessages(msgsRaw []domain.RawMessage) []domain.Message {
msgs := make([]domain.Message, 0, len(msgsRaw)) msgs := make([]domain.Message, 0, len(msgsRaw))
for _, v := range msgsRaw { for _, v := range msgsRaw {
msg, err := s.AddAvatarImageAndUsernameToMessage(v) msg, err := s.AddAvatarImageAndUsernameToMessage(v)
@ -51,10 +52,19 @@ func (s *messageService) AddAvatarImageAndUsernameToMessages(msgsRaw []domain.Me
return msgs return msgs
} }
func (s *messageService) GetRaw(ID domain.UUID) (domain.RawMessage, error) {
rawMessage, err := s.repo.Get(ID)
if err != nil {
s.l.Infof("error getting message: %s", err)
return domain.RawMessage{}, domain.InternalServerError
}
return rawMessage, nil
}
func (s *messageService) GetMessage(ID domain.UUID) (domain.Message, error) { func (s *messageService) GetMessage(ID domain.UUID) (domain.Message, error) {
rawMessage, err := s.GetRaw(ID) rawMessage, err := s.GetRaw(ID)
if err != nil { if err != nil {
s.l.Infof("error getting message: %s", err.Error())
return domain.Message{}, domain.InternalServerError return domain.Message{}, domain.InternalServerError
} }
@ -66,26 +76,16 @@ func (s *messageService) GetMessage(ID domain.UUID) (domain.Message, error) {
return newMessage, nil 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) { func (s *messageService) GetPinned(chatID int) ([]domain.Message, error) {
IDs, err := s.repo.GetPinnedIDs(chatID) IDs, err := s.repo.GetPinnedIDs(chatID)
if err != nil { if err != nil {
s.l.Infof("error getting pinned ids: %s", err.Error()) s.l.Infof("error getting pinned ids: %s", err)
return nil, domain.InternalServerError return nil, domain.InternalServerError
} }
rawMessages, err := s.repo.GetByIDs(IDs) rawMessages, err := s.repo.GetByIDs(IDs)
if err != nil { if err != nil {
s.l.Infof("error messages by ids: %s", err.Error()) s.l.Infof("error messages by ids: %s", err)
return nil, domain.InternalServerError return nil, domain.InternalServerError
} }
@ -94,11 +94,11 @@ func (s *messageService) GetPinned(chatID int) ([]domain.Message, error) {
return messages, nil return messages, nil
} }
func (s *messageService) GetSome(chatID, messageNumberFrom, messagesToGet int) ([]domain.Message, error) { func (s *messageService) GetSome(chatID, offset, limit int) ([]domain.Message, error) {
messagesRaw, err := s.repo.GetSome(repository.GetSome{ChatID: chatID, MessageNumberFrom: messageNumberFrom, MessagesToGet: messagesToGet}) messagesRaw, err := s.repo.GetSome(repository.GetSome{ChatID: chatID, Offset: offset, Limit: limit})
if err != nil { if err != nil {
s.l.Infof("error getting some messages: %s", err.Error()) s.l.Infof("error getting some messages: %s", err)
return nil, err return nil, domain.InternalServerError
} }
messages := s.AddAvatarImageAndUsernameToMessages(messagesRaw) messages := s.AddAvatarImageAndUsernameToMessages(messagesRaw)
@ -107,28 +107,28 @@ func (s *messageService) GetSome(chatID, messageNumberFrom, messagesToGet int) (
} }
func (s *messageService) SendMessage(userID, chatID int, message domain.SendMessage) (domain.Message, error) { func (s *messageService) SendMessage(userID, chatID int, message domain.SendMessage) (domain.Message, error) {
var messageID domain.UUID var rawMessage domain.RawMessage
var err error var err error
if message.Answer.IsZero() { if message.Answer.IsZero() {
messageID, err = s.repo.Send(repository.SendMessage{ rawMessage, err = s.repo.Send(repository.SendMessage{
Message: message.Message, Message: message.Message,
ImageUrl: message.ImageUrl, ImageUrl: message.ImageUrl,
ChatID: chatID, ChatID: chatID,
UserID: userID, UserID: userID,
}) })
if err != nil { if err != nil {
s.l.Infof("error sending message: %s", err.Error()) s.l.Infof("error sending message: %s", err)
return domain.Message{}, domain.InternalServerError return domain.Message{}, domain.InternalServerError
} }
} else { } else {
answerMessage, err := s.GetRaw(message.Answer) answerMessage, err := s.GetRaw(message.Answer)
if err != nil { if err != nil {
s.l.Infof("error getting message: %s", err.Error()) s.l.Infof("error getting message: %s", err)
return domain.Message{}, domain.InternalServerError return domain.Message{}, domain.InternalServerError
} }
messageID, err = s.repo.Send(repository.SendMessage{ rawMessage, err = s.repo.Send(repository.SendMessage{
Message: message.Message, Message: message.Message,
ImageUrl: message.ImageUrl, ImageUrl: message.ImageUrl,
ChatID: chatID, ChatID: chatID,
@ -138,14 +138,14 @@ func (s *messageService) SendMessage(userID, chatID int, message domain.SendMess
AnswerImageUrl: answerMessage.ImageUrl, AnswerImageUrl: answerMessage.ImageUrl,
}) })
if err != nil { if err != nil {
s.l.Infof("error sending message: %s", err.Error()) s.l.Infof("error sending message: %s", err)
return domain.Message{}, domain.InternalServerError return domain.Message{}, domain.InternalServerError
} }
} }
newMessage, err := s.GetMessage(messageID) newMessage, err := s.AddAvatarImageAndUsernameToMessage(rawMessage)
if err != nil { if err != nil {
s.l.Infof("error getting message: %s", err.Error()) s.l.Infof("error getting message: %s", err)
return domain.Message{}, domain.InternalServerError return domain.Message{}, domain.InternalServerError
} }
@ -154,7 +154,7 @@ func (s *messageService) SendMessage(userID, chatID int, message domain.SendMess
func (s *messageService) Delete(ID domain.UUID) error { func (s *messageService) Delete(ID domain.UUID) error {
if err := s.repo.Delete(ID); err != nil { if err := s.repo.Delete(ID); err != nil {
s.l.Infof("error deleting message: %s", err.Error()) s.l.Infof("error deleting message: %s", err)
return domain.InternalServerError return domain.InternalServerError
} }
@ -163,7 +163,7 @@ func (s *messageService) Delete(ID domain.UUID) error {
func (s *messageService) Edit(ID domain.UUID, newMessage, newImageUrl string) error { 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 { if err := s.repo.Edit(repository.EditMessage{ID: ID, Message: newMessage, ImageUrl: newImageUrl}); err != nil {
s.l.Infof("error editing message: %s", err.Error()) s.l.Infof("error editing message: %s", err)
return domain.InternalServerError return domain.InternalServerError
} }
@ -177,13 +177,13 @@ func (s *messageService) Pin(chatID, userID int, messageID domain.UUID) (domain.
return domain.Message{}, err return domain.Message{}, err
} }
s.l.Infof("error pinning message: %s", err.Error()) s.l.Infof("error pinning message: %s", err)
return domain.Message{}, domain.InternalServerError return domain.Message{}, domain.InternalServerError
} }
message, err := s.GetMessage(messageID) message, err := s.GetMessage(messageID)
if err != nil { if err != nil {
s.l.Infof("error getting message: %s", err.Error()) s.l.Infof("error getting message: %s", err)
return domain.Message{}, domain.InternalServerError return domain.Message{}, domain.InternalServerError
} }
@ -193,7 +193,7 @@ func (s *messageService) Pin(chatID, userID int, messageID domain.UUID) (domain.
func (s *messageService) Unpin(chatID int, messageID domain.UUID) error { func (s *messageService) Unpin(chatID int, messageID domain.UUID) error {
err := s.repo.Unpin(repository.UnpinMessage{ChatID: chatID, MessageID: messageID}) err := s.repo.Unpin(repository.UnpinMessage{ChatID: chatID, MessageID: messageID})
if err != nil { if err != nil {
s.l.Infof("error unpinning message: %s", err.Error()) s.l.Infof("error unpinning message: %s", err)
return domain.InternalServerError return domain.InternalServerError
} }

File diff suppressed because it is too large Load diff

View file

@ -25,7 +25,6 @@ import (
type MockUser struct { type MockUser struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *MockUserMockRecorder recorder *MockUserMockRecorder
isgomock struct{}
} }
// MockUserMockRecorder is the mock recorder for MockUser. // MockUserMockRecorder is the mock recorder for MockUser.
@ -61,18 +60,18 @@ func (mr *MockUserMockRecorder) FindOne(username, email any) *gomock.Call {
} }
// Get mocks base method. // Get mocks base method.
func (m *MockUser) Get(userID int) (domain.User, error) { func (m *MockUser) Get(userID int, isFast bool) (domain.User, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Get", userID) ret := m.ctrl.Call(m, "Get", userID, isFast)
ret0, _ := ret[0].(domain.User) ret0, _ := ret[0].(domain.User)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
// Get indicates an expected call of Get. // Get indicates an expected call of Get.
func (mr *MockUserMockRecorder) Get(userID any) *gomock.Call { func (mr *MockUserMockRecorder) Get(userID, isFast any) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockUser)(nil).Get), userID) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockUser)(nil).Get), userID, isFast)
} }
// GetAll mocks base method. // GetAll mocks base method.
@ -90,21 +89,6 @@ func (mr *MockUserMockRecorder) GetAll(username any) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAll", reflect.TypeOf((*MockUser)(nil).GetAll), username) 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. // GetVerificated mocks base method.
func (m *MockUser) GetVerificated(userID int) (domain.User, error) { func (m *MockUser) GetVerificated(userID int) (domain.User, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@ -135,23 +119,10 @@ func (mr *MockUserMockRecorder) Register(userData any) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Register", reflect.TypeOf((*MockUser)(nil).Register), userData) 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. // MockAuth is a mock of Auth interface.
type MockAuth struct { type MockAuth struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *MockAuthMockRecorder recorder *MockAuthMockRecorder
isgomock struct{}
} }
// MockAuthMockRecorder is the mock recorder for MockAuth. // MockAuthMockRecorder is the mock recorder for MockAuth.
@ -249,7 +220,6 @@ func (mr *MockAuthMockRecorder) VerifyHashedPassword(p, hp any) *gomock.Call {
type MockChat struct { type MockChat struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *MockChatMockRecorder recorder *MockChatMockRecorder
isgomock struct{}
} }
// MockChatMockRecorder is the mock recorder for MockChat. // MockChatMockRecorder is the mock recorder for MockChat.
@ -273,7 +243,6 @@ func (m *MockChat) EXPECT() *MockChatMockRecorder {
type MockMessages struct { type MockMessages struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *MockMessagesMockRecorder recorder *MockMessagesMockRecorder
isgomock struct{}
} }
// MockMessagesMockRecorder is the mock recorder for MockMessages. // MockMessagesMockRecorder is the mock recorder for MockMessages.
@ -294,7 +263,7 @@ func (m *MockMessages) EXPECT() *MockMessagesMockRecorder {
} }
// AddAvatarImageAndUsernameToMessage mocks base method. // AddAvatarImageAndUsernameToMessage mocks base method.
func (m *MockMessages) AddAvatarImageAndUsernameToMessage(msgRaw domain.MessageRaw) (domain.Message, error) { func (m *MockMessages) AddAvatarImageAndUsernameToMessage(msgRaw domain.RawMessage) (domain.Message, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddAvatarImageAndUsernameToMessage", msgRaw) ret := m.ctrl.Call(m, "AddAvatarImageAndUsernameToMessage", msgRaw)
ret0, _ := ret[0].(domain.Message) ret0, _ := ret[0].(domain.Message)
@ -309,7 +278,7 @@ func (mr *MockMessagesMockRecorder) AddAvatarImageAndUsernameToMessage(msgRaw an
} }
// AddAvatarImageAndUsernameToMessages mocks base method. // AddAvatarImageAndUsernameToMessages mocks base method.
func (m *MockMessages) AddAvatarImageAndUsernameToMessages(msgsRaw []domain.MessageRaw) []domain.Message { func (m *MockMessages) AddAvatarImageAndUsernameToMessages(msgsRaw []domain.RawMessage) []domain.Message {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddAvatarImageAndUsernameToMessages", msgsRaw) ret := m.ctrl.Call(m, "AddAvatarImageAndUsernameToMessages", msgsRaw)
ret0, _ := ret[0].([]domain.Message) ret0, _ := ret[0].([]domain.Message)
@ -381,10 +350,10 @@ func (mr *MockMessagesMockRecorder) GetPinned(chatID any) *gomock.Call {
} }
// GetRaw mocks base method. // GetRaw mocks base method.
func (m *MockMessages) GetRaw(ID domain.UUID) (domain.MessageRaw, error) { func (m *MockMessages) GetRaw(ID domain.UUID) (domain.RawMessage, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetRaw", ID) ret := m.ctrl.Call(m, "GetRaw", ID)
ret0, _ := ret[0].(domain.MessageRaw) ret0, _ := ret[0].(domain.RawMessage)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -396,18 +365,18 @@ func (mr *MockMessagesMockRecorder) GetRaw(ID any) *gomock.Call {
} }
// GetSome mocks base method. // GetSome mocks base method.
func (m *MockMessages) GetSome(chatID, messageNumberFrom, messagesToGet int) ([]domain.Message, error) { func (m *MockMessages) GetSome(chatID, offset, limit int) ([]domain.Message, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetSome", chatID, messageNumberFrom, messagesToGet) ret := m.ctrl.Call(m, "GetSome", chatID, offset, limit)
ret0, _ := ret[0].([]domain.Message) ret0, _ := ret[0].([]domain.Message)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
// GetSome indicates an expected call of GetSome. // GetSome indicates an expected call of GetSome.
func (mr *MockMessagesMockRecorder) GetSome(chatID, messageNumberFrom, messagesToGet any) *gomock.Call { func (mr *MockMessagesMockRecorder) GetSome(chatID, offset, limit any) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSome", reflect.TypeOf((*MockMessages)(nil).GetSome), chatID, messageNumberFrom, messagesToGet) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSome", reflect.TypeOf((*MockMessages)(nil).GetSome), chatID, offset, limit)
} }
// Pin mocks base method. // Pin mocks base method.
@ -458,7 +427,6 @@ func (mr *MockMessagesMockRecorder) Unpin(chatID, messageID any) *gomock.Call {
type MockCache struct { type MockCache struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *MockCacheMockRecorder recorder *MockCacheMockRecorder
isgomock struct{}
} }
// MockCacheMockRecorder is the mock recorder for MockCache. // MockCacheMockRecorder is the mock recorder for MockCache.
@ -479,31 +447,31 @@ func (m *MockCache) EXPECT() *MockCacheMockRecorder {
} }
// Get mocks base method. // Get mocks base method.
func (m *MockCache) Get(key string, v encoding.BinaryUnmarshaler) error { func (m *MockCache) Get(key string, v encoding.BinaryUnmarshaler, isFast bool) error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Get", key, v) ret := m.ctrl.Call(m, "Get", key, v, isFast)
ret0, _ := ret[0].(error) ret0, _ := ret[0].(error)
return ret0 return ret0
} }
// Get indicates an expected call of Get. // Get indicates an expected call of Get.
func (mr *MockCacheMockRecorder) Get(key, v any) *gomock.Call { func (mr *MockCacheMockRecorder) Get(key, v, isFast any) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockCache)(nil).Get), key, v) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockCache)(nil).Get), key, v, isFast)
} }
// GetCtx mocks base method. // GetCtx mocks base method.
func (m *MockCache) GetCtx(ctx context.Context, key string, v encoding.BinaryUnmarshaler) error { func (m *MockCache) GetCtx(ctx context.Context, key string, v encoding.BinaryUnmarshaler, isFast bool) error {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetCtx", ctx, key, v) ret := m.ctrl.Call(m, "GetCtx", ctx, key, v, isFast)
ret0, _ := ret[0].(error) ret0, _ := ret[0].(error)
return ret0 return ret0
} }
// GetCtx indicates an expected call of GetCtx. // GetCtx indicates an expected call of GetCtx.
func (mr *MockCacheMockRecorder) GetCtx(ctx, key, v any) *gomock.Call { func (mr *MockCacheMockRecorder) GetCtx(ctx, key, v, isFast any) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCtx", reflect.TypeOf((*MockCache)(nil).GetCtx), ctx, key, v) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCtx", reflect.TypeOf((*MockCache)(nil).GetCtx), ctx, key, v, isFast)
} }
// Set mocks base method. // Set mocks base method.
@ -538,7 +506,6 @@ func (mr *MockCacheMockRecorder) SetCtx(ctx, key, v, ex any) *gomock.Call {
type MockParser struct { type MockParser struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *MockParserMockRecorder recorder *MockParserMockRecorder
isgomock struct{}
} }
// MockParserMockRecorder is the mock recorder for MockParser. // MockParserMockRecorder is the mock recorder for MockParser.
@ -623,7 +590,6 @@ func (mr *MockParserMockRecorder) ParseWithClaims(tokenString, claims, keyFunc a
type MockClaims struct { type MockClaims struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *MockClaimsMockRecorder recorder *MockClaimsMockRecorder
isgomock struct{}
} }
// MockClaimsMockRecorder is the mock recorder for MockClaims. // MockClaimsMockRecorder is the mock recorder for MockClaims.
@ -737,7 +703,6 @@ func (mr *MockClaimsMockRecorder) GetSubject() *gomock.Call {
type MockServ struct { type MockServ struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *MockServMockRecorder recorder *MockServMockRecorder
isgomock struct{}
} }
// MockServMockRecorder is the mock recorder for MockServ. // MockServMockRecorder is the mock recorder for MockServ.
@ -758,7 +723,7 @@ func (m *MockServ) EXPECT() *MockServMockRecorder {
} }
// AddAvatarImageAndUsernameToMessage mocks base method. // AddAvatarImageAndUsernameToMessage mocks base method.
func (m *MockServ) AddAvatarImageAndUsernameToMessage(msgRaw domain.MessageRaw) (domain.Message, error) { func (m *MockServ) AddAvatarImageAndUsernameToMessage(msgRaw domain.RawMessage) (domain.Message, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddAvatarImageAndUsernameToMessage", msgRaw) ret := m.ctrl.Call(m, "AddAvatarImageAndUsernameToMessage", msgRaw)
ret0, _ := ret[0].(domain.Message) ret0, _ := ret[0].(domain.Message)
@ -773,7 +738,7 @@ func (mr *MockServMockRecorder) AddAvatarImageAndUsernameToMessage(msgRaw any) *
} }
// AddAvatarImageAndUsernameToMessages mocks base method. // AddAvatarImageAndUsernameToMessages mocks base method.
func (m *MockServ) AddAvatarImageAndUsernameToMessages(msgsRaw []domain.MessageRaw) []domain.Message { func (m *MockServ) AddAvatarImageAndUsernameToMessages(msgsRaw []domain.RawMessage) []domain.Message {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddAvatarImageAndUsernameToMessages", msgsRaw) ret := m.ctrl.Call(m, "AddAvatarImageAndUsernameToMessages", msgsRaw)
ret0, _ := ret[0].([]domain.Message) ret0, _ := ret[0].([]domain.Message)
@ -875,18 +840,18 @@ func (mr *MockServMockRecorder) FindOne(username, email any) *gomock.Call {
} }
// Get mocks base method. // Get mocks base method.
func (m *MockServ) Get(userID int) (domain.User, error) { func (m *MockServ) Get(userID int, isFast bool) (domain.User, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Get", userID) ret := m.ctrl.Call(m, "Get", userID, isFast)
ret0, _ := ret[0].(domain.User) ret0, _ := ret[0].(domain.User)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
// Get indicates an expected call of Get. // Get indicates an expected call of Get.
func (mr *MockServMockRecorder) Get(userID any) *gomock.Call { func (mr *MockServMockRecorder) Get(userID, isFast any) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockServ)(nil).Get), userID) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockServ)(nil).Get), userID, isFast)
} }
// GetAll mocks base method. // GetAll mocks base method.
@ -904,21 +869,6 @@ func (mr *MockServMockRecorder) GetAll(username any) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAll", reflect.TypeOf((*MockServ)(nil).GetAll), username) 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. // GetMessage mocks base method.
func (m *MockServ) GetMessage(ID domain.UUID) (domain.Message, error) { func (m *MockServ) GetMessage(ID domain.UUID) (domain.Message, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@ -950,10 +900,10 @@ func (mr *MockServMockRecorder) GetPinned(chatID any) *gomock.Call {
} }
// GetRaw mocks base method. // GetRaw mocks base method.
func (m *MockServ) GetRaw(ID domain.UUID) (domain.MessageRaw, error) { func (m *MockServ) GetRaw(ID domain.UUID) (domain.RawMessage, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetRaw", ID) ret := m.ctrl.Call(m, "GetRaw", ID)
ret0, _ := ret[0].(domain.MessageRaw) ret0, _ := ret[0].(domain.RawMessage)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -965,18 +915,18 @@ func (mr *MockServMockRecorder) GetRaw(ID any) *gomock.Call {
} }
// GetSome mocks base method. // GetSome mocks base method.
func (m *MockServ) GetSome(chatID, messageNumberFrom, messagesToGet int) ([]domain.Message, error) { func (m *MockServ) GetSome(chatID, offset, limit int) ([]domain.Message, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetSome", chatID, messageNumberFrom, messagesToGet) ret := m.ctrl.Call(m, "GetSome", chatID, offset, limit)
ret0, _ := ret[0].([]domain.Message) ret0, _ := ret[0].([]domain.Message)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
// GetSome indicates an expected call of GetSome. // GetSome indicates an expected call of GetSome.
func (mr *MockServMockRecorder) GetSome(chatID, messageNumberFrom, messagesToGet any) *gomock.Call { func (mr *MockServMockRecorder) GetSome(chatID, offset, limit any) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSome", reflect.TypeOf((*MockServ)(nil).GetSome), chatID, messageNumberFrom, messagesToGet) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSome", reflect.TypeOf((*MockServ)(nil).GetSome), chatID, offset, limit)
} }
// GetVerificated mocks base method. // GetVerificated mocks base method.
@ -1054,18 +1004,6 @@ func (mr *MockServMockRecorder) SendMessage(userID, chatID, message any) *gomock
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMessage", reflect.TypeOf((*MockServ)(nil).SendMessage), userID, chatID, message) 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. // Unpin mocks base method.
func (m *MockServ) Unpin(chatID int, messageID domain.UUID) error { func (m *MockServ) Unpin(chatID int, messageID domain.UUID) error {
m.ctrl.T.Helper() m.ctrl.T.Helper()

View file

@ -17,9 +17,7 @@ import (
//go:generate mockgen -source=service.go -destination=mocks/mock.go //go:generate mockgen -source=service.go -destination=mocks/mock.go
type User interface { type User interface {
GetCachedUser(userID int) (domain.User, error) Get(userID int, isFast bool) (domain.User, error)
SetCachedUser(u domain.User)
Get(userID int) (domain.User, error)
GetVerificated(userID int) (domain.User, error) GetVerificated(userID int) (domain.User, error)
GetAll(username string) ([]domain.User, error) GetAll(username string) ([]domain.User, error)
FindOne(username, email string) (domain.User, error) FindOne(username, email string) (domain.User, error)
@ -37,12 +35,12 @@ type Auth interface {
type Chat interface{} type Chat interface{}
type Messages interface { type Messages interface {
AddAvatarImageAndUsernameToMessage(msgRaw domain.MessageRaw) (domain.Message, error) AddAvatarImageAndUsernameToMessage(msgRaw domain.RawMessage) (domain.Message, error)
AddAvatarImageAndUsernameToMessages(msgsRaw []domain.MessageRaw) []domain.Message AddAvatarImageAndUsernameToMessages(msgsRaw []domain.RawMessage) []domain.Message
GetRaw(ID domain.UUID) (domain.RawMessage, error)
GetMessage(ID domain.UUID) (domain.Message, error) GetMessage(ID domain.UUID) (domain.Message, error)
GetRaw(ID domain.UUID) (domain.MessageRaw, error)
GetPinned(chatID int) ([]domain.Message, error) GetPinned(chatID int) ([]domain.Message, error)
GetSome(chatID, messageNumberFrom, messagesToGet int) ([]domain.Message, error) GetSome(chatID, offset, limit int) ([]domain.Message, error)
SendMessage(userID, chatID int, message domain.SendMessage) (domain.Message, error) SendMessage(userID, chatID int, message domain.SendMessage) (domain.Message, error)
Delete(ID domain.UUID) error Delete(ID domain.UUID) error
Edit(ID domain.UUID, newMessage, newImageUrl string) error Edit(ID domain.UUID, newMessage, newImageUrl string) error
@ -51,8 +49,8 @@ type Messages interface {
} }
type Cache interface { type Cache interface {
Get(key string, v encoding.BinaryUnmarshaler) error Get(key string, v encoding.BinaryUnmarshaler, isFast bool) error
GetCtx(ctx context.Context, key string, v encoding.BinaryUnmarshaler) error GetCtx(ctx context.Context, key string, v encoding.BinaryUnmarshaler, isFast bool) error
Set(key string, v encoding.BinaryMarshaler, ex time.Duration) error Set(key string, v encoding.BinaryMarshaler, ex time.Duration) error
SetCtx(ctx context.Context, key string, v encoding.BinaryMarshaler, ex time.Duration) error SetCtx(ctx context.Context, key string, v encoding.BinaryMarshaler, ex time.Duration) error
} }

View file

@ -23,9 +23,9 @@ func Test_NewService(t *testing.T) {
rdb := &redis.Client{} rdb := &redis.Client{}
serv := NewService(repo, cfg, log, rdb) serv := NewService(repo, cfg, log, rdb)
cache := &cacheService{l: log, r: rdb} cache := &cacheService{l: log, r: rdb, storage: &sync.Map{}}
auth := &authService{cfg: cfg.JWT, parser: jwt.NewParser(), l: log} auth := &authService{cfg: cfg.JWT, parser: jwt.NewParser(), l: log}
user := &userService{ur: repo, auth: auth, l: log, cache: cache, m: &sync.Map{}} user := &userService{ur: repo, auth: auth, l: log, cache: cache}
expectedServ := &Service{ expectedServ := &Service{
User: user, User: user,
Auth: auth, Auth: auth,

View file

@ -3,7 +3,6 @@ package service
import ( import (
"errors" "errors"
"fmt" "fmt"
"sync"
"time" "time"
"git.urec56.ru/urec/chat_back_go/internal/domain" "git.urec56.ru/urec/chat_back_go/internal/domain"
@ -13,58 +12,30 @@ import (
type userService struct { type userService struct {
cache Cache cache Cache
m *sync.Map
ur repository.User ur repository.User
auth Auth auth Auth
l *logger.Logger l *logger.Logger
} }
type userCache struct {
u domain.User
expiresAt time.Time
}
func newUserService(user repository.User, auth Auth, l *logger.Logger, cache Cache) *userService { 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{}} return &userService{ur: user, auth: auth, l: l, cache: cache}
} }
func (s *userService) GetCachedUser(userID int) (domain.User, error) { func (s *userService) Get(userID int, isFast bool) (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 := domain.User{} u := domain.User{}
err := s.cache.Get(fmt.Sprintf("user: {'id': %d}", userID), &u) err := s.cache.Get(fmt.Sprintf("user: {'id': %d}", userID), &u, isFast)
if err == nil { if err == nil {
return u, nil return u, nil
} }
s.l.Infof("error getting user from cache: %s", err.Error()) s.l.Infof("error getting user from cache: %s", err)
u, err = s.ur.GetByID(userID) u, err = s.ur.GetByID(userID)
if err != nil { if err != nil {
return u, err return u, err
} }
if err = s.cache.Set(fmt.Sprintf("user: {'id': %d}", userID), u, time.Second*20); err != nil { 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()) s.l.Infof("error setting user to cache: %s", err)
} }
return u, nil return u, nil
} }

View file

@ -5,7 +5,6 @@ import (
"errors" "errors"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.uber.org/mock/gomock" "go.uber.org/mock/gomock"
"sync"
"testing" "testing"
"time" "time"
@ -27,7 +26,7 @@ func Test_newUserService(t *testing.T) {
serv := newUserService(repo, auth, log, cache) serv := newUserService(repo, auth, log, cache)
assert.EqualValues(t, &userService{ur: repo, auth: auth, l: log, cache: cache, m: &sync.Map{}}, serv) assert.EqualValues(t, &userService{ur: repo, auth: auth, l: log, cache: cache}, serv)
} }
func TestUserService_Get(t *testing.T) { func TestUserService_Get(t *testing.T) {
@ -64,8 +63,10 @@ func TestUserService_Get(t *testing.T) {
name: "user_in_cache", name: "user_in_cache",
repoBehavior: 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) {},
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) { cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
c.EXPECT().Get(key, gomock.Any()).DoAndReturn( c.EXPECT().Get(key, gomock.Any(), false).DoAndReturn(
func(key string, v encoding.BinaryUnmarshaler) error { return v.UnmarshalBinary([]byte(`{"id": 1}`)) }, func(key string, v encoding.BinaryUnmarshaler, isFast bool) error {
return v.UnmarshalBinary([]byte(`{"id": 1}`))
},
) )
}, },
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {}, cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {},
@ -80,7 +81,7 @@ func TestUserService_Get(t *testing.T) {
r.EXPECT().GetByID(userID).Return(user, err) r.EXPECT().GetByID(userID).Return(user, err)
}, },
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) { cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
c.EXPECT().Get(key, gomock.Any()).Return(err) c.EXPECT().Get(key, gomock.Any(), false).Return(err)
}, },
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) { cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {
c.EXPECT().Set(key, v, ex).Return(err) c.EXPECT().Set(key, v, ex).Return(err)
@ -99,7 +100,7 @@ func TestUserService_Get(t *testing.T) {
r.EXPECT().GetByID(userID).Return(user, err) r.EXPECT().GetByID(userID).Return(user, err)
}, },
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) { cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
c.EXPECT().Get(key, gomock.Any()).Return(err) c.EXPECT().Get(key, gomock.Any(), false).Return(err)
}, },
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {}, cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {},
cacheKey: "user: {'id': 1}", cacheKey: "user: {'id': 1}",
@ -115,7 +116,7 @@ func TestUserService_Get(t *testing.T) {
r.EXPECT().GetByID(userID).Return(user, err) r.EXPECT().GetByID(userID).Return(user, err)
}, },
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) { cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
c.EXPECT().Get(key, gomock.Any()).Return(err) c.EXPECT().Get(key, gomock.Any(), false).Return(err)
}, },
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) { cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {
c.EXPECT().Set(key, v, ex).Return(err) c.EXPECT().Set(key, v, ex).Return(err)
@ -134,7 +135,7 @@ func TestUserService_Get(t *testing.T) {
r.EXPECT().GetByID(userID).Return(user, err) r.EXPECT().GetByID(userID).Return(user, err)
}, },
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) { cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
c.EXPECT().Get(key, gomock.Any()).Return(err) c.EXPECT().Get(key, gomock.Any(), false).Return(err)
}, },
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) { cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {
c.EXPECT().Set(key, v, ex).Return(err) c.EXPECT().Set(key, v, ex).Return(err)
@ -154,7 +155,7 @@ func TestUserService_Get(t *testing.T) {
r.EXPECT().GetByID(userID).Return(user, err) r.EXPECT().GetByID(userID).Return(user, err)
}, },
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) { cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
c.EXPECT().Get(key, gomock.Any()).Return(err) c.EXPECT().Get(key, gomock.Any(), false).Return(err)
}, },
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {}, cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {},
cacheKey: "user: {'id': 1}", cacheKey: "user: {'id': 1}",
@ -178,9 +179,9 @@ func TestUserService_Get(t *testing.T) {
tc.repoBehavior(repo, tc.userID, tc.repoUser, tc.repoErr) tc.repoBehavior(repo, tc.userID, tc.repoUser, tc.repoErr)
tc.cacheGetBehavior(cache, tc.cacheKey, tc.cacheGetData.container, tc.cacheGetData.err) 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) tc.cacheSetBehavior(cache, tc.cacheKey, &tc.cacheSetData.value, tc.cacheSetData.duration, tc.cacheSetData.err)
u, err := serv.Get(tc.userID) u, err := serv.Get(tc.userID, false)
assert.Equal(t, tc.expectedUser, u) assert.Equal(t, tc.expectedUser, u)
assert.ErrorIs(t, err, tc.expectedErr) assert.ErrorIs(t, err, tc.expectedErr)

View file

@ -17,7 +17,7 @@ func (h *Handler) GetUsers(w http.ResponseWriter, r *http.Request) {
users, err := h.serv.GetAll(username) users, err := h.serv.GetAll(username)
if err != nil { if err != nil {
h.l.Infof("[%s] getting users: %s", r.URL.Path, err.Error()) h.l.Infof("[%s] getting users: %s", r.URL.Path, err)
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
return return
} }
@ -25,7 +25,7 @@ func (h *Handler) GetUsers(w http.ResponseWriter, r *http.Request) {
j, _ := json.Marshal(map[string][]domain.User{"users": users}) // no error because []domain.User can`t cause any error here j, _ := json.Marshal(map[string][]domain.User{"users": users}) // no error because []domain.User can`t cause any error here
if _, err = w.Write(j); err != nil { if _, err = w.Write(j); err != nil {
h.l.Errorf("[%s] writing response: %s", r.URL.Path, err.Error()) h.l.Errorf("[%s] writing response: %s", r.URL.Path, err)
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
return return
} }
@ -42,14 +42,14 @@ func (h *Handler) CheckExisting(w http.ResponseWriter, r *http.Request) {
} }
if err := domain.V.Struct(userFilter); err != nil { if err := domain.V.Struct(userFilter); err != nil {
h.l.Infof("[%s] validation: %s", r.URL.Path, err.Error()) h.l.Infof("[%s] validation: %s", r.URL.Path, err)
w.WriteHeader(http.StatusUnprocessableEntity) w.WriteHeader(http.StatusUnprocessableEntity)
return return
} }
u, err := h.serv.FindOne(userFilter.Username, userFilter.Email) u, err := h.serv.FindOne(userFilter.Username, userFilter.Email)
if err != nil { if err != nil {
h.l.Infof("[%s] serv.FindOne error: %s", r.URL.Path, err.Error()) h.l.Infof("[%s] serv.FindOne error: %s", r.URL.Path, err)
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
return return
} }
@ -77,7 +77,7 @@ func (h *Handler) Register(w http.ResponseWriter, r *http.Request) {
} }
if err := domain.V.Struct(userData); err != nil { if err := domain.V.Struct(userData); err != nil {
h.l.Infof("[%s] validation: %s", r.URL.Path, err.Error()) h.l.Infof("[%s] validation: %s", r.URL.Path, err)
w.WriteHeader(http.StatusUnprocessableEntity) w.WriteHeader(http.StatusUnprocessableEntity)
return return
} }
@ -87,7 +87,7 @@ func (h *Handler) Register(w http.ResponseWriter, r *http.Request) {
if errors.Is(err, domain.UserAlreadyExistsError) { if errors.Is(err, domain.UserAlreadyExistsError) {
w.WriteHeader(http.StatusConflict) w.WriteHeader(http.StatusConflict)
} else { } else {
h.l.Infof("[%s] serv.Register: %s", r.URL.Path, err.Error()) h.l.Infof("[%s] serv.Register: %s", r.URL.Path, err)
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
} }
return return
@ -97,7 +97,7 @@ func (h *Handler) Register(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusCreated) w.WriteHeader(http.StatusCreated)
if _, err = w.Write(resp); err != nil { if _, err = w.Write(resp); err != nil {
h.l.Errorf("[%s] writing response: %s", r.URL.Path, err.Error()) h.l.Errorf("[%s] writing response: %s", r.URL.Path, err)
return return
} }
} }
@ -125,7 +125,7 @@ func (h *Handler) Get(w http.ResponseWriter, r *http.Request) {
j, _ := json.Marshal(user) // no error because domain.User can`t cause any error here j, _ := json.Marshal(user) // no error because domain.User can`t cause any error here
if _, err := w.Write(j); err != nil { if _, err := w.Write(j); err != nil {
h.l.Errorf("[%s] writing response: %s", r.URL.Path, err.Error()) h.l.Errorf("[%s] writing response: %s", r.URL.Path, err)
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
return return
} }

View file

@ -13,25 +13,25 @@ func (m *Middleware) Auth(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
t, err := m.serv.ExtractAuthToken(r) t, err := m.serv.ExtractAuthToken(r)
if err != nil { if err != nil {
m.l.Infof("[%s] error extracting token: %s", r.URL.Path, err.Error()) m.l.Infof("[%s] error extracting token: %s", r.URL.Path, err)
w.WriteHeader(http.StatusUnauthorized) w.WriteHeader(http.StatusUnauthorized)
return return
} }
userID, err := m.serv.DecodeAuthToken(t) userID, err := m.serv.DecodeAuthToken(t)
if err != nil { if err != nil {
m.l.Infof("[%s] error decoding token: %s", r.URL.Path, err.Error()) m.l.Infof("[%s] error decoding token: %s", r.URL.Path, err)
w.WriteHeader(http.StatusUnauthorized) w.WriteHeader(http.StatusUnauthorized)
return return
} }
user, err := m.serv.Get(userID) user, err := m.serv.Get(userID, false)
if err != nil { if err != nil {
if errors.Is(err, domain.UserNotFoundError) { if errors.Is(err, domain.UserNotFoundError) {
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
return return
} }
m.l.Infof("[%s] error resolving user: %s", r.URL.Path, err.Error()) m.l.Infof("[%s] error resolving user: %s", r.URL.Path, err)
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
return return
} }
@ -48,14 +48,14 @@ func (m *Middleware) VerificatedAuth(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
t, err := m.serv.ExtractAuthToken(r) t, err := m.serv.ExtractAuthToken(r)
if err != nil { if err != nil {
m.l.Infof("[%s] error extracting token: %s", r.URL.Path, err.Error()) m.l.Infof("[%s] error extracting token: %s", r.URL.Path, err)
w.WriteHeader(http.StatusUnauthorized) w.WriteHeader(http.StatusUnauthorized)
return return
} }
userID, err := m.serv.DecodeAuthToken(t) userID, err := m.serv.DecodeAuthToken(t)
if err != nil { if err != nil {
m.l.Infof("[%s] error decoding token: %s", r.URL.Path, err.Error()) m.l.Infof("[%s] error decoding token: %s", r.URL.Path, err)
w.WriteHeader(http.StatusUnauthorized) w.WriteHeader(http.StatusUnauthorized)
return return
} }
@ -68,7 +68,7 @@ func (m *Middleware) VerificatedAuth(next http.HandlerFunc) http.HandlerFunc {
w.WriteHeader(http.StatusConflict) w.WriteHeader(http.StatusConflict)
return return
} }
m.l.Infof("[%s] error resolving user: %s", r.URL.Path, err.Error()) m.l.Infof("[%s] error resolving user: %s", r.URL.Path, err)
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
return return
} }

View file

@ -44,7 +44,7 @@ func TestMiddleware_Auth(t *testing.T) {
s.EXPECT().DecodeAuthToken(token).Return(userID, err) s.EXPECT().DecodeAuthToken(token).Return(userID, err)
}, },
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) { getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {
s.EXPECT().Get(userID).Return(user, err) s.EXPECT().Get(userID, false).Return(user, err)
}, },
reqToken: "Bearer token", reqToken: "Bearer token",
extractToken: "token", extractToken: "token",
@ -82,7 +82,7 @@ func TestMiddleware_Auth(t *testing.T) {
s.EXPECT().DecodeAuthToken(token).Return(userID, err) s.EXPECT().DecodeAuthToken(token).Return(userID, err)
}, },
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) { getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {
s.EXPECT().Get(userID).Return(user, err) s.EXPECT().Get(userID, false).Return(user, err)
}, },
reqToken: "Bearer token", reqToken: "Bearer token",
extractToken: "token", extractToken: "token",
@ -122,7 +122,7 @@ func TestMiddleware_Auth(t *testing.T) {
s.EXPECT().DecodeAuthToken(token).Return(userID, err) s.EXPECT().DecodeAuthToken(token).Return(userID, err)
}, },
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) { getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {
s.EXPECT().Get(userID).Return(user, err) s.EXPECT().Get(userID, false).Return(user, err)
}, },
getErr: domain.AnyError, getErr: domain.AnyError,
logErr: domain.AnyError, logErr: domain.AnyError,

View file

@ -3,9 +3,11 @@ package rest
import ( import (
"context" "context"
"expvar" "expvar"
"github.com/urec56/pathparams" "fmt"
"net/http" "net/http"
"github.com/urec56/pathparams"
"git.urec56.ru/urec/chat_back_go/config" "git.urec56.ru/urec/chat_back_go/config"
"git.urec56.ru/urec/chat_back_go/internal/logger" "git.urec56.ru/urec/chat_back_go/internal/logger"
"git.urec56.ru/urec/chat_back_go/internal/service" "git.urec56.ru/urec/chat_back_go/internal/service"
@ -23,11 +25,11 @@ 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)} return &Server{m: middleware.NewMiddleware(serv, l, cfg.Srv), h: handler.NewHandler(serv, l)}
} }
func (s *Server) Run(port string) error { func (s *Server) Run(port int) error {
r := s.getRouter() r := s.getRouter()
s.httpServer = &http.Server{ s.httpServer = &http.Server{
Addr: ":" + port, Addr: fmt.Sprintf(":%d", port),
Handler: r, Handler: r,
} }