diff --git a/core/unifi/types.go b/core/unifi/types.go index bced62e2..f904a01d 100644 --- a/core/unifi/types.go +++ b/core/unifi/types.go @@ -38,8 +38,8 @@ const ( APILoginPath string = "/api/login" // APILoginPathNew is how we log into UDM 5.12.55+. APILoginPathNew string = "/api/auth/login" - // APILogoutPath is the how we logout from UDM - APILogoutPath string = "/api/auth/logout" + // APILogoutPath is how we logout from UDM + APILogoutPath string = "/api/logout" // APIEventPathIDS returns Intrusion Detection/Prevention Systems Events. APIEventPathIDS string = "/api/s/%s/stat/ips/event" // APIEventPathAlarms contains the site alarms. diff --git a/core/unifi/unifi.go b/core/unifi/unifi.go index 653f6895..da139367 100644 --- a/core/unifi/unifi.go +++ b/core/unifi/unifi.go @@ -28,7 +28,7 @@ import ( var ( ErrAuthenticationFailed = fmt.Errorf("authentication failed") ErrInvalidStatusCode = fmt.Errorf("invalid status code from server") - ErrNoParams = fmt.Errorf("requedted PUT with no parameters") + ErrNoParams = fmt.Errorf("requested PUT with no parameters") ErrInvalidSignature = fmt.Errorf("certificate signature does not match") ) @@ -144,9 +144,9 @@ func (u *Unifi) Login() error { // Logout closes the current session func (u *Unifi) Logout() error { - var response struct { - } - return u.GetData(APILogoutPath, &response) + // a post is needed for logout + _, err := u.PostJSON(APILogoutPath) + return err } // with the release of controller version 5.12.55 on UDM in Jan 2020 the api paths @@ -286,6 +286,19 @@ func (u *Unifi) UniReqPut(apiPath string, params string) (*http.Request, error) return req, nil } +// UniReqPost is the Post call equivalent to UniReq. +func (u *Unifi) UniReqPost(apiPath string, params string) (*http.Request, error) { + apiPath = u.path(apiPath) + + req, err := http.NewRequest(http.MethodPost, u.URL+apiPath, bytes.NewBufferString("")) //nolint:noctx + if err != nil { + return nil, fmt.Errorf("creating request: %w", err) + } + + u.setHeaders(req, params) + return req, nil +} + // GetJSON returns the raw JSON from a path. This is useful for debugging. func (u *Unifi) GetJSON(apiPath string, params ...string) ([]byte, error) { req, err := u.UniReq(apiPath, strings.Join(params, " ")) @@ -307,6 +320,17 @@ func (u *Unifi) PutJSON(apiPath string, params ...string) ([]byte, error) { return u.do(req) } +// PostJSON uses a POST call and returns the raw JSON in the same way as GetData +// Use this if you want to change data via the REST API. +func (u *Unifi) PostJSON(apiPath string, params ...string) ([]byte, error) { + req, err := u.UniReqPost(apiPath, strings.Join(params, " ")) + if err != nil { + return []byte{}, err + } + + return u.do(req) +} + func (u *Unifi) do(req *http.Request) ([]byte, error) { var ( cancel func() diff --git a/core/unifi/users.go b/core/unifi/users.go index 56b034d1..d2384c8f 100644 --- a/core/unifi/users.go +++ b/core/unifi/users.go @@ -41,29 +41,29 @@ func (u *Unifi) GetUsers(sites []*Site, hours int) ([]*User, error) { // User defines the metadata available for previously connected clients type User struct { - SourceName string `json:"-"` - SiteName string `json:"-"` - ID string `json:"_id"` - Mac string `json:"mac"` - SiteID string `json:"site_id"` - Oui string `json:"oui,omitempty"` - IsGuest bool `json:"is_guest"` - FirstSeen int64 `json:"first_seen,omitempty"` - LastSeen int64 `json:"last_seen,omitempty"` - IsWired bool `json:"is_wired,omitempty"` - Hostname string `json:"hostname,omitempty"` - Duration int64 `json:"duration,omitempty"` - TxBytes int64 `json:"tx_bytes,omitempty"` - TxPackets int64 `json:"tx_packets,omitempty"` - RxBytes int64 `json:"rx_bytes,omitempty"` - RxPackets int64 `json:"rx_packets,omitempty"` - WifiTxAttempts int64 `json:"wifi_tx_attempts,omitempty"` - TxRetries int64 `json:"tx_retries,omitempty"` - UsergroupID string `json:"usergroup_id,omitempty"` - Name string `json:"name,omitempty"` - Note string `json:"note,omitempty"` - Noted bool `json:"noted,omitempty"` - Blocked bool `json:"blocked,omitempty"` - DevIDOverride int64 `json:"dev_id_override,omitempty"` - FingerprintOverride bool `json:"fingerprint_override,omitempty"` + SourceName string `json:"-"` + SiteName string `json:"-"` + ID string `json:"_id"` + Mac string `json:"mac"` + SiteID string `json:"site_id"` + Oui string `json:"oui,omitempty"` + IsGuest bool `json:"is_guest"` + FirstSeen FlexInt `json:"first_seen,omitempty"` + LastSeen FlexInt `json:"last_seen,omitempty"` + IsWired bool `json:"is_wired,omitempty"` + Hostname string `json:"hostname,omitempty"` + Duration FlexInt `json:"duration,omitempty"` + TxBytes FlexInt `json:"tx_bytes,omitempty"` + TxPackets FlexInt `json:"tx_packets,omitempty"` + RxBytes FlexInt `json:"rx_bytes,omitempty"` + RxPackets FlexInt `json:"rx_packets,omitempty"` + WifiTxAttempts FlexInt `json:"wifi_tx_attempts,omitempty"` + TxRetries FlexInt `json:"tx_retries,omitempty"` + UsergroupID string `json:"usergroup_id,omitempty"` + Name string `json:"name,omitempty"` + Note string `json:"note,omitempty"` + Noted FlexBool `json:"noted,omitempty"` + Blocked FlexBool `json:"blocked,omitempty"` + DevIDOverride FlexInt `json:"dev_id_override,omitempty"` + FingerprintOverride FlexBool `json:"fingerprint_override,omitempty"` }