package articles import ( "errors" "github.com/gin-gonic/gin" "github.com/gothinkster/golang-gin-realworld-example-app/common" "github.com/gothinkster/golang-gin-realworld-example-app/users" "gorm.io/gorm" "net/http" "strconv" ) func ArticlesRegister(router *gin.RouterGroup) { router.GET("/feed", ArticleFeed) router.POST("", ArticleCreate) router.POST("/", ArticleCreate) router.PUT("/:slug", ArticleUpdate) router.PUT("/:slug/", ArticleUpdate) router.DELETE("/:slug", ArticleDelete) router.POST("/:slug/favorite", ArticleFavorite) router.DELETE("/:slug/favorite", ArticleUnfavorite) router.POST("/:slug/comments", ArticleCommentCreate) router.DELETE("/:slug/comments/:id", ArticleCommentDelete) } func ArticlesAnonymousRegister(router *gin.RouterGroup) { router.GET("", ArticleList) router.GET("/", ArticleList) router.GET("/:slug", ArticleRetrieve) router.GET("/:slug/comments", ArticleCommentList) } func TagsAnonymousRegister(router *gin.RouterGroup) { router.GET("", TagList) router.GET("/", TagList) } func ArticleCreate(c *gin.Context) { articleModelValidator := NewArticleModelValidator() if err := articleModelValidator.Bind(c); err != nil { c.JSON(http.StatusUnprocessableEntity, common.NewValidatorError(err)) return } //fmt.Println(articleModelValidator.articleModel.Author.UserModel) if err := SaveOne(&articleModelValidator.articleModel); err != nil { c.JSON(http.StatusUnprocessableEntity, common.NewError("database", err)) return } serializer := ArticleSerializer{c, articleModelValidator.articleModel} c.JSON(http.StatusCreated, gin.H{"article": serializer.Response()}) } func ArticleList(c *gin.Context) { //condition := ArticleModel{} tag := c.Query("tag") author := c.Query("author") favorited := c.Query("favorited") limit := c.Query("limit") offset := c.Query("offset") articleModels, modelCount, err := FindManyArticle(tag, author, limit, offset, favorited) if err != nil { c.JSON(http.StatusNotFound, common.NewError("articles", errors.New("Invalid param"))) return } serializer := ArticlesSerializer{c, articleModels} c.JSON(http.StatusOK, gin.H{"articles": serializer.Response(), "articlesCount": modelCount}) } func ArticleFeed(c *gin.Context) { limit := c.Query("limit") offset := c.Query("offset") myUserModel := c.MustGet("my_user_model").(users.UserModel) if myUserModel.ID == 0 { c.AbortWithError(http.StatusUnauthorized, errors.New("{error : \"Require auth!\"}")) return } articleUserModel := GetArticleUserModel(myUserModel) articleModels, modelCount, err := articleUserModel.GetArticleFeed(limit, offset) if err != nil { c.JSON(http.StatusNotFound, common.NewError("articles", errors.New("Invalid param"))) return } serializer := ArticlesSerializer{c, articleModels} c.JSON(http.StatusOK, gin.H{"articles": serializer.Response(), "articlesCount": modelCount}) } func ArticleRetrieve(c *gin.Context) { slug := c.Param("slug") articleModel, err := FindOneArticle(&ArticleModel{Slug: slug}) if err != nil { c.JSON(http.StatusNotFound, common.NewError("articles", errors.New("Invalid slug"))) return } serializer := ArticleSerializer{c, articleModel} c.JSON(http.StatusOK, gin.H{"article": serializer.Response()}) } func ArticleUpdate(c *gin.Context) { slug := c.Param("slug") articleModel, err := FindOneArticle(&ArticleModel{Slug: slug}) if err != nil { c.JSON(http.StatusNotFound, common.NewError("articles", errors.New("Invalid slug"))) return } // Check if current user is the author myUserModel := c.MustGet("my_user_model").(users.UserModel) articleUserModel := GetArticleUserModel(myUserModel) if articleModel.AuthorID != articleUserModel.ID { c.JSON(http.StatusForbidden, common.NewError("article", errors.New("you are not the author"))) return } articleModelValidator := NewArticleModelValidatorFillWith(articleModel) if err := articleModelValidator.Bind(c); err != nil { c.JSON(http.StatusUnprocessableEntity, common.NewValidatorError(err)) return } articleModelValidator.articleModel.ID = articleModel.ID if err := articleModel.Update(articleModelValidator.articleModel); err != nil { c.JSON(http.StatusUnprocessableEntity, common.NewError("database", err)) return } serializer := ArticleSerializer{c, articleModel} c.JSON(http.StatusOK, gin.H{"article": serializer.Response()}) } func ArticleDelete(c *gin.Context) { slug := c.Param("slug") articleModel, err := FindOneArticle(&ArticleModel{Slug: slug}) if err == nil { // Article exists, check authorization myUserModel := c.MustGet("my_user_model").(users.UserModel) articleUserModel := GetArticleUserModel(myUserModel) if articleModel.AuthorID != articleUserModel.ID { c.JSON(http.StatusForbidden, common.NewError("article", errors.New("you are not the author"))) return } } // Delete regardless of existence (idempotent) if err := DeleteArticleModel(&ArticleModel{Slug: slug}); err != nil { c.JSON(http.StatusUnprocessableEntity, common.NewError("database", err)) return } c.JSON(http.StatusOK, gin.H{"article": "delete success"}) } func ArticleFavorite(c *gin.Context) { slug := c.Param("slug") articleModel, err := FindOneArticle(&ArticleModel{Slug: slug}) if err != nil { c.JSON(http.StatusNotFound, common.NewError("articles", errors.New("Invalid slug"))) return } myUserModel := c.MustGet("my_user_model").(users.UserModel) if err = articleModel.favoriteBy(GetArticleUserModel(myUserModel)); err != nil { c.JSON(http.StatusUnprocessableEntity, common.NewError("database", err)) return } serializer := ArticleSerializer{c, articleModel} c.JSON(http.StatusOK, gin.H{"article": serializer.Response()}) } func ArticleUnfavorite(c *gin.Context) { slug := c.Param("slug") articleModel, err := FindOneArticle(&ArticleModel{Slug: slug}) if err != nil { c.JSON(http.StatusNotFound, common.NewError("articles", errors.New("Invalid slug"))) return } myUserModel := c.MustGet("my_user_model").(users.UserModel) if err = articleModel.unFavoriteBy(GetArticleUserModel(myUserModel)); err != nil { c.JSON(http.StatusUnprocessableEntity, common.NewError("database", err)) return } serializer := ArticleSerializer{c, articleModel} c.JSON(http.StatusOK, gin.H{"article": serializer.Response()}) } func ArticleCommentCreate(c *gin.Context) { slug := c.Param("slug") articleModel, err := FindOneArticle(&ArticleModel{Slug: slug}) if err != nil { c.JSON(http.StatusNotFound, common.NewError("comment", errors.New("Invalid slug"))) return } commentModelValidator := NewCommentModelValidator() if err := commentModelValidator.Bind(c); err != nil { c.JSON(http.StatusUnprocessableEntity, common.NewValidatorError(err)) return } commentModelValidator.commentModel.Article = articleModel if err := SaveOne(&commentModelValidator.commentModel); err != nil { c.JSON(http.StatusUnprocessableEntity, common.NewError("database", err)) return } serializer := CommentSerializer{c, commentModelValidator.commentModel} c.JSON(http.StatusCreated, gin.H{"comment": serializer.Response()}) } func ArticleCommentDelete(c *gin.Context) { id64, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusNotFound, common.NewError("comment", errors.New("Invalid id"))) return } id := uint(id64) commentModel, err := FindOneComment(&CommentModel{Model: gorm.Model{ID: id}}) if err == nil { // Comment exists, check authorization myUserModel := c.MustGet("my_user_model").(users.UserModel) articleUserModel := GetArticleUserModel(myUserModel) if commentModel.AuthorID != articleUserModel.ID { c.JSON(http.StatusForbidden, common.NewError("comment", errors.New("you are not the author"))) return } } // Delete regardless of existence (idempotent) if err := DeleteCommentModel([]uint{id}); err != nil { c.JSON(http.StatusUnprocessableEntity, common.NewError("database", err)) return } c.JSON(http.StatusOK, gin.H{"comment": "delete success"}) } func ArticleCommentList(c *gin.Context) { slug := c.Param("slug") articleModel, err := FindOneArticle(&ArticleModel{Slug: slug}) if err != nil { c.JSON(http.StatusNotFound, common.NewError("comments", errors.New("Invalid slug"))) return } err = articleModel.getComments() if err != nil { c.JSON(http.StatusNotFound, common.NewError("comments", errors.New("Database error"))) return } serializer := CommentsSerializer{c, articleModel.Comments} c.JSON(http.StatusOK, gin.H{"comments": serializer.Response()}) } func TagList(c *gin.Context) { tagModels, err := getAllTags() if err != nil { c.JSON(http.StatusNotFound, common.NewError("articles", errors.New("Invalid param"))) return } serializer := TagsSerializer{c, tagModels} c.JSON(http.StatusOK, gin.H{"tags": serializer.Response()}) }