refactored by AI to be clearer and easier to support. Seems to work.
This commit is contained in:
parent
76a03cda57
commit
54b412a3fe
|
@ -3,3 +3,4 @@ data/*
|
||||||
images/*
|
images/*
|
||||||
.DS_Store
|
.DS_Store
|
||||||
build/*
|
build/*
|
||||||
|
boxes-api
|
||||||
|
|
12
admin.go
12
admin.go
|
@ -71,7 +71,7 @@ func BackupDatabaseHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
// ...
|
// ...
|
||||||
fmt.Println("BackupDatabaseHandler called")
|
fmt.Println("BackupDatabaseHandler called")
|
||||||
// Open the database file using the path from the config
|
// Open the database file using the path from the config
|
||||||
file, err := os.Open(config.DatabasePath)
|
file, err := os.Open(*DatabasePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to open database file", http.StatusInternalServerError)
|
http.Error(w, "Failed to open database file", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
@ -122,13 +122,13 @@ func RestoreDatabaseHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
func createDatabaseBackup() error {
|
func createDatabaseBackup() error {
|
||||||
// Create a backup of the existing database
|
// Create a backup of the existing database
|
||||||
src, err := os.Open(config.DatabasePath)
|
src, err := os.Open(*DatabasePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer src.Close()
|
defer src.Close()
|
||||||
|
|
||||||
dst, err := os.Create(config.DatabasePath + ".bak")
|
dst, err := os.Create(*DatabasePath + ".bak")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,7 @@ func saveNewDatabase(r *http.Request) error {
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
dst, err := os.Create(config.DatabasePath)
|
dst, err := os.Create(*DatabasePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ func saveNewDatabase(r *http.Request) error {
|
||||||
|
|
||||||
func validateNewDatabase() error {
|
func validateNewDatabase() error {
|
||||||
// Validate the new database is properly initialized
|
// Validate the new database is properly initialized
|
||||||
db, err := ConnectDB(config.DatabasePath)
|
db, err := ConnectDB(*DatabasePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ func validateNewDatabase() error {
|
||||||
|
|
||||||
func switchToNewDatabase() error {
|
func switchToNewDatabase() error {
|
||||||
// Switch to the new database app-wide
|
// Switch to the new database app-wide
|
||||||
db, err := ConnectDB(config.DatabasePath)
|
db, err := ConnectDB(*DatabasePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ func LoadConfig(configPath string) (*Config, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.AllowedOrigins == "" {
|
if config.AllowedOrigins == "" {
|
||||||
config.AllowedOrigins = "http://localhost:3000"
|
config.AllowedOrigins = "http://localhost:8080"
|
||||||
}
|
}
|
||||||
|
|
||||||
return &config, nil
|
return &config, nil
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
database_path: "data/boxes.db"
|
database_path: "/app/data/boxes.db"
|
||||||
test_database_path: "data/test_database.db"
|
test_database_path: "/app/data/test_database.db"
|
||||||
jwt_secret: "super_secret_key"
|
jwt_secret: "super_secret_key"
|
||||||
image_storage_dir: "images"
|
image_storage_dir: "/app/images"
|
||||||
listening_port: 8080
|
listening_port: 8080
|
||||||
log_file: "boxes.log"
|
log_file: "boxes.log"
|
||||||
static_files_dir: "/app/build/"
|
static_files_dir: "/app/build/"
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
database_path: "data/boxes.db"
|
database_path: "./data/boxes.db"
|
||||||
test_database_path: "data/test_database.db"
|
test_database_path: "./data/test_database.db"
|
||||||
jwt_secret: "super_secret_key"
|
jwt_secret: "super_secret_key"
|
||||||
image_storage_dir: "images/"
|
image_storage_dir: "./images/"
|
||||||
listening_port: 8080
|
listening_port: 8080
|
||||||
log_file: "boxes.log"
|
log_file: "boxes.log"
|
||||||
static_files_dir: "build/"
|
static_files_dir: "./build/"
|
||||||
allowed_origins: "*"
|
allowed_origins: "*"
|
||||||
|
|
31
handlers.go
31
handlers.go
|
@ -32,11 +32,32 @@ type LoginResponse struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
fmt.Printf("handlers.go init: config = %+v", config)
|
||||||
|
}
|
||||||
|
|
||||||
// loginHandler handles the /login endpoint.
|
// loginHandler handles the /login endpoint.
|
||||||
// LoginHandler handles the /login endpoint.
|
// LoginHandler handles the /login endpoint.
|
||||||
func LoginHandler(w http.ResponseWriter, r *http.Request) {
|
func LoginHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
var req LoginRequest
|
var req LoginRequest
|
||||||
fmt.Println(db, config)
|
fmt.Println("db is ", db)
|
||||||
|
//fmt.Println("config is ", config)
|
||||||
|
if db == nil {
|
||||||
|
fmt.Println("DB is nil")
|
||||||
|
http.Error(w, "Database not initialized", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println("DB is not nil")
|
||||||
|
|
||||||
|
//if config == nil {
|
||||||
|
//fmt.Println("Config is nil in LoginHandler")
|
||||||
|
//h//ttp.Error(w, "Configuration not loaded", http.StatusInternalServerError)
|
||||||
|
//return
|
||||||
|
//}
|
||||||
|
//fmt.Println("Config is not nil")
|
||||||
|
|
||||||
|
fmt.Printf("DB: %+v\n", db)
|
||||||
|
//fmt.Printf("Config: %+v\n", config)
|
||||||
fmt.Println("LoginHandler called")
|
fmt.Println("LoginHandler called")
|
||||||
err := json.NewDecoder(r.Body).Decode(&req)
|
err := json.NewDecoder(r.Body).Decode(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -65,7 +86,7 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
"exp": time.Now().Add(time.Hour * 24).Unix(), // Token expires in 24 hours
|
"exp": time.Now().Add(time.Hour * 24).Unix(), // Token expires in 24 hours
|
||||||
})
|
})
|
||||||
|
|
||||||
tokenString, err := token.SignedString([]byte(config.JWTSecret))
|
tokenString, err := token.SignedString(*JWTSecret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to generate token", http.StatusInternalServerError)
|
http.Error(w, "Failed to generate token", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
@ -213,12 +234,12 @@ func UploadItemImageHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
// Save the uploaded file locally or to a storage service
|
// Save the uploaded file locally or to a storage service
|
||||||
// Ensure the directory exists
|
// Ensure the directory exists
|
||||||
if err := os.MkdirAll(config.ImageStorageDir, 0755); err != nil {
|
if err := os.MkdirAll(*ImageStorage, 0755); err != nil {
|
||||||
http.Error(w, "Unable to create image storage directory", http.StatusInternalServerError)
|
http.Error(w, "Unable to create image storage directory", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
filePath := fmt.Sprintf("%s/%s", config.ImageStorageDir, handler.Filename)
|
filePath := fmt.Sprintf("%s/%s", *ImageStorage, handler.Filename)
|
||||||
outFile, err := os.Create(filePath)
|
outFile, err := os.Create(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Unable to save the file", http.StatusInternalServerError)
|
http.Error(w, "Unable to save the file", http.StatusInternalServerError)
|
||||||
|
@ -390,7 +411,7 @@ func AuthMiddleware(next http.Handler) http.Handler {
|
||||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||||
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
||||||
}
|
}
|
||||||
return []byte(config.JWTSecret), nil
|
return *JWTSecret, nil
|
||||||
})
|
})
|
||||||
if err != nil || !token.Valid {
|
if err != nil || !token.Valid {
|
||||||
http.Error(w, "Invalid token", http.StatusUnauthorized)
|
http.Error(w, "Invalid token", http.StatusUnauthorized)
|
||||||
|
|
240
main.go
240
main.go
|
@ -5,8 +5,8 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
|
@ -14,56 +14,131 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
db *gorm.DB // Declare db globally
|
db *gorm.DB // Declare db globally
|
||||||
config *Config
|
config *Config
|
||||||
|
JWTSecret *[]byte
|
||||||
|
ImageStorage *string
|
||||||
|
DatabasePath *string
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// Load configuration
|
||||||
configFile := os.Getenv("BOXES_API_CONFIG")
|
config, err := loadAndValidateConfig()
|
||||||
var err error
|
if err != nil {
|
||||||
config, err = LoadConfig(configFile)
|
|
||||||
|
|
||||||
// get the static files directory
|
|
||||||
staticPath := config.StaticFilesDir
|
|
||||||
|
|
||||||
// Add this before setting up the handler
|
|
||||||
if _, err := os.Stat(staticPath); os.IsNotExist(err) {
|
|
||||||
log.Fatalf("Static directory does not exist: %s", staticPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the allowed origins from the ALLOWED_ORIGINS environment variable
|
|
||||||
// If empty, defaults to http://localhost:3000
|
|
||||||
allowedOrigins := config.AllowedOrigins
|
|
||||||
fmt.Println("Allowed origins: ", allowedOrigins)
|
|
||||||
origins := []string{"http://localhost:3000"} // Default value
|
|
||||||
|
|
||||||
if allowedOrigins != "" {
|
|
||||||
// Split the comma-separated string into a slice of strings
|
|
||||||
origins = strings.Split(allowedOrigins, ",")
|
|
||||||
fmt.Println("Listening for connections from: ", origins)
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for errors
|
|
||||||
if err != nil || config == nil {
|
|
||||||
log.Fatalf("Failed to load config: %v", err)
|
log.Fatalf("Failed to load config: %v", err)
|
||||||
}
|
}
|
||||||
|
fmt.Printf("Config loaded successfully in main(), DB path %s", config.DatabasePath)
|
||||||
fmt.Println(config.DatabasePath)
|
|
||||||
fmt.Println(config.ImageStorageDir)
|
|
||||||
fmt.Println(config.JWTSecret)
|
|
||||||
fmt.Println(config.LogFile)
|
|
||||||
fmt.Println(config.ListeningPort)
|
|
||||||
|
|
||||||
// Connect to the database
|
// Connect to the database
|
||||||
db, err = ConnectDB(config.DatabasePath)
|
db, err = connectToDatabase(config)
|
||||||
if err != nil || db == nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to connect to database: %v", err)
|
log.Fatalf("Failed to connect to database: %v", err)
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
// Modify your custom handler to include more detailed logging
|
// Create routers
|
||||||
customHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
baseRouter := mux.NewRouter()
|
||||||
|
apiRouter := createAPIRouter(baseRouter)
|
||||||
|
staticRouter := createStaticRouter(baseRouter, config.StaticFilesDir)
|
||||||
|
|
||||||
|
// Set up routes
|
||||||
|
setupAPIRoutes(apiRouter)
|
||||||
|
setupStaticRoutes(staticRouter, config.StaticFilesDir)
|
||||||
|
|
||||||
|
// Create CORS handler
|
||||||
|
corsHandler := createCORSHandler(config.AllowedOrigins)
|
||||||
|
|
||||||
|
// Start the server
|
||||||
|
startServer(config.ListeningPort, corsHandler(baseRouter))
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadAndValidateConfig() (*Config, error) {
|
||||||
|
configFile := os.Getenv("BOXES_API_CONFIG")
|
||||||
|
config, err := LoadConfig(configFile)
|
||||||
|
if err != nil || config == nil {
|
||||||
|
return nil, fmt.Errorf("failed to load config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the database path
|
||||||
|
if config.DatabasePath == "" {
|
||||||
|
return nil, fmt.Errorf("database path is not set in config")
|
||||||
|
}
|
||||||
|
DatabasePath = &config.DatabasePath
|
||||||
|
|
||||||
|
// Set JWTSecret
|
||||||
|
jwtSecretBytes := []byte(config.JWTSecret)
|
||||||
|
JWTSecret = &jwtSecretBytes
|
||||||
|
|
||||||
|
ImageStorage = &config.ImageStorageDir
|
||||||
|
|
||||||
|
// Log config details
|
||||||
|
logConfigDetails(config)
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func connectToDatabase(config *Config) (*gorm.DB, error) {
|
||||||
|
if config == nil {
|
||||||
|
return nil, fmt.Errorf("config is nil in connectToDatabase")
|
||||||
|
}
|
||||||
|
db, err := ConnectDB(config.DatabasePath)
|
||||||
|
if err != nil || db == nil {
|
||||||
|
return nil, fmt.Errorf("failed to connect to database: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Println("Connected to database in connectToDatabase")
|
||||||
|
return db, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createAPIRouter(baseRouter *mux.Router) *mux.Router {
|
||||||
|
return baseRouter.PathPrefix("/api/v1").Subrouter()
|
||||||
|
}
|
||||||
|
|
||||||
|
func createStaticRouter(baseRouter *mux.Router, staticPath string) *mux.Router {
|
||||||
|
if err := validateStaticDirectory(staticPath); err != nil {
|
||||||
|
log.Fatalf("Static directory error: %v", err)
|
||||||
|
}
|
||||||
|
return baseRouter.PathPrefix("/").Subrouter()
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupAPIRoutes(router *mux.Router) {
|
||||||
|
router.Handle("/login", http.HandlerFunc(LoginHandler)).Methods("POST", "OPTIONS")
|
||||||
|
|
||||||
|
// Protected routes
|
||||||
|
protected := router.NewRoute().Subrouter()
|
||||||
|
protected.Use(AuthMiddleware)
|
||||||
|
|
||||||
|
protected.Handle("/boxes", http.HandlerFunc(GetBoxesHandler)).Methods("GET", "OPTIONS")
|
||||||
|
protected.Handle("/boxes", http.HandlerFunc(CreateBoxHandler)).Methods("POST", "OPTIONS")
|
||||||
|
protected.Handle("/boxes/{id}", http.HandlerFunc(DeleteBoxHandler)).Methods("DELETE", "OPTIONS")
|
||||||
|
protected.Handle("/boxes/{id}", http.HandlerFunc(GetBoxHandler)).Methods("GET", "OPTIONS")
|
||||||
|
protected.Handle("/items", http.HandlerFunc(GetItemsHandler)).Methods("GET", "OPTIONS")
|
||||||
|
protected.Handle("/items", http.HandlerFunc(CreateItemHandler)).Methods("POST", "OPTIONS")
|
||||||
|
protected.Handle("/items/{id}", http.HandlerFunc(GetItemHandler)).Methods("GET", "OPTIONS")
|
||||||
|
protected.Handle("/boxes/{id}/items", http.HandlerFunc(GetItemsInBoxHandler)).Methods("GET", "OPTIONS")
|
||||||
|
protected.Handle("/items/{id}", http.HandlerFunc(UpdateItemHandler)).Methods("PUT", "OPTIONS")
|
||||||
|
protected.Handle("/items/{id}", http.HandlerFunc(DeleteItemHandler)).Methods("DELETE", "OPTIONS")
|
||||||
|
protected.Handle("/items/{id}/image", http.HandlerFunc(GetItemImageHandler)).Methods("GET", "OPTIONS")
|
||||||
|
protected.Handle("/search/items", http.HandlerFunc(SearchItemsHandler)).Methods("GET", "OPTIONS")
|
||||||
|
protected.Handle("/items/{id}/upload", http.HandlerFunc(UploadItemImageHandler)).Methods("POST", "OPTIONS")
|
||||||
|
|
||||||
|
setupManagementRoutes(protected.PathPrefix("/admin").Subrouter())
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupManagementRoutes(router *mux.Router) {
|
||||||
|
router.Handle("/user", http.HandlerFunc(GetUsersHandler)).Methods("GET", "OPTIONS")
|
||||||
|
router.Handle("/user", http.HandlerFunc(CreateUserHandler)).Methods("POST", "OPTIONS")
|
||||||
|
router.Handle("/user/{id}", http.HandlerFunc(GetUserHandler)).Methods("GET", "OPTIONS")
|
||||||
|
router.Handle("/user/{id}", http.HandlerFunc(DeleteUserHandler)).Methods("DELETE", "OPTIONS")
|
||||||
|
router.Handle("/db", http.HandlerFunc(BackupDatabaseHandler)).Methods("GET", "OPTIONS")
|
||||||
|
router.Handle("/db", http.HandlerFunc(RestoreDatabaseHandler)).Methods("POST", "OPTIONS")
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupStaticRoutes(router *mux.Router, staticPath string) {
|
||||||
|
customHandler := createCustomStaticHandler(staticPath)
|
||||||
|
router.PathPrefix("/").Handler(http.StripPrefix("/", customHandler))
|
||||||
|
}
|
||||||
|
|
||||||
|
func createCustomStaticHandler(staticPath string) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Printf("Attempting to serve: %s from directory: %s", r.URL.Path, staticPath)
|
log.Printf("Attempting to serve: %s from directory: %s", r.URL.Path, staticPath)
|
||||||
fullPath := filepath.Join(staticPath, r.URL.Path)
|
fullPath := filepath.Join(staticPath, r.URL.Path)
|
||||||
if _, err := os.Stat(fullPath); os.IsNotExist(err) {
|
if _, err := os.Stat(fullPath); os.IsNotExist(err) {
|
||||||
|
@ -72,65 +147,42 @@ func main() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
http.FileServer(http.Dir(staticPath)).ServeHTTP(w, r)
|
http.FileServer(http.Dir(staticPath)).ServeHTTP(w, r)
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println("Default user 'boxuser' created successfully!")
|
func createCORSHandler(allowedOrigins string) func(http.Handler) http.Handler {
|
||||||
|
origins := strings.Split(allowedOrigins, ",")
|
||||||
|
if len(origins) == 0 {
|
||||||
|
origins = []string{"http://localhost:3000"}
|
||||||
|
}
|
||||||
|
|
||||||
// Create the router
|
return cors.New(cors.Options{
|
||||||
baseRouter := mux.NewRouter()
|
|
||||||
|
|
||||||
router := baseRouter.PathPrefix("/api/v1").Subrouter()
|
|
||||||
staticRouter := baseRouter.PathPrefix("/").Subrouter()
|
|
||||||
|
|
||||||
// Define your routes
|
|
||||||
router.Handle("/login", http.HandlerFunc(LoginHandler)).Methods("POST", "OPTIONS")
|
|
||||||
router.Handle("/boxes", AuthMiddleware(http.HandlerFunc(GetBoxesHandler))).Methods("GET", "OPTIONS")
|
|
||||||
router.Handle("/boxes", AuthMiddleware(http.HandlerFunc(CreateBoxHandler))).Methods("POST", "OPTIONS")
|
|
||||||
router.Handle("/boxes/{id}", AuthMiddleware(http.HandlerFunc(DeleteBoxHandler))).Methods("DELETE", "OPTIONS")
|
|
||||||
router.Handle("/boxes/{id}", AuthMiddleware(http.HandlerFunc(GetBoxHandler))).Methods("GET", "OPTIONS")
|
|
||||||
router.Handle("/items", AuthMiddleware(http.HandlerFunc(GetItemsHandler))).Methods("GET", "OPTIONS")
|
|
||||||
router.Handle("/items", AuthMiddleware(http.HandlerFunc(CreateItemHandler))).Methods("POST", "OPTIONS")
|
|
||||||
router.Handle("/items/{id}", AuthMiddleware(http.HandlerFunc(GetItemHandler))).Methods("GET", "OPTIONS")
|
|
||||||
router.Handle("/boxes/{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")
|
|
||||||
router.Handle("/items/{id}/image", AuthMiddleware(http.HandlerFunc(GetItemImageHandler))).Methods("GET", "OPTIONS")
|
|
||||||
fmt.Println("Registering route for search items...")
|
|
||||||
router.Handle("/search/items", AuthMiddleware(http.HandlerFunc(SearchItemsHandler))).Methods("GET", "OPTIONS")
|
|
||||||
// Add a new route for uploading an image with AuthMiddleware
|
|
||||||
router.HandleFunc("/items/{id}/upload", UploadItemImageHandler).
|
|
||||||
Methods("POST").
|
|
||||||
Handler(AuthMiddleware(http.HandlerFunc(UploadItemImageHandler)))
|
|
||||||
|
|
||||||
managementRouter := router.PathPrefix("/admin").Subrouter()
|
|
||||||
managementRouter.Use(AuthMiddleware)
|
|
||||||
|
|
||||||
managementRouter.Handle("/user", http.HandlerFunc(GetUsersHandler)).Methods("GET", "OPTIONS")
|
|
||||||
managementRouter.Handle("/user", http.HandlerFunc(CreateUserHandler)).Methods("POST", "OPTIONS")
|
|
||||||
managementRouter.Handle("/user/{id}", http.HandlerFunc(GetUserHandler)).Methods("GET", "OPTIONS")
|
|
||||||
managementRouter.Handle("/user/{id}", http.HandlerFunc(DeleteUserHandler)).Methods("DELETE", "OPTIONS")
|
|
||||||
managementRouter.Handle("/db", http.HandlerFunc(BackupDatabaseHandler)).Methods("GET", "OPTIONS")
|
|
||||||
managementRouter.Handle("/db", http.HandlerFunc(RestoreDatabaseHandler)).Methods("POST", "OPTIONS")
|
|
||||||
|
|
||||||
// Define a route for serving static files
|
|
||||||
fmt.Println("Serving static files from:", staticPath)
|
|
||||||
//staticHandler := http.FileServer(http.Dir(staticPath))
|
|
||||||
fmt.Println("Registering route for serving static files, no StripPrefix")
|
|
||||||
//staticRouter.HandleFunc("/", customHandler).Methods("GET", "OPTIONS")
|
|
||||||
// perplexity recommends:
|
|
||||||
staticRouter.PathPrefix("/").Handler(http.StripPrefix("/", customHandler))
|
|
||||||
|
|
||||||
|
|
||||||
// Apply CORS middleware
|
|
||||||
c := cors.New(cors.Options{
|
|
||||||
AllowedOrigins: origins,
|
AllowedOrigins: origins,
|
||||||
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
|
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
|
||||||
AllowedHeaders: []string{"Authorization", "Content-Type"},
|
AllowedHeaders: []string{"Authorization", "Content-Type"},
|
||||||
ExposedHeaders: []string{"Content-Length", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Cache-Control", "Content-Language", "Content-Type", "Expires", "Last-Modified", "Pragma", "ETag"},
|
ExposedHeaders: []string{"Content-Length", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Cache-Control", "Content-Language", "Content-Type", "Expires", "Last-Modified", "Pragma", "ETag"},
|
||||||
AllowCredentials: true,
|
AllowCredentials: true,
|
||||||
})
|
}).Handler
|
||||||
|
}
|
||||||
// Start the server with CORS middleware
|
|
||||||
fmt.Printf("Server listening on port %d\n", config.ListeningPort)
|
func startServer(port int, handler http.Handler) {
|
||||||
http.ListenAndServe(fmt.Sprintf(":%d", config.ListeningPort), c.Handler(baseRouter))
|
fmt.Printf("Server listening on port %d\n", port)
|
||||||
|
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", port), handler))
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateStaticDirectory(path string) error {
|
||||||
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||||
|
return fmt.Errorf("static directory does not exist: %s", path)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func logConfigDetails(config *Config) {
|
||||||
|
fmt.Println("Config details:")
|
||||||
|
fmt.Printf("Database Path: %s\n", config.DatabasePath)
|
||||||
|
fmt.Printf("Image Storage Dir: %s\n", config.ImageStorageDir)
|
||||||
|
fmt.Printf("JWT Secret: %s\n", config.JWTSecret)
|
||||||
|
fmt.Printf("Log File: %s\n", config.LogFile)
|
||||||
|
fmt.Printf("Listening Port: %d\n", config.ListeningPort)
|
||||||
|
fmt.Printf("Allowed Origins: %s\n", config.AllowedOrigins)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,19 @@
|
||||||
#!/binb/ash
|
#!/binb/ash
|
||||||
|
|
||||||
# Set the password you want to use
|
# Set the password you want to use
|
||||||
PASSWORD="12m0nk3ys"
|
PASSWORD="boxuser"
|
||||||
|
<<<<<<< Updated upstream
|
||||||
|
DATABASE="/Users/stwhite/CODE/Boxes-App/boxes-api/data/boxes.db"
|
||||||
|
=======
|
||||||
|
DATABASE="../data/boxes.db"
|
||||||
|
>>>>>>> Stashed changes
|
||||||
|
|
||||||
# Use htpasswd to create a bcrypt hash of the password
|
# Use htpasswd to create a bcrypt hash of the password
|
||||||
HASHED_PASSWORD=$(htpasswd -nbBC 10 "" "$PASSWORD" | tr -d ':\n')
|
HASHED_PASSWORD=$(htpasswd -nbBC 10 "" "$PASSWORD" | tr -d ':\n')
|
||||||
|
|
||||||
# Create the user in the SQLite database
|
# Create the user in the SQLite database
|
||||||
sqlite3 your_database.db "INSERT INTO users (username, password, email, email, email, email, email, email, email, email, email) VALUES ('boxuser', '$HASHED_PASSWORD','boxuser@r8z.us');"
|
<<<<<<< Updated upstream
|
||||||
|
sqlite3 $DATABASE "INSERT INTO users (username, password, email) VALUES ('boxuser', '$HASHED_PASSWORD','boxuser@r8z.us')"
|
||||||
|
=======
|
||||||
|
sqlite3 $DATABASE "INSERT INTO users (username, password, email) VALUES ('boxuser', '$HASHED_PASSWORD','boxuser@r8z.us');"
|
||||||
|
>>>>>>> Stashed changes
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
API_BASE_URL="http://localhost:8080/api/v1" # Adjusted to include /api/v1
|
||||||
|
USERNAME="boxuser"
|
||||||
|
PASSWORD="boxuser"
|
||||||
|
|
||||||
|
echo "Sending request to: $API_BASE_URL/login"
|
||||||
|
echo "Username: $USERNAME"
|
||||||
|
echo "Password: $PASSWORD"
|
||||||
|
|
||||||
|
response=$(curl -vi -w "\n%{http_code}" -X POST -H "Content-Type: application/json" \
|
||||||
|
-d "{\"username\":\"$USERNAME\", \"password\":\"$PASSWORD\"}" \
|
||||||
|
"$API_BASE_URL/login")
|
||||||
|
|
||||||
|
http_status=$(echo "$response" | tail -n1)
|
||||||
|
body=$(echo "$response" | sed '$d')
|
||||||
|
|
||||||
|
echo "HTTP Status: $http_status"
|
||||||
|
echo "Response body: $body"
|
||||||
|
|
||||||
|
if [ "$http_status" -eq 200 ]; then
|
||||||
|
TOKEN=$(echo "$body" | jq -r '.token // empty')
|
||||||
|
if [ -n "$TOKEN" ]; then
|
||||||
|
echo "Token obtained successfully:"
|
||||||
|
echo "$TOKEN"
|
||||||
|
else
|
||||||
|
echo "Failed to extract token from response."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Failed to obtain token. Server returned status $http_status"
|
||||||
|
fi
|
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# API base URL
|
# API base URL
|
||||||
API_BASE_URL="http://10.0.0.66:8080"
|
API_BASE_URL="http://localhost:8080/api/v1"
|
||||||
|
|
||||||
# Login credentials
|
# Login credentials
|
||||||
USERNAME="boxuser"
|
USERNAME="boxuser"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# API base URL
|
# API base URL
|
||||||
API_BASE_URL="http://localhost:8080"
|
API_BASE_URL="http://localhost:8080/api/v1/"
|
||||||
|
|
||||||
# Login credentials
|
# Login credentials
|
||||||
USERNAME="boxuser"
|
USERNAME="boxuser"
|
||||||
|
@ -11,8 +11,9 @@ PASSWORD="boxuser"
|
||||||
TOKEN=$(curl -s -X POST -H "Content-Type: application/json" \
|
TOKEN=$(curl -s -X POST -H "Content-Type: application/json" \
|
||||||
-d "{\"username\":\"$USERNAME\", \"password\":\"$PASSWORD\"}" \
|
-d "{\"username\":\"$USERNAME\", \"password\":\"$PASSWORD\"}" \
|
||||||
"$API_BASE_URL/login" | jq -r '.token')
|
"$API_BASE_URL/login" | jq -r '.token')
|
||||||
|
echo $TOKEN
|
||||||
|
|
||||||
curl -X GET \
|
curl -X GET \
|
||||||
$API_BASE_URL/admin/user \
|
$API_BASE_URL/admin/user \
|
||||||
-H "Authorization: Bearer $TOKEN" \
|
-H "Authorization: Bearer $TOKEN" \
|
||||||
-H "Content-Type: application/json"
|
-H "Content-Type: application/json"
|
||||||
|
|
Loading…
Reference in New Issue