diff --git a/api/api.go b/api/api.go index ada2548..1925d88 100644 --- a/api/api.go +++ b/api/api.go @@ -1,8 +1,12 @@ package api import ( + "math/rand" "net/http" + "os" + "time" + "github.com/Iknite-Space/sqlc-example-api/campay" "github.com/Iknite-Space/sqlc-example-api/db/repo" "github.com/gin-gonic/gin" ) @@ -25,62 +29,84 @@ func (h *MessageHandler) WireHttpHandler() http.Handler { c.AbortWithStatus(http.StatusInternalServerError) })) - r.POST("/message", h.handleCreateMessage) - r.GET("/message/:id", h.handleGetMessage) - r.GET("/thread/:id/messages", h.handleGetThreadMessages) + r.POST("/customer", h.handleCreateCustomer) + r.POST("/order/", h.handleCreateOrders) + // r.GET("/thread/:id/messages", h.handleGetThreadMessages) + //r.POST("/orders", h.handleCreateCustomerOrders) return r } -func (h *MessageHandler) handleCreateMessage(c *gin.Context) { - var req repo.CreateMessageParams +func (h *MessageHandler) handleCreateCustomer(c *gin.Context) { + var req repo.CreateCustomerParams err := c.ShouldBindBodyWithJSON(&req) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } - message, err := h.querier.CreateMessage(c, req) + customer, err := h.querier.CreateCustomer(c, req) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } - c.JSON(http.StatusOK, message) + c.JSON(http.StatusOK, customer) } -func (h *MessageHandler) handleGetMessage(c *gin.Context) { - id := c.Param("id") - if id == "" { - c.JSON(http.StatusBadRequest, gin.H{"error": "id is required"}) +func (h *MessageHandler) handleCreateOrders(c *gin.Context) { + var req repo.CreateOrderParams + err := c.ShouldBindBodyWithJSON(&req) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } - message, err := h.querier.GetMessageByID(c, id) + order, err := h.querier.CreateOrder(c, req) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } - c.JSON(http.StatusOK, message) -} + num := "673501707" + amount := "13" + des := "order" + ref := GenerateRandomLetters(10) -func (h *MessageHandler) handleGetThreadMessages(c *gin.Context) { - id := c.Param("id") - if id == "" { - c.JSON(http.StatusBadRequest, gin.H{"error": "id is required"}) - return + apik := os.Getenv("API_KEY") + + reqpay := campay.Payment(apik, num, amount, des, ref) + + time.Sleep(20 * time.Second) + + state := campay.Status(apik, reqpay.Reference) + + reqs := repo.UpadateOrderByIdParams{ + ID: order.ID, + OrderStatus: state.Status, } - messages, err := h.querier.GetMessagesByThread(c, id) + updatedOrder, err := h.querier.UpadateOrderById(c, reqs) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } - c.JSON(http.StatusOK, gin.H{ - "thread": id, - "topic": "example", - "messages": messages, - }) + c.JSON(http.StatusOK, gin.H{"Order Created": updatedOrder, "campay request": reqpay, "campay response": state}) +} + +// Function to generate random letters +func GenerateRandomLetters(n int) string { + // Define the set of characters to choose from + letters := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + + // Create a new random generator with a source based on the current time + r := rand.New(rand.NewSource(time.Now().UnixNano())) + + // Create a slice to store the random letters + randomLetters := make([]byte, n) + for i := 0; i < n; i++ { + randomLetters[i] = letters[r.Intn(len(letters))] + } + return string(randomLetters) } diff --git a/bin/api b/bin/api new file mode 100755 index 0000000..59c2360 Binary files /dev/null and b/bin/api differ diff --git a/campay/PaymentStatus.go b/campay/PaymentStatus.go new file mode 100644 index 0000000..d743195 --- /dev/null +++ b/campay/PaymentStatus.go @@ -0,0 +1,51 @@ +package campay + +import ( + "encoding/json" + "fmt" + "log" + "net/http" +) + +type PaymentStatus struct { + Reference string `json:"reference"` + Status string `json:"status"` +} + +func Status(apikey string, reference string) PaymentStatus { + client := &http.Client{} + var url = fmt.Sprintf("https://demo.campay.net/api/transaction/%s/", reference) + + req, err := http.NewRequest("GET", url, nil) + if err != nil { + fmt.Printf(" could not make a new request") + log.Fatal(err) + } + req.Header.Set("Authorization", fmt.Sprintf("Token %s", apikey)) + req.Header.Add("Content-Type", "application/json") + + resp, err := client.Do(req) + if err != nil { + fmt.Printf(" check get request method") + log.Fatal(err) + } + + defer func() { + if err := resp.Body.Close(); err != nil { + log.Printf("failed to close response body: %v", err) + } + }() + + var state PaymentStatus + if err := json.NewDecoder(resp.Body).Decode(&state); err != nil { + log.Printf("failed to decode response: %v", err) + + } + return state + // defer resp.Body.Close() + + // var state PaymentStatus + // json.NewDecoder(resp.Body).Decode(&state) + // return state + +} diff --git a/campay/RequestPayment.go b/campay/RequestPayment.go new file mode 100644 index 0000000..7b5decb --- /dev/null +++ b/campay/RequestPayment.go @@ -0,0 +1,72 @@ +package campay + +import ( + "bytes" + "encoding/json" + "fmt" + "log" + "net/http" +) + +type PaymentRequest struct { + From string `json:"from"` + Amount string `json:"amount"` + Description string `json:"description"` + External_Reference string `json:"external_reference"` +} + +type PaymentResponse struct { + Reference string `json:"reference"` + Ussd_Code string `json:"ussd_code"` +} + +func Payment(apikey string, number string, amount string, description string, external_reference string) PaymentResponse { + + number = "237" + number + + client := &http.Client{} + + iraq := PaymentRequest{ + From: number, + Amount: amount, + Description: description, + External_Reference: external_reference, + } + + postbody, _ := json.Marshal(iraq) + + postbodyparam := bytes.NewBuffer(postbody) + + req, err := http.NewRequest("POST", "https://demo.campay.net/api/collect/", postbodyparam) + + if err != nil { + fmt.Printf(" could not make a new request") + log.Fatal(err) + } + req.Header.Set("Authorization", fmt.Sprintf("Token %s", apikey)) + req.Header.Add("Content-Type", "application/json") + + response, err := client.Do(req) + if err != nil { + fmt.Println("Invalid Request, check POST request credentials") + log.Fatal(err) + } + + defer func() { + if err := response.Body.Close(); err != nil { + log.Printf("failed to close response body: %v", err) + } + }() + + var makepay PaymentResponse + if err := json.NewDecoder(response.Body).Decode(&makepay); err != nil { + log.Printf("failed to decode response: %v", err) + } + + return makepay + // defer response.Body.Close() + + // var makepay PaymentResponse + // json.NewDecoder(response.Body).Decode(&makepay) + // return makepay +} diff --git a/db/migrations/000001_init_schema.down.sql b/db/migrations/000001_init_schema.down.sql index 6782590..0ba494a 100644 --- a/db/migrations/000001_init_schema.down.sql +++ b/db/migrations/000001_init_schema.down.sql @@ -1,3 +1 @@ -DROP TABLE users; -DROP TYPE user_status; -DROP TYPE identity_document; \ No newline at end of file +DROP TABLE customer; \ No newline at end of file diff --git a/db/migrations/000001_init_schema.up.sql b/db/migrations/000001_init_schema.up.sql index ee92b1e..b8e65ff 100644 --- a/db/migrations/000001_init_schema.up.sql +++ b/db/migrations/000001_init_schema.up.sql @@ -1,12 +1,7 @@ - - - - -CREATE TABLE "message" ( - "id" VARCHAR(36) PRIMARY KEY DEFAULT gen_random_uuid()::varchar(36), - "thread" VARCHAR(36) NOT NULL, - "sender" VARCHAR(100) NOT NULL, - "content" TEXT NOT NULL, - "created_at" TIMESTAMP DEFAULT now() +CREATE TABLE "customer" ( +"id" VARCHAR(36) PRIMARY KEY DEFAULT gen_random_uuid()::varchar(36), +"customer_name" VARCHAR(100) NOT NULL, +"phone_number" VARCHAR(20) NOT NULL UNIQUE, +"email" VARCHAR(100) NOT NULL UNIQUE, +"created_at" TIMESTAMP DEFAULT now() ); - diff --git a/db/migrations/000002_orders_table.down.sql b/db/migrations/000002_orders_table.down.sql new file mode 100644 index 0000000..90a3149 --- /dev/null +++ b/db/migrations/000002_orders_table.down.sql @@ -0,0 +1 @@ +DROP TABLE order \ No newline at end of file diff --git a/db/migrations/000002_orders_table.up.sql b/db/migrations/000002_orders_table.up.sql new file mode 100644 index 0000000..9ebf929 --- /dev/null +++ b/db/migrations/000002_orders_table.up.sql @@ -0,0 +1,13 @@ +CREATE TABLE "order" ( + "id" VARCHAR(36) PRIMARY KEY DEFAULT gen_random_uuid()::varchar(36), + "customer_id" VARCHAR(36) NOT NULL, + "product_name" VARCHAR(30) NOT NULL, + "price" VARCHAR(10) NOT NULL, + "order_status" VARCHAR(20) NOT NULL, + "order_date" TIMESTAMP DEFAULT now() NOT NULL, + FOREIGN KEY ("customer_id") + REFERENCES "customer"("id") + ON DELETE CASCADE +) + + \ No newline at end of file diff --git a/db/query/message.sql b/db/query/message.sql index 1d34c69..04d0447 100644 --- a/db/query/message.sql +++ b/db/query/message.sql @@ -1,13 +1,34 @@ --- name: CreateMessage :one -INSERT INTO message (thread, sender, content) +-- -- name: CreateMessage :one +-- INSERT INTO message (thread, sender, content) +-- VALUES ($1, $2, $3) +-- RETURNING *; + +-- -- name: GetMessageByID :one +-- SELECT * FROM message +-- WHERE id = $1; + +-- -- name: GetMessagesByThread :many +-- SELECT * FROM message +-- WHERE thread = $1 +-- ORDER BY created_at DESC; + +-- -- name: CustomerOrders :many +-- INSERT INTO orders (reference, phone_number, amount, transaction_status, transaction_description) +-- VALUES ($1, $2, $3, $4, $5) +-- RETURNING *; + +-- name: CreateCustomer :one +INSERT INTO customer (customer_name, phone_number, email) VALUES ($1, $2, $3) RETURNING *; --- name: GetMessageByID :one -SELECT * FROM message -WHERE id = $1; +-- name: CreateOrder :one +INSERT INTO "order" (customer_id, product_name, price, order_status) +VALUES ($1, $2, $3, $4) +RETURNING *; --- name: GetMessagesByThread :many -SELECT * FROM message -WHERE thread = $1 -ORDER BY created_at DESC; \ No newline at end of file +-- name: UpadateOrderById :one +UPDATE "order" +SET order_status = $2 +WHERE id =$1 +RETURNING *; \ No newline at end of file diff --git a/db/repo/message.sql.go b/db/repo/message.sql.go index ce74c13..92cc2aa 100644 --- a/db/repo/message.sql.go +++ b/db/repo/message.sql.go @@ -9,77 +9,104 @@ import ( "context" ) -const createMessage = `-- name: CreateMessage :one -INSERT INTO message (thread, sender, content) +const createCustomer = `-- name: CreateCustomer :one + + + + +INSERT INTO customer (customer_name, phone_number, email) VALUES ($1, $2, $3) -RETURNING id, thread, sender, content, created_at +RETURNING id, customer_name, phone_number, email, created_at ` -type CreateMessageParams struct { - Thread string `json:"thread"` - Sender string `json:"sender"` - Content string `json:"content"` +type CreateCustomerParams struct { + CustomerName string `json:"customer_name"` + PhoneNumber string `json:"phone_number"` + Email string `json:"email"` } -func (q *Queries) CreateMessage(ctx context.Context, arg CreateMessageParams) (Message, error) { - row := q.db.QueryRow(ctx, createMessage, arg.Thread, arg.Sender, arg.Content) - var i Message +// -- name: CreateMessage :one +// INSERT INTO message (thread, sender, content) +// VALUES ($1, $2, $3) +// RETURNING *; +// -- name: GetMessageByID :one +// SELECT * FROM message +// WHERE id = $1; +// -- name: GetMessagesByThread :many +// SELECT * FROM message +// WHERE thread = $1 +// ORDER BY created_at DESC; +// -- name: CustomerOrders :many +// INSERT INTO orders (reference, phone_number, amount, transaction_status, transaction_description) +// VALUES ($1, $2, $3, $4, $5) +// RETURNING *; +func (q *Queries) CreateCustomer(ctx context.Context, arg CreateCustomerParams) (Customer, error) { + row := q.db.QueryRow(ctx, createCustomer, arg.CustomerName, arg.PhoneNumber, arg.Email) + var i Customer err := row.Scan( &i.ID, - &i.Thread, - &i.Sender, - &i.Content, + &i.CustomerName, + &i.PhoneNumber, + &i.Email, &i.CreatedAt, ) return i, err } -const getMessageByID = `-- name: GetMessageByID :one -SELECT id, thread, sender, content, created_at FROM message -WHERE id = $1 +const createOrder = `-- name: CreateOrder :one +INSERT INTO "order" (customer_id, product_name, price, order_status) +VALUES ($1, $2, $3, $4) +RETURNING id, customer_id, product_name, price, order_status, order_date ` -func (q *Queries) GetMessageByID(ctx context.Context, id string) (Message, error) { - row := q.db.QueryRow(ctx, getMessageByID, id) - var i Message +type CreateOrderParams struct { + CustomerID string `json:"customer_id"` + ProductName string `json:"product_name"` + Price string `json:"price"` + OrderStatus string `json:"order_status"` +} + +func (q *Queries) CreateOrder(ctx context.Context, arg CreateOrderParams) (Order, error) { + row := q.db.QueryRow(ctx, createOrder, + arg.CustomerID, + arg.ProductName, + arg.Price, + arg.OrderStatus, + ) + var i Order err := row.Scan( &i.ID, - &i.Thread, - &i.Sender, - &i.Content, - &i.CreatedAt, + &i.CustomerID, + &i.ProductName, + &i.Price, + &i.OrderStatus, + &i.OrderDate, ) return i, err } -const getMessagesByThread = `-- name: GetMessagesByThread :many -SELECT id, thread, sender, content, created_at FROM message -WHERE thread = $1 -ORDER BY created_at DESC +const upadateOrderById = `-- name: UpadateOrderById :one +UPDATE "order" +SET order_status = $2 +WHERE id =$1 +RETURNING id, customer_id, product_name, price, order_status, order_date ` -func (q *Queries) GetMessagesByThread(ctx context.Context, thread string) ([]Message, error) { - rows, err := q.db.Query(ctx, getMessagesByThread, thread) - if err != nil { - return nil, err - } - defer rows.Close() - items := []Message{} - for rows.Next() { - var i Message - if err := rows.Scan( - &i.ID, - &i.Thread, - &i.Sender, - &i.Content, - &i.CreatedAt, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil +type UpadateOrderByIdParams struct { + ID string `json:"id"` + OrderStatus string `json:"order_status"` +} + +func (q *Queries) UpadateOrderById(ctx context.Context, arg UpadateOrderByIdParams) (Order, error) { + row := q.db.QueryRow(ctx, upadateOrderById, arg.ID, arg.OrderStatus) + var i Order + err := row.Scan( + &i.ID, + &i.CustomerID, + &i.ProductName, + &i.Price, + &i.OrderStatus, + &i.OrderDate, + ) + return i, err } diff --git a/db/repo/migrations.go b/db/repo/migrations.go index cb9f2cd..2650ab5 100644 --- a/db/repo/migrations.go +++ b/db/repo/migrations.go @@ -2,6 +2,7 @@ package repo import ( "errors" + "log" "path/filepath" "github.com/golang-migrate/migrate/v4" @@ -25,7 +26,16 @@ func Migrate(dbURL string, migrationsPath string) error { if err != nil { return err } - defer m.Close() + + defer func() { + sourceErr, dbErr := m.Close() + if sourceErr != nil { + log.Printf("failed to close migration source: %v", sourceErr) + } + if dbErr != nil { + log.Printf("failed to close migration database: %v", dbErr) + } + }() // Apply migrations err = m.Up() @@ -51,7 +61,15 @@ func MigrateDown(dbURL string, migrationsPath string) error { if err != nil { return err } - defer m.Close() + defer func() { + sourceErr, dbErr := m.Close() + if sourceErr != nil { + log.Printf("failed to close migration source: %v", sourceErr) + } + if dbErr != nil { + log.Printf("failed to close migration database: %v", dbErr) + } + }() // Apply migrations err = m.Down() diff --git a/db/repo/models.go b/db/repo/models.go index 92c72c8..f1a1ff5 100644 --- a/db/repo/models.go +++ b/db/repo/models.go @@ -8,10 +8,19 @@ import ( "github.com/jackc/pgx/v5/pgtype" ) -type Message struct { - ID string `json:"id"` - Thread string `json:"thread"` - Sender string `json:"sender"` - Content string `json:"content"` - CreatedAt pgtype.Timestamp `json:"created_at"` +type Customer struct { + ID string `json:"id"` + CustomerName string `json:"customer_name"` + PhoneNumber string `json:"phone_number"` + Email string `json:"email"` + CreatedAt pgtype.Timestamp `json:"created_at"` +} + +type Order struct { + ID string `json:"id"` + CustomerID string `json:"customer_id"` + ProductName string `json:"product_name"` + Price string `json:"price"` + OrderStatus string `json:"order_status"` + OrderDate pgtype.Timestamp `json:"order_date"` } diff --git a/db/repo/querier.go b/db/repo/querier.go index 5b0504e..e81c716 100644 --- a/db/repo/querier.go +++ b/db/repo/querier.go @@ -9,9 +9,24 @@ import ( ) type Querier interface { - CreateMessage(ctx context.Context, arg CreateMessageParams) (Message, error) - GetMessageByID(ctx context.Context, id string) (Message, error) - GetMessagesByThread(ctx context.Context, thread string) ([]Message, error) + // -- name: CreateMessage :one + // INSERT INTO message (thread, sender, content) + // VALUES ($1, $2, $3) + // RETURNING *; + // -- name: GetMessageByID :one + // SELECT * FROM message + // WHERE id = $1; + // -- name: GetMessagesByThread :many + // SELECT * FROM message + // WHERE thread = $1 + // ORDER BY created_at DESC; + // -- name: CustomerOrders :many + // INSERT INTO orders (reference, phone_number, amount, transaction_status, transaction_description) + // VALUES ($1, $2, $3, $4, $5) + // RETURNING *; + CreateCustomer(ctx context.Context, arg CreateCustomerParams) (Customer, error) + CreateOrder(ctx context.Context, arg CreateOrderParams) (Order, error) + UpadateOrderById(ctx context.Context, arg UpadateOrderByIdParams) (Order, error) } var _ Querier = (*Queries)(nil) diff --git a/go.mod b/go.mod index 044585d..c319ada 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,6 @@ require ( github.com/golang-migrate/migrate/v4 v4.18.2 github.com/jackc/pgx/v5 v5.7.4 github.com/joho/godotenv v1.5.1 - github.com/rs/zerolog v1.34.0 ) require ( @@ -31,7 +30,6 @@ require ( github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/lib/pq v1.10.9 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -40,11 +38,11 @@ require ( github.com/ugorji/go/codec v1.2.12 // indirect go.uber.org/atomic v1.7.0 // indirect golang.org/x/arch v0.8.0 // indirect - golang.org/x/crypto v0.31.0 // indirect - golang.org/x/net v0.33.0 // indirect - golang.org/x/sync v0.10.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/crypto v0.36.0 // indirect + golang.org/x/net v0.38.0 // indirect + golang.org/x/sync v0.12.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/text v0.23.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index cfed3a0..486875c 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,7 @@ +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/ardanlabs/conf/v3 v3.4.0 h1:Qy7/doJjhsv7Lvzqd9tbvH8fAZ9jzqKtwnwcmZ+sxGs= github.com/ardanlabs/conf/v3 v3.4.0/go.mod h1:OIi6NK95fj8jKFPdZ/UmcPlY37JBg99hdP9o5XmNK9c= github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= @@ -8,15 +12,33 @@ github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 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= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dhui/dktest v0.4.4 h1:+I4s6JRE1yGuqflzwqG+aIaMdgXIorCf5P98JnaAWa8= +github.com/dhui/dktest v0.4.4/go.mod h1:4+22R4lgsdAXrDyaH4Nqx2JEz2hLp49MqQmm9HLCQhM= +github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v27.2.0+incompatible h1:Rk9nIVdfH3+Vz4cyI/uhbINhEZ/oLmc+CBXmH6fbNk4= +github.com/docker/docker v27.2.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= @@ -25,9 +47,12 @@ github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBEx github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-migrate/migrate/v4 v4.18.2 h1:2VSCMz7x7mjyTXx3m2zPokOY82LTRgxK1yQYKo6wWQ8= github.com/golang-migrate/migrate/v4 v4.18.2/go.mod h1:2CM6tJvn2kqPXwnXO/d3rAQYiyoIm180VsO8PRX6Rpk= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= @@ -50,28 +75,39 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -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.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 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/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +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/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= -github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= -github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -82,37 +118,44 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +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/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= +go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= +go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= +go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= +go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= +go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= +go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=