1// Copyright 2016 Circonus, Inc. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// User API support - Fetch, Update, and Search 6// See: https://login.circonus.com/resources/api/calls/user 7// Note: Create and Delete are not supported directly via the User API 8// endpoint. See the Account endpoint for inviting and removing users 9// from specific accounts. 10 11package api 12 13import ( 14 "encoding/json" 15 "fmt" 16 "net/url" 17 "regexp" 18 19 "github.com/circonus-labs/circonus-gometrics/api/config" 20) 21 22// UserContactInfo defines known contact details 23type UserContactInfo struct { 24 SMS string `json:"sms,omitempty"` // string 25 XMPP string `json:"xmpp,omitempty"` // string 26} 27 28// User defines a user. See https://login.circonus.com/resources/api/calls/user for more information. 29type User struct { 30 CID string `json:"_cid,omitempty"` // string 31 ContactInfo UserContactInfo `json:"contact_info,omitempty"` // UserContactInfo 32 Email string `json:"email"` // string 33 Firstname string `json:"firstname"` // string 34 Lastname string `json:"lastname"` // string 35} 36 37// FetchUser retrieves user with passed cid. Pass nil for '/user/current'. 38func (a *API) FetchUser(cid CIDType) (*User, error) { 39 var userCID string 40 41 if cid == nil || *cid == "" { 42 userCID = config.UserPrefix + "/current" 43 } else { 44 userCID = string(*cid) 45 } 46 47 matched, err := regexp.MatchString(config.UserCIDRegex, userCID) 48 if err != nil { 49 return nil, err 50 } 51 if !matched { 52 return nil, fmt.Errorf("Invalid user CID [%s]", userCID) 53 } 54 55 result, err := a.Get(userCID) 56 if err != nil { 57 return nil, err 58 } 59 60 if a.Debug { 61 a.Log.Printf("[DEBUG] fetch user, received JSON: %s", string(result)) 62 } 63 64 user := new(User) 65 if err := json.Unmarshal(result, user); err != nil { 66 return nil, err 67 } 68 69 return user, nil 70} 71 72// FetchUsers retrieves all users available to API Token. 73func (a *API) FetchUsers() (*[]User, error) { 74 result, err := a.Get(config.UserPrefix) 75 if err != nil { 76 return nil, err 77 } 78 79 var users []User 80 if err := json.Unmarshal(result, &users); err != nil { 81 return nil, err 82 } 83 84 return &users, nil 85} 86 87// UpdateUser updates passed user. 88func (a *API) UpdateUser(cfg *User) (*User, error) { 89 if cfg == nil { 90 return nil, fmt.Errorf("Invalid user config [nil]") 91 } 92 93 userCID := string(cfg.CID) 94 95 matched, err := regexp.MatchString(config.UserCIDRegex, userCID) 96 if err != nil { 97 return nil, err 98 } 99 if !matched { 100 return nil, fmt.Errorf("Invalid user CID [%s]", userCID) 101 } 102 103 jsonCfg, err := json.Marshal(cfg) 104 if err != nil { 105 return nil, err 106 } 107 108 if a.Debug { 109 a.Log.Printf("[DEBUG] update user, sending JSON: %s", string(jsonCfg)) 110 } 111 112 result, err := a.Put(userCID, jsonCfg) 113 if err != nil { 114 return nil, err 115 } 116 117 user := &User{} 118 if err := json.Unmarshal(result, user); err != nil { 119 return nil, err 120 } 121 122 return user, nil 123} 124 125// SearchUsers returns users matching a filter (search queries 126// are not suppoted by the user endpoint). Pass nil as filter for all 127// users available to the API Token. 128func (a *API) SearchUsers(filterCriteria *SearchFilterType) (*[]User, error) { 129 q := url.Values{} 130 131 if filterCriteria != nil && len(*filterCriteria) > 0 { 132 for filter, criteria := range *filterCriteria { 133 for _, val := range criteria { 134 q.Add(filter, val) 135 } 136 } 137 } 138 139 if q.Encode() == "" { 140 return a.FetchUsers() 141 } 142 143 reqURL := url.URL{ 144 Path: config.UserPrefix, 145 RawQuery: q.Encode(), 146 } 147 148 result, err := a.Get(reqURL.String()) 149 if err != nil { 150 return nil, fmt.Errorf("[ERROR] API call error %+v", err) 151 } 152 153 var users []User 154 if err := json.Unmarshal(result, &users); err != nil { 155 return nil, err 156 } 157 158 return &users, nil 159} 160