fixed image upload, patched up tests.bash

This commit is contained in:
Steve White 2024-10-06 18:02:38 -05:00
parent 7d853c26f1
commit 94115067c4
6 changed files with 125 additions and 5 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
data/boxes.db
images/*

View File

@ -1,6 +1,6 @@
database_path: "data/boxes.db"
test_database_path: "data/test_database.db"
jwt_secret: "super_secret_key"
image_storage_dir: "images/"
image_storage_dir: "./images/"
listening_port: 8080
log_file: "boxes.log"

8
db.go
View File

@ -16,10 +16,10 @@ type Box struct {
// Define the Item model
type Item struct {
gorm.Model
Name string `json:"name"`
Description string `json:"description"`
BoxID uint `json:"box_id"`
ImagePath *string `json:"image_path"`
Name string `json:"name"`
Description string `json:"description"`
BoxID uint `json:"box_id"`
ImagePath string `json:"image_path"`
}
// Define the User model

View File

@ -4,7 +4,9 @@ import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
@ -149,6 +151,75 @@ func CreateItemHandler(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(response)
}
// UploadItemImageHandler handles the image upload for an item
func UploadItemImageHandler(w http.ResponseWriter, r *http.Request) {
// Extract the authenticated user from context (assuming this is how AuthMiddleware works)
user, ok := r.Context().Value(userKey).(string)
if !ok || user == "" {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
// Parse the form data, 10MB limit for file uploads
err := r.ParseMultipartForm(10 << 20)
if err != nil {
http.Error(w, "Unable to parse form", http.StatusBadRequest)
return
}
// Get the file from the form data
file, handler, err := r.FormFile("image")
if err != nil {
http.Error(w, "Error retrieving the file", http.StatusBadRequest)
return
}
defer file.Close()
// Get item ID from the URL
vars := mux.Vars(r)
itemID := vars["id"]
// Validate that the item exists (fetch from DB using itemID)
var item Item
if err := db.First(&item, itemID).Error; err != nil {
http.Error(w, "Item not found", http.StatusNotFound)
return
}
// Save the uploaded file locally or to a storage service
// Ensure the directory exists
if err := os.MkdirAll(config.ImageStorageDir, 0755); err != nil {
http.Error(w, "Unable to create image storage directory", http.StatusInternalServerError)
return
}
filePath := fmt.Sprintf("%s/%s", config.ImageStorageDir, handler.Filename)
outFile, err := os.Create(filePath)
if err != nil {
http.Error(w, "Unable to save the file", http.StatusInternalServerError)
return
}
defer outFile.Close()
// Copy the uploaded file to the destination
_, err = io.Copy(outFile, file)
if err != nil {
http.Error(w, "Unable to save the file", http.StatusInternalServerError)
return
}
// Update the item record in the database with the image path
item.ImagePath = filePath
if err := db.Save(&item).Error; err != nil {
http.Error(w, "Unable to save image path in database", http.StatusInternalServerError)
return
}
// Return the image path in the response
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{"imagePath": filePath})
}
// getItemHandler handles the GET /items/{id} endpoint.
func GetItemHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)

View File

@ -51,6 +51,10 @@ func main() {
router.Handle("/items/{id}/items", AuthMiddleware(http.HandlerFunc(GetItemsInBoxHandler))).Methods("GET", "OPTIONS")
router.Handle("/items/{id}", AuthMiddleware(http.HandlerFunc(UpdateItemHandler))).Methods("PUT", "OPTIONS")
router.Handle("/items/{id}", AuthMiddleware(http.HandlerFunc(DeleteItemHandler))).Methods("DELETE", "OPTIONS")
// Add a new route for uploading an image with AuthMiddleware
router.HandleFunc("/items/{id}/upload", UploadItemImageHandler).
Methods("POST").
Handler(AuthMiddleware(http.HandlerFunc(UploadItemImageHandler)))
// Apply CORS middleware
c := cors.New(cors.Options{

View File

@ -110,6 +110,48 @@ else
echo "$response"
fi
# 11. Create Image and Assign to Item (Assuming an item with ID $ITEM_ID exists)
echo
echo
echo "Testing /items/$ITEM_ID/upload (POST)..."
# Get a new JWT token
TOKEN=$(curl -s -X POST -H "Content-Type: application/json" \
-d "{\"username\":\"$USERNAME\", \"password\":\"$PASSWORD\"}" \
"$API_BASE_URL/login" | jq -r '.token')
# Create a temporary image file
IMAGE_FILE=$(mktemp /tmp/test_image.XXXXXX)
echo "Test Image Content" > "$IMAGE_FILE"
echo "Token is $TOKEN"
# Make the request using curl to upload the image
response=$(curl -s -w "%{http_code}" -X POST \
-H "Authorization: Bearer $(echo "$TOKEN")" \
-F "image=@$IMAGE_FILE" \
"$API_BASE_URL/items/$ITEM_ID/upload")
echo $response
# Separate the body and the HTTP status code
http_status=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
# Remove the temporary image file
rm "$IMAGE_FILE"
# Check if the HTTP status is 200 (OK) and the imagePath is returned
if [[ "$http_status" == "200" && $(echo "$body" | jq -r '.imagePath') != "null" ]]; then
echo -e "\033[32m /items/$ITEM_ID/upload (POST): PASS\033[0m" # Green PASS
IMAGE_PATH=$(echo "$body" | jq -r '.imagePath')
echo "Image Path: $IMAGE_PATH"
else
echo -e "\033[31m /items/$ITEM_ID/upload (POST): FAIL (Invalid response or no imagePath)\033[0m" # Red FAIL
echo "Response: $response"
fi
# 6. Get Items
echo
echo "Testing /items (GET)..."
@ -130,6 +172,8 @@ echo
echo "Testing /items/{id} (GET)..."
response=$(authenticated_request "GET" "/items/$ITEM_ID" "")
echo $response | jq .
# Check if the request was successful AND if the response ID matches $ITEM_ID
if [[ $? -eq 0 ]] && [[ $(echo "$response" | jq -r '.ID') == "$ITEM_ID" ]]; then
echo -e "\033[32m /items/{id} (GET): PASS\033[0m" # Green PASS