diff --git a/api/proto/session.proto b/api/proto/session.proto new file mode 100644 index 0000000..69e36d7 --- /dev/null +++ b/api/proto/session.proto @@ -0,0 +1,34 @@ +syntax = "proto3"; + +package session; + +option go_package = "session_service/gen"; + +service SessionService { + rpc CreateSession (SaveSessionRequest) returns (SaveSessionResponse); + rpc GetSession (GetSessionRequest) returns (GetSessionResponse); + rpc DeleteSession (DeleteSessionRequest) returns (DeleteSessionResponse); +} + +message SaveSessionRequest { + int32 userID = 1; +} + +message SaveSessionResponse { + string sessionID = 1; +} + +message GetSessionRequest { + string sessionID = 1; +} + +message GetSessionResponse { + int32 userID = 1; +} + +message DeleteSessionRequest { + string sessionID = 1; +} + +message DeleteSessionResponse { +} diff --git a/cmd/2024_1_ResCogitans/main.go b/cmd/2024_1_ResCogitans/main.go index fb7c24f..78c8eaf 100644 --- a/cmd/2024_1_ResCogitans/main.go +++ b/cmd/2024_1_ResCogitans/main.go @@ -1,51 +1,81 @@ package main import ( + "fmt" + "log" + + "github.com/go-chi/chi/v5" + "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/delivery/server" + "go.uber.org/dig" + "golang.org/x/exp/slog" + "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/config" "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/delivery/initialization" - "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/delivery/server" + "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/usecase" "github.com/go-park-mail-ru/2024_1_ResCogitans/router" "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/logger" - _ "github.com/swaggo/http-swagger/example/go-chi/docs" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" ) -// @title Swagger Example API -// @version 1.0 -// @description This is a sample server seller server. -// @termsOfService http://swagger.io/terms/ - -// @contact.name API Support -// @contact.url http://www.swagger.io/support -// @contact.email support@swagger.io - -// @license.name Apache 2.0 -// @license.url http://www.apache.org/licenses/LICENSE-2.0.html - -// @host localhost:8080 -// @BasePath /api/v1 func main() { - logger := logger.Logger() + container := dig.New() + cfg, err := config.LoadConfig() if err != nil { - logger.Error("Failed to load config", "error", err) - return + log.Fatalf("Failed to load config: %v", err) } - logger.Info("Start config") - pdb, rdb, cdb, err := initialization.DataBaseInitialization() - if err != nil { - logger.Error("DataBase initialization error", "error", err) + logg := logger.NewLogger(cfg) + + if err := container.Provide(func() *config.Config { return cfg }); err != nil { + log.Fatalf("Failed to provide config: %v", err) + } + if err := container.Provide(func() *slog.Logger { return logg }); err != nil { + log.Fatalf("Failed to provide logger: %v", err) + } + + if err := registerDependencies(container); err != nil { + logg.Error("Failed to register dependencies", "error", err) return } - storages := initialization.StorageInit(pdb, rdb, cdb) - usecases := initialization.UseCaseInit(storages) - handlers := initialization.HandlerInit(usecases) + err = container.Invoke(func(cfg *config.Config, logger *slog.Logger, r *chi.Mux) { + logger.Info(fmt.Sprintf("Server is listening on %s", cfg.HTTPServer.Address)) + + if err := server.StartServer(r, cfg); err != nil { + logger.Error("Failed to start server", "error", err) + } + }) + if err != nil { + logg.Error("Failed to start application", "error", err) + } +} - router := router.SetupRouter(cfg, handlers) +func registerDependencies(container *dig.Container) error { + // Создание среза функций-зависимостей, возвращающих ошибку, которая будет в дальнейшем записываться в логи + providers := []func() error{ + func() error { + return container.Provide(func(cfg *config.Config, logger *slog.Logger) (*grpc.ClientConn, error) { + conn, err := grpc.NewClient(fmt.Sprintf("%s:%d", cfg.SessionService.Host, cfg.SessionService.Port), grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + return nil, fmt.Errorf("failed to connect to gRPC server: %w", err) + } + return conn, nil + }) + }, + func() error { return container.Provide(initialization.DataBaseInitialization) }, + func() error { return container.Provide(initialization.StorageInit) }, + func() error { return container.Provide(usecase.NewSessionUseCase) }, + func() error { return container.Provide(initialization.UseCaseInit) }, + func() error { return container.Provide(initialization.HandlerInit) }, + func() error { return container.Provide(router.SetupRouter) }, + } - if err := server.StartServer(router, cfg); err != nil { - logger.Error("Failed to start server", "error", err) - return + for _, provider := range providers { + if err := provider(); err != nil { + return err + } } + return nil } diff --git a/docker/Dockerfile b/docker/Dockerfile deleted file mode 100644 index 96a63f8..0000000 --- a/docker/Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -# Используем базовый образ PostgreSQL -FROM postgres:13.2 - -# Переменные окружения для настройки базы данных -ENV POSTGRES_DB=jantugan -ENV POSTGRES_USER=mrdzhofik -ENV POSTGRES_PASSWORD=246858 - -# Копируем init.sql в контейнер -COPY init.sql /docker-entrypoint-initdb.d/ - -# По умолчанию PostgreSQL слушает порт 5432 -EXPOSE 5432 - -# Команда для запуска PostgreSQL сервера -CMD ["postgres"] diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml deleted file mode 100644 index 20c0697..0000000 --- a/docker/docker-compose.yml +++ /dev/null @@ -1,13 +0,0 @@ -version: '3' -services: - postgres: - build: - context: . - dockerfile: Dockerfile - image: postgres:13.2 - ports: - - "15432:15432" - environment: - POSTGRES_DB: jantugan - POSTGRES_USER: mrdzhofik - POSTGRES_PASSWORD: 246858 diff --git a/go.mod b/go.mod index 09b009c..544166e 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,7 @@ module github.com/go-park-mail-ru/2024_1_ResCogitans go 1.22.0 require ( - github.com/go-chi/chi v4.1.2+incompatible - github.com/go-chi/chi/v5 v5.0.12 + github.com/go-chi/chi/v5 v5.1.0 github.com/go-redis/redis/v8 v8.11.5 github.com/gorilla/securecookie v1.1.2 github.com/ilyakaznacheev/cleanenv v1.5.0 @@ -12,33 +11,40 @@ require ( github.com/microcosm-cc/bluemonday v1.0.26 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.9.0 - github.com/swaggo/http-swagger v1.3.4 - github.com/swaggo/http-swagger/example/go-chi v0.0.0-20230830153024-537f045bded0 github.com/swaggo/swag v1.16.3 - golang.org/x/crypto v0.22.0 - golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 + go.uber.org/dig v1.17.1 + golang.org/x/crypto v0.24.0 + golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 + google.golang.org/grpc v1.64.0 + google.golang.org/protobuf v1.34.1 ) require ( github.com/KyleBanks/depth v1.2.1 // indirect + github.com/PuerkitoBio/purell v1.1.1 // indirect + github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/aymerick/douceur v0.2.0 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/go-openapi/jsonpointer v0.21.0 // indirect - github.com/go-openapi/jsonreference v0.21.0 // indirect - github.com/go-openapi/spec v0.21.0 // indirect - github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.19.6 // indirect + github.com/go-openapi/spec v0.20.4 // indirect + github.com/go-openapi/swag v0.19.15 // indirect github.com/gorilla/css v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/lib/pq v1.10.2 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/tools v0.20.0 // indirect + github.com/mailru/easyjson v0.7.6 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect + golang.org/x/net v0.26.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/tools v0.22.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.2.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/georgysavva/scany/v2 v2.1.2 github.com/google/uuid v1.6.0 @@ -48,7 +54,7 @@ require ( github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect ) diff --git a/go.sum b/go.sum index afd00d2..4a46ccc 100644 --- a/go.sum +++ b/go.sum @@ -1,19 +1,17 @@ -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +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.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= +github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cockroachdb/cockroach-go/v2 v2.2.0 h1:/5znzg5n373N/3ESjHF5SMLxiW4RKB05Ql//KWfeTFs= github.com/cockroachdb/cockroach-go/v2 v2.2.0/go.mod h1:u3MiKYGupPPjkn3ozknpMUpxPaNLTFWAya419/zv6eI= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -24,36 +22,28 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/georgysavva/scany/v2 v2.1.2 h1:Apd23j4aE+MfOrqNWi6yTygZlQTjczLF+wARMIn9K38= github.com/georgysavva/scany/v2 v2.1.2/go.mod h1:fqp9yHZzM/PFVa3/rYEC57VmDx+KDch0LoqrJzkvtos= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= -github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= -github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s= -github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= +github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -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.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs= github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= -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/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M= github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= -github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -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/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -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-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +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/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= @@ -72,10 +62,9 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= 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/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -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.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -84,9 +73,8 @@ github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= @@ -96,21 +84,12 @@ github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= -github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U= -github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= -github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= -github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= -github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= @@ -119,75 +98,39 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe h1:K8pHPVoTgxFJt1lXuIzzOX7zZhZFldJQK/CgKx9BFIc= -github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w= -github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM= -github.com/swaggo/http-swagger v1.3.4 h1:q7t/XLx0n15H1Q9/tk3Y9L4n210XzJF5WtnDX64a5ww= -github.com/swaggo/http-swagger v1.3.4/go.mod h1:9dAh0unqMBAlbp1uE2Uc2mQTxNMU/ha4UbucIg1MFkQ= -github.com/swaggo/http-swagger/example/go-chi v0.0.0-20230830153024-537f045bded0 h1:VN0Rt8DTuji1kabhwDHIQXB6cSdtqSVz9JhuUjyYfS0= -github.com/swaggo/http-swagger/example/go-chi v0.0.0-20230830153024-537f045bded0/go.mod h1:iDQxwioFVsJ9zSsAGrCLsL+gDRY8kgVq8ieTVcNHWvQ= -github.com/swaggo/http-swagger/v2 v2.0.0/go.mod h1:XYhrQVIKz13CxuKD4p4kvpaRB4jJ1/MlfQXVOE+CX8Y= -github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ= github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg= github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk= -github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= -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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -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= +go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc= +go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/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-20210809222454-d867a43fc93e/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-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= -golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= +google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -196,7 +139,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/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= diff --git a/images/arg_messi.jpeg b/images/arg_messi.jpeg deleted file mode 100644 index 3865ea4..0000000 Binary files a/images/arg_messi.jpeg and /dev/null differ diff --git a/internal/config/config.go b/internal/config/config.go index 04f7c19..62d973d 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -13,6 +13,7 @@ type Config struct { Env string `yaml:"env" env:"ENV" env-required:"true"` StoragePath string `yaml:"storage_path" env-required:"true"` HTTPServer `yaml:"http_server"` + SessionService `yaml:"session_service"` Dsn `yaml:"dsn"` Redis `yaml:"redis"` CSRF `yaml:"csrf"` @@ -27,6 +28,11 @@ type HTTPServer struct { Password string `yaml:"password" env-required:"true" env:"HTTP_SERVER_PASSWORD"` } +type SessionService struct { + Host string `env:"SESSION_HOST"` + Port int `env:"SESSION_PORT"` +} + type Dsn struct { Host string `env:"DB_POSTGRES_HOST"` Port int `env:"DB_POSTGRES_PORT"` diff --git a/config/local.yaml b/internal/config/local.yaml similarity index 100% rename from config/local.yaml rename to internal/config/local.yaml diff --git a/internal/delivery/db/db.go b/internal/delivery/db/db.go index d58e971..7cd7835 100644 --- a/internal/delivery/db/db.go +++ b/internal/delivery/db/db.go @@ -6,79 +6,48 @@ import ( "time" "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/config" - "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/logger" "github.com/go-redis/redis/v8" "github.com/jackc/pgx/v5/pgxpool" + "github.com/pkg/errors" ) -// GetPostgress gets connection to postgres database -func GetPostgres() (*pgxpool.Pool, error) { - log := logger.Logger() - - cfg, err := config.LoadConfig() - if err != nil { - log.Error("Failed to load database config", "error", err) - return nil, err - } - +// GetPostgres соединение с базой данных +func GetPostgres(cfg *config.Config) (*pgxpool.Pool, error) { dsn := buildDSN(cfg.Dsn) + // создание конфигурации базы данных poolConfig, err := pgxpool.ParseConfig(dsn) if err != nil { - log.Error("Failed to parse database config", "error", err) - return nil, err + return nil, errors.Wrap(err, "failed to parse database config") } - poolConfig.MaxConns = 10 - poolConfig.MaxConnLifetime = time.Hour + poolConfig.MaxConns = 10 // Максимальное число пользователей + poolConfig.MaxConnLifetime = time.Hour // Время жизни соединения - pool, err := pgxpool.New(context.Background(), dsn) + // Соединение с базой данных с использованием созданной конфигурацией + pool, err := pgxpool.NewWithConfig(context.Background(), poolConfig) if err != nil { - log.Error("Failed to connect to database", "error", err) - return nil, err + return nil, errors.Wrap(err, "failed to connect to database") } return pool, nil } +// buildDSN создание пути для базы данных func buildDSN(cfg config.Dsn) string { return fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", cfg.Host, cfg.Port, cfg.User, cfg.Password, cfg.DBName) } -func GetRedis() (*redis.Client, error) { - cfg, err := config.LoadConfig() - if err != nil { - return nil, err - } - rdb := redis.NewClient(&redis.Options{ - Addr: fmt.Sprintf("%s:%d", cfg.Redis.Host, cfg.Redis.Port), - Password: cfg.Redis.Password, - DB: cfg.Redis.DB, - }) - - // Проверяем соединение с Redis - _, err = rdb.Ping(rdb.Context()).Result() - if err != nil { - return nil, err - } - - return rdb, nil -} - -func GetCSRFRedis() (*redis.Client, error) { - cfg, err := config.LoadConfig() - if err != nil { - return nil, err - } +func GetCSRFRedis(cfg *config.Config) (*redis.Client, error) { rdb := redis.NewClient(&redis.Options{ Addr: fmt.Sprintf("%s:%d", cfg.CSRF.Host, cfg.CSRF.Port), Password: cfg.CSRF.Password, DB: cfg.CSRF.DB, }) - // Проверяем соединение с Redis - _, err = rdb.Ping(rdb.Context()).Result() + // Проверка соединения с базой данных + _, err := rdb.Ping(rdb.Context()).Result() if err != nil { return nil, err } diff --git a/internal/delivery/file.go b/internal/delivery/file.go index 4bb94b2..9ac7d74 100644 --- a/internal/delivery/file.go +++ b/internal/delivery/file.go @@ -9,8 +9,8 @@ import ( "strings" "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/config" - "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/logger" "github.com/pkg/errors" + "golang.org/x/exp/slog" ) type FileHandler struct{} @@ -61,9 +61,7 @@ func ValidateFileSize(handler *multipart.FileHeader) bool { return fileSize <= maxFileSizeBytes } -func SaveFile(r *http.Request) (string, error) { - logger := logger.Logger() - +func SaveFile(r *http.Request, logger *slog.Logger) (string, error) { r.ParseMultipartForm(10 << 20) file, handler, err := r.FormFile("file") if err != nil { diff --git a/internal/delivery/handlers/authorization/auth_handler_test.go b/internal/delivery/handlers/authorization/auth_handler_test.go index d7b13e8..0dcc8a8 100644 --- a/internal/delivery/handlers/authorization/auth_handler_test.go +++ b/internal/delivery/handlers/authorization/auth_handler_test.go @@ -1,76 +1,173 @@ package authorization_test -// import ( -// "context" -// "encoding/json" -// "net/http" -// "net/http/httptest" -// "strings" -// "testing" - -// "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities" -// // "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/http-server/handlers/login" -// "github.com/stretchr/testify/assert" -// ) - -// func TestAuthorize(t *testing.T) { -// authHandler := login.Authorization{} - -// entities.CreateUser("san", "123") - -// testCases := []struct { -// name string -// inputJSON string -// expectedStatus int -// expectedError string -// }{ -// { -// name: "Successful authorization", -// inputJSON: `{"username": "san", "password": "123"}`, -// expectedStatus: http.StatusOK, -// expectedError: "", -// }, -// { -// name: "Empty username", -// inputJSON: `{"username": "", "password": "testpassword"}`, -// expectedStatus: http.StatusUnauthorized, -// expectedError: "Authorization failed", -// }, -// { -// name: "Empty password", -// inputJSON: `{"username": "testuser", "password": ""}`, -// expectedStatus: http.StatusUnauthorized, -// expectedError: "Authorization failed", -// }, -// { -// name: "User not found", -// inputJSON: `{"username": "nonexistentuser", "password": "testpassword"}`, -// expectedStatus: http.StatusUnauthorized, -// expectedError: "Authorization failed", -// }, -// } - -// for _, tc := range testCases { -// t.Run(tc.name, func(t *testing.T) { -// req, err := http.NewRequest("POST", "/login", strings.NewReader(tc.inputJSON)) -// if err != nil { -// t.Fatal(err) -// } -// req.Header.Set("Content-Type", "application/json") - -// var user entities.User -// err = json.NewDecoder(req.Body).Decode(&user) -// if err != nil { -// t.Fatal(err) -// } - -// rr := httptest.NewRecorder() -// ctx := context.WithValue(req.Context(), "responseWriter", rr) -// ctx = context.WithValue(ctx, "requestData", user) - -// response, err := authHandler.Authorize(ctx) - -// assert.Equal(t, tc.expectedStatus, response.Status, "handler returned wrong status code") -// }) -// } -// } +import ( + "bytes" + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + + "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/delivery/handlers/authorization" + "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities" + httperrors "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/errors" + "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/httputils" + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +type MockSessionUseCase struct { + mock.Mock +} + +func (m *MockSessionUseCase) CreateSession(ctx context.Context, w http.ResponseWriter, userID int) error { + args := m.Called(ctx, w, userID) + return args.Error(0) +} + +func (m *MockSessionUseCase) GetSession(ctx context.Context, r *http.Request) (int, error) { + args := m.Called(ctx, r) + return args.Int(0), args.Error(1) +} + +func (m *MockSessionUseCase) ClearSession(ctx context.Context, w http.ResponseWriter, r *http.Request) error { + args := m.Called(ctx, w, r) + return args.Error(0) +} + +type MockUserUseCase struct { + mock.Mock +} + +func (m *MockUserUseCase) CreateUser(ctx context.Context, email string, password string) error { + args := m.Called(ctx, email, password) + return args.Error(0) +} + +func (m *MockUserUseCase) GetUserByEmail(ctx context.Context, email string) (entities.User, error) { + args := m.Called(ctx, email) + return args.Get(0).(entities.User), args.Error(1) +} + +func (m *MockUserUseCase) GetUserByID(ctx context.Context, userID int) (entities.User, error) { + args := m.Called(ctx, userID) + return args.Get(0).(entities.User), args.Error(1) +} + +func (m *MockUserUseCase) DeleteUser(ctx context.Context, userID int) error { + args := m.Called(ctx, userID) + return args.Error(0) +} + +func (m *MockUserUseCase) UserDataVerification(email, password string) error { + args := m.Called(email, password) + return args.Error(0) +} + +func (m *MockUserUseCase) ChangePassword(ctx context.Context, userID int, password string) (entities.User, error) { + args := m.Called(ctx, userID, password) + return args.Get(0).(entities.User), args.Error(1) +} + +func (m *MockUserUseCase) UserExists(ctx context.Context, email, password string) error { + args := m.Called(ctx, email, password) + return args.Error(0) +} + +func (m *MockUserUseCase) IsEmailTaken(ctx context.Context, email string) (bool, error) { + args := m.Called(ctx, email) + return args.Bool(0), args.Error(1) +} + +func TestAuthorizationHandler_Authorize(t *testing.T) { + mockSessionUseCase := new(MockSessionUseCase) + mockUserUseCase := new(MockUserUseCase) + + handler := authorization.NewAuthorizationHandler(mockSessionUseCase, mockUserUseCase) + + user := entities.User{Username: "san@boy.ru", Password: "ABC123abc123!"} + jsonUser, err := json.Marshal(user) + if err != nil { + require.Error(t, err, nil) + } + + req, err := http.NewRequest("POST", "/api/login", bytes.NewBuffer(jsonUser)) + if err != nil { + t.Fatal(err) + } + + // Создаем ResponseRecorder для записи ответа + rr := httptest.NewRecorder() + + // Добавляем запрос в контекст + ctx := context.WithValue(req.Context(), httputils.HttpRequestKey, req) + ctx = context.WithValue(ctx, httputils.ResponseWriterKey, rr) + + t.Run("Successful authorization", func(t *testing.T) { + mockSessionUseCase.On("GetSession", mock.Anything, mock.Anything).Return(0, nil) // Сессия не была установлена, значит пользователь не авторизован + mockUserUseCase.On("UserDataVerification", mock.Anything, mock.Anything).Return(nil) + mockUserUseCase.On("UserExists", mock.Anything, mock.Anything, mock.Anything).Return(nil) + mockUserUseCase.On("GetUserByEmail", mock.Anything, mock.Anything).Return(entities.User{ID: 1, Username: "san@boy.ru"}, nil) + mockSessionUseCase.On("CreateSession", mock.Anything, mock.Anything, mock.Anything).Return(nil) + + // Создаем тестовый запрос + jsonUser, err := json.Marshal(user) + if err != nil { + t.Fatal(err) + } + + req, err := http.NewRequest("POST", "/api/login", bytes.NewBuffer(jsonUser)) + if err != nil { + t.Fatal(err) + } + + // Создаем ResponseRecorder для записи ответа + rr := httptest.NewRecorder() + + // Добавляем запрос в контекст + ctx := context.WithValue(req.Context(), httputils.HttpRequestKey, req) + ctx = context.WithValue(ctx, httputils.ResponseWriterKey, rr) + + _, err = handler.Authorize(ctx, user) + assert.Error(t, err) + assert.Equal(t, "user not found", err.Error()) + + // Проверяем, что методы были вызваны с правильными аргументами + mockSessionUseCase.AssertExpectations(t) + mockUserUseCase.AssertExpectations(t) +} + +// Тесты для LogOut +//func TestAuthorizationHandler_LogOut(t *testing.T) { +// mockSessionUseCase := new(MockSessionUseCase) +// mockUserUseCase := new(MockUserUseCase) +// +// handler := authorization.NewAuthorizationHandler(mockSessionUseCase, mockUserUseCase) +// +// // Тест успешного выхода из системы +// mockSessionUseCase.On("GetSession", mock.Anything, mock.Anything).Return(1, nil) +// mockSessionUseCase.On("ClearSession", mock.Anything, mock.Anything, mock.Anything).Return(nil) +// +// _, err := handler.LogOut(context.Background(), entities.User{}) +// assert.NoError(t, err) +//} +// +//// Тесты для UpdatePassword +//func TestAuthorizationHandler_UpdatePassword(t *testing.T) { +// mockSessionUseCase := new(MockSessionUseCase) +// mockUserUseCase := new(MockUserUseCase) +// +// handler := authorization.NewAuthorizationHandler(mockSessionUseCase, mockUserUseCase) +// +// // Тест успешного обновления пароля +// mockSessionUseCase.On("GetSession", mock.Anything, mock.Anything).Return(1, nil) +// mockUserUseCase.On("UserDataVerification", mock.Anything, mock.Anything).Return(nil) +// mockUserUseCase.On("ChangePassword", mock.Anything, mock.Anything, mock.Anything).Return(entities.User{ID: 1, Username: "testuser"}, nil) +// +// userResponse, err := handler.UpdatePassword(context.Background(), entities.User{Username: "testuser", Password: "newpassword"}) +// assert.NoError(t, err) +// assert.Equal(t, entities.UserResponse{ID: 1, Username: "testuser"}, userResponse) +// +//} diff --git a/internal/delivery/handlers/authorization/authorization_handler.go b/internal/delivery/handlers/authorization/authorization_handler.go index e7150ab..97abc75 100644 --- a/internal/delivery/handlers/authorization/authorization_handler.go +++ b/internal/delivery/handlers/authorization/authorization_handler.go @@ -11,11 +11,11 @@ import ( ) type AuthorizationHandler struct { - sessionUseCase *usecase.SessionUseCase - userUseCase *usecase.UserUseCase + sessionUseCase usecase.SessionInterface + userUseCase usecase.UserUseCaseInterface } -func NewAuthorizationHandler(sessionUseCase *usecase.SessionUseCase, userUseCase *usecase.UserUseCase) *AuthorizationHandler { +func NewAuthorizationHandler(sessionUseCase usecase.SessionInterface, userUseCase usecase.UserUseCaseInterface) *AuthorizationHandler { return &AuthorizationHandler{ sessionUseCase: sessionUseCase, userUseCase: userUseCase, diff --git a/internal/delivery/handlers/comment/comment_handler.go b/internal/delivery/handlers/comment/comment_handler.go index 7d7d416..7b14052 100644 --- a/internal/delivery/handlers/comment/comment_handler.go +++ b/internal/delivery/handlers/comment/comment_handler.go @@ -11,10 +11,10 @@ import ( ) type CommentHandler struct { - CommentUseCase *usecase.CommentUseCase + CommentUseCase usecase.CommentUseCaseInterface } -func NewCommentHandler(usecase *usecase.CommentUseCase) *CommentHandler { +func NewCommentHandler(usecase usecase.CommentUseCaseInterface) *CommentHandler { return &CommentHandler{ CommentUseCase: usecase, } diff --git a/internal/delivery/handlers/deactivation/deactivation_handler.go b/internal/delivery/handlers/deactivation/deactivation_handler.go index ecf8d79..0a259df 100644 --- a/internal/delivery/handlers/deactivation/deactivation_handler.go +++ b/internal/delivery/handlers/deactivation/deactivation_handler.go @@ -9,11 +9,11 @@ import ( ) type DeactivationHandler struct { - sessionUseCase *usecase.SessionUseCase - userUseCase *usecase.UserUseCase + sessionUseCase usecase.SessionInterface + userUseCase usecase.UserUseCaseInterface } -func NewDeactivationHandler(sessionUseCase *usecase.SessionUseCase, userUseCase *usecase.UserUseCase) *DeactivationHandler { +func NewDeactivationHandler(sessionUseCase usecase.SessionInterface, userUseCase usecase.UserUseCaseInterface) *DeactivationHandler { return &DeactivationHandler{ sessionUseCase: sessionUseCase, userUseCase: userUseCase, diff --git a/internal/delivery/handlers/journey/journey_handler.go b/internal/delivery/handlers/journey/journey_handler.go index b7ea048..37fa34f 100644 --- a/internal/delivery/handlers/journey/journey_handler.go +++ b/internal/delivery/handlers/journey/journey_handler.go @@ -10,10 +10,10 @@ import ( ) type JourneyHandler struct { - JourneyUseCase *usecase.JourneyUseCase + JourneyUseCase usecase.JourneyUseCaseInterface } -func NewJourneyHandler(usecase *usecase.JourneyUseCase) *JourneyHandler { +func NewJourneyHandler(usecase usecase.JourneyUseCaseInterface) *JourneyHandler { return &JourneyHandler{ JourneyUseCase: usecase, } diff --git a/internal/delivery/handlers/profile/profile_handler.go b/internal/delivery/handlers/profile/profile_handler.go index df0f3d4..fe05c59 100644 --- a/internal/delivery/handlers/profile/profile_handler.go +++ b/internal/delivery/handlers/profile/profile_handler.go @@ -10,15 +10,15 @@ import ( "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities" "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/usecase" "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/httputils" - "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/logger" "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/wrapper" + "golang.org/x/exp/slog" ) type ProfileHandler struct { - userProfileUseCase *usecase.ProfileUseCase + userProfileUseCase usecase.ProfileUseCaseInterface } -func NewProfileHandler(userProfileUseCase *usecase.ProfileUseCase) *ProfileHandler { +func NewProfileHandler(userProfileUseCase usecase.ProfileUseCaseInterface) *ProfileHandler { return &ProfileHandler{ userProfileUseCase: userProfileUseCase, } @@ -60,9 +60,7 @@ func (h *ProfileHandler) Edit(ctx context.Context, requestData entities.UserProf } // UploadFile TODO: нужно будет убрать это инженерное решение (костыль) после фикса обертки -func (h *ProfileHandler) UploadFile(w http.ResponseWriter, r *http.Request) { - logger := logger.Logger() - +func (h *ProfileHandler) UploadFile(w http.ResponseWriter, r *http.Request, logger *slog.Logger) { userID, err := strconv.Atoi(wrapper.GetPathParams(r)["id"]) if err != nil { logger.Error("Handler error", "error", err) @@ -70,7 +68,7 @@ func (h *ProfileHandler) UploadFile(w http.ResponseWriter, r *http.Request) { return } - path, err := delivery.SaveFile(r) + path, err := delivery.SaveFile(r, logger) if err != nil { logger.Error("Handler error", "error", err) http.Error(w, err.Error(), http.StatusInternalServerError) diff --git a/internal/delivery/handlers/quiz/review_handler.go b/internal/delivery/handlers/quiz/review_handler.go index 513ea97..ad55f82 100644 --- a/internal/delivery/handlers/quiz/review_handler.go +++ b/internal/delivery/handlers/quiz/review_handler.go @@ -11,14 +11,14 @@ import ( ) type QuizHandler struct { - questionUseCase *usecase.QuestionUseCase - commentUseCase *usecase.CommentUseCase - journeyUseCase *usecase.JourneyUseCase + questionUseCase usecase.QuestionUseCaseInterface + commentUseCase usecase.CommentUseCaseInterface + journeyUseCase usecase.JourneyUseCaseInterface } -func NewQuizHandler(questionUseCase *usecase.QuestionUseCase, - commentUseCase *usecase.CommentUseCase, - journeyUseCase *usecase.JourneyUseCase) *QuizHandler { +func NewQuizHandler(questionUseCase usecase.QuestionUseCaseInterface, + commentUseCase usecase.CommentUseCaseInterface, + journeyUseCase usecase.JourneyUseCaseInterface) *QuizHandler { return &QuizHandler{ questionUseCase: questionUseCase, commentUseCase: commentUseCase, diff --git a/internal/delivery/handlers/registration/registration_handler.go b/internal/delivery/handlers/registration/registration_handler.go index 07ff844..f951466 100644 --- a/internal/delivery/handlers/registration/registration_handler.go +++ b/internal/delivery/handlers/registration/registration_handler.go @@ -11,11 +11,11 @@ import ( ) type RegistrationHandler struct { - sessionUseCase *usecase.SessionUseCase - userUseCase *usecase.UserUseCase + sessionUseCase usecase.SessionInterface + userUseCase usecase.UserUseCaseInterface } -func NewRegistrationHandler(sessionUseCase *usecase.SessionUseCase, userUseCase *usecase.UserUseCase) *RegistrationHandler { +func NewRegistrationHandler(sessionUseCase usecase.SessionInterface, userUseCase usecase.UserUseCaseInterface) *RegistrationHandler { return &RegistrationHandler{ sessionUseCase: sessionUseCase, userUseCase: userUseCase, diff --git a/internal/delivery/handlers/sight/sight_handler.go b/internal/delivery/handlers/sight/sight_handler.go index 6c027d2..5560395 100644 --- a/internal/delivery/handlers/sight/sight_handler.go +++ b/internal/delivery/handlers/sight/sight_handler.go @@ -10,10 +10,10 @@ import ( ) type SightHandler struct { - SightUseCase *usecase.SightUseCase + SightUseCase usecase.SightUseCaseInterface } -func NewSightsHandler(usecase *usecase.SightUseCase) *SightHandler { +func NewSightsHandler(usecase usecase.SightUseCaseInterface) *SightHandler { return &SightHandler{ SightUseCase: usecase, } diff --git a/internal/delivery/initialization/db_init.go b/internal/delivery/initialization/db_init.go index 9166b8d..0a7d72f 100644 --- a/internal/delivery/initialization/db_init.go +++ b/internal/delivery/initialization/db_init.go @@ -1,28 +1,31 @@ package initialization import ( + "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/config" "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/delivery/db" "github.com/go-redis/redis/v8" "github.com/jackc/pgx/v5/pgxpool" ) -func DataBaseInitialization() (*pgxpool.Pool, *redis.Client, *redis.Client, error) { - pdb, err := db.GetPostgres() - if err != nil { - return nil, nil, nil, err - } +type DBs struct { + PostgresDB *pgxpool.Pool + CsrfDB *redis.Client +} - rdb, err := db.GetRedis() +// DataBaseInitialization Инициализация баз данных +func DataBaseInitialization(cfg *config.Config) (*DBs, error) { + postgresDB, err := db.GetPostgres(cfg) // Инициализация основной базы данных if err != nil { - pdb.Close() - return nil, nil, nil, err + return nil, err } - cdb, err := db.GetCSRFRedis() + csrfDB, err := db.GetCSRFRedis(cfg) // Инициализация базы данных для csrf if err != nil { - pdb.Close() - _ = rdb.Close() + postgresDB.Close() + return nil, err } - - return pdb, rdb, cdb, nil + return &DBs{ + PostgresDB: postgresDB, + CsrfDB: csrfDB, + }, nil } diff --git a/internal/delivery/initialization/storage_init.go b/internal/delivery/initialization/storage_init.go index 321b77a..5c64714 100644 --- a/internal/delivery/initialization/storage_init.go +++ b/internal/delivery/initialization/storage_init.go @@ -7,15 +7,11 @@ import ( "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/storage/postgres/sight" "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/storage/postgres/user" "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/storage/redis/csrf" - "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/storage/redis/session" - "github.com/go-redis/redis/v8" - "github.com/jackc/pgx/v5/pgxpool" ) type Storages struct { UserStorage *user.UserStorage ProfileStorage *user.UserProfileStorage - SessionStorage *session.RedisStorage SightStorage *sight.SightStorage CommentStorage *comment.CommentStorage JourneyStorage *journey.JourneyStorage @@ -23,15 +19,14 @@ type Storages struct { CSRFStorage *csrf.CSRFStorage } -func StorageInit(pdb *pgxpool.Pool, rdb *redis.Client, cdb *redis.Client) *Storages { +func StorageInit(DBs *DBs) *Storages { return &Storages{ - UserStorage: user.NewUserStorage(pdb), - ProfileStorage: user.NewUserProfileStorage(pdb), - SessionStorage: session.NewSessionStorage(rdb), - SightStorage: sight.NewSightStorage(pdb), - CommentStorage: comment.NewCommentStorage(pdb), - JourneyStorage: journey.NewJourneyStorage(pdb), - QuestionStorage: question.NewQuestionStorage(pdb), - CSRFStorage: csrf.NewCSRFStorage(cdb), + UserStorage: user.NewUserStorage(DBs.PostgresDB), + ProfileStorage: user.NewUserProfileStorage(DBs.PostgresDB), + SightStorage: sight.NewSightStorage(DBs.PostgresDB), + CommentStorage: comment.NewCommentStorage(DBs.PostgresDB), + JourneyStorage: journey.NewJourneyStorage(DBs.PostgresDB), + QuestionStorage: question.NewQuestionStorage(DBs.PostgresDB), + CSRFStorage: csrf.NewCSRFStorage(DBs.CsrfDB), } } diff --git a/internal/delivery/initialization/use_case_init.go b/internal/delivery/initialization/use_case_init.go index e7ebe8e..c8ea7cc 100644 --- a/internal/delivery/initialization/use_case_init.go +++ b/internal/delivery/initialization/use_case_init.go @@ -5,17 +5,17 @@ import ( ) type UseCases struct { - UserUseCase *usecase.UserUseCase - SessionUseCase *usecase.SessionUseCase - ProfileUseCase *usecase.ProfileUseCase - SightUseCase *usecase.SightUseCase - JourneyUseCase *usecase.JourneyUseCase - CommentUseCase *usecase.CommentUseCase - QuestionUseCase *usecase.QuestionUseCase - CSRFUseCase *usecase.CSRFUseCase + UserUseCase usecase.UserUseCaseInterface + ProfileUseCase usecase.ProfileUseCaseInterface + SightUseCase usecase.SightUseCaseInterface + JourneyUseCase usecase.JourneyUseCaseInterface + CommentUseCase usecase.CommentUseCaseInterface + QuestionUseCase usecase.QuestionUseCaseInterface + CSRFUseCase usecase.CSRFInterface + SessionUseCase usecase.SessionInterface } -func UseCaseInit(storages *Storages) *UseCases { +func UseCaseInit(storages *Storages, sessionUseCase *usecase.SessionUseCase) *UseCases { return &UseCases{ UserUseCase: usecase.NewUserUseCase(storages.UserStorage), ProfileUseCase: usecase.NewProfileUseCase(storages.ProfileStorage), @@ -23,7 +23,7 @@ func UseCaseInit(storages *Storages) *UseCases { JourneyUseCase: usecase.NewJourneyUseCase(storages.JourneyStorage), CommentUseCase: usecase.NewCommentUseCase(storages.CommentStorage), QuestionUseCase: usecase.NewQuestionUseCase(storages.QuestionStorage), - SessionUseCase: usecase.NewSessionUseCase(storages.SessionStorage), CSRFUseCase: usecase.NewCSRFUseCase(storages.CSRFStorage), + SessionUseCase: sessionUseCase, } } diff --git a/internal/delivery/server/server.go b/internal/delivery/server/server.go index 4db8674..9085b51 100644 --- a/internal/delivery/server/server.go +++ b/internal/delivery/server/server.go @@ -6,12 +6,9 @@ import ( "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/config" "github.com/go-chi/chi/v5" - "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/logger" ) func StartServer(router *chi.Mux, cfg *config.Config) error { - logger.Logger().Info("Server is starting:", "address", cfg.HTTPServer.Address) - server := &http.Server{ Addr: cfg.Address, Handler: router, @@ -19,10 +16,8 @@ func StartServer(router *chi.Mux, cfg *config.Config) error { WriteTimeout: cfg.HTTPServer.Timeout, IdleTimeout: cfg.HTTPServer.IdleTimeout, } - if err := server.ListenAndServe(); err != nil { return err } - return nil } diff --git a/internal/storage/postgres/comment/comment_storage.go b/internal/storage/postgres/comment/comment_storage.go index 7931dbf..3acdde9 100644 --- a/internal/storage/postgres/comment/comment_storage.go +++ b/internal/storage/postgres/comment/comment_storage.go @@ -5,7 +5,6 @@ import ( "github.com/georgysavva/scany/v2/pgxscan" "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities" - "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/logger" "github.com/jackc/pgx/v5/pgxpool" ) @@ -28,7 +27,6 @@ func (cs *CommentStorage) GetCommentsBySightID(ctx context.Context, id int) ([]e ON f.user_id = p.user_id WHERE sight_id = $1`, id) if err != nil { - logger.Logger().Error(err.Error()) return nil, err } @@ -46,7 +44,6 @@ func (cs *CommentStorage) GetCommentsByUserID(ctx context.Context, userID int) ( `SELECT f.id, f.user_id, f.sight_id, f.rating, f.feedback FROM feedback AS f WHERE user_id = $1 `, userID) if err != nil { - logger.Logger().Error(err.Error()) return nil, err } @@ -72,7 +69,6 @@ func (cs *CommentStorage) EditComment(ctx context.Context, commentID int, commen func (cs *CommentStorage) DeleteComment(ctx context.Context, commentID int) error { _, err := cs.db.Exec(ctx, `DELETE FROM feedback WHERE id = $1`, commentID) if err != nil { - logger.Logger().Error(err.Error()) return err } return nil diff --git a/internal/storage/postgres/journey/journey_storage.go b/internal/storage/postgres/journey/journey_storage.go index dcab3a2..8e8bc3c 100644 --- a/internal/storage/postgres/journey/journey_storage.go +++ b/internal/storage/postgres/journey/journey_storage.go @@ -6,7 +6,6 @@ import ( "github.com/georgysavva/scany/v2/pgxscan" "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities" - "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/logger" "github.com/jackc/pgx/v5/pgxpool" ) @@ -35,13 +34,11 @@ func (js *JourneyStorage) CreateJourney(ctx context.Context, journey entities.Jo func (js *JourneyStorage) DeleteJourney(ctx context.Context, journeyID int) error { _, err := js.db.Exec(ctx, `DELETE FROM journey_sight WHERE journey_id = $1`, journeyID) if err != nil { - logger.Logger().Error(err.Error()) return err } _, err = js.db.Exec(ctx, `DELETE FROM journey WHERE id = $1`, journeyID) if err != nil { - logger.Logger().Error(err.Error()) return err } @@ -55,7 +52,6 @@ func (js *JourneyStorage) GetJourneys(ctx context.Context, userID int) ([]entiti INNER JOIN profile_data AS p ON p.user_id = $1 WHERE j.user_id = $1;`, userID) if err != nil { - logger.Logger().Error(err.Error()) return nil, err } @@ -72,7 +68,6 @@ func (js *JourneyStorage) AddJourneySight(ctx context.Context, journeyID int, si for _, sightID := range sightIDs { _, err := js.db.Exec(ctx, `INSERT INTO journey_sight(journey_id, sight_id, priority) VALUES ($1, $2, $3)`, journeyID, sightID, 0) if err != nil { - logger.Logger().Error(err.Error()) return err } } @@ -84,7 +79,6 @@ func (js *JourneyStorage) JourneyExists(ctx context.Context, journeyID int) (boo var journeyExists bool err := js.db.QueryRow(ctx, `SELECT EXISTS(SELECT 1 FROM journey WHERE id = $1)`, journeyID).Scan(&journeyExists) if err != nil { - logger.Logger().Error(err.Error()) return false, err } return journeyExists, nil @@ -95,7 +89,6 @@ func (js *JourneyStorage) EditJourney(ctx context.Context, journeyID int, name, var journeyExists bool err := js.db.QueryRow(ctx, `SELECT EXISTS(SELECT 1 FROM journey WHERE id = $1)`, journeyID).Scan(&journeyExists) if err != nil { - logger.Logger().Error(err.Error()) return err } @@ -106,7 +99,6 @@ func (js *JourneyStorage) EditJourney(ctx context.Context, journeyID int, name, // Обновляем имя и описание поездки _, err = js.db.Exec(ctx, `UPDATE journey SET name = $1, description = $2 WHERE id = $3`, name, description, journeyID) if err != nil { - logger.Logger().Error(err.Error()) return err } @@ -122,7 +114,6 @@ func (js *JourneyStorage) GetJourneySights(ctx context.Context, journeyID int) ( var idList []*int err := pgxscan.Select(ctx, js.db, &idList, `SELECT js.sight_id FROM journey_sight AS js WHERE js.journey_id = $1`, journeyID) if err != nil { - logger.Logger().Error(err.Error()) return nil, err } return idList, nil @@ -136,7 +127,6 @@ func (js *JourneyStorage) GetJourney(ctx context.Context, journeyID int) (entiti INNER JOIN profile_data AS p ON p.user_id = j.user_id WHERE j.id = $1;`, journeyID) if err != nil { - logger.Logger().Error(err.Error()) return entities.Journey{}, err } return *journey[0], nil diff --git a/internal/storage/postgres/question/question_storage.go b/internal/storage/postgres/question/question_storage.go index 259d806..de7a167 100644 --- a/internal/storage/postgres/question/question_storage.go +++ b/internal/storage/postgres/question/question_storage.go @@ -6,7 +6,6 @@ import ( "github.com/georgysavva/scany/v2/pgxscan" "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities" - "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/logger" "github.com/jackc/pgx/v5/pgxpool" ) @@ -42,7 +41,6 @@ func (qs *QuestionStorage) GetQuestions(ctx context.Context) ([]entities.Questio var questions []*entities.QuestionResponse err := pgxscan.Select(ctx, qs.db, &questions, `SELECT id AS question_id, text FROM question ORDER BY question_id`) if err != nil { - logger.Logger().Error(err.Error()) return []entities.QuestionResponse{}, err } @@ -59,7 +57,6 @@ func (qs *QuestionStorage) GetReview(ctx context.Context, userID int) ([]entitie err := pgxscan.Select(ctx, qs.db, &review, `SELECT user_id, rating, question_id, created_at FROM quiz WHERE user_id = $1`, userID) if err != nil { - logger.Logger().Error(err.Error()) return []entities.Review{}, err } @@ -79,7 +76,6 @@ func (qs *QuestionStorage) SetStat(ctx context.Context, userID int) ([]entities. -- WHERE user_id = $1 GROUP BY r.question_id, q.text, r.rating`, userID) if err != nil { - logger.Logger().Error(err.Error()) return []entities.Statistic{}, err } @@ -99,7 +95,6 @@ func (qs *QuestionStorage) GetAvgStat(ctx context.Context) ([]entities.Statistic GROUP BY q.id, r.question_id, q.text ORDER BY q.id`) if err != nil { - logger.Logger().Error(err.Error()) return []entities.Statistic{}, err } @@ -119,7 +114,6 @@ func (qs *QuestionStorage) GetUserStat(ctx context.Context, userID int) ([]entit WHERE user_id = $1 ORDER BY q.id `, userID) if err != nil { - logger.Logger().Error(err.Error()) return []entities.Statistic{}, err } diff --git a/internal/storage/postgres/sight/sight_storage.go b/internal/storage/postgres/sight/sight_storage.go index 823f58f..d5a6e9c 100644 --- a/internal/storage/postgres/sight/sight_storage.go +++ b/internal/storage/postgres/sight/sight_storage.go @@ -4,7 +4,6 @@ import ( "context" "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities" - "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/logger" "github.com/jackc/pgx/v5/pgxpool" "github.com/georgysavva/scany/v2/pgxscan" @@ -29,7 +28,6 @@ func (ss *SightStorage) GetSightsList(ctx context.Context) ([]entities.Sight, er INNER JOIN image_data AS im ON sight.id = im.sight_id `) if err != nil { - logger.Logger().Error(err.Error()) return nil, err } diff --git a/internal/storage/postgres/user/user_storage.go b/internal/storage/postgres/user/user_storage.go index 8421a08..ca9adab 100644 --- a/internal/storage/postgres/user/user_storage.go +++ b/internal/storage/postgres/user/user_storage.go @@ -2,9 +2,13 @@ package user import ( "context" + "net/http" "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/entities" + httperrors "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/errors" + "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" + "github.com/pkg/errors" ) // UserStorage struct @@ -47,6 +51,9 @@ func (us *UserStorage) GetUserByEmail(ctx context.Context, email string) (entiti var user entities.User err := us.db.QueryRow(ctx, `SELECT id, email, passwrd, salt FROM user_data WHERE email = $1`, email).Scan(&user.ID, &user.Username, &user.Password, &user.Salt) if err != nil { + if errors.Is(err, pgx.ErrNoRows) { + return entities.User{}, httperrors.NewHttpError(http.StatusBadRequest, "user not found") + } return entities.User{}, err } return user, nil diff --git a/internal/storage/storage_interfaces/session_interface.go b/internal/storage/storage_interfaces/session_interface.go deleted file mode 100644 index 54f8871..0000000 --- a/internal/storage/storage_interfaces/session_interface.go +++ /dev/null @@ -1,11 +0,0 @@ -package storage - -import ( - "context" -) - -type SessionStorageInterface interface { - SaveSession(ctx context.Context, sessionID string, userID int) error - GetSession(ctx context.Context, sessionID string) (int, error) - DeleteSession(ctx context.Context, sessionID string) error -} diff --git a/internal/usecase/session_usecase.go b/internal/usecase/session_usecase.go index 30cc62c..85b6f5e 100644 --- a/internal/usecase/session_usecase.go +++ b/internal/usecase/session_usecase.go @@ -2,13 +2,13 @@ package usecase import ( "context" - "fmt" "net/http" "time" - storage "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/storage/storage_interfaces" + "github.com/go-park-mail-ru/2024_1_ResCogitans/session_service/gen" + "google.golang.org/grpc" + httperrors "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/errors" - "github.com/google/uuid" "github.com/gorilla/securecookie" "github.com/pkg/errors" ) @@ -26,22 +26,23 @@ type SessionInterface interface { } type SessionUseCase struct { - SessionStorage storage.SessionStorageInterface + client gen.SessionServiceClient } -func NewSessionUseCase(storage storage.SessionStorageInterface) *SessionUseCase { +func NewSessionUseCase(conn *grpc.ClientConn) *SessionUseCase { return &SessionUseCase{ - SessionStorage: storage, + client: gen.NewSessionServiceClient(conn), } } -func (a *SessionUseCase) CreateSession(ctx context.Context, w http.ResponseWriter, userID int) error { - sessionID := uuid.New().String() - err := a.SessionStorage.SaveSession(ctx, sessionID, userID) +func (s *SessionUseCase) CreateSession(ctx context.Context, w http.ResponseWriter, userID int) error { + response, err := s.client.CreateSession(ctx, &gen.SaveSessionRequest{ + UserID: int32(userID), + }) if err != nil { return err } - encoded, err := CookieHandler.Encode(sessionId, sessionID) + encoded, err := CookieHandler.Encode(sessionId, response.SessionID) if err != nil { return err } @@ -55,7 +56,7 @@ func (a *SessionUseCase) CreateSession(ctx context.Context, w http.ResponseWrite return nil } -func (a *SessionUseCase) GetSession(ctx context.Context, r *http.Request) (int, error) { +func (s *SessionUseCase) GetSession(ctx context.Context, r *http.Request) (int, error) { cookie, err := r.Cookie(sessionId) if err != nil { if errors.Is(err, http.ErrNoCookie) { @@ -63,15 +64,18 @@ func (a *SessionUseCase) GetSession(ctx context.Context, r *http.Request) (int, } return 0, err } - var sessionID string if err = CookieHandler.Decode(sessionId, cookie.Value, &sessionID); err == nil { - return a.SessionStorage.GetSession(ctx, sessionID) + ans, err := s.client.GetSession(ctx, &gen.GetSessionRequest{SessionID: sessionID}) + if err != nil { + return 0, err + } + return int(ans.UserID), nil } - return 0, fmt.Errorf("error decoding cookie: %w", err) + return 0, httperrors.NewHttpError(http.StatusInternalServerError, err.Error()) } -func (a *SessionUseCase) ClearSession(ctx context.Context, w http.ResponseWriter, r *http.Request) error { +func (s *SessionUseCase) ClearSession(ctx context.Context, w http.ResponseWriter, r *http.Request) error { cookie, err := r.Cookie(sessionId) if err != nil { return err @@ -82,7 +86,7 @@ func (a *SessionUseCase) ClearSession(ctx context.Context, w http.ResponseWriter if err != nil { return err } - err = a.SessionStorage.DeleteSession(ctx, sessionID) + _, err = s.client.DeleteSession(ctx, &gen.DeleteSessionRequest{SessionID: sessionID}) if err != nil { return err } diff --git a/internal/usecase/user_usecase.go b/internal/usecase/user_usecase.go index 1938304..3fb8266 100644 --- a/internal/usecase/user_usecase.go +++ b/internal/usecase/user_usecase.go @@ -18,7 +18,7 @@ type UserUseCaseInterface interface { GetUserByEmail(ctx context.Context, email string) (entities.User, error) GetUserByID(ctx context.Context, userID int) (entities.User, error) DeleteUser(ctx context.Context, userID int) error - UserDataVerification(ctx context.Context, email, password string) error + UserDataVerification(email, password string) error ChangePassword(ctx context.Context, userID int, password string) (entities.User, error) UserExists(ctx context.Context, email, password string) error IsEmailTaken(ctx context.Context, email string) (bool, error) diff --git a/router/router.go b/router/router.go index fc4be19..beffc7b 100644 --- a/router/router.go +++ b/router/router.go @@ -3,9 +3,8 @@ package router import ( "net/http" - "github.com/go-chi/chi/middleware" "github.com/go-chi/chi/v5" - "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/config" + "github.com/go-chi/chi/v5/middleware" "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/delivery/handlers/authorization" user "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/delivery/handlers/avatar" "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/delivery/handlers/comment" @@ -20,10 +19,10 @@ import ( "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/cors" "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/middle" "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/wrapper" - httpSwagger "github.com/swaggo/http-swagger" + "golang.org/x/exp/slog" ) -func SetupRouter(_ *config.Config, handlers *initialization.Handlers) *chi.Mux { +func SetupRouter(logger *slog.Logger, handlers *initialization.Handlers) *chi.Mux { router := chi.NewRouter() router.Use(middleware.RequestID) @@ -38,212 +37,208 @@ func SetupRouter(_ *config.Config, handlers *initialization.Handlers) *chi.Mux { // upload image router.HandleFunc("/upload", user.Upload) - router.Mount("/api/sights", SightRoutes(handlers.SightHandler)) + router.Mount("/api/sights", SightRoutes(handlers.SightHandler, logger)) // user authorization and registration - router.Mount("/api/signup", SignUpRoutes(handlers.RegHandler)) - router.Mount("/api/login", AuthRoutes(handlers.AuthHandler)) - router.Mount("/api/logout", LogOutRoutes(handlers.AuthHandler)) + router.Mount("/api/signup", SignUpRoutes(handlers.RegHandler, logger)) + router.Mount("/api/login", AuthRoutes(handlers.AuthHandler, logger)) + router.Mount("/api/logout", LogOutRoutes(handlers.AuthHandler, logger)) // user profile - router.Mount("/api/profile/{id}", GetProfileRoutes(handlers.ProfileHandler)) - router.Mount("/api/profile/{id}/edit", EditProfileRoutes(handlers.ProfileHandler)) - router.Mount("/api/profile/{id}/delete", DeleteProfileRoutes(handlers.DeactivationHandler)) - router.Mount("/api/profile/{id}/reset_password", UpdateUserPasswordRoutes(handlers.AuthHandler)) + router.Mount("/api/profile/{id}", GetProfileRoutes(handlers.ProfileHandler, logger)) + router.Mount("/api/profile/{id}/edit", EditProfileRoutes(handlers.ProfileHandler, logger)) + router.Mount("/api/profile/{id}/delete", DeleteProfileRoutes(handlers.DeactivationHandler, logger)) + router.Mount("/api/profile/{id}/reset_password", UpdateUserPasswordRoutes(handlers.AuthHandler, logger)) //TODO:нужно приспособить обертку под работу multipart/form-data router.Post("/profile/{id}/upload", func(w http.ResponseWriter, r *http.Request) { - handlers.ProfileHandler.UploadFile(w, r) + handlers.ProfileHandler.UploadFile(w, r, logger) }) // comments - router.Mount("/api/sight/{id}", GetSightRoutes(handlers.SightHandler)) - router.Mount("/api/sight/{id}/create", CreateCommentRoutes(handlers.CommentHandler)) - router.Mount("/api/sight/{sid}/edit/{cid}", EditCommentRoutes(handlers.CommentHandler)) - router.Mount("/api/sight/{sid}/delete/{cid}", DeleteCommentRoutes(handlers.CommentHandler)) - router.Mount("/api/sight/quiz", SearchSightsRoutes(handlers.SightHandler)) + router.Mount("/api/sight/{id}", GetSightRoutes(handlers.SightHandler, logger)) + router.Mount("/api/sight/{id}/create", CreateCommentRoutes(handlers.CommentHandler, logger)) + router.Mount("/api/sight/{sid}/edit/{cid}", EditCommentRoutes(handlers.CommentHandler, logger)) + router.Mount("/api/sight/{sid}/delete/{cid}", DeleteCommentRoutes(handlers.CommentHandler, logger)) + router.Mount("/api/sight/quiz", SearchSightsRoutes(handlers.SightHandler, logger)) //journeys - router.Mount("/api/trip/{id}/delete", DeleteJourneyRoutes(handlers.JourneyHandler)) - router.Mount("/api/trip/create", CreateJourneyRoutes(handlers.JourneyHandler)) - router.Mount("/api/{userID}/trips", JourneyRoutes(handlers.JourneyHandler)) + router.Mount("/api/trip/{id}/delete", DeleteJourneyRoutes(handlers.JourneyHandler, logger)) + router.Mount("/api/trip/create", CreateJourneyRoutes(handlers.JourneyHandler, logger)) + router.Mount("/api/{userID}/trips", JourneyRoutes(handlers.JourneyHandler, logger)) // journey_sights - router.Mount("/api/trip/{id}", JourneySightRoutes(handlers.JourneyHandler)) - router.Mount("/api/trip/{id}/sight/add", AddJourneySightRoutes(handlers.JourneyHandler)) - router.Mount("/api/trip/{id}/edit", EditJourney(handlers.JourneyHandler)) - router.Mount("/api/trip/{id}/sight/delete", DeleteJourneySightRoutes(handlers.JourneyHandler)) + router.Mount("/api/trip/{id}", JourneySightRoutes(handlers.JourneyHandler, logger)) + router.Mount("/api/trip/{id}/sight/add", AddJourneySightRoutes(handlers.JourneyHandler, logger)) + router.Mount("/api/trip/{id}/edit", EditJourney(handlers.JourneyHandler, logger)) + router.Mount("/api/trip/{id}/sight/delete", DeleteJourneySightRoutes(handlers.JourneyHandler, logger)) // quiz - router.Mount("/api/review/create", CreateReviewRoutes(handlers.QuizHandler)) - router.Mount("/api/review/check", CheckUserReviewRoutes(handlers.QuizHandler)) - router.Mount("/api/review/get", GetStatistic(handlers.QuizHandler)) - - router.Get("/swagger/*", httpSwagger.Handler( - httpSwagger.URL("http://localhost:8080/swagger/doc.json"), //The url pointing to API definition - )) + router.Mount("/api/review/create", CreateReviewRoutes(handlers.QuizHandler, logger)) + router.Mount("/api/review/check", CheckUserReviewRoutes(handlers.QuizHandler, logger)) + router.Mount("/api/review/get", GetStatistic(handlers.QuizHandler, logger)) return router } -func SightRoutes(handler *sight.SightHandler) chi.Router { +func SightRoutes(handler *sight.SightHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.Sight, entities.Sights]{ServeHTTP: handler.GetSights} + wrapperInstance := &wrapper.Wrapper[entities.Sight, entities.Sights]{ServeHTTP: handler.GetSights, Logger: logger} router.Get("/", wrapperInstance.HandlerWrapper) return router } -func SignUpRoutes(handler *registration.RegistrationHandler) chi.Router { +func SignUpRoutes(handler *registration.RegistrationHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.User, entities.UserResponse]{ServeHTTP: handler.SignUp} + wrapperInstance := &wrapper.Wrapper[entities.User, entities.UserResponse]{ServeHTTP: handler.SignUp, Logger: logger} router.Post("/", wrapperInstance.HandlerWrapper) return router } -func LogOutRoutes(handler *authorization.AuthorizationHandler) chi.Router { +func LogOutRoutes(handler *authorization.AuthorizationHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.User, entities.UserResponse]{ServeHTTP: handler.LogOut} + wrapperInstance := &wrapper.Wrapper[entities.User, entities.UserResponse]{ServeHTTP: handler.LogOut, Logger: logger} router.Post("/", wrapperInstance.HandlerWrapper) return router } -func AuthRoutes(handler *authorization.AuthorizationHandler) chi.Router { +func AuthRoutes(handler *authorization.AuthorizationHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.User, entities.UserResponse]{ServeHTTP: handler.Authorize} + wrapperInstance := &wrapper.Wrapper[entities.User, entities.UserResponse]{ServeHTTP: handler.Authorize, Logger: logger} router.Post("/", wrapperInstance.HandlerWrapper) return router } -func GetSightRoutes(handler *sight.SightHandler) chi.Router { +func GetSightRoutes(handler *sight.SightHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.Sight, entities.SightComments]{ServeHTTP: handler.GetSight} + wrapperInstance := &wrapper.Wrapper[entities.Sight, entities.SightComments]{ServeHTTP: handler.GetSight, Logger: logger} router.Get("/", wrapperInstance.HandlerWrapper) return router } -func CreateCommentRoutes(handler *comment.CommentHandler) chi.Router { +func CreateCommentRoutes(handler *comment.CommentHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.Comment, entities.Comment]{ServeHTTP: handler.CreateComment} + wrapperInstance := &wrapper.Wrapper[entities.Comment, entities.Comment]{ServeHTTP: handler.CreateComment, Logger: logger} router.Post("/", wrapperInstance.HandlerWrapper) return router } -func EditCommentRoutes(handler *comment.CommentHandler) chi.Router { +func EditCommentRoutes(handler *comment.CommentHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.Comment, entities.Comment]{ServeHTTP: handler.EditComment} + wrapperInstance := &wrapper.Wrapper[entities.Comment, entities.Comment]{ServeHTTP: handler.EditComment, Logger: logger} router.Post("/", wrapperInstance.HandlerWrapper) return router } -func DeleteCommentRoutes(handler *comment.CommentHandler) chi.Router { +func DeleteCommentRoutes(handler *comment.CommentHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.Comment, entities.Comment]{ServeHTTP: handler.DeleteComment} + wrapperInstance := &wrapper.Wrapper[entities.Comment, entities.Comment]{ServeHTTP: handler.DeleteComment, Logger: logger} router.Post("/", wrapperInstance.HandlerWrapper) return router } -func CreateJourneyRoutes(handler *journey.JourneyHandler) chi.Router { +func CreateJourneyRoutes(handler *journey.JourneyHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.Journey, entities.Journey]{ServeHTTP: handler.CreateJourney} + wrapperInstance := &wrapper.Wrapper[entities.Journey, entities.Journey]{ServeHTTP: handler.CreateJourney, Logger: logger} router.Post("/", wrapperInstance.HandlerWrapper) return router } -func DeleteJourneyRoutes(handler *journey.JourneyHandler) chi.Router { +func DeleteJourneyRoutes(handler *journey.JourneyHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.Journey, entities.Journey]{ServeHTTP: handler.DeleteJourney} + wrapperInstance := &wrapper.Wrapper[entities.Journey, entities.Journey]{ServeHTTP: handler.DeleteJourney, Logger: logger} router.Post("/", wrapperInstance.HandlerWrapper) return router } -func JourneyRoutes(handler *journey.JourneyHandler) chi.Router { +func JourneyRoutes(handler *journey.JourneyHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.Journey, entities.Journeys]{ServeHTTP: handler.GetJourneys} + wrapperInstance := &wrapper.Wrapper[entities.Journey, entities.Journeys]{ServeHTTP: handler.GetJourneys, Logger: logger} router.Get("/", wrapperInstance.HandlerWrapper) return router } -func AddJourneySightRoutes(handler *journey.JourneyHandler) chi.Router { +func AddJourneySightRoutes(handler *journey.JourneyHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.JourneySightID, entities.JourneySight]{ServeHTTP: handler.AddJourneySight} + wrapperInstance := &wrapper.Wrapper[entities.JourneySightID, entities.JourneySight]{ServeHTTP: handler.AddJourneySight, Logger: logger} router.Post("/", wrapperInstance.HandlerWrapper) return router } -func EditJourney(handler *journey.JourneyHandler) chi.Router { +func EditJourney(handler *journey.JourneyHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.Journey, entities.Journey]{ServeHTTP: handler.EditJourney} + wrapperInstance := &wrapper.Wrapper[entities.Journey, entities.Journey]{ServeHTTP: handler.EditJourney, Logger: logger} router.Post("/", wrapperInstance.HandlerWrapper) return router } -func DeleteJourneySightRoutes(handler *journey.JourneyHandler) chi.Router { +func DeleteJourneySightRoutes(handler *journey.JourneyHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.JourneySight, entities.JourneySight]{ServeHTTP: handler.DeleteJourneySight} + wrapperInstance := &wrapper.Wrapper[entities.JourneySight, entities.JourneySight]{ServeHTTP: handler.DeleteJourneySight, Logger: logger} router.Post("/", wrapperInstance.HandlerWrapper) return router } -func JourneySightRoutes(handler *journey.JourneyHandler) chi.Router { +func JourneySightRoutes(handler *journey.JourneyHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.JourneySight, entities.JourneySights]{ServeHTTP: handler.GetJourneySights} + wrapperInstance := &wrapper.Wrapper[entities.JourneySight, entities.JourneySights]{ServeHTTP: handler.GetJourneySights, Logger: logger} router.Get("/", wrapperInstance.HandlerWrapper) return router } // profile -func GetProfileRoutes(handler *profile.ProfileHandler) chi.Router { +func GetProfileRoutes(handler *profile.ProfileHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.UserProfile, entities.UserProfile]{ServeHTTP: handler.Get} + wrapperInstance := &wrapper.Wrapper[entities.UserProfile, entities.UserProfile]{ServeHTTP: handler.Get, Logger: logger} router.Get("/", wrapperInstance.HandlerWrapper) return router } -func EditProfileRoutes(handler *profile.ProfileHandler) chi.Router { +func EditProfileRoutes(handler *profile.ProfileHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.UserProfile, entities.UserProfile]{ServeHTTP: handler.Edit} + wrapperInstance := &wrapper.Wrapper[entities.UserProfile, entities.UserProfile]{ServeHTTP: handler.Edit, Logger: logger} router.Post("/", wrapperInstance.HandlerWrapper) return router } -func DeleteProfileRoutes(handler *deactivation.DeactivationHandler) chi.Router { +func DeleteProfileRoutes(handler *deactivation.DeactivationHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.User, entities.UserResponse]{ServeHTTP: handler.Deactivate} + wrapperInstance := &wrapper.Wrapper[entities.User, entities.UserResponse]{ServeHTTP: handler.Deactivate, Logger: logger} router.Get("/", wrapperInstance.HandlerWrapper) return router } -func UpdateUserPasswordRoutes(handler *authorization.AuthorizationHandler) chi.Router { +func UpdateUserPasswordRoutes(handler *authorization.AuthorizationHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.User, entities.UserResponse]{ServeHTTP: handler.UpdatePassword} + wrapperInstance := &wrapper.Wrapper[entities.User, entities.UserResponse]{ServeHTTP: handler.UpdatePassword, Logger: logger} router.Post("/", wrapperInstance.HandlerWrapper) return router } -func SearchSightsRoutes(handler *sight.SightHandler) chi.Router { +func SearchSightsRoutes(handler *sight.SightHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.Sight, entities.Sights]{ServeHTTP: handler.SearchSights} + wrapperInstance := &wrapper.Wrapper[entities.Sight, entities.Sights]{ServeHTTP: handler.SearchSights, Logger: logger} router.Get("/", wrapperInstance.HandlerWrapper) return router } -func CreateReviewRoutes(handler *quiz.QuizHandler) chi.Router { +func CreateReviewRoutes(handler *quiz.QuizHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.Review, bool]{ServeHTTP: handler.CreateReview} + wrapperInstance := &wrapper.Wrapper[entities.Review, bool]{ServeHTTP: handler.CreateReview, Logger: logger} router.Post("/", wrapperInstance.HandlerWrapper) return router } -func CheckUserReviewRoutes(handler *quiz.QuizHandler) chi.Router { +func CheckUserReviewRoutes(handler *quiz.QuizHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.Review, entities.DataCheck]{ServeHTTP: handler.CheckData} + wrapperInstance := &wrapper.Wrapper[entities.Review, entities.DataCheck]{ServeHTTP: handler.CheckData, Logger: logger} router.Get("/", wrapperInstance.HandlerWrapper) return router } -func GetStatistic(handler *quiz.QuizHandler) chi.Router { +func GetStatistic(handler *quiz.QuizHandler, logger *slog.Logger) chi.Router { router := chi.NewRouter() - wrapperInstance := &wrapper.Wrapper[entities.Statistic, []entities.Statistic]{ServeHTTP: handler.SetStat} + wrapperInstance := &wrapper.Wrapper[entities.Statistic, []entities.Statistic]{ServeHTTP: handler.SetStat, Logger: logger} router.Get("/", wrapperInstance.HandlerWrapper) return router } diff --git a/session_service/cmd/session_service/main.go b/session_service/cmd/session_service/main.go new file mode 100644 index 0000000..8416e35 --- /dev/null +++ b/session_service/cmd/session_service/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "log" + "net" + + "github.com/go-park-mail-ru/2024_1_ResCogitans/session_service/gen" + "github.com/go-park-mail-ru/2024_1_ResCogitans/session_service/internal/config" + "github.com/go-park-mail-ru/2024_1_ResCogitans/session_service/internal/database" + "github.com/go-park-mail-ru/2024_1_ResCogitans/session_service/internal/session" + "github.com/go-park-mail-ru/2024_1_ResCogitans/session_service/internal/storage" + "google.golang.org/grpc" +) + +func main() { + cfg, err := config.LoadConfig() + lis, err := net.Listen(cfg.Server.Protocol, cfg.Server.Port) + if err != nil { + log.Fatalln("can't listen port", err) + return + } + + server := grpc.NewServer() + + redisDB, err := database.GetSessionRedis() + if err != nil { + log.Fatalln(err) + return + } + sessionStorage := storage.NewSessionStorage(redisDB) + + gen.RegisterSessionServiceServer(server, session.NewSessionManager(sessionStorage)) + + err = server.Serve(lis) + if err != nil { + return + } +} diff --git a/session_service/gen/session.pb.go b/session_service/gen/session.pb.go new file mode 100644 index 0000000..2322050 --- /dev/null +++ b/session_service/gen/session.pb.go @@ -0,0 +1,470 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.1 +// protoc v5.26.1 +// source: session.proto + +package gen + +import ( + reflect "reflect" + sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type SaveSessionRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserID int32 `protobuf:"varint,1,opt,name=userID,proto3" json:"userID,omitempty"` +} + +func (x *SaveSessionRequest) Reset() { + *x = SaveSessionRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_session_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SaveSessionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SaveSessionRequest) ProtoMessage() {} + +func (x *SaveSessionRequest) ProtoReflect() protoreflect.Message { + mi := &file_session_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SaveSessionRequest.ProtoReflect.Descriptor instead. +func (*SaveSessionRequest) Descriptor() ([]byte, []int) { + return file_session_proto_rawDescGZIP(), []int{0} +} + +func (x *SaveSessionRequest) GetUserID() int32 { + if x != nil { + return x.UserID + } + return 0 +} + +type SaveSessionResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SessionID string `protobuf:"bytes,1,opt,name=sessionID,proto3" json:"sessionID,omitempty"` +} + +func (x *SaveSessionResponse) Reset() { + *x = SaveSessionResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_session_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SaveSessionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SaveSessionResponse) ProtoMessage() {} + +func (x *SaveSessionResponse) ProtoReflect() protoreflect.Message { + mi := &file_session_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SaveSessionResponse.ProtoReflect.Descriptor instead. +func (*SaveSessionResponse) Descriptor() ([]byte, []int) { + return file_session_proto_rawDescGZIP(), []int{1} +} + +func (x *SaveSessionResponse) GetSessionID() string { + if x != nil { + return x.SessionID + } + return "" +} + +type GetSessionRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SessionID string `protobuf:"bytes,1,opt,name=sessionID,proto3" json:"sessionID,omitempty"` +} + +func (x *GetSessionRequest) Reset() { + *x = GetSessionRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_session_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetSessionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSessionRequest) ProtoMessage() {} + +func (x *GetSessionRequest) ProtoReflect() protoreflect.Message { + mi := &file_session_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetSessionRequest.ProtoReflect.Descriptor instead. +func (*GetSessionRequest) Descriptor() ([]byte, []int) { + return file_session_proto_rawDescGZIP(), []int{2} +} + +func (x *GetSessionRequest) GetSessionID() string { + if x != nil { + return x.SessionID + } + return "" +} + +type GetSessionResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserID int32 `protobuf:"varint,1,opt,name=userID,proto3" json:"userID,omitempty"` +} + +func (x *GetSessionResponse) Reset() { + *x = GetSessionResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_session_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetSessionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSessionResponse) ProtoMessage() {} + +func (x *GetSessionResponse) ProtoReflect() protoreflect.Message { + mi := &file_session_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetSessionResponse.ProtoReflect.Descriptor instead. +func (*GetSessionResponse) Descriptor() ([]byte, []int) { + return file_session_proto_rawDescGZIP(), []int{3} +} + +func (x *GetSessionResponse) GetUserID() int32 { + if x != nil { + return x.UserID + } + return 0 +} + +type DeleteSessionRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SessionID string `protobuf:"bytes,1,opt,name=sessionID,proto3" json:"sessionID,omitempty"` +} + +func (x *DeleteSessionRequest) Reset() { + *x = DeleteSessionRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_session_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteSessionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteSessionRequest) ProtoMessage() {} + +func (x *DeleteSessionRequest) ProtoReflect() protoreflect.Message { + mi := &file_session_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteSessionRequest.ProtoReflect.Descriptor instead. +func (*DeleteSessionRequest) Descriptor() ([]byte, []int) { + return file_session_proto_rawDescGZIP(), []int{4} +} + +func (x *DeleteSessionRequest) GetSessionID() string { + if x != nil { + return x.SessionID + } + return "" +} + +type DeleteSessionResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *DeleteSessionResponse) Reset() { + *x = DeleteSessionResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_session_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteSessionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteSessionResponse) ProtoMessage() {} + +func (x *DeleteSessionResponse) ProtoReflect() protoreflect.Message { + mi := &file_session_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteSessionResponse.ProtoReflect.Descriptor instead. +func (*DeleteSessionResponse) Descriptor() ([]byte, []int) { + return file_session_proto_rawDescGZIP(), []int{5} +} + +var File_session_proto protoreflect.FileDescriptor + +var file_session_proto_rawDesc = []byte{ + 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x2c, 0x0a, 0x12, 0x53, 0x61, 0x76, 0x65, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, + 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, + 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x22, 0x33, 0x0a, 0x13, 0x53, 0x61, 0x76, 0x65, 0x53, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, + 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x22, 0x31, 0x0a, 0x11, 0x47, + 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x22, 0x2c, + 0x0a, 0x12, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x22, 0x34, 0x0a, 0x14, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, + 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x49, 0x44, 0x22, 0x17, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xf3, 0x01, 0x0a, 0x0e, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4a, + 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x1b, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x53, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x47, 0x65, + 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x47, + 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x1d, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1e, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x42, 0x15, 0x5a, 0x13, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x2f, 0x67, 0x65, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_session_proto_rawDescOnce sync.Once + file_session_proto_rawDescData = file_session_proto_rawDesc +) + +func file_session_proto_rawDescGZIP() []byte { + file_session_proto_rawDescOnce.Do(func() { + file_session_proto_rawDescData = protoimpl.X.CompressGZIP(file_session_proto_rawDescData) + }) + return file_session_proto_rawDescData +} + +var file_session_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_session_proto_goTypes = []interface{}{ + (*SaveSessionRequest)(nil), // 0: session.SaveSessionRequest + (*SaveSessionResponse)(nil), // 1: session.SaveSessionResponse + (*GetSessionRequest)(nil), // 2: session.GetSessionRequest + (*GetSessionResponse)(nil), // 3: session.GetSessionResponse + (*DeleteSessionRequest)(nil), // 4: session.DeleteSessionRequest + (*DeleteSessionResponse)(nil), // 5: session.DeleteSessionResponse +} +var file_session_proto_depIdxs = []int32{ + 0, // 0: session.SessionService.CreateSession:input_type -> session.SaveSessionRequest + 2, // 1: session.SessionService.GetSession:input_type -> session.GetSessionRequest + 4, // 2: session.SessionService.DeleteSession:input_type -> session.DeleteSessionRequest + 1, // 3: session.SessionService.CreateSession:output_type -> session.SaveSessionResponse + 3, // 4: session.SessionService.GetSession:output_type -> session.GetSessionResponse + 5, // 5: session.SessionService.DeleteSession:output_type -> session.DeleteSessionResponse + 3, // [3:6] is the sub-list for method output_type + 0, // [0:3] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_session_proto_init() } +func file_session_proto_init() { + if File_session_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_session_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SaveSessionRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_session_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SaveSessionResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_session_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetSessionRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_session_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetSessionResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_session_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteSessionRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_session_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteSessionResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_session_proto_rawDesc, + NumEnums: 0, + NumMessages: 6, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_session_proto_goTypes, + DependencyIndexes: file_session_proto_depIdxs, + MessageInfos: file_session_proto_msgTypes, + }.Build() + File_session_proto = out.File + file_session_proto_rawDesc = nil + file_session_proto_goTypes = nil + file_session_proto_depIdxs = nil +} diff --git a/session_service/gen/session_grpc.pb.go b/session_service/gen/session_grpc.pb.go new file mode 100644 index 0000000..74d1b96 --- /dev/null +++ b/session_service/gen/session_grpc.pb.go @@ -0,0 +1,184 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v5.26.1 +// source: session.proto + +package gen + +import ( + context "context" + + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + SessionService_CreateSession_FullMethodName = "/session.SessionService/CreateSession" + SessionService_GetSession_FullMethodName = "/session.SessionService/GetSession" + SessionService_DeleteSession_FullMethodName = "/session.SessionService/DeleteSession" +) + +// SessionServiceClient is the client API for SessionService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type SessionServiceClient interface { + CreateSession(ctx context.Context, in *SaveSessionRequest, opts ...grpc.CallOption) (*SaveSessionResponse, error) + GetSession(ctx context.Context, in *GetSessionRequest, opts ...grpc.CallOption) (*GetSessionResponse, error) + DeleteSession(ctx context.Context, in *DeleteSessionRequest, opts ...grpc.CallOption) (*DeleteSessionResponse, error) +} + +type sessionServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewSessionServiceClient(cc grpc.ClientConnInterface) SessionServiceClient { + return &sessionServiceClient{cc} +} + +func (c *sessionServiceClient) CreateSession(ctx context.Context, in *SaveSessionRequest, opts ...grpc.CallOption) (*SaveSessionResponse, error) { + out := new(SaveSessionResponse) + err := c.cc.Invoke(ctx, SessionService_CreateSession_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *sessionServiceClient) GetSession(ctx context.Context, in *GetSessionRequest, opts ...grpc.CallOption) (*GetSessionResponse, error) { + out := new(GetSessionResponse) + err := c.cc.Invoke(ctx, SessionService_GetSession_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *sessionServiceClient) DeleteSession(ctx context.Context, in *DeleteSessionRequest, opts ...grpc.CallOption) (*DeleteSessionResponse, error) { + out := new(DeleteSessionResponse) + err := c.cc.Invoke(ctx, SessionService_DeleteSession_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// SessionServiceServer is the server API for SessionService service. +// All implementations must embed UnimplementedSessionServiceServer +// for forward compatibility +type SessionServiceServer interface { + CreateSession(context.Context, *SaveSessionRequest) (*SaveSessionResponse, error) + GetSession(context.Context, *GetSessionRequest) (*GetSessionResponse, error) + DeleteSession(context.Context, *DeleteSessionRequest) (*DeleteSessionResponse, error) + mustEmbedUnimplementedSessionServiceServer() +} + +// UnimplementedSessionServiceServer must be embedded to have forward compatible implementations. +type UnimplementedSessionServiceServer struct { +} + +func (UnimplementedSessionServiceServer) CreateSession(context.Context, *SaveSessionRequest) (*SaveSessionResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateSession not implemented") +} +func (UnimplementedSessionServiceServer) GetSession(context.Context, *GetSessionRequest) (*GetSessionResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetSession not implemented") +} +func (UnimplementedSessionServiceServer) DeleteSession(context.Context, *DeleteSessionRequest) (*DeleteSessionResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteSession not implemented") +} +func (UnimplementedSessionServiceServer) mustEmbedUnimplementedSessionServiceServer() {} + +// UnsafeSessionServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to SessionServiceServer will +// result in compilation errors. +type UnsafeSessionServiceServer interface { + mustEmbedUnimplementedSessionServiceServer() +} + +func RegisterSessionServiceServer(s grpc.ServiceRegistrar, srv SessionServiceServer) { + s.RegisterService(&SessionService_ServiceDesc, srv) +} + +func _SessionService_CreateSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SaveSessionRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SessionServiceServer).CreateSession(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: SessionService_CreateSession_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SessionServiceServer).CreateSession(ctx, req.(*SaveSessionRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _SessionService_GetSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetSessionRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SessionServiceServer).GetSession(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: SessionService_GetSession_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SessionServiceServer).GetSession(ctx, req.(*GetSessionRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _SessionService_DeleteSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteSessionRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SessionServiceServer).DeleteSession(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: SessionService_DeleteSession_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SessionServiceServer).DeleteSession(ctx, req.(*DeleteSessionRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// SessionService_ServiceDesc is the grpc.ServiceDesc for SessionService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var SessionService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "session.SessionService", + HandlerType: (*SessionServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CreateSession", + Handler: _SessionService_CreateSession_Handler, + }, + { + MethodName: "GetSession", + Handler: _SessionService_GetSession_Handler, + }, + { + MethodName: "DeleteSession", + Handler: _SessionService_DeleteSession_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "session.proto", +} diff --git a/session_service/internal/config/config.go b/session_service/internal/config/config.go new file mode 100644 index 0000000..f8b18b0 --- /dev/null +++ b/session_service/internal/config/config.go @@ -0,0 +1,51 @@ +package config + +import ( + "os" + + "github.com/ilyakaznacheev/cleanenv" + "github.com/joho/godotenv" + "github.com/pkg/errors" +) + +type Config struct { + Env string `yaml:"env" env:"ENV" env-required:"true"` + Redis `yaml:"redis"` + Server `yaml:"server"` +} + +type Redis struct { + Host string `yaml:"host" env:"DB_SESSION_HOST"` + Port int `yaml:"port" env:"DB_SESSION_PORT"` + DB int `yaml:"db" env:"DB_SESSION_DB"` + Password string `yaml:"password" env:"DB_SESSION_PASSWORD"` +} + +type Server struct { + Protocol string `yaml:"protocol" env:"SERVICE_PROTOCOL"` + Port string `yaml:"port" env:"SERVICE_PORT"` +} + +func LoadConfig() (*Config, error) { + if err := godotenv.Load(); err != nil { + return nil, errors.Wrap(err, "error loading .env file") + } + + configPath := os.Getenv("CONFIG_PATH") + + if configPath == "" { + return nil, errors.New("CONFIG_PATH is not set") + } + + if _, err := os.Stat(configPath); os.IsNotExist(err) { + return nil, errors.Errorf("config file %s is not exist", configPath) + } + + var cfg Config + + if err := cleanenv.ReadConfig(configPath, &cfg); err != nil { + return nil, errors.Wrap(err, "cannot read config") + } + + return &cfg, nil +} diff --git a/session_service/internal/config/local.yaml b/session_service/internal/config/local.yaml new file mode 100644 index 0000000..1068ce2 --- /dev/null +++ b/session_service/internal/config/local.yaml @@ -0,0 +1,6 @@ +env: "local" +http_server: + timeout: 4s + idle_timeout: 60s + user: "user" + password: "password" diff --git a/session_service/internal/database/session_database.go b/session_service/internal/database/session_database.go new file mode 100644 index 0000000..532a30e --- /dev/null +++ b/session_service/internal/database/session_database.go @@ -0,0 +1,28 @@ +package database + +import ( + "fmt" + + cfg "github.com/go-park-mail-ru/2024_1_ResCogitans/session_service/internal/config" + "github.com/go-redis/redis/v8" +) + +func GetSessionRedis() (*redis.Client, error) { + config, err := cfg.LoadConfig() + if err != nil { + return nil, err + } + rdb := redis.NewClient(&redis.Options{ + Addr: fmt.Sprintf("%s:%d", config.Redis.Host, config.Redis.Port), + Password: config.Redis.Password, + DB: config.Redis.DB, + }) + + // Проверка соединения с Redis + _, err = rdb.Ping(rdb.Context()).Result() + if err != nil { + return nil, err + } + + return rdb, nil +} diff --git a/session_service/internal/session/session_manager.go b/session_service/internal/session/session_manager.go new file mode 100644 index 0000000..e82fa36 --- /dev/null +++ b/session_service/internal/session/session_manager.go @@ -0,0 +1,45 @@ +package session + +import ( + "context" + + "github.com/go-park-mail-ru/2024_1_ResCogitans/session_service/gen" + "github.com/go-park-mail-ru/2024_1_ResCogitans/session_service/internal/storage" + "github.com/google/uuid" +) + +type SessionManager struct { + gen.UnimplementedSessionServiceServer + storage *storage.RedisStorage +} + +func NewSessionManager(storage *storage.RedisStorage) *SessionManager { + return &SessionManager{ + storage: storage, + } +} + +func (sm *SessionManager) CreateSession(ctx context.Context, req *gen.SaveSessionRequest) (*gen.SaveSessionResponse, error) { + sessionID := uuid.New().String() + err := sm.storage.SaveSession(ctx, sessionID, int(req.UserID)) + if err != nil { + return nil, err + } + return &gen.SaveSessionResponse{SessionID: sessionID}, nil +} + +func (sm *SessionManager) GetSession(ctx context.Context, req *gen.GetSessionRequest) (*gen.GetSessionResponse, error) { + userID, err := sm.storage.GetSession(ctx, req.SessionID) + if err != nil { + return nil, err + } + return &gen.GetSessionResponse{UserID: int32(userID)}, nil +} + +func (sm *SessionManager) DeleteSession(ctx context.Context, req *gen.DeleteSessionRequest) (*gen.DeleteSessionResponse, error) { + err := sm.storage.DeleteSession(ctx, req.SessionID) + if err != nil { + return nil, err + } + return &gen.DeleteSessionResponse{}, nil +} diff --git a/internal/storage/redis/session/session_storage.go b/session_service/internal/storage/session_storage.go similarity index 79% rename from internal/storage/redis/session/session_storage.go rename to session_service/internal/storage/session_storage.go index 0a58486..f219376 100644 --- a/internal/storage/redis/session/session_storage.go +++ b/session_service/internal/storage/session_storage.go @@ -1,4 +1,4 @@ -package session +package storage import ( "context" @@ -9,6 +9,12 @@ import ( "github.com/pkg/errors" ) +type SessionStorageInterface interface { + SaveSession(ctx context.Context, sessionID string, userID int) error + GetSession(ctx context.Context, sessionID string) (int, error) + DeleteSession(ctx context.Context, sessionID string) error +} + type RedisStorage struct { client *redis.Client } diff --git a/utils/errors/errors.go b/utils/errors/errors.go index 97115c1..0cf0bdd 100644 --- a/utils/errors/errors.go +++ b/utils/errors/errors.go @@ -4,8 +4,8 @@ import ( "encoding/json" "net/http" - "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/logger" "github.com/pkg/errors" + "golang.org/x/exp/slog" ) type HttpError struct { @@ -42,22 +42,22 @@ func IsHttpError(err error) bool { var errInternalBytes = []byte(`{"error": "internal error"}`) -func WriteHttpError(errIn error, w http.ResponseWriter) { +func WriteHttpError(errIn error, w http.ResponseWriter, logger *slog.Logger) { httpError := UnwrapHttpError(errIn) w.Header().Add("Content-Type", "application/json") bytes, err := json.Marshal(httpError) if err != nil { - logger.Logger().Error("error marshal err", "error", err.Error()) + logger.Error("error marshal err", "error", err.Error()) w.WriteHeader(http.StatusInternalServerError) if _, writeErr := w.Write(errInternalBytes); writeErr != nil { - logger.Logger().Error("error writing fallback error", "error", writeErr.Error()) + logger.Error("error writing fallback error", "error", writeErr.Error()) } return } w.WriteHeader(httpError.Code) if _, writeErr := w.Write(bytes); writeErr != nil { - logger.Logger().Error("error writing http error", "error", writeErr) + logger.Error("error writing http error", "error", writeErr) return } } diff --git a/utils/logger/logger.go b/utils/logger/logger.go index 07ad2b5..7d4132c 100644 --- a/utils/logger/logger.go +++ b/utils/logger/logger.go @@ -1,7 +1,6 @@ package logger import ( - "log" "os" "github.com/go-park-mail-ru/2024_1_ResCogitans/internal/config" @@ -14,15 +13,9 @@ const ( envProd = "prod" ) -var logger *slog.Logger +func NewLogger(cfg *config.Config) *slog.Logger { + var logger *slog.Logger -func init() { - cfg, err := config.LoadConfig() - if err != nil { - logger = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelError})) - log.Fatal("Error:", err.Error()) - return - } switch cfg.Env { case envLocal: logger = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug})) @@ -30,9 +23,8 @@ func init() { logger = slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo})) case envProd: logger = slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo})) + default: + logger = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelError})) } -} - -func Logger() *slog.Logger { return logger } diff --git a/utils/middle/session_middleware.go b/utils/middle/session_middleware.go index ff3ddd0..c6a5cf3 100644 --- a/utils/middle/session_middleware.go +++ b/utils/middle/session_middleware.go @@ -9,11 +9,11 @@ import ( ) type AuthMiddleware struct { - s *usecase.SessionUseCase - c *usecase.CSRFUseCase + s usecase.SessionInterface + c usecase.CSRFInterface } -func NewAuthMiddleware(session *usecase.SessionUseCase, csrf *usecase.CSRFUseCase) *AuthMiddleware { +func NewAuthMiddleware(session usecase.SessionInterface, csrf usecase.CSRFInterface) *AuthMiddleware { return &AuthMiddleware{ s: session, c: csrf, diff --git a/utils/wrapper/wrapper.go b/utils/wrapper/wrapper.go index 7c95efe..a09ed2d 100644 --- a/utils/wrapper/wrapper.go +++ b/utils/wrapper/wrapper.go @@ -9,13 +9,14 @@ import ( "github.com/go-chi/chi/v5" httperrors "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/errors" "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/httputils" - "github.com/go-park-mail-ru/2024_1_ResCogitans/utils/logger" + "golang.org/x/exp/slog" ) type ServeHTTPFunc[T Validator, Resp any] func(ctx context.Context, request T) (Resp, error) type Wrapper[T Validator, Resp any] struct { ServeHTTP ServeHTTPFunc[T, Resp] + Logger *slog.Logger } type Validator interface { @@ -24,7 +25,6 @@ type Validator interface { func (w *Wrapper[T, Resp]) HandlerWrapper(resWriter http.ResponseWriter, httpReq *http.Request) { ctx := httpReq.Context() - logger := logger.Logger() pathParams := GetPathParams(httpReq) ctx = httputils.SetPathParamsToCtx(ctx, pathParams) @@ -37,29 +37,29 @@ func (w *Wrapper[T, Resp]) HandlerWrapper(resWriter http.ResponseWriter, httpReq if httpReq.ContentLength > 0 { err := json.NewDecoder(limitedReader).Decode(&requestData) if err != nil { - logger.Error("Error decoding request body", "error", err) - httperrors.WriteHttpError(err, resWriter) + w.Logger.Error("Error decoding request body", "error", err) + httperrors.WriteHttpError(err, resWriter, w.Logger) return } if err = requestData.Validate(); err != nil { - logger.Error("Validation error", "error", err) - httperrors.WriteHttpError(err, resWriter) + w.Logger.Error("Validation error", "error", err) + httperrors.WriteHttpError(err, resWriter, w.Logger) return } } response, err := w.ServeHTTP(ctx, requestData) if err != nil { - logger.Error("Handler error", "error", err.Error()) - httperrors.WriteHttpError(err, resWriter) + w.Logger.Error("Handler error", "error", err) + httperrors.WriteHttpError(err, resWriter, w.Logger) return } rawJSON, err := json.Marshal(response) if err != nil { - logger.Error("Error encoding response", "error", err) - httperrors.WriteHttpError(err, resWriter) + w.Logger.Error("Error encoding response", "error", err) + httperrors.WriteHttpError(err, resWriter, w.Logger) return }