blob: 9ef45b62951cfe81f4bc35bf55a2274da52ed319 [file] [log] [blame]
Ash Wilson1f110512014-10-02 15:43:47 -04001package tokens
2
3import (
4 "time"
5
6 "github.com/mitchellh/mapstructure"
Jon Perritt27249f42016-02-18 10:35:59 -06007 "github.com/gophercloud/gophercloud"
8 "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants"
Ash Wilson1f110512014-10-02 15:43:47 -04009)
10
11// Token provides only the most basic information related to an authentication token.
12type Token struct {
13 // ID provides the primary means of identifying a user to the OpenStack API.
14 // OpenStack defines this field as an opaque value, so do not depend on its content.
15 // It is safe, however, to compare for equality.
16 ID string
17
18 // ExpiresAt provides a timestamp in ISO 8601 format, indicating when the authentication token becomes invalid.
19 // After this point in time, future API requests made using this authentication token will respond with errors.
20 // Either the caller will need to reauthenticate manually, or more preferably, the caller should exploit automatic re-authentication.
21 // See the AuthOptions structure for more details.
22 ExpiresAt time.Time
23
24 // Tenant provides information about the tenant to which this token grants access.
25 Tenant tenants.Tenant
hzlouchao04543602015-11-30 18:44:15 +080026}
hzlouchaob7640892015-11-04 21:37:20 +080027
hzlouchao04543602015-11-30 18:44:15 +080028// Authorization need user info which can get from token authentication's response
29type Role struct {
30 Name string `mapstructure:"name"`
31}
32type User struct {
33 ID string `mapstructure:"id"`
34 Name string `mapstructure:"name"`
35 UserName string `mapstructure:"username"`
36 Roles []Role `mapstructure:"roles"`
Ash Wilson1f110512014-10-02 15:43:47 -040037}
38
Ash Wilsonab48bbc2014-10-03 09:57:03 -040039// Endpoint represents a single API endpoint offered by a service.
40// It provides the public and internal URLs, if supported, along with a region specifier, again if provided.
41// The significance of the Region field will depend upon your provider.
42//
43// In addition, the interface offered by the service will have version information associated with it
44// through the VersionId, VersionInfo, and VersionList fields, if provided or supported.
45//
46// In all cases, fields which aren't supported by the provider and service combined will assume a zero-value ("").
47type Endpoint struct {
48 TenantID string `mapstructure:"tenantId"`
49 PublicURL string `mapstructure:"publicURL"`
50 InternalURL string `mapstructure:"internalURL"`
51 AdminURL string `mapstructure:"adminURL"`
52 Region string `mapstructure:"region"`
53 VersionID string `mapstructure:"versionId"`
54 VersionInfo string `mapstructure:"versionInfo"`
55 VersionList string `mapstructure:"versionList"`
56}
57
58// CatalogEntry provides a type-safe interface to an Identity API V2 service catalog listing.
59// Each class of service, such as cloud DNS or block storage services, will have a single
60// CatalogEntry representing it.
61//
62// Note: when looking for the desired service, try, whenever possible, to key off the type field.
63// Otherwise, you'll tie the representation of the service to a specific provider.
64type CatalogEntry struct {
65 // Name will contain the provider-specified name for the service.
66 Name string `mapstructure:"name"`
67
68 // Type will contain a type string if OpenStack defines a type for the service.
69 // Otherwise, for provider-specific services, the provider may assign their own type strings.
70 Type string `mapstructure:"type"`
71
72 // Endpoints will let the caller iterate over all the different endpoints that may exist for
73 // the service.
74 Endpoints []Endpoint `mapstructure:"endpoints"`
75}
76
77// ServiceCatalog provides a view into the service catalog from a previous, successful authentication.
78type ServiceCatalog struct {
79 Entries []CatalogEntry
80}
81
Ash Wilson1f110512014-10-02 15:43:47 -040082// CreateResult defers the interpretation of a created token.
83// Use ExtractToken() to interpret it as a Token, or ExtractServiceCatalog() to interpret it as a service catalog.
84type CreateResult struct {
Ash Wilsonf548aad2014-10-20 08:35:34 -040085 gophercloud.Result
Ash Wilson1f110512014-10-02 15:43:47 -040086}
87
hzlouchao04543602015-11-30 18:44:15 +080088// GetResult is the deferred response from a Get call, which is the same with a Created token.
89// Use ExtractUser() to interpret it as a User.
hzlouchaof6e29262015-10-27 12:51:08 +080090type GetResult struct {
hzlouchao04543602015-11-30 18:44:15 +080091 CreateResult
hzlouchaof6e29262015-10-27 12:51:08 +080092}
93
Ash Wilson1f110512014-10-02 15:43:47 -040094// ExtractToken returns the just-created Token from a CreateResult.
95func (result CreateResult) ExtractToken() (*Token, error) {
Ash Wilson27d29e22014-10-03 11:57:14 -040096 if result.Err != nil {
97 return nil, result.Err
98 }
99
Ash Wilson1f110512014-10-02 15:43:47 -0400100 var response struct {
101 Access struct {
102 Token struct {
103 Expires string `mapstructure:"expires"`
104 ID string `mapstructure:"id"`
105 Tenant tenants.Tenant `mapstructure:"tenant"`
106 } `mapstructure:"token"`
107 } `mapstructure:"access"`
108 }
109
Ash Wilsond3dc2542014-10-20 10:10:48 -0400110 err := mapstructure.Decode(result.Body, &response)
Ash Wilson1f110512014-10-02 15:43:47 -0400111 if err != nil {
112 return nil, err
113 }
114
115 expiresTs, err := time.Parse(gophercloud.RFC3339Milli, response.Access.Token.Expires)
116 if err != nil {
117 return nil, err
118 }
119
120 return &Token{
121 ID: response.Access.Token.ID,
122 ExpiresAt: expiresTs,
123 Tenant: response.Access.Token.Tenant,
124 }, nil
125}
126
Ash Wilsonab48bbc2014-10-03 09:57:03 -0400127// ExtractServiceCatalog returns the ServiceCatalog that was generated along with the user's Token.
128func (result CreateResult) ExtractServiceCatalog() (*ServiceCatalog, error) {
Ash Wilson27d29e22014-10-03 11:57:14 -0400129 if result.Err != nil {
130 return nil, result.Err
131 }
132
Ash Wilsonab48bbc2014-10-03 09:57:03 -0400133 var response struct {
134 Access struct {
135 Entries []CatalogEntry `mapstructure:"serviceCatalog"`
136 } `mapstructure:"access"`
137 }
138
Ash Wilsond3dc2542014-10-20 10:10:48 -0400139 err := mapstructure.Decode(result.Body, &response)
Ash Wilsonab48bbc2014-10-03 09:57:03 -0400140 if err != nil {
141 return nil, err
142 }
143
144 return &ServiceCatalog{Entries: response.Access.Entries}, nil
145}
146
Ash Wilson1f110512014-10-02 15:43:47 -0400147// createErr quickly packs an error in a CreateResult.
148func createErr(err error) CreateResult {
Ash Wilsonf548aad2014-10-20 08:35:34 -0400149 return CreateResult{gophercloud.Result{Err: err}}
Ash Wilson1f110512014-10-02 15:43:47 -0400150}
hzlouchaob7640892015-11-04 21:37:20 +0800151
hzlouchao04543602015-11-30 18:44:15 +0800152// ExtractUser returns the User from a GetResult.
153func (result GetResult) ExtractUser() (*User, error) {
hzlouchaob7640892015-11-04 21:37:20 +0800154 if result.Err != nil {
155 return nil, result.Err
156 }
157
158 var response struct {
159 Access struct {
hzlouchao04543602015-11-30 18:44:15 +0800160 User User `mapstructure:"user"`
hzlouchaob7640892015-11-04 21:37:20 +0800161 } `mapstructure:"access"`
162 }
163
164 err := mapstructure.Decode(result.Body, &response)
165 if err != nil {
166 return nil, err
167 }
168
hzlouchao04543602015-11-30 18:44:15 +0800169 return &response.Access.User, nil
hzlouchaob7640892015-11-04 21:37:20 +0800170}