fleet/server/datastore/mysql/invites_test.go

293 lines
7.5 KiB
Go

package mysql
import (
"context"
"errors"
"fmt"
"testing"
"github.com/fleetdm/fleet/v4/server/fleet"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/guregu/null.v3"
)
func TestInvites(t *testing.T) {
ds := CreateMySQLDS(t)
cases := []struct {
name string
fn func(t *testing.T, ds *Datastore)
}{
{"Create", testInvitesCreate},
{"List", testInvitesList},
{"Delete", testInvitesDelete},
{"ByToken", testInvitesByToken},
{"ByEmail", testInvitesByEmail},
{"Invite", testInvitesInvite},
{"Update", testInvitesUpdate},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
defer TruncateTables(t, ds)
c.fn(t, ds)
})
}
}
func testInvitesCreate(t *testing.T, ds *Datastore) {
for i := 0; i < 3; i++ {
_, err := ds.NewTeam(context.Background(), &fleet.Team{Name: fmt.Sprintf("%d", i)})
require.NoError(t, err)
}
invite := &fleet.Invite{
Email: "user@foo.com",
Name: "user",
Token: "some_user",
Teams: []fleet.UserTeam{
{Role: fleet.RoleObserver, Team: fleet.Team{ID: 1}},
{Role: fleet.RoleMaintainer, Team: fleet.Team{ID: 3}},
},
}
invite, err := ds.NewInvite(context.Background(), invite)
require.NoError(t, err)
verify, err := ds.InviteByEmail(context.Background(), invite.Email)
require.NoError(t, err)
assert.Equal(t, invite.ID, verify.ID)
assert.Equal(t, invite.Email, verify.Email)
assert.Len(t, invite.Teams, 2)
_, err = ds.NewInvite(context.Background(), &fleet.Invite{
Email: "anotheruser@foo.com",
Name: "anotheruser",
Token: "anothersome_user",
Teams: []fleet.UserTeam{
{Role: fleet.RoleAdmin, Team: fleet.Team{ID: 3}},
},
})
require.NoError(t, err)
}
func setupTestInvites(t *testing.T, ds fleet.Datastore) {
admin := &fleet.Invite{
Email: "admin@foo.com",
Name: "Xadmin",
Token: "admin",
GlobalRole: null.StringFrom("admin"),
}
admin, err := ds.NewInvite(context.Background(), admin)
require.NoError(t, err)
for user := 0; user < 23; user++ {
i := fleet.Invite{
InvitedBy: admin.ID,
Email: fmt.Sprintf("user%d@foo.com", user),
Name: fmt.Sprintf("User%02d", user),
Token: fmt.Sprintf("usertoken%d", user),
GlobalRole: null.StringFrom("observer"),
}
_, err := ds.NewInvite(context.Background(), &i)
require.NoError(t, err, "Failure creating user", user)
}
}
func testInvitesList(t *testing.T, ds *Datastore) {
setupTestInvites(t, ds)
opt := fleet.ListOptions{
Page: 0,
PerPage: 10,
OrderDirection: fleet.OrderAscending,
OrderKey: "name",
}
result, err := ds.ListInvites(context.Background(), opt)
assert.Nil(t, err)
assert.NotNil(t, result)
assert.Equal(t, len(result), 10)
assert.Equal(t, "User00", result[0].Name)
assert.Equal(t, "User09", result[9].Name)
assert.Equal(t, null.StringFrom("observer"), result[9].GlobalRole)
opt.Page = 2
opt.OrderDirection = fleet.OrderDescending
result, err = ds.ListInvites(context.Background(), opt)
assert.Nil(t, err)
assert.Equal(t, 4, len(result)) // allow for admin we created
assert.Equal(t, "User00", result[3].Name)
}
func testInvitesDelete(t *testing.T, ds *Datastore) {
setupTestInvites(t, ds)
invite, err := ds.InviteByEmail(context.Background(), "user0@foo.com")
assert.Nil(t, err)
assert.NotNil(t, invite)
err = ds.DeleteInvite(context.Background(), invite.ID)
assert.Nil(t, err)
invite, err = ds.InviteByEmail(context.Background(), "user0@foo.com")
assert.NotNil(t, err)
assert.Nil(t, invite)
}
func testInvitesByToken(t *testing.T, ds *Datastore) {
setupTestInvites(t, ds)
var inviteTests = []struct {
token string
wantErr error
}{
{
token: "admin",
},
{
token: "nosuchtoken",
wantErr: errors.New("Invite with token nosuchtoken was not found in the datastore"),
},
}
for _, tt := range inviteTests {
t.Run(tt.token, func(t *testing.T) {
invite, err := ds.InviteByToken(context.Background(), tt.token)
if tt.wantErr != nil {
require.NotNil(t, err)
assert.Contains(t, err.Error(), tt.wantErr.Error())
return
}
require.Nil(t, err)
assert.NotEqual(t, invite.ID, 0)
})
}
}
func testInvitesByEmail(t *testing.T, ds *Datastore) {
setupTestInvites(t, ds)
var inviteTests = []struct {
email string
wantErr error
}{
{
email: "user0@foo.com",
},
{
email: "nosuchuser@nosuchdomain.com",
wantErr: errors.New("Invite with email nosuchuser@nosuchdomain.com was not found in the datastore"),
},
}
for _, tt := range inviteTests {
t.Run(tt.email, func(t *testing.T) {
invite, err := ds.InviteByEmail(context.Background(), tt.email)
if tt.wantErr != nil {
require.NotNil(t, err)
assert.Contains(t, err.Error(), tt.wantErr.Error())
return
}
require.Nil(t, err)
assert.NotEqual(t, invite.ID, 0)
})
}
}
func testInvitesInvite(t *testing.T, ds *Datastore) {
admin := &fleet.Invite{
Email: "admin@foo.com",
Name: "Xadmin",
Token: "admin",
GlobalRole: null.StringFrom("admin"),
}
admin, err := ds.NewInvite(context.Background(), admin)
require.NoError(t, err)
gotI, err := ds.Invite(context.Background(), admin.ID)
require.NoError(t, err)
assert.Equal(t, admin.ID, gotI.ID)
}
func testInvitesUpdate(t *testing.T, ds *Datastore) {
for i := 0; i < 3; i++ {
_, err := ds.NewTeam(context.Background(), &fleet.Team{Name: fmt.Sprintf("%d", i)})
require.NoError(t, err)
}
invite := &fleet.Invite{
Email: "user@foo.com",
Name: "user",
Token: "some_user",
Teams: []fleet.UserTeam{
{Role: fleet.RoleObserver, Team: fleet.Team{ID: 1}},
{Role: fleet.RoleMaintainer, Team: fleet.Team{ID: 3}},
},
}
sentinelInvite := &fleet.Invite{
Email: "user@sentinel.com",
Name: "sentinel",
Token: "some_sentinel",
Teams: []fleet.UserTeam{
{Role: fleet.RoleAdmin, Team: fleet.Team{ID: 1}},
},
}
invite, err := ds.NewInvite(context.Background(), invite)
require.NoError(t, err)
sentinelInvite, err = ds.NewInvite(context.Background(), sentinelInvite)
require.NoError(t, err)
invite.Name = "someothername"
invite, err = ds.UpdateInvite(context.Background(), invite.ID, invite)
require.NoError(t, err)
verify, err := ds.InviteByEmail(context.Background(), invite.Email)
require.NoError(t, err)
assert.Equal(t, invite.ID, verify.ID)
assert.Equal(t, verify.Name, "someothername")
invite.Teams = []fleet.UserTeam{
{Role: fleet.RoleObserver, Team: fleet.Team{ID: 1}},
{Role: fleet.RoleMaintainer, Team: fleet.Team{ID: 2}},
}
invite, err = ds.UpdateInvite(context.Background(), invite.ID, invite)
require.NoError(t, err)
verify, err = ds.InviteByEmail(context.Background(), invite.Email)
require.NoError(t, err)
assert.Equal(t, invite.ID, verify.ID)
require.Len(t, verify.Teams, 2)
assert.Equal(t, uint(1), invite.Teams[0].ID)
assert.Equal(t, uint(2), invite.Teams[1].ID)
invite.GlobalRole = null.StringFrom(fleet.RoleAdmin)
invite.Teams = nil
invite, err = ds.UpdateInvite(context.Background(), invite.ID, invite)
require.NoError(t, err)
verify, err = ds.InviteByEmail(context.Background(), invite.Email)
require.NoError(t, err)
assert.Equal(t, invite.ID, verify.ID)
assert.Equal(t, null.StringFrom(fleet.RoleAdmin), verify.GlobalRole)
assert.Len(t, verify.Teams, 0)
// Make sure it only updates the specified invite
verify, err = ds.InviteByEmail(context.Background(), sentinelInvite.Email)
require.NoError(t, err)
assert.Equal(t, verify.ID, sentinelInvite.ID)
assert.Equal(t, verify.Name, sentinelInvite.Name)
require.Len(t, verify.Teams, 1)
assert.Equal(t, fleet.RoleAdmin, verify.Teams[0].Role)
}