validate use input mongo id

This commit is contained in:
yaziming
2020-05-29 22:51:23 +08:00
parent 0a50f5ce23
commit 4575ecd673
14 changed files with 229 additions and 43 deletions

View File

@@ -125,6 +125,10 @@ func GetNodeList(c *gin.Context) {
func GetNode(c *gin.Context) {
var result model.Node
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
for _, node := range NodeList {
if node.Id == bson.ObjectId(id) {
result = node
@@ -150,6 +154,10 @@ func Ping(c *gin.Context) {
func PostNode(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
var oldItem model.Node
for _, node := range NodeList {
if node.Id == bson.ObjectId(id) {
@@ -200,7 +208,10 @@ func DeleteNode(c *gin.Context) {
func GetSystemInfo(c *gin.Context) {
id := c.Param("id")
log.Info(id)
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
sysInfo := systemInfo
c.JSON(http.StatusOK, Response{

View File

@@ -54,7 +54,10 @@ func GetScheduleList(c *gin.Context) {
func GetSchedule(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
var result model.Schedule
for _, sch := range scheduleList {
if sch.Id == bson.ObjectId(id) {
@@ -70,6 +73,10 @@ func GetSchedule(c *gin.Context) {
func PostSchedule(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
var oldItem model.Schedule
for _, sch := range scheduleList {
if sch.Id == bson.ObjectId(id) {

View File

@@ -49,6 +49,7 @@ func GetSpider(c *gin.Context) {
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
for _, spider := range SpiderList {
@@ -87,7 +88,10 @@ func PostSpider(c *gin.Context) {
func GetSpiderDir(c *gin.Context) {
// 爬虫ID
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
// 目录相对路径
path := c.Query("path")
var spi model.Spider
@@ -127,7 +131,10 @@ func GetSpiderDir(c *gin.Context) {
func GetSpiderTasks(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
var spider model.Spider
for _, spi := range SpiderList {
if spi.Id == bson.ObjectId(id) {

View File

@@ -65,7 +65,10 @@ func GetTaskList(c *gin.Context) {
func GetTask(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
var result model.Task
for _, task := range TaskList {
if task.Id == id {
@@ -111,7 +114,10 @@ func PutTask(c *gin.Context) {
func DeleteTask(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
for _, task := range TaskList {
if task.Id == id {
fmt.Println("delete the task")
@@ -126,7 +132,10 @@ func DeleteTask(c *gin.Context) {
func GetTaskResults(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
// 绑定数据
data := TaskResultsRequestData{}
if err := c.ShouldBindQuery(&data); err != nil {
@@ -157,7 +166,10 @@ func GetTaskResults(c *gin.Context) {
func DownloadTaskResultsCsv(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
// 获取任务
var task model.Task
for _, ta := range TaskList {

View File

@@ -10,7 +10,10 @@ import (
func GetAction(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
user, err := model.GetAction(bson.ObjectIdHex(id))
if err != nil {
HandleError(http.StatusInternalServerError, c, err)

View File

@@ -129,7 +129,10 @@ func PostConfigSpider(c *gin.Context) {
// @Router /config_spiders/{id}/upload [post]
func UploadConfigSpider(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
// 获取爬虫
var spider model.Spider
spider, err := model.GetSpider(bson.ObjectIdHex(id))
@@ -231,7 +234,10 @@ func PostConfigSpiderSpiderfile(c *gin.Context) {
}
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
// 文件内容
var reqBody Body
if err := c.ShouldBindJSON(&reqBody); err != nil {
@@ -297,7 +303,10 @@ func PostConfigSpiderSpiderfile(c *gin.Context) {
// @Router /config_spiders/{id}/config [post]
func PostConfigSpiderConfig(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
// 获取爬虫
var spider model.Spider
spider, err := model.GetSpider(bson.ObjectIdHex(id))

View File

@@ -45,7 +45,10 @@ func GetNodeList(c *gin.Context) {
// @Router /nodes/{id} [get]
func GetNode(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
result, err := model.GetNode(bson.ObjectIdHex(id))
if err != nil {
HandleError(http.StatusInternalServerError, c, err)
@@ -71,7 +74,6 @@ func Ping(c *gin.Context) {
})
}
// @Summary Post node
// @Description Post node
// @Tags node
@@ -84,7 +86,10 @@ func Ping(c *gin.Context) {
// @Router /nodes/{id} [post]
func PostNode(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
item, err := model.GetNode(bson.ObjectIdHex(id))
if err != nil {
HandleError(http.StatusInternalServerError, c, err)
@@ -120,7 +125,10 @@ func PostNode(c *gin.Context) {
// @Router /nodes/{id}/tasks [get]
func GetNodeTaskList(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
tasks, err := model.GetNodeTaskList(bson.ObjectIdHex(id))
if err != nil {
HandleError(http.StatusInternalServerError, c, err)
@@ -145,7 +153,10 @@ func GetNodeTaskList(c *gin.Context) {
// @Router /nodes/{id}/system [get]
func GetSystemInfo(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
sysInfo, _ := services.GetSystemInfo(id)
c.JSON(http.StatusOK, Response{
@@ -166,6 +177,10 @@ func GetSystemInfo(c *gin.Context) {
// @Router /nodes/{id} [delete]
func DeleteNode(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
node, err := model.GetNode(bson.ObjectIdHex(id))
if err != nil {
HandleError(http.StatusInternalServerError, c, err)

View File

@@ -41,7 +41,10 @@ func GetScheduleList(c *gin.Context) {
// @Router /schedules/{id} [get]
func GetSchedule(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
result, err := model.GetSchedule(bson.ObjectIdHex(id))
if err != nil {
HandleError(http.StatusInternalServerError, c, err)
@@ -64,7 +67,10 @@ func GetSchedule(c *gin.Context) {
// @Router /schedules/{id} [post]
func PostSchedule(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
// 绑定数据模型
var newItem model.Schedule
if err := c.ShouldBindJSON(&newItem); err != nil {
@@ -148,7 +154,10 @@ func PutSchedule(c *gin.Context) {
// @Router /schedules/{id} [delete]
func DeleteSchedule(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
// 删除定时任务
if err := model.RemoveSchedule(bson.ObjectIdHex(id)); err != nil {
HandleError(http.StatusInternalServerError, c, err)
@@ -177,6 +186,10 @@ func DeleteSchedule(c *gin.Context) {
// @Router /schedules/{id}/disable [post]
func DisableSchedule(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
if err := services.Sched.Disable(bson.ObjectIdHex(id)); err != nil {
HandleError(http.StatusInternalServerError, c, err)
return
@@ -197,6 +210,10 @@ func DisableSchedule(c *gin.Context) {
// @Router /schedules/{id}/enable [post]
func EnableSchedule(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
if err := services.Sched.Enable(bson.ObjectIdHex(id)); err != nil {
HandleError(http.StatusInternalServerError, c, err)
return

View File

@@ -567,7 +567,10 @@ func UploadSpiderFromId(c *gin.Context) {
// TODO: 与 UploadSpider 部分逻辑重复,需要优化代码
// 爬虫ID
spiderId := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
// 获取爬虫
spider, err := model.GetSpider(bson.ObjectIdHex(spiderId))
if err != nil {
@@ -877,7 +880,10 @@ func RunSelectedSpider(c *gin.Context) {
// @Router /spiders/{id}/tasks [get]
func GetSpiderTasks(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
spider, err := model.GetSpider(bson.ObjectIdHex(id))
if err != nil {
HandleError(http.StatusInternalServerError, c, err)
@@ -924,7 +930,10 @@ func GetSpiderStats(c *gin.Context) {
}
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
spider, err := model.GetSpider(bson.ObjectIdHex(id))
if err != nil {
log.Errorf(err.Error())
@@ -1074,7 +1083,10 @@ func GetSpiderSchedules(c *gin.Context) {
func GetSpiderDir(c *gin.Context) {
// 爬虫ID
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
// 目录相对路径
path := c.Query("path")
@@ -1131,7 +1143,10 @@ type SpiderFileReqBody struct {
func GetSpiderFile(c *gin.Context) {
// 爬虫ID
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
// 文件相对路径
path := c.Query("path")
@@ -1168,7 +1183,10 @@ func GetSpiderFile(c *gin.Context) {
func GetSpiderFileTree(c *gin.Context) {
// 爬虫ID
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
// 获取爬虫
spider, err := model.GetSpider(bson.ObjectIdHex(id))
if err != nil {
@@ -1208,7 +1226,10 @@ func GetSpiderFileTree(c *gin.Context) {
func PostSpiderFile(c *gin.Context) {
// 爬虫ID
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
// 文件相对路径
var reqBody SpiderFileReqBody
if err := c.ShouldBindJSON(&reqBody); err != nil {
@@ -1254,6 +1275,10 @@ func PostSpiderFile(c *gin.Context) {
// @Router /spiders/{id}/file [post]
func PutSpiderFile(c *gin.Context) {
spiderId := c.Param("id")
if !bson.IsObjectIdHex(spiderId) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
var reqBody SpiderFileReqBody
if err := c.ShouldBindJSON(&reqBody); err != nil {
HandleError(http.StatusBadRequest, c, err)
@@ -1304,6 +1329,10 @@ func PutSpiderFile(c *gin.Context) {
// @Router /spiders/{id}/file [put]
func PutSpiderDir(c *gin.Context) {
spiderId := c.Param("id")
if !bson.IsObjectIdHex(spiderId) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
var reqBody SpiderFileReqBody
if err := c.ShouldBindJSON(&reqBody); err != nil {
HandleError(http.StatusBadRequest, c, err)
@@ -1354,6 +1383,10 @@ func PutSpiderDir(c *gin.Context) {
// @Router /spiders/{id}/file [delete]
func DeleteSpiderFile(c *gin.Context) {
spiderId := c.Param("id")
if !bson.IsObjectIdHex(spiderId) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
var reqBody SpiderFileReqBody
if err := c.ShouldBindJSON(&reqBody); err != nil {
HandleError(http.StatusBadRequest, c, err)
@@ -1394,6 +1427,11 @@ func DeleteSpiderFile(c *gin.Context) {
// @Router /spiders/{id}/file/rename [post]
func RenameSpiderFile(c *gin.Context) {
spiderId := c.Param("id")
if !bson.IsObjectIdHex(spiderId) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
var reqBody SpiderFileReqBody
if err := c.ShouldBindJSON(&reqBody); err != nil {
HandleError(http.StatusBadRequest, c, err)
@@ -1494,7 +1532,10 @@ func PutSpiderScrapySpiders(c *gin.Context) {
}
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
var reqBody ReqBody
if err := c.ShouldBindJSON(&reqBody); err != nil {
HandleErrorF(http.StatusBadRequest, c, "invalid request")
@@ -1724,7 +1765,10 @@ func GetSpiderScrapyPipelines(c *gin.Context) {
// @Router /spiders/{id}/scrapy/spider/filepath [get]
func GetSpiderScrapySpiderFilepath(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
spiderName := c.Query("spider_name")
if spiderName == "" {
HandleErrorF(http.StatusBadRequest, c, "spider_name is empty")

View File

@@ -7,6 +7,7 @@ import (
"crawlab/services/rpc"
"fmt"
"github.com/gin-gonic/gin"
"github.com/globalsign/mgo/bson"
"net/http"
"strings"
)
@@ -22,6 +23,10 @@ import (
// @Router /nodes/{id}/langs [get]
func GetLangList(c *gin.Context) {
nodeId := c.Param("id")
if !bson.IsObjectIdHex(nodeId) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
c.JSON(http.StatusOK, Response{
Status: "ok",
Message: "success",
@@ -44,7 +49,10 @@ func GetDepList(c *gin.Context) {
nodeId := c.Param("id")
lang := c.Query("lang")
depName := c.Query("dep_name")
if !bson.IsObjectIdHex(nodeId) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
var depList []entity.Dependency
if lang == constants.Python {
list, err := services.GetPythonDepList(nodeId, depName)
@@ -85,6 +93,11 @@ func GetDepList(c *gin.Context) {
func GetInstalledDepList(c *gin.Context) {
nodeId := c.Param("id")
lang := c.Query("lang")
if !bson.IsObjectIdHex(nodeId) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
var depList []entity.Dependency
if services.IsMasterNode(nodeId) {
list, err := rpc.GetInstalledDepsLocal(lang)
@@ -177,7 +190,10 @@ func InstallDep(c *gin.Context) {
}
nodeId := c.Param("id")
if !bson.IsObjectIdHex(nodeId) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
var reqBody ReqBody
if err := c.ShouldBindJSON(&reqBody); err != nil {
HandleError(http.StatusBadRequest, c, err)
@@ -218,7 +234,10 @@ func UninstallDep(c *gin.Context) {
}
nodeId := c.Param("id")
if !bson.IsObjectIdHex(nodeId) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
var reqBody ReqBody
if err := c.ShouldBindJSON(&reqBody); err != nil {
HandleError(http.StatusBadRequest, c, err)
@@ -292,7 +311,10 @@ func InstallLang(c *gin.Context) {
}
nodeId := c.Param("id")
if !bson.IsObjectIdHex(nodeId) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
var reqBody ReqBody
if err := c.ShouldBindJSON(&reqBody); err != nil {
HandleError(http.StatusBadRequest, c, err)

View File

@@ -101,7 +101,10 @@ func GetTaskList(c *gin.Context) {
// @Router /tasks/{id} [get]
func GetTask(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
result, err := model.GetTask(id)
if err != nil {
HandleError(http.StatusInternalServerError, c, err)
@@ -273,7 +276,10 @@ func DeleteSelectedTask(c *gin.Context) {
// @Router /task/{id} [delete]
func DeleteTask(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
// 删除日志文件
if err := services.RemoveLogByTaskId(id); err != nil {
HandleError(http.StatusInternalServerError, c, err)
@@ -303,6 +309,10 @@ func GetTaskLog(c *gin.Context) {
Keyword string `form:"keyword"`
}
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
var reqData RequestData
if err := c.ShouldBindQuery(&reqData); err != nil {
HandleErrorF(http.StatusBadRequest, c, "invalid request")
@@ -332,6 +342,10 @@ func GetTaskLog(c *gin.Context) {
// @Router /tasks/{id}/error-log [delete]
func GetTaskErrorLog(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
u := services.GetCurrentUser(c)
errLogItems, err := services.GetTaskErrorLog(id, u.Setting.MaxErrorLog)
if err != nil {
@@ -357,7 +371,10 @@ func GetTaskErrorLog(c *gin.Context) {
// @Router /tasks/{id}/results [get]
func GetTaskResults(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
// 绑定数据
data := TaskResultsRequestData{}
if err := c.ShouldBindQuery(&data); err != nil {
@@ -387,7 +404,6 @@ func GetTaskResults(c *gin.Context) {
})
}
// @Summary Get task results
// @Description Get task results
// @Tags task
@@ -399,7 +415,10 @@ func GetTaskResults(c *gin.Context) {
// @Router /tasks/{id}/results/download [get]
func DownloadTaskResultsCsv(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
// 获取任务
task, err := model.GetTask(id)
if err != nil {
@@ -466,7 +485,6 @@ func DownloadTaskResultsCsv(c *gin.Context) {
c.Data(http.StatusOK, "text/csv", bytesBuffer.Bytes())
}
// @Summary Cancel task
// @Description Cancel task
// @Tags task
@@ -478,7 +496,10 @@ func DownloadTaskResultsCsv(c *gin.Context) {
// @Router /tasks/{id}/cancel [post]
func CancelTask(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
if err := services.CancelTask(id); err != nil {
HandleError(http.StatusInternalServerError, c, err)
return
@@ -497,7 +518,10 @@ func CancelTask(c *gin.Context) {
// @Router /tasks/{id}/restart [post]
func RestartTask(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
uid := services.GetCurrentUserId(c)
if err := services.RestartTask(id, uid); err != nil {

View File

@@ -80,7 +80,10 @@ func PutToken(c *gin.Context) {
// @Router /tokens/{id} [delete]
func DeleteToken(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
if err := model.DeleteTokenById(bson.ObjectIdHex(id)); err != nil {
HandleError(http.StatusInternalServerError, c, err)
return

View File

@@ -36,7 +36,10 @@ type UserRequestData struct {
// @Router /users/{id} [get]
func GetUser(c *gin.Context) {
id := c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
user, err := model.GetUser(bson.ObjectIdHex(id))
if err != nil {
HandleError(http.StatusInternalServerError, c, err)

View File

@@ -45,6 +45,11 @@ func PutVariable(c *gin.Context) {
// @Router /variable/{id} [post]
func PostVariable(c *gin.Context) {
var id = c.Param("id")
if !bson.IsObjectIdHex(id) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
var variable model.Variable
if err := c.ShouldBindJSON(&variable); err != nil {
HandleError(http.StatusBadRequest, c, err)
@@ -71,6 +76,10 @@ func PostVariable(c *gin.Context) {
// @Router /variable/{id} [delete]
func DeleteVariable(c *gin.Context) {
var idStr = c.Param("id")
if !bson.IsObjectIdHex(idStr) {
HandleErrorF(http.StatusBadRequest, c, "invalid id")
return
}
var id = bson.ObjectIdHex(idStr)
variable, err := model.GetVariable(id)
if err != nil {