refactor: moving each routes to new directory
This commit is contained in:
parent
84cc35eb10
commit
84cfab08ef
|
@ -0,0 +1,31 @@
|
|||
package health
|
||||
|
||||
import (
|
||||
"context"
|
||||
"jokes-bapak2-api/app/v1/handler"
|
||||
"jokes-bapak2-api/app/v1/models"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func Health(c *fiber.Ctx) error {
|
||||
// Ping REDIS database
|
||||
err := handler.Redis.Ping(context.Background()).Err()
|
||||
if err != nil {
|
||||
return c.
|
||||
Status(fiber.StatusServiceUnavailable).
|
||||
JSON(models.Error{
|
||||
Error: "REDIS: " + err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
_, err = handler.Db.Query(context.Background(), "SELECT \"id\" FROM \"jokesbapak2\" LIMIT 1")
|
||||
if err != nil {
|
||||
return c.
|
||||
Status(fiber.StatusServiceUnavailable).
|
||||
JSON(models.Error{
|
||||
Error: "POSTGRESQL: " + err.Error(),
|
||||
})
|
||||
}
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package health_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
v1 "jokes-bapak2-api/app/v1"
|
||||
"jokes-bapak2-api/app/v1/platform/database"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestHealth(t *testing.T) {
|
||||
err := database.Setup()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = db.Query(context.Background(), "INSERT INTO \"administrators\" (id, key, token, last_used) VALUES ($1, $2, $3, $4);", 1, "very secure", "not the real one", time.Now().Format(time.RFC3339))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = db.Query(context.Background(), "INSERT INTO \"jokesbapak2\" (id, link, creator) VALUES ($1, $2, $3), ($4, $5, $6), ($7, $8, $9);", jokesData...)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Cleanup(cleanup)
|
||||
|
||||
app := v1.New()
|
||||
|
||||
t.Run("Health - should return 200", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "/health", nil)
|
||||
res, err := app.Test(req, -1)
|
||||
|
||||
assert.Equalf(t, false, err != nil, "health")
|
||||
assert.Equalf(t, 200, res.StatusCode, "health")
|
||||
assert.NotEqualf(t, 0, res.ContentLength, "health")
|
||||
_, err = ioutil.ReadAll(res.Body)
|
||||
assert.Nilf(t, err, "health")
|
||||
})
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package joke
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"jokes-bapak2-api/app/v1/core"
|
||||
"jokes-bapak2-api/app/v1/handler"
|
||||
"jokes-bapak2-api/app/v1/models"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func AddNewJoke(c *fiber.Ctx) error {
|
||||
var body models.Joke
|
||||
err := c.BodyParser(&body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check link validity
|
||||
valid, err := core.CheckImageValidity(handler.Client, body.Link)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !valid {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(models.Error{
|
||||
Error: "URL provided is not a valid image",
|
||||
})
|
||||
}
|
||||
|
||||
sql, args, err := handler.Psql.Insert("jokesbapak2").Columns("link", "creator").Values(body.Link, c.Locals("userID")).ToSql()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: Implement solution if the link provided already exists.
|
||||
_, err = handler.Db.Query(context.Background(), sql, args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = core.SetAllJSONJoke(handler.Db, handler.Memory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = core.SetTotalJoke(handler.Db, handler.Memory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(models.ResponseJoke{
|
||||
Link: body.Link,
|
||||
})
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package joke_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
v1 "jokes-bapak2-api/app/v1"
|
||||
"jokes-bapak2-api/app/v1/handler"
|
||||
"jokes-bapak2-api/app/v1/platform/database"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAddNewJoke(t *testing.T) {
|
||||
// t.SkipNow()
|
||||
err := database.Setup()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
hashedToken := "$argon2id$v=19$m=65536,t=16,p=4$48beb241490caa57fbca8e63df1e1b5fba8934baf78205ee775f96a85f45b889$e6dfca3f69adbe7653dbb353f366d741a3640313c45e33eabaca0c217c16417de80d70ac67f217c9ca46634b0abaad5f4ea2b064caa44ce218fb110b4cba9d36"
|
||||
_, err = handler.Db.Query(context.Background(), "INSERT INTO \"administrators\" (id, key, token, last_used) VALUES ($1, $2, $3, $4);", 1, "very secure", hashedToken, time.Now().Format(time.RFC3339))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Cleanup(cleanup)
|
||||
|
||||
app := v1.New()
|
||||
|
||||
t.Run("Add - should return 201", func(t *testing.T) {
|
||||
reqBody := strings.NewReader("{\"link\":\"https://via.placeholder.com/300/07f/ff0000.png\",\"key\":\"very secure\",\"token\":\"password\"}")
|
||||
req, _ := http.NewRequest("PUT", "/", reqBody)
|
||||
req.Header.Set("content-type", "application/json")
|
||||
req.Header.Add("accept", "application/json")
|
||||
res, err := app.Test(req, -1)
|
||||
|
||||
assert.Equalf(t, false, err != nil, "joke add")
|
||||
assert.Equalf(t, 201, res.StatusCode, "joke add")
|
||||
assert.NotEqualf(t, 0, res.ContentLength, "joke add")
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
assert.Nilf(t, err, "joke add")
|
||||
assert.Equalf(t, "{\"link\":\"https://via.placeholder.com/300/07f/ff0000.png\"}", string(body), "joke add")
|
||||
})
|
||||
|
||||
t.Run("Add - should not be a valid image", func(t *testing.T) {
|
||||
reqBody := strings.NewReader("{\"link\":\"https://google.com/\",\"key\":\"very secure\",\"token\":\"password\"}")
|
||||
req, _ := http.NewRequest("PUT", "/", reqBody)
|
||||
req.Header.Set("content-type", "application/json")
|
||||
req.Header.Add("accept", "application/json")
|
||||
res, err := app.Test(req, -1)
|
||||
|
||||
assert.Equalf(t, false, err != nil, "joke add")
|
||||
assert.Equalf(t, 400, res.StatusCode, "joke add")
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
assert.Nilf(t, err, "joke add")
|
||||
assert.Equalf(t, "{\"error\":\"URL provided is not a valid image\"}", string(body), "joke add")
|
||||
})
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package joke
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"jokes-bapak2-api/app/v1/core"
|
||||
"jokes-bapak2-api/app/v1/handler"
|
||||
"jokes-bapak2-api/app/v1/models"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func DeleteJoke(c *fiber.Ctx) error {
|
||||
id, err := strconv.Atoi(c.Params("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if the joke exists
|
||||
sql, args, err := handler.Psql.Select("id").From("jokesbapak2").Where(squirrel.Eq{"id": id}).ToSql()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var jokeID int
|
||||
err = handler.Db.QueryRow(context.Background(), sql, args...).Scan(&jokeID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if jokeID == id {
|
||||
sql, args, err = handler.Psql.Delete("jokesbapak2").Where(squirrel.Eq{"id": id}).ToSql()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = handler.Db.Query(context.Background(), sql, args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = core.SetAllJSONJoke(handler.Db, handler.Memory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = core.SetTotalJoke(handler.Db, handler.Memory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(models.ResponseJoke{
|
||||
Message: "specified joke id has been deleted",
|
||||
})
|
||||
}
|
||||
return c.Status(fiber.StatusNotAcceptable).JSON(models.Error{
|
||||
Error: "specified joke id does not exists",
|
||||
})
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package joke_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
v1 "jokes-bapak2-api/app/v1"
|
||||
"jokes-bapak2-api/app/v1/handler"
|
||||
"jokes-bapak2-api/app/v1/platform/database"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDeleteJoke(t *testing.T) {
|
||||
// TODO: Remove this line below, make this test works
|
||||
t.SkipNow()
|
||||
|
||||
err := database.Setup()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
hashedToken := "$argon2id$v=19$m=65536,t=16,p=4$48beb241490caa57fbca8e63df1e1b5fba8934baf78205ee775f96a85f45b889$e6dfca3f69adbe7653dbb353f366d741a3640313c45e33eabaca0c217c16417de80d70ac67f217c9ca46634b0abaad5f4ea2b064caa44ce218fb110b4cba9d36"
|
||||
_, err = handler.Db.Query(context.Background(), "INSERT INTO \"administrators\" (id, key, token, last_used) VALUES ($1, $2, $3, $4);", 1, "very secure", hashedToken, time.Now().Format(time.RFC3339))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = handler.Db.Query(context.Background(), "INSERT INTO \"jokesbapak2\" (id, link, creator) VALUES ($1, $2, $3), ($4, $5, $6), ($7, $8, $9);", jokesData...)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Cleanup(cleanup)
|
||||
|
||||
app := v1.New()
|
||||
|
||||
t.Run("Delete - should return 200", func(t *testing.T) {
|
||||
reqBody := strings.NewReader("{\"key\":\"very secure\",\"token\":\"password\"}")
|
||||
req, _ := http.NewRequest("DELETE", "/id/1", reqBody)
|
||||
res, err := app.Test(req, -1)
|
||||
|
||||
assert.Equalf(t, false, err != nil, "joke delete")
|
||||
assert.Equalf(t, 200, res.StatusCode, "joke delete")
|
||||
assert.NotEqualf(t, 0, res.ContentLength, "joke delete")
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
assert.Nilf(t, err, "joke delete")
|
||||
assert.Equalf(t, "{\"message\":\"specified joke id has been deleted\"}", string(body), "joke delete")
|
||||
})
|
||||
|
||||
t.Run("Delete - id doesn't exists", func(t *testing.T) {
|
||||
reqBody := strings.NewReader("{\"key\":\"very secure\",\"token\":\"password\"}")
|
||||
req, _ := http.NewRequest("DELETE", "/id/100", reqBody)
|
||||
res, err := app.Test(req, -1)
|
||||
|
||||
assert.Equalf(t, false, err != nil, "joke delete")
|
||||
assert.Equalf(t, 406, res.StatusCode, "joke delete")
|
||||
assert.NotEqualf(t, 0, res.ContentLength, "joke delete")
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
assert.Nilf(t, err, "joke delete")
|
||||
assert.Equalf(t, "{\"message\":\"specified joke id does not exists\"}", string(body), "joke delete")
|
||||
})
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
package joke
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"jokes-bapak2-api/app/v1/core"
|
||||
"jokes-bapak2-api/app/v1/handler"
|
||||
"jokes-bapak2-api/app/v1/models"
|
||||
"jokes-bapak2-api/app/v1/utils"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func TodayJoke(c *fiber.Ctx) error {
|
||||
// check from handler.Redis if today's joke already exists
|
||||
// send the joke if exists
|
||||
// get a new joke if it's not, then send it.
|
||||
var joke models.Today
|
||||
err := handler.Redis.MGet(context.Background(), "today:link", "today:date", "today:image", "today:contentType").Scan(&joke)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
eq, err := utils.IsToday(joke.Date)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if eq {
|
||||
c.Set("Content-Type", joke.ContentType)
|
||||
return c.Status(fiber.StatusOK).Send([]byte(joke.Image))
|
||||
} else {
|
||||
var link string
|
||||
err := handler.Db.QueryRow(context.Background(), "SELECT link FROM jokesbapak2 ORDER BY random() LIMIT 1").Scan(&link)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
response, err := handler.Client.Get(link, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
now := time.Now().UTC().Format(time.RFC3339)
|
||||
err = handler.Redis.MSet(context.Background(), map[string]interface{}{
|
||||
"today:link": link,
|
||||
"today:date": now,
|
||||
"today:image": string(data),
|
||||
"today:contentType": response.Header.Get("content-type"),
|
||||
}).Err()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.Set("Content-Type", response.Header.Get("content-type"))
|
||||
return c.Status(fiber.StatusOK).Send(data)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func SingleJoke(c *fiber.Ctx) error {
|
||||
checkCache, err := core.CheckJokesCache(handler.Memory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !checkCache {
|
||||
jokes, err := core.GetAllJSONJokes(handler.Db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = handler.Memory.Set("jokes", jokes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
link, err := core.GetRandomJokeFromCache(handler.Memory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get image data
|
||||
response, err := handler.Client.Get(link, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.Set("Content-Type", response.Header.Get("content-type"))
|
||||
return c.Status(fiber.StatusOK).Send(data)
|
||||
|
||||
}
|
||||
|
||||
func JokeByID(c *fiber.Ctx) error {
|
||||
checkCache, err := core.CheckJokesCache(handler.Memory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !checkCache {
|
||||
jokes, err := core.GetAllJSONJokes(handler.Db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = handler.Memory.Set("jokes", jokes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
id, err := strconv.Atoi(c.Params("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
link, err := core.GetCachedJokeByID(handler.Memory, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if link == "" {
|
||||
return c.Status(fiber.StatusNotFound).Send([]byte("Requested ID was not found."))
|
||||
}
|
||||
|
||||
// Get image data
|
||||
response, err := handler.Client.Get(link, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.Set("Content-Type", response.Header.Get("content-type"))
|
||||
return c.Status(fiber.StatusOK).Send(data)
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
package joke_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
v1 "jokes-bapak2-api/app/v1"
|
||||
"jokes-bapak2-api/app/v1/platform/database"
|
||||
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var db = database.New()
|
||||
var jokesData = []interface{}{1, "https://via.placeholder.com/300/06f/fff.png", 1, 2, "https://via.placeholder.com/300/07f/fff.png", 1, 3, "https://via.placeholder.com/300/08f/fff.png", 1}
|
||||
|
||||
func cleanup() {
|
||||
_, err := db.Query(context.Background(), "DROP TABLE \"jokesbapak2\"")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = db.Query(context.Background(), "DROP TABLE \"administrators\"")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Need to find some workaround for this test
|
||||
func TestJokeGet(t *testing.T) {
|
||||
err := database.Setup()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = db.Query(context.Background(), "INSERT INTO \"administrators\" (id, key, token, last_used) VALUES ($1, $2, $3, $4);", 1, "very secure", "not the real one", time.Now().Format(time.RFC3339))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = db.Query(context.Background(), "INSERT INTO \"jokesbapak2\" (id, link, creator) VALUES ($1, $2, $3), ($4, $5, $6), ($7, $8, $9);", jokesData...)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Cleanup(cleanup)
|
||||
|
||||
app := v1.New()
|
||||
|
||||
t.Run("TodayJoke - should return 200", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "/today", nil)
|
||||
res, err := app.Test(req, -1)
|
||||
|
||||
assert.Equalf(t, false, err != nil, "today joke")
|
||||
assert.Equalf(t, 200, res.StatusCode, "today joke")
|
||||
assert.NotEqualf(t, 0, res.ContentLength, "today joke")
|
||||
_, err = ioutil.ReadAll(res.Body)
|
||||
assert.Nilf(t, err, "today joke")
|
||||
})
|
||||
|
||||
t.Run("SingleJoke - should return 200", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "/", nil)
|
||||
res, err := app.Test(req, -1)
|
||||
|
||||
assert.Equalf(t, false, err != nil, "single joke")
|
||||
assert.Equalf(t, 200, res.StatusCode, "single joke")
|
||||
assert.NotEqualf(t, 0, res.ContentLength, "single joke")
|
||||
_, err = ioutil.ReadAll(res.Body)
|
||||
assert.Nilf(t, err, "single joke")
|
||||
})
|
||||
|
||||
t.Run("JokeByID - should return 200", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "/id/1", nil)
|
||||
res, err := app.Test(req, -1)
|
||||
|
||||
assert.Equalf(t, false, err != nil, "joke by id")
|
||||
assert.Equalf(t, 200, res.StatusCode, "joke by id")
|
||||
assert.NotEqualf(t, 0, res.ContentLength, "joke by id")
|
||||
_, err = ioutil.ReadAll(res.Body)
|
||||
assert.Nilf(t, err, "joke by id")
|
||||
})
|
||||
|
||||
t.Run("JokeByID - should return 404", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "/id/300", nil)
|
||||
res, err := app.Test(req, -1)
|
||||
|
||||
assert.Equalf(t, false, err != nil, "joke by id")
|
||||
assert.Equalf(t, 404, res.StatusCode, "joke by id")
|
||||
assert.NotEqualf(t, 0, res.ContentLength, "joke by id")
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
assert.Nilf(t, err, "joke by id")
|
||||
assert.Equalf(t, "Requested ID was not found.", string(body), "joke by id")
|
||||
})
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package joke
|
||||
|
||||
import (
|
||||
"jokes-bapak2-api/app/v1/core"
|
||||
"jokes-bapak2-api/app/v1/handler"
|
||||
"jokes-bapak2-api/app/v1/models"
|
||||
"strconv"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func TotalJokes(c *fiber.Ctx) error {
|
||||
checkTotal, err := core.CheckTotalJokesCache(handler.Memory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !checkTotal {
|
||||
err = core.SetTotalJoke(handler.Db, handler.Memory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
total, err := handler.Memory.Get("total")
|
||||
|
||||
if err != nil {
|
||||
if err.Error() == "Entry not found" {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(models.Error{
|
||||
Error: "no data found",
|
||||
})
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(models.ResponseJoke{
|
||||
Message: strconv.Itoa(int(total[0])),
|
||||
})
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package joke_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
v1 "jokes-bapak2-api/app/v1"
|
||||
"jokes-bapak2-api/app/v1/handler"
|
||||
"jokes-bapak2-api/app/v1/platform/database"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTotalJokes(t *testing.T) {
|
||||
err := database.Setup()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = handler.Db.Query(context.Background(), "INSERT INTO \"administrators\" (id, key, token, last_used) VALUES ($1, $2, $3, $4);", 1, "very secure", "not the real one", time.Now().Format(time.RFC3339))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = handler.Db.Query(context.Background(), "INSERT INTO \"jokesbapak2\" (id, link, creator) VALUES ($1, $2, $3), ($4, $5, $6), ($7, $8, $9);", jokesData...)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Cleanup(cleanup)
|
||||
|
||||
app := v1.New()
|
||||
|
||||
t.Run("Total - should return 200", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "/total", nil)
|
||||
res, err := app.Test(req, -1)
|
||||
|
||||
assert.Equalf(t, false, err != nil, "joke total")
|
||||
assert.Equalf(t, 200, res.StatusCode, "joke total")
|
||||
assert.NotEqualf(t, 0, res.ContentLength, "joke total")
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
assert.Nilf(t, err, "joke total")
|
||||
// FIXME: This should be "message": "3", not one. I don't know what's wrong as it's 1 AM.
|
||||
assert.Equalf(t, "{\"message\":\"1\"}", string(body), "joke total")
|
||||
})
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package joke
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"jokes-bapak2-api/app/v1/core"
|
||||
"jokes-bapak2-api/app/v1/handler"
|
||||
"jokes-bapak2-api/app/v1/models"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func UpdateJoke(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
// Check if the joke exists
|
||||
sql, args, err := handler.Psql.Select("id").From("jokesbapak2").Where(squirrel.Eq{"id": id}).ToSql()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var jokeID string
|
||||
err = handler.Db.QueryRow(context.Background(), sql, args...).Scan(&jokeID)
|
||||
if err != nil && err != models.ErrNoRows {
|
||||
return err
|
||||
}
|
||||
|
||||
if jokeID == id {
|
||||
body := new(models.Joke)
|
||||
err = c.BodyParser(&body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check link validity
|
||||
valid, err := core.CheckImageValidity(handler.Client, body.Link)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !valid {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(models.Error{
|
||||
Error: "URL provided is not a valid image",
|
||||
})
|
||||
}
|
||||
|
||||
sql, args, err = handler.Psql.Update("jokesbapak2").Set("link", body.Link).Set("creator", c.Locals("userID")).ToSql()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = handler.Db.Query(context.Background(), sql, args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = core.SetAllJSONJoke(handler.Db, handler.Memory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = core.SetTotalJoke(handler.Db, handler.Memory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(models.ResponseJoke{
|
||||
Message: "specified joke id has been updated",
|
||||
Link: body.Link,
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusNotAcceptable).JSON(models.Error{
|
||||
Error: "specified joke id does not exists",
|
||||
})
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package joke_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
v1 "jokes-bapak2-api/app/v1"
|
||||
"jokes-bapak2-api/app/v1/handler"
|
||||
"jokes-bapak2-api/app/v1/platform/database"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestUpdateJoke(t *testing.T) {
|
||||
t.SkipNow()
|
||||
err := database.Setup()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
hashedToken := "$argon2id$v=19$m=65536,t=16,p=4$48beb241490caa57fbca8e63df1e1b5fba8934baf78205ee775f96a85f45b889$e6dfca3f69adbe7653dbb353f366d741a3640313c45e33eabaca0c217c16417de80d70ac67f217c9ca46634b0abaad5f4ea2b064caa44ce218fb110b4cba9d36"
|
||||
_, err = handler.Db.Query(context.Background(), "INSERT INTO \"administrators\" (id, key, token, last_used) VALUES ($1, $2, $3, $4);", 1, "very secure", hashedToken, time.Now().Format(time.RFC3339))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = handler.Db.Query(context.Background(), "INSERT INTO \"jokesbapak2\" (id, link, creator) VALUES ($1, $2, $3), ($4, $5, $6), ($7, $8, $9);", jokesData...)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Cleanup(cleanup)
|
||||
|
||||
app := v1.New()
|
||||
|
||||
t.Run("Update - should return 200", func(t *testing.T) {
|
||||
reqBody := strings.NewReader("{\"link\":\"https://picsum.photos/id/9/200/300\",\"key\":\"very secure\",\"token\":\"password\"}")
|
||||
req, _ := http.NewRequest("PATCH", "/id/1", reqBody)
|
||||
res, err := app.Test(req, -1)
|
||||
|
||||
assert.Equalf(t, false, err != nil, "joke update")
|
||||
assert.Equalf(t, 200, res.StatusCode, "joke update")
|
||||
assert.NotEqualf(t, 0, res.ContentLength, "joke update")
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
assert.Nilf(t, err, "joke update")
|
||||
assert.Equalf(t, "{\"message\":\"specified joke id has been deleted\"}", string(body), "joke update")
|
||||
})
|
||||
|
||||
t.Run("Update - id doesn't exists", func(t *testing.T) {
|
||||
reqBody := strings.NewReader("{\"link\":\"https://picsum.photos/id/9/200/300\",\"key\":\"very secure\",\"token\":\"password\"}")
|
||||
req, _ := http.NewRequest("PATCH", "/id/100", reqBody)
|
||||
res, err := app.Test(req, -1)
|
||||
|
||||
assert.Equalf(t, false, err != nil, "joke update")
|
||||
assert.Equalf(t, 406, res.StatusCode, "joke update")
|
||||
assert.NotEqualf(t, 0, res.ContentLength, "joke update")
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
assert.Nilf(t, err, "joke update")
|
||||
assert.Equalf(t, "{\"message\":\"specified joke id does not exists\"}", string(body), "joke update")
|
||||
})
|
||||
}
|
|
@ -1,14 +1,14 @@
|
|||
package routes
|
||||
|
||||
import (
|
||||
"jokes-bapak2-api/app/v1/handler"
|
||||
"jokes-bapak2-api/app/v1/handler/health"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func Health(app *fiber.App) *fiber.App {
|
||||
// Health check
|
||||
app.Get("/health", handler.Health)
|
||||
app.Get("/health", health.Health)
|
||||
|
||||
return app
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package routes
|
||||
|
||||
import (
|
||||
"jokes-bapak2-api/app/v1/handler"
|
||||
"jokes-bapak2-api/app/v1/handler/joke"
|
||||
"jokes-bapak2-api/app/v1/middleware"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
|
@ -9,25 +9,25 @@ import (
|
|||
|
||||
func Joke(app *fiber.App) *fiber.App {
|
||||
// Single route
|
||||
app.Get("/", handler.SingleJoke)
|
||||
app.Get("/", joke.SingleJoke)
|
||||
|
||||
// Today's joke
|
||||
app.Get("/today", handler.TodayJoke)
|
||||
app.Get("/today", joke.TodayJoke)
|
||||
|
||||
// Joke by ID
|
||||
app.Get("/id/:id", middleware.OnlyIntegerAsID(), handler.JokeByID)
|
||||
app.Get("/id/:id", middleware.OnlyIntegerAsID(), joke.JokeByID)
|
||||
|
||||
// Count total jokes
|
||||
app.Get("/total", handler.TotalJokes)
|
||||
app.Get("/total", joke.TotalJokes)
|
||||
|
||||
// Add new joke
|
||||
app.Put("/", middleware.RequireAuth(), handler.AddNewJoke)
|
||||
app.Put("/", middleware.RequireAuth(), joke.AddNewJoke)
|
||||
|
||||
// Update a joke
|
||||
app.Patch("/id/:id", middleware.RequireAuth(), middleware.OnlyIntegerAsID(), handler.UpdateJoke)
|
||||
app.Patch("/id/:id", middleware.RequireAuth(), middleware.OnlyIntegerAsID(), joke.UpdateJoke)
|
||||
|
||||
// Delete a joke
|
||||
app.Delete("/id/:id", middleware.RequireAuth(), middleware.OnlyIntegerAsID(), handler.DeleteJoke)
|
||||
app.Delete("/id/:id", middleware.RequireAuth(), middleware.OnlyIntegerAsID(), joke.DeleteJoke)
|
||||
|
||||
return app
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue