From 083c02116b142eb189cd6017dfcb3b8bf97c59a8 Mon Sep 17 00:00:00 2001 From: Dmitry Sirotkin Date: Fri, 21 Mar 2025 19:49:54 +0300 Subject: [PATCH] init --- .gitignore | 2 + cmd/workshop.go | 28 ++++++++++ go.mod | 16 ++++++ go.sum | 39 ++++++++++++++ internal/controllers/accountController.go | 19 +++++++ internal/controllers/contactController.go | 33 ++++++++++++ internal/models/bonuse.go | 38 +++++++++++++ internal/models/client.go | 21 ++++++++ internal/models/contact.go | 66 +++++++++++++++++++++++ internal/models/db.go | 39 ++++++++++++++ internal/models/service.go | 23 ++++++++ internal/utils/utils.go | 15 ++++++ 12 files changed, 339 insertions(+) create mode 100644 .gitignore create mode 100644 cmd/workshop.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 internal/controllers/accountController.go create mode 100644 internal/controllers/contactController.go create mode 100644 internal/models/bonuse.go create mode 100644 internal/models/client.go create mode 100644 internal/models/contact.go create mode 100644 internal/models/db.go create mode 100644 internal/models/service.go create mode 100644 internal/utils/utils.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5048da6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.vscode +.env \ No newline at end of file diff --git a/cmd/workshop.go b/cmd/workshop.go new file mode 100644 index 0000000..1e391b4 --- /dev/null +++ b/cmd/workshop.go @@ -0,0 +1,28 @@ +package main + +import ( + "gocommunity.ru/workshop/internal/controllers" + "fmt" + "github.com/gorilla/mux" + "net/http" + "os" +) + +func main() { + + router := mux.NewRouter() + + router.HandleFunc("/user/new", controllers.CreateService).Methods("POST") + router.HandleFunc("/contacts/new", controllers.CreateContact).Methods("POST") + router.HandleFunc("/me/contacts", controllers.GetContacts).Methods("GET") + + port := os.Getenv("PORT") + if port == "" { + port = "8000" + } + + err := http.ListenAndServe(":"+port, router) + if err != nil { + fmt.Print(err) + } +} \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..a3109a8 --- /dev/null +++ b/go.mod @@ -0,0 +1,16 @@ +module gocommunity.ru/workshop + +go 1.23.6 + +require ( + github.com/dgrijalva/jwt-go v3.2.0+incompatible + github.com/gorilla/mux v1.8.1 + github.com/jinzhu/gorm v1.9.16 + github.com/joho/godotenv v1.5.1 + golang.org/x/crypto v0.36.0 +) + +require ( + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/lib/pq v1.1.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..bd7f3db --- /dev/null +++ b/go.sum @@ -0,0 +1,39 @@ +github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= +github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= +github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM= +github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= +github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o= +github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M= +github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4= +github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA= +github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +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.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +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-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/internal/controllers/accountController.go b/internal/controllers/accountController.go new file mode 100644 index 0000000..ca4b89e --- /dev/null +++ b/internal/controllers/accountController.go @@ -0,0 +1,19 @@ +package controllers + +import ( + "gocommunity.ru/workshop/internal/models" + u "gocommunity.ru/workshop/internal/utils" + "encoding/json" + "net/http" +) + +var CreateService = func(w http.ResponseWriter, r *http.Request) { + account := &models.Service{} + err := json.NewDecoder(r.Body).Decode(account) + if err != nil { + u.Respond(w, u.Message(false, "Invalid request!")) + return + } + resp := account.CreateService() + u.Respond(w, resp) +} diff --git a/internal/controllers/contactController.go b/internal/controllers/contactController.go new file mode 100644 index 0000000..b11bc3d --- /dev/null +++ b/internal/controllers/contactController.go @@ -0,0 +1,33 @@ +package controllers + +import ( + "gocommunity.ru/workshop/internal/models" + u "gocommunity.ru/workshop/internal/utils" + "encoding/json" + "net/http" +) + +var CreateContact = func(w http.ResponseWriter, r *http.Request) { + + user := r.Context().Value("user").(uint) + contact := &models.Contact{} + + err := json.NewDecoder(r.Body).Decode(contact) + if err != nil { + u.Respond(w, u.Message(false, "Error!")) + return + } + + contact.UserId = user + resp := contact.CreateContact() + u.Respond(w, resp) +} + +var GetContacts = func(w http.ResponseWriter, r *http.Request) { + + id := r.Context().Value("user").(uint) + data := models.GetContacts(id) + resp := u.Message(true, "success") + resp["data"] = data + u.Respond(w, resp) +} diff --git a/internal/models/bonuse.go b/internal/models/bonuse.go new file mode 100644 index 0000000..20ce37d --- /dev/null +++ b/internal/models/bonuse.go @@ -0,0 +1,38 @@ +package models + +import ( + u "gocommunity.ru/workshop/internal/utils" + "github.com/jinzhu/gorm" +) + +type Bonuse struct { + gorm.Model + DiscountPercent uint16 `json:"discount_percent"` + ClientId uint `gorm:"column:client_id"` +} + +func (bonuse *Bonuse) ValidateBonuse() (map[string]any, bool) { + + if bonuse.ClientId <= 0 { + return u.Message(false, "value should be > 0"), false + } + + if bonuse.DiscountPercent <= 0 || bonuse.DiscountPercent > 100 { + return u.Message(false, "value should be betwen 0 and 100!"), false + } + + return u.Message(true, "success"), true +} + +func (bonuse *Bonuse) CreateBonuse() map[string]interface{} { + + if response, ok := bonuse.ValidateBonuse(); !ok { + return response + } + + GetDB().Create(bonuse) + + resp := u.Message(true, "success") + resp["bonuse"] = bonuse + return resp +} diff --git a/internal/models/client.go b/internal/models/client.go new file mode 100644 index 0000000..e887def --- /dev/null +++ b/internal/models/client.go @@ -0,0 +1,21 @@ +package models + +import ( + u "gocommunity.ru/workshop/internal/utils" + "github.com/jinzhu/gorm" +) + +type Client struct { + gorm.Model + Bonuse Bonuse `json:"bonus_id"` + Name string `json:"name"` +} + +func (client *Client) CreateClient() map[string]interface{} { + + GetDB().Create(client) + + resp := u.Message(true, "success") + resp["client"] = client + return resp +} \ No newline at end of file diff --git a/internal/models/contact.go b/internal/models/contact.go new file mode 100644 index 0000000..5f48074 --- /dev/null +++ b/internal/models/contact.go @@ -0,0 +1,66 @@ +package models + +import ( + u "gocommunity.ru/workshop/internal/utils" + "fmt" + "github.com/jinzhu/gorm" +) + +type Contact struct { + gorm.Model + Name string `json:"name"` + Phone string `json:"phone"` + UserId uint `json:"user_id"` +} + +func (contact *Contact) ValidateContact() (map[string]interface{}, bool) { + + if contact.Name == "" { + return u.Message(false, "Name cannot be empty!"), false + } + + if contact.Phone == "" { + return u.Message(false, "Phone number cannot be empty!"), false + } + + if contact.UserId <= 0 { + return u.Message(false, "User not found!"), false + } + + return u.Message(true, "success"), true +} + +func (contact *Contact) CreateContact() map[string]interface{} { + + if response, ok := contact.ValidateContact(); !ok { + return response + } + + GetDB().Create(contact) + + resp := u.Message(true, "success") + resp["contact"] = contact + return resp +} + +func GetContact(id uint) *Contact { + + contact := &Contact{} + err := GetDB().Table("contacts").Where("id = ?", id).First(contact).Error + if err != nil { + return nil + } + return contact +} + +func GetContacts(user uint) []*Contact { + + contactsSlice := make([]*Contact, 0) + err := GetDB().Table("contacts").Where("user_id = ?", user).Find(&contactsSlice).Error + if err != nil { + fmt.Println(err) + return nil + } + + return contactsSlice +} diff --git a/internal/models/db.go b/internal/models/db.go new file mode 100644 index 0000000..60befd9 --- /dev/null +++ b/internal/models/db.go @@ -0,0 +1,39 @@ +package models + +import ( + "fmt" + "github.com/jinzhu/gorm" + _ "github.com/jinzhu/gorm/dialects/postgres" + "github.com/joho/godotenv" + "os" +) + +var db *gorm.DB //База данных + +func init() { + + e := godotenv.Load() + if e != nil { + fmt.Print(e) + } + + username := os.Getenv("DB_USER") + password := os.Getenv("DB_PASS") + dbName := os.Getenv("DB_NAME") + dbHost := os.Getenv("DB_HOST") + + dbUri := fmt.Sprintf("host=%s user=%s dbname=%s sslmode=disable password=%s", dbHost, username, dbName, password) + fmt.Println(dbUri) + + conn, err := gorm.Open("postgres", dbUri) + if err != nil { + fmt.Print(err) + } + + db = conn + db.Debug().AutoMigrate(&Service{}, &Bonuse{}, &Client{}) //Миграция базы данных +} + +func GetDB() *gorm.DB { + return db +} diff --git a/internal/models/service.go b/internal/models/service.go new file mode 100644 index 0000000..8356dda --- /dev/null +++ b/internal/models/service.go @@ -0,0 +1,23 @@ +package models + +import ( + u "gocommunity.ru/workshop/internal/utils" + "github.com/jinzhu/gorm" +) + +type Service struct { + gorm.Model + Price string `json:"email"` + Name string `json:"name"` + Description string `json:"description"` +} + + +func (service *Service) CreateService() map[string]interface{} { + + GetDB().Create(service) + + resp := u.Message(true, "success") + resp["service"] = service + return resp +} diff --git a/internal/utils/utils.go b/internal/utils/utils.go new file mode 100644 index 0000000..5f51065 --- /dev/null +++ b/internal/utils/utils.go @@ -0,0 +1,15 @@ +package utils + +import ( + "encoding/json" + "net/http" +) + +func Message(status bool, message string) map[string]interface{} { + return map[string]interface{}{"status": status, "message": message} +} + +func Respond(w http.ResponseWriter, data map[string]interface{}) { + w.Header().Add("Content-Type", "application/json") + json.NewEncoder(w).Encode(data) +}