From 3a39c1e2e1d67cef9d75519039cb8ab8ca10d73a Mon Sep 17 00:00:00 2001 From: pasha1coil Date: Fri, 1 Dec 2023 19:46:02 +0300 Subject: [PATCH] add check query --- .env.test | 4 ++ cmd/main.go | 55 ++++++++++++++++ go.mod | 18 ++++- go.sum | 40 ++++++++++++ privilege/client/hubadmin.go | 105 ++++++++++++++++++++++++++++++ privilege/config/config.go | 29 +++++++++ privilege/config/model.go | 29 +++++++++ privilege/controller/privilege.go | 66 +++++++++++++++++++ 8 files changed, 345 insertions(+), 1 deletion(-) create mode 100644 .env.test create mode 100644 cmd/main.go create mode 100644 go.sum create mode 100644 privilege/client/hubadmin.go create mode 100644 privilege/config/config.go create mode 100644 privilege/config/model.go create mode 100644 privilege/controller/privilege.go diff --git a/.env.test b/.env.test new file mode 100644 index 0000000..7ebf98b --- /dev/null +++ b/.env.test @@ -0,0 +1,4 @@ +HTTP_PORT = 8080 +HTTP_HOST=localhost +ADMIN_GET_PRIVILEGE_URL = http://localhost:8081/privilege +ADMIN_POST_PRIVILEGE_URL = http://localhost:8081/privilege \ No newline at end of file diff --git a/cmd/main.go b/cmd/main.go new file mode 100644 index 0000000..f3657d2 --- /dev/null +++ b/cmd/main.go @@ -0,0 +1,55 @@ +package main + +import ( + "github.com/gofiber/fiber/v2" + "github.com/sirupsen/logrus" + "os" + "os/signal" + "penahub.gitlab.yandexcloud.net/backend/penahub_common/privilege/client" + "penahub.gitlab.yandexcloud.net/backend/penahub_common/privilege/config" + "penahub.gitlab.yandexcloud.net/backend/penahub_common/privilege/controller" +) + +func main() { + logger := logrus.New() + + cfg, err := config.LoadConfig() + if err != nil { + logger.Fatal("Error loading configuration:", err) + } + + hubAdminClient := client.NewHubAdminClient(&client.HubAdminClientDeps{ + Logger: logger, + URLs: &config.AdminMicroServiceURL{ + GetPrivilege: cfg.AdminGetPrivilege, + PostPrivilege: cfg.AdminPostPrivilege, + }, + }) + + privilegeController := controller.NewPrivilegeController(logger, hubAdminClient) + + app := fiber.New() + + app.Post("/check", privilegeController.Check) + + go gracefulShutdown(app, logger) + + err = app.Listen(cfg.HTTPHost + ":" + cfg.HTTPPort) + if err != nil { + logger.Fatal("Error starting Fiber app:", err) + } +} + +func gracefulShutdown(app *fiber.App, logger *logrus.Logger) { + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt, os.Kill) + + <-c + logger.Info("Shutting down...") + + if err := app.Shutdown(); err != nil { + logger.Error("Graceful shutdown failed:", err) + } else { + logger.Info("Graceful shutdown completed") + } +} diff --git a/go.mod b/go.mod index c16a3b3..105e41b 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,20 @@ module penahub.gitlab.yandexcloud.net/backend/penahub_common go 1.19 -require github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect +require ( + github.com/andybalholm/brotli v1.0.5 // indirect + github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect + github.com/gofiber/fiber/v2 v2.51.0 // indirect + github.com/google/uuid v1.4.0 // indirect + github.com/joho/godotenv v1.5.1 // indirect + github.com/klauspost/compress v1.16.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.50.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + golang.org/x/sys v0.14.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..01c962a --- /dev/null +++ b/go.sum @@ -0,0 +1,40 @@ +github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/gofiber/fiber/v2 v2.51.0 h1:JNACcZy5e2tGApWB2QrRpenTWn0fq0hkFm6k0C86gKQ= +github.com/gofiber/fiber/v2 v2.51.0/go.mod h1:xaQRZQJGqnKOQnbQw+ltvku3/h8QxvNi8o6JiJ7Ll0U= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= +github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.50.0 h1:H7fweIlBm0rXLs2q0XbalvJ6r0CUPFWK3/bB4N13e9M= +github.com/valyala/fasthttp v1.50.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= +github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/privilege/client/hubadmin.go b/privilege/client/hubadmin.go new file mode 100644 index 0000000..53bb0b6 --- /dev/null +++ b/privilege/client/hubadmin.go @@ -0,0 +1,105 @@ +package client + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "github.com/sirupsen/logrus" + "io" + "net/http" + "penahub.gitlab.yandexcloud.net/backend/penahub_common/privilege/config" +) + +type HubAdminClientDeps struct { + Logger *logrus.Logger + URLs *config.AdminMicroServiceURL +} + +type HubAdminClient struct { + logger *logrus.Logger + urls *config.AdminMicroServiceURL +} + +func NewHubAdminClient(deps *HubAdminClientDeps) *HubAdminClient { + return &HubAdminClient{ + logger: deps.Logger, + urls: deps.URLs, + } +} + +func (receiver *HubAdminClient) GetPrivilege(ctx context.Context) ([]config.Privilege, error) { + hubAdminURL := receiver.urls.GetPrivilege + req, err := http.NewRequestWithContext(ctx, http.MethodGet, hubAdminURL, nil) + if err != nil { + receiver.logger.Errorf("failed to create GET request: %v", err) + return nil, err + } + + response, err := http.DefaultClient.Do(req) + if err != nil { + receiver.logger.Errorf("failed to get privilege on of : %v", err) + return nil, err + } + defer response.Body.Close() + + if response.StatusCode != http.StatusOK { + return nil, errors.New("unexpected status code") + } + + var buffer bytes.Buffer + if _, err := io.Copy(&buffer, response.Body); err != nil { + receiver.logger.Errorf("failed to read response body: %v", err) + return nil, err + } + + var privileges []config.Privilege + if err := json.Unmarshal(buffer.Bytes(), &privileges); err != nil { + receiver.logger.Errorf("failed to unmarshal response body: %v", err) + return nil, err + } + + return privileges, nil +} + +func (receiver *HubAdminClient) PostPrivilege(ctx context.Context, data []config.Privilege) ([]config.Privilege, error) { + postPrivilegeURL := receiver.urls.PostPrivilege + + payload, err := json.Marshal(data) + if err != nil { + receiver.logger.Errorf("failed to marshal request body: %v", err) + return nil, err + } + + req, err := http.NewRequestWithContext(ctx, http.MethodPost, postPrivilegeURL, bytes.NewBuffer(payload)) + if err != nil { + receiver.logger.Errorf("failed to create POST request: %v", err) + return nil, err + } + req.Header.Set("Content-Type", "application/json") + + response, err := http.DefaultClient.Do(req) + if err != nil { + receiver.logger.Errorf("failed to post privilege on of : %v", err) + return nil, err + } + defer response.Body.Close() + + if response.StatusCode != http.StatusOK { + return nil, errors.New("unexpected status code") + } + + var buffer bytes.Buffer + if _, err := io.Copy(&buffer, response.Body); err != nil { + receiver.logger.Errorf("failed to read response body: %v", err) + return nil, err + } + + var privileges []config.Privilege + if err := json.Unmarshal(buffer.Bytes(), &privileges); err != nil { + receiver.logger.Errorf("failed to unmarshal response body: %v", err) + return nil, err + } + + return privileges, nil +} diff --git a/privilege/config/config.go b/privilege/config/config.go new file mode 100644 index 0000000..944e76d --- /dev/null +++ b/privilege/config/config.go @@ -0,0 +1,29 @@ +package config + +import ( + "github.com/joho/godotenv" + "log" + "os" +) + +type Config struct { + HTTPPort string + HTTPHost string + AdminGetPrivilege string + AdminPostPrivilege string +} + +func LoadConfig() (*Config, error) { + err := godotenv.Load("./env.test") + if err != nil { + log.Fatal("Error loading .env file") + return nil, err + } + + return &Config{ + HTTPPort: os.Getenv("HTTP_PORT"), + HTTPHost: os.Getenv("HTTP_HOST"), + AdminGetPrivilege: os.Getenv("ADMIN_GET_PRIVILEGE_URL"), + AdminPostPrivilege: os.Getenv("ADMIN_POST_PRIVILEGE_URL"), + }, nil +} diff --git a/privilege/config/model.go b/privilege/config/model.go new file mode 100644 index 0000000..8a1919b --- /dev/null +++ b/privilege/config/model.go @@ -0,0 +1,29 @@ +package config + +import "time" + +type Privilege struct { + ID string `json:"_id"` + PrivilegeID string `json:"privilegeId"` + Name string `json:"name"` + ServiceKey string `json:"serviceKey"` + Description string `json:"description"` + Type string `json:"type"` + Value string `json:"value"` + Price float64 `json:"price"` + Amount int `json:"amount"` + IsDeleted bool `json:"isDeleted"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + DeletedAt time.Time `json:"deletedAt"` +} + +type RequestParams struct { + ServiceName string `json:"service"` + Privileges []Privilege `json:"privileges"` +} + +type AdminMicroServiceURL struct { + GetPrivilege string + PostPrivilege string +} diff --git a/privilege/controller/privilege.go b/privilege/controller/privilege.go new file mode 100644 index 0000000..392d25e --- /dev/null +++ b/privilege/controller/privilege.go @@ -0,0 +1,66 @@ +package controller + +import ( + "github.com/gofiber/fiber/v2" + "github.com/sirupsen/logrus" + "net/http" + "penahub.gitlab.yandexcloud.net/backend/penahub_common/privilege/client" + "penahub.gitlab.yandexcloud.net/backend/penahub_common/privilege/config" +) + +type Controller struct { + logger *logrus.Logger + hubAdmin *client.HubAdminClient +} + +func NewPrivilegeController(logger *logrus.Logger, hubAdmin *client.HubAdminClient) *Controller { + return &Controller{ + logger: logger, + hubAdmin: hubAdmin, + } +} + +func (receiver *Controller) Check(c *fiber.Ctx) error { + ctx := c.Context() + + var requestParams config.RequestParams + if err := c.BodyParser(&requestParams); err != nil { + receiver.logger.Errorf("failed to parse request body: %v", err) + return c.Status(http.StatusBadRequest).JSON(map[string]string{"error": "invalid request body"}) + } + + existingPrivileges, err := receiver.hubAdmin.GetPrivilege(ctx) + if err != nil { + receiver.logger.Errorf("failed to get existing privileges: %v", err) + return c.Status(http.StatusInternalServerError).JSON(map[string]string{"error": "failed to get existing privileges"}) + } + + updatedPrivileges := compareAndMergePrivileges(existingPrivileges, requestParams.Privileges) + if len(updatedPrivileges) == 0 { + return c.Status(http.StatusOK).JSON("no updates") + } + + _, err = receiver.hubAdmin.PostPrivilege(ctx, updatedPrivileges) + if err != nil { + receiver.logger.Errorf("failed to post privileges: %v", err) + return c.Status(http.StatusInternalServerError).JSON(map[string]string{"error": "failed to post privileges"}) + } + + return c.Status(http.StatusOK).JSON(map[string][]config.Privilege{"successful registration": updatedPrivileges}) +} + +func compareAndMergePrivileges(existing []config.Privilege, incoming []config.Privilege) []config.Privilege { + existingMap := make(map[string]config.Privilege) + result := make([]config.Privilege, 0) + for _, privilege := range existing { + existingMap[privilege.ID] = privilege + } + + for _, privilege := range incoming { + if _, found := existingMap[privilege.ID]; !found { + result = append(existing, existingMap[privilege.ID]) + } + } + + return result +}