diff --git a/.github/workflows/deploy-backend-dev.yml b/.github/workflows/deploy-backend-dev.yml index 219c877b0..49c98bafe 100644 --- a/.github/workflows/deploy-backend-dev.yml +++ b/.github/workflows/deploy-backend-dev.yml @@ -28,7 +28,7 @@ jobs: - name: Build backend and copy zip to S3 run: | secret_value="${{ secrets.RECAPTCHA_CONFIG_JSON_BASE64 }}" - awk -v val="${secret_value}" '{gsub(/{{RECAPTCHA_CONFIG_JSON_BASE64}}/, val)} 1' utils/helper.go > temp.go && mv temp.go utils/helper.go + awk -v val="${secret_value}" '{gsub(/{{RECAPTCHA_CONFIG_JSON_BASE64}}/, val)} 1' utils/helper.go > updated_helper.go && mv updated_helper.go utils/helper.go apt-get update && apt-get install -y zip GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o main main.go zip canopas_serverless_dev_${{ github.sha }}.zip main diff --git a/.github/workflows/deploy-backend-prod.yml b/.github/workflows/deploy-backend-prod.yml index fd785130f..f41767adb 100644 --- a/.github/workflows/deploy-backend-prod.yml +++ b/.github/workflows/deploy-backend-prod.yml @@ -28,7 +28,7 @@ jobs: - name: Build backend and copy zip to S3 run: | secret_value="${{ secrets.RECAPTCHA_CONFIG_JSON_BASE64 }}" - awk -v val="${secret_value}" '{gsub(/{{RECAPTCHA_CONFIG_JSON_BASE64}}/, val)} 1' utils/helper.go > temp.go && mv temp.go utils/helper.go + awk -v val="${secret_value}" '{gsub(/{{RECAPTCHA_CONFIG_JSON_BASE64}}/, val)} 1' utils/helper.go > updated_helper.go && mv updated_helper.go utils/helper.go apt-get update && apt-get install -y zip GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o main main.go zip canopas_serverless_prod_${{ github.sha }}.zip main diff --git a/db/blog_sql.go b/db/blog_sql.go index 8d02082c0..8dbcff28f 100644 --- a/db/blog_sql.go +++ b/db/blog_sql.go @@ -12,7 +12,7 @@ import ( log "github.com/sirupsen/logrus" ) -func NewBlogSql() *sqlx.DB { +func BlogDBInstance() *sqlx.DB { log.Info("Initializing New Blog Postgres Instance") @@ -42,7 +42,7 @@ func NewBlogSql() *sqlx.DB { } sslmode := "require" - + if os.Getenv("DB_ENV") == "test" { sslmode = "disable" } diff --git a/go.mod b/go.mod index 9d7980b55..b02938fce 100644 --- a/go.mod +++ b/go.mod @@ -71,11 +71,13 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.0.9 // indirect + github.com/samber/lo v1.39.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect go.opencensus.io v0.24.0 // indirect golang.org/x/arch v0.4.0 // indirect golang.org/x/crypto v0.14.0 // indirect + golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/oauth2 v0.11.0 // indirect golang.org/x/sync v0.3.0 // indirect diff --git a/go.sum b/go.sum index 9ac6a0caa..60c6baf42 100644 --- a/go.sum +++ b/go.sum @@ -168,6 +168,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA= +github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -206,6 +208,8 @@ golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM= +golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= diff --git a/infrastructure/backend.yml b/infrastructure/backend.yml index fe64b9c08..3584a4f60 100644 --- a/infrastructure/backend.yml +++ b/infrastructure/backend.yml @@ -48,7 +48,7 @@ Parameters: Description: Postgres database name. BlogDbName: Type: String - Description: Postgres blog database name. + Description: Postgres database name for blogs. RecaptchaSiteKey: Type: String Description: Use to verify recpatcha token. diff --git a/main.go b/main.go index 5dcca0a43..90184c818 100644 --- a/main.go +++ b/main.go @@ -94,12 +94,12 @@ func setupRouter() *gin.Engine { router.GET("/api/perksimages", lifePerksImagesRepo.PerksImages) - blogSqlDb := db.NewBlogSql() + blogSqlDb := db.BlogDBInstance() postRepo := post.New(blogSqlDb) router.GET("/api/posts", postRepo.Get) - router.GET("/api/posts/:slug", postRepo.GetById) + router.GET("/api/posts/:slug", postRepo.Show) router.GET("/api/posts/tags/:slug", postRepo.GetPostsByTag) diff --git a/post/author.go b/post/author.go index 1e51b69fc..e2605b732 100644 --- a/post/author.go +++ b/post/author.go @@ -2,8 +2,10 @@ package post import ( "encoding/json" + "fmt" "net/http" "strconv" + "strings" "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" @@ -11,6 +13,11 @@ import ( func (repository *Repository) GetPostsByAuthor(c *gin.Context) { username := c.Param("username") + if username == "" { + log.Warn("Username not found in query parameter") + c.AbortWithStatus(http.StatusBadRequest) + return + } skip, err := strconv.Atoi(c.DefaultQuery("skip", "0")) if err != nil { @@ -65,59 +72,119 @@ func (repository *Repository) GetPostsByAuthor(c *gin.Context) { post.Tag = "" post.Tags = tags - err = repository.Db.Get(&post.Image, `SELECT f.id, f.name, f.alternative_text, f.caption, f.width, f.height, f.formats as format, f.hash, f.ext, f.mime, - f.size, f.url, f.preview_url, f.provider, f.provider_metadata, f.folder_path, f.created_at, f.updated_at - FROM files f - JOIN files_related_morphs frm ON frm.related_id = $1 AND frm.related_type = 'api::post.post' AND frm.file_id = f.id`, post.Id) - if err != nil { - log.Error("Error while fetching post images: ", err) - c.AbortWithStatus(http.StatusInternalServerError) - return - } + new_posts = append(new_posts, post) + } - var postFormats Formats + new_posts = repository.PreparePosts(new_posts) - if err := json.Unmarshal([]byte(post.Image.Format), &postFormats); err != nil { - log.Error("Error while unmarshal post image formats: ", err) - c.AbortWithStatus(http.StatusInternalServerError) - return - } + c.JSON(http.StatusOK, new_posts) +} - post.Image.Format = "" - post.Image.Formats = postFormats +func (repository *Repository) GetAuthorByPostId(id int) (error, Author) { + author := Author{} - err = repository.Db.Get(&post.Author, `SELECT a.id, a.username, a.name, a.email, a.created_at, a.updated_at, a.bio + err := repository.Db.Get(&author, `SELECT a.id, a.username, a.name, a.email, a.created_at, a.updated_at, a.bio FROM authors a - JOIN posts_author_links pa ON pa.post_id = $1 AND pa.author_id = a.id`, post.Id) - if err != nil { - log.Error("Error while fetching author: ", err) - c.AbortWithStatus(http.StatusInternalServerError) - return - } + JOIN posts_author_links pa ON pa.post_id = $1 AND pa.author_id = a.id`, id) + if err != nil { + log.Error("Error while fetching author: ", err) + return err, author + } - err = repository.Db.Get(&post.Author.Image, `SELECT f.id, f.name, f.alternative_text, f.caption, f.width, f.height, f.formats as format, f.hash, f.ext, f.mime, + err = repository.Db.Get(&author.Image, `SELECT f.id, f.name, f.alternative_text, f.caption, f.width, f.height, f.formats as format, f.hash, f.ext, f.mime, f.size, f.url, f.preview_url, f.provider, f.provider_metadata, f.folder_path, f.created_at, f.updated_at FROM files f - JOIN files_related_morphs frm ON frm.related_id = $1 AND frm.related_type = 'api::author.author' AND frm.file_id = f.id`, post.Author.Id) - if err != nil { - log.Error("Error while fetching author image: ", err) - c.AbortWithStatus(http.StatusInternalServerError) - return - } + JOIN files_related_morphs frm ON frm.related_id = $1 AND frm.related_type = 'api::author.author' AND frm.file_id = f.id`, author.Id) + if err != nil { + log.Error("Error while fetching author image: ", err) + return err, author + } - var authorFormats Formats + var authorFormats Formats - if err := json.Unmarshal([]byte(post.Author.Image.Format), &authorFormats); err != nil { - log.Error("Error while unmarshal author image formats: ", err) - c.AbortWithStatus(http.StatusInternalServerError) - return - } + if err := json.Unmarshal([]byte(author.Image.Format), &authorFormats); err != nil { + log.Error("Error while unmarshal author image formats: ", err) + return err, author + } - post.Author.Image.Format = "" - post.Author.Image.Formats = authorFormats + author.Image.Format = "" + author.Image.Formats = authorFormats - new_posts = append(new_posts, post) + return nil, author +} + +func (repository *Repository) SetAuthorWithImageInPosts(posts []Post) []Post { + + postIds := []string{} + for _, post := range posts { + postIds = append(postIds, strconv.Itoa(post.Id)) } - c.JSON(http.StatusOK, new_posts) + new_post_ids := strings.Join(postIds, ", ") + + authors := []Author{} + authorQuery := fmt.Sprintf(`SELECT a.id, pa.post_id as related_id, a.username, a.name, a.email, a.created_at, a.updated_at, a.bio + FROM authors a + JOIN posts_author_links pa ON pa.post_id IN (%s) AND pa.author_id = a.id`, new_post_ids) + + err := repository.Db.Select(&authors, authorQuery) + if err != nil { + log.Error("Error while fetching author: ", err) + return posts + } + + authorIds := []string{} + for _, author := range authors { + authorIds = append(authorIds, strconv.Itoa(author.Id)) + } + + new_author_ids := strings.Join(authorIds, ", ") + + images := []Image{} + authorImageQuery := fmt.Sprintf(`SELECT f.id, frm.related_id as related_id, f.name, f.alternative_text, f.caption, f.width, f.height, f.formats as format, f.hash, f.ext, f.mime, + f.size, f.url, f.preview_url, f.provider, f.provider_metadata, f.folder_path, f.created_at, f.updated_at + FROM files f + JOIN files_related_morphs frm ON frm.related_id IN (%s) AND frm.related_type = 'api::author.author' AND frm.file_id = f.id`, new_author_ids) + + err = repository.Db.Select(&images, authorImageQuery) + if err != nil { + log.Error("Error while fetching post images: ", err) + return posts + } + + // set author image in author + for i, author := range authors { + for _, image := range images { + if author.Id == image.RelatedId { + + authors[i].Image = image + + // set format of author image if exists + if authors[i].Image.Format != "" { + + var authorFormats Formats + if err := json.Unmarshal([]byte(authors[i].Image.Format), &authorFormats); err != nil { + log.Error("Error while unmarshal post image formats: ", err) + return posts + } + + authors[i].Image.Format = "" + authors[i].Image.Formats = authorFormats + } + break + } + } + } + + // set author with image in post + for i, post := range posts { + for _, author := range authors { + if post.Id == author.RelatedId { + posts[i].Author = author + break + } + } + } + + return posts } diff --git a/post/go.mod b/post/go.mod index dbea6d6d7..247c7966f 100644 --- a/post/go.mod +++ b/post/go.mod @@ -4,14 +4,11 @@ go 1.21.3 replace db => ../db -replace utils => ../utils - require ( github.com/gin-gonic/gin v1.9.1 github.com/jmoiron/sqlx v1.3.5 github.com/sirupsen/logrus v1.9.3 gopkg.in/guregu/null.v3 v3.5.0 - utils v0.0.0-00010101000000-000000000000 ) require ( diff --git a/post/index.go b/post/index.go index 40b38a4e7..3a5cf2a08 100644 --- a/post/index.go +++ b/post/index.go @@ -3,12 +3,14 @@ package post import ( "database/sql" "encoding/json" + "fmt" "net/http" "strconv" - "utils" + "strings" "github.com/gin-gonic/gin" "github.com/jmoiron/sqlx" + "github.com/samber/lo" log "github.com/sirupsen/logrus" ) @@ -85,18 +87,18 @@ func (repository *Repository) GetPosts(isFeatured, isResource, isPublished bool, featuredQuery := "" if isFeatured { - featuredQuery = " AND is_featured = true " + featuredQuery = " AND is_featured = true" } publishQuery := "" if isPublished { - publishQuery = " AND is_published = true " + publishQuery = " AND is_published = true" } posts := []Post{} err := repository.Db.Select(&posts, `SELECT id, title, slug, is_featured, is_published, published_on, published_at, reading_time, summary FROM posts - WHERE is_resource = $1`+publishQuery+featuredQuery+` + WHERE is_resource = $1`+publishQuery+featuredQuery+` ORDER BY published_on DESC LIMIT $2 OFFSET $3`, isResource, limit, skip) if err != nil { @@ -105,65 +107,18 @@ func (repository *Repository) GetPosts(isFeatured, isResource, isPublished bool, } new_posts := []Post{} - for _, post := range posts { - - err = repository.Db.Get(&post.Image, `SELECT f.id, f.name, f.alternative_text, f.caption, f.width, f.height, f.formats as format, f.hash, f.ext, f.mime, - f.size, f.url, f.preview_url, f.provider, f.provider_metadata, f.folder_path, f.created_at, f.updated_at - FROM files f - JOIN files_related_morphs frm ON frm.related_id = $1 AND frm.related_type = 'api::post.post' AND frm.file_id = f.id`, post.Id) - if err != nil && err != sql.ErrNoRows { - log.Error("Error while fetching post images: ", err) - return err, nil - } - - if post.Image.Format != "" { - - var postFormats Formats - - if err := json.Unmarshal([]byte(post.Image.Format), &postFormats); err != nil { - log.Error("Error while unmarshal post image formats: ", err) - return err, nil - } - - post.Image.Format = "" - post.Image.Formats = postFormats - } - - err = repository.Db.Get(&post.Author, `SELECT a.id, a.username, a.name, a.email, a.created_at, a.updated_at, a.bio - FROM authors a - JOIN posts_author_links pa ON pa.post_id = $1 AND pa.author_id = a.id`, post.Id) - if err != nil { - log.Error("Error while fetching author: ", err) - return err, nil - } - - err = repository.Db.Get(&post.Author.Image, `SELECT f.id, f.name, f.alternative_text, f.caption, f.width, f.height, f.formats as format, f.hash, f.ext, f.mime, - f.size, f.url, f.preview_url, f.provider, f.provider_metadata, f.folder_path, f.created_at, f.updated_at - FROM files f - JOIN files_related_morphs frm ON frm.related_id = $1 AND frm.related_type = 'api::author.author' AND frm.file_id = f.id`, post.Author.Id) - if err != nil { - log.Error("Error while fetching author image: ", err) - return err, nil - } - - var authorFormats Formats - - if err := json.Unmarshal([]byte(post.Author.Image.Format), &authorFormats); err != nil { - log.Error("Error while unmarshal author image formats: ", err) - return err, nil - } - - post.Author.Image.Format = "" - post.Author.Image.Formats = authorFormats - - new_posts = append(new_posts, post) - } + new_posts = repository.PreparePosts(posts) return nil, new_posts } -func (repository *Repository) GetById(c *gin.Context) { +func (repository *Repository) Show(c *gin.Context) { slug := c.Param("slug") + if slug == "" { + log.Warn("Slug not found in query paramete") + c.AbortWithStatus(http.StatusBadRequest) + return + } post := Post{} err := repository.Db.Get(&post, `SELECT id, title, content, slug, published_on, is_featured, created_at, updated_at, published_at, @@ -192,60 +147,6 @@ func (repository *Repository) GetById(c *gin.Context) { post.Tag = "" post.Tags = tags - err = repository.Db.Get(&post.Image, `SELECT f.id, f.name, f.alternative_text, f.caption, f.width, f.height, f.formats as format, f.hash, f.ext, f.mime, - f.size, f.url, f.preview_url, f.provider, f.provider_metadata, f.folder_path, f.created_at, f.updated_at - FROM files f - JOIN files_related_morphs frm ON frm.related_id = $1 AND frm.related_type = 'api::post.post' AND frm.file_id = f.id`, post.Id) - if err != nil && err != sql.ErrNoRows { - log.Error("Error while fetching post images: ", err) - c.AbortWithStatus(http.StatusInternalServerError) - return - } - - if post.Image.Format != "" { - - var postFormats Formats - - if err := json.Unmarshal([]byte(post.Image.Format), &postFormats); err != nil { - log.Error("Error while unmarshal post image formats: ", err) - c.AbortWithStatus(http.StatusInternalServerError) - return - } - - post.Image.Format = "" - post.Image.Formats = postFormats - } - - err = repository.Db.Get(&post.Author, `SELECT a.id, a.username, a.name, a.email, a.created_at, a.updated_at, a.bio - FROM authors a - JOIN posts_author_links pa ON pa.post_id = $1 AND pa.author_id = a.id`, post.Id) - if err != nil { - log.Error("Error while fetching author: ", err) - c.AbortWithStatus(http.StatusInternalServerError) - return - } - - err = repository.Db.Get(&post.Author.Image, `SELECT f.id, f.name, f.alternative_text, f.caption, f.width, f.height, f.formats as format, f.hash, f.ext, f.mime, - f.size, f.url, f.preview_url, f.provider, f.provider_metadata, f.folder_path, f.created_at, f.updated_at - FROM files f - JOIN files_related_morphs frm ON frm.related_id = $1 AND frm.related_type = 'api::author.author' AND frm.file_id = f.id`, post.Author.Id) - if err != nil { - log.Error("Error while fetching author image: ", err) - c.AbortWithStatus(http.StatusInternalServerError) - return - } - - var authorFormats Formats - - if err := json.Unmarshal([]byte(post.Author.Image.Format), &authorFormats); err != nil { - log.Error("Error while unmarshal author image formats: ", err) - c.AbortWithStatus(http.StatusInternalServerError) - return - } - - post.Author.Image.Format = "" - post.Author.Image.Formats = authorFormats - err = repository.Db.Get(&post.Cta, `SELECT c.id, c.name, c.component_name, c.created_at, c.updated_at FROM ctas c JOIN posts_cta_links pc ON pc.post_id = $1 AND pc.cta_id = c.id`, post.Id) @@ -263,10 +164,10 @@ func (repository *Repository) GetById(c *gin.Context) { if post.IsResource { posts := []RecommendedPost{} err = repository.Db.Select(&posts, `SELECT id, title, content, slug, published_on, is_featured, created_at, updated_at, published_at, - summary, blog_content, meta_description, toc, tags as tag, is_published, keywords, new_content, new_toc, new_blog_content, - is_resource, reading_time - FROM posts - WHERE slug != $1`, slug) + summary, blog_content, meta_description, toc, tags as tag, is_published, keywords, new_content, new_toc, new_blog_content, + is_resource, reading_time + FROM posts + WHERE slug != $1`, slug) if err != nil { log.Error("Error while fetching recommended post: ", err) c.AbortWithStatus(http.StatusInternalServerError) @@ -276,15 +177,72 @@ func (repository *Repository) GetById(c *gin.Context) { post.RecommendedPosts = repository.FilterPostsByTags(posts, repository.ExtractTagNames(post.Tags)) } - c.JSON(http.StatusOK, post) + new_posts := repository.PreparePosts([]Post{post}) + + c.JSON(http.StatusOK, new_posts[0]) } -// Assuming you have a function to filter posts based on tags +func (repository *Repository) PreparePosts(posts []Post) []Post { + + new_posts := repository.SetPostImageInPosts(posts) + new_posts = repository.SetAuthorWithImageInPosts(posts) + + return new_posts +} + +func (repository *Repository) SetPostImageInPosts(posts []Post) []Post { + + postIds := []string{} + for _, post := range posts { + postIds = append(postIds, strconv.Itoa(post.Id)) + } + + new_post_ids := strings.Join(postIds, ", ") + + images := []Image{} + postImageQuery := fmt.Sprintf(`SELECT f.id, frm.related_id as related_id, f.name, f.alternative_text, f.caption, f.width, f.height, f.formats as format, f.hash, f.ext, f.mime, + f.size, f.url, f.preview_url, f.provider, f.provider_metadata, f.folder_path, f.created_at, f.updated_at + FROM files f + JOIN files_related_morphs frm ON frm.related_id IN (%s) AND frm.related_type = 'api::post.post' AND frm.file_id = f.id`, new_post_ids) + + err := repository.Db.Select(&images, postImageQuery) + if err != nil { + log.Error("Error while fetching post images: ", err) + return posts + } + + for i, post := range posts { + for _, image := range images { + if post.Id == image.RelatedId { + // set image in post + posts[i].Image = image + + // set format of image if exists + if posts[i].Image.Format != "" { + + var postFormats Formats + if err := json.Unmarshal([]byte(posts[i].Image.Format), &postFormats); err != nil { + log.Error("Error while unmarshal post image formats: ", err) + return posts + } + + posts[i].Image.Format = "" + posts[i].Image.Formats = postFormats + } + break + } + } + } + + return posts +} + +// Filter posts based on tags func (repository *Repository) FilterPostsByTags(posts []RecommendedPost, tags []string) []RecommendedPost { - // Filter posts based on tags - // You should replace this with your filtering logic + filteredPosts := []RecommendedPost{} count := 0 + var err error for _, post := range posts { if count >= 3 { @@ -293,7 +251,7 @@ func (repository *Repository) FilterPostsByTags(posts []RecommendedPost, tags [] var postTags []Tag - if err := json.Unmarshal([]byte(post.Tag), &postTags); err != nil { + if err = json.Unmarshal([]byte(post.Tag), &postTags); err != nil { log.Error("Error while unmarshal tags: ", err) return nil } @@ -301,53 +259,13 @@ func (repository *Repository) FilterPostsByTags(posts []RecommendedPost, tags [] post.Tags = postTags for _, tag := range post.Tags { - if utils.Contains(tags, tag.Name) { - err := repository.Db.Get(&post.Image, `SELECT f.id, f.name, f.alternative_text, f.caption, f.width, f.height, f.formats as format, f.hash, f.ext, f.mime, - f.size, f.url, f.preview_url, f.provider, f.provider_metadata, f.folder_path, f.created_at, f.updated_at - FROM files f - JOIN files_related_morphs frm ON frm.related_id = $1 AND frm.related_type = 'api::post.post' AND frm.file_id = f.id`, post.Id) - if err != nil { - log.Error("Error while fetching post images: ", err) - return nil - } - - var postFormats Formats - - if err := json.Unmarshal([]byte(post.Image.Format), &postFormats); err != nil { - log.Error("Error while unmarshal post image formats: ", err) - return nil - } - - post.Image.Format = "" - post.Image.Formats = postFormats - - err = repository.Db.Get(&post.Author, `SELECT a.id, a.username, a.name, a.email, a.created_at, a.updated_at, a.bio - FROM authors a - JOIN posts_author_links pa ON pa.post_id = $1 AND pa.author_id = a.id`, post.Id) - if err != nil { - log.Error("Error while fetching author: ", err) - return nil - } + if lo.Contains(tags, tag.Name) { - err = repository.Db.Get(&post.Author.Image, `SELECT f.id, f.name, f.alternative_text, f.caption, f.width, f.height, f.formats as format, f.hash, f.ext, f.mime, - f.size, f.url, f.preview_url, f.provider, f.provider_metadata, f.folder_path, f.created_at, f.updated_at - FROM files f - JOIN files_related_morphs frm ON frm.related_id = $1 AND frm.related_type = 'api::author.author' AND frm.file_id = f.id`, post.Author.Id) + err, post.Author = repository.GetAuthorByPostId(post.Id) if err != nil { - log.Error("Error while fetching author image: ", err) - return nil - } - - var authorFormats Formats - - if err := json.Unmarshal([]byte(post.Author.Image.Format), &authorFormats); err != nil { - log.Error("Error while unmarshal author image formats: ", err) return nil } - post.Author.Image.Format = "" - post.Author.Image.Formats = authorFormats - filteredPosts = append(filteredPosts, post) count++ diff --git a/post/models.go b/post/models.go index 03b9780ca..bd57f320a 100644 --- a/post/models.go +++ b/post/models.go @@ -20,7 +20,7 @@ type Post struct { IsFeatured bool `json:"is_featured"` CreatedAt string `json:"created_at,omitempty"` UpdatedAt string `json:"updated_at,omitempty"` - PublishedAt null.String `json:"published_at"` + PublishedAt null.String `json:"published_at"` Summary string `json:"summary,omitempty"` BlogContent string `json:"blog_content,omitempty"` MetaDescription string `json:"meta_description,omitempty"` @@ -36,7 +36,7 @@ type Post struct { ReadingTime *null.Int `json:"reading_time,omitempty"` Author Author `json:"author"` Image Image `json:"image"` - Cta Cta `json:"cta,omitempty"` + Cta Cta `json:"cta,omitempty"` RecommendedPosts []RecommendedPost `json:"recommended_posts,omitempty"` } @@ -50,6 +50,7 @@ type Tag struct { type Author struct { Id int `json:"id"` + RelatedId int `json:"related_id"` Username string `json:"username"` Name string `json:"name"` Email string `json:"email"` @@ -61,6 +62,7 @@ type Author struct { type Image struct { Id int `json:"id"` + RelatedId int `json:"related_id"` Name string `json:"name"` AlternativeText null.String `json:"alternative_text"` Caption null.String `json:"caption"` @@ -117,7 +119,7 @@ type RecommendedPost struct { IsFeatured bool `json:"is_featured"` CreatedAt string `json:"created_at"` UpdatedAt string `json:"updated_at"` - PublishedAt null.String `json:"published_at"` + PublishedAt null.String `json:"published_at"` Summary string `json:"summary"` BlogContent string `json:"blog_content"` MetaDescription string `json:"meta_description"` diff --git a/post/tag.go b/post/tag.go index 192598aa4..e25facc98 100644 --- a/post/tag.go +++ b/post/tag.go @@ -11,6 +11,11 @@ import ( func (repository *Repository) GetPostsByTag(c *gin.Context) { slug := c.Param("slug") + if slug == "" { + log.Warn("Slug not found in query paramete") + c.AbortWithStatus(http.StatusBadRequest) + return + } isPublished, err := strconv.ParseBool(c.DefaultQuery("is_published", "false")) if err != nil { @@ -48,59 +53,10 @@ func (repository *Repository) GetPostsByTag(c *gin.Context) { post.Tag = "" post.Tags = tags - err = repository.Db.Get(&post.Image, `SELECT f.id, f.name, f.alternative_text, f.caption, f.width, f.height, f.formats as format, f.hash, f.ext, f.mime, - f.size, f.url, f.preview_url, f.provider, f.provider_metadata, f.folder_path, f.created_at, f.updated_at - FROM files f - JOIN files_related_morphs frm ON frm.related_id = $1 AND frm.related_type = 'api::post.post' AND frm.file_id = f.id`, post.Id) - if err != nil { - log.Error("Error while fetching post images: ", err) - c.AbortWithStatus(http.StatusInternalServerError) - return - } - - var postFormats Formats - - if err := json.Unmarshal([]byte(post.Image.Format), &postFormats); err != nil { - log.Error("Error while unmarshal post image formats: ", err) - c.AbortWithStatus(http.StatusInternalServerError) - return - } - - post.Image.Format = "" - post.Image.Formats = postFormats - - err = repository.Db.Get(&post.Author, `SELECT a.id, a.username, a.name, a.email, a.created_at, a.updated_at, a.bio - FROM authors a - JOIN posts_author_links pa ON pa.post_id = $1 AND pa.author_id = a.id`, post.Id) - if err != nil { - log.Error("Error while fetching author: ", err) - c.AbortWithStatus(http.StatusInternalServerError) - return - } - - err = repository.Db.Get(&post.Author.Image, `SELECT f.id, f.name, f.alternative_text, f.caption, f.width, f.height, f.formats as format, f.hash, f.ext, f.mime, - f.size, f.url, f.preview_url, f.provider, f.provider_metadata, f.folder_path, f.created_at, f.updated_at - FROM files f - JOIN files_related_morphs frm ON frm.related_id = $1 AND frm.related_type = 'api::author.author' AND frm.file_id = f.id`, post.Author.Id) - if err != nil { - log.Error("Error while fetching author image: ", err) - c.AbortWithStatus(http.StatusInternalServerError) - return - } - - var authorFormats Formats - - if err := json.Unmarshal([]byte(post.Author.Image.Format), &authorFormats); err != nil { - log.Error("Error while unmarshal author image formats: ", err) - c.AbortWithStatus(http.StatusInternalServerError) - return - } - - post.Author.Image.Format = "" - post.Author.Image.Formats = authorFormats - new_posts = append(new_posts, post) } + new_posts = repository.PreparePosts(new_posts) + c.JSON(http.StatusOK, new_posts) } diff --git a/utils/helper.go b/utils/helper.go index 93664b199..0e9743c66 100755 --- a/utils/helper.go +++ b/utils/helper.go @@ -115,13 +115,3 @@ func GenerateUniqueFileName(filename string) string { name = strings.Replace(name, " ", "", -1) return fmt.Sprintf("%s_%d%s", name, time.Now().Unix(), ext) } - -// Helper function to check if a string exists in a slice of strings -func Contains(slice []string, item string) bool { - for _, i := range slice { - if i == item { - return true - } - } - return false -}