Implement local DB migrations and archived configuration lifecycle
This commit is contained in:
127
cmd/qfs/main.go
127
cmd/qfs/main.go
@@ -629,8 +629,13 @@ func setupRouter(cfg *config.Config, local *localdb.LocalDB, connMgr *db.Connect
|
||||
configs.GET("", func(c *gin.Context) {
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
perPage, _ := strconv.Atoi(c.DefaultQuery("per_page", "20"))
|
||||
status := c.DefaultQuery("status", "active")
|
||||
if status != "active" && status != "archived" && status != "all" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid status"})
|
||||
return
|
||||
}
|
||||
|
||||
cfgs, total, err := configService.ListAll(page, perPage)
|
||||
cfgs, total, err := configService.ListAllWithStatus(page, perPage, status)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
@@ -641,6 +646,7 @@ func setupRouter(cfg *config.Config, local *localdb.LocalDB, connMgr *db.Connect
|
||||
"total": total,
|
||||
"page": page,
|
||||
"per_page": perPage,
|
||||
"status": status,
|
||||
})
|
||||
})
|
||||
|
||||
@@ -706,7 +712,20 @@ func setupRouter(cfg *config.Config, local *localdb.LocalDB, connMgr *db.Connect
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"message": "deleted"})
|
||||
c.JSON(http.StatusOK, gin.H{"message": "archived"})
|
||||
})
|
||||
|
||||
configs.POST("/:uuid/reactivate", func(c *gin.Context) {
|
||||
uuid := c.Param("uuid")
|
||||
config, err := configService.ReactivateNoAuth(uuid)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "reactivated",
|
||||
"config": config,
|
||||
})
|
||||
})
|
||||
|
||||
configs.PATCH("/:uuid/rename", func(c *gin.Context) {
|
||||
@@ -756,6 +775,110 @@ func setupRouter(cfg *config.Config, local *localdb.LocalDB, connMgr *db.Connect
|
||||
}
|
||||
c.JSON(http.StatusOK, config)
|
||||
})
|
||||
|
||||
configs.GET("/:uuid/versions", func(c *gin.Context) {
|
||||
uuid := c.Param("uuid")
|
||||
|
||||
limit, err := strconv.Atoi(c.DefaultQuery("limit", "20"))
|
||||
if err != nil || limit <= 0 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid limit"})
|
||||
return
|
||||
}
|
||||
offset, err := strconv.Atoi(c.DefaultQuery("offset", "0"))
|
||||
if err != nil || offset < 0 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid offset"})
|
||||
return
|
||||
}
|
||||
|
||||
versions, err := configService.ListVersions(uuid, limit, offset)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, services.ErrConfigNotFound):
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "configuration not found"})
|
||||
case errors.Is(err, services.ErrInvalidVersionNumber):
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid paging params"})
|
||||
default:
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"versions": versions,
|
||||
"limit": limit,
|
||||
"offset": offset,
|
||||
})
|
||||
})
|
||||
|
||||
configs.GET("/:uuid/versions/:version", func(c *gin.Context) {
|
||||
uuid := c.Param("uuid")
|
||||
versionNo, err := strconv.Atoi(c.Param("version"))
|
||||
if err != nil || versionNo <= 0 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid version number"})
|
||||
return
|
||||
}
|
||||
|
||||
version, err := configService.GetVersion(uuid, versionNo)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, services.ErrInvalidVersionNumber):
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid version number"})
|
||||
case errors.Is(err, services.ErrConfigVersionNotFound):
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "version not found"})
|
||||
default:
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, version)
|
||||
})
|
||||
|
||||
configs.POST("/:uuid/rollback", func(c *gin.Context) {
|
||||
uuid := c.Param("uuid")
|
||||
var req struct {
|
||||
TargetVersion int `json:"target_version"`
|
||||
Note string `json:"note"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
if req.TargetVersion <= 0 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid target_version"})
|
||||
return
|
||||
}
|
||||
|
||||
config, err := configService.RollbackToVersionWithNote(uuid, req.TargetVersion, dbUsername, req.Note)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, services.ErrInvalidVersionNumber):
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid target_version"})
|
||||
case errors.Is(err, services.ErrConfigNotFound), errors.Is(err, services.ErrConfigVersionNotFound):
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "version not found"})
|
||||
case errors.Is(err, services.ErrVersionConflict):
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "version conflict"})
|
||||
default:
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
currentVersion, err := configService.GetCurrentVersion(uuid)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "rollback applied",
|
||||
"config": config,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "rollback applied",
|
||||
"config": config,
|
||||
"current_version": currentVersion,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Pricing admin (public - RBAC disabled)
|
||||
|
||||
Reference in New Issue
Block a user