Skip to content

Commit 08b22ca

Browse files
author
Laurie T. Malau
committed
[pat] Implement GetPersonalAccessToken
1 parent a0a9ddd commit 08b22ca

File tree

4 files changed

+79
-35
lines changed

4 files changed

+79
-35
lines changed

components/gitpod-db/go/personal_access_token.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@ import (
99
"database/sql/driver"
1010
"errors"
1111
"fmt"
12-
"strings"
13-
"time"
14-
1512
"github.com/google/uuid"
1613
"gorm.io/gorm"
14+
"strings"
15+
"time"
1716
)
1817

1918
type PersonalAccessToken struct {
@@ -36,14 +35,17 @@ func (d *PersonalAccessToken) TableName() string {
3635
return "d_b_personal_access_token"
3736
}
3837

39-
func GetToken(ctx context.Context, conn *gorm.DB, id uuid.UUID) (PersonalAccessToken, error) {
38+
func GetTokenForUser(ctx context.Context, conn *gorm.DB, tokenID uuid.UUID, userID uuid.UUID) (PersonalAccessToken, error) {
4039
var token PersonalAccessToken
4140

4241
db := conn.WithContext(ctx)
4342

44-
db = db.Where("id = ?", id).First(&token)
43+
db = db.Where("id = ?", tokenID).Where("userId", userID).First(&token)
4544
if db.Error != nil {
46-
return PersonalAccessToken{}, fmt.Errorf("Failed to retrieve token: %w", db.Error)
45+
if errors.Is(db.Error, gorm.ErrRecordNotFound) {
46+
return PersonalAccessToken{}, fmt.Errorf("Token with ID %s not found: %w", tokenID, ErrorNotFound)
47+
}
48+
return PersonalAccessToken{}, fmt.Errorf("Failed to retrieve token: %v", db.Error)
4749
}
4850

4951
return token, nil

components/gitpod-db/go/personal_access_token_test.go

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,38 @@ import (
1919
func TestPersonalAccessToken_Get(t *testing.T) {
2020
conn := dbtest.ConnectForTests(t)
2121

22-
token := db.PersonalAccessToken{
23-
ID: uuid.New(),
24-
UserID: uuid.New(),
25-
Hash: "some-secure-hash",
26-
Name: "some-name",
27-
Description: "some-description",
28-
Scopes: []string{"read", "write"},
29-
ExpirationTime: time.Now().Add(5),
30-
CreatedAt: time.Now(),
31-
LastModified: time.Now(),
32-
}
22+
firstUserId := uuid.New()
23+
secondUserId := uuid.New()
3324

34-
tx := conn.Create(token)
35-
require.NoError(t, tx.Error)
25+
token := dbtest.NewPersonalAccessToken(t, db.PersonalAccessToken{UserID: firstUserId})
26+
token2 := dbtest.NewPersonalAccessToken(t, db.PersonalAccessToken{UserID: secondUserId})
27+
28+
tokenEntries := []db.PersonalAccessToken{token, token2}
29+
30+
dbtest.CreatePersonalAccessTokenRecords(t, conn, tokenEntries...)
31+
32+
t.Run("not matching user", func(t *testing.T) {
33+
_, err := db.GetTokenForUser(context.Background(), conn, token.ID, token2.UserID)
34+
require.Error(t, err, db.ErrorNotFound)
35+
})
36+
37+
t.Run("not matching token", func(t *testing.T) {
38+
_, err := db.GetTokenForUser(context.Background(), conn, token2.ID, token.UserID)
39+
require.Error(t, err, db.ErrorNotFound)
40+
})
41+
42+
t.Run("both token and user don't exist in the DB", func(t *testing.T) {
43+
_, err := db.GetTokenForUser(context.Background(), conn, uuid.New(), uuid.New())
44+
require.Error(t, err, db.ErrorNotFound)
45+
})
46+
47+
t.Run("valid", func(t *testing.T) {
48+
returned, err := db.GetTokenForUser(context.Background(), conn, token.ID, token.UserID)
49+
require.NoError(t, err)
50+
require.Equal(t, token.ID, returned.ID)
51+
require.Equal(t, token.UserID, returned.UserID)
52+
})
3653

37-
result, err := db.GetToken(context.Background(), conn, token.ID)
38-
require.NoError(t, err)
39-
require.Equal(t, token.ID, result.ID)
4054
}
4155

4256
func TestPersonalAccessToken_Create(t *testing.T) {

components/public-api-server/pkg/apiv1/tokens.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
"fmt"
1111
"strings"
1212

13-
"github.com/bufbuild/connect-go"
13+
connect "github.com/bufbuild/connect-go"
1414
"github.com/gitpod-io/gitpod/common-go/experiments"
1515
"github.com/gitpod-io/gitpod/common-go/log"
1616
db "github.com/gitpod-io/gitpod/components/gitpod-db/go"
@@ -67,13 +67,27 @@ func (s *TokensService) GetPersonalAccessToken(ctx context.Context, req *connect
6767
return nil, err
6868
}
6969

70-
_, err = s.getUser(ctx, conn)
70+
user, err := s.getUser(ctx, conn)
7171
if err != nil {
72-
return nil, err
72+
return nil, connect.NewError(connect.CodeNotFound, fmt.Errorf("User not found."))
7373
}
7474

7575
log.Infof("Handling GetPersonalAccessToken request for Token ID '%s'", tokenID.String())
76-
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("gitpod.experimental.v1.TokensService.GetPersonalAccessToken is not implemented"))
76+
77+
userId, err := uuid.Parse(user.ID)
78+
if err != nil {
79+
return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("Failed to parse user ID as UUID"))
80+
}
81+
82+
token, err := db.GetTokenForUser(ctx, s.dbConn, tokenID, userId)
83+
if err != nil {
84+
if errors.Is(err, gorm.ErrRecordNotFound) {
85+
return &connect.Response[v1.GetPersonalAccessTokenResponse]{}, fmt.Errorf("Token with ID %s does not exist", tokenID)
86+
}
87+
return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("Failed to get Personal Access Token for User %s", userId.String()))
88+
}
89+
90+
return connect.NewResponse(&v1.GetPersonalAccessTokenResponse{Token: personalAccessTokenToAPI(token, "")}), nil
7791
}
7892

7993
func (s *TokensService) ListPersonalAccessTokens(ctx context.Context, req *connect.Request[v1.ListPersonalAccessTokensRequest]) (*connect.Response[v1.ListPersonalAccessTokensResponse], error) {

components/public-api-server/pkg/apiv1/tokens_test.go

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,18 +65,31 @@ func TestTokensService_CreatePersonalAccessTokenWithoutFeatureFlag(t *testing.T)
6565

6666
func TestTokensService_GetPersonalAccessToken(t *testing.T) {
6767
user := newUser(&protocol.User{})
68+
user2 := newUser(&protocol.User{})
6869

69-
t.Run("permission denied when feature flag is disabled", func(t *testing.T) {
70-
serverMock, _, client := setupTokensService(t, withTokenFeatureDisabled)
70+
t.Run("get correct token", func(t *testing.T) {
71+
serverMock, dbConn, client := setupTokensService(t, withTokenFeatureEnabled)
72+
73+
tokens := dbtest.CreatePersonalAccessTokenRecords(t, dbConn,
74+
dbtest.NewPersonalAccessToken(t, db.PersonalAccessToken{
75+
UserID: uuid.MustParse(user.ID),
76+
}),
77+
dbtest.NewPersonalAccessToken(t, db.PersonalAccessToken{
78+
UserID: uuid.MustParse(user2.ID),
79+
}),
80+
)
7181

7282
serverMock.EXPECT().GetLoggedInUser(gomock.Any()).Return(user, nil)
7383

74-
_, err := client.GetPersonalAccessToken(context.Background(), connect.NewRequest(&v1.GetPersonalAccessTokenRequest{
75-
Id: uuid.New().String(),
84+
response, err := client.GetPersonalAccessToken(context.Background(), connect.NewRequest(&v1.GetPersonalAccessTokenRequest{
85+
Id: tokens[0].ID.String(),
7686
}))
7787

78-
require.Error(t, err, "This feature is currently in beta. If you would like to be part of the beta, please contact us.")
79-
require.Equal(t, connect.CodePermissionDenied, connect.CodeOf(err))
88+
require.NoError(t, err)
89+
90+
requireEqualProto(t, &v1.GetPersonalAccessTokenResponse{
91+
Token: personalAccessTokenToAPI(tokens[0], ""),
92+
}, response.Msg)
8093
})
8194

8295
t.Run("invalid argument when Token ID is empty", func(t *testing.T) {
@@ -97,16 +110,17 @@ func TestTokensService_GetPersonalAccessToken(t *testing.T) {
97110
require.Equal(t, connect.CodeInvalidArgument, connect.CodeOf(err))
98111
})
99112

100-
t.Run("unimplemented when feature flag enabled", func(t *testing.T) {
101-
serverMock, _, client := setupTokensService(t, withTokenFeatureEnabled)
113+
t.Run("permission denied when feature flag disabled", func(t *testing.T) {
114+
serverMock, _, client := setupTokensService(t, withTokenFeatureDisabled)
102115

103116
serverMock.EXPECT().GetLoggedInUser(gomock.Any()).Return(user, nil)
104117

105118
_, err := client.GetPersonalAccessToken(context.Background(), connect.NewRequest(&v1.GetPersonalAccessTokenRequest{
106119
Id: uuid.New().String(),
107120
}))
108121

109-
require.Equal(t, connect.CodeUnimplemented, connect.CodeOf(err))
122+
require.Error(t, err, "This feature is currently in beta. If you would like to be part of the beta, please contact us.")
123+
require.Equal(t, connect.CodeNotFound, connect.CodeOf(err))
110124
})
111125
}
112126

0 commit comments

Comments
 (0)