Skip to content
This repository was archived by the owner on Aug 1, 2023. It is now read-only.

Commit 0454360

Browse files
author
hzlouchao
committed
add extract user method from get token's response include the unit and acceptance tests
1 parent b764089 commit 0454360

File tree

6 files changed

+113
-42
lines changed

6 files changed

+113
-42
lines changed

acceptance/openstack/identity/v2/token_test.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import (
99
th "github.com/rackspace/gophercloud/testhelper"
1010
)
1111

12-
func TestAuthenticate(t *testing.T) {
12+
func TestAuthenticateAndValidate(t *testing.T) {
13+
// 1. TestAuthenticate
1314
ao := v2AuthOptions(t)
1415
service := unauthenticatedClient(t)
1516

@@ -35,4 +36,19 @@ func TestAuthenticate(t *testing.T) {
3536
t.Logf(" - region=[%s] publicURL=[%s]", endpoint.Region, endpoint.PublicURL)
3637
}
3738
}
39+
40+
// 2. TestValidate
41+
client := authenticatedClient(t)
42+
43+
// Validate Token!
44+
getResult := tokens2.Get(client, token.ID)
45+
46+
// Extract and print the user.
47+
user, err := getResult.ExtractUser()
48+
th.AssertNoErr(t, err)
49+
50+
t.Logf("Acquired User: [%s]", user.Name)
51+
t.Logf("The User id: [%s]", user.ID)
52+
t.Logf("The User username: [%s]", user.UserName)
53+
t.Logf("The User roles: [%#v]", user.Roles)
3854
}

openstack/identity/v2/tokens/fixtures.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
"github.com/rackspace/gophercloud/openstack/identity/v2/tenants"
1212
th "github.com/rackspace/gophercloud/testhelper"
13+
thclient "github.com/rackspace/gophercloud/testhelper/client"
1314
)
1415

1516
// ExpectedToken is the token that should be parsed from TokenCreationResponse.
@@ -54,6 +55,14 @@ var ExpectedServiceCatalog = &ServiceCatalog{
5455
},
5556
}
5657

58+
// ExpectedUser is the token that should be parsed from TokenGetResponse.
59+
var ExpectedUser = &User{
60+
ID: "a530fefc3d594c4ba2693a4ecd6be74e",
61+
Name: "apiserver",
62+
Roles: []Role{{"member"}, {"service"}},
63+
UserName: "apiserver",
64+
}
65+
5766
// TokenCreationResponse is a JSON response that contains ExpectedToken and ExpectedServiceCatalog.
5867
const TokenCreationResponse = `
5968
{
@@ -99,6 +108,39 @@ const TokenCreationResponse = `
99108
}
100109
`
101110

111+
// TokenGetResponse is a JSON response that contains ExpectedToken and ExpectedUser.
112+
const TokenGetResponse = `
113+
{
114+
"access": {
115+
"token": {
116+
"issued_at": "2014-01-30T15:30:58.000000Z",
117+
"expires": "2014-01-31T15:30:58Z",
118+
"id": "aaaabbbbccccdddd",
119+
"tenant": {
120+
"description": "There are many tenants. This one is yours.",
121+
"enabled": true,
122+
"id": "fc394f2ab2df4114bde39905f800dc57",
123+
"name": "test"
124+
}
125+
},
126+
"serviceCatalog": [],
127+
"user": {
128+
"id": "a530fefc3d594c4ba2693a4ecd6be74e",
129+
"name": "apiserver",
130+
"roles": [
131+
{
132+
"name": "member"
133+
},
134+
{
135+
"name": "service"
136+
}
137+
],
138+
"roles_links": [],
139+
"username": "apiserver"
140+
}
141+
}
142+
}`
143+
102144
// HandleTokenPost expects a POST against a /tokens handler, ensures that the request body has been
103145
// constructed properly given certain auth options, and returns the result.
104146
func HandleTokenPost(t *testing.T, requestJSON string) {
@@ -115,6 +157,19 @@ func HandleTokenPost(t *testing.T, requestJSON string) {
115157
})
116158
}
117159

160+
// HandleTokenGet expects a Get against a /tokens handler, ensures that the request body has been
161+
// constructed properly given certain auth options, and returns the result.
162+
func HandleTokenGet(t *testing.T, token string) {
163+
th.Mux.HandleFunc("/tokens/"+token, func(w http.ResponseWriter, r *http.Request) {
164+
th.TestMethod(t, r, "GET")
165+
th.TestHeader(t, r, "Accept", "application/json")
166+
th.TestHeader(t, r, "X-Auth-Token", thclient.TokenID)
167+
168+
w.WriteHeader(http.StatusOK)
169+
fmt.Fprintf(w, TokenGetResponse)
170+
})
171+
}
172+
118173
// IsSuccessful ensures that a CreateResult was successful and contains the correct token and
119174
// service catalog.
120175
func IsSuccessful(t *testing.T, result CreateResult) {
@@ -126,3 +181,15 @@ func IsSuccessful(t *testing.T, result CreateResult) {
126181
th.AssertNoErr(t, err)
127182
th.CheckDeepEquals(t, ExpectedServiceCatalog, serviceCatalog)
128183
}
184+
185+
// GetIsSuccessful ensures that a GetResult was successful and contains the correct token and
186+
// User Info.
187+
func GetIsSuccessful(t *testing.T, result GetResult) {
188+
token, err := result.ExtractToken()
189+
th.AssertNoErr(t, err)
190+
th.CheckDeepEquals(t, ExpectedToken, token)
191+
192+
user, err := result.ExtractUser()
193+
th.AssertNoErr(t, err)
194+
th.CheckDeepEquals(t, ExpectedUser, user)
195+
}

openstack/identity/v2/tokens/requests.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,5 @@ func Get(client *gophercloud.ServiceClient, token string) GetResult {
9595
_, result.Err = client.Get(GetURL(client, token), &result.Body, &gophercloud.RequestOpts{
9696
OkCodes: []int{200, 203},
9797
})
98-
if result.Err != nil {
99-
return result
100-
}
10198
return result
10299
}

openstack/identity/v2/tokens/requests_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,14 @@ func TestRequirePassword(t *testing.T) {
139139

140140
tokenPostErr(t, options, ErrPasswordRequired)
141141
}
142+
143+
func tokenGet(t *testing.T, tokenId string) GetResult {
144+
th.SetupHTTP()
145+
defer th.TeardownHTTP()
146+
HandleTokenGet(t, tokenId)
147+
return Get(client.ServiceClient(), tokenId)
148+
}
149+
150+
func TestGetWithToken(t *testing.T) {
151+
GetIsSuccessful(t, tokenGet(t, "db22caf43c934e6c829087c41ff8d8d6"))
152+
}

openstack/identity/v2/tokens/results.go

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,17 @@ type Token struct {
2323

2424
// Tenant provides information about the tenant to which this token grants access.
2525
Tenant tenants.Tenant
26+
}
2627

27-
// the owner user of token
28-
UserName string
29-
UserID string
28+
// Authorization need user info which can get from token authentication's response
29+
type Role struct {
30+
Name string `mapstructure:"name"`
31+
}
32+
type User struct {
33+
ID string `mapstructure:"id"`
34+
Name string `mapstructure:"name"`
35+
UserName string `mapstructure:"username"`
36+
Roles []Role `mapstructure:"roles"`
3037
}
3138

3239
// Endpoint represents a single API endpoint offered by a service.
@@ -78,9 +85,10 @@ type CreateResult struct {
7885
gophercloud.Result
7986
}
8087

81-
// GetResult is the deferred response from a Get call.
88+
// 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.
8290
type GetResult struct {
83-
gophercloud.Result
91+
CreateResult
8492
}
8593

8694
// ExtractToken returns the just-created Token from a CreateResult.
@@ -141,22 +149,15 @@ func createErr(err error) CreateResult {
141149
return CreateResult{gophercloud.Result{Err: err}}
142150
}
143151

144-
// ExtractToken returns the Token from a GetResult.
145-
func (result GetResult) ExtractToken() (*Token, error) {
152+
// ExtractUser returns the User from a GetResult.
153+
func (result GetResult) ExtractUser() (*User, error) {
146154
if result.Err != nil {
147155
return nil, result.Err
148156
}
149157

150158
var response struct {
151159
Access struct {
152-
Token struct {
153-
Expires string `mapstructure:"expires"`
154-
ID string `mapstructure:"id"`
155-
} `mapstructure:"token"`
156-
User struct {
157-
ID string `mapstructure:"id"`
158-
Name string `mapstructure:"name"`
159-
} `mapstructure:"user"`
160+
User User `mapstructure:"user"`
160161
} `mapstructure:"access"`
161162
}
162163

@@ -165,15 +166,5 @@ func (result GetResult) ExtractToken() (*Token, error) {
165166
return nil, err
166167
}
167168

168-
expiresTs, err := time.Parse(gophercloud.RFC3339Milli, response.Access.Token.Expires)
169-
if err != nil {
170-
return nil, err
171-
}
172-
173-
return &Token{
174-
ID: response.Access.Token.ID,
175-
ExpiresAt: expiresTs,
176-
UserID: response.Access.User.ID,
177-
UserName: response.Access.User.Name,
178-
}, nil
169+
return &response.Access.User, nil
179170
}

provider_client.go

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -185,21 +185,10 @@ func (client *ProviderClient) Request(method, url string, options RequestOpts) (
185185

186186
if resp.StatusCode == http.StatusUnauthorized {
187187
if client.ReauthFunc != nil {
188-
// make sure ReauthFunc only exec one time, or will occur endless recursive loop when admin reauth fail
189-
execFunc := client.ReauthFunc
190-
client.ReauthFunc = nil
191-
err = execFunc()
192-
client.ReauthFunc = execFunc
188+
err = client.ReauthFunc()
193189
if err != nil {
194190
return nil, fmt.Errorf("Error trying to re-authenticate: %s", err)
195191
}
196-
197-
if options.MoreHeaders != nil {
198-
options.MoreHeaders["X-Auth-Token"] = client.TokenID
199-
} else {
200-
options.MoreHeaders = client.AuthenticatedHeaders()
201-
}
202-
203192
if options.RawBody != nil {
204193
options.RawBody.Seek(0, 0)
205194
}

0 commit comments

Comments
 (0)