refactor: configuring context and moving logic to its designated directory
This commit is contained in:
parent
31652fb3ab
commit
483a042ccb
|
@ -25,7 +25,7 @@ func GetUserID(db *pgxpool.Pool, ctx context.Context, key string) (int, error) {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := c.Query(context.Background(), sql, args...)
|
r, err := c.Query(ctx, sql, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ func GetUserID(db *pgxpool.Pool, ctx context.Context, key string) (int, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var id int
|
var id int
|
||||||
err = c.QueryRow(context.Background(), sql, args...).Scan(&id)
|
err = c.QueryRow(ctx, sql, args...).Scan(&id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ func CheckKeyExists(db *pgxpool.Pool, ctx context.Context, key string) (string,
|
||||||
}
|
}
|
||||||
|
|
||||||
var token string
|
var token string
|
||||||
err = conn.QueryRow(context.Background(), sql, args...).Scan(&token)
|
err = conn.QueryRow(ctx, sql, args...).Scan(&token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, pgx.ErrNoRows) {
|
if errors.Is(err, pgx.ErrNoRows) {
|
||||||
return "", nil
|
return "", nil
|
||||||
|
|
|
@ -25,7 +25,7 @@ func GetAllJSONJokes(db *pgxpool.Pool, ctx context.Context) ([]byte, error) {
|
||||||
defer conn.Release()
|
defer conn.Release()
|
||||||
|
|
||||||
var jokes []schema.Joke
|
var jokes []schema.Joke
|
||||||
results, err := conn.Query(context.Background(), "SELECT \"id\",\"link\" FROM \"jokesbapak2\" ORDER BY \"id\"")
|
results, err := conn.Query(ctx, "SELECT \"id\",\"link\" FROM \"jokesbapak2\" ORDER BY \"id\"")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ func GetRandomJokeFromDB(db *pgxpool.Pool, ctx context.Context) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
var link string
|
var link string
|
||||||
err = conn.QueryRow(context.Background(), "SELECT link FROM jokesbapak2 ORDER BY random() LIMIT 1").Scan(&link)
|
err = conn.QueryRow(ctx, "SELECT link FROM jokesbapak2 ORDER BY random() LIMIT 1").Scan(&link)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -172,7 +172,7 @@ func CheckJokeExists(db *pgxpool.Pool, ctx context.Context, id string) (bool, er
|
||||||
}
|
}
|
||||||
|
|
||||||
var jokeID int
|
var jokeID int
|
||||||
err = conn.QueryRow(context.Background(), sql, args...).Scan(&jokeID)
|
err = conn.QueryRow(ctx, sql, args...).Scan(&jokeID)
|
||||||
if err != nil && err != pgx.ErrNoRows {
|
if err != nil && err != pgx.ErrNoRows {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ func InsertJokeIntoDB(db *pgxpool.Pool, ctx context.Context, joke schema.Joke) e
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := conn.Query(context.Background(), sql, args...)
|
r, err := conn.Query(ctx, sql, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ func DeleteSingleJoke(db *pgxpool.Pool, ctx context.Context, id int) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := conn.Query(context.Background(), sql, args...)
|
r, err := conn.Query(ctx, sql, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ func UpdateJoke(db *pgxpool.Pool, ctx context.Context, link, creator string) err
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := conn.Query(context.Background(), sql, args...)
|
r, err := conn.Query(ctx, sql, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,3 +4,7 @@ import "errors"
|
||||||
|
|
||||||
var ErrNotFound = errors.New("record not found")
|
var ErrNotFound = errors.New("record not found")
|
||||||
var ErrEmpty = errors.New("record is empty")
|
var ErrEmpty = errors.New("record is empty")
|
||||||
|
|
||||||
|
type Error struct {
|
||||||
|
Error string `json:"error"`
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package submit
|
package schema
|
||||||
|
|
||||||
type Submission struct {
|
type Submission struct {
|
||||||
ID int `json:"id,omitempty" db:"id"`
|
ID int `json:"id,omitempty" db:"id"`
|
||||||
|
@ -22,7 +22,3 @@ type ResponseSubmission struct {
|
||||||
Submission Submission `json:"submission,omitempty"`
|
Submission Submission `json:"submission,omitempty"`
|
||||||
AuthorPage string `json:"author_page,omitempty"`
|
AuthorPage string `json:"author_page,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Error struct {
|
|
||||||
Error string `json:"error"`
|
|
||||||
}
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
package submit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"jokes-bapak2-api/core/schema"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/aldy505/bob"
|
||||||
|
"github.com/georgysavva/scany/pgxscan"
|
||||||
|
"github.com/jackc/pgx/v4/pgxpool"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetSubmittedItems(db *pgxpool.Pool, ctx context.Context, queries schema.SubmissionQuery) ([]schema.Submission, error) {
|
||||||
|
var err error
|
||||||
|
var limit int
|
||||||
|
var offset int
|
||||||
|
var approved bool
|
||||||
|
|
||||||
|
if queries.Limit != "" {
|
||||||
|
limit, err = strconv.Atoi(queries.Limit)
|
||||||
|
if err != nil {
|
||||||
|
return []schema.Submission{}, err
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if queries.Page != "" {
|
||||||
|
page, err := strconv.Atoi(queries.Page)
|
||||||
|
if err != nil {
|
||||||
|
return []schema.Submission{}, err
|
||||||
|
|
||||||
|
}
|
||||||
|
offset = (page - 1) * 20
|
||||||
|
}
|
||||||
|
|
||||||
|
if queries.Approved != "" {
|
||||||
|
approved, err = strconv.ParseBool(queries.Approved)
|
||||||
|
if err != nil {
|
||||||
|
return []schema.Submission{}, err
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var status int
|
||||||
|
|
||||||
|
if approved {
|
||||||
|
status = 1
|
||||||
|
} else {
|
||||||
|
status = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
sql, args, err := GetterQueryBuilder(queries, status, limit, offset)
|
||||||
|
if err != nil {
|
||||||
|
return []schema.Submission{}, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := db.Acquire(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return []schema.Submission{}, err
|
||||||
|
}
|
||||||
|
defer conn.Release()
|
||||||
|
|
||||||
|
var submissions []schema.Submission
|
||||||
|
results, err := conn.Query(ctx, sql, args...)
|
||||||
|
if err != nil {
|
||||||
|
return []schema.Submission{}, err
|
||||||
|
|
||||||
|
}
|
||||||
|
defer results.Close()
|
||||||
|
|
||||||
|
err = pgxscan.ScanAll(&submissions, results)
|
||||||
|
if err != nil {
|
||||||
|
return []schema.Submission{}, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return submissions, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetterQueryBuilder(queries schema.SubmissionQuery, status, limit, offset int) (string, []interface{}, error) {
|
||||||
|
var sql string
|
||||||
|
var args []interface{}
|
||||||
|
var sqlQuery *bytes.Buffer = &bytes.Buffer{}
|
||||||
|
sqlQuery.WriteString("SELECT * FROM submission WHERE TRUE")
|
||||||
|
|
||||||
|
if queries.Author != "" {
|
||||||
|
sqlQuery.WriteString(" AND author = ?")
|
||||||
|
escapedAuthor, err := url.QueryUnescape(queries.Author)
|
||||||
|
if err != nil {
|
||||||
|
return sql, args, err
|
||||||
|
|
||||||
|
}
|
||||||
|
args = append(args, escapedAuthor)
|
||||||
|
}
|
||||||
|
|
||||||
|
if queries.Approved != "" {
|
||||||
|
sqlQuery.WriteString(" AND status = ?")
|
||||||
|
args = append(args, status)
|
||||||
|
}
|
||||||
|
|
||||||
|
if limit > 0 {
|
||||||
|
sqlQuery.WriteString(" LIMIT " + strconv.Itoa(limit))
|
||||||
|
} else {
|
||||||
|
sqlQuery.WriteString(" LIMIT 20")
|
||||||
|
}
|
||||||
|
|
||||||
|
if queries.Page != "" {
|
||||||
|
sqlQuery.WriteString(" OFFSET " + strconv.Itoa(offset))
|
||||||
|
}
|
||||||
|
|
||||||
|
sql = bob.ReplacePlaceholder(sqlQuery.String(), bob.Dollar)
|
||||||
|
|
||||||
|
return sql, args, nil
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ package submit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"jokes-bapak2-api/core/schema"
|
"jokes-bapak2-api/core/schema"
|
||||||
|
@ -10,8 +11,12 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/Masterminds/squirrel"
|
||||||
|
"github.com/georgysavva/scany/pgxscan"
|
||||||
"github.com/gojek/heimdall/v7/httpclient"
|
"github.com/gojek/heimdall/v7/httpclient"
|
||||||
|
"github.com/jackc/pgx/v4/pgxpool"
|
||||||
"github.com/pquerna/ffjson/ffjson"
|
"github.com/pquerna/ffjson/ffjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -79,3 +84,39 @@ func UploadImage(client *httpclient.Client, image io.Reader) (string, error) {
|
||||||
|
|
||||||
return data.Data.URL, nil
|
return data.Data.URL, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SubmitJoke(db *pgxpool.Pool, ctx context.Context, s schema.Submission, link string) (schema.Submission, error) {
|
||||||
|
var query = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||||
|
|
||||||
|
conn, err := db.Acquire(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return schema.Submission{}, err
|
||||||
|
}
|
||||||
|
defer conn.Release()
|
||||||
|
|
||||||
|
now := time.Now().UTC().Format(time.RFC3339)
|
||||||
|
|
||||||
|
sql, args, err := query.
|
||||||
|
Insert("submission").
|
||||||
|
Columns("link", "created_at", "author").
|
||||||
|
Values(link, now, s.Author).
|
||||||
|
Suffix("RETURNING id,created_at,link,author,status").
|
||||||
|
ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return schema.Submission{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var submission schema.Submission
|
||||||
|
result, err := conn.Query(ctx, sql, args...)
|
||||||
|
if err != nil {
|
||||||
|
return schema.Submission{}, err
|
||||||
|
}
|
||||||
|
defer result.Close()
|
||||||
|
|
||||||
|
err = pgxscan.ScanOne(&submission, result)
|
||||||
|
if err != nil {
|
||||||
|
return schema.Submission{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return submission, nil
|
||||||
|
}
|
||||||
|
|
|
@ -10,14 +10,15 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Validate if link already exists
|
// Validate if link already exists
|
||||||
func LinkAlreadyExists(db *pgxpool.Pool, ctx context.Context, link string) (bool, error) {
|
func JokeLinkExists(db *pgxpool.Pool, ctx context.Context, link string) (bool, error) {
|
||||||
conn, err := db.Acquire(ctx)
|
conn, err := db.Acquire(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
var query = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
|
||||||
defer conn.Release()
|
defer conn.Release()
|
||||||
|
|
||||||
|
var query = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||||
|
|
||||||
sql, args, err := query.
|
sql, args, err := query.
|
||||||
Select("link").
|
Select("link").
|
||||||
From("jokesbapak2").
|
From("jokesbapak2").
|
||||||
|
@ -28,7 +29,7 @@ func LinkAlreadyExists(db *pgxpool.Pool, ctx context.Context, link string) (bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var validateLink string
|
var validateLink string
|
||||||
err = conn.QueryRow(context.Background(), sql, args...).Scan(&validateLink)
|
err = conn.QueryRow(ctx, sql, args...).Scan(&validateLink)
|
||||||
if err != nil && err != pgx.ErrNoRows {
|
if err != nil && err != pgx.ErrNoRows {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
@ -37,7 +38,7 @@ func LinkAlreadyExists(db *pgxpool.Pool, ctx context.Context, link string) (bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the joke exists
|
// Check if the joke exists
|
||||||
func IDAlreadyExists(db *pgxpool.Pool, ctx context.Context, id int) (bool, error) {
|
func JokeIDExists(db *pgxpool.Pool, ctx context.Context, id int) (bool, error) {
|
||||||
conn, err := db.Acquire(ctx)
|
conn, err := db.Acquire(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
@ -55,7 +56,7 @@ func IDAlreadyExists(db *pgxpool.Pool, ctx context.Context, id int) (bool, error
|
||||||
}
|
}
|
||||||
|
|
||||||
var jokeID int
|
var jokeID int
|
||||||
err = conn.QueryRow(context.Background(), sql, args...).Scan(&jokeID)
|
err = conn.QueryRow(ctx, sql, args...).Scan(&jokeID)
|
||||||
if err != nil && !errors.Is(err, pgx.ErrNoRows) {
|
if err != nil && !errors.Is(err, pgx.ErrNoRows) {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package validator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/Masterminds/squirrel"
|
||||||
|
"github.com/jackc/pgx/v4"
|
||||||
|
"github.com/jackc/pgx/v4/pgxpool"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SubmitLinkExists(db *pgxpool.Pool, ctx context.Context, query squirrel.StatementBuilderType, link string) (bool, error) {
|
||||||
|
conn, err := db.Acquire(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
defer conn.Release()
|
||||||
|
|
||||||
|
sql, args, err := query.
|
||||||
|
Select("link").
|
||||||
|
From("submission").
|
||||||
|
Where(squirrel.Eq{"link": link}).
|
||||||
|
ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var validateLink string
|
||||||
|
err = conn.QueryRow(ctx, sql, args...).Scan(&validateLink)
|
||||||
|
if err != nil && err != pgx.ErrNoRows {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil && validateLink != "" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
|
@ -28,7 +28,7 @@ func (d *Dependencies) AddNewJoke(c *fiber.Ctx) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
validateLink, err := validator.LinkAlreadyExists(d.DB, c.Context(), body.Link)
|
validateLink, err := validator.JokeLinkExists(d.DB, c.Context(), body.Link)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ func (d *Dependencies) DeleteJoke(c *fiber.Ctx) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
validate, err := validator.IDAlreadyExists(d.DB, c.Context(), id)
|
validate, err := validator.JokeIDExists(d.DB, c.Context(), id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,13 @@
|
||||||
package submit
|
package submit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"jokes-bapak2-api/core/schema"
|
||||||
core "jokes-bapak2-api/core/submit"
|
core "jokes-bapak2-api/core/submit"
|
||||||
"jokes-bapak2-api/core/validator"
|
"jokes-bapak2-api/core/validator"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/Masterminds/squirrel"
|
|
||||||
"github.com/georgysavva/scany/pgxscan"
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/jackc/pgx/v4"
|
|
||||||
"github.com/jackc/pgx/v4/pgxpool"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (d *Dependencies) SubmitJoke(c *fiber.Ctx) error {
|
func (d *Dependencies) SubmitJoke(c *fiber.Ctx) error {
|
||||||
|
@ -22,7 +17,7 @@ func (d *Dependencies) SubmitJoke(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
defer conn.Release()
|
defer conn.Release()
|
||||||
|
|
||||||
var body Submission
|
var body schema.Submission
|
||||||
err = c.BodyParser(&body)
|
err = c.BodyParser(&body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -30,21 +25,21 @@ func (d *Dependencies) SubmitJoke(c *fiber.Ctx) error {
|
||||||
|
|
||||||
// Image and/or Link should not be empty
|
// Image and/or Link should not be empty
|
||||||
if body.Image == "" && body.Link == "" {
|
if body.Image == "" && body.Link == "" {
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(Error{
|
return c.Status(fiber.StatusBadRequest).JSON(schema.Error{
|
||||||
Error: "A link or an image should be supplied in a form of multipart/form-data",
|
Error: "A link or an image should be supplied in a form of multipart/form-data",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Author should be supplied
|
// Author should be supplied
|
||||||
if body.Author == "" {
|
if body.Author == "" {
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(Error{
|
return c.Status(fiber.StatusBadRequest).JSON(schema.Error{
|
||||||
Error: "An author key consisting on the format \"yourname <youremail@mail>\" must be supplied",
|
Error: "An author key consisting on the format \"yourname <youremail@mail>\" must be supplied",
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// Validate format
|
// Validate format
|
||||||
valid := validator.ValidateAuthor(body.Author)
|
valid := validator.ValidateAuthor(body.Author)
|
||||||
if !valid {
|
if !valid {
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(Error{
|
return c.Status(fiber.StatusBadRequest).JSON(schema.Error{
|
||||||
Error: "Please stick to the format of \"yourname <youremail@mail>\" and within 200 characters",
|
Error: "Please stick to the format of \"yourname <youremail@mail>\" and within 200 characters",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -59,7 +54,7 @@ func (d *Dependencies) SubmitJoke(c *fiber.Ctx) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !valid {
|
if !valid {
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(Error{
|
return c.Status(fiber.StatusBadRequest).JSON(schema.Error{
|
||||||
Error: "URL provided is not a valid image",
|
Error: "URL provided is not a valid image",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -78,75 +73,27 @@ func (d *Dependencies) SubmitJoke(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate if link already exists
|
// Validate if link already exists
|
||||||
validateLink, err := validateIfLinkExists(d.DB, c.Context(), d.Query, link)
|
validateLink, err := validator.SubmitLinkExists(d.DB, c.Context(), d.Query, link)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if validateLink {
|
if validateLink {
|
||||||
return c.Status(fiber.StatusConflict).JSON(Error{
|
return c.Status(fiber.StatusConflict).JSON(schema.Error{
|
||||||
Error: "Given link is already on the submission queue.",
|
Error: "Given link is already on the submission queue.",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now().UTC().Format(time.RFC3339)
|
submission, err := core.SubmitJoke(d.DB, c.Context(), body, link)
|
||||||
|
|
||||||
sql, args, err := d.Query.
|
|
||||||
Insert("submission").
|
|
||||||
Columns("link", "created_at", "author").
|
|
||||||
Values(link, now, body.Author).
|
|
||||||
Suffix("RETURNING id,created_at,link,author,status").
|
|
||||||
ToSql()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var submission []Submission
|
|
||||||
result, err := conn.Query(c.Context(), sql, args...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer result.Close()
|
|
||||||
|
|
||||||
err = pgxscan.ScanAll(&submission, result)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.
|
return c.
|
||||||
Status(fiber.StatusCreated).
|
Status(fiber.StatusCreated).
|
||||||
JSON(ResponseSubmission{
|
JSON(schema.ResponseSubmission{
|
||||||
Message: "Joke submitted. Please wait for a few days for admin to approve your submission.",
|
Message: "Joke submitted. Please wait for a few days for admin to approve your submission.",
|
||||||
Submission: submission[0],
|
Submission: submission,
|
||||||
AuthorPage: "/submit?author=" + url.QueryEscape(body.Author),
|
AuthorPage: "/submit?author=" + url.QueryEscape(body.Author),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateIfLinkExists(db *pgxpool.Pool, ctx context.Context, query squirrel.StatementBuilderType, link string) (bool, error) {
|
|
||||||
conn, err := db.Acquire(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
defer conn.Release()
|
|
||||||
|
|
||||||
sql, args, err := query.
|
|
||||||
Select("link").
|
|
||||||
From("submission").
|
|
||||||
Where(squirrel.Eq{"link": link}).
|
|
||||||
ToSql()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var validateLink string
|
|
||||||
err = conn.QueryRow(context.Background(), sql, args...).Scan(&validateLink)
|
|
||||||
if err != nil && err != pgx.ErrNoRows {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err == nil && validateLink != "" {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,96 +1,20 @@
|
||||||
package submit
|
package submit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"jokes-bapak2-api/core/schema"
|
||||||
"net/url"
|
core "jokes-bapak2-api/core/submit"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/aldy505/bob"
|
|
||||||
"github.com/georgysavva/scany/pgxscan"
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (d *Dependencies) GetSubmission(c *fiber.Ctx) error {
|
func (d *Dependencies) GetSubmission(c *fiber.Ctx) error {
|
||||||
query := new(SubmissionQuery)
|
query := new(schema.SubmissionQuery)
|
||||||
err := c.QueryParser(query)
|
err := c.QueryParser(query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var limit int
|
submissions, err := core.GetSubmittedItems(d.DB, c.Context(), *query)
|
||||||
var offset int
|
|
||||||
var approved bool
|
|
||||||
|
|
||||||
if query.Limit != "" {
|
|
||||||
limit, err = strconv.Atoi(query.Limit)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if query.Page != "" {
|
|
||||||
page, err := strconv.Atoi(query.Page)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
offset = (page - 1) * 20
|
|
||||||
}
|
|
||||||
|
|
||||||
if query.Approved != "" {
|
|
||||||
approved, err = strconv.ParseBool(query.Approved)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var status int
|
|
||||||
|
|
||||||
if approved {
|
|
||||||
status = 1
|
|
||||||
} else {
|
|
||||||
status = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
var sql string
|
|
||||||
var args []interface{}
|
|
||||||
|
|
||||||
var sqlQuery *bytes.Buffer = &bytes.Buffer{}
|
|
||||||
sqlQuery.WriteString("SELECT * FROM submission WHERE TRUE")
|
|
||||||
|
|
||||||
if query.Author != "" {
|
|
||||||
sqlQuery.WriteString(" AND author = ?")
|
|
||||||
escapedAuthor, err := url.QueryUnescape(query.Author)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
args = append(args, escapedAuthor)
|
|
||||||
}
|
|
||||||
|
|
||||||
if query.Approved != "" {
|
|
||||||
sqlQuery.WriteString(" AND status = ?")
|
|
||||||
args = append(args, status)
|
|
||||||
}
|
|
||||||
|
|
||||||
if limit > 0 {
|
|
||||||
sqlQuery.WriteString(" LIMIT " + strconv.Itoa(limit))
|
|
||||||
} else {
|
|
||||||
sqlQuery.WriteString(" LIMIT 20")
|
|
||||||
}
|
|
||||||
|
|
||||||
if query.Page != "" {
|
|
||||||
sqlQuery.WriteString(" OFFSET " + strconv.Itoa(offset))
|
|
||||||
}
|
|
||||||
|
|
||||||
sql = bob.ReplacePlaceholder(sqlQuery.String(), bob.Dollar)
|
|
||||||
|
|
||||||
var submissions []Submission
|
|
||||||
results, err := d.DB.Query(c.Context(), sql, args...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer results.Close()
|
|
||||||
|
|
||||||
err = pgxscan.ScanAll(&submissions, results)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
10
api/main.go
10
api/main.go
|
@ -72,18 +72,20 @@ func main() {
|
||||||
}
|
}
|
||||||
defer sentry.Flush(2 * time.Second)
|
defer sentry.Flush(2 * time.Second)
|
||||||
|
|
||||||
// TODO: These sequence below might be better wrapped as a Populate() function.
|
setupCtx, setupCancel := context.WithDeadline(context.Background(), time.Now().Add(time.Minute*4))
|
||||||
err = database.Setup(db)
|
defer setupCancel()
|
||||||
|
|
||||||
|
err = database.Populate(db, setupCtx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sentry.CaptureException(err)
|
sentry.CaptureException(err)
|
||||||
log.Panicln(err)
|
log.Panicln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = joke.SetAllJSONJoke(db, context.Background(), memory)
|
err = joke.SetAllJSONJoke(db, setupCtx, memory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicln(err)
|
log.Panicln(err)
|
||||||
}
|
}
|
||||||
err = joke.SetTotalJoke(db, context.Background(), memory)
|
err = joke.SetTotalJoke(db, setupCtx, memory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicln(err)
|
log.Panicln(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,18 +8,18 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Setup the table connection, create table if not exists
|
// Setup the table connection, create table if not exists
|
||||||
func Setup(db *pgxpool.Pool) error {
|
func Populate(db *pgxpool.Pool, ctx context.Context) error {
|
||||||
err := setupAuthTable(db)
|
err := setupAuthTable(db, ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = setupJokesTable(db)
|
err = setupJokesTable(db, ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = setupSubmissionTable(db)
|
err = setupSubmissionTable(db, ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,8 @@ func Setup(db *pgxpool.Pool) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupAuthTable(db *pgxpool.Pool) error {
|
func setupAuthTable(db *pgxpool.Pool, ctx context.Context) error {
|
||||||
conn, err := db.Acquire(context.Background())
|
conn, err := db.Acquire(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ func setupAuthTable(db *pgxpool.Pool) error {
|
||||||
|
|
||||||
// Check if table exists
|
// Check if table exists
|
||||||
var tableAuthExists bool
|
var tableAuthExists bool
|
||||||
err = conn.QueryRow(context.Background(), `SELECT EXISTS (
|
err = conn.QueryRow(ctx, `SELECT EXISTS (
|
||||||
SELECT FROM information_schema.tables
|
SELECT FROM information_schema.tables
|
||||||
WHERE table_schema = 'public'
|
WHERE table_schema = 'public'
|
||||||
AND table_name = 'administrators'
|
AND table_name = 'administrators'
|
||||||
|
@ -57,7 +57,7 @@ func setupAuthTable(db *pgxpool.Pool) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = conn.Exec(context.Background(), sql)
|
_, err = conn.Exec(ctx, sql)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -65,8 +65,8 @@ func setupAuthTable(db *pgxpool.Pool) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupJokesTable(db *pgxpool.Pool) error {
|
func setupJokesTable(db *pgxpool.Pool, ctx context.Context) error {
|
||||||
conn, err := db.Acquire(context.Background())
|
conn, err := db.Acquire(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ func setupJokesTable(db *pgxpool.Pool) error {
|
||||||
|
|
||||||
// Check if table exists
|
// Check if table exists
|
||||||
var tableJokesExists bool
|
var tableJokesExists bool
|
||||||
err = conn.QueryRow(context.Background(), `SELECT EXISTS (
|
err = conn.QueryRow(ctx, `SELECT EXISTS (
|
||||||
SELECT FROM information_schema.tables
|
SELECT FROM information_schema.tables
|
||||||
WHERE table_schema = 'public'
|
WHERE table_schema = 'public'
|
||||||
AND table_name = 'jokesbapak2'
|
AND table_name = 'jokesbapak2'
|
||||||
|
@ -94,7 +94,7 @@ func setupJokesTable(db *pgxpool.Pool) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = conn.Exec(context.Background(), sql)
|
_, err = conn.Exec(ctx, sql)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -103,8 +103,8 @@ func setupJokesTable(db *pgxpool.Pool) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupSubmissionTable(db *pgxpool.Pool) error {
|
func setupSubmissionTable(db *pgxpool.Pool, ctx context.Context) error {
|
||||||
conn, err := db.Acquire(context.Background())
|
conn, err := db.Acquire(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ func setupSubmissionTable(db *pgxpool.Pool) error {
|
||||||
|
|
||||||
//Check if table exists
|
//Check if table exists
|
||||||
var tableSubmissionExists bool
|
var tableSubmissionExists bool
|
||||||
err = conn.QueryRow(context.Background(), `SELECT EXISTS (
|
err = conn.QueryRow(ctx, `SELECT EXISTS (
|
||||||
SELECT FROM information_schema.tables
|
SELECT FROM information_schema.tables
|
||||||
WHERE table_schema = 'public'
|
WHERE table_schema = 'public'
|
||||||
AND table_name = 'submission'
|
AND table_name = 'submission'
|
||||||
|
@ -134,7 +134,7 @@ func setupSubmissionTable(db *pgxpool.Pool) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = conn.Exec(context.Background(), sql)
|
_, err = conn.Exec(ctx, sql)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue