created dummy API routes, passing API test
This commit is contained in:
@@ -103,3 +103,167 @@ func createTables(db *sql.DB) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// User represents a row in the users table.
|
||||||
|
type User struct {
|
||||||
|
UserID string
|
||||||
|
RootObjectID string
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateUser inserts a new user into the users table.
|
||||||
|
func CreateUser(userID, rootObjectID string) error {
|
||||||
|
_, err := DB.Exec(
|
||||||
|
"INSERT INTO users (userId, rootObjectId) VALUES (?, ?)",
|
||||||
|
userID, rootObjectID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create user: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUser retrieves a user by ID.
|
||||||
|
func GetUser(userID string) (User, error) {
|
||||||
|
var user User
|
||||||
|
err := DB.QueryRow(
|
||||||
|
"SELECT userId, rootObjectId FROM users WHERE userId = ?",
|
||||||
|
userID,
|
||||||
|
).Scan(&user.UserID, &user.RootObjectID)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return User{}, fmt.Errorf("user not found")
|
||||||
|
}
|
||||||
|
return User{}, fmt.Errorf("failed to get user: %w", err)
|
||||||
|
}
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateUser updates the rootObjectId for a user.
|
||||||
|
func UpdateUser(userID, rootObjectID string) error {
|
||||||
|
result, err := DB.Exec(
|
||||||
|
"UPDATE users SET rootObjectId = ? WHERE userId = ?",
|
||||||
|
rootObjectID, userID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to update user: %w", err)
|
||||||
|
}
|
||||||
|
rows, err := result.RowsAffected()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to check update result: %w", err)
|
||||||
|
}
|
||||||
|
if rows == 0 {
|
||||||
|
return fmt.Errorf("user not found")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteUser removes a user by ID.
|
||||||
|
func DeleteUser(userID string) error {
|
||||||
|
result, err := DB.Exec("DELETE FROM users WHERE userId = ?", userID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to delete user: %w", err)
|
||||||
|
}
|
||||||
|
rows, err := result.RowsAffected()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to check delete result: %w", err)
|
||||||
|
}
|
||||||
|
if rows == 0 {
|
||||||
|
return fmt.Errorf("user not found")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Object represents a row in the objects table.
|
||||||
|
type Object struct {
|
||||||
|
ObjectID string
|
||||||
|
UserID string
|
||||||
|
ObjectData string
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateObject inserts a new object into the objects table.
|
||||||
|
func CreateObject(objectID, userID, objectData string) error {
|
||||||
|
_, err := DB.Exec(
|
||||||
|
"INSERT INTO objects (objectId, userId, objectData) VALUES (?, ?, ?)",
|
||||||
|
objectID, userID, objectData,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create object: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetObject retrieves an object by ID.
|
||||||
|
func GetObject(objectID string) (Object, error) {
|
||||||
|
var obj Object
|
||||||
|
err := DB.QueryRow(
|
||||||
|
"SELECT objectId, userId, objectData FROM objects WHERE objectId = ?",
|
||||||
|
objectID,
|
||||||
|
).Scan(&obj.ObjectID, &obj.UserID, &obj.ObjectData)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return Object{}, fmt.Errorf("object not found")
|
||||||
|
}
|
||||||
|
return Object{}, fmt.Errorf("failed to get object: %w", err)
|
||||||
|
}
|
||||||
|
return obj, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetObjectsByUser retrieves all objects belonging to a user.
|
||||||
|
func GetObjectsByUser(userID string) ([]Object, error) {
|
||||||
|
rows, err := DB.Query(
|
||||||
|
"SELECT objectId, userId, objectData FROM objects WHERE userId = ?",
|
||||||
|
userID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to query objects: %w", err)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var objects []Object
|
||||||
|
for rows.Next() {
|
||||||
|
var obj Object
|
||||||
|
if err := rows.Scan(&obj.ObjectID, &obj.UserID, &obj.ObjectData); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to scan object: %w", err)
|
||||||
|
}
|
||||||
|
objects = append(objects, obj)
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to iterate objects: %w", err)
|
||||||
|
}
|
||||||
|
return objects, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateObject updates the objectData for an object.
|
||||||
|
func UpdateObject(objectID, objectData string) error {
|
||||||
|
result, err := DB.Exec(
|
||||||
|
"UPDATE objects SET objectData = ? WHERE objectId = ?",
|
||||||
|
objectData, objectID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to update object: %w", err)
|
||||||
|
}
|
||||||
|
rows, err := result.RowsAffected()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to check update result: %w", err)
|
||||||
|
}
|
||||||
|
if rows == 0 {
|
||||||
|
return fmt.Errorf("object not found")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteObject removes an object by ID.
|
||||||
|
func DeleteObject(objectID string) error {
|
||||||
|
result, err := DB.Exec("DELETE FROM objects WHERE objectId = ?", objectID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to delete object: %w", err)
|
||||||
|
}
|
||||||
|
rows, err := result.RowsAffected()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to check delete result: %w", err)
|
||||||
|
}
|
||||||
|
if rows == 0 {
|
||||||
|
return fmt.Errorf("object not found")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
+178
@@ -15,11 +15,13 @@ func main() {
|
|||||||
DB = db
|
DB = db
|
||||||
|
|
||||||
router := gin.Default()
|
router := gin.Default()
|
||||||
|
|
||||||
router.GET("/ping", func(c *gin.Context) {
|
router.GET("/ping", func(c *gin.Context) {
|
||||||
c.JSON(200, gin.H{
|
c.JSON(200, gin.H{
|
||||||
"message": "pong",
|
"message": "pong",
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
router.GET("/db-check", func(c *gin.Context) {
|
router.GET("/db-check", func(c *gin.Context) {
|
||||||
if err := DB.Ping(); err != nil {
|
if err := DB.Ping(); err != nil {
|
||||||
c.JSON(http.StatusServiceUnavailable, gin.H{"status": "unreachable", "error": err.Error()})
|
c.JSON(http.StatusServiceUnavailable, gin.H{"status": "unreachable", "error": err.Error()})
|
||||||
@@ -27,5 +29,181 @@ func main() {
|
|||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, gin.H{"status": "ok"})
|
c.JSON(http.StatusOK, gin.H{"status": "ok"})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
router.Run() // listens on 0.0.0.0:8080 by default
|
router.Run() // listens on 0.0.0.0:8080 by default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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"})
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
services:
|
services:
|
||||||
application:
|
backend:
|
||||||
build: ./backend
|
build: ./backend
|
||||||
container_name: ${SERVICE_NAME}-oworganizer-backend
|
container_name: ${SERVICE_NAME}-oworganizer-backend
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
Reference in New Issue
Block a user