diff --git a/articles/models.go b/articles/models.go index f5a0ec1..6271eba 100644 --- a/articles/models.go +++ b/articles/models.go @@ -1,11 +1,13 @@ package articles import ( - _ "fmt" - "github.com/jinzhu/gorm" - "github.com/wangzitian0/golang-gin-starter-kit/common" - "github.com/wangzitian0/golang-gin-starter-kit/users" + "fmt" + "golang-gin-realworld-example-app/common" + "golang-gin-realworld-example-app/users" "strconv" + "time" + + "github.com/jinzhu/gorm" ) type ArticleModel struct { @@ -44,11 +46,22 @@ type TagModel struct { type CommentModel struct { gorm.Model - Article ArticleModel - ArticleID uint - Author ArticleUserModel - AuthorID uint - Body string `gorm:"size:2048"` + Article ArticleModel + ArticleID uint + Author ArticleUserModel + CommentVote []CommentModelVote `gorm:"foreignkey:CommentID"` + AuthorID uint + Body string `gorm:"size:2048"` +} + +type CommentModelVote struct { + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt *time.Time + UserID uint `gorm:"primary_key;auto_increment:false"` + CommentID uint `gorm:"primary_key;auto_increment:false"` + UpVote bool + DownVote bool } func GetArticleUserModel(userModel users.UserModel) ArticleUserModel { @@ -267,3 +280,45 @@ func DeleteCommentModel(condition interface{}) error { err := db.Where(condition).Delete(CommentModel{}).Error return err } + +func GetCommentVote(vote CommentVoteValidator, userId uint) (CommentModelVote, error) { + db := common.GetDB() + var commentVote CommentModelVote + voteQuery := CommentModelVote{ + UserID: userId, + CommentID: vote.CommentID, + } + err := db.Where(&voteQuery).First(&commentVote).Error + return commentVote, err +} + +func CreateCommentVote(vote CommentVoteValidator, userId uint) (CommentModelVote, error) { + db := common.GetDB() + commentVote := CommentModelVote{ + CommentID: vote.CommentID, + UserID: userId, + UpVote: vote.UpVote, + DownVote: vote.DownVote, + } + err := db.Create(&commentVote).Error + fmt.Printf("\n\nthis is in CreateCommentVote: %+v\n\n", commentVote) + return commentVote, err +} + +func DeleteCommentVote(commentVote CommentModelVote) error { + db := common.GetDB() + err := db.Unscoped().Delete(&commentVote).Error + return err +} + +func UpdateCommentVote(vote CommentVoteValidator, userId uint) (CommentModelVote, error) { + db := common.GetDB() + voteModel, err := GetCommentVote(vote, userId) + if err != nil { + return voteModel, err + } + voteModel.UpVote = vote.UpVote + voteModel.DownVote = vote.DownVote + err2 := db.Save(&voteModel).Error + return voteModel, err2 +} diff --git a/articles/routers.go b/articles/routers.go index 820ed4c..a0c05f9 100644 --- a/articles/routers.go +++ b/articles/routers.go @@ -2,11 +2,13 @@ package articles import ( "errors" - "github.com/wangzitian0/golang-gin-starter-kit/common" - "github.com/wangzitian0/golang-gin-starter-kit/users" - "gopkg.in/gin-gonic/gin.v1" + "fmt" + "golang-gin-realworld-example-app/common" + "golang-gin-realworld-example-app/users" "net/http" "strconv" + + "github.com/gin-gonic/gin" ) func ArticlesRegister(router *gin.RouterGroup) { @@ -17,8 +19,74 @@ func ArticlesRegister(router *gin.RouterGroup) { router.DELETE("/:slug/favorite", ArticleUnfavorite) router.POST("/:slug/comments", ArticleCommentCreate) router.DELETE("/:slug/comments/:id", ArticleCommentDelete) + router.POST("/:slug/comments/:id/vote", ArticleCommentVotePost) + router.DELETE("/:slug/comments/:id/vote", ArticleCommentVoteDelete) + router.PUT("/:slug/comments/:id/vote", ArticleCommentVoteUpdate) +} + +func ArticleCommentVotePost(c *gin.Context) { + commentVoteValidator := CommentVoteValidator{} + if err := commentVoteValidator.Bind(c); err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + userId := c.MustGet("my_user_id").(uint) + vote, err := CreateCommentVote(commentVoteValidator, userId) + if err != nil { + c.JSON(http.StatusConflict, gin.H{ + "error": err.Error(), + }) + return + } + serial := VoteSerializer{vote: vote} + c.JSON(http.StatusCreated, gin.H{ + "vote": serial.Response(), + }) +} +func ArticleCommentVoteUpdate(c *gin.Context) { + commentVoteValidator := CommentVoteValidator{} + if err := commentVoteValidator.Bind(c); err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + userId := c.MustGet("my_user_id").(uint) + vote, err := UpdateCommentVote(commentVoteValidator, userId) + if err != nil { + c.JSON(http.StatusConflict, gin.H{ + "error": err.Error(), + }) + return + } + serial := VoteSerializer{vote: vote} + c.JSON(http.StatusOK, gin.H{ + "vote": serial.Response(), + }) } +func ArticleCommentVoteDelete(c *gin.Context) { + commentVoteValidator := CommentVoteValidator{} + if err := commentVoteValidator.BindCommentId(c); err != nil { + c.JSON(http.StatusBadRequest, err.Error()) + return + } + userId := c.MustGet("my_user_id").(uint) + vote, err := GetCommentVote(commentVoteValidator, userId) + if err != nil { + c.JSON(http.StatusNotFound, gin.H{ + "error": err.Error(), + }) + return + } + if err := DeleteCommentVote(vote); err != nil { + c.JSON(http.StatusForbidden, gin.H{ + "error": err.Error(), + }) + return + } + c.JSON(http.StatusOK, gin.H{ + "success": "comment got deleted", + }) +} func ArticlesAnonymousRegister(router *gin.RouterGroup) { router.GET("/", ArticleList) router.GET("/:slug", ArticleRetrieve) @@ -35,6 +103,7 @@ func ArticleCreate(c *gin.Context) { c.JSON(http.StatusUnprocessableEntity, common.NewValidatorError(err)) return } + fmt.Printf("ArticleModelValidator: %+v\n", articleModelValidator) //fmt.Println(articleModelValidator.articleModel.Author.UserModel) if err := SaveOne(&articleModelValidator.articleModel); err != nil { diff --git a/articles/serializers.go b/articles/serializers.go index 0a0d4c4..5a38635 100644 --- a/articles/serializers.go +++ b/articles/serializers.go @@ -1,9 +1,10 @@ package articles import ( + "golang-gin-realworld-example-app/users" + + "github.com/gin-gonic/gin" "github.com/gosimple/slug" - "github.com/wangzitian0/golang-gin-starter-kit/users" - "gopkg.in/gin-gonic/gin.v1" ) type TagSerializer struct { @@ -134,3 +135,25 @@ func (s *CommentsSerializer) Response() []CommentResponse { } return response } + +type VoteSerializer struct { + vote CommentModelVote +} + +type VoteResponse struct { + UserID uint `json:"user_id"` + CommentID uint `json:"comment_id"` + UpVote bool `json:"up_vote"` + DownVote bool `json:"down_vote"` +} + +func (self VoteSerializer) Response() VoteResponse { + voteModel := self.vote + voteResponse := VoteResponse{ + UserID: voteModel.UserID, + CommentID: voteModel.CommentID, + UpVote: voteModel.UpVote, + DownVote: voteModel.DownVote, + } + return voteResponse +} diff --git a/articles/validators.go b/articles/validators.go index 33082c5..b9fed5a 100644 --- a/articles/validators.go +++ b/articles/validators.go @@ -1,15 +1,17 @@ package articles import ( + "fmt" + "golang-gin-realworld-example-app/common" + "golang-gin-realworld-example-app/users" + + "github.com/gin-gonic/gin" "github.com/gosimple/slug" - "github.com/wangzitian0/golang-gin-starter-kit/common" - "github.com/wangzitian0/golang-gin-starter-kit/users" - "gopkg.in/gin-gonic/gin.v1" ) type ArticleModelValidator struct { Article struct { - Title string `form:"title" json:"title" binding:"exists,min=4"` + Title string `form:"title" json:"title" binding:"required"` Description string `form:"description" json:"description" binding:"max=2048"` Body string `form:"body" json:"body" binding:"max=2048"` Tags []string `form:"tagList" json:"tagList"` @@ -17,6 +19,20 @@ type ArticleModelValidator struct { articleModel ArticleModel `json:"-"` } +type CommentVoteValidator struct { + CommentID uint `uri:"id" binding:"required"` + UpVote bool `json:"up_vote"` + DownVote bool `json:"down_vote"` +} + +type CommentVoteError struct { + err string +} + +func (e CommentVoteError) Error() string { + return e.err +} + func NewArticleModelValidator() ArticleModelValidator { return ArticleModelValidator{} } @@ -70,3 +86,29 @@ func (s *CommentModelValidator) Bind(c *gin.Context) error { s.commentModel.Author = GetArticleUserModel(myUserModel) return nil } + +func (s *CommentVoteValidator) Bind(c *gin.Context) error { + // commentID := c.Param("id")(int) + // s.CommentID = commentID + if err := c.ShouldBindUri(s); err != nil { + return err + } + err := common.Bind(c, s) + if err != nil { + return err + } + fmt.Printf("\n\n In Bind: %+v \n\n", s) + if (s.DownVote && s.UpVote) || !(s.UpVote || s.DownVote) { + err := CommentVoteError{err: "Either one of the UpVote or DownVote can be true not both."} + return err + } + return nil +} + +func (s *CommentVoteValidator) BindCommentId(c *gin.Context) error { + if err := c.ShouldBindUri(s); err != nil { + return err + } + fmt.Printf("\n\n In Bind: %+v \n\n", s) + return nil +} diff --git a/common/database.go b/common/database.go index 57aa3af..8b37068 100644 --- a/common/database.go +++ b/common/database.go @@ -2,9 +2,12 @@ package common import ( "fmt" + + "os" + "github.com/jinzhu/gorm" + _ "github.com/jinzhu/gorm/dialects/postgres" _ "github.com/jinzhu/gorm/dialects/sqlite" - "os" ) type Database struct { @@ -15,13 +18,14 @@ var DB *gorm.DB // Opening a database and save the reference to `Database` struct. func Init() *gorm.DB { - db, err := gorm.Open("sqlite3", "./../gorm.db") + db, err := gorm.Open("postgres", "host=localhost port=5432 user=postgres dbname=realworld password=postgres") if err != nil { fmt.Println("db err: ", err) } db.DB().SetMaxIdleConns(10) - //db.LogMode(true) + db.LogMode(true) DB = db + fmt.Printf("db is: %+v\n", *DB) return DB } diff --git a/common/unit_test.go b/common/unit_test.go index 71b4997..7c30168 100644 --- a/common/unit_test.go +++ b/common/unit_test.go @@ -3,12 +3,15 @@ package common import ( "bytes" "errors" - "github.com/stretchr/testify/assert" - "gopkg.in/gin-gonic/gin.v1" + "net/http" "net/http/httptest" "os" "testing" + + "github.com/stretchr/testify/assert" + // "gopkg.in/gin-gonic/gin.v1" + "github.com/gin-gonic/gin" ) func TestConnectingDatabase(t *testing.T) { @@ -19,7 +22,7 @@ func TestConnectingDatabase(t *testing.T) { asserts.NoError(err, "Db should exist") asserts.NoError(db.DB().Ping(), "Db should be able to ping") - // Test get a connecting from connection pools + // Test get a connection from connection pools connection := GetDB() asserts.NoError(connection.DB().Ping(), "Db should be able to ping") db.Close() @@ -83,8 +86,8 @@ func TestNewValidatorError(t *testing.T) { asserts := assert.New(t) type Login struct { - Username string `form:"username" json:"username" binding:"exists,alphanum,min=4,max=255"` - Password string `form:"password" json:"password" binding:"exists,min=8,max=255"` + Username string `form:"username" json:"username" binding:"required,alphanum,min=4,max=255"` + Password string `form:"password" json:"password" binding:"required,min=8,max=255"` } var requestTests = []struct { diff --git a/common/utils.go b/common/utils.go index 0c8bfa2..9eca5da 100644 --- a/common/utils.go +++ b/common/utils.go @@ -6,11 +6,12 @@ import ( "math/rand" "time" - "github.com/dgrijalva/jwt-go" + jwt "github.com/dgrijalva/jwt-go" "gopkg.in/go-playground/validator.v8" "github.com/gin-gonic/gin/binding" - "gopkg.in/gin-gonic/gin.v1" + // "gopkg.in/gin-gonic/gin.v1" + "github.com/gin-gonic/gin" ) var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..59344fd --- /dev/null +++ b/go.mod @@ -0,0 +1,13 @@ +module golang-gin-realworld-example-app + +go 1.14 + +require ( + github.com/dgrijalva/jwt-go v3.2.0+incompatible + github.com/gin-gonic/gin v1.6.3 + github.com/gosimple/slug v1.9.0 + github.com/jinzhu/gorm v1.9.14 + github.com/mattn/go-sqlite3 v1.14.0 // indirect + golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd + gopkg.in/go-playground/validator.v8 v8.18.2 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..6ece12b --- /dev/null +++ b/go.sum @@ -0,0 +1,80 @@ +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/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/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/dgrijalva/jwt-go v1.0.2 h1:KPldsxuKGsS2FPWsNeg9ZO18aCrGKujPoWXn2yo+KQM= +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/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= +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.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-playground/validator/v10 v10.3.0 h1:nZU+7q+yJoFmwvNgv/LnPUkwPal62+b2xXj0AU1Es7o= +github.com/go-playground/validator/v10 v10.3.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +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/gosimple/slug v1.9.0 h1:r5vDcYrFz9BmfIAMC829un9hq7hKM4cHUrsv36LbEqs= +github.com/gosimple/slug v1.9.0/go.mod h1:AMZ+sOVe65uByN3kgEyf9WEBKBCSS+dJjMX9x4vDJbg= +github.com/jinzhu/gorm v1.9.14 h1:Kg3ShyTPcM6nzVo148fRrcMO6MNKuqtOUwnzqMgVniM= +github.com/jinzhu/gorm v1.9.14/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/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +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/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-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.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA= +github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be h1:ta7tUOvsPHVHGom5hKW5VXNc2xZIkfCKP8iaqOyYtUQ= +github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be/go.mod h1:MIDFMn7db1kT65GmV94GzpX9Qdi7N/pQlwb+AN8wh+Q= +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/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +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= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= +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 h1:GGJVjV8waZKRHrgwvtH66z9ZGVurTD1MT0n1Bb+q4aM= +golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +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-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= +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= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ= +gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= +gopkg.in/go-playground/validator.v9 v9.31.0 h1:bmXmP2RSNtFES+bn4uYuHT7iJFJv7Vj+an+ZQdDaD1M= +gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +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= diff --git a/golang-gin-realworld-example-app b/golang-gin-realworld-example-app new file mode 100755 index 0000000..44b1336 Binary files /dev/null and b/golang-gin-realworld-example-app differ diff --git a/hello.go b/hello.go index b8eb678..7afb642 100644 --- a/hello.go +++ b/hello.go @@ -2,28 +2,35 @@ package main import ( "fmt" - - "gopkg.in/gin-gonic/gin.v1" + "golang-gin-realworld-example-app/articles" + "golang-gin-realworld-example-app/common" + "golang-gin-realworld-example-app/users" "github.com/jinzhu/gorm" - "github.com/wangzitian0/golang-gin-starter-kit/articles" - "github.com/wangzitian0/golang-gin-starter-kit/common" - "github.com/wangzitian0/golang-gin-starter-kit/users" + + // gin "gopkg.in/gin-gonic/gin.v1" + "github.com/gin-gonic/gin" + // "github.com/wangzitian0/golang-gin-starter-kit/articles" + // "github.com/wangzitian0/golang-gin-starter-kit/common" + // "github.com/wangzitian0/golang-gin-starter-kit/users" ) -func Migrate(db *gorm.DB) { +func migrate(db *gorm.DB) { + // db.DropTable(&articles.ArticleModel{}, &articles.TagModel{}, &articles.FavoriteModel{}, &articles.ArticleUserModel{}, &articles.CommentModel{}, &users.UserModel{}, &users.FollowModel{}) users.AutoMigrate() db.AutoMigrate(&articles.ArticleModel{}) db.AutoMigrate(&articles.TagModel{}) db.AutoMigrate(&articles.FavoriteModel{}) db.AutoMigrate(&articles.ArticleUserModel{}) db.AutoMigrate(&articles.CommentModel{}) + db.AutoMigrate(&articles.CommentModelVote{}) + } func main() { db := common.Init() - Migrate(db) + migrate(db) defer db.Close() r := gin.Default() diff --git a/users/middlewares.go b/users/middlewares.go index ffeda29..1c87db4 100644 --- a/users/middlewares.go +++ b/users/middlewares.go @@ -1,12 +1,15 @@ package users import ( + "golang-gin-realworld-example-app/common" + "github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go/request" - "github.com/wangzitian0/golang-gin-starter-kit/common" - "gopkg.in/gin-gonic/gin.v1" + "net/http" "strings" + + "github.com/gin-gonic/gin" ) // Strips 'TOKEN ' prefix from token string @@ -60,7 +63,6 @@ func AuthMiddleware(auto401 bool) gin.HandlerFunc { } if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { my_user_id := uint(claims["id"].(float64)) - //fmt.Println(my_user_id,claims["id"]) UpdateContextUserModel(c, my_user_id) } } diff --git a/users/models.go b/users/models.go index f2406fb..ed68127 100644 --- a/users/models.go +++ b/users/models.go @@ -2,8 +2,9 @@ package users import ( "errors" + "golang-gin-realworld-example-app/common" + "github.com/jinzhu/gorm" - "github.com/wangzitian0/golang-gin-starter-kit/common" "golang.org/x/crypto/bcrypt" ) @@ -19,6 +20,7 @@ type UserModel struct { Bio string `gorm:"column:bio;size:1024"` Image *string `gorm:"column:image"` PasswordHash string `gorm:"column:password;not null"` + // Vote []articles.CommentModelVote `gorm:"foreignkey:UserID"` } // A hack way to save ManyToMany relationship, diff --git a/users/routers.go b/users/routers.go index aa661c7..83a491a 100644 --- a/users/routers.go +++ b/users/routers.go @@ -2,9 +2,10 @@ package users import ( "errors" - "github.com/wangzitian0/golang-gin-starter-kit/common" - "gopkg.in/gin-gonic/gin.v1" + "golang-gin-realworld-example-app/common" "net/http" + + "github.com/gin-gonic/gin" ) func UsersRegister(router *gin.RouterGroup) { diff --git a/users/serializers.go b/users/serializers.go index c7e23cd..0b9fa88 100644 --- a/users/serializers.go +++ b/users/serializers.go @@ -1,9 +1,9 @@ package users import ( - "gopkg.in/gin-gonic/gin.v1" + "golang-gin-realworld-example-app/common" - "github.com/wangzitian0/golang-gin-starter-kit/common" + "github.com/gin-gonic/gin" ) type ProfileSerializer struct { diff --git a/users/unit_test.go b/users/unit_test.go index 32f9d12..f20eed4 100644 --- a/users/unit_test.go +++ b/users/unit_test.go @@ -1,18 +1,21 @@ package users import ( - "github.com/stretchr/testify/assert" "testing" + "github.com/stretchr/testify/assert" + "bytes" "fmt" - "github.com/jinzhu/gorm" - "github.com/wangzitian0/golang-gin-starter-kit/common" - "gopkg.in/gin-gonic/gin.v1" "net/http" "net/http/httptest" "os" _ "regexp" + + "github.com/jinzhu/gorm" + "github.com/wangzitian0/golang-gin-starter-kit/common" + + "github.com/gin-gonic/gin" ) var image_url = "https://golang.org/doc/gopher/frontpage.png" diff --git a/users/validators.go b/users/validators.go index 8933c99..3d104e8 100644 --- a/users/validators.go +++ b/users/validators.go @@ -1,8 +1,9 @@ package users import ( - "github.com/wangzitian0/golang-gin-starter-kit/common" - "gopkg.in/gin-gonic/gin.v1" + "golang-gin-realworld-example-app/common" + + "github.com/gin-gonic/gin" ) // *ModelValidator containing two parts: @@ -11,9 +12,9 @@ import ( // Then, you can just call model.save() after the data is ready in DataModel. type UserModelValidator struct { User struct { - Username string `form:"username" json:"username" binding:"exists,alphanum,min=4,max=255"` - Email string `form:"email" json:"email" binding:"exists,email"` - Password string `form:"password" json:"password" binding:"exists,min=8,max=255"` + Username string `form:"username" json:"username" binding:"required,alphanum,min=4,max=255"` + Email string `form:"email" json:"email" binding:"required,email"` + Password string `form:"password" json:"password" binding:"required,min=4,max=255"` Bio string `form:"bio" json:"bio" binding:"max=1024"` Image string `form:"image" json:"image" binding:"omitempty,url"` } `json:"user"` @@ -63,8 +64,8 @@ func NewUserModelValidatorFillWith(userModel UserModel) UserModelValidator { type LoginValidator struct { User struct { - Email string `form:"email" json:"email" binding:"exists,email"` - Password string `form:"password"json:"password" binding:"exists,min=8,max=255"` + Email string `form:"email" json:"email" binding:"required,email"` + Password string `form:"password"json:"password" binding:"required,min=8,max=255"` } `json:"user"` userModel UserModel `json:"-"` } diff --git a/vendor/vendor.json b/vendor/vendor.json deleted file mode 100644 index ab95daa..0000000 --- a/vendor/vendor.json +++ /dev/null @@ -1,211 +0,0 @@ -{ - "comment": "", - "ignore": "test", - "package": [ - { - "checksumSHA1": "8tLSbloQ6bpVBB/CcPbP9sLW45Y=", - "path": "github.com/Pallinder/go-randomdata", - "revision": "8c3362a5e6781e0d1046f1267b3c1f19b2cde334", - "revisionTime": "2017-04-10T16:13:40Z" - }, - { - "checksumSHA1": "mrz/kicZiUaHxkyfvC/DyQcr8Do=", - "path": "github.com/davecgh/go-spew/spew", - "revision": "adab96458c51a58dc1783b3335dcce5461522e75", - "revisionTime": "2017-07-11T18:34:51Z" - }, - { - "checksumSHA1": "GXOurDGgsLmJs0wounpdWZZRSGw=", - "path": "github.com/dgrijalva/jwt-go", - "revision": "a539ee1a749a2b895533f979515ac7e6e0f5b650", - "revisionTime": "2017-06-08T00:51:49Z" - }, - { - "checksumSHA1": "9Xy4JjEsr+Mu4v4eE9KA0TItfQU=", - "path": "github.com/dgrijalva/jwt-go/request", - "revision": "a539ee1a749a2b895533f979515ac7e6e0f5b650", - "revisionTime": "2017-06-08T00:51:49Z" - }, - { - "checksumSHA1": "QeKwBtN2df+j+4stw3bQJ6yO4EY=", - "path": "github.com/gin-contrib/sse", - "revision": "22d885f9ecc78bf4ee5d72b937e4bbcdc58e8cae", - "revisionTime": "2017-01-09T09:34:21Z" - }, - { - "checksumSHA1": "AXApcxmpMmki0JwVDzn3FMd3CTw=", - "path": "github.com/gin-gonic/contrib/jwt", - "revision": "d4fc5a96cc0d29cb0e862bb1312dd6f4fedfcaee", - "revisionTime": "2017-05-29T06:23:10Z" - }, - { - "checksumSHA1": "g1ULoqYPmgLWhNTimHlM5usWZ1s=", - "path": "github.com/gin-gonic/gin", - "revision": "93b3a0d7ec95c33dc327397ab1756c36853328ee", - "revisionTime": "2017-07-16T03:42:08Z" - }, - { - "checksumSHA1": "A09l4+1MIuaXhh3Nn6aoOm+rr3Q=", - "path": "github.com/gin-gonic/gin/binding", - "revision": "aa6d2d29f8ac39c365aa5b72fdec01029b0d5264", - "revisionTime": "2017-07-11T15:28:08Z" - }, - { - "checksumSHA1": "8UlyJTegyrXbE8UErbf2lH7X4AM=", - "path": "github.com/gin-gonic/gin/render", - "revision": "aa6d2d29f8ac39c365aa5b72fdec01029b0d5264", - "revisionTime": "2017-07-11T15:28:08Z" - }, - { - "checksumSHA1": "pI0js2qnSKXOzUq9AoA5CJDJNRw=", - "path": "github.com/go-playground/locales", - "revision": "1e5f1161c6416a5ff48840eb8724a394e48cc534", - "revisionTime": "2017-03-27T19:14:50Z" - }, - { - "checksumSHA1": "YWIa2z/i81ttb1Db9fm95XnIgwI=", - "path": "github.com/go-playground/locales/currency", - "revision": "1e5f1161c6416a5ff48840eb8724a394e48cc534", - "revisionTime": "2017-03-27T19:14:50Z" - }, - { - "checksumSHA1": "oi7+/A/rpTHDn9+8LOqqDjrF29s=", - "path": "github.com/go-playground/locales/zh_Hans_CN", - "revision": "1e5f1161c6416a5ff48840eb8724a394e48cc534", - "revisionTime": "2017-03-27T19:14:50Z" - }, - { - "checksumSHA1": "7QcjNTtW0Rc/5BPw1MPaQ6YNjso=", - "path": "github.com/go-playground/universal-translator", - "revision": "71201497bace774495daed26a3874fd339e0b538", - "revisionTime": "2017-03-27T19:17:03Z" - }, - { - "checksumSHA1": "yqF125xVSkmfLpIVGrLlfE05IUk=", - "path": "github.com/golang/protobuf/proto", - "revision": "0a4f71a498b7c4812f64969510bcb4eca251e33a", - "revisionTime": "2017-07-12T04:22:13Z" - }, - { - "checksumSHA1": "HZ/dfTQbxIkJESoFdgzlXRfJSD8=", - "path": "github.com/gosimple/slug", - "revision": "e756f2ec7e1e59e2ef20938fac5e677842641777", - "revisionTime": "2017-07-24T20:16:30Z" - }, - { - "checksumSHA1": "IqQmIPZbwgzbZD4k7YX6Rj230pY=", - "path": "github.com/jinzhu/gorm", - "revision": "2a1463811ee1dc85d168fd639a2d4251d030e6e5", - "revisionTime": "2017-07-03T13:49:54Z" - }, - { - "checksumSHA1": "4VZ1gLZHMumRjV3fclS1aX8S1aQ=", - "path": "github.com/jinzhu/gorm/dialects/sqlite", - "revision": "2a1463811ee1dc85d168fd639a2d4251d030e6e5", - "revisionTime": "2017-07-03T13:49:54Z" - }, - { - "checksumSHA1": "VIp1lZm6joWhlNdwhady8u//qRw=", - "path": "github.com/jinzhu/inflection", - "revision": "1c35d901db3da928c72a72d8458480cc9ade058f", - "revisionTime": "2017-01-02T12:52:26Z" - }, - { - "checksumSHA1": "nQYiBET0TB7M17zUh2p1tsgCH6U=", - "path": "github.com/json-iterator/go", - "revision": "b9dc3ebda73c459dbed33da2f46f95b3c47843c6", - "revisionTime": "2017-07-11T23:04:30Z" - }, - { - "checksumSHA1": "U6lX43KDDlNOn+Z0Yyww+ZzHfFo=", - "path": "github.com/mattn/go-isatty", - "revision": "fc9e8d8ef48496124e79ae0df75490096eccf6fe", - "revisionTime": "2017-03-22T23:44:13Z" - }, - { - "checksumSHA1": "CmknXrMVBRJrx4LsIA9jEOmsLQQ=", - "path": "github.com/mattn/go-sqlite3", - "revision": "47fc4e5e9153645da45af6a86a5bce95e63a0f9e", - "revisionTime": "2017-07-10T14:00:56Z" - }, - { - "checksumSHA1": "LuFv4/jlrmFNnDb/5SCSEPAM9vU=", - "path": "github.com/pmezard/go-difflib/difflib", - "revision": "792786c7400a136282c1664665ae0a8db921c6c2", - "revisionTime": "2016-01-10T10:55:54Z" - }, - { - "checksumSHA1": "pvg8L4xN+zO9HLJislpVeHPPLjM=", - "path": "github.com/rainycape/unidecode", - "revision": "cb7f23ec59bec0d61b19c56cd88cee3d0cc1870c", - "revisionTime": "2015-09-07T02:38:54Z" - }, - { - "checksumSHA1": "K0crHygPTP42i1nLKWphSlvOQJw=", - "path": "github.com/stretchr/objx", - "revision": "1a9d0bb9f541897e62256577b352fdbc1fb4fd94", - "revisionTime": "2015-09-28T12:21:52Z" - }, - { - "checksumSHA1": "J+ppEq6nYMKxhB9+c+MD1x9UwSc=", - "path": "github.com/stretchr/testify/assert", - "revision": "05e8a0eda380579888eb53c394909df027f06991", - "revisionTime": "2017-07-13T16:51:06Z" - }, - { - "checksumSHA1": "fg3TzS9/QK3wZbzei3Z6O8XPLHg=", - "path": "github.com/stretchr/testify/http", - "revision": "05e8a0eda380579888eb53c394909df027f06991", - "revisionTime": "2017-07-13T16:51:06Z" - }, - { - "checksumSHA1": "o+jsS/rxceTym4M3reSPfrPxaio=", - "path": "github.com/stretchr/testify/mock", - "revision": "05e8a0eda380579888eb53c394909df027f06991", - "revisionTime": "2017-07-13T16:51:06Z" - }, - { - "checksumSHA1": "9Zw986fuQM/hCoVd8vmHoSM+8sU=", - "path": "github.com/ugorji/go/codec", - "revision": "5efa3251c7f7d05e5d9704a69a984ec9f1386a40", - "revisionTime": "2017-06-20T10:48:52Z" - }, - { - "checksumSHA1": "Y+HGqEkYM15ir+J93MEaHdyFy0c=", - "path": "golang.org/x/net/context", - "revision": "f01ecb60fe3835d80d9a0b7b2bf24b228c89260e", - "revisionTime": "2017-07-11T11:58:19Z" - }, - { - "checksumSHA1": "+lIUrdF5DkSZaOaNSgyiwQ9PfmE=", - "path": "golang.org/x/sys/unix", - "revision": "abf9c25f54453410d0c6668e519582a9e1115027", - "revisionTime": "2017-07-10T15:57:01Z" - }, - { - "checksumSHA1": "lqXx4OhLBZFV5p4+I0OvpNabF4A=", - "path": "gopkg.in/gin-gonic/gin.v1", - "revision": "d459835d2b077e44f7c9b453505ee29881d5d12d", - "revisionTime": "2017-07-02T09:28:26Z" - }, - { - "checksumSHA1": "39V1idWER42Lmcmg2Uy40wMzOlo=", - "path": "gopkg.in/go-playground/validator.v8", - "revision": "5f57d2222ad794d0dffb07e664ea05e2ee07d60c", - "revisionTime": "2016-07-18T13:41:25Z" - }, - { - "checksumSHA1": "4GRl0rg8N/CYMv8aadrBXVe0JSo=", - "path": "gopkg.in/stretchr/testify.v1", - "revision": "69483b4bd14f5845b5a1e55bca19e954e827f1d0", - "revisionTime": "2016-09-25T01:54:16Z" - }, - { - "checksumSHA1": "MxQKqsbREjYp+nUw2xW0df6i34Y=", - "path": "gopkg.in/yaml.v2", - "revision": "1be3d31502d6eabc0dd7ce5b0daab022e14a5538", - "revisionTime": "2017-07-12T05:45:46Z" - } - ], - "rootPath": "github.com/wangzitian0/golang-gin-starter-kit" -}