diff --git a/internal/cron/sftp_cron.go b/internal/cron/sftp_cron.go index 8d24c39..d412caf 100644 --- a/internal/cron/sftp_cron.go +++ b/internal/cron/sftp_cron.go @@ -7,7 +7,6 @@ import ( "github.com/pterodactyl/wings/internal/models" "github.com/pterodactyl/wings/server" "github.com/pterodactyl/wings/system" - "gorm.io/gorm" "reflect" ) @@ -79,17 +78,13 @@ func (sc *sftpCron) Run(ctx context.Context) error { if len(events.m) == 0 { return nil } - - err = database.Instance().Transaction(func(tx *gorm.DB) error { - tx.Where("id IN ?", events.ids).Delete(&models.Activity{}) - if tx.Error != nil { - return tx.Error - } - - return sc.manager.Client().SendActivityLogs(ctx, events.Elements()) - }) - - return errors.WithStack(err) + if err := sc.manager.Client().SendActivityLogs(ctx, events.Elements()); err != nil { + return errors.Wrap(err, "failed to send sftp activity logs to Panel") + } + if tx := database.Instance().Where("id IN ?", events.ids).Delete(&models.Activity{}); tx.Error != nil { + return errors.WithStack(tx.Error) + } + return nil } // fetchRecords returns a group of activity events starting at the given offset. This is used diff --git a/router/websocket/websocket.go b/router/websocket/websocket.go index d30b5eb..a1a56c4 100644 --- a/router/websocket/websocket.go +++ b/router/websocket/websocket.go @@ -370,7 +370,7 @@ func (h *Handler) HandleInbound(ctx context.Context, m Message) error { } if err == nil { - _ = h.ra.Save(h.server, models.Event(server.ActivityPowerPrefix+action), nil) + h.server.SaveActivity(h.ra, models.Event(server.ActivityPowerPrefix+action), nil) } return err @@ -429,11 +429,13 @@ func (h *Handler) HandleInbound(ctx context.Context, m Message) error { } } - _ = h.ra.Save(h.server, server.ActivityConsoleCommand, models.ActivityMeta{ + if err := h.server.Environment.SendCommand(strings.Join(m.Args, "")); err != nil { + return err + } + h.server.SaveActivity(h.ra, server.ActivityConsoleCommand, models.ActivityMeta{ "command": strings.Join(m.Args, ""), }) - - return h.server.Environment.SendCommand(strings.Join(m.Args, "")) + return nil } } diff --git a/server/activity.go b/server/activity.go index edca85e..0c9ddbc 100644 --- a/server/activity.go +++ b/server/activity.go @@ -1,9 +1,11 @@ package server import ( + "context" "emperror.dev/errors" "github.com/pterodactyl/wings/internal/database" "github.com/pterodactyl/wings/internal/models" + "time" ) const ActivityPowerPrefix = "server:power." @@ -34,29 +36,6 @@ func (ra RequestActivity) Event(event models.Event, metadata models.ActivityMeta return a.SetUser(ra.user) } -// Save creates a new event instance and saves it. If an error is encountered it is automatically -// logged to the provided server's error logging output. The error is also returned to the caller -// but can be ignored. -func (ra RequestActivity) Save(s *Server, event models.Event, metadata models.ActivityMeta) error { - if tx := database.Instance().Create(ra.Event(event, metadata)); tx.Error != nil { - err := errors.WithStackIf(tx.Error) - - s.Log().WithField("error", err).WithField("event", event).Error("activity: failed to save event") - - return err - } - return nil -} - -// IP returns the IP address associated with this entry. -func (ra RequestActivity) IP() string { - return ra.ip -} - -func (ra *RequestActivity) User() string { - return ra.user -} - // SetUser clones the RequestActivity struct and sets a new user value on the copy // before returning it. func (ra RequestActivity) SetUser(u string) RequestActivity { @@ -68,3 +47,17 @@ func (ra RequestActivity) SetUser(u string) RequestActivity { func (s *Server) NewRequestActivity(user string, ip string) RequestActivity { return RequestActivity{server: s.ID(), user: user, ip: ip} } + +// SaveActivity saves an activity entry to the database in a background routine. If an error is +// encountered it is logged but not returned to the caller. +func (s *Server) SaveActivity(a RequestActivity, event models.Event, metadata models.ActivityMeta) { + ctx, cancel := context.WithTimeout(s.Context(), time.Second*3) + go func() { + defer cancel() + if tx := database.Instance().WithContext(ctx).Create(a.Event(event, metadata)); tx.Error != nil { + s.Log().WithField("error", errors.WithStack(tx.Error)). + WithField("event", event). + Error("activity: failed to save event") + } + }() +}