This commit is contained in:
@@ -265,6 +265,9 @@ func main() {
|
||||
scriptsGroup.POST("/folder", scriptManageHandlers.CreateFolder)
|
||||
scriptsGroup.DELETE("/folder", scriptManageHandlers.DeleteFolder)
|
||||
|
||||
// Rename script or folder
|
||||
scriptsGroup.POST("/rename", scriptManageHandlers.Rename)
|
||||
|
||||
// Get script by path
|
||||
scriptsGroup.GET("/by-path", scriptManageHandlers.GetScriptByPath)
|
||||
}
|
||||
|
||||
@@ -2018,6 +2018,73 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/scripts/rename": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"description": "Renames a single script or all scripts under a folder prefix",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"scripts"
|
||||
],
|
||||
"summary": "Rename script or folder",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Rename request",
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/internal_handlers.RenameRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Rename result with count of renamed scripts",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not Found",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"409": {
|
||||
"description": "Conflict",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/scripts/run": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -2798,6 +2865,23 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"internal_handlers.RenameRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"new_path",
|
||||
"old_path"
|
||||
],
|
||||
"properties": {
|
||||
"new_path": {
|
||||
"type": "string",
|
||||
"example": "deploy/nginx-v2"
|
||||
},
|
||||
"old_path": {
|
||||
"type": "string",
|
||||
"example": "deploy/nginx"
|
||||
}
|
||||
}
|
||||
},
|
||||
"internal_handlers.RunScriptIn": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
||||
@@ -2007,6 +2007,73 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/scripts/rename": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"description": "Renames a single script or all scripts under a folder prefix",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"scripts"
|
||||
],
|
||||
"summary": "Rename script or folder",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Rename request",
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/internal_handlers.RenameRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Rename result with count of renamed scripts",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not Found",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"409": {
|
||||
"description": "Conflict",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/scripts/run": {
|
||||
"post": {
|
||||
"security": [
|
||||
@@ -2787,6 +2854,23 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"internal_handlers.RenameRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"new_path",
|
||||
"old_path"
|
||||
],
|
||||
"properties": {
|
||||
"new_path": {
|
||||
"type": "string",
|
||||
"example": "deploy/nginx-v2"
|
||||
},
|
||||
"old_path": {
|
||||
"type": "string",
|
||||
"example": "deploy/nginx"
|
||||
}
|
||||
}
|
||||
},
|
||||
"internal_handlers.RunScriptIn": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
||||
@@ -477,6 +477,18 @@ definitions:
|
||||
client_cert:
|
||||
type: string
|
||||
type: object
|
||||
internal_handlers.RenameRequest:
|
||||
properties:
|
||||
new_path:
|
||||
example: deploy/nginx-v2
|
||||
type: string
|
||||
old_path:
|
||||
example: deploy/nginx
|
||||
type: string
|
||||
required:
|
||||
- new_path
|
||||
- old_path
|
||||
type: object
|
||||
internal_handlers.RunScriptIn:
|
||||
properties:
|
||||
agent_id:
|
||||
@@ -1809,6 +1821,49 @@ paths:
|
||||
summary: Update interpreter
|
||||
tags:
|
||||
- scripts
|
||||
/scripts/rename:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Renames a single script or all scripts under a folder prefix
|
||||
parameters:
|
||||
- description: Rename request
|
||||
in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/internal_handlers.RenameRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Rename result with count of renamed scripts
|
||||
schema:
|
||||
additionalProperties: true
|
||||
type: object
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
"404":
|
||||
description: Not Found
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
"409":
|
||||
description: Conflict
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
security:
|
||||
- Bearer: []
|
||||
summary: Rename script or folder
|
||||
tags:
|
||||
- scripts
|
||||
/scripts/run:
|
||||
post:
|
||||
consumes:
|
||||
|
||||
@@ -280,6 +280,96 @@ type DeleteFolderRequest struct {
|
||||
Path string `json:"path" binding:"required" example:"deploy/nginx" description:"Folder path to delete"`
|
||||
}
|
||||
|
||||
// RenameRequest is the request body for renaming a script or folder.
|
||||
type RenameRequest struct {
|
||||
OldPath string `json:"old_path" binding:"required" example:"deploy/nginx" description:"Current path"`
|
||||
NewPath string `json:"new_path" binding:"required" example:"deploy/nginx-v2" description:"New path"`
|
||||
}
|
||||
|
||||
// Rename renames a script or all scripts under a folder path.
|
||||
// @Summary Rename script or folder
|
||||
// @Description Renames a single script or all scripts under a folder prefix
|
||||
// @Tags scripts
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body RenameRequest true "Rename request"
|
||||
// @Success 200 {object} map[string]interface{} "Rename result with count of renamed scripts"
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Failure 409 {object} map[string]string
|
||||
// @Security Bearer
|
||||
// @Router /scripts/rename [post]
|
||||
func (sh *ScriptHandlersGroup) Rename(c *gin.Context) {
|
||||
var req RenameRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"})
|
||||
return
|
||||
}
|
||||
|
||||
// Validate new path
|
||||
if err := validateScriptPath(req.NewPath); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("invalid new path: %v", err)})
|
||||
return
|
||||
}
|
||||
|
||||
// Validate old path
|
||||
if err := validateScriptPath(req.OldPath); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("invalid old path: %v", err)})
|
||||
return
|
||||
}
|
||||
|
||||
// Get all scripts
|
||||
allScripts, err := sh.svc.Repo.ListScripts()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list scripts"})
|
||||
return
|
||||
}
|
||||
|
||||
// Find scripts to rename: exact match or folder prefix
|
||||
prefix := req.OldPath + "/"
|
||||
var toRename []repository.Script
|
||||
for _, script := range allScripts {
|
||||
if script.Path == req.OldPath || strings.HasPrefix(script.Path, prefix) {
|
||||
toRename = append(toRename, script)
|
||||
}
|
||||
}
|
||||
|
||||
if len(toRename) == 0 {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "no scripts found with this path"})
|
||||
return
|
||||
}
|
||||
|
||||
// Rename each script
|
||||
renamedCount := 0
|
||||
for _, script := range toRename {
|
||||
newPath := req.NewPath + strings.TrimPrefix(script.Path, req.OldPath)
|
||||
|
||||
// Check if new path already exists (excluding the scripts we're renaming)
|
||||
for _, existing := range allScripts {
|
||||
if existing.ID != script.ID && existing.Path == newPath {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": fmt.Sprintf("path '%s' already exists", newPath)})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
_, err := sh.svc.Repo.UpdateScript(script.ID, repository.ScriptUpdate{
|
||||
Path: &newPath,
|
||||
})
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("failed to rename %s: %v", script.Path, err)})
|
||||
return
|
||||
}
|
||||
renamedCount++
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "renamed",
|
||||
"old_path": req.OldPath,
|
||||
"new_path": req.NewPath,
|
||||
"renamed_count": renamedCount,
|
||||
})
|
||||
}
|
||||
|
||||
// CreateFolder creates a virtual folder in the script tree.
|
||||
// @Summary Create folder
|
||||
// @Description Creates a virtual folder by creating a placeholder script with the folder path
|
||||
|
||||
Reference in New Issue
Block a user