2021-07-16 18:28:13 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2021-09-14 12:11:07 +00:00
|
|
|
"context"
|
2021-07-16 18:28:13 +00:00
|
|
|
"net/http/httptest"
|
|
|
|
"os"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/fleetdm/fleet/v4/server/fleet"
|
|
|
|
"github.com/fleetdm/fleet/v4/server/mock"
|
|
|
|
"github.com/fleetdm/fleet/v4/server/service"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/urfave/cli/v2"
|
|
|
|
)
|
|
|
|
|
Add read replica testing helpers and fix non-sso login bug (#4908)
not set on the INSERT.
- OUT: Only sets the ID on the passed session and returns it. (`CreatedAt`, `AccessedAt`, are not set.)
New version:
```go
func (ds *Datastore) NewSession(ctx context.Context, userID uint, sessionKey string) (*fleet.Session, error) {
sqlStatement := `
INSERT INTO sessions (
user_id,
` + "`key`" + `
)
VALUES(?,?)
`
result, err := ds.writer.ExecContext(ctx, sqlStatement, userID, sessionKey)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "inserting session")
}
id, _ := result.LastInsertId() // cannot fail with the mysql driver
return ds.sessionByID(ctx, ds.writer, uint(id))
}
```
- IN: Define arguments that are truly used when creating a session.
- OUT: Load and return the fleet.Session struct with all values set (using the `ds.writer` to support read replicas correctly).
PS: The new `NewSession` version mimics what we already do with other entities, like policies (`Datastore.NewGlobalPolicy`).
2022-04-04 23:52:05 +00:00
|
|
|
// runServerWithMockedDS runs the fleet server with several mocked DS methods.
|
|
|
|
//
|
|
|
|
// NOTE: Assumes the current session is always from the admin user (see ds.SessionByKeyFunc below).
|
2022-05-10 15:29:17 +00:00
|
|
|
func runServerWithMockedDS(t *testing.T, opts ...*service.TestServerOpts) (*httptest.Server, *mock.Store) {
|
2021-07-16 18:28:13 +00:00
|
|
|
ds := new(mock.Store)
|
|
|
|
var users []*fleet.User
|
2021-07-19 19:48:49 +00:00
|
|
|
var admin *fleet.User
|
2021-09-14 12:11:07 +00:00
|
|
|
ds.NewUserFunc = func(ctx context.Context, user *fleet.User) (*fleet.User, error) {
|
2021-07-19 19:48:49 +00:00
|
|
|
if user.GlobalRole != nil && *user.GlobalRole == fleet.RoleAdmin {
|
|
|
|
admin = user
|
|
|
|
}
|
2021-07-16 18:28:13 +00:00
|
|
|
users = append(users, user)
|
|
|
|
return user, nil
|
|
|
|
}
|
2021-09-14 12:11:07 +00:00
|
|
|
ds.SessionByKeyFunc = func(ctx context.Context, key string) (*fleet.Session, error) {
|
2021-07-16 18:28:13 +00:00
|
|
|
return &fleet.Session{
|
|
|
|
CreateTimestamp: fleet.CreateTimestamp{CreatedAt: time.Now()},
|
|
|
|
ID: 1,
|
|
|
|
AccessedAt: time.Now(),
|
Add read replica testing helpers and fix non-sso login bug (#4908)
not set on the INSERT.
- OUT: Only sets the ID on the passed session and returns it. (`CreatedAt`, `AccessedAt`, are not set.)
New version:
```go
func (ds *Datastore) NewSession(ctx context.Context, userID uint, sessionKey string) (*fleet.Session, error) {
sqlStatement := `
INSERT INTO sessions (
user_id,
` + "`key`" + `
)
VALUES(?,?)
`
result, err := ds.writer.ExecContext(ctx, sqlStatement, userID, sessionKey)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "inserting session")
}
id, _ := result.LastInsertId() // cannot fail with the mysql driver
return ds.sessionByID(ctx, ds.writer, uint(id))
}
```
- IN: Define arguments that are truly used when creating a session.
- OUT: Load and return the fleet.Session struct with all values set (using the `ds.writer` to support read replicas correctly).
PS: The new `NewSession` version mimics what we already do with other entities, like policies (`Datastore.NewGlobalPolicy`).
2022-04-04 23:52:05 +00:00
|
|
|
UserID: admin.ID,
|
2021-07-16 18:28:13 +00:00
|
|
|
Key: key,
|
|
|
|
}, nil
|
|
|
|
}
|
2021-09-14 12:11:07 +00:00
|
|
|
ds.MarkSessionAccessedFunc = func(ctx context.Context, session *fleet.Session) error {
|
2021-07-16 18:28:13 +00:00
|
|
|
return nil
|
|
|
|
}
|
2021-09-14 12:11:07 +00:00
|
|
|
ds.UserByIDFunc = func(ctx context.Context, id uint) (*fleet.User, error) {
|
2021-07-19 19:48:49 +00:00
|
|
|
return admin, nil
|
2021-07-16 18:28:13 +00:00
|
|
|
}
|
2021-09-14 12:11:07 +00:00
|
|
|
ds.ListUsersFunc = func(ctx context.Context, opt fleet.UserListOptions) ([]*fleet.User, error) {
|
2021-07-16 18:28:13 +00:00
|
|
|
return users, nil
|
|
|
|
}
|
2021-07-19 19:48:49 +00:00
|
|
|
_, server := service.RunServerForTestsWithDS(t, ds, opts...)
|
2021-07-16 18:28:13 +00:00
|
|
|
os.Setenv("FLEET_SERVER_ADDRESS", server.URL)
|
|
|
|
|
|
|
|
return server, ds
|
|
|
|
}
|
|
|
|
|
|
|
|
func runAppForTest(t *testing.T, args []string) string {
|
2022-02-14 16:43:34 +00:00
|
|
|
w, err := runAppNoChecks(args)
|
|
|
|
require.NoError(t, err)
|
2021-07-21 17:03:10 +00:00
|
|
|
return w.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
func runAppCheckErr(t *testing.T, args []string, errorMsg string) string {
|
2022-02-14 16:43:34 +00:00
|
|
|
w, err := runAppNoChecks(args)
|
2021-07-21 17:03:10 +00:00
|
|
|
require.Equal(t, errorMsg, err.Error())
|
|
|
|
return w.String()
|
|
|
|
}
|
|
|
|
|
2022-02-14 16:43:34 +00:00
|
|
|
func runAppNoChecks(args []string) (*bytes.Buffer, error) {
|
|
|
|
// first arg must be the binary name. Allow tests to omit it.
|
|
|
|
args = append([]string{""}, args...)
|
|
|
|
|
2021-07-16 18:28:13 +00:00
|
|
|
w := new(bytes.Buffer)
|
2022-02-14 16:43:34 +00:00
|
|
|
app := createApp(nil, w, noopExitErrHandler)
|
|
|
|
err := app.Run(args)
|
|
|
|
return w, err
|
2021-07-16 18:28:13 +00:00
|
|
|
}
|
2022-02-14 16:43:34 +00:00
|
|
|
|
|
|
|
func noopExitErrHandler(c *cli.Context, err error) {}
|