mirror of
https://github.com/gitpod-io/gitpod.git
synced 2025-12-08 17:36:30 +00:00
697 lines
21 KiB
Go
697 lines
21 KiB
Go
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
|
|
// Licensed under the GNU Affero General Public License (AGPL).
|
|
// See License.AGPL.txt in the project root for license information.
|
|
|
|
package apiv1
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/bufbuild/connect-go"
|
|
"github.com/gitpod-io/gitpod/components/public-api/go/config"
|
|
v1 "github.com/gitpod-io/gitpod/components/public-api/go/experimental/v1"
|
|
"github.com/gitpod-io/gitpod/components/public-api/go/experimental/v1/v1connect"
|
|
protocol "github.com/gitpod-io/gitpod/gitpod-protocol"
|
|
"github.com/gitpod-io/gitpod/public-api-server/pkg/auth"
|
|
"github.com/gitpod-io/gitpod/public-api-server/pkg/jws"
|
|
"github.com/gitpod-io/gitpod/public-api-server/pkg/jws/jwstest"
|
|
"github.com/golang/mock/gomock"
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/google/uuid"
|
|
"github.com/sourcegraph/jsonrpc2"
|
|
"github.com/stretchr/testify/require"
|
|
"google.golang.org/protobuf/testing/protocmp"
|
|
)
|
|
|
|
func TestTeamsService_CreateTeam(t *testing.T) {
|
|
|
|
var (
|
|
name = "Shiny New Team"
|
|
id = uuid.New().String()
|
|
)
|
|
|
|
t.Run("returns invalid argument when name is empty", func(t *testing.T) {
|
|
ctx := context.Background()
|
|
_, client := setupTeamService(t)
|
|
|
|
_, err := client.CreateTeam(ctx, connect.NewRequest(&v1.CreateTeamRequest{Name: ""}))
|
|
require.Error(t, err)
|
|
require.Equal(t, connect.CodeInvalidArgument, connect.CodeOf(err))
|
|
})
|
|
|
|
t.Run("returns invalid request when server returns invalid request", func(t *testing.T) {
|
|
ctx := context.Background()
|
|
serverMock, client := setupTeamService(t)
|
|
|
|
serverMock.EXPECT().CreateTeam(gomock.Any(), name).Return(nil, &jsonrpc2.Error{
|
|
Code: 400,
|
|
Message: "invalid request",
|
|
})
|
|
|
|
_, err := client.CreateTeam(ctx, connect.NewRequest(&v1.CreateTeamRequest{Name: name}))
|
|
require.Error(t, err)
|
|
require.Equal(t, connect.CodeInvalidArgument, connect.CodeOf(err))
|
|
})
|
|
|
|
t.Run("returns team with members and invite", func(t *testing.T) {
|
|
teamMembers := []*protocol.TeamMemberInfo{
|
|
newTeamMember(&protocol.TeamMemberInfo{
|
|
FullName: "Alice Alice",
|
|
Role: protocol.TeamMember_Owner,
|
|
}),
|
|
newTeamMember(&protocol.TeamMemberInfo{
|
|
FullName: "Bob Bob",
|
|
Role: protocol.TeamMember_Member,
|
|
}),
|
|
}
|
|
inviteID := uuid.New().String()
|
|
invite := &protocol.TeamMembershipInvite{
|
|
ID: inviteID,
|
|
TeamID: id,
|
|
}
|
|
team := newTeam(&protocol.Team{
|
|
ID: id,
|
|
})
|
|
|
|
serverMock, client := setupTeamService(t)
|
|
|
|
serverMock.EXPECT().CreateTeam(gomock.Any(), name).Return(team, nil)
|
|
serverMock.EXPECT().GetTeamMembers(gomock.Any(), id).Return(teamMembers, nil)
|
|
serverMock.EXPECT().GetGenericInvite(gomock.Any(), id).Return(&protocol.TeamMembershipInvite{
|
|
ID: inviteID,
|
|
TeamID: id,
|
|
}, nil)
|
|
|
|
response, err := client.CreateTeam(context.Background(), connect.NewRequest(&v1.CreateTeamRequest{Name: name}))
|
|
require.NoError(t, err)
|
|
|
|
requireEqualProto(t, &v1.CreateTeamResponse{
|
|
Team: teamToAPIResponse(team, teamMembers, invite),
|
|
}, response.Msg)
|
|
})
|
|
|
|
t.Run("returns team with members and no invite", func(t *testing.T) {
|
|
teamMembers := []*protocol.TeamMemberInfo{
|
|
newTeamMember(&protocol.TeamMemberInfo{
|
|
FullName: "Alice Alice",
|
|
Role: protocol.TeamMember_Owner,
|
|
}),
|
|
newTeamMember(&protocol.TeamMemberInfo{
|
|
FullName: "Bob Bob",
|
|
Role: protocol.TeamMember_Member,
|
|
}),
|
|
}
|
|
team := newTeam(&protocol.Team{
|
|
ID: id,
|
|
})
|
|
|
|
serverMock, client := setupTeamService(t)
|
|
|
|
serverMock.EXPECT().CreateTeam(gomock.Any(), name).Return(team, nil)
|
|
serverMock.EXPECT().GetTeamMembers(gomock.Any(), id).Return(teamMembers, nil)
|
|
serverMock.EXPECT().GetGenericInvite(gomock.Any(), id).Return(nil, &jsonrpc2.Error{Code: 404, Message: "not found"})
|
|
|
|
response, err := client.CreateTeam(context.Background(), connect.NewRequest(&v1.CreateTeamRequest{Name: name}))
|
|
require.NoError(t, err)
|
|
|
|
requireEqualProto(t, &v1.CreateTeamResponse{
|
|
Team: teamToAPIResponse(team, teamMembers, nil),
|
|
}, response.Msg)
|
|
})
|
|
}
|
|
|
|
func TestTeamsService_ListTeams(t *testing.T) {
|
|
t.Run("returns teams with members and invite", func(t *testing.T) {
|
|
ctx := context.Background()
|
|
serverMock, client := setupTeamService(t)
|
|
|
|
teamMembers := []*protocol.TeamMemberInfo{
|
|
newTeamMember(&protocol.TeamMemberInfo{
|
|
FullName: "Alice Alice",
|
|
Role: protocol.TeamMember_Owner,
|
|
}),
|
|
newTeamMember(&protocol.TeamMemberInfo{
|
|
FullName: "Bob Bob",
|
|
Role: protocol.TeamMember_Member,
|
|
}),
|
|
}
|
|
teams := []*protocol.Team{
|
|
newTeam(&protocol.Team{
|
|
Name: "Team A",
|
|
}),
|
|
newTeam(&protocol.Team{
|
|
Name: "Team B",
|
|
}),
|
|
}
|
|
inviteID := uuid.New().String()
|
|
invite := &protocol.TeamMembershipInvite{
|
|
ID: inviteID,
|
|
TeamID: teams[1].ID,
|
|
}
|
|
|
|
serverMock.EXPECT().GetTeams(gomock.Any()).Return(teams, nil)
|
|
|
|
// Mocks for populating team A details
|
|
serverMock.EXPECT().GetTeamMembers(gomock.Any(), teams[0].ID).Return(teamMembers, nil)
|
|
serverMock.EXPECT().GetGenericInvite(gomock.Any(), teams[0].ID).Return(&protocol.TeamMembershipInvite{
|
|
ID: inviteID,
|
|
TeamID: teams[0].ID,
|
|
}, nil)
|
|
// Mock for populating team B details
|
|
serverMock.EXPECT().GetTeamMembers(gomock.Any(), teams[1].ID).Return(teamMembers, nil)
|
|
serverMock.EXPECT().GetGenericInvite(gomock.Any(), teams[1].ID).Return(invite, nil)
|
|
|
|
response, err := client.ListTeams(ctx, connect.NewRequest(&v1.ListTeamsRequest{}))
|
|
require.NoError(t, err)
|
|
requireEqualProto(t, &v1.ListTeamsResponse{
|
|
Teams: []*v1.Team{
|
|
teamToAPIResponse(teams[0], teamMembers, invite),
|
|
teamToAPIResponse(teams[1], teamMembers, invite),
|
|
},
|
|
}, response.Msg)
|
|
})
|
|
|
|
t.Run("returns team with members and no invite for non-owner", func(t *testing.T) {
|
|
ctx := context.Background()
|
|
serverMock, client := setupTeamService(t)
|
|
|
|
teamMembers := []*protocol.TeamMemberInfo{
|
|
newTeamMember(&protocol.TeamMemberInfo{
|
|
FullName: "Alice Alice",
|
|
Role: protocol.TeamMember_Owner,
|
|
}),
|
|
newTeamMember(&protocol.TeamMemberInfo{
|
|
FullName: "Bob Bob",
|
|
Role: protocol.TeamMember_Member,
|
|
}),
|
|
}
|
|
team := newTeam(&protocol.Team{
|
|
Name: "Team A",
|
|
})
|
|
serverMock.EXPECT().GetTeams(gomock.Any()).Return([]*protocol.Team{team}, nil)
|
|
|
|
// Mock for populating team details
|
|
serverMock.EXPECT().GetTeamMembers(gomock.Any(), team.ID).Return(teamMembers, nil)
|
|
serverMock.EXPECT().GetGenericInvite(gomock.Any(), team.ID).Return(nil, &jsonrpc2.Error{Code: 403, Message: "not access"})
|
|
|
|
response, err := client.ListTeams(ctx, connect.NewRequest(&v1.ListTeamsRequest{}))
|
|
require.NoError(t, err)
|
|
requireEqualProto(t, &v1.ListTeamsResponse{
|
|
Teams: []*v1.Team{
|
|
teamToAPIResponse(team, teamMembers, nil),
|
|
},
|
|
}, response.Msg)
|
|
})
|
|
}
|
|
|
|
func TestTeamService_GetTeam(t *testing.T) {
|
|
var (
|
|
teamID = uuid.New().String()
|
|
)
|
|
|
|
t.Run("returns invalid argument when empty ID provided", func(t *testing.T) {
|
|
_, client := setupTeamService(t)
|
|
|
|
_, err := client.GetTeam(context.Background(), connect.NewRequest(&v1.GetTeamRequest{
|
|
TeamId: "",
|
|
}))
|
|
require.Error(t, err)
|
|
require.Equal(t, connect.CodeInvalidArgument, connect.CodeOf(err))
|
|
})
|
|
|
|
t.Run("proxies request to server", func(t *testing.T) {
|
|
serverMock, client := setupTeamService(t)
|
|
|
|
team := newTeam(&protocol.Team{
|
|
ID: teamID,
|
|
})
|
|
members := []*protocol.TeamMemberInfo{newTeamMember(&protocol.TeamMemberInfo{}), newTeamMember(&protocol.TeamMemberInfo{})}
|
|
invite := &protocol.TeamMembershipInvite{ID: uuid.New().String()}
|
|
|
|
serverMock.EXPECT().GetTeam(gomock.Any(), teamID).Return(team, nil)
|
|
serverMock.EXPECT().GetTeamMembers(gomock.Any(), teamID).Return(members, nil)
|
|
serverMock.EXPECT().GetGenericInvite(gomock.Any(), teamID).Return(invite, nil)
|
|
|
|
retrieved, err := client.GetTeam(context.Background(), connect.NewRequest(&v1.GetTeamRequest{
|
|
TeamId: teamID,
|
|
}))
|
|
require.NoError(t, err)
|
|
requireEqualProto(t, &v1.GetTeamResponse{
|
|
Team: teamToAPIResponse(team, members, invite),
|
|
}, retrieved.Msg)
|
|
})
|
|
}
|
|
|
|
func TestTeamsService_JoinTeam(t *testing.T) {
|
|
|
|
var (
|
|
teamID = uuid.New().String()
|
|
inviteID = uuid.New().String()
|
|
)
|
|
|
|
t.Run("fails with invalid argument when no join ID is specified", func(t *testing.T) {
|
|
_, client := setupTeamService(t)
|
|
|
|
_, err := client.JoinTeam(context.Background(), connect.NewRequest(&v1.JoinTeamRequest{
|
|
InvitationId: "",
|
|
}))
|
|
require.Error(t, err)
|
|
require.Equal(t, connect.CodeInvalidArgument, connect.CodeOf(err))
|
|
})
|
|
|
|
t.Run("delegates joining to server, and populates team response", func(t *testing.T) {
|
|
serverMock, client := setupTeamService(t)
|
|
|
|
team := newTeam(&protocol.Team{ID: teamID})
|
|
teamMembers := []*protocol.TeamMemberInfo{newTeamMember(&protocol.TeamMemberInfo{})}
|
|
invite := &protocol.TeamMembershipInvite{
|
|
ID: uuid.New().String(),
|
|
}
|
|
|
|
serverMock.EXPECT().JoinTeam(gomock.Any(), inviteID).Return(team, nil)
|
|
serverMock.EXPECT().GetTeamMembers(gomock.Any(), teamID).Return(teamMembers, nil)
|
|
serverMock.EXPECT().GetGenericInvite(gomock.Any(), teamID).Return(invite, nil)
|
|
|
|
response, err := client.JoinTeam(context.Background(), connect.NewRequest(&v1.JoinTeamRequest{
|
|
InvitationId: inviteID,
|
|
}))
|
|
require.NoError(t, err)
|
|
requireEqualProto(t, &v1.JoinTeamResponse{
|
|
Team: teamToAPIResponse(team, teamMembers, invite),
|
|
}, response.Msg)
|
|
})
|
|
}
|
|
|
|
func TestTeamToAPIResponse(t *testing.T) {
|
|
// Here, we're deliberately not using our helpers newTeam, newTeamMembers because
|
|
// we want to assert from first principles
|
|
team := &protocol.Team{
|
|
ID: uuid.New().String(),
|
|
Name: "New Team",
|
|
CreationTime: "2022-09-09T09:09:09.000Z",
|
|
}
|
|
members := []*protocol.TeamMemberInfo{
|
|
{
|
|
UserId: uuid.New().String(),
|
|
FullName: "First Last",
|
|
PrimaryEmail: "email1@gitpod.io",
|
|
AvatarUrl: "https://avatars.com/foo",
|
|
Role: protocol.TeamMember_Member,
|
|
MemberSince: "2022-09-09T09:09:09.000Z",
|
|
},
|
|
{
|
|
UserId: uuid.New().String(),
|
|
FullName: "Second Last",
|
|
PrimaryEmail: "email2@gitpod.io",
|
|
AvatarUrl: "https://avatars.com/bar",
|
|
Role: protocol.TeamMember_Owner,
|
|
MemberSince: "2022-09-09T09:09:09.000Z",
|
|
},
|
|
}
|
|
invite := &protocol.TeamMembershipInvite{
|
|
ID: uuid.New().String(),
|
|
TeamID: uuid.New().String(),
|
|
Role: protocol.TeamMember_Member,
|
|
CreationTime: "2022-08-08T08:08:08.000Z",
|
|
InvalidationTime: "2022-11-11T11:11:11.000Z",
|
|
InvitedEmail: "nope@gitpod.io",
|
|
}
|
|
|
|
response := teamToAPIResponse(team, members, invite)
|
|
requireEqualProto(t, &v1.Team{
|
|
Id: team.ID,
|
|
Name: team.Name,
|
|
Members: []*v1.TeamMember{
|
|
{
|
|
UserId: members[0].UserId,
|
|
Role: teamRoleToAPIResponse(members[0].Role),
|
|
MemberSince: parseGitpodTimeStampOrDefault(members[0].MemberSince),
|
|
AvatarUrl: members[0].AvatarUrl,
|
|
FullName: members[0].FullName,
|
|
PrimaryEmail: members[0].PrimaryEmail,
|
|
},
|
|
{
|
|
UserId: members[1].UserId,
|
|
Role: teamRoleToAPIResponse(members[1].Role),
|
|
MemberSince: parseGitpodTimeStampOrDefault(members[1].MemberSince),
|
|
AvatarUrl: members[1].AvatarUrl,
|
|
FullName: members[1].FullName,
|
|
PrimaryEmail: members[1].PrimaryEmail,
|
|
},
|
|
},
|
|
TeamInvitation: &v1.TeamInvitation{
|
|
Id: invite.ID,
|
|
},
|
|
}, response)
|
|
}
|
|
|
|
func TestTeamsService_ListTeamMembers(t *testing.T) {
|
|
t.Run("missing team ID returns invalid argument", func(t *testing.T) {
|
|
_, client := setupTeamService(t)
|
|
|
|
_, err := client.ListTeamMembers(context.Background(), connect.NewRequest(&v1.ListTeamMembersRequest{}))
|
|
require.Error(t, err)
|
|
require.Equal(t, connect.CodeInvalidArgument, connect.CodeOf(err))
|
|
})
|
|
|
|
t.Run("returns permission denied for non-owner", func(t *testing.T) {
|
|
ctx := context.Background()
|
|
serverMock, client := setupTeamService(t)
|
|
|
|
team := newTeam(&protocol.Team{
|
|
Name: "Team A",
|
|
})
|
|
serverMock.EXPECT().GetTeamMembers(gomock.Any(), team.ID).Return(nil, &jsonrpc2.Error{Code: 403, Message: "not access"})
|
|
|
|
_, err := client.ListTeamMembers(ctx, connect.NewRequest(&v1.ListTeamMembersRequest{
|
|
TeamId: team.ID,
|
|
}))
|
|
require.Error(t, err)
|
|
require.Equal(t, connect.CodePermissionDenied, connect.CodeOf(err))
|
|
})
|
|
|
|
t.Run("returns members", func(t *testing.T) {
|
|
teamMembers := []*protocol.TeamMemberInfo{
|
|
newTeamMember(&protocol.TeamMemberInfo{
|
|
FullName: "Alice Alice",
|
|
Role: protocol.TeamMember_Owner,
|
|
}),
|
|
newTeamMember(&protocol.TeamMemberInfo{
|
|
FullName: "Bob Bob",
|
|
Role: protocol.TeamMember_Member,
|
|
}),
|
|
}
|
|
team := newTeam(&protocol.Team{
|
|
ID: uuid.New().String(),
|
|
})
|
|
|
|
serverMock, client := setupTeamService(t)
|
|
|
|
serverMock.EXPECT().GetTeamMembers(gomock.Any(), team.ID).Return(teamMembers, nil)
|
|
|
|
response, err := client.ListTeamMembers(context.Background(), connect.NewRequest(&v1.ListTeamMembersRequest{TeamId: team.ID}))
|
|
require.NoError(t, err)
|
|
|
|
requireEqualProto(t, &v1.ListTeamMembersResponse{
|
|
Members: teamMembersToAPIResponse(teamMembers),
|
|
}, response.Msg)
|
|
})
|
|
}
|
|
|
|
func TestTeamsService_UpdateTeamMember(t *testing.T) {
|
|
var (
|
|
teamID = uuid.New().String()
|
|
teamMemberID = uuid.New().String()
|
|
)
|
|
|
|
t.Run("invalid argument when team ID is missing", func(t *testing.T) {
|
|
_, client := setupTeamService(t)
|
|
|
|
_, err := client.UpdateTeamMember(context.Background(), connect.NewRequest(&v1.UpdateTeamMemberRequest{}))
|
|
require.Error(t, err)
|
|
require.Equal(t, connect.CodeInvalidArgument, connect.CodeOf(err))
|
|
})
|
|
|
|
t.Run("invalid argument when team member ID is missing", func(t *testing.T) {
|
|
_, client := setupTeamService(t)
|
|
|
|
_, err := client.UpdateTeamMember(context.Background(), connect.NewRequest(&v1.UpdateTeamMemberRequest{
|
|
TeamId: teamID,
|
|
TeamMember: &v1.TeamMember{},
|
|
}))
|
|
require.Error(t, err)
|
|
require.Equal(t, connect.CodeInvalidArgument, connect.CodeOf(err))
|
|
})
|
|
|
|
t.Run("invalid argument when team member role is missing", func(t *testing.T) {
|
|
_, client := setupTeamService(t)
|
|
|
|
_, err := client.UpdateTeamMember(context.Background(), connect.NewRequest(&v1.UpdateTeamMemberRequest{
|
|
TeamId: teamID,
|
|
TeamMember: &v1.TeamMember{
|
|
UserId: teamMemberID,
|
|
},
|
|
}))
|
|
require.Error(t, err)
|
|
require.Equal(t, connect.CodeInvalidArgument, connect.CodeOf(err))
|
|
})
|
|
|
|
t.Run("proxies request to server", func(t *testing.T) {
|
|
serverMock, client := setupTeamService(t)
|
|
|
|
serverMock.EXPECT().SetTeamMemberRole(gomock.Any(), teamID, teamMemberID, protocol.TeamMember_Owner).Return(nil)
|
|
|
|
response, err := client.UpdateTeamMember(context.Background(), connect.NewRequest(&v1.UpdateTeamMemberRequest{
|
|
TeamId: teamID,
|
|
TeamMember: &v1.TeamMember{
|
|
UserId: teamMemberID,
|
|
Role: v1.TeamRole_TEAM_ROLE_OWNER,
|
|
},
|
|
}))
|
|
require.NoError(t, err)
|
|
requireEqualProto(t, &v1.UpdateTeamMemberResponse{
|
|
TeamMember: &v1.TeamMember{
|
|
UserId: teamMemberID,
|
|
Role: v1.TeamRole_TEAM_ROLE_OWNER,
|
|
},
|
|
}, response.Msg)
|
|
})
|
|
}
|
|
|
|
func TestTeamsService_DeleteTeamMember(t *testing.T) {
|
|
var (
|
|
teamID = uuid.New().String()
|
|
teamMemberID = uuid.New().String()
|
|
)
|
|
|
|
t.Run("invalid argument when team ID is missing", func(t *testing.T) {
|
|
_, client := setupTeamService(t)
|
|
|
|
_, err := client.DeleteTeamMember(context.Background(), connect.NewRequest(&v1.DeleteTeamMemberRequest{}))
|
|
require.Error(t, err)
|
|
require.Equal(t, connect.CodeInvalidArgument, connect.CodeOf(err))
|
|
})
|
|
|
|
t.Run("invalid argument when team member ID is missing", func(t *testing.T) {
|
|
_, client := setupTeamService(t)
|
|
|
|
_, err := client.DeleteTeamMember(context.Background(), connect.NewRequest(&v1.DeleteTeamMemberRequest{
|
|
TeamId: teamID,
|
|
}))
|
|
require.Error(t, err)
|
|
require.Equal(t, connect.CodeInvalidArgument, connect.CodeOf(err))
|
|
})
|
|
|
|
t.Run("proxies to server", func(t *testing.T) {
|
|
serverMock, client := setupTeamService(t)
|
|
|
|
serverMock.EXPECT().RemoveTeamMember(gomock.Any(), teamID, teamMemberID).Return(nil)
|
|
|
|
response, err := client.DeleteTeamMember(context.Background(), connect.NewRequest(&v1.DeleteTeamMemberRequest{
|
|
TeamId: teamID,
|
|
TeamMemberId: teamMemberID,
|
|
}))
|
|
require.NoError(t, err)
|
|
requireEqualProto(t, &v1.DeleteTeamMemberResponse{}, response.Msg)
|
|
})
|
|
}
|
|
|
|
func TestTeamService_ResetTeamInvitation(t *testing.T) {
|
|
t.Run("missing team ID returns invalid argument", func(t *testing.T) {
|
|
_, client := setupTeamService(t)
|
|
|
|
_, err := client.ResetTeamInvitation(context.Background(), connect.NewRequest(&v1.ResetTeamInvitationRequest{}))
|
|
require.Error(t, err)
|
|
require.Equal(t, connect.CodeInvalidArgument, connect.CodeOf(err))
|
|
})
|
|
|
|
t.Run("proxies request to server", func(t *testing.T) {
|
|
teamID := uuid.New().String()
|
|
|
|
serverMock, client := setupTeamService(t)
|
|
|
|
invite := &protocol.TeamMembershipInvite{
|
|
ID: uuid.New().String(),
|
|
}
|
|
|
|
serverMock.EXPECT().ResetGenericInvite(gomock.Any(), teamID).Return(invite, nil)
|
|
|
|
response, err := client.ResetTeamInvitation(context.Background(), connect.NewRequest(&v1.ResetTeamInvitationRequest{
|
|
TeamId: teamID,
|
|
}))
|
|
require.NoError(t, err)
|
|
requireEqualProto(t, &v1.ResetTeamInvitationResponse{
|
|
TeamInvitation: teamInviteToAPIResponse(invite),
|
|
}, response.Msg)
|
|
})
|
|
}
|
|
|
|
func TestTeamService_GetTeamInvitation(t *testing.T) {
|
|
t.Run("missing team ID returns invalid argument", func(t *testing.T) {
|
|
_, client := setupTeamService(t)
|
|
|
|
_, err := client.GetTeamInvitation(context.Background(), connect.NewRequest(&v1.GetTeamInvitationRequest{}))
|
|
require.Error(t, err)
|
|
require.Equal(t, connect.CodeInvalidArgument, connect.CodeOf(err))
|
|
})
|
|
|
|
t.Run("proxies request to server", func(t *testing.T) {
|
|
teamID := uuid.New().String()
|
|
|
|
serverMock, client := setupTeamService(t)
|
|
|
|
invite := &protocol.TeamMembershipInvite{
|
|
ID: uuid.New().String(),
|
|
}
|
|
|
|
serverMock.EXPECT().GetGenericInvite(gomock.Any(), teamID).Return(invite, nil)
|
|
|
|
response, err := client.GetTeamInvitation(context.Background(), connect.NewRequest(&v1.GetTeamInvitationRequest{
|
|
TeamId: teamID,
|
|
}))
|
|
require.NoError(t, err)
|
|
requireEqualProto(t, &v1.GetTeamInvitationResponse{
|
|
TeamInvitation: teamInviteToAPIResponse(invite),
|
|
}, response.Msg)
|
|
})
|
|
|
|
t.Run("returns permission denied for non-owner", func(t *testing.T) {
|
|
ctx := context.Background()
|
|
serverMock, client := setupTeamService(t)
|
|
|
|
team := newTeam(&protocol.Team{
|
|
Name: "Team A",
|
|
})
|
|
serverMock.EXPECT().GetGenericInvite(gomock.Any(), team.ID).Return(nil, &jsonrpc2.Error{Code: 403, Message: "not access"})
|
|
|
|
_, err := client.GetTeamInvitation(ctx, connect.NewRequest(&v1.GetTeamInvitationRequest{
|
|
TeamId: team.ID,
|
|
}))
|
|
require.Error(t, err)
|
|
require.Equal(t, connect.CodePermissionDenied, connect.CodeOf(err))
|
|
})
|
|
}
|
|
|
|
func TestTeamService_DeleteTeam(t *testing.T) {
|
|
t.Run("missing team ID returns invalid argument", func(t *testing.T) {
|
|
_, client := setupTeamService(t)
|
|
|
|
_, err := client.DeleteTeam(context.Background(), connect.NewRequest(&v1.DeleteTeamRequest{}))
|
|
require.Error(t, err)
|
|
require.Equal(t, connect.CodeInvalidArgument, connect.CodeOf(err))
|
|
})
|
|
|
|
t.Run("proxies request to server", func(t *testing.T) {
|
|
teamID := uuid.New().String()
|
|
|
|
serverMock, client := setupTeamService(t)
|
|
|
|
serverMock.EXPECT().DeleteTeam(gomock.Any(), teamID).Return(nil)
|
|
|
|
response, err := client.DeleteTeam(context.Background(), connect.NewRequest(&v1.DeleteTeamRequest{
|
|
TeamId: teamID,
|
|
}))
|
|
require.NoError(t, err)
|
|
requireEqualProto(t, &v1.DeleteTeamResponse{}, response.Msg)
|
|
})
|
|
}
|
|
|
|
func newTeam(t *protocol.Team) *protocol.Team {
|
|
result := &protocol.Team{
|
|
ID: uuid.New().String(),
|
|
Name: "Team Name",
|
|
CreationTime: "2022-10-10T10:10:10.000Z",
|
|
}
|
|
|
|
if t.ID != "" {
|
|
result.ID = t.ID
|
|
}
|
|
|
|
if t.Name != "" {
|
|
result.Name = t.Name
|
|
}
|
|
|
|
if t.CreationTime != "" {
|
|
result.CreationTime = t.CreationTime
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func newTeamMember(m *protocol.TeamMemberInfo) *protocol.TeamMemberInfo {
|
|
result := &protocol.TeamMemberInfo{
|
|
UserId: uuid.New().String(),
|
|
FullName: "First Last",
|
|
PrimaryEmail: "email@gitpod.io",
|
|
AvatarUrl: "https://avatars.yolo/first.png",
|
|
Role: protocol.TeamMember_Member,
|
|
MemberSince: "2022-09-09T09:09:09.000Z",
|
|
}
|
|
|
|
if m.UserId != "" {
|
|
result.UserId = m.UserId
|
|
}
|
|
if m.FullName != "" {
|
|
result.FullName = m.FullName
|
|
}
|
|
if m.PrimaryEmail != "" {
|
|
result.PrimaryEmail = m.PrimaryEmail
|
|
}
|
|
if m.AvatarUrl != "" {
|
|
result.AvatarUrl = m.AvatarUrl
|
|
}
|
|
if m.Role != "" {
|
|
result.Role = m.Role
|
|
}
|
|
if m.MemberSince != "" {
|
|
result.MemberSince = m.MemberSince
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func setupTeamService(t *testing.T) (*protocol.MockAPIInterface, v1connect.TeamsServiceClient) {
|
|
t.Helper()
|
|
|
|
ctrl := gomock.NewController(t)
|
|
t.Cleanup(ctrl.Finish)
|
|
|
|
serverMock := protocol.NewMockAPIInterface(ctrl)
|
|
|
|
svc := NewTeamsService(&FakeServerConnPool{
|
|
api: serverMock,
|
|
})
|
|
|
|
keyset := jwstest.GenerateKeySet(t)
|
|
rsa256, err := jws.NewRSA256(keyset)
|
|
require.NoError(t, err)
|
|
|
|
_, handler := v1connect.NewTeamsServiceHandler(svc, connect.WithInterceptors(auth.NewServerInterceptor(config.SessionConfig{
|
|
Issuer: "unitetest.com",
|
|
Cookie: config.CookieConfig{
|
|
Name: "cookie_jwt",
|
|
},
|
|
}, rsa256)))
|
|
|
|
srv := httptest.NewServer(handler)
|
|
t.Cleanup(srv.Close)
|
|
|
|
client := v1connect.NewTeamsServiceClient(http.DefaultClient, srv.URL, connect.WithInterceptors(
|
|
auth.NewClientInterceptor("auth-token"),
|
|
))
|
|
|
|
return serverMock, client
|
|
}
|
|
|
|
func requireEqualProto(t *testing.T, expected interface{}, actual interface{}) {
|
|
t.Helper()
|
|
|
|
diff := cmp.Diff(expected, actual, protocmp.Transform())
|
|
if diff != "" {
|
|
require.Fail(t, diff)
|
|
}
|
|
}
|