1package oauth1 2 3import ( 4 "encoding/json" 5 "net/url" 6 "time" 7 8 "github.com/gophercloud/gophercloud" 9 "github.com/gophercloud/gophercloud/pagination" 10) 11 12// Consumer represents a delegated authorization request between two 13// identities. 14type Consumer struct { 15 ID string `json:"id"` 16 Secret string `json:"secret"` 17 Description string `json:"description"` 18} 19 20type consumerResult struct { 21 gophercloud.Result 22} 23 24// CreateConsumerResult is the response from a Create operation. Call its 25// Extract method to interpret it as a Consumer. 26type CreateConsumerResult struct { 27 consumerResult 28} 29 30// UpdateConsumerResult is the response from a Create operation. Call its 31// Extract method to interpret it as a Consumer. 32type UpdateConsumerResult struct { 33 consumerResult 34} 35 36// DeleteConsumerResult is the response from a Delete operation. Call its 37// ExtractErr to determine if the request succeeded or failed. 38type DeleteConsumerResult struct { 39 gophercloud.ErrResult 40} 41 42// ConsumersPage is a single page of Region results. 43type ConsumersPage struct { 44 pagination.LinkedPageBase 45} 46 47// GetConsumerResult is the response from a Get operation. Call its Extract 48// method to interpret it as a Consumer. 49type GetConsumerResult struct { 50 consumerResult 51} 52 53// IsEmpty determines whether or not a page of Consumers contains any results. 54func (c ConsumersPage) IsEmpty() (bool, error) { 55 consumers, err := ExtractConsumers(c) 56 return len(consumers) == 0, err 57} 58 59// NextPageURL extracts the "next" link from the links section of the result. 60func (c ConsumersPage) NextPageURL() (string, error) { 61 var s struct { 62 Links struct { 63 Next string `json:"next"` 64 Previous string `json:"previous"` 65 } `json:"links"` 66 } 67 err := c.ExtractInto(&s) 68 if err != nil { 69 return "", err 70 } 71 return s.Links.Next, err 72} 73 74// ExtractConsumers returns a slice of Consumers contained in a single page of 75// results. 76func ExtractConsumers(r pagination.Page) ([]Consumer, error) { 77 var s struct { 78 Consumers []Consumer `json:"consumers"` 79 } 80 err := (r.(ConsumersPage)).ExtractInto(&s) 81 return s.Consumers, err 82} 83 84// Extract interprets any consumer result as a Consumer. 85func (c consumerResult) Extract() (*Consumer, error) { 86 var s struct { 87 Consumer *Consumer `json:"consumer"` 88 } 89 err := c.ExtractInto(&s) 90 return s.Consumer, err 91} 92 93// Token contains an OAuth1 token. 94type Token struct { 95 // OAuthToken is the key value for the oauth token that the Identity API returns. 96 OAuthToken string `q:"oauth_token"` 97 // OAuthTokenSecret is the secret value associated with the OAuth Token. 98 OAuthTokenSecret string `q:"oauth_token_secret"` 99 // OAUthExpiresAt is the date and time when an OAuth token expires. 100 OAUthExpiresAt *time.Time `q:"-"` 101} 102 103// TokenResult is a struct to handle 104// "Content-Type: application/x-www-form-urlencoded" response. 105type TokenResult struct { 106 gophercloud.Result 107 Body []byte 108} 109 110// Extract interprets any OAuth1 token result as a Token. 111func (r TokenResult) Extract() (*Token, error) { 112 if r.Err != nil { 113 return nil, r.Err 114 } 115 116 values, err := url.ParseQuery(string(r.Body)) 117 if err != nil { 118 return nil, err 119 } 120 121 token := &Token{ 122 OAuthToken: values.Get("oauth_token"), 123 OAuthTokenSecret: values.Get("oauth_token_secret"), 124 } 125 126 if v := values.Get("oauth_expires_at"); v != "" { 127 if t, err := time.Parse(gophercloud.RFC3339Milli, v); err != nil { 128 return nil, err 129 } else { 130 token.OAUthExpiresAt = &t 131 } 132 } 133 134 return token, nil 135} 136 137// AuthorizedToken contains an OAuth1 authorized token info. 138type AuthorizedToken struct { 139 // OAuthVerifier is the ID of the token verifier. 140 OAuthVerifier string `json:"oauth_verifier"` 141} 142 143type AuthorizeTokenResult struct { 144 gophercloud.Result 145} 146 147// Extract interprets AuthorizeTokenResult result as a AuthorizedToken. 148func (r AuthorizeTokenResult) Extract() (*AuthorizedToken, error) { 149 var s struct { 150 AuthorizedToken *AuthorizedToken `json:"token"` 151 } 152 err := r.ExtractInto(&s) 153 return s.AuthorizedToken, err 154} 155 156// AccessToken represents an AccessToken response as a struct. 157type AccessToken struct { 158 ID string `json:"id"` 159 ConsumerID string `json:"consumer_id"` 160 ProjectID string `json:"project_id"` 161 AuthorizingUserID string `json:"authorizing_user_id"` 162 ExpiresAt *time.Time `json:"-"` 163} 164 165func (r *AccessToken) UnmarshalJSON(b []byte) error { 166 type tmp AccessToken 167 var s struct { 168 tmp 169 ExpiresAt *gophercloud.JSONRFC3339Milli `json:"expires_at"` 170 } 171 err := json.Unmarshal(b, &s) 172 if err != nil { 173 return err 174 } 175 *r = AccessToken(s.tmp) 176 177 if s.ExpiresAt != nil { 178 t := time.Time(*s.ExpiresAt) 179 r.ExpiresAt = &t 180 } 181 182 return nil 183} 184 185type GetAccessTokenResult struct { 186 gophercloud.Result 187} 188 189// Extract interprets any GetAccessTokenResult result as an AccessToken. 190func (r GetAccessTokenResult) Extract() (*AccessToken, error) { 191 var s struct { 192 AccessToken *AccessToken `json:"access_token"` 193 } 194 err := r.ExtractInto(&s) 195 return s.AccessToken, err 196} 197 198// RevokeAccessTokenResult is the response from a Delete operation. Call its 199// ExtractErr to determine if the request succeeded or failed. 200type RevokeAccessTokenResult struct { 201 gophercloud.ErrResult 202} 203 204// AccessTokensPage is a single page of Access Tokens results. 205type AccessTokensPage struct { 206 pagination.LinkedPageBase 207} 208 209// IsEmpty determines whether or not a an AccessTokensPage contains any results. 210func (r AccessTokensPage) IsEmpty() (bool, error) { 211 accessTokens, err := ExtractAccessTokens(r) 212 return len(accessTokens) == 0, err 213} 214 215// NextPageURL extracts the "next" link from the links section of the result. 216func (r AccessTokensPage) NextPageURL() (string, error) { 217 var s struct { 218 Links struct { 219 Next string `json:"next"` 220 Previous string `json:"previous"` 221 } `json:"links"` 222 } 223 err := r.ExtractInto(&s) 224 if err != nil { 225 return "", err 226 } 227 return s.Links.Next, err 228} 229 230// ExtractAccessTokens returns a slice of AccessTokens contained in a single 231// page of results. 232func ExtractAccessTokens(r pagination.Page) ([]AccessToken, error) { 233 var s struct { 234 AccessTokens []AccessToken `json:"access_tokens"` 235 } 236 err := (r.(AccessTokensPage)).ExtractInto(&s) 237 return s.AccessTokens, err 238} 239 240// AccessTokenRole represents an Access Token Role struct. 241type AccessTokenRole struct { 242 ID string `json:"id"` 243 Name string `json:"name"` 244 DomainID string `json:"domain_id"` 245} 246 247// AccessTokenRolesPage is a single page of Access Token roles results. 248type AccessTokenRolesPage struct { 249 pagination.LinkedPageBase 250} 251 252// IsEmpty determines whether or not a an AccessTokensPage contains any results. 253func (r AccessTokenRolesPage) IsEmpty() (bool, error) { 254 accessTokenRoles, err := ExtractAccessTokenRoles(r) 255 return len(accessTokenRoles) == 0, err 256} 257 258// NextPageURL extracts the "next" link from the links section of the result. 259func (r AccessTokenRolesPage) NextPageURL() (string, error) { 260 var s struct { 261 Links struct { 262 Next string `json:"next"` 263 Previous string `json:"previous"` 264 } `json:"links"` 265 } 266 err := r.ExtractInto(&s) 267 if err != nil { 268 return "", err 269 } 270 return s.Links.Next, err 271} 272 273// ExtractAccessTokenRoles returns a slice of AccessTokenRole contained in a 274// single page of results. 275func ExtractAccessTokenRoles(r pagination.Page) ([]AccessTokenRole, error) { 276 var s struct { 277 AccessTokenRoles []AccessTokenRole `json:"roles"` 278 } 279 err := (r.(AccessTokenRolesPage)).ExtractInto(&s) 280 return s.AccessTokenRoles, err 281} 282 283type GetAccessTokenRoleResult struct { 284 gophercloud.Result 285} 286 287// Extract interprets any GetAccessTokenRoleResult result as an AccessTokenRole. 288func (r GetAccessTokenRoleResult) Extract() (*AccessTokenRole, error) { 289 var s struct { 290 AccessTokenRole *AccessTokenRole `json:"role"` 291 } 292 err := r.ExtractInto(&s) 293 return s.AccessTokenRole, err 294} 295 296// OAuth1 is an OAuth1 object, returned in OAuth1 token result. 297type OAuth1 struct { 298 AccessTokenID string `json:"access_token_id"` 299 ConsumerID string `json:"consumer_id"` 300} 301 302// TokenExt represents an extension of the base token result. 303type TokenExt struct { 304 OAuth1 OAuth1 `json:"OS-OAUTH1"` 305} 306