Skip to content

Commit b989e0d

Browse files
committed
Distinguish between empty and nil team token description
An empty string for a description should be unique from an omitted, nil description. Only nil descriptions should use the legacy token API.
1 parent 4c63cff commit b989e0d

File tree

2 files changed

+44
-21
lines changed

2 files changed

+44
-21
lines changed

team_token.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ type teamTokens struct {
5050
type TeamToken struct {
5151
ID string `jsonapi:"primary,authentication-tokens"`
5252
CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"`
53-
Description string `jsonapi:"attr,description"`
53+
Description *string `jsonapi:"attr,description"`
5454
LastUsedAt time.Time `jsonapi:"attr,last-used-at,iso8601"`
5555
Token string `jsonapi:"attr,token"`
5656
ExpiredAt time.Time `jsonapi:"attr,expired-at,iso8601"`
@@ -66,7 +66,7 @@ type TeamTokenCreateOptions struct {
6666

6767
// Optional: The token's description, which must unique per team.
6868
// This feature is considered BETA, SUBJECT TO CHANGE, and likely unavailable to most users.
69-
Description string `jsonapi:"attr,description,omitempty"`
69+
Description *string `jsonapi:"attr,description,omitempty"`
7070
}
7171

7272
// Create a new team token using the legacy creation behavior, which creates a token without a description
@@ -84,7 +84,7 @@ func (s *teamTokens) CreateWithOptions(ctx context.Context, teamID string, optio
8484
}
8585

8686
var u string
87-
if options.Description != "" {
87+
if options.Description != nil {
8888
u = fmt.Sprintf("teams/%s/authentication-tokens", url.PathEscape(teamID))
8989
} else {
9090
u = fmt.Sprintf("teams/%s/authentication-token", url.PathEscape(teamID))

team_token_integration_test.go

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -105,57 +105,76 @@ func TestTeamTokens_CreateWithOptions_MultipleTokens(t *testing.T) {
105105
t.Run("with multiple tokens", func(t *testing.T) {
106106
desc1 := fmt.Sprintf("go-tfe-team-token-test-%s", randomString(t))
107107
tt, err := client.TeamTokens.CreateWithOptions(ctx, tmTest.ID, TeamTokenCreateOptions{
108-
Description: desc1,
108+
Description: &desc1,
109109
})
110110
require.NoError(t, err)
111111
require.NotEmpty(t, tt.Token)
112-
require.Equal(t, tt.Description, desc1)
112+
require.NotNil(t, tt.Description)
113+
require.Equal(t, *tt.Description, desc1)
113114

114115
desc2 := fmt.Sprintf("go-tfe-team-token-test-%s", randomString(t))
115116
tt, err = client.TeamTokens.CreateWithOptions(ctx, tmTest.ID, TeamTokenCreateOptions{
116-
Description: desc2,
117+
Description: &desc2,
117118
})
118119
require.NoError(t, err)
119120
require.NotEmpty(t, tt.Token)
120-
require.Equal(t, tt.Description, desc2)
121+
require.NotNil(t, tt.Description)
122+
require.Equal(t, *tt.Description, desc2)
123+
124+
emptyString := ""
125+
tt, err = client.TeamTokens.CreateWithOptions(ctx, tmTest.ID, TeamTokenCreateOptions{
126+
Description: &emptyString,
127+
})
128+
require.NoError(t, err)
129+
require.NotEmpty(t, tt.Token)
130+
require.NotNil(t, tt.Description)
131+
require.Equal(t, *tt.Description, emptyString)
132+
133+
tt, err = client.TeamTokens.CreateWithOptions(ctx, tmTest.ID, TeamTokenCreateOptions{})
134+
require.NoError(t, err)
135+
require.NotEmpty(t, tt.Token)
136+
require.Nil(t, tt.Description)
121137
})
122138

123139
t.Run("with an expiration date", func(t *testing.T) {
124140
desc := fmt.Sprintf("go-tfe-team-token-test-%s", randomString(t))
125141
currentTime := time.Now().UTC().Truncate(time.Second)
126142
oneDayLater := currentTime.Add(24 * time.Hour)
127143
tt, err := client.TeamTokens.CreateWithOptions(ctx, tmTest.ID, TeamTokenCreateOptions{
128-
Description: desc,
144+
Description: &desc,
129145
ExpiredAt: &oneDayLater,
130146
})
131147
require.NoError(t, err)
132148
require.NotEmpty(t, tt.Token)
133149
assert.Equal(t, tt.ExpiredAt, oneDayLater)
134-
require.Equal(t, tt.Description, desc)
150+
require.NotNil(t, tt.Description)
151+
require.Equal(t, *tt.Description, desc)
135152
})
136153

137154
t.Run("without an expiration date", func(t *testing.T) {
138155
desc := fmt.Sprintf("go-tfe-team-token-test-%s", randomString(t))
139156
tt, err := client.TeamTokens.CreateWithOptions(ctx, tmTest.ID, TeamTokenCreateOptions{
140-
Description: desc,
157+
Description: &desc,
141158
})
142159
require.NoError(t, err)
143160
require.NotEmpty(t, tt.Token)
144161
assert.Empty(t, tt.ExpiredAt)
145-
require.Equal(t, tt.Description, desc)
162+
require.NotNil(t, tt.Description)
163+
require.Equal(t, *tt.Description, desc)
146164
})
147165

148166
t.Run("when a token already exists with the same description", func(t *testing.T) {
149167
desc := fmt.Sprintf("go-tfe-team-token-test-%s", randomString(t))
150168
tt, err := client.TeamTokens.CreateWithOptions(ctx, tmTest.ID, TeamTokenCreateOptions{
151-
Description: desc,
169+
Description: &desc,
152170
})
153171
require.NoError(t, err)
154172
require.NotEmpty(t, tt.Token)
155-
require.Equal(t, tt.Description, desc)
173+
require.NotNil(t, tt.Description)
174+
require.Equal(t, *tt.Description, desc)
156175

157176
tt, err = client.TeamTokens.CreateWithOptions(ctx, tmTest.ID, TeamTokenCreateOptions{
158-
Description: desc,
177+
Description: &desc,
159178
})
160179
assert.Nil(t, tt)
161180
assert.Equal(t, err, ErrInvalidDescriptionConflict)
@@ -234,7 +253,7 @@ func TestTeamTokensReadByID(t *testing.T) {
234253
tt, err := client.TeamTokens.ReadByID(ctx, token.ID)
235254
require.NoError(t, err)
236255
require.NotEmpty(t, tt)
237-
assert.Empty(t, tt.Description)
256+
assert.Nil(t, tt.Description)
238257
assert.Equal(t, tt.ExpiredAt, oneDayLater)
239258
require.NotEmpty(t, tt.Team)
240259
assert.Equal(t, tt.Team.ID, tmTest.ID)
@@ -244,29 +263,31 @@ func TestTeamTokensReadByID(t *testing.T) {
244263
skipUnlessBeta(t)
245264
desc1 := fmt.Sprintf("go-tfe-team-token-test-%s", randomString(t))
246265
token, ttTestCleanup := createTeamTokenWithOptions(t, client, tmTest, TeamTokenCreateOptions{
247-
Description: desc1,
266+
Description: &desc1,
248267
})
249268
t.Cleanup(ttTestCleanup)
250269

251270
tt, err := client.TeamTokens.ReadByID(ctx, token.ID)
252271
require.NoError(t, err)
253272
require.NotEmpty(t, tt)
254-
assert.Equal(t, tt.Description, desc1)
273+
require.NotNil(t, tt.Description)
274+
assert.Equal(t, *tt.Description, desc1)
255275
assert.Empty(t, tt.ExpiredAt)
256276
require.NotEmpty(t, tt.Team)
257277
assert.Equal(t, tt.Team.ID, tmTest.ID)
258278

259279
desc2 := fmt.Sprintf("go-tfe-team-token-test-%s", randomString(t))
260280
tokenWithExpiration, ttTestCleanup2 := createTeamTokenWithOptions(t, client, tmTest, TeamTokenCreateOptions{
261281
ExpiredAt: &oneDayLater,
262-
Description: desc2,
282+
Description: &desc2,
263283
})
264284
t.Cleanup(ttTestCleanup2)
265285

266286
tt2, err := client.TeamTokens.ReadByID(ctx, tokenWithExpiration.ID)
267287
require.NoError(t, err)
268288
require.NotEmpty(t, tt2)
269-
assert.Equal(t, tt2.Description, desc2)
289+
require.NotNil(t, tt2.Description)
290+
assert.Equal(t, *tt2.Description, desc2)
270291
assert.Equal(t, tt2.ExpiredAt, oneDayLater)
271292
require.NotEmpty(t, tt.Team)
272293
assert.Equal(t, tt.Team.ID, tmTest.ID)
@@ -319,12 +340,14 @@ func TestTeamTokensDeleteByID(t *testing.T) {
319340

320341
t.Run("with multiple team tokens", func(t *testing.T) {
321342
skipUnlessBeta(t)
343+
desc1 := fmt.Sprintf("go-tfe-team-token-test-%s", randomString(t))
322344
token1, _ := createTeamTokenWithOptions(t, client, tmTest, TeamTokenCreateOptions{
323-
Description: fmt.Sprintf("go-tfe-team-token-test-%s", randomString(t)),
345+
Description: &desc1,
324346
})
325347

348+
desc2 := fmt.Sprintf("go-tfe-team-token-test-%s", randomString(t))
326349
token2, _ := createTeamTokenWithOptions(t, client, tmTest, TeamTokenCreateOptions{
327-
Description: fmt.Sprintf("go-tfe-team-token-test-%s", randomString(t)),
350+
Description: &desc2,
328351
})
329352

330353
err := client.TeamTokens.DeleteByID(ctx, token1.ID)

0 commit comments

Comments
 (0)