From 334b3e8d1093d1fbe5c4fcf4e61e7c1114791e08 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sat, 31 Oct 2020 10:04:20 -0700 Subject: [PATCH] Refactor HTTP endpoints to be less complicated and follow better standards --- api/api.go | 150 +++++++++++++++++++------------------- api/backup_endpoints.go | 13 +--- api/error.go | 28 +++++++ api/server_endpoints.go | 137 ++++++++++++---------------------- api/sftp_endpoints.go | 31 +++----- installer/installer.go | 8 +- router/router_transfer.go | 26 +++---- server/backup.go | 10 +-- server/install.go | 20 +++-- server/loader.go | 8 +- server/server.go | 15 ++-- sftp/sftp.go | 2 +- 12 files changed, 203 insertions(+), 245 deletions(-) create mode 100644 api/error.go diff --git a/api/api.go b/api/api.go index 3849c7b..3367445 100644 --- a/api/api.go +++ b/api/api.go @@ -7,6 +7,8 @@ import ( "github.com/apex/log" "github.com/pkg/errors" "github.com/pterodactyl/wings/config" + "github.com/pterodactyl/wings/system" + "io" "io/ioutil" "net/http" "strings" @@ -14,30 +16,34 @@ import ( ) // Initializes the requester instance. -func NewRequester() *PanelRequest { - return &PanelRequest{ - Response: nil, - } +func New() *Request { + return &Request{} } -type PanelRequest struct { - Response *http.Response +// A generic type allowing for easy binding use when making requests to API endpoints +// that only expect a singular argument or something that would not benefit from being +// a typed struct. +// +// Inspired by gin.H, same concept. +type D map[string]interface{} + +// A custom API requester struct for Wings. +type Request struct{} + +// A custom response type that allows for commonly used error handling and response +// parsing from the Panel API. This just embeds the normal HTTP response from Go and +// we attach a few helper functions to it. +type Response struct { + *http.Response } // Builds the base request instance that can be used with the HTTP client. -func (r *PanelRequest) GetClient() *http.Client { +func (r *Request) Client() *http.Client { return &http.Client{Timeout: time.Second * 30} } -func (r *PanelRequest) SetHeaders(req *http.Request) *http.Request { - req.Header.Set("Accept", "application/vnd.pterodactyl.v1+json") - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Authorization", fmt.Sprintf("Bearer %s.%s", config.Get().AuthenticationTokenId, config.Get().AuthenticationToken)) - - return req -} - -func (r *PanelRequest) GetEndpoint(endpoint string) string { +// Returns the given endpoint formatted as a URL to the Panel API. +func (r *Request) Endpoint(endpoint string) string { return fmt.Sprintf( "%s/api/remote/%s", strings.TrimSuffix(config.Get().PanelLocation, "/"), @@ -45,9 +51,29 @@ func (r *PanelRequest) GetEndpoint(endpoint string) string { ) } +// Makes a HTTP request to the given endpoint, attaching the necessary request headers from +// Wings to ensure that the request is properly handled by the Panel. +func (r *Request) Make(method, url string, body io.Reader) (*Response, error) { + req, err := http.NewRequest(method, url, body) + if err != nil { + return nil, errors.WithStack(err) + } + + req.Header.Set("User-Agent", fmt.Sprintf("Pterodactyl Wings/v%s (id:%s)", system.Version, config.Get().AuthenticationTokenId)) + req.Header.Set("Accept", "application/vnd.pterodactyl.v1+json") + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s.%s", config.Get().AuthenticationTokenId, config.Get().AuthenticationToken)) + + r.debug(req) + + res, err := r.Client().Do(req) + + return &Response{Response: res}, err +} + // Logs the request into the debug log with all of the important request bits. // The authorization key will be cleaned up before being output. -func (r *PanelRequest) logDebug(req *http.Request) { +func (r *Request) debug(req *http.Request) { headers := make(map[string][]string) for k, v := range req.Header { if k != "Authorization" || len(v) == 0 { @@ -65,49 +91,42 @@ func (r *PanelRequest) logDebug(req *http.Request) { }).Debug("making request to external HTTP endpoint") } -func (r *PanelRequest) Get(url string) (*http.Response, error) { - c := r.GetClient() - - req, err := http.NewRequest(http.MethodGet, r.GetEndpoint(url), nil) - req = r.SetHeaders(req) - +// Makes a GET request to the given Panel API endpoint. If any data is passed as the +// second argument it will be passed through on the request as URL parameters. +func (r *Request) Get(url string, data interface{}) (*Response, error) { + b, err := json.Marshal(data) if err != nil { - return nil, err + return nil, errors.WithStack(err) } - r.logDebug(req) - - return c.Do(req) + return r.Make(http.MethodGet, r.Endpoint(url), bytes.NewBuffer(b)) } -func (r *PanelRequest) Post(url string, data []byte) (*http.Response, error) { - c := r.GetClient() - - req, err := http.NewRequest(http.MethodPost, r.GetEndpoint(url), bytes.NewBuffer(data)) - req = r.SetHeaders(req) - +// Makes a POST request to the given Panel API endpoint. +func (r *Request) Post(url string, data interface{}) (*Response, error) { + b, err := json.Marshal(data) if err != nil { - return nil, err + return nil, errors.WithStack(err) } - r.logDebug(req) - - return c.Do(req) + return r.Make(http.MethodPost, r.Endpoint(url), bytes.NewBuffer(b)) } // Determines if the API call encountered an error. If no request has been made -// the response will be false. -func (r *PanelRequest) HasError() bool { +// the response will be false. This function will evaluate to true if the response +// code is anything 300 or higher. +func (r *Response) HasError() bool { if r.Response == nil { return false } - return r.Response.StatusCode >= 300 || r.Response.StatusCode < 200 + return r.StatusCode >= 300 || r.StatusCode < 200 } // Reads the body from the response and returns it, then replaces it on the response -// so that it can be read again later. -func (r *PanelRequest) ReadBody() ([]byte, error) { +// so that it can be read again later. This does not close the response body, so any +// functions calling this should be sure to manually defer a Body.Close() call. +func (r *Response) Read() ([]byte, error) { var b []byte if r.Response == nil { return nil, errors.New("no response exists on interface") @@ -122,49 +141,28 @@ func (r *PanelRequest) ReadBody() ([]byte, error) { return b, nil } -func (r *PanelRequest) HttpResponseCode() int { - if r.Response == nil { - return 0 +// Binds a given interface with the data returned in the response. This is a shortcut +// for calling Read and then manually calling json.Unmarshal on the raw bytes. +func (r *Response) Bind(v interface{}) error { + b, err := r.Read() + if err != nil { + return errors.WithStack(err) } - return r.Response.StatusCode -} - -func IsRequestError(err error) bool { - _, ok := err.(*RequestError) - - return ok -} - -type RequestError struct { - response *http.Response - Code string `json:"code"` - Status string `json:"status"` - Detail string `json:"detail"` -} - -// Returns the error response in a string form that can be more easily consumed. -func (re *RequestError) Error() string { - return fmt.Sprintf("Error response from Panel: %s: %s (HTTP/%d)", re.Code, re.Detail, re.response.StatusCode) -} - -func (re *RequestError) String() string { - return re.Error() -} - -type RequestErrorBag struct { - Errors []RequestError `json:"errors"` + return errors.WithStack(json.Unmarshal(b, &v)) } // Returns the error message from the API call as a string. The error message will be formatted // similar to the below example: // // HttpNotFoundException: The requested resource does not exist. (HTTP/404) -func (r *PanelRequest) Error() *RequestError { - body, _ := r.ReadBody() +func (r *Response) Error() *RequestError { + if !r.HasError() { + return nil + } - bag := RequestErrorBag{} - json.Unmarshal(body, &bag) + var bag RequestErrorBag + _ = r.Bind(&bag) e := new(RequestError) if len(bag.Errors) > 0 { diff --git a/api/backup_endpoints.go b/api/backup_endpoints.go index b7b8d9b..7e7ea4a 100644 --- a/api/backup_endpoints.go +++ b/api/backup_endpoints.go @@ -15,22 +15,17 @@ type BackupRequest struct { // Notifies the panel that a specific backup has been completed and is now // available for a user to view and download. -func (r *PanelRequest) SendBackupStatus(backup string, data BackupRequest) (*RequestError, error) { +func (r *Request) SendBackupStatus(backup string, data BackupRequest) error { b, err := json.Marshal(data) if err != nil { - return nil, errors.WithStack(err) + return errors.WithStack(err) } resp, err := r.Post(fmt.Sprintf("/backups/%s", backup), b) if err != nil { - return nil, errors.WithStack(err) + return errors.WithStack(err) } defer resp.Body.Close() - r.Response = resp - if r.HasError() { - return r.Error(), nil - } - - return nil, nil + return resp.Error() } diff --git a/api/error.go b/api/error.go new file mode 100644 index 0000000..72a747d --- /dev/null +++ b/api/error.go @@ -0,0 +1,28 @@ +package api + +import ( + "fmt" + "net/http" +) + +type RequestErrorBag struct { + Errors []RequestError `json:"errors"` +} + +type RequestError struct { + response *http.Response + Code string `json:"code"` + Status string `json:"status"` + Detail string `json:"detail"` +} + +func IsRequestError(err error) bool { + _, ok := err.(*RequestError) + + return ok +} + +// Returns the error response in a string form that can be more easily consumed. +func (re *RequestError) Error() string { + return fmt.Sprintf("Error response from Panel: %s: %s (HTTP/%d)", re.Code, re.Detail, re.response.StatusCode) +} diff --git a/api/server_endpoints.go b/api/server_endpoints.go index 0368b0c..b44f287 100644 --- a/api/server_endpoints.go +++ b/api/server_endpoints.go @@ -34,155 +34,108 @@ type InstallationScript struct { } // GetAllServerConfigurations fetches configurations for all servers assigned to this node. -func (r *PanelRequest) GetAllServerConfigurations() (map[string]json.RawMessage, *RequestError, error) { - resp, err := r.Get("/servers") +func (r *Request) GetAllServerConfigurations() (map[string]json.RawMessage, error) { + resp, err := r.Get("/servers", nil) if err != nil { - return nil, nil, errors.WithStack(err) + return nil, errors.WithStack(err) } defer resp.Body.Close() - r.Response = resp - - if r.HasError() { - return nil, r.Error(), nil + if resp.HasError() { + return nil, resp.Error() } - b, _ := r.ReadBody() - res := map[string]json.RawMessage{} - if len(b) == 2 { - return res, nil, nil + var res map[string]json.RawMessage + if err := resp.Bind(&res); err != nil { + return nil, errors.WithStack(err) } - if err := json.Unmarshal(b, &res); err != nil { - return nil, nil, errors.WithStack(err) - } - - return res, nil, nil + return res, nil } // Fetches the server configuration and returns the struct for it. -func (r *PanelRequest) GetServerConfiguration(uuid string) (ServerConfigurationResponse, *RequestError, error) { - res := ServerConfigurationResponse{} +func (r *Request) GetServerConfiguration(uuid string) (ServerConfigurationResponse, error) { + var cfg ServerConfigurationResponse - resp, err := r.Get(fmt.Sprintf("/servers/%s", uuid)) + resp, err := r.Get(fmt.Sprintf("/servers/%s", uuid), nil) if err != nil { - return res, nil, errors.WithStack(err) + return cfg, errors.WithStack(err) } defer resp.Body.Close() - r.Response = resp - if r.HasError() { - return res, r.Error(), nil + if resp.HasError() { + return cfg, resp.Error() } - b, _ := r.ReadBody() - if err := json.Unmarshal(b, &res); err != nil { - return res, nil, errors.WithStack(err) + if err := resp.Bind(&cfg); err != nil { + return cfg, errors.WithStack(err) } - return res, nil, nil + return cfg, nil } // Fetches installation information for the server process. -func (r *PanelRequest) GetInstallationScript(uuid string) (InstallationScript, *RequestError, error) { - res := InstallationScript{} - - resp, err := r.Get(fmt.Sprintf("/servers/%s/install", uuid)) +func (r *Request) GetInstallationScript(uuid string) (InstallationScript, error) { + var is InstallationScript + resp, err := r.Get(fmt.Sprintf("/servers/%s/install", uuid), nil) if err != nil { - return res, nil, errors.WithStack(err) + return is, errors.WithStack(err) } defer resp.Body.Close() - r.Response = resp - - if r.HasError() { - return res, r.Error(), nil + if resp.HasError() { + return is, resp.Error() } - b, _ := r.ReadBody() - - if err := json.Unmarshal(b, &res); err != nil { - return res, nil, errors.WithStack(err) + if err := resp.Bind(&is); err != nil { + return is, errors.WithStack(err) } - return res, nil, nil -} -type installRequest struct { - Successful bool `json:"successful"` + return is, nil } // Marks a server as being installed successfully or unsuccessfully on the panel. -func (r *PanelRequest) SendInstallationStatus(uuid string, successful bool) (*RequestError, error) { - b, err := json.Marshal(installRequest{Successful: successful}) +func (r *Request) SendInstallationStatus(uuid string, successful bool) error { + resp, err := r.Post(fmt.Sprintf("/servers/%s/install", uuid), D{"successful": successful}) if err != nil { - return nil, errors.WithStack(err) - } - - resp, err := r.Post(fmt.Sprintf("/servers/%s/install", uuid), b) - if err != nil { - return nil, errors.WithStack(err) + return errors.WithStack(err) } defer resp.Body.Close() - r.Response = resp - if r.HasError() { - return r.Error(), nil + if resp.HasError() { + return resp.Error() } - return nil, nil + return nil } -type archiveRequest struct { - Successful bool `json:"successful"` -} - -func (r *PanelRequest) SendArchiveStatus(uuid string, successful bool) (*RequestError, error) { - b, err := json.Marshal(archiveRequest{Successful: successful}) +func (r *Request) SendArchiveStatus(uuid string, successful bool) error { + resp, err := r.Post(fmt.Sprintf("/servers/%s/archive", uuid), D{"successful": successful}) if err != nil { - return nil, errors.WithStack(err) - } - - resp, err := r.Post(fmt.Sprintf("/servers/%s/archive", uuid), b) - if err != nil { - return nil, errors.WithStack(err) + return errors.WithStack(err) } defer resp.Body.Close() - r.Response = resp - if r.HasError() { - return r.Error(), nil - } - - return nil, nil + return resp.Error() } -func (r *PanelRequest) SendTransferFailure(uuid string) (*RequestError, error) { - resp, err := r.Get(fmt.Sprintf("/servers/%s/transfer/failure", uuid)) +func (r *Request) SendTransferFailure(uuid string) error { + resp, err := r.Get(fmt.Sprintf("/servers/%s/transfer/failure", uuid), nil) if err != nil { - return nil, errors.WithStack(err) + return errors.WithStack(err) } defer resp.Body.Close() - r.Response = resp - if r.HasError() { - return r.Error(), nil - } - - return nil, nil + return resp.Error() } -func (r *PanelRequest) SendTransferSuccess(uuid string) (*RequestError, error) { - resp, err := r.Get(fmt.Sprintf("/servers/%s/transfer/success", uuid)) +func (r *Request) SendTransferSuccess(uuid string) error { + resp, err := r.Get(fmt.Sprintf("/servers/%s/transfer/success", uuid), nil) if err != nil { - return nil, errors.WithStack(err) + return errors.WithStack(err) } defer resp.Body.Close() - r.Response = resp - if r.HasError() { - return r.Error(), nil - } - - return nil, nil + return resp.Error() } diff --git a/api/sftp_endpoints.go b/api/sftp_endpoints.go index ce88552..5dbbfa6 100644 --- a/api/sftp_endpoints.go +++ b/api/sftp_endpoints.go @@ -1,7 +1,6 @@ package api import ( - "encoding/json" "github.com/apex/log" "github.com/pkg/errors" "regexp" @@ -39,7 +38,7 @@ func IsInvalidCredentialsError(err error) bool { // server and sending a flood of usernames. var validUsernameRegexp = regexp.MustCompile(`^(?i)(.+)\.([a-z0-9]{8})$`) -func (r *PanelRequest) ValidateSftpCredentials(request SftpAuthRequest) (*SftpAuthResponse, error) { +func (r *Request) ValidateSftpCredentials(request SftpAuthRequest) (*SftpAuthResponse, error) { // If the username doesn't meet the expected format that the Panel would even recognize just go ahead // and bail out of the process here to avoid accidentally brute forcing the panel if a bot decides // to connect to spam username attempts. @@ -53,41 +52,33 @@ func (r *PanelRequest) ValidateSftpCredentials(request SftpAuthRequest) (*SftpAu return nil, new(sftpInvalidCredentialsError) } - b, err := json.Marshal(request) - if err != nil { - return nil, err - } - - resp, err := r.Post("/sftp/auth", b) + resp, err := r.Post("/sftp/auth", request) if err != nil { return nil, err } defer resp.Body.Close() - r.Response = resp - - if r.HasError() { - if r.HttpResponseCode() >= 400 && r.HttpResponseCode() < 500 { + e := resp.Error() + if e != nil { + if resp.StatusCode >= 400 && resp.StatusCode < 500 { log.WithFields(log.Fields{ "subsystem": "sftp", "username": request.User, "ip": request.IP, - }).Warn(r.Error().String()) + }).Warn(e.Error()) - return nil, new(sftpInvalidCredentialsError) + return nil, &sftpInvalidCredentialsError{} } - rerr := errors.New(r.Error().String()) + rerr := errors.New(e.Error()) return nil, rerr } - response := new(SftpAuthResponse) - body, _ := r.ReadBody() - - if err := json.Unmarshal(body, response); err != nil { + var response SftpAuthResponse + if err := resp.Bind(&response); err != nil { return nil, err } - return response, nil + return &response, nil } diff --git a/installer/installer.go b/installer/installer.go index 966f1e9..4910e68 100644 --- a/installer/installer.go +++ b/installer/installer.go @@ -63,13 +63,13 @@ func New(data []byte) (*Installer, error) { cfg.Container.Image = getString(data, "container", "image") - c, rerr, err := api.NewRequester().GetServerConfiguration(cfg.Uuid) - if err != nil || rerr != nil { - if err != nil { + c, err := api.New().GetServerConfiguration(cfg.Uuid) + if err != nil { + if !api.IsRequestError(err) { return nil, errors.WithStack(err) } - return nil, errors.New(rerr.String()) + return nil, errors.New(err.Error()) } // Create a new server instance using the configuration we wrote to the disk diff --git a/router/router_transfer.go b/router/router_transfer.go index d5d7760..3584a30 100644 --- a/router/router_transfer.go +++ b/router/router_transfer.go @@ -101,15 +101,15 @@ func postServerArchive(c *gin.Context) { s.Log().Debug("successfully created server archive, notifying panel") - r := api.NewRequester() - rerr, err := r.SendArchiveStatus(s.Id(), true) - if rerr != nil || err != nil { - if err != nil { + r := api.New() + err := r.SendArchiveStatus(s.Id(), true) + if err != nil { + if !api.IsRequestError(err) { s.Log().WithField("error", err).Error("failed to notify panel of archive status") return } - s.Log().WithField("error", rerr.String()).Error("panel returned an error when sending the archive status") + s.Log().WithField("error", err.Error()).Error("panel returned an error when sending the archive status") return } @@ -140,14 +140,14 @@ func postTransfer(c *gin.Context) { } l.Info("server transfer failed, notifying panel") - rerr, err := api.NewRequester().SendTransferFailure(serverID) - if rerr != nil || err != nil { - if err != nil { + err := api.New().SendTransferFailure(serverID) + if err != nil { + if !api.IsRequestError(err) { l.WithField("error", err).Error("failed to notify panel with transfer failure") return } - l.WithField("error", errors.WithStack(rerr)).Error("received error response from panel while notifying of transfer failure") + l.WithField("error", err.Error()).Error("received error response from panel while notifying of transfer failure") return } @@ -296,14 +296,14 @@ func postTransfer(c *gin.Context) { hasError = false // Notify the panel that the transfer succeeded. - rerr, err := api.NewRequester().SendTransferSuccess(serverID) - if rerr != nil || err != nil { - if err != nil { + err = api.New().SendTransferSuccess(serverID) + if err != nil { + if !api.IsRequestError(err) { l.WithField("error", errors.WithStack(err)).Error("failed to notify panel of transfer success") return } - l.WithField("error", errors.WithStack(rerr)).Error("panel responded with error after transfer success") + l.WithField("error", err.Error()).Error("panel responded with error after transfer success") return } diff --git a/server/backup.go b/server/backup.go index e76e5fe..9d8cd1f 100644 --- a/server/backup.go +++ b/server/backup.go @@ -13,10 +13,10 @@ import ( // Notifies the panel of a backup's state and returns an error if one is encountered // while performing this action. func (s *Server) notifyPanelOfBackup(uuid string, ad *backup.ArchiveDetails, successful bool) error { - r := api.NewRequester() - rerr, err := r.SendBackupStatus(uuid, ad.ToRequest(successful)) - if rerr != nil || err != nil { - if err != nil { + r := api.New() + err := r.SendBackupStatus(uuid, ad.ToRequest(successful)) + if err != nil { + if !api.IsRequestError(err) { s.Log().WithFields(log.Fields{ "backup": uuid, "error": err, @@ -25,7 +25,7 @@ func (s *Server) notifyPanelOfBackup(uuid string, ad *backup.ArchiveDetails, suc return err } - return errors.New(rerr.String()) + return errors.New(err.Error()) } return nil diff --git a/server/install.go b/server/install.go index 2666fb7..b0c982f 100644 --- a/server/install.go +++ b/server/install.go @@ -87,13 +87,13 @@ func (s *Server) Reinstall() error { // Internal installation function used to simplify reporting back to the Panel. func (s *Server) internalInstall() error { - script, rerr, err := api.NewRequester().GetInstallationScript(s.Id()) - if err != nil || rerr != nil { - if err != nil { - return err + script, err := api.New().GetInstallationScript(s.Id()) + if err != nil { + if !api.IsRequestError(err) { + return errors.WithStack(err) } - return errors.New(rerr.String()) + return errors.New(err.Error()) } p, err := NewInstallationProcess(s, &script) @@ -512,15 +512,13 @@ func (ip *InstallationProcess) StreamOutput(id string) error { // value of "true" means everything was successful, "false" means something went // wrong and the server must be deleted and re-created. func (s *Server) SyncInstallState(successful bool) error { - r := api.NewRequester() - - rerr, err := r.SendInstallationStatus(s.Id(), successful) - if rerr != nil || err != nil { - if err != nil { + err := api.New().SendInstallationStatus(s.Id(), successful) + if err != nil { + if !api.IsRequestError(err) { return errors.WithStack(err) } - return errors.New(rerr.String()) + return errors.New(err.Error()) } return nil diff --git a/server/loader.go b/server/loader.go index 89996b3..fef3904 100644 --- a/server/loader.go +++ b/server/loader.go @@ -32,13 +32,13 @@ func LoadDirectory() error { } log.Info("fetching list of servers from API") - configs, rerr, err := api.NewRequester().GetAllServerConfigurations() - if err != nil || rerr != nil { - if err != nil { + configs, err := api.New().GetAllServerConfigurations() + if err != nil { + if !api.IsRequestError(err) { return errors.WithStack(err) } - return errors.New(rerr.String()) + return errors.New(err.Error()) } start := time.Now() diff --git a/server/server.go b/server/server.go index 84756c1..68f8b59 100644 --- a/server/server.go +++ b/server/server.go @@ -112,17 +112,17 @@ func (s *Server) Log() *log.Entry { // This also means mass actions can be performed against servers on the Panel and they // will automatically sync with Wings when the server is started. func (s *Server) Sync() error { - cfg, rerr, err := s.GetProcessConfiguration() - if err != nil || rerr != nil { - if err != nil { + cfg, err := api.New().GetServerConfiguration(s.Id()) + if err != nil { + if !api.IsRequestError(err) { return errors.WithStack(err) } - if rerr.Status == "404" { + if err.(*api.RequestError).Status == "404" { return &serverDoesNotExist{} } - return errors.New(rerr.String()) + return errors.New(err.Error()) } return s.SyncWithConfiguration(cfg) @@ -177,11 +177,6 @@ func (s *Server) CreateEnvironment() error { return s.Environment.Create() } -// Gets the process configuration data for the server. -func (s *Server) GetProcessConfiguration() (api.ServerConfigurationResponse, *api.RequestError, error) { - return api.NewRequester().GetServerConfiguration(s.Id()) -} - // Checks if the server is marked as being suspended or not on the system. func (s *Server) IsSuspended() bool { return s.Config().Suspended diff --git a/sftp/sftp.go b/sftp/sftp.go index 6fc8482..dcd870f 100644 --- a/sftp/sftp.go +++ b/sftp/sftp.go @@ -72,7 +72,7 @@ func validateCredentials(c api.SftpAuthRequest) (*api.SftpAuthResponse, error) { f := log.Fields{"subsystem": "sftp", "username": c.User, "ip": c.IP} log.WithFields(f).Debug("validating credentials for SFTP connection") - resp, err := api.NewRequester().ValidateSftpCredentials(c) + resp, err := api.New().ValidateSftpCredentials(c) if err != nil { if api.IsInvalidCredentialsError(err) { log.WithFields(f).Warn("failed to validate user credentials (invalid username or password)")