From 892307185a95218b580112727c00b77581d16bce Mon Sep 17 00:00:00 2001 From: Jasper Spahl Date: Mon, 24 Jan 2022 13:14:36 +0100 Subject: [PATCH] sql privider --- .vscode/settings.json | 11 +++ go.mod | 7 +- go.sum | 18 ++++- internal/api/api.go | 17 +++-- internal/implementations/MemoryProvider.go | 4 +- internal/implementations/SqlProvider.go | 82 ++++++++++++++++++++++ internal/models/Item.go | 17 +++++ internal/models/User.go | 17 +++++ internal/models/setup.go | 20 ++++++ internal/server/routes.go | 11 +-- internal/server/server.go | 3 + internal/types/IPersistentProvider.go | 2 +- internal/types/IUser.go | 1 + 13 files changed, 197 insertions(+), 13 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 internal/implementations/SqlProvider.go create mode 100644 internal/models/Item.go create mode 100644 internal/models/User.go create mode 100644 internal/models/setup.go diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..c5de3fb --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "sqltools.connections": [ + { + "previewLimit": 50, + "driver": "SQLite", + "name": "devdb", + "database": "${workspaceFolder}/dev.db" + } + ], + "sqltools.useNodeRuntime": true +} \ No newline at end of file diff --git a/go.mod b/go.mod index d3f269d..ac18b6b 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,9 @@ module dymatrix.de/jspahl/todo go 1.15 -require github.com/gin-gonic/gin v1.7.7 +require ( + github.com/gin-gonic/gin v1.7.7 + github.com/mattn/go-sqlite3 v1.14.10 + gorm.io/driver/sqlite v1.2.6 + gorm.io/gorm v1.22.5 +) diff --git a/go.sum b/go.sum index 5ee9be1..b62b75e 100644 --- a/go.sum +++ b/go.sum @@ -16,12 +16,20 @@ github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +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.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas= +github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.10 h1:MLn+5bFRlWMGoSRmJour3CL1w/qL96mvipqpwQW/Sfk= +github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= @@ -30,8 +38,9 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= @@ -52,3 +61,10 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/sqlite v1.2.6 h1:SStaH/b+280M7C8vXeZLz/zo9cLQmIGwwj3cSj7p6l4= +gorm.io/driver/sqlite v1.2.6/go.mod h1:gyoX0vHiiwi0g49tv+x2E7l8ksauLK0U/gShcdUsjWY= +gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= +gorm.io/gorm v1.22.5 h1:lYREBgc02Be/5lSCTuysZZDb6ffL2qrat6fg9CFbvXU= +gorm.io/gorm v1.22.5/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= diff --git a/internal/api/api.go b/internal/api/api.go index 5acd839..755cd74 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -21,12 +21,16 @@ func (item ItemDTO) GetMessage() string { } type UserDTO struct { - id int + id int + username string } func (user UserDTO) GetId() int { return user.id } +func (user UserDTO) GetUsername() string { + return user.username +} func ItemToDTO(item types.IItem) ItemDTO { var itemDto = ItemDTO{} @@ -132,13 +136,18 @@ func RegisterRoutes(router *gin.RouterGroup, prov types.IPersitenceProvider) { }) router.POST("/user", func(c *gin.Context) { var user struct { - id int + username string } if err := c.BindJSON(&user); err != nil { c.String(http.StatusBadRequest, err.Error()) return } - prov.CreateUser(UserDTO{user.id}) - c.Status(200) + id, err := prov.CreateUser(UserDTO{username: user.username}) + if err != nil { + c.String(404, err.Error()) + } + c.JSON(200, &gin.H{ + "id": id, + }) }) } diff --git a/internal/implementations/MemoryProvider.go b/internal/implementations/MemoryProvider.go index 890f231..55fe5b7 100644 --- a/internal/implementations/MemoryProvider.go +++ b/internal/implementations/MemoryProvider.go @@ -95,6 +95,6 @@ func (prov MemoryProvider) DeleteItem(item types.IItem) error { return nil } -func (prov MemoryProvider) CreateUser(user types.IUser) error { - return nil +func (prov MemoryProvider) CreateUser(user types.IUser) (int, error) { + return prov.index, nil } diff --git a/internal/implementations/SqlProvider.go b/internal/implementations/SqlProvider.go new file mode 100644 index 0000000..399e63c --- /dev/null +++ b/internal/implementations/SqlProvider.go @@ -0,0 +1,82 @@ +package implementations + +import ( + "dymatrix.de/jspahl/todo/internal/models" + "dymatrix.de/jspahl/todo/internal/types" +) + +type SqlProvider struct { +} + +func (prov SqlProvider) CreateItem(item types.IItem) error { + storedItem := models.Item{Message: item.GetMessage()} + result := models.DB.Create(storedItem) + if result.Error != nil { + return result.Error + } + return nil +} +func (prov SqlProvider) UpdateItem(item types.IItem) error { + var dbItem models.Item + result := models.DB.First(&dbItem, item.GetId()) + if result.Error != nil { + return result.Error + } + dbItem.Message = item.GetMessage() + result = models.DB.Save(&dbItem) + if result.Error != nil { + return result.Error + } + return nil +} +func (prov SqlProvider) GetItem(id int) (types.IItem, error) { + var dbItem models.Item + result := models.DB.First(&dbItem, id) + if result.Error != nil { + return nil, result.Error + } + return dbItem, nil +} +func (prov SqlProvider) GetItemByUser(user types.IUser) ([]types.IItem, error) { + var dbUser models.User + if result := models.DB.Preload("Items").First(&dbUser, user.GetId()); result.Error != nil { + return nil, result.Error + } + var items []types.IItem + for _, item := range dbUser.Items { + items = append(items, item) + } + return items, nil +} +func (prov SqlProvider) GetAllItems() ([]types.IItem, error) { + var dbItems []models.Item + if err := models.DB.Find(&dbItems).Error; err != nil { + return nil, err + } + var items []types.IItem + for _, item := range dbItems { + items = append(items, item) + } + return items, nil +} +func (prov SqlProvider) Link(user types.IUser, item types.IItem) error { + var dbUser models.User + if err := models.DB.First(&dbUser, user.GetId()).Error; err != nil { + return err + } + var dbItem models.Item + if err := models.DB.First(&dbItem, item.GetId()).Error; err != nil { + return err + } + dbUser.Items = append(dbUser.Items, dbItem) + dbItem.UserID = dbUser.ID + return models.DB.Save(&dbUser).Save(&dbItem).Error +} +func (prov SqlProvider) DeleteItem(item types.IItem) error { + return models.DB.Where("id = ?", item.GetId()).Delete(&models.Item{}).Error +} +func (prov SqlProvider) CreateUser(user types.IUser) (int, error) { + dbUser := models.User{} + err := models.DB.Create(&dbUser).Error + return int(dbUser.ID), err +} diff --git a/internal/models/Item.go b/internal/models/Item.go new file mode 100644 index 0000000..f8d5002 --- /dev/null +++ b/internal/models/Item.go @@ -0,0 +1,17 @@ +package models + +import "gorm.io/gorm" + +type Item struct { + gorm.Model + Message string + UserID uint +} + +func (item Item) GetId() int { + return int(item.ID) +} + +func (item Item) GetMessage() string { + return item.Message +} diff --git a/internal/models/User.go b/internal/models/User.go new file mode 100644 index 0000000..0fb3774 --- /dev/null +++ b/internal/models/User.go @@ -0,0 +1,17 @@ +package models + +import "gorm.io/gorm" + +type User struct { + gorm.Model + UserName string + Items []Item +} + +func (user User) GetId() int { + return int(user.ID) +} + +func (user User) GetUsername() string { + return user.UserName +} diff --git a/internal/models/setup.go b/internal/models/setup.go new file mode 100644 index 0000000..679e1d4 --- /dev/null +++ b/internal/models/setup.go @@ -0,0 +1,20 @@ +package models + +import ( + "gorm.io/driver/sqlite" + "gorm.io/gorm" +) + +var DB *gorm.DB + +func ConnectDatabase() error { + db, err := gorm.Open(sqlite.Open("dev.db"), &gorm.Config{}) + if err != nil { + return err + } + + db.AutoMigrate(&Item{}, &User{}) + + DB = db + return nil +} diff --git a/internal/server/routes.go b/internal/server/routes.go index 71f448e..57d95e1 100644 --- a/internal/server/routes.go +++ b/internal/server/routes.go @@ -3,6 +3,7 @@ package server import ( "dymatrix.de/jspahl/todo/internal/api" "dymatrix.de/jspahl/todo/internal/implementations" + "dymatrix.de/jspahl/todo/internal/models" "github.com/gin-gonic/gin" ) @@ -14,8 +15,10 @@ func registerRoutes(router *gin.Engine) { memoryProv := implementations.MemoryProvider{} api.RegisterRoutes(memory, memoryProv) } - // sql := router.Group("/sql") - // { - // api.RegisterRoutes(sql) - // } + sql := router.Group("/sql") + { + models.ConnectDatabase() + sqlProvider := implementations.SqlProvider{} + api.RegisterRoutes(sql, sqlProvider) + } } diff --git a/internal/server/server.go b/internal/server/server.go index 44d2bd0..64ad263 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -2,6 +2,7 @@ package server import ( "fmt" + "log" "net/http" "dymatrix.de/jspahl/todo/internal/config" @@ -27,6 +28,8 @@ func ListenAndServe() error { Handler: httpRouter, Addr: fmt.Sprintf("%s:%d", c.Listen.Host, c.Listen.Port), } + log.Printf("Starting web server at %s", httpServer.Addr) + err = httpServer.ListenAndServe() } return err } diff --git a/internal/types/IPersistentProvider.go b/internal/types/IPersistentProvider.go index 652b3ef..62f5743 100644 --- a/internal/types/IPersistentProvider.go +++ b/internal/types/IPersistentProvider.go @@ -8,5 +8,5 @@ type IPersitenceProvider interface { GetAllItems() ([]IItem, error) Link(user IUser, item IItem) error DeleteItem(item IItem) error - CreateUser(user IUser) error + CreateUser(user IUser) (int, error) } diff --git a/internal/types/IUser.go b/internal/types/IUser.go index e16e914..6c0b80a 100644 --- a/internal/types/IUser.go +++ b/internal/types/IUser.go @@ -2,4 +2,5 @@ package types type IUser interface { GetId() int + GetUsername() string }