Squashed commit of the following:
commitf5baab4e88Author: DaneEveritt <dane@daneeveritt.com> Date: Sat Jul 9 17:50:53 2022 -0400 Finalize activity event sending logic and cron config commit9830387f21Author: DaneEveritt <dane@daneeveritt.com> Date: Sat Jul 9 16:26:13 2022 -0400 Send power events in a more usable format commit49f3a61d16Author: DaneEveritt <dane@daneeveritt.com> Date: Sat Jul 9 15:47:24 2022 -0400 Configure cron to actually send to endpoint commit28137c4c14Author: DaneEveritt <dane@daneeveritt.com> Date: Sat Jul 9 15:42:29 2022 -0400 Copy the body buffer otherwise subsequent backoff attempts will not have a buffer to send commit20e44bdc55Author: DaneEveritt <dane@daneeveritt.com> Date: Sat Jul 9 14:38:41 2022 -0400 Add internal logic to process activity events and send them to the panel commit0380488cd2Author: DaneEveritt <dane@daneeveritt.com> Date: Mon Jul 4 17:55:17 2022 -0400 Track power events commit9eab08b92fAuthor: DaneEveritt <dane@daneeveritt.com> Date: Mon Jul 4 17:36:03 2022 -0400 Initial logic to support logging activity on Wings to send back to the panel
This commit is contained in:
@@ -66,6 +66,7 @@ func Configure(m *wserver.Manager, client remote.Client) *gin.Engine {
|
||||
server.DELETE("", deleteServer)
|
||||
|
||||
server.GET("/logs", getServerLogs)
|
||||
server.GET("/activity", getServerActivityLogs)
|
||||
server.POST("/power", postServerPower)
|
||||
server.POST("/commands", postServerCommands)
|
||||
server.POST("/install", postServerInstall)
|
||||
|
||||
@@ -2,6 +2,9 @@ package router
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/goccy/go-json"
|
||||
"github.com/pterodactyl/wings/internal/database"
|
||||
"github.com/xujiajun/nutsdb"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
@@ -40,6 +43,44 @@ func getServerLogs(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"data": out})
|
||||
}
|
||||
|
||||
// Returns the activity logs tracked internally for the server instance. Note that these
|
||||
// logs are routinely cleared out as Wings communicates directly with the Panel to pass
|
||||
// along all of the logs for servers it monitors. As activities are passed to the panel
|
||||
// they are deleted from Wings.
|
||||
//
|
||||
// As a result, this endpoint may or may not return data, and the data returned can change
|
||||
// between requests.
|
||||
func getServerActivityLogs(c *gin.Context) {
|
||||
s := ExtractServer(c)
|
||||
|
||||
var out [][]byte
|
||||
err := database.DB().View(func(tx *nutsdb.Tx) error {
|
||||
items, err := tx.LRange(database.ServerActivityBucket, []byte(s.ID()), 0, 10)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out = items
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
middleware.CaptureAndAbort(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
var activity []*server.Activity
|
||||
for _, b := range out {
|
||||
var a server.Activity
|
||||
if err := json.Unmarshal(b, &a); err != nil {
|
||||
middleware.CaptureAndAbort(c, err)
|
||||
return
|
||||
}
|
||||
activity = append(activity, &a)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"data": activity})
|
||||
}
|
||||
|
||||
// Handles a request to control the power state of a server. If the action being passed
|
||||
// through is invalid a 404 is returned. Otherwise, a HTTP/202 Accepted response is returned
|
||||
// and the actual power action is run asynchronously so that we don't have to block the
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/gbrlsnchs/jwt/v3"
|
||||
"github.com/goccy/go-json"
|
||||
)
|
||||
|
||||
// The time at which Wings was booted. No JWT's created before this time are allowed to
|
||||
@@ -35,15 +34,15 @@ func DenyJTI(jti string) {
|
||||
denylist.Store(jti, time.Now())
|
||||
}
|
||||
|
||||
// A JWT payload for Websocket connections. This JWT is passed along to the Websocket after
|
||||
// it has been connected to by sending an "auth" event.
|
||||
// WebsocketPayload defines the JWT payload for a websocket connection. This JWT is passed along to
|
||||
// the websocket after it has been connected to by sending an "auth" event.
|
||||
type WebsocketPayload struct {
|
||||
jwt.Payload
|
||||
sync.RWMutex
|
||||
|
||||
UserID json.Number `json:"user_id"`
|
||||
ServerUUID string `json:"server_uuid"`
|
||||
Permissions []string `json:"permissions"`
|
||||
UserUUID string `json:"user_uuid"`
|
||||
ServerUUID string `json:"server_uuid"`
|
||||
Permissions []string `json:"permissions"`
|
||||
}
|
||||
|
||||
// Returns the JWT payload.
|
||||
|
||||
@@ -40,6 +40,7 @@ type Handler struct {
|
||||
Connection *websocket.Conn `json:"-"`
|
||||
jwt *tokens.WebsocketPayload
|
||||
server *server.Server
|
||||
ra server.RequestActivity
|
||||
uuid uuid.UUID
|
||||
}
|
||||
|
||||
@@ -109,6 +110,7 @@ func GetHandler(s *server.Server, w http.ResponseWriter, r *http.Request) (*Hand
|
||||
Connection: conn,
|
||||
jwt: nil,
|
||||
server: s,
|
||||
ra: s.NewRequestActivity("", r.RemoteAddr),
|
||||
uuid: u,
|
||||
}, nil
|
||||
}
|
||||
@@ -264,6 +266,7 @@ func (h *Handler) GetJwt() *tokens.WebsocketPayload {
|
||||
// setJwt sets the JWT for the websocket in a race-safe manner.
|
||||
func (h *Handler) setJwt(token *tokens.WebsocketPayload) {
|
||||
h.Lock()
|
||||
h.ra = h.ra.SetUser(token.UserUUID)
|
||||
h.jwt = token
|
||||
h.Unlock()
|
||||
}
|
||||
@@ -365,6 +368,10 @@ func (h *Handler) HandleInbound(ctx context.Context, m Message) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
_ = h.ra.Save(h.server, server.Event(server.ActivityPowerPrefix+action), nil)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
case SendServerLogsEvent:
|
||||
@@ -421,6 +428,10 @@ func (h *Handler) HandleInbound(ctx context.Context, m Message) error {
|
||||
}
|
||||
}
|
||||
|
||||
_ = h.ra.Save(h.server, server.ActivityConsoleCommand, server.ActivityMeta{
|
||||
"command": strings.Join(m.Args, ""),
|
||||
})
|
||||
|
||||
return h.server.Environment.SendCommand(strings.Join(m.Args, ""))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user