mirror of
https://github.com/grafana/grafana.git
synced 2025-08-02 12:22:11 +08:00

* Add isProvisioned field to model * Add new isProvisioned column to migration * Disable auto assignment to organization if the user is provisioned * add annotation to user model * add annotation to user models * Remove IsProvisioned field from Identity * Move new field assignenment and add default value * Update annotations for user query results * Remove isProvisioned from identity * Add new column to test * Resolve user from identity at SyncOrgHook
172 lines
4.6 KiB
Go
172 lines
4.6 KiB
Go
package dbimpl
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"net/http"
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/require"
|
|
"go.opentelemetry.io/otel/trace"
|
|
traceNoop "go.opentelemetry.io/otel/trace/noop"
|
|
ini "gopkg.in/ini.v1"
|
|
|
|
"github.com/grafana/grafana/pkg/bus"
|
|
infraDB "github.com/grafana/grafana/pkg/infra/db"
|
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
|
"github.com/grafana/grafana/pkg/services/sqlstore"
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
)
|
|
|
|
type (
|
|
// cfgSectionMap represents an INI section, mapping from an INI key to an
|
|
// INI value.
|
|
cfgSectionMap = map[string]string
|
|
// cfgMap is a map from INI section name to INI section contents.
|
|
cfgMap = map[string]cfgSectionMap
|
|
)
|
|
|
|
// setupDBForGrafana modifies `m` in the following way:
|
|
//
|
|
// [database]
|
|
// type = sqlite3
|
|
// path = unique-random-path
|
|
//
|
|
// After that, it initializes a temporary SQLite filesystem-backed database that
|
|
// is later deleted when the test finishes.
|
|
func setupDBForGrafana(t *testing.T, ctx context.Context, m cfgMap) {
|
|
dbSection, ok := m["database"]
|
|
if !ok {
|
|
dbSection = cfgSectionMap{}
|
|
m["database"] = dbSection
|
|
}
|
|
dbSection["type"] = "sqlite3"
|
|
dbSection["path"] = t.TempDir() + "/" + uuid.New().String()
|
|
|
|
db, err := sql.Open("sqlite3", "file:"+dbSection["path"])
|
|
require.NoError(t, err)
|
|
|
|
_, err = db.ExecContext(ctx, `
|
|
CREATE TABLE user (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
version INTEGER NOT NULL,
|
|
login TEXT NOT NULL,
|
|
email TEXT NOT NULL,
|
|
name TEXT NULL,
|
|
password TEXT NULL,
|
|
salt TEXT NULL,
|
|
rands TEXT NULL,
|
|
company TEXT NULL,
|
|
org_id INTEGER NOT NULL,
|
|
is_admin INTEGER NOT NULL,
|
|
email_verified INTEGER NULL,
|
|
theme TEXT NULL,
|
|
created DATETIME NOT NULL,
|
|
updated DATETIME NOT NULL,
|
|
help_flags1 INTEGER NOT NULL DEFAULT 0,
|
|
last_seen_at DATETIME NULL,
|
|
is_disabled INTEGER NOT NULL DEFAULT 0,
|
|
is_service_account BOOLEAN DEFAULT 0,
|
|
is_provisioned BOOLEAN DEFAULT 0,
|
|
uid TEXT NULL
|
|
);
|
|
CREATE TABLE org (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
version INTEGER NOT NULL,
|
|
name TEXT NOT NULL,
|
|
address1 TEXT NULL,
|
|
address2 TEXT NULL,
|
|
city TEXT NULL,
|
|
state TEXT NULL,
|
|
zip_code TEXT NULL,
|
|
country TEXT NULL,
|
|
billing_email TEXT NULL,
|
|
created DATETIME NOT NULL,
|
|
updated DATETIME NOT NULL
|
|
);
|
|
CREATE TABLE org_user (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
org_id INTEGER NOT NULL,
|
|
user_id INTEGER NOT NULL,
|
|
role TEXT NOT NULL,
|
|
created DATETIME NOT NULL,
|
|
updated DATETIME NOT NULL
|
|
);
|
|
`)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func newTestInfraDB(t *testing.T, m cfgMap) infraDB.DB {
|
|
t.Helper()
|
|
// nil migrations means no migrations
|
|
sqlstoreDB, err := sqlstore.ProvideService(
|
|
newCfgFromIniMap(t, m), // *setting.Cfg
|
|
featureTogglesNop{}, // featuremgmt.FeatureToggles
|
|
nil, // registry.DatabaseMigrator
|
|
nopBus{}, // github.com/grafana/grafana/pkg/bus.Bus
|
|
newNopTestGrafanaTracer(),
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
return sqlstoreDB
|
|
}
|
|
|
|
// globalUnprotectedMutableState controls access to global mutable state found
|
|
// in the `setting` package that is not appropriately protected. This would
|
|
// ideally be a part of some struct instead of being global, be protected if it
|
|
// needs to change, and be unmutable once it no longer needs to change. Example:
|
|
// `setting.AppUrl`. Nothing can run in parallel because of this.
|
|
// TODO: fix that.
|
|
var globalUnprotectedMutableState sync.Mutex
|
|
|
|
func newCfgFromIniMap(t *testing.T, m cfgMap) *setting.Cfg {
|
|
t.Helper()
|
|
globalUnprotectedMutableState.Lock()
|
|
defer globalUnprotectedMutableState.Unlock()
|
|
cfg, err := setting.NewCfgFromINIFile(newTestINIFile(t, m))
|
|
require.NoError(t, err)
|
|
return cfg
|
|
}
|
|
|
|
func newTestINIFile(t *testing.T, m cfgMap) *ini.File {
|
|
t.Helper()
|
|
f := ini.Empty()
|
|
for sectionName, kvs := range m {
|
|
section, err := f.NewSection(sectionName)
|
|
require.NoError(t, err)
|
|
for k, v := range kvs {
|
|
_, err := section.NewKey(k, v)
|
|
require.NoError(t, err)
|
|
}
|
|
}
|
|
return f
|
|
}
|
|
|
|
type (
|
|
testGrafanaTracer struct {
|
|
trace.Tracer
|
|
}
|
|
featureTogglesNop struct{}
|
|
nopBus struct{}
|
|
)
|
|
|
|
func (testGrafanaTracer) Inject(context.Context, http.Header, trace.Span) {}
|
|
func newNopTestGrafanaTracer() tracing.Tracer {
|
|
return testGrafanaTracer{traceNoop.NewTracerProvider().Tracer("test")}
|
|
}
|
|
|
|
func (featureTogglesNop) IsEnabled(context.Context, string) bool {
|
|
return false
|
|
}
|
|
func (featureTogglesNop) IsEnabledGlobally(string) bool {
|
|
return false
|
|
}
|
|
func (featureTogglesNop) GetEnabled(context.Context) map[string]bool {
|
|
return map[string]bool{}
|
|
}
|
|
|
|
func (nopBus) Publish(context.Context, bus.Msg) error { return nil }
|
|
func (nopBus) AddEventListener(bus.HandlerFunc) {}
|