Removes api handlers
This commit is contained in:
parent
dc1cd46815
commit
e903e9e3a4
6 changed files with 0 additions and 281 deletions
|
|
@ -1,34 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
"errors"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
|
||||||
"github.com/gofiber/fiber/v2/middleware/keyauth"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Setup(app *fiber.App, db *sql.DB) error {
|
|
||||||
apiKey := os.Getenv("API_KEY")
|
|
||||||
|
|
||||||
if apiKey == "" {
|
|
||||||
return errors.New("Could not read API_KEY from ENV file.")
|
|
||||||
}
|
|
||||||
|
|
||||||
api := app.Group("/api", keyauth.New(keyauth.Config{
|
|
||||||
SuccessHandler: successHandler,
|
|
||||||
ErrorHandler: errHandler,
|
|
||||||
KeyLookup: "header:x-api-key",
|
|
||||||
ContextKey: "apiKey",
|
|
||||||
Validator: apiKeyValidator(apiKey),
|
|
||||||
}))
|
|
||||||
|
|
||||||
apiHandler := NewHandler(db)
|
|
||||||
|
|
||||||
v1 := api.Group("/v1")
|
|
||||||
v1.Post("/users", apiHandler.createUser)
|
|
||||||
v1.Post("/users/:userID/feeds", apiHandler.createFeed)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/sha256"
|
|
||||||
"crypto/subtle"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
|
||||||
"github.com/gofiber/fiber/v2/middleware/keyauth"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
apiKey = "willbechanged"
|
|
||||||
protectedURLs = []*regexp.Regexp{
|
|
||||||
regexp.MustCompile("^/api$"),
|
|
||||||
}
|
|
||||||
errForbidden = &fiber.Error{
|
|
||||||
Code: 403,
|
|
||||||
Message: "API Key is missing or invalid",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func apiKeyValidator(apiKey string) func(*fiber.Ctx, string) (bool, error) {
|
|
||||||
return func(_ *fiber.Ctx, key string) (bool, error) {
|
|
||||||
hashedAPIKey := sha256.Sum256([]byte(apiKey))
|
|
||||||
hashedKey := sha256.Sum256([]byte(key))
|
|
||||||
|
|
||||||
if subtle.ConstantTimeCompare(hashedAPIKey[:], hashedKey[:]) == 1 {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, keyauth.ErrMissingOrMalformedAPIKey
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func protectedRoutesFilter(ctx *fiber.Ctx) bool {
|
|
||||||
originalURL := strings.ToLower(ctx.OriginalURL())
|
|
||||||
|
|
||||||
for _, pattern := range protectedURLs {
|
|
||||||
if pattern.MatchString(originalURL) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func successHandler(ctx *fiber.Ctx) error {
|
|
||||||
return ctx.Next()
|
|
||||||
}
|
|
||||||
|
|
||||||
func errHandler(ctx *fiber.Ctx, err error) error {
|
|
||||||
ctx.Status(fiber.StatusForbidden)
|
|
||||||
|
|
||||||
return ctx.JSON(errForbidden)
|
|
||||||
}
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"freed/internal/model"
|
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
|
||||||
"github.com/gofiber/fiber/v2/log"
|
|
||||||
"github.com/mattn/go-sqlite3"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (h *Handler) createFeed(c *fiber.Ctx) error {
|
|
||||||
userID := c.Params("userID")
|
|
||||||
feed := new(model.Feed)
|
|
||||||
|
|
||||||
if parseErr := c.BodyParser(feed); parseErr != nil {
|
|
||||||
log.Warn(parseErr)
|
|
||||||
return defaultUserError
|
|
||||||
}
|
|
||||||
|
|
||||||
validationErr := ValidateModel(feed)
|
|
||||||
|
|
||||||
if validationErr != nil {
|
|
||||||
return fiber.NewError(fiber.ErrInternalServerError.Code, validationErr.Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
userExists := h.userExists(userID)
|
|
||||||
fmt.Printf("exists? %v", userExists)
|
|
||||||
|
|
||||||
if h.userExists(userID) == false {
|
|
||||||
return fiber.NewError(fiber.ErrInternalServerError.Code, "No existing user found, check user id path param.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Get name from feed
|
|
||||||
// TODO: Get type from feed
|
|
||||||
// TODO: Either schedule or request items from feed immediately
|
|
||||||
|
|
||||||
sqlResult, insertErr := h.db.Exec("INSERT INTO feed (userId, name, url) VALUES (?, ?, ?)", userID, feed.Url, feed.Url)
|
|
||||||
|
|
||||||
if sqliteErr, ok := insertErr.(sqlite3.Error); ok {
|
|
||||||
log.Warn(insertErr)
|
|
||||||
|
|
||||||
if sqliteErr.ExtendedCode == sqlite3.ErrConstraintUnique {
|
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Feed with url already exists")
|
|
||||||
}
|
|
||||||
|
|
||||||
return fiber.NewError(fiber.ErrInternalServerError.Code, "Could not create feed")
|
|
||||||
}
|
|
||||||
|
|
||||||
feedID, idErr := sqlResult.LastInsertId()
|
|
||||||
|
|
||||||
if idErr != nil {
|
|
||||||
return fiber.NewError(fiber.ErrInternalServerError.Code, "Created feed, but could not retrieve its ID, check database.")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.SendStatus(201)
|
|
||||||
return c.JSON(&fiber.Map{"id": feedID})
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Handler struct {
|
|
||||||
db *sql.DB
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewHandler(db *sql.DB) *Handler {
|
|
||||||
return &Handler{db: db}
|
|
||||||
}
|
|
||||||
|
|
@ -1,80 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"freed/internal/model"
|
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
|
||||||
"github.com/gofiber/fiber/v2/log"
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/mattn/go-sqlite3"
|
|
||||||
)
|
|
||||||
|
|
||||||
var defaultUserError = fiber.NewError(fiber.ErrInternalServerError.Code, "Could not create user")
|
|
||||||
|
|
||||||
func (h *Handler) createUser(c *fiber.Ctx) error {
|
|
||||||
user := new(model.User)
|
|
||||||
|
|
||||||
userId, idErr := uuid.NewRandom()
|
|
||||||
|
|
||||||
if idErr != nil {
|
|
||||||
log.Warn(idErr)
|
|
||||||
return defaultUserError
|
|
||||||
}
|
|
||||||
|
|
||||||
user.ID = userId.String()
|
|
||||||
|
|
||||||
if parseErr := c.BodyParser(user); parseErr != nil {
|
|
||||||
log.Warn(parseErr)
|
|
||||||
return defaultUserError
|
|
||||||
}
|
|
||||||
|
|
||||||
validationErr := ValidateModel(user)
|
|
||||||
|
|
||||||
if validationErr != nil {
|
|
||||||
return fiber.NewError(fiber.ErrInternalServerError.Code, validationErr.Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, insertErr := h.db.Exec("INSERT INTO user (id, first_name, email) VALUES (?, ?, ?)", user.ID, user.FirstName, user.Email)
|
|
||||||
|
|
||||||
if sqliteErr, ok := insertErr.(sqlite3.Error); ok {
|
|
||||||
log.Warn(insertErr)
|
|
||||||
|
|
||||||
if sqliteErr.ExtendedCode == sqlite3.ErrConstraintUnique {
|
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "User with email already exists")
|
|
||||||
}
|
|
||||||
|
|
||||||
return defaultUserError
|
|
||||||
}
|
|
||||||
|
|
||||||
c.SendStatus(201)
|
|
||||||
return c.JSON(&fiber.Map{"userId": userId})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Handler) getUserByID(id string) (*model.User, error) {
|
|
||||||
var user *model.User
|
|
||||||
|
|
||||||
if err := h.db.QueryRow("SELECT * FROM user WHERE id = ?", id).Scan(&user); err != nil {
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
notFoundErrMessage := fmt.Sprintf("No user found with ID: %s", id)
|
|
||||||
return nil, errors.New(notFoundErrMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
unexpectedErrMessage := fmt.Sprintf("Unexpected error occured, could not get user with ID: %s", id)
|
|
||||||
return nil, errors.New(unexpectedErrMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
return user, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Handler) userExists(id string) bool {
|
|
||||||
var userID string
|
|
||||||
|
|
||||||
if err := h.db.QueryRow("SELECT id FROM user WHERE id = ?", id).Scan(&userID); err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"freed/internal/model"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10"
|
|
||||||
"github.com/gofiber/fiber/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ModelConstraint interface {
|
|
||||||
*model.User | *model.Feed
|
|
||||||
}
|
|
||||||
|
|
||||||
type ValidationError struct {
|
|
||||||
FailedField string
|
|
||||||
Tag string
|
|
||||||
Value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func ValidateModel[T ModelConstraint](s T) *fiber.Error {
|
|
||||||
var errorMessages []string
|
|
||||||
validate := validator.New()
|
|
||||||
err := validate.Struct(s)
|
|
||||||
|
|
||||||
fmt.Printf("%#v", err)
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, err := range err.(validator.ValidationErrors) {
|
|
||||||
err := fmt.Sprintf("Field %s is invalid, reason: %s", err.StructNamespace(), err.Tag())
|
|
||||||
|
|
||||||
errorMessages = append(errorMessages, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fiber.NewError(fiber.StatusBadRequest, strings.Join(errorMessages, ". "))
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue