Refactor usage of null values in Teams models (#863)
- Use pointers rather than null package types. - Use new internal ptr package. - Improved handling of changing user teams/roles.
This commit is contained in:
@@ -11,10 +11,10 @@ import (
|
||||
|
||||
"github.com/WatchBeam/clock"
|
||||
"github.com/fleetdm/fleet/server/kolide"
|
||||
"github.com/fleetdm/fleet/server/ptr"
|
||||
"github.com/fleetdm/fleet/server/test"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/guregu/null.v3"
|
||||
)
|
||||
|
||||
var enrollTests = []struct {
|
||||
@@ -495,7 +495,7 @@ func testSearchHosts(t *testing.T, ds kolide.Datastore) {
|
||||
})
|
||||
require.Nil(t, err)
|
||||
|
||||
user := &kolide.User{GlobalRole: null.StringFrom(kolide.RoleAdmin)}
|
||||
user := &kolide.User{GlobalRole: ptr.String(kolide.RoleAdmin)}
|
||||
filter := kolide.TeamFilter{User: user}
|
||||
|
||||
// We once threw errors when the search query was empty. Verify that we
|
||||
@@ -551,7 +551,7 @@ func testSearchHosts(t *testing.T, ds kolide.Datastore) {
|
||||
}
|
||||
|
||||
func testSearchHostsLimit(t *testing.T, ds kolide.Datastore) {
|
||||
user := &kolide.User{GlobalRole: null.StringFrom(kolide.RoleAdmin)}
|
||||
user := &kolide.User{GlobalRole: ptr.String(kolide.RoleAdmin)}
|
||||
filter := kolide.TeamFilter{User: user}
|
||||
|
||||
for i := 0; i < 15; i++ {
|
||||
@@ -939,7 +939,7 @@ func testAddHostsToTeam(t *testing.T, ds kolide.Datastore) {
|
||||
for i := 1; i <= 10; i++ {
|
||||
host, err := ds.Host(uint(i))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, null.Int{}, host.TeamID)
|
||||
assert.Nil(t, host.TeamID)
|
||||
}
|
||||
|
||||
require.NoError(t, ds.AddHostsToTeam(&team1.ID, []uint{1, 2, 3}))
|
||||
@@ -948,12 +948,12 @@ func testAddHostsToTeam(t *testing.T, ds kolide.Datastore) {
|
||||
for i := 1; i <= 10; i++ {
|
||||
host, err := ds.Host(uint(i))
|
||||
require.NoError(t, err)
|
||||
expectedID := null.Int{}
|
||||
var expectedID *uint
|
||||
switch {
|
||||
case i <= 2:
|
||||
expectedID = null.IntFrom(int64(team1.ID))
|
||||
expectedID = &team1.ID
|
||||
case i <= 5:
|
||||
expectedID = null.IntFrom(int64(team2.ID))
|
||||
expectedID = &team2.ID
|
||||
}
|
||||
assert.Equal(t, expectedID, host.TeamID)
|
||||
}
|
||||
@@ -964,10 +964,10 @@ func testAddHostsToTeam(t *testing.T, ds kolide.Datastore) {
|
||||
for i := 1; i <= 10; i++ {
|
||||
host, err := ds.Host(uint(i))
|
||||
require.NoError(t, err)
|
||||
expectedID := null.Int{}
|
||||
var expectedID *uint
|
||||
switch {
|
||||
case i >= 5:
|
||||
expectedID = null.IntFrom(int64(team1.ID))
|
||||
expectedID = &team1.ID
|
||||
}
|
||||
assert.Equal(t, expectedID, host.TeamID)
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/fleetdm/fleet/server/kolide"
|
||||
"github.com/fleetdm/fleet/server/ptr"
|
||||
"github.com/fleetdm/fleet/server/test"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/guregu/null.v3"
|
||||
)
|
||||
|
||||
func testLabels(t *testing.T, db kolide.Datastore) {
|
||||
@@ -240,7 +240,7 @@ func testSearchLabels(t *testing.T, db kolide.Datastore) {
|
||||
l3, err := db.Label(specs[2].ID)
|
||||
require.Nil(t, err)
|
||||
|
||||
user := &kolide.User{GlobalRole: null.StringFrom(kolide.RoleAdmin)}
|
||||
user := &kolide.User{GlobalRole: ptr.String(kolide.RoleAdmin)}
|
||||
filter := kolide.TeamFilter{User: user}
|
||||
|
||||
// We once threw errors when the search query was empty. Verify that we
|
||||
@@ -285,7 +285,7 @@ func testSearchLabelsLimit(t *testing.T, db kolide.Datastore) {
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
user := &kolide.User{GlobalRole: null.StringFrom(kolide.RoleAdmin)}
|
||||
user := &kolide.User{GlobalRole: ptr.String(kolide.RoleAdmin)}
|
||||
filter := kolide.TeamFilter{User: user}
|
||||
|
||||
labels, err := db.SearchLabels(filter, "foo")
|
||||
@@ -357,7 +357,7 @@ func testListHostsInLabel(t *testing.T, db kolide.Datastore) {
|
||||
func testBuiltInLabels(t *testing.T, db kolide.Datastore) {
|
||||
require.Nil(t, db.MigrateData())
|
||||
|
||||
user := &kolide.User{GlobalRole: null.StringFrom(kolide.RoleAdmin)}
|
||||
user := &kolide.User{GlobalRole: ptr.String(kolide.RoleAdmin)}
|
||||
filter := kolide.TeamFilter{User: user}
|
||||
|
||||
hits, err := db.SearchLabels(filter, "macOS")
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/WatchBeam/clock"
|
||||
"github.com/fleetdm/fleet/server/kolide"
|
||||
"github.com/fleetdm/fleet/server/ptr"
|
||||
"github.com/fleetdm/fleet/server/test"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -191,9 +192,6 @@ func setupPackSpecsTest(t *testing.T, ds kolide.Datastore) []*kolide.PackSpec {
|
||||
err = ds.ApplyLabelSpecs(labels)
|
||||
require.Nil(t, err)
|
||||
|
||||
boolPtr := func(b bool) *bool { return &b }
|
||||
uintPtr := func(x uint) *uint { return &x }
|
||||
stringPtr := func(s string) *string { return &s }
|
||||
expectedSpecs := []*kolide.PackSpec{
|
||||
&kolide.PackSpec{
|
||||
ID: 1,
|
||||
@@ -216,18 +214,18 @@ func setupPackSpecsTest(t *testing.T, ds kolide.Datastore) []*kolide.PackSpec {
|
||||
QueryName: queries[0].Name,
|
||||
Name: "foo_snapshot",
|
||||
Interval: 600,
|
||||
Snapshot: boolPtr(true),
|
||||
Denylist: boolPtr(false),
|
||||
Snapshot: ptr.Bool(true),
|
||||
Denylist: ptr.Bool(false),
|
||||
},
|
||||
kolide.PackSpecQuery{
|
||||
Name: "q2",
|
||||
QueryName: queries[1].Name,
|
||||
Interval: 600,
|
||||
Removed: boolPtr(false),
|
||||
Shard: uintPtr(73),
|
||||
Platform: stringPtr("foobar"),
|
||||
Version: stringPtr("0.0.0.0.0.1"),
|
||||
Denylist: boolPtr(true),
|
||||
Removed: ptr.Bool(false),
|
||||
Shard: ptr.Uint(73),
|
||||
Platform: ptr.String("foobar"),
|
||||
Version: ptr.String("0.0.0.0.0.1"),
|
||||
Denylist: ptr.Bool(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -253,16 +251,16 @@ func setupPackSpecsTest(t *testing.T, ds kolide.Datastore) []*kolide.PackSpec {
|
||||
QueryName: queries[0].Name,
|
||||
Name: "foo_snapshot",
|
||||
Interval: 600,
|
||||
Snapshot: boolPtr(true),
|
||||
Snapshot: ptr.Bool(true),
|
||||
},
|
||||
kolide.PackSpecQuery{
|
||||
Name: "q2",
|
||||
QueryName: queries[1].Name,
|
||||
Interval: 600,
|
||||
Removed: boolPtr(false),
|
||||
Shard: uintPtr(73),
|
||||
Platform: stringPtr("foobar"),
|
||||
Version: stringPtr("0.0.0.0.0.1"),
|
||||
Removed: ptr.Bool(false),
|
||||
Shard: ptr.Uint(73),
|
||||
Platform: ptr.String("foobar"),
|
||||
Version: ptr.String("0.0.0.0.0.1"),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/fleetdm/fleet/server/kolide"
|
||||
"github.com/fleetdm/fleet/server/ptr"
|
||||
"github.com/fleetdm/fleet/server/test"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -19,11 +20,11 @@ func testListScheduledQueriesInPack(t *testing.T, ds kolide.Datastore) {
|
||||
require.Nil(t, err)
|
||||
|
||||
specs := []*kolide.PackSpec{
|
||||
&kolide.PackSpec{
|
||||
{
|
||||
Name: "baz",
|
||||
Targets: kolide.PackSpecTargets{Labels: []string{}},
|
||||
Queries: []kolide.PackSpecQuery{
|
||||
kolide.PackSpecQuery{
|
||||
{
|
||||
QueryName: queries[0].Name,
|
||||
Description: "test_foo",
|
||||
Interval: 60,
|
||||
@@ -41,29 +42,28 @@ func testListScheduledQueriesInPack(t *testing.T, ds kolide.Datastore) {
|
||||
assert.Equal(t, "test_foo", gotQueries[0].Description)
|
||||
assert.Equal(t, "select * from foo", gotQueries[0].Query)
|
||||
|
||||
boolPtr := func(b bool) *bool { return &b }
|
||||
specs = []*kolide.PackSpec{
|
||||
&kolide.PackSpec{
|
||||
{
|
||||
Name: "baz",
|
||||
Targets: kolide.PackSpecTargets{Labels: []string{}},
|
||||
Queries: []kolide.PackSpecQuery{
|
||||
kolide.PackSpecQuery{
|
||||
{
|
||||
QueryName: queries[0].Name,
|
||||
Description: "test_foo",
|
||||
Interval: 60,
|
||||
},
|
||||
kolide.PackSpecQuery{
|
||||
{
|
||||
QueryName: queries[1].Name,
|
||||
Name: "test bar",
|
||||
Description: "test_bar",
|
||||
Interval: 60,
|
||||
},
|
||||
kolide.PackSpecQuery{
|
||||
{
|
||||
QueryName: queries[1].Name,
|
||||
Name: "test bar snapshot",
|
||||
Description: "test_bar",
|
||||
Interval: 60,
|
||||
Snapshot: boolPtr(true),
|
||||
Snapshot: ptr.Bool(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -143,22 +143,22 @@ func testCascadingDeletionOfQueries(t *testing.T, ds kolide.Datastore) {
|
||||
require.Nil(t, err)
|
||||
|
||||
specs := []*kolide.PackSpec{
|
||||
&kolide.PackSpec{
|
||||
{
|
||||
Name: "baz",
|
||||
Targets: kolide.PackSpecTargets{Labels: []string{}},
|
||||
Queries: []kolide.PackSpecQuery{
|
||||
kolide.PackSpecQuery{
|
||||
{
|
||||
QueryName: queries[0].Name,
|
||||
Description: "test_foo",
|
||||
Interval: 60,
|
||||
},
|
||||
kolide.PackSpecQuery{
|
||||
{
|
||||
QueryName: queries[1].Name,
|
||||
Name: "test bar",
|
||||
Description: "test_bar",
|
||||
Interval: 60,
|
||||
},
|
||||
kolide.PackSpecQuery{
|
||||
{
|
||||
QueryName: queries[1].Name,
|
||||
Name: "test bar snapshot",
|
||||
Description: "test_bar",
|
||||
|
||||
@@ -7,10 +7,10 @@ import (
|
||||
|
||||
"github.com/WatchBeam/clock"
|
||||
"github.com/fleetdm/fleet/server/kolide"
|
||||
"github.com/fleetdm/fleet/server/ptr"
|
||||
"github.com/fleetdm/fleet/server/test"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/guregu/null.v3"
|
||||
)
|
||||
|
||||
func testCountHostsInTargets(t *testing.T, ds kolide.Datastore) {
|
||||
@@ -18,7 +18,7 @@ func testCountHostsInTargets(t *testing.T, ds kolide.Datastore) {
|
||||
t.Skip("inmem is being deprecated, test skipped")
|
||||
}
|
||||
|
||||
user := &kolide.User{GlobalRole: null.StringFrom(kolide.RoleAdmin)}
|
||||
user := &kolide.User{GlobalRole: ptr.String(kolide.RoleAdmin)}
|
||||
filter := kolide.TeamFilter{User: user}
|
||||
|
||||
mockClock := clock.NewMockClock()
|
||||
@@ -136,7 +136,7 @@ func testHostStatus(t *testing.T, ds kolide.Datastore) {
|
||||
h, err := ds.EnrollHost("1", "key1", "default", 0)
|
||||
require.Nil(t, err)
|
||||
|
||||
user := &kolide.User{GlobalRole: null.StringFrom(kolide.RoleAdmin)}
|
||||
user := &kolide.User{GlobalRole: ptr.String(kolide.RoleAdmin)}
|
||||
filter := kolide.TeamFilter{User: user}
|
||||
|
||||
// Make host no longer appear new
|
||||
@@ -193,7 +193,7 @@ func testHostIDsInTargets(t *testing.T, ds kolide.Datastore) {
|
||||
t.Skip("inmem is being deprecated, test skipped")
|
||||
}
|
||||
|
||||
user := &kolide.User{GlobalRole: null.StringFrom(kolide.RoleAdmin)}
|
||||
user := &kolide.User{GlobalRole: ptr.String(kolide.RoleAdmin)}
|
||||
filter := kolide.TeamFilter{User: user}
|
||||
|
||||
hostCount := 0
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/fleetdm/fleet/server/kolide"
|
||||
"github.com/fleetdm/fleet/server/ptr"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/guregu/null.v3"
|
||||
)
|
||||
|
||||
func testCreateUser(t *testing.T, ds kolide.Datastore) {
|
||||
@@ -117,7 +117,7 @@ func testEmailAttribute(t *testing.T, ds kolide.Datastore, users []*kolide.User)
|
||||
|
||||
func testUserGlobalRole(t *testing.T, ds kolide.Datastore, users []*kolide.User) {
|
||||
for _, user := range users {
|
||||
user.GlobalRole = null.StringFrom("admin")
|
||||
user.GlobalRole = ptr.String("admin")
|
||||
err := ds.SaveUser(user)
|
||||
assert.Nil(t, err)
|
||||
|
||||
|
||||
@@ -353,20 +353,22 @@ func (d *Datastore) whereFilterHostsByTeams(filter kolide.TeamFilter, hostKey st
|
||||
return "FALSE"
|
||||
}
|
||||
|
||||
switch filter.User.GlobalRole.String {
|
||||
if filter.User.GlobalRole != nil {
|
||||
switch *filter.User.GlobalRole {
|
||||
|
||||
case kolide.RoleAdmin, kolide.RoleMaintainer:
|
||||
return "TRUE"
|
||||
|
||||
case kolide.RoleObserver:
|
||||
if filter.IncludeObserver {
|
||||
case kolide.RoleAdmin, kolide.RoleMaintainer:
|
||||
return "TRUE"
|
||||
} else {
|
||||
return "FALSE"
|
||||
}
|
||||
|
||||
default:
|
||||
// Fall through to specific teams
|
||||
case kolide.RoleObserver:
|
||||
if filter.IncludeObserver {
|
||||
return "TRUE"
|
||||
} else {
|
||||
return "FALSE"
|
||||
}
|
||||
|
||||
default:
|
||||
// Fall through to specific teams
|
||||
}
|
||||
}
|
||||
|
||||
// Collect matching teams
|
||||
|
||||
@@ -6,13 +6,13 @@ import (
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
"github.com/VividCortex/mysqlerr"
|
||||
"github.com/fleetdm/fleet/server/kolide"
|
||||
"github.com/fleetdm/fleet/server/ptr"
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/go-sql-driver/mysql"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/guregu/null.v3"
|
||||
)
|
||||
|
||||
func TestSanitizeColumn(t *testing.T) {
|
||||
@@ -308,25 +308,25 @@ func TestWhereFilterHostsByTeams(t *testing.T) {
|
||||
// Global role
|
||||
{
|
||||
filter: kolide.TeamFilter{
|
||||
User: &kolide.User{GlobalRole: null.StringFrom(kolide.RoleAdmin)},
|
||||
User: &kolide.User{GlobalRole: ptr.String(kolide.RoleAdmin)},
|
||||
},
|
||||
expected: "TRUE",
|
||||
},
|
||||
{
|
||||
filter: kolide.TeamFilter{
|
||||
User: &kolide.User{GlobalRole: null.StringFrom(kolide.RoleMaintainer)},
|
||||
User: &kolide.User{GlobalRole: ptr.String(kolide.RoleMaintainer)},
|
||||
},
|
||||
expected: "TRUE",
|
||||
},
|
||||
{
|
||||
filter: kolide.TeamFilter{
|
||||
User: &kolide.User{GlobalRole: null.StringFrom(kolide.RoleObserver)},
|
||||
User: &kolide.User{GlobalRole: ptr.String(kolide.RoleObserver)},
|
||||
},
|
||||
expected: "FALSE",
|
||||
},
|
||||
{
|
||||
filter: kolide.TeamFilter{
|
||||
User: &kolide.User{GlobalRole: null.StringFrom(kolide.RoleObserver)},
|
||||
User: &kolide.User{GlobalRole: ptr.String(kolide.RoleObserver)},
|
||||
IncludeObserver: true,
|
||||
},
|
||||
expected: "TRUE",
|
||||
|
||||
@@ -6,8 +6,6 @@ import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"gopkg.in/guregu/null.v3"
|
||||
)
|
||||
|
||||
type HostStatus string
|
||||
@@ -155,7 +153,7 @@ type Host struct {
|
||||
Additional *json.RawMessage `json:"additional,omitempty" db:"additional"`
|
||||
EnrollSecretName string `json:"enroll_secret_name" db:"enroll_secret_name"`
|
||||
|
||||
TeamID null.Int `json:"team_id" db:"team_id"`
|
||||
TeamID *uint `json:"team_id" db:"team_id"`
|
||||
// TeamName is the name of the team, loaded by JOIN to the teams table.
|
||||
TeamName *string `json:"team_name" db:"team_name"`
|
||||
// Loaded via JOIN in DB
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"gopkg.in/guregu/null.v3"
|
||||
)
|
||||
|
||||
// UserStore contains methods for managing users in a datastore
|
||||
@@ -101,8 +100,8 @@ type User struct {
|
||||
GravatarURL string `json:"gravatar_url" db:"gravatar_url"`
|
||||
Position string `json:"position,omitempty"` // job role
|
||||
// SSOEnabled if true, the user may only log in via SSO
|
||||
SSOEnabled bool `json:"sso_enabled" db:"sso_enabled"`
|
||||
GlobalRole null.String `json:"global_role" db:"global_role"`
|
||||
SSOEnabled bool `json:"sso_enabled" db:"sso_enabled"`
|
||||
GlobalRole *string `json:"global_role" db:"global_role"`
|
||||
|
||||
// Teams is the teams this user has roles in.
|
||||
Teams []UserTeam `json:"teams"`
|
||||
@@ -171,7 +170,7 @@ func (p UserPayload) User(keySize, cost int) (*User, error) {
|
||||
user.Teams = *p.Teams
|
||||
}
|
||||
if p.GlobalRole != nil {
|
||||
user.GlobalRole = null.StringFrom(*p.GlobalRole)
|
||||
user.GlobalRole = p.GlobalRole
|
||||
}
|
||||
|
||||
return user, nil
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
// Package ptr includes functions for creating pointers from values.
|
||||
package ptr
|
||||
|
||||
// String returns a pointer to the provided string.
|
||||
func String(x string) *string {
|
||||
return &x
|
||||
}
|
||||
|
||||
// Int returns a pointer to the provided int.
|
||||
func Int(x int) *int {
|
||||
return &x
|
||||
}
|
||||
|
||||
// Uint returns a pointer to the provided uint.
|
||||
func Uint(x uint) *uint {
|
||||
return &x
|
||||
}
|
||||
|
||||
// Bool returns a pointer to the provided bool.
|
||||
func Bool(x bool) *bool {
|
||||
return &x
|
||||
}
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
|
||||
func (svc service) AgentOptionsForHost(ctx context.Context, host *kolide.Host) (json.RawMessage, error) {
|
||||
// If host has a team and team has non-empty options, prioritize that.
|
||||
if host.TeamID.Valid {
|
||||
team, err := svc.ds.Team(uint(host.TeamID.Int64))
|
||||
if host.TeamID != nil {
|
||||
team, err := svc.ds.Team(*host.TeamID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "load team for host")
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/fleetdm/fleet/server/mock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/guregu/null.v3"
|
||||
)
|
||||
|
||||
func TestAgentOptionsForHost(t *testing.T) {
|
||||
@@ -28,7 +27,7 @@ func TestAgentOptionsForHost(t *testing.T) {
|
||||
}
|
||||
|
||||
host := &kolide.Host{
|
||||
TeamID: null.IntFrom(int64(teamID)),
|
||||
TeamID: &teamID,
|
||||
Platform: "darwin",
|
||||
}
|
||||
|
||||
@@ -42,7 +41,7 @@ func TestAgentOptionsForHost(t *testing.T) {
|
||||
assert.JSONEq(t, `{"foo":"bar"}`, string(opt))
|
||||
|
||||
// Should take gobal option with no team
|
||||
host.TeamID.Valid = false
|
||||
host.TeamID = nil
|
||||
opt, err = svc.AgentOptionsForHost(context.Background(), host)
|
||||
require.NoError(t, err)
|
||||
assert.JSONEq(t, `{"baz":"bar"}`, string(opt))
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/fleetdm/fleet/server/kolide"
|
||||
"github.com/fleetdm/fleet/server/mock"
|
||||
"github.com/fleetdm/fleet/server/ptr"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -45,12 +46,12 @@ func TestCreateAppConfig(t *testing.T) {
|
||||
{
|
||||
configPayload: kolide.AppConfigPayload{
|
||||
OrgInfo: &kolide.OrgInfo{
|
||||
OrgLogoURL: stringPtr("acme.co/images/logo.png"),
|
||||
OrgName: stringPtr("Acme"),
|
||||
OrgLogoURL: ptr.String("acme.co/images/logo.png"),
|
||||
OrgName: ptr.String("Acme"),
|
||||
},
|
||||
ServerSettings: &kolide.ServerSettings{
|
||||
KolideServerURL: stringPtr("https://acme.co:8080/"),
|
||||
LiveQueryDisabled: boolPtr(true),
|
||||
KolideServerURL: ptr.String("https://acme.co:8080/"),
|
||||
LiveQueryDisabled: ptr.Bool(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/fleetdm/fleet/server/contexts/viewer"
|
||||
"github.com/fleetdm/fleet/server/kolide"
|
||||
"github.com/fleetdm/fleet/server/mock"
|
||||
"github.com/fleetdm/fleet/server/ptr"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -34,7 +35,7 @@ func TestInviteNewUserMock(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx = viewer.NewContext(ctx, viewer.Viewer{User: &kolide.User{ID: 3}})
|
||||
payload := kolide.InvitePayload{
|
||||
Email: stringPtr("user@acme.co"),
|
||||
Email: ptr.String("user@acme.co"),
|
||||
}
|
||||
|
||||
// happy path
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"github.com/fleetdm/fleet/server/contexts/viewer"
|
||||
"github.com/fleetdm/fleet/server/kolide"
|
||||
"github.com/fleetdm/fleet/server/mock"
|
||||
"github.com/fleetdm/fleet/server/ptr"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/guregu/null.v3"
|
||||
)
|
||||
|
||||
func TestSearchTargets(t *testing.T) {
|
||||
@@ -17,7 +17,7 @@ func TestSearchTargets(t *testing.T) {
|
||||
svc, err := newTestService(ds, nil, nil)
|
||||
require.Nil(t, err)
|
||||
|
||||
user := &kolide.User{GlobalRole: null.StringFrom(kolide.RoleAdmin)}
|
||||
user := &kolide.User{GlobalRole: ptr.String(kolide.RoleAdmin)}
|
||||
ctx := viewer.NewContext(context.Background(), viewer.Viewer{User: user})
|
||||
|
||||
hosts := []*kolide.Host{
|
||||
@@ -50,7 +50,7 @@ func TestSearchWithOmit(t *testing.T) {
|
||||
svc, err := newTestService(ds, nil, nil)
|
||||
require.Nil(t, err)
|
||||
|
||||
user := &kolide.User{GlobalRole: null.StringFrom(kolide.RoleAdmin)}
|
||||
user := &kolide.User{GlobalRole: ptr.String(kolide.RoleAdmin)}
|
||||
ctx := viewer.NewContext(context.Background(), viewer.Viewer{User: user})
|
||||
|
||||
ds.SearchHostsFunc = func(filter kolide.TeamFilter, query string, omit ...uint) ([]*kolide.Host, error) {
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/fleetdm/fleet/server/kolide"
|
||||
"github.com/fleetdm/fleet/server/mail"
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/guregu/null.v3"
|
||||
)
|
||||
|
||||
func (svc service) CreateUserWithInvite(ctx context.Context, p kolide.UserPayload) (*kolide.User, error) {
|
||||
@@ -84,7 +83,7 @@ func (svc service) ModifyUser(ctx context.Context, userID uint, p kolide.UserPay
|
||||
user.Name = *p.Name
|
||||
}
|
||||
|
||||
if p.Email != nil {
|
||||
if p.Email != nil && *p.Email != user.Email {
|
||||
err = svc.modifyEmailAddress(ctx, user, *p.Email, p.Password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -103,18 +102,15 @@ func (svc service) ModifyUser(ctx context.Context, userID uint, p kolide.UserPay
|
||||
user.SSOEnabled = *p.SSOEnabled
|
||||
}
|
||||
|
||||
if p.Teams != nil {
|
||||
if p.GlobalRole != nil {
|
||||
if p.GlobalRole != nil && *p.GlobalRole != "" {
|
||||
if p.Teams != nil && len(*p.Teams) > 0 {
|
||||
return nil, newInvalidArgumentError("teams", "may not be specified with global_role")
|
||||
}
|
||||
|
||||
user.Teams = *p.Teams
|
||||
user.GlobalRole = null.StringFromPtr(nil)
|
||||
}
|
||||
|
||||
if p.GlobalRole != nil {
|
||||
user.GlobalRole = null.StringFrom(*p.GlobalRole)
|
||||
user.GlobalRole = p.GlobalRole
|
||||
user.Teams = []kolide.UserTeam{}
|
||||
} else if p.Teams != nil {
|
||||
user.Teams = *p.Teams
|
||||
user.GlobalRole = nil
|
||||
}
|
||||
|
||||
err = svc.saveUser(user)
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/fleetdm/fleet/server/contexts/viewer"
|
||||
"github.com/fleetdm/fleet/server/datastore/inmem"
|
||||
"github.com/fleetdm/fleet/server/kolide"
|
||||
"github.com/fleetdm/fleet/server/ptr"
|
||||
|
||||
"github.com/WatchBeam/clock"
|
||||
"github.com/fleetdm/fleet/server/mock"
|
||||
@@ -74,9 +75,9 @@ func TestModifyUserEmail(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx = viewer.NewContext(ctx, viewer.Viewer{User: user})
|
||||
payload := kolide.UserPayload{
|
||||
Email: stringPtr("zip@zap.com"),
|
||||
Password: stringPtr("password"),
|
||||
Position: stringPtr("minion"),
|
||||
Email: ptr.String("zip@zap.com"),
|
||||
Password: ptr.String("password"),
|
||||
Position: ptr.String("minion"),
|
||||
}
|
||||
_, err = svc.ModifyUser(ctx, 3, payload)
|
||||
require.Nil(t, err)
|
||||
@@ -116,9 +117,9 @@ func TestModifyUserEmailNoPassword(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx = viewer.NewContext(ctx, viewer.Viewer{User: user})
|
||||
payload := kolide.UserPayload{
|
||||
Email: stringPtr("zip@zap.com"),
|
||||
Email: ptr.String("zip@zap.com"),
|
||||
// NO PASSWORD
|
||||
// Password: stringPtr("password"),
|
||||
// Password: ptr.String("password"),
|
||||
}
|
||||
_, err = svc.ModifyUser(ctx, 3, payload)
|
||||
require.NotNil(t, err)
|
||||
@@ -162,9 +163,9 @@ func TestModifyAdminUserEmailNoPassword(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx = viewer.NewContext(ctx, viewer.Viewer{User: user})
|
||||
payload := kolide.UserPayload{
|
||||
Email: stringPtr("zip@zap.com"),
|
||||
Email: ptr.String("zip@zap.com"),
|
||||
// NO PASSWORD
|
||||
// Password: stringPtr("password"),
|
||||
// Password: ptr.String("password"),
|
||||
}
|
||||
_, err = svc.ModifyUser(ctx, 3, payload)
|
||||
require.NotNil(t, err)
|
||||
@@ -208,8 +209,8 @@ func TestModifyAdminUserEmailPassword(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx = viewer.NewContext(ctx, viewer.Viewer{User: user})
|
||||
payload := kolide.UserPayload{
|
||||
Email: stringPtr("zip@zap.com"),
|
||||
Password: stringPtr("password"),
|
||||
Email: ptr.String("zip@zap.com"),
|
||||
Password: ptr.String("password"),
|
||||
}
|
||||
_, err = svc.ModifyUser(ctx, 3, payload)
|
||||
require.Nil(t, err)
|
||||
@@ -308,46 +309,46 @@ func TestCreateUserWithInvite(t *testing.T) {
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
Username: stringPtr("admin2"),
|
||||
Password: stringPtr("foobarbaz1234!"),
|
||||
Username: ptr.String("admin2"),
|
||||
Password: ptr.String("foobarbaz1234!"),
|
||||
InviteToken: &invites["admin2@example.com"].Token,
|
||||
wantErr: &invalidArgumentError{invalidArgument{name: "email", reason: "missing required argument"}},
|
||||
},
|
||||
{
|
||||
Username: stringPtr("admin2"),
|
||||
Password: stringPtr("foobarbaz1234!"),
|
||||
Email: stringPtr("admin2@example.com"),
|
||||
Username: ptr.String("admin2"),
|
||||
Password: ptr.String("foobarbaz1234!"),
|
||||
Email: ptr.String("admin2@example.com"),
|
||||
wantErr: &invalidArgumentError{invalidArgument{name: "invite_token", reason: "missing required argument"}},
|
||||
},
|
||||
{
|
||||
Username: stringPtr("admin2"),
|
||||
Password: stringPtr("foobarbaz1234!"),
|
||||
Email: stringPtr("admin2@example.com"),
|
||||
NeedsPasswordReset: boolPtr(true),
|
||||
Username: ptr.String("admin2"),
|
||||
Password: ptr.String("foobarbaz1234!"),
|
||||
Email: ptr.String("admin2@example.com"),
|
||||
NeedsPasswordReset: ptr.Bool(true),
|
||||
InviteToken: &invites["admin2@example.com"].Token,
|
||||
},
|
||||
{ // should return ErrNotFound because the invite is deleted
|
||||
// after a user signs up
|
||||
Username: stringPtr("admin2"),
|
||||
Password: stringPtr("foobarbaz1234!"),
|
||||
Email: stringPtr("admin2@example.com"),
|
||||
NeedsPasswordReset: boolPtr(true),
|
||||
Username: ptr.String("admin2"),
|
||||
Password: ptr.String("foobarbaz1234!"),
|
||||
Email: ptr.String("admin2@example.com"),
|
||||
NeedsPasswordReset: ptr.Bool(true),
|
||||
InviteToken: &invites["admin2@example.com"].Token,
|
||||
wantErr: errors.New("Invite with token admin2@example.com was not found in the datastore"),
|
||||
},
|
||||
{
|
||||
Username: stringPtr("admin3"),
|
||||
Password: stringPtr("foobarbaz1234!"),
|
||||
Username: ptr.String("admin3"),
|
||||
Password: ptr.String("foobarbaz1234!"),
|
||||
Email: &invites["expired"].Email,
|
||||
NeedsPasswordReset: boolPtr(true),
|
||||
NeedsPasswordReset: ptr.Bool(true),
|
||||
InviteToken: &invites["expired"].Token,
|
||||
wantErr: &invalidArgumentError{{name: "invite_token", reason: "Invite token has expired."}},
|
||||
},
|
||||
{
|
||||
Username: stringPtr("admin3@example.com"),
|
||||
Password: stringPtr("foobarbaz1234!"),
|
||||
Email: stringPtr("admin3@example.com"),
|
||||
NeedsPasswordReset: boolPtr(true),
|
||||
Username: ptr.String("admin3@example.com"),
|
||||
Password: ptr.String("foobarbaz1234!"),
|
||||
Email: ptr.String("admin3@example.com"),
|
||||
NeedsPasswordReset: ptr.Bool(true),
|
||||
InviteToken: &invites["admin3@example.com"].Token,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"github.com/WatchBeam/clock"
|
||||
"github.com/fleetdm/fleet/server/config"
|
||||
"github.com/fleetdm/fleet/server/kolide"
|
||||
"github.com/fleetdm/fleet/server/ptr"
|
||||
kitlog "github.com/go-kit/kit/log"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/guregu/null.v3"
|
||||
)
|
||||
|
||||
func newTestService(ds kolide.Datastore, rs kolide.QueryResultStore, lq kolide.LiveQueryStore) (kolide.Service, error) {
|
||||
@@ -65,25 +65,25 @@ var testUsers = map[string]struct {
|
||||
Username string
|
||||
Email string
|
||||
PlaintextPassword string
|
||||
GlobalRole null.String
|
||||
GlobalRole *string
|
||||
}{
|
||||
"admin1": {
|
||||
Username: "admin1",
|
||||
PlaintextPassword: "foobarbaz1234!",
|
||||
Email: "admin1@example.com",
|
||||
GlobalRole: null.StringFrom("admin"),
|
||||
GlobalRole: ptr.String(kolide.RoleAdmin),
|
||||
},
|
||||
"user1": {
|
||||
Username: "user1",
|
||||
PlaintextPassword: "foobarbaz1234!",
|
||||
Email: "user1@example.com",
|
||||
GlobalRole: null.StringFrom("maintainer"),
|
||||
GlobalRole: ptr.String(kolide.RoleMaintainer),
|
||||
},
|
||||
"user2": {
|
||||
Username: "user2",
|
||||
PlaintextPassword: "bazfoo1234!",
|
||||
Email: "user2@example.com",
|
||||
GlobalRole: null.StringFrom("maintainer"),
|
||||
GlobalRole: ptr.String(kolide.RoleObserver),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -96,11 +96,3 @@ func (svc *mockMailService) SendEmail(e kolide.Email) error {
|
||||
svc.Invoked = true
|
||||
return svc.SendEmailFn(e)
|
||||
}
|
||||
|
||||
func stringPtr(s string) *string {
|
||||
return &s
|
||||
}
|
||||
|
||||
func boolPtr(b bool) *bool {
|
||||
return &b
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user