76 lines
2.0 KiB
Go
76 lines
2.0 KiB
Go
package server
|
|
|
|
import (
|
|
"io"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/x-grk/longpolling-remote-access/internal/proto"
|
|
)
|
|
|
|
// fsOps maps the URL op segment to a proto task type.
|
|
var fsOps = map[string]string{
|
|
"list": proto.TaskFSList,
|
|
"read": proto.TaskFSRead,
|
|
"write": proto.TaskFSWrite,
|
|
"mkdir": proto.TaskFSMkdir,
|
|
"delete": proto.TaskFSDelete,
|
|
"deltree": proto.TaskFSDelTree,
|
|
"unzip": proto.TaskFSUnzip,
|
|
"zip": proto.TaskFSZip,
|
|
"move": proto.TaskFSMove,
|
|
"stat": proto.TaskFSStat,
|
|
"chmod": proto.TaskFSChmod,
|
|
"copy": proto.TaskFSCopy,
|
|
}
|
|
|
|
// fsTaskTimeout bounds how long we wait for an agent to answer a file op.
|
|
const fsTaskTimeout = 60 * time.Second
|
|
|
|
func (s *Server) handleFilesPage(w http.ResponseWriter, r *http.Request) {
|
|
id := r.PathValue("id")
|
|
a, err := s.db.GetAgent(id)
|
|
if err != nil || a == nil {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
s.render(w, "files.html", map[string]any{"Agent": a, "EditLimit": proto.FSReadCap})
|
|
}
|
|
|
|
// POST /api/panel/agents/{id}/fs/{op} - run a file-manager operation on the
|
|
// agent and return its result. The request body is the op's JSON args and is
|
|
// forwarded verbatim to the agent.
|
|
func (s *Server) handleFSOp(w http.ResponseWriter, r *http.Request) {
|
|
agentID := r.PathValue("id")
|
|
op := r.PathValue("op")
|
|
taskType, ok := fsOps[op]
|
|
if !ok {
|
|
http.Error(w, "unknown op", http.StatusBadRequest)
|
|
return
|
|
}
|
|
a, err := s.db.GetAgent(agentID)
|
|
if err != nil || a == nil {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
if !s.online(a) {
|
|
writeJSON(w, proto.TaskResult{Error: "машина офлайн"})
|
|
return
|
|
}
|
|
args, err := io.ReadAll(http.MaxBytesReader(w, r.Body, 64<<20))
|
|
if err != nil {
|
|
http.Error(w, "bad request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
taskID, resultCh := s.hub.CreateTask(agentID, taskType, args)
|
|
defer s.hub.DiscardTask(taskID)
|
|
|
|
select {
|
|
case res := <-resultCh:
|
|
writeJSON(w, res)
|
|
case <-time.After(fsTaskTimeout):
|
|
writeJSON(w, proto.TaskResult{Error: "таймаут ожидания агента"})
|
|
}
|
|
}
|