github.com/gophercloud/gophercloud@v1.11.0/openstack/identity/v3/users/results.go (about) 1 package users 2 3 import ( 4 "encoding/json" 5 "time" 6 7 "github.com/gophercloud/gophercloud" 8 "github.com/gophercloud/gophercloud/pagination" 9 ) 10 11 // User represents a User in the OpenStack Identity Service. 12 type User struct { 13 // DefaultProjectID is the ID of the default project of the user. 14 DefaultProjectID string `json:"default_project_id"` 15 16 // Description is the description of the user. 17 Description string `json:"description"` 18 19 // DomainID is the domain ID the user belongs to. 20 DomainID string `json:"domain_id"` 21 22 // Enabled is whether or not the user is enabled. 23 Enabled bool `json:"enabled"` 24 25 // Extra is a collection of miscellaneous key/values. 26 Extra map[string]interface{} `json:"-"` 27 28 // ID is the unique ID of the user. 29 ID string `json:"id"` 30 31 // Links contains referencing links to the user. 32 Links map[string]interface{} `json:"links"` 33 34 // Name is the name of the user. 35 Name string `json:"name"` 36 37 // Options are a set of defined options of the user. 38 Options map[string]interface{} `json:"options"` 39 40 // PasswordExpiresAt is the timestamp when the user's password expires. 41 PasswordExpiresAt time.Time `json:"-"` 42 } 43 44 func (r *User) UnmarshalJSON(b []byte) error { 45 type tmp User 46 var s struct { 47 tmp 48 Extra map[string]interface{} `json:"extra"` 49 PasswordExpiresAt gophercloud.JSONRFC3339MilliNoZ `json:"password_expires_at"` 50 } 51 err := json.Unmarshal(b, &s) 52 if err != nil { 53 return err 54 } 55 *r = User(s.tmp) 56 57 r.PasswordExpiresAt = time.Time(s.PasswordExpiresAt) 58 59 // Collect other fields and bundle them into Extra 60 // but only if a field titled "extra" wasn't sent. 61 if s.Extra != nil { 62 r.Extra = s.Extra 63 } else { 64 var result interface{} 65 err := json.Unmarshal(b, &result) 66 if err != nil { 67 return err 68 } 69 if resultMap, ok := result.(map[string]interface{}); ok { 70 delete(resultMap, "password_expires_at") 71 r.Extra = gophercloud.RemainingKeys(User{}, resultMap) 72 } 73 } 74 75 return err 76 } 77 78 type userResult struct { 79 gophercloud.Result 80 } 81 82 // GetResult is the response from a Get operation. Call its Extract method 83 // to interpret it as a User. 84 type GetResult struct { 85 userResult 86 } 87 88 // CreateResult is the response from a Create operation. Call its Extract method 89 // to interpret it as a User. 90 type CreateResult struct { 91 userResult 92 } 93 94 // UpdateResult is the response from an Update operation. Call its Extract 95 // method to interpret it as a User. 96 type UpdateResult struct { 97 userResult 98 } 99 100 // ChangePasswordResult is the response from a ChangePassword operation. Call its 101 // ExtractErr method to determine if the request succeeded or failed. 102 type ChangePasswordResult struct { 103 gophercloud.ErrResult 104 } 105 106 // DeleteResult is the response from a Delete operation. Call its ExtractErr to 107 // determine if the request succeeded or failed. 108 type DeleteResult struct { 109 gophercloud.ErrResult 110 } 111 112 // AddToGroupResult is the response from a AddToGroup operation. Call its 113 // ExtractErr method to determine if the request succeeded or failed. 114 type AddToGroupResult struct { 115 gophercloud.ErrResult 116 } 117 118 // IsMemberOfGroupResult is the response from a IsMemberOfGroup operation. Call its 119 // Extract method to determine if the request succeeded or failed. 120 type IsMemberOfGroupResult struct { 121 isMember bool 122 gophercloud.Result 123 } 124 125 // RemoveFromGroupResult is the response from a RemoveFromGroup operation. Call its 126 // ExtractErr method to determine if the request succeeded or failed. 127 type RemoveFromGroupResult struct { 128 gophercloud.ErrResult 129 } 130 131 // UserPage is a single page of User results. 132 type UserPage struct { 133 pagination.LinkedPageBase 134 } 135 136 // IsEmpty determines whether or not a UserPage contains any results. 137 func (r UserPage) IsEmpty() (bool, error) { 138 if r.StatusCode == 204 { 139 return true, nil 140 } 141 142 users, err := ExtractUsers(r) 143 return len(users) == 0, err 144 } 145 146 // NextPageURL extracts the "next" link from the links section of the result. 147 func (r UserPage) NextPageURL() (string, error) { 148 var s struct { 149 Links struct { 150 Next string `json:"next"` 151 Previous string `json:"previous"` 152 } `json:"links"` 153 } 154 err := r.ExtractInto(&s) 155 if err != nil { 156 return "", err 157 } 158 return s.Links.Next, err 159 } 160 161 // ExtractUsers returns a slice of Users contained in a single page of results. 162 func ExtractUsers(r pagination.Page) ([]User, error) { 163 var s struct { 164 Users []User `json:"users"` 165 } 166 err := (r.(UserPage)).ExtractInto(&s) 167 return s.Users, err 168 } 169 170 // Extract interprets any user results as a User. 171 func (r userResult) Extract() (*User, error) { 172 var s struct { 173 User *User `json:"user"` 174 } 175 err := r.ExtractInto(&s) 176 return s.User, err 177 } 178 179 // Extract extracts IsMemberOfGroupResult as bool and error values 180 func (r IsMemberOfGroupResult) Extract() (bool, error) { 181 return r.isMember, r.Err 182 }