[wip] unifi_user resource
This commit is contained in:
@@ -78,3 +78,27 @@ func (c *lazyClient) UpdateUserGroup(site string, d *unifi.UserGroup) (*unifi.Us
|
||||
c.init()
|
||||
return c.inner.UpdateUserGroup(site, d)
|
||||
}
|
||||
func (c *lazyClient) GetUser(site, id string) (*unifi.User, error) {
|
||||
c.init()
|
||||
return c.inner.GetUser(site, id)
|
||||
}
|
||||
func (c *lazyClient) CreateUser(site string, d *unifi.User) (*unifi.User, error) {
|
||||
c.init()
|
||||
return c.inner.CreateUser(site, d)
|
||||
}
|
||||
func (c *lazyClient) UpdateUser(site string, d *unifi.User) (*unifi.User, error) {
|
||||
c.init()
|
||||
return c.inner.UpdateUser(site, d)
|
||||
}
|
||||
func (c *lazyClient) DeleteUserByMAC(site, mac string) error {
|
||||
c.init()
|
||||
return c.inner.DeleteUserByMAC(site, mac)
|
||||
}
|
||||
func (c *lazyClient) BlockUserByMAC(site, mac string) error {
|
||||
c.init()
|
||||
return c.inner.BlockUserByMAC(site, mac)
|
||||
}
|
||||
func (c *lazyClient) UnblockUserByMAC(site, mac string) error {
|
||||
c.init()
|
||||
return c.inner.UnblockUserByMAC(site, mac)
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ func Provider() terraform.ResourceProvider {
|
||||
ResourcesMap: map[string]*schema.Resource{
|
||||
"unifi_network": resourceNetwork(),
|
||||
"unifi_user_group": resourceUserGroup(),
|
||||
"unifi_user": resourceUser(),
|
||||
"unifi_wlan": resourceWLAN(),
|
||||
},
|
||||
}
|
||||
@@ -90,6 +91,14 @@ type unifiClient interface {
|
||||
DeleteWLAN(site, id string) error
|
||||
CreateWLAN(site string, d *unifi.WLAN) (*unifi.WLAN, error)
|
||||
GetWLAN(site, id string) (*unifi.WLAN, error)
|
||||
|
||||
GetUser(site, id string) (*unifi.User, error)
|
||||
// GetUserByMAC(site, mac string) (*unifi.User, error)
|
||||
CreateUser(site string, d *unifi.User) (*unifi.User, error)
|
||||
BlockUserByMAC(site, mac string) error
|
||||
UnblockUserByMAC(site, mac string) error
|
||||
UpdateUser(site string, d *unifi.User) (*unifi.User, error)
|
||||
DeleteUserByMAC(site, mac string) error
|
||||
}
|
||||
|
||||
type client struct {
|
||||
|
||||
202
provider/resource_user.go
Normal file
202
provider/resource_user.go
Normal file
@@ -0,0 +1,202 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
|
||||
|
||||
"github.com/paultyng/terraform-provider-unifi/unifi"
|
||||
)
|
||||
|
||||
func resourceUser() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceUserCreate,
|
||||
Read: resourceUserRead,
|
||||
Update: resourceUserUpdate,
|
||||
Delete: resourceUserDelete,
|
||||
Importer: &schema.ResourceImporter{
|
||||
State: schema.ImportStatePassthrough,
|
||||
},
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"mac": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
|
||||
old = strings.TrimSpace(strings.ReplaceAll(strings.ToLower(old), "-", ":"))
|
||||
new = strings.TrimSpace(strings.ReplaceAll(strings.ToLower(new), "-", ":"))
|
||||
return old == new
|
||||
},
|
||||
// Validation:
|
||||
},
|
||||
"name": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"user_group_id": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
"note": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
"fixed_ip": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
// TODO: Validate
|
||||
},
|
||||
"network_id": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
"blocked": {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
},
|
||||
|
||||
// this is a "meta" attribute that controls TF UX
|
||||
"allow_existing": {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Default: true,
|
||||
},
|
||||
// TODO: "skip_forget_on_destroy": {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceUserCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
c := meta.(*client)
|
||||
|
||||
req, err := resourceUserGetResourceData(d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
allowExisting := d.Get("allow_existing").(bool)
|
||||
|
||||
resp, err := c.c.CreateUser(c.site, req)
|
||||
if err != nil {
|
||||
apiErr, ok := err.(*unifi.APIError)
|
||||
if !ok || (apiErr.Message != "api.err.MacUsed" && !allowExisting) {
|
||||
return err
|
||||
}
|
||||
// TODO: handle mac in use flow
|
||||
return fmt.Errorf("allow_existing not yet implemented")
|
||||
}
|
||||
|
||||
d.SetId(resp.ID)
|
||||
|
||||
if d.Get("blocked").(bool) {
|
||||
err := c.c.BlockUserByMAC(c.site, d.Get("mac").(string))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return resourceUserSetResourceData(resp, d)
|
||||
}
|
||||
|
||||
func resourceUserGetResourceData(d *schema.ResourceData) (*unifi.User, error) {
|
||||
fixedIP := d.Get("fixed_ip").(string)
|
||||
|
||||
return &unifi.User{
|
||||
MAC: d.Get("mac").(string),
|
||||
Name: d.Get("name").(string),
|
||||
UserGroupID: d.Get("user_group_id").(string),
|
||||
Note: d.Get("note").(string),
|
||||
FixedIP: fixedIP,
|
||||
UseFixedIP: fixedIP != "",
|
||||
NetworkID: d.Get("network_id").(string),
|
||||
// not sure if this matters/works
|
||||
Blocked: d.Get("blocked").(bool),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func resourceUserSetResourceData(resp *unifi.User, d *schema.ResourceData) error {
|
||||
fixedIP := ""
|
||||
if resp.UseFixedIP {
|
||||
fixedIP = resp.FixedIP
|
||||
}
|
||||
|
||||
d.Set("mac", resp.MAC)
|
||||
d.Set("name", resp.Name)
|
||||
d.Set("user_group_id", resp.UserGroupID)
|
||||
d.Set("note", resp.Note)
|
||||
d.Set("fixed_ip", fixedIP)
|
||||
d.Set("network_id", resp.NetworkID)
|
||||
d.Set("blocked", resp.Blocked)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceUserRead(d *schema.ResourceData, meta interface{}) error {
|
||||
c := meta.(*client)
|
||||
|
||||
id := d.Id()
|
||||
|
||||
resp, err := c.c.GetUser(c.site, id)
|
||||
if _, ok := err.(*unifi.NotFoundError); ok {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return resourceUserSetResourceData(resp, d)
|
||||
}
|
||||
|
||||
func resourceUserUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
c := meta.(*client)
|
||||
|
||||
if d.HasChange("blocked") {
|
||||
mac := d.Get("mac").(string)
|
||||
if d.Get("blocked").(bool) {
|
||||
err := c.c.BlockUserByMAC(c.site, mac)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err := c.c.UnblockUserByMAC(c.site, mac)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
req, err := resourceUserGetResourceData(d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.ID = d.Id()
|
||||
req.SiteID = c.site
|
||||
|
||||
resp, err := c.c.UpdateUser(c.site, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return resourceUserSetResourceData(resp, d)
|
||||
}
|
||||
|
||||
func resourceUserDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
c := meta.(*client)
|
||||
|
||||
id := d.Id()
|
||||
|
||||
u, err := c.c.GetUser(c.site, id)
|
||||
if _, ok := err.(*unifi.NotFoundError); ok {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.c.DeleteUserByMAC(c.site, u.MAC)
|
||||
return err
|
||||
}
|
||||
160
provider/resource_user_test.go
Normal file
160
provider/resource_user_test.go
Normal file
@@ -0,0 +1,160 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
|
||||
)
|
||||
|
||||
func TestAccUser_basic(t *testing.T) {
|
||||
resource.ParallelTest(t, resource.TestCase{
|
||||
Providers: providers,
|
||||
PreCheck: func() { preCheck(t) },
|
||||
// TODO: CheckDestroy: ,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccUserConfig("00:00:5E:00:53:00", "tfacc", "tfacc note"),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
// testCheckNetworkExists(t, "name"),
|
||||
resource.TestCheckResourceAttr("unifi_user.test", "note", "tfacc note"),
|
||||
),
|
||||
},
|
||||
importStep("unifi_user.test", "allow_existing"),
|
||||
{
|
||||
Config: testAccUserConfig("00:00:5E:00:53:00", "tfacc-2", "tfacc note 2"),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("unifi_user.test", "note", "tfacc note 2"),
|
||||
),
|
||||
},
|
||||
importStep("unifi_user.test", "allow_existing"),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccUser_fixed_ip(t *testing.T) {
|
||||
resource.ParallelTest(t, resource.TestCase{
|
||||
Providers: providers,
|
||||
PreCheck: func() { preCheck(t) },
|
||||
// TODO: CheckDestroy: ,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccUserConfig("00:00:5E:00:53:10", "tfacc", "tfacc fixed ip"),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
// testCheckNetworkExists(t, "name"),
|
||||
resource.TestCheckResourceAttr("unifi_user.test", "fixed_ip", ""),
|
||||
),
|
||||
},
|
||||
importStep("unifi_user.test", "allow_existing"),
|
||||
{
|
||||
Config: testAccUserConfig_fixedIP("00:00:5E:00:53:10"),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
// testCheckNetworkExists(t, "name"),
|
||||
resource.TestCheckResourceAttr("unifi_user.test", "fixed_ip", "10.1.10.50"),
|
||||
),
|
||||
},
|
||||
importStep("unifi_user.test", "allow_existing"),
|
||||
{
|
||||
// this passes the network again even though its not used
|
||||
// to avoid a destroy order of operations issue, can
|
||||
// maybe work it out some other way
|
||||
Config: testAccUserConfig_network + testAccUserConfig("00:00:5E:00:53:10", "tfacc", "tfacc fixed ip"),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
// testCheckNetworkExists(t, "name"),
|
||||
resource.TestCheckResourceAttr("unifi_user.test", "fixed_ip", ""),
|
||||
),
|
||||
},
|
||||
importStep("unifi_user.test", "allow_existing"),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccUser_blocking(t *testing.T) {
|
||||
resource.ParallelTest(t, resource.TestCase{
|
||||
Providers: providers,
|
||||
PreCheck: func() { preCheck(t) },
|
||||
// TODO: CheckDestroy: ,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccUserConfig_block("00:00:5E:00:53:20", false),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
// testCheckNetworkExists(t, "name"),
|
||||
resource.TestCheckResourceAttr("unifi_user.test", "blocked", "false"),
|
||||
),
|
||||
},
|
||||
importStep("unifi_user.test", "allow_existing"),
|
||||
{
|
||||
Config: testAccUserConfig_block("00:00:5E:00:53:20", true),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
// testCheckNetworkExists(t, "name"),
|
||||
resource.TestCheckResourceAttr("unifi_user.test", "blocked", "true"),
|
||||
),
|
||||
},
|
||||
importStep("unifi_user.test", "allow_existing"),
|
||||
{
|
||||
Config: testAccUserConfig_block("00:00:5E:00:53:20", false),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
// testCheckNetworkExists(t, "name"),
|
||||
resource.TestCheckResourceAttr("unifi_user.test", "blocked", "false"),
|
||||
),
|
||||
},
|
||||
importStep("unifi_user.test", "allow_existing"),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// for test MAC addresses, see https://tools.ietf.org/html/rfc7042#section-2.1.2
|
||||
// func TestAccUser_existing_mac_allow(t *testing.T) {
|
||||
// func TestAccUser_existing_mac_deny(t *testing.T) {
|
||||
|
||||
func testAccUserConfig(mac, name, note string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "unifi_user" "test" {
|
||||
mac = "%s"
|
||||
name = "%s"
|
||||
note = "%s"
|
||||
}
|
||||
`, mac, name, note)
|
||||
}
|
||||
|
||||
const testAccUserConfig_network = `
|
||||
variable "subnet" {
|
||||
default = "10.1.10.1/24"
|
||||
}
|
||||
|
||||
resource "unifi_network" "test" {
|
||||
name = "tfaccfixedip"
|
||||
purpose = "corporate"
|
||||
|
||||
vlan_id = 66
|
||||
subnet = var.subnet
|
||||
dhcp_start = cidrhost(var.subnet, 6)
|
||||
dhcp_stop = cidrhost(var.subnet, 254)
|
||||
dhcp_enabled = true
|
||||
}
|
||||
`
|
||||
|
||||
func testAccUserConfig_fixedIP(mac string) string {
|
||||
return fmt.Sprintf(testAccUserConfig_network+`
|
||||
resource "unifi_user" "test" {
|
||||
mac = "%s"
|
||||
name = "tfacc"
|
||||
note = "tfacc fixed ip"
|
||||
|
||||
fixed_ip = "10.1.10.50"
|
||||
network_id = unifi_network.test.id
|
||||
}
|
||||
`, mac)
|
||||
}
|
||||
|
||||
func testAccUserConfig_block(mac string, blocked bool) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "unifi_user" "test" {
|
||||
mac = "%s"
|
||||
name = "tfacc"
|
||||
note = "tfacc block %t"
|
||||
|
||||
blocked = %t
|
||||
}
|
||||
`, mac, blocked, blocked)
|
||||
}
|
||||
@@ -21,6 +21,15 @@ func (err *NotFoundError) Error() string {
|
||||
return "not found"
|
||||
}
|
||||
|
||||
type APIError struct {
|
||||
RC string
|
||||
Message string
|
||||
}
|
||||
|
||||
func (err *APIError) Error() string {
|
||||
return err.Message
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
c *http.Client
|
||||
baseURL *url.URL
|
||||
@@ -131,3 +140,14 @@ type meta struct {
|
||||
RC string `json:"rc"`
|
||||
Message string `json:"msg"`
|
||||
}
|
||||
|
||||
func (m *meta) error() error {
|
||||
if m.RC != "ok" {
|
||||
return &APIError{
|
||||
RC: m.RC,
|
||||
Message: m.Message,
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
185
unifi/user.go
Normal file
185
unifi/user.go
Normal file
@@ -0,0 +1,185 @@
|
||||
package unifi
|
||||
|
||||
import "fmt"
|
||||
|
||||
// GET https://73.212.25.176:8443/api/s/default/stat/user/e4:f0:42:bf:bd:11
|
||||
// {"meta":{"rc":"ok"},"data":[{"_id":"5deeac76439adf048407dd01","mac":"e4:f0:42:bf:bd:11","site_id":"5d6d8b07439adf048407dcd9","oui":"Google","is_guest":false,"first_seen":1575922805,"last_seen":1577907316,"is_wired":true,"fingerprint_engine":"tdts","dev_cat":6,"dev_family":9,"os_class":16,"os_name":56,"dev_vendor":7,"dev_id":2822,"priority":101,"fingerprint_source":0,"name":"Google WiFi","usergroup_id":"","noted":true,"fixed_ip":"10.0.6.11","note":"","confidence":100,"network_id":"5d6d8b0c439adf048407dce7","use_fixedip":true,"duration":1966599,"tx_bytes":2391811124,"tx_packets":2227771,"rx_bytes":1431694370,"rx_packets":2606611,"wifi_tx_attempts":0,"tx_retries":0,"assoc_time":1577889972,"latest_assoc_time":1577889972,"user_id":"5deeac76439adf048407dd01","_uptime_by_ugw":1984511,"_last_seen_by_ugw":1577907316,"_is_guest_by_ugw":false,"gw_mac":"74:83:c2:d6:ff:83","network":"LAN","ip":"192.168.1.135","uptime":17344,"tx_bytes-r":0,"rx_bytes-r":0,"authorized":true,"qos_policy_applied":true,"_uptime_by_usw":1984511,"_last_seen_by_usw":1577907316,"_is_guest_by_usw":false,"sw_mac":"74:83:c2:d6:ff:83","sw_depth":0,"sw_port":4,"wired-tx_bytes":2176183895,"wired-rx_bytes":1406877963,"wired-tx_packets":2156208,"wired-rx_packets":2444036,"wired-tx_bytes-r":1968908,"wired-rx_bytes-r":105359}]}
|
||||
|
||||
// PUT https://73.212.25.176:8443/api/s/default/rest/user/5deeac76439adf048407dd01
|
||||
// { use_fixedip: true, network_id: "5df7f70f1e801c052a1ab032", fixed_ip: "10.0.6.11" }
|
||||
// { note: "my note", usergroup_id: "", name: "Google WiFi alias"}
|
||||
// {"meta":{"rc":"ok"},"data":[{"_id":"5deeac76439adf048407dd01","mac":"e4:f0:42:bf:bd:11","site_id":"5d6d8b07439adf048407dcd9","oui":"Google","is_guest":false,"first_seen":1575922805,"last_seen":1577889639,"is_wired":true,"fingerprint_engine":"tdts","dev_cat":6,"dev_family":9,"os_class":16,"os_name":56,"dev_vendor":7,"dev_id":2822,"priority":101,"fingerprint_source":0,"name":"Google WiFi","usergroup_id":"","noted":true,"fixed_ip":"10.0.6.11","note":"","confidence":100,"network_id":"5df7f70f1e801c052a1ab032","use_fixedip":true}]}
|
||||
|
||||
type User struct {
|
||||
ID string `json:"_id,omitempty"`
|
||||
SiteID string `json:"site_id,omitempty"`
|
||||
Name string `json:"name"`
|
||||
MAC string `json:"mac"`
|
||||
|
||||
UserGroupID string `json:"user_group_id"`
|
||||
Note string `json:"note"`
|
||||
UseFixedIP bool `json:"use_fixedip"`
|
||||
FixedIP string `json:"fixed_ip,omitempty"`
|
||||
NetworkID string `json:"network_id"`
|
||||
|
||||
// not sure if you can end this for create/update, etc, only
|
||||
// observed modifying via stamgr
|
||||
Blocked bool `json:"blocked,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Client) ListUser(site string) ([]User, error) {
|
||||
var respBody struct {
|
||||
Meta meta `json:"meta"`
|
||||
Data []User `json:"data"`
|
||||
}
|
||||
|
||||
err := c.do("GET", fmt.Sprintf("s/%s/rest/user", site), nil, &respBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return respBody.Data, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetUser(site, id string) (*User, error) {
|
||||
var respBody struct {
|
||||
Meta meta `json:"meta"`
|
||||
Data []User `json:"data"`
|
||||
}
|
||||
|
||||
err := c.do("GET", fmt.Sprintf("s/%s/rest/user/%s", site, id), nil, &respBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(respBody.Data) != 1 {
|
||||
return nil, &NotFoundError{}
|
||||
}
|
||||
|
||||
d := respBody.Data[0]
|
||||
return &d, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetUserByMAC(site, mac string) (*User, error) {
|
||||
var respBody struct {
|
||||
Meta meta `json:"meta"`
|
||||
Data []User `json:"data"`
|
||||
}
|
||||
|
||||
err := c.do("GET", fmt.Sprintf("s/%s/stat/user/%s", site, mac), nil, &respBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(respBody.Data) != 1 {
|
||||
return nil, &NotFoundError{}
|
||||
}
|
||||
|
||||
d := respBody.Data[0]
|
||||
return &d, nil
|
||||
}
|
||||
|
||||
func (c *Client) CreateUser(site string, d *User) (*User, error) {
|
||||
reqBody := struct {
|
||||
Objects []struct {
|
||||
Data *User `json:"data"`
|
||||
} `json:"objects"`
|
||||
}{
|
||||
Objects: []struct {
|
||||
Data *User `json:"data"`
|
||||
}{
|
||||
{Data: d},
|
||||
},
|
||||
}
|
||||
|
||||
var respBody struct {
|
||||
Meta meta `json:"meta"`
|
||||
Data []struct {
|
||||
Meta meta `json:"meta"`
|
||||
Data []User `json:"data"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
err := c.do("POST", fmt.Sprintf("s/%s/group/user", site), reqBody, &respBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(respBody.Data) != 1 {
|
||||
return nil, fmt.Errorf("malformed group response")
|
||||
}
|
||||
|
||||
if err := respBody.Data[0].Meta.error(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(respBody.Data[0].Data) != 1 {
|
||||
return nil, &NotFoundError{}
|
||||
}
|
||||
|
||||
new := respBody.Data[0].Data[0]
|
||||
|
||||
return &new, nil
|
||||
}
|
||||
|
||||
func (c *Client) stamgr(site, cmd string, data map[string]interface{}) error {
|
||||
reqBody := map[string]interface{}{}
|
||||
|
||||
for k, v := range data {
|
||||
reqBody[k] = v
|
||||
}
|
||||
|
||||
reqBody["cmd"] = cmd
|
||||
|
||||
var respBody struct {
|
||||
Meta meta `json:"meta"`
|
||||
Data []User `json:"data"`
|
||||
}
|
||||
|
||||
err := c.do("POST", fmt.Sprintf("s/%s/cmd/stamgr", site), reqBody, &respBody)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: confirm count/state of returned Data?
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) BlockUserByMAC(site, mac string) error {
|
||||
return c.stamgr(site, "block-sta", map[string]interface{}{
|
||||
"mac": mac,
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Client) UnblockUserByMAC(site, mac string) error {
|
||||
return c.stamgr(site, "unblock-sta", map[string]interface{}{
|
||||
"mac": mac,
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Client) UpdateUser(site string, d *User) (*User, error) {
|
||||
var respBody struct {
|
||||
Meta meta `json:"meta"`
|
||||
Data []User `json:"data"`
|
||||
}
|
||||
|
||||
err := c.do("PUT", fmt.Sprintf("s/%s/rest/user/%s", site, d.ID), d, &respBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(respBody.Data) != 1 {
|
||||
return nil, &NotFoundError{}
|
||||
}
|
||||
|
||||
new := respBody.Data[0]
|
||||
|
||||
return &new, nil
|
||||
}
|
||||
|
||||
func (c *Client) DeleteUserByMAC(site, mac string) error {
|
||||
return c.stamgr(site, "forget-sta", map[string]interface{}{
|
||||
"macs": []string{mac},
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user