Files
OwOrganizer/backend/main.go
T

227 lines
5.9 KiB
Go
Raw Normal View History

2026-07-16 00:12:44 -07:00
package main
import (
"log"
"net/http"
2026-07-16 16:04:48 -07:00
"os"
"strings"
2026-07-16 00:12:44 -07:00
2026-07-16 16:04:48 -07:00
"github.com/gin-contrib/cors"
2026-07-16 00:12:44 -07:00
"github.com/gin-gonic/gin"
)
func main() {
db, err := InitDB()
if err != nil {
log.Fatalf("failed to initialize database: %v", err)
}
DB = db
router := gin.Default()
2026-07-16 14:01:39 -07:00
2026-07-16 16:04:48 -07:00
// Configure CORS. In production, set CORS_ALLOWED_ORIGINS to your public domain.
allowedOrigins := []string{"http://localhost:5173"}
if envOrigins := os.Getenv("CORS_ALLOWED_ORIGINS"); envOrigins != "" {
allowedOrigins = strings.Split(envOrigins, ",")
}
router.Use(cors.New(cors.Config{
AllowOrigins: allowedOrigins,
AllowMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"},
AllowHeaders: []string{"Origin", "Content-Type", "Accept", "Authorization"},
ExposeHeaders: []string{"Content-Length"},
AllowCredentials: true,
MaxAge: 12 * 60 * 60,
}))
2026-07-16 00:12:44 -07:00
router.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
2026-07-16 14:01:39 -07:00
2026-07-16 00:12:44 -07:00
router.GET("/db-check", func(c *gin.Context) {
if err := DB.Ping(); err != nil {
c.JSON(http.StatusServiceUnavailable, gin.H{"status": "unreachable", "error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"status": "ok"})
})
2026-07-16 14:01:39 -07:00
// User routes
router.POST("/users", createUserHandler)
router.GET("/users/:id", getUserHandler)
router.PUT("/users/:id", updateUserHandler)
router.DELETE("/users/:id", deleteUserHandler)
// Object routes
router.POST("/objects", createObjectHandler)
router.GET("/objects/:id", getObjectHandler)
router.GET("/users/:id/objects", getObjectsByUserHandler)
router.PUT("/objects/:id", updateObjectHandler)
router.DELETE("/objects/:id", deleteObjectHandler)
2026-07-16 00:12:44 -07:00
router.Run() // listens on 0.0.0.0:8080 by default
}
2026-07-16 14:01:39 -07:00
// createUserRequest is the expected body for POST /users.
type createUserRequest struct {
UserID string `json:"userId" binding:"required"`
RootObjectID string `json:"rootObjectId" binding:"required"`
}
func createUserHandler(c *gin.Context) {
var req createUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if err := CreateUser(req.UserID, req.RootObjectID); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, gin.H{"status": "created"})
}
func getUserHandler(c *gin.Context) {
id := c.Param("id")
user, err := GetUser(id)
if err != nil {
if err.Error() == "user not found" {
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, user)
}
// updateUserRequest is the expected body for PUT /users/:id.
type updateUserRequest struct {
RootObjectID string `json:"rootObjectId" binding:"required"`
}
func updateUserHandler(c *gin.Context) {
id := c.Param("id")
var req updateUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if err := UpdateUser(id, req.RootObjectID); err != nil {
if err.Error() == "user not found" {
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"status": "updated"})
}
func deleteUserHandler(c *gin.Context) {
id := c.Param("id")
if err := DeleteUser(id); err != nil {
if err.Error() == "user not found" {
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"status": "deleted"})
}
// createObjectRequest is the expected body for POST /objects.
type createObjectRequest struct {
ObjectID string `json:"objectId" binding:"required"`
UserID string `json:"userId" binding:"required"`
ObjectData string `json:"objectData" binding:"required"`
}
func createObjectHandler(c *gin.Context) {
var req createObjectRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if err := CreateObject(req.ObjectID, req.UserID, req.ObjectData); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, gin.H{"status": "created"})
}
func getObjectHandler(c *gin.Context) {
id := c.Param("id")
obj, err := GetObject(id)
if err != nil {
if err.Error() == "object not found" {
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, obj)
}
func getObjectsByUserHandler(c *gin.Context) {
id := c.Param("id")
objects, err := GetObjectsByUser(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, objects)
}
// updateObjectRequest is the expected body for PUT /objects/:id.
type updateObjectRequest struct {
ObjectData string `json:"objectData" binding:"required"`
}
func updateObjectHandler(c *gin.Context) {
id := c.Param("id")
var req updateObjectRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if err := UpdateObject(id, req.ObjectData); err != nil {
if err.Error() == "object not found" {
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"status": "updated"})
}
func deleteObjectHandler(c *gin.Context) {
id := c.Param("id")
if err := DeleteObject(id); err != nil {
if err.Error() == "object not found" {
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"status": "deleted"})
}