From 1eb49e1b0fa4603641523dcdae0283d8e2ece53e Mon Sep 17 00:00:00 2001 From: Karl Persson Date: Wed, 28 Aug 2024 14:15:26 +0200 Subject: [PATCH] Chore: restructure legacy store for identity (#92572) * Restructure user queries * restructure display query * restructure team queries * restructure team bindings query * Restructure team members * Restructure store --- pkg/registry/apis/identity/legacy/display.go | 53 +++++ .../{query_display.sql => display_query.sql} | 0 pkg/registry/apis/identity/legacy/queries.go | 136 ----------- pkg/registry/apis/identity/legacy/sql.go | 54 +++++ .../legacy/{queries_test.go => sql_test.go} | 20 +- .../legacy/{legacy_sql.go => team.go} | 212 +++++++++++------- ...m_bindings.sql => team_bindings_query.sql} | 3 +- ...eam_members.sql => team_members_query.sql} | 0 .../{query_teams.sql => teams_query.sql} | 0 ...l => mysql--display_query-display_ids.sql} | 0 ...mysql--display_query-display_ids_uids.sql} | 0 ... => mysql--display_query-display_uids.sql} | 0 ...--team_bindings_query-team_1_bindings.sql} | 3 +- ...m_bindings_query-team_bindings_page_1.sql} | 3 +- ...m_bindings_query-team_bindings_page_2.sql} | 3 +- ...m_members_query-team_1_members_page_1.sql} | 0 ...m_members_query-team_1_members_page_2.sql} | 0 ...ql => mysql--teams_query-teams_page_1.sql} | 0 ...ql => mysql--teams_query-teams_page_2.sql} | 0 ...d.sql => mysql--teams_query-teams_uid.sql} | 0 ...ql => mysql--users_query-users_page_1.sql} | 0 ...ql => mysql--users_query-users_page_2.sql} | 0 ...d.sql => mysql--users_query-users_uid.sql} | 0 ...> postgres--display_query-display_ids.sql} | 0 ...tgres--display_query-display_ids_uids.sql} | 0 ... postgres--display_query-display_uids.sql} | 0 ...--team_bindings_query-team_1_bindings.sql} | 3 +- ...m_bindings_query-team_bindings_page_1.sql} | 3 +- ...m_bindings_query-team_bindings_page_2.sql} | 3 +- ...m_members_query-team_1_members_page_1.sql} | 0 ...m_members_query-team_1_members_page_2.sql} | 0 ...=> postgres--teams_query-teams_page_1.sql} | 0 ...=> postgres--teams_query-teams_page_2.sql} | 0 ...ql => postgres--teams_query-teams_uid.sql} | 0 ...=> postgres--users_query-users_page_1.sql} | 0 ...=> postgres--users_query-users_page_2.sql} | 0 ...ql => postgres--users_query-users_uid.sql} | 0 ... => sqlite--display_query-display_ids.sql} | 0 ...qlite--display_query-display_ids_uids.sql} | 0 ...=> sqlite--display_query-display_uids.sql} | 0 ...--team_bindings_query-team_1_bindings.sql} | 3 +- ...m_bindings_query-team_bindings_page_1.sql} | 3 +- ...m_bindings_query-team_bindings_page_2.sql} | 3 +- ...m_members_query-team_1_members_page_1.sql} | 0 ...m_members_query-team_1_members_page_2.sql} | 0 ...l => sqlite--teams_query-teams_page_1.sql} | 0 ...l => sqlite--teams_query-teams_page_2.sql} | 0 ....sql => sqlite--teams_query-teams_uid.sql} | 0 ...l => sqlite--users_query-users_page_1.sql} | 0 ...l => sqlite--users_query-users_page_2.sql} | 0 ....sql => sqlite--users_query-users_uid.sql} | 0 pkg/registry/apis/identity/legacy/types.go | 106 --------- pkg/registry/apis/identity/legacy/user.go | 111 +++++++++ .../{query_users.sql => users_query.sql} | 0 .../apis/identity/user/display_store.go | 2 +- 55 files changed, 375 insertions(+), 349 deletions(-) create mode 100644 pkg/registry/apis/identity/legacy/display.go rename pkg/registry/apis/identity/legacy/{query_display.sql => display_query.sql} (100%) delete mode 100644 pkg/registry/apis/identity/legacy/queries.go create mode 100644 pkg/registry/apis/identity/legacy/sql.go rename pkg/registry/apis/identity/legacy/{queries_test.go => sql_test.go} (90%) rename pkg/registry/apis/identity/legacy/{legacy_sql.go => team.go} (58%) rename pkg/registry/apis/identity/legacy/{query_team_bindings.sql => team_bindings_query.sql} (87%) rename pkg/registry/apis/identity/legacy/{query_team_members.sql => team_members_query.sql} (100%) rename pkg/registry/apis/identity/legacy/{query_teams.sql => teams_query.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{mysql--query_display-display_ids.sql => mysql--display_query-display_ids.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{mysql--query_display-display_ids_uids.sql => mysql--display_query-display_ids_uids.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{mysql--query_display-display_uids.sql => mysql--display_query-display_uids.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{mysql--query_team_bindings-team_1_bindings.sql => mysql--team_bindings_query-team_1_bindings.sql} (75%) rename pkg/registry/apis/identity/legacy/testdata/{mysql--query_team_bindings-team_bindings_page_1.sql => mysql--team_bindings_query-team_bindings_page_1.sql} (80%) rename pkg/registry/apis/identity/legacy/testdata/{mysql--query_team_bindings-team_bindings_page_2.sql => mysql--team_bindings_query-team_bindings_page_2.sql} (81%) rename pkg/registry/apis/identity/legacy/testdata/{mysql--query_team_members-team_1_members_page_1.sql => mysql--team_members_query-team_1_members_page_1.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{mysql--query_team_members-team_1_members_page_2.sql => mysql--team_members_query-team_1_members_page_2.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{mysql--query_teams-teams_page_1.sql => mysql--teams_query-teams_page_1.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{mysql--query_teams-teams_page_2.sql => mysql--teams_query-teams_page_2.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{mysql--query_teams-teams_uid.sql => mysql--teams_query-teams_uid.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{mysql--query_users-users_page_1.sql => mysql--users_query-users_page_1.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{mysql--query_users-users_page_2.sql => mysql--users_query-users_page_2.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{mysql--query_users-users_uid.sql => mysql--users_query-users_uid.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{postgres--query_display-display_ids.sql => postgres--display_query-display_ids.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{postgres--query_display-display_ids_uids.sql => postgres--display_query-display_ids_uids.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{postgres--query_display-display_uids.sql => postgres--display_query-display_uids.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{sqlite--query_team_bindings-team_1_bindings.sql => postgres--team_bindings_query-team_1_bindings.sql} (75%) rename pkg/registry/apis/identity/legacy/testdata/{postgres--query_team_bindings-team_bindings_page_1.sql => postgres--team_bindings_query-team_bindings_page_1.sql} (80%) rename pkg/registry/apis/identity/legacy/testdata/{postgres--query_team_bindings-team_bindings_page_2.sql => postgres--team_bindings_query-team_bindings_page_2.sql} (81%) rename pkg/registry/apis/identity/legacy/testdata/{postgres--query_team_members-team_1_members_page_1.sql => postgres--team_members_query-team_1_members_page_1.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{postgres--query_team_members-team_1_members_page_2.sql => postgres--team_members_query-team_1_members_page_2.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{postgres--query_teams-teams_page_1.sql => postgres--teams_query-teams_page_1.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{postgres--query_teams-teams_page_2.sql => postgres--teams_query-teams_page_2.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{postgres--query_teams-teams_uid.sql => postgres--teams_query-teams_uid.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{postgres--query_users-users_page_1.sql => postgres--users_query-users_page_1.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{postgres--query_users-users_page_2.sql => postgres--users_query-users_page_2.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{postgres--query_users-users_uid.sql => postgres--users_query-users_uid.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{sqlite--query_display-display_ids.sql => sqlite--display_query-display_ids.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{sqlite--query_display-display_ids_uids.sql => sqlite--display_query-display_ids_uids.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{sqlite--query_display-display_uids.sql => sqlite--display_query-display_uids.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{postgres--query_team_bindings-team_1_bindings.sql => sqlite--team_bindings_query-team_1_bindings.sql} (75%) rename pkg/registry/apis/identity/legacy/testdata/{sqlite--query_team_bindings-team_bindings_page_1.sql => sqlite--team_bindings_query-team_bindings_page_1.sql} (80%) rename pkg/registry/apis/identity/legacy/testdata/{sqlite--query_team_bindings-team_bindings_page_2.sql => sqlite--team_bindings_query-team_bindings_page_2.sql} (81%) rename pkg/registry/apis/identity/legacy/testdata/{sqlite--query_team_members-team_1_members_page_1.sql => sqlite--team_members_query-team_1_members_page_1.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{sqlite--query_team_members-team_1_members_page_2.sql => sqlite--team_members_query-team_1_members_page_2.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{sqlite--query_teams-teams_page_1.sql => sqlite--teams_query-teams_page_1.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{sqlite--query_teams-teams_page_2.sql => sqlite--teams_query-teams_page_2.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{sqlite--query_teams-teams_uid.sql => sqlite--teams_query-teams_uid.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{sqlite--query_users-users_page_1.sql => sqlite--users_query-users_page_1.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{sqlite--query_users-users_page_2.sql => sqlite--users_query-users_page_2.sql} (100%) rename pkg/registry/apis/identity/legacy/testdata/{sqlite--query_users-users_uid.sql => sqlite--users_query-users_uid.sql} (100%) delete mode 100644 pkg/registry/apis/identity/legacy/types.go create mode 100644 pkg/registry/apis/identity/legacy/user.go rename pkg/registry/apis/identity/legacy/{query_users.sql => users_query.sql} (100%) diff --git a/pkg/registry/apis/identity/legacy/display.go b/pkg/registry/apis/identity/legacy/display.go new file mode 100644 index 00000000000..87e4b6e2e94 --- /dev/null +++ b/pkg/registry/apis/identity/legacy/display.go @@ -0,0 +1,53 @@ +package legacy + +import ( + "context" + "fmt" + + "github.com/grafana/authlib/claims" + "github.com/grafana/grafana/pkg/storage/legacysql" + "github.com/grafana/grafana/pkg/storage/unified/sql/sqltemplate" +) + +type ListDisplayQuery struct { + OrgID int64 + UIDs []string + IDs []int64 +} + +var sqlQueryDisplayTemplate = mustTemplate("display_query.sql") + +func newListDisplay(sql *legacysql.LegacyDatabaseHelper, q *ListDisplayQuery) listDisplayQuery { + return listDisplayQuery{ + SQLTemplate: sqltemplate.New(sql.DialectForDriver()), + UserTable: sql.Table("user"), + OrgUserTable: sql.Table("org_user"), + Query: q, + } +} + +type listDisplayQuery struct { + sqltemplate.SQLTemplate + Query *ListDisplayQuery + UserTable string + OrgUserTable string +} + +func (r listDisplayQuery) Validate() error { + return nil // TODO +} + +// GetDisplay implements LegacyIdentityStore. +func (s *legacySQLStore) ListDisplay(ctx context.Context, ns claims.NamespaceInfo, query ListDisplayQuery) (*ListUserResult, error) { + query.OrgID = ns.OrgID + if ns.OrgID == 0 { + return nil, fmt.Errorf("expected non zero org id") + } + + sql, err := s.sql(ctx) + if err != nil { + return nil, err + } + + return s.queryUsers(ctx, sql, sqlQueryDisplayTemplate, newListDisplay(sql, &query), 10000) +} diff --git a/pkg/registry/apis/identity/legacy/query_display.sql b/pkg/registry/apis/identity/legacy/display_query.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/query_display.sql rename to pkg/registry/apis/identity/legacy/display_query.sql diff --git a/pkg/registry/apis/identity/legacy/queries.go b/pkg/registry/apis/identity/legacy/queries.go deleted file mode 100644 index 5ee649b2196..00000000000 --- a/pkg/registry/apis/identity/legacy/queries.go +++ /dev/null @@ -1,136 +0,0 @@ -package legacy - -import ( - "embed" - "fmt" - "text/template" - - "github.com/grafana/grafana/pkg/storage/legacysql" - "github.com/grafana/grafana/pkg/storage/unified/sql/sqltemplate" -) - -// Templates setup. -var ( - //go:embed *.sql - sqlTemplatesFS embed.FS - - sqlTemplates = template.Must(template.New("sql").ParseFS(sqlTemplatesFS, `*.sql`)) -) - -func mustTemplate(filename string) *template.Template { - if t := sqlTemplates.Lookup(filename); t != nil { - return t - } - panic(fmt.Sprintf("template file not found: %s", filename)) -} - -// Templates. -var ( - sqlQueryTeams = mustTemplate("query_teams.sql") - sqlQueryUsers = mustTemplate("query_users.sql") - sqlQueryDisplay = mustTemplate("query_display.sql") - sqlQueryTeamBindings = mustTemplate("query_team_bindings.sql") - sqlQueryTeamMembers = mustTemplate("query_team_members.sql") -) - -type sqlQueryListUsers struct { - sqltemplate.SQLTemplate - Query *ListUserQuery - UserTable string - OrgUserTable string -} - -func newListUser(sql *legacysql.LegacyDatabaseHelper, q *ListUserQuery) sqlQueryListUsers { - return sqlQueryListUsers{ - SQLTemplate: sqltemplate.New(sql.DialectForDriver()), - UserTable: sql.Table("user"), - OrgUserTable: sql.Table("org_user"), - Query: q, - } -} - -func (r sqlQueryListUsers) Validate() error { - return nil // TODO -} - -type sqlQueryListTeams struct { - sqltemplate.SQLTemplate - Query *ListTeamQuery - TeamTable string -} - -func newListTeams(sql *legacysql.LegacyDatabaseHelper, q *ListTeamQuery) sqlQueryListTeams { - return sqlQueryListTeams{ - SQLTemplate: sqltemplate.New(sql.DialectForDriver()), - TeamTable: sql.Table("team"), - Query: q, - } -} - -func (r sqlQueryListTeams) Validate() error { - return nil // TODO -} - -type sqlQueryGetDisplay struct { - sqltemplate.SQLTemplate - Query *GetUserDisplayQuery - UserTable string - OrgUserTable string -} - -func newGetDisplay(sql *legacysql.LegacyDatabaseHelper, q *GetUserDisplayQuery) sqlQueryGetDisplay { - return sqlQueryGetDisplay{ - SQLTemplate: sqltemplate.New(sql.DialectForDriver()), - UserTable: sql.Table("user"), - OrgUserTable: sql.Table("org_user"), - Query: q, - } -} - -func (r sqlQueryGetDisplay) Validate() error { - return nil // TODO -} - -type sqlQueryListTeamBindings struct { - sqltemplate.SQLTemplate - Query *ListTeamBindingsQuery - UserTable string - TeamTable string - TeamMemberTable string -} - -func (r sqlQueryListTeamBindings) Validate() error { - return nil // TODO -} - -func newListTeamBindings(sql *legacysql.LegacyDatabaseHelper, q *ListTeamBindingsQuery) sqlQueryListTeamBindings { - return sqlQueryListTeamBindings{ - SQLTemplate: sqltemplate.New(sql.DialectForDriver()), - UserTable: sql.Table("user"), - TeamTable: sql.Table("team"), - TeamMemberTable: sql.Table("team_member"), - Query: q, - } -} - -type sqlQueryListTeamMembers struct { - sqltemplate.SQLTemplate - Query *ListTeamMembersQuery - UserTable string - TeamTable string - TeamMemberTable string -} - -func (r sqlQueryListTeamMembers) Validate() error { - return nil // TODO -} - -func newListTeamMembers(sql *legacysql.LegacyDatabaseHelper, q *ListTeamMembersQuery) sqlQueryListTeamMembers { - return sqlQueryListTeamMembers{ - SQLTemplate: sqltemplate.New(sql.DialectForDriver()), - UserTable: sql.Table("user"), - TeamTable: sql.Table("team"), - TeamMemberTable: sql.Table("team_member"), - Query: q, - } -} diff --git a/pkg/registry/apis/identity/legacy/sql.go b/pkg/registry/apis/identity/legacy/sql.go new file mode 100644 index 00000000000..10964349fbd --- /dev/null +++ b/pkg/registry/apis/identity/legacy/sql.go @@ -0,0 +1,54 @@ +package legacy + +import ( + "context" + "embed" + "fmt" + "text/template" + + "github.com/grafana/authlib/claims" + "github.com/grafana/grafana/pkg/services/team" + "github.com/grafana/grafana/pkg/storage/legacysql" +) + +// In every case, RBAC should be applied before calling, or before returning results to the requester +type LegacyIdentityStore interface { + ListDisplay(ctx context.Context, ns claims.NamespaceInfo, query ListDisplayQuery) (*ListUserResult, error) + + ListUsers(ctx context.Context, ns claims.NamespaceInfo, query ListUserQuery) (*ListUserResult, error) + + ListTeams(ctx context.Context, ns claims.NamespaceInfo, query ListTeamQuery) (*ListTeamResult, error) + ListTeamBindings(ctx context.Context, ns claims.NamespaceInfo, query ListTeamBindingsQuery) (*ListTeamBindingsResult, error) + ListTeamMembers(ctx context.Context, ns claims.NamespaceInfo, query ListTeamMembersQuery) (*ListTeamMembersResult, error) + + GetUserTeams(ctx context.Context, ns claims.NamespaceInfo, uid string) ([]team.Team, error) +} + +var ( + _ LegacyIdentityStore = (*legacySQLStore)(nil) +) + +func NewLegacySQLStores(sql legacysql.LegacyDatabaseProvider) LegacyIdentityStore { + return &legacySQLStore{ + sql: sql, + } +} + +type legacySQLStore struct { + sql legacysql.LegacyDatabaseProvider +} + +// Templates setup. +var ( + //go:embed *.sql + sqlTemplatesFS embed.FS + + sqlTemplates = template.Must(template.New("sql").ParseFS(sqlTemplatesFS, `*.sql`)) +) + +func mustTemplate(filename string) *template.Template { + if t := sqlTemplates.Lookup(filename); t != nil { + return t + } + panic(fmt.Sprintf("template file not found: %s", filename)) +} diff --git a/pkg/registry/apis/identity/legacy/queries_test.go b/pkg/registry/apis/identity/legacy/sql_test.go similarity index 90% rename from pkg/registry/apis/identity/legacy/queries_test.go rename to pkg/registry/apis/identity/legacy/sql_test.go index 8027ff7af80..75b56710ff4 100644 --- a/pkg/registry/apis/identity/legacy/queries_test.go +++ b/pkg/registry/apis/identity/legacy/sql_test.go @@ -18,8 +18,8 @@ func TestIdentityQueries(t *testing.T) { }, } - getDisplay := func(q *GetUserDisplayQuery) sqltemplate.SQLTemplate { - v := newGetDisplay(nodb, q) + getDisplay := func(q *ListDisplayQuery) sqltemplate.SQLTemplate { + v := newListDisplay(nodb, q) v.SQLTemplate = mocks.NewTestingSQLTemplate() return &v } @@ -51,7 +51,7 @@ func TestIdentityQueries(t *testing.T) { mocks.CheckQuerySnapshots(t, mocks.TemplateTestSetup{ RootDir: "testdata", Templates: map[*template.Template][]mocks.TemplateTestCase{ - sqlQueryTeams: { + sqlQueryTeamsTemplate: { { Name: "teams_uid", Data: listTeams(&ListTeamQuery{ @@ -75,7 +75,7 @@ func TestIdentityQueries(t *testing.T) { }), }, }, - sqlQueryUsers: { + sqlQueryUsersTemplate: { { Name: "users_uid", Data: listUsers(&ListUserQuery{ @@ -99,31 +99,31 @@ func TestIdentityQueries(t *testing.T) { }), }, }, - sqlQueryDisplay: { + sqlQueryDisplayTemplate: { { Name: "display_uids", - Data: getDisplay(&GetUserDisplayQuery{ + Data: getDisplay(&ListDisplayQuery{ OrgID: 2, UIDs: []string{"a", "b"}, }), }, { Name: "display_ids", - Data: getDisplay(&GetUserDisplayQuery{ + Data: getDisplay(&ListDisplayQuery{ OrgID: 2, IDs: []int64{1, 2}, }), }, { Name: "display_ids_uids", - Data: getDisplay(&GetUserDisplayQuery{ + Data: getDisplay(&ListDisplayQuery{ OrgID: 2, UIDs: []string{"a", "b"}, IDs: []int64{1, 2}, }), }, }, - sqlQueryTeamBindings: { + sqlQueryTeamBindingsTemplate: { { Name: "team_1_bindings", Data: listTeamBindings(&ListTeamBindingsQuery{ @@ -150,7 +150,7 @@ func TestIdentityQueries(t *testing.T) { }), }, }, - sqlQueryTeamMembers: { + sqlQueryTeamMembersTemplate: { { Name: "team_1_members_page_1", Data: listTeamMembers(&ListTeamMembersQuery{ diff --git a/pkg/registry/apis/identity/legacy/legacy_sql.go b/pkg/registry/apis/identity/legacy/team.go similarity index 58% rename from pkg/registry/apis/identity/legacy/legacy_sql.go rename to pkg/registry/apis/identity/legacy/team.go index a1deea114f9..97cb14e23d8 100644 --- a/pkg/registry/apis/identity/legacy/legacy_sql.go +++ b/pkg/registry/apis/identity/legacy/team.go @@ -4,27 +4,47 @@ import ( "context" "database/sql" "fmt" - "text/template" + "time" "github.com/grafana/authlib/claims" + "github.com/grafana/grafana/pkg/apimachinery/identity" + "github.com/grafana/grafana/pkg/registry/apis/identity/common" "github.com/grafana/grafana/pkg/services/team" - "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/storage/legacysql" "github.com/grafana/grafana/pkg/storage/unified/sql/sqltemplate" ) -var ( - _ LegacyIdentityStore = (*legacySQLStore)(nil) -) +type ListTeamQuery struct { + OrgID int64 + UID string -func NewLegacySQLStores(sql legacysql.LegacyDatabaseProvider) LegacyIdentityStore { - return &legacySQLStore{ - sql: sql, + Pagination common.Pagination +} + +type ListTeamResult struct { + Teams []team.Team + Continue int64 + RV int64 +} + +var sqlQueryTeamsTemplate = mustTemplate("teams_query.sql") + +type listTeamsQuery struct { + sqltemplate.SQLTemplate + Query *ListTeamQuery + TeamTable string +} + +func newListTeams(sql *legacysql.LegacyDatabaseHelper, q *ListTeamQuery) listTeamsQuery { + return listTeamsQuery{ + SQLTemplate: sqltemplate.New(sql.DialectForDriver()), + TeamTable: sql.Table("team"), + Query: q, } } -type legacySQLStore struct { - sql legacysql.LegacyDatabaseProvider +func (r listTeamsQuery) Validate() error { + return nil // TODO } // ListTeams implements LegacyIdentityStore. @@ -42,9 +62,9 @@ func (s *legacySQLStore) ListTeams(ctx context.Context, ns claims.NamespaceInfo, } req := newListTeams(sql, &query) - q, err := sqltemplate.Execute(sqlQueryTeams, req) + q, err := sqltemplate.Execute(sqlQueryTeamsTemplate, req) if err != nil { - return nil, fmt.Errorf("execute template %q: %w", sqlQueryTeams.Name(), err) + return nil, fmt.Errorf("execute template %q: %w", sqlQueryTeamsTemplate.Name(), err) } rows, err := sql.DB.GetSqlxSession().Query(ctx, q, req.GetArgs()...) @@ -83,81 +103,65 @@ func (s *legacySQLStore) ListTeams(ctx context.Context, ns claims.NamespaceInfo, return res, err } -// ListUsers implements LegacyIdentityStore. -func (s *legacySQLStore) ListUsers(ctx context.Context, ns claims.NamespaceInfo, query ListUserQuery) (*ListUserResult, error) { - // for continue - limit := int(query.Pagination.Limit) - query.Pagination.Limit += 1 - - query.OrgID = ns.OrgID - if ns.OrgID == 0 { - return nil, fmt.Errorf("expected non zero orgID") - } - - sql, err := s.sql(ctx) - if err != nil { - return nil, err - } - - res, err := s.queryUsers(ctx, sql, sqlQueryUsers, newListUser(sql, &query), limit) - if err == nil && query.UID != "" { - res.RV, err = sql.GetResourceVersion(ctx, "user", "updated") - } - - return res, err +type ListTeamBindingsQuery struct { + // UID is team uid to list bindings for. If not set store should list bindings for all teams + UID string + OrgID int64 + Pagination common.Pagination } -// GetDisplay implements LegacyIdentityStore. -func (s *legacySQLStore) GetDisplay(ctx context.Context, ns claims.NamespaceInfo, query GetUserDisplayQuery) (*ListUserResult, error) { - query.OrgID = ns.OrgID - if ns.OrgID == 0 { - return nil, fmt.Errorf("expected non zero orgID") - } - - sql, err := s.sql(ctx) - if err != nil { - return nil, err - } - - return s.queryUsers(ctx, sql, sqlQueryDisplay, newGetDisplay(sql, &query), 10000) +type ListTeamBindingsResult struct { + Bindings []TeamBinding + Continue int64 + RV int64 } -func (s *legacySQLStore) queryUsers(ctx context.Context, sql *legacysql.LegacyDatabaseHelper, t *template.Template, req sqltemplate.Args, limit int) (*ListUserResult, error) { - q, err := sqltemplate.Execute(t, req) - if err != nil { - return nil, fmt.Errorf("execute template %q: %w", sqlQueryUsers.Name(), err) +type TeamMember struct { + ID int64 + TeamID int64 + TeamUID string + UserID int64 + UserUID string + Name string + Email string + Username string + External bool + Updated time.Time + Created time.Time + Permission team.PermissionType +} + +func (m TeamMember) MemberID() string { + return identity.NewTypedIDString(claims.TypeUser, m.UserUID) +} + +type TeamBinding struct { + TeamUID string + Members []TeamMember +} + +var sqlQueryTeamBindingsTemplate = mustTemplate("team_bindings_query.sql") + +type listTeamBindingsQuery struct { + sqltemplate.SQLTemplate + Query *ListTeamBindingsQuery + UserTable string + TeamTable string + TeamMemberTable string +} + +func (r listTeamBindingsQuery) Validate() error { + return nil // TODO +} + +func newListTeamBindings(sql *legacysql.LegacyDatabaseHelper, q *ListTeamBindingsQuery) listTeamBindingsQuery { + return listTeamBindingsQuery{ + SQLTemplate: sqltemplate.New(sql.DialectForDriver()), + UserTable: sql.Table("user"), + TeamTable: sql.Table("team"), + TeamMemberTable: sql.Table("team_member"), + Query: q, } - - res := &ListUserResult{} - rows, err := sql.DB.GetSqlxSession().Query(ctx, q, req.GetArgs()...) - defer func() { - if rows != nil { - _ = rows.Close() - } - }() - - if err == nil { - var lastID int64 - for rows.Next() { - u := user.User{} - err = rows.Scan(&u.OrgID, &u.ID, &u.UID, &u.Login, &u.Email, &u.Name, - &u.Created, &u.Updated, &u.IsServiceAccount, &u.IsDisabled, &u.IsAdmin, - ) - if err != nil { - return res, err - } - - lastID = u.ID - res.Users = append(res.Users, u) - if len(res.Users) > limit { - res.Users = res.Users[0 : len(res.Users)-1] - res.Continue = lastID - break - } - } - } - - return res, err } // ListTeamsBindings implements LegacyIdentityStore. @@ -175,9 +179,9 @@ func (s *legacySQLStore) ListTeamBindings(ctx context.Context, ns claims.Namespa } req := newListTeamBindings(sql, &query) - q, err := sqltemplate.Execute(sqlQueryTeamBindings, req) + q, err := sqltemplate.Execute(sqlQueryTeamBindingsTemplate, req) if err != nil { - return nil, fmt.Errorf("execute template %q: %w", sqlQueryTeams.Name(), err) + return nil, fmt.Errorf("execute template %q: %w", sqlQueryTeamsTemplate.Name(), err) } rows, err := sql.DB.GetSqlxSession().Query(ctx, q, req.GetArgs()...) @@ -233,6 +237,42 @@ func (s *legacySQLStore) ListTeamBindings(ctx context.Context, ns claims.Namespa return res, err } +type ListTeamMembersQuery struct { + UID string + OrgID int64 + Pagination common.Pagination +} + +type ListTeamMembersResult struct { + Continue int64 + Members []TeamMember +} + +// Templates. +var sqlQueryTeamMembersTemplate = mustTemplate("team_members_query.sql") + +type listTeamMembersQuery struct { + sqltemplate.SQLTemplate + Query *ListTeamMembersQuery + UserTable string + TeamTable string + TeamMemberTable string +} + +func (r listTeamMembersQuery) Validate() error { + return nil // TODO +} + +func newListTeamMembers(sql *legacysql.LegacyDatabaseHelper, q *ListTeamMembersQuery) listTeamMembersQuery { + return listTeamMembersQuery{ + SQLTemplate: sqltemplate.New(sql.DialectForDriver()), + UserTable: sql.Table("user"), + TeamTable: sql.Table("team"), + TeamMemberTable: sql.Table("team_member"), + Query: q, + } +} + // ListTeamMembers implements LegacyIdentityStore. func (s *legacySQLStore) ListTeamMembers(ctx context.Context, ns claims.NamespaceInfo, query ListTeamMembersQuery) (*ListTeamMembersResult, error) { query.Pagination.Limit += 1 @@ -247,9 +287,9 @@ func (s *legacySQLStore) ListTeamMembers(ctx context.Context, ns claims.Namespac } req := newListTeamMembers(sql, &query) - q, err := sqltemplate.Execute(sqlQueryTeamMembers, req) + q, err := sqltemplate.Execute(sqlQueryTeamMembersTemplate, req) if err != nil { - return nil, fmt.Errorf("execute template %q: %w", sqlQueryTeams.Name(), err) + return nil, fmt.Errorf("execute template %q: %w", sqlQueryTeamsTemplate.Name(), err) } rows, err := sql.DB.GetSqlxSession().Query(ctx, q, req.GetArgs()...) diff --git a/pkg/registry/apis/identity/legacy/query_team_bindings.sql b/pkg/registry/apis/identity/legacy/team_bindings_query.sql similarity index 87% rename from pkg/registry/apis/identity/legacy/query_team_bindings.sql rename to pkg/registry/apis/identity/legacy/team_bindings_query.sql index 2a53b975ac7..fb8930c9fde 100644 --- a/pkg/registry/apis/identity/legacy/query_team_bindings.sql +++ b/pkg/registry/apis/identity/legacy/team_bindings_query.sql @@ -1,4 +1,5 @@ -SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission FROM {{ .Ident .TeamMemberTable }} tm +SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission +FROM {{ .Ident .TeamMemberTable }} tm INNER JOIN {{ .Ident .TeamTable }} t ON tm.team_id = t.id INNER JOIN {{ .Ident .UserTable }} u ON tm.user_id = u.id WHERE diff --git a/pkg/registry/apis/identity/legacy/query_team_members.sql b/pkg/registry/apis/identity/legacy/team_members_query.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/query_team_members.sql rename to pkg/registry/apis/identity/legacy/team_members_query.sql diff --git a/pkg/registry/apis/identity/legacy/query_teams.sql b/pkg/registry/apis/identity/legacy/teams_query.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/query_teams.sql rename to pkg/registry/apis/identity/legacy/teams_query.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/mysql--query_display-display_ids.sql b/pkg/registry/apis/identity/legacy/testdata/mysql--display_query-display_ids.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/mysql--query_display-display_ids.sql rename to pkg/registry/apis/identity/legacy/testdata/mysql--display_query-display_ids.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/mysql--query_display-display_ids_uids.sql b/pkg/registry/apis/identity/legacy/testdata/mysql--display_query-display_ids_uids.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/mysql--query_display-display_ids_uids.sql rename to pkg/registry/apis/identity/legacy/testdata/mysql--display_query-display_ids_uids.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/mysql--query_display-display_uids.sql b/pkg/registry/apis/identity/legacy/testdata/mysql--display_query-display_uids.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/mysql--query_display-display_uids.sql rename to pkg/registry/apis/identity/legacy/testdata/mysql--display_query-display_uids.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/mysql--query_team_bindings-team_1_bindings.sql b/pkg/registry/apis/identity/legacy/testdata/mysql--team_bindings_query-team_1_bindings.sql similarity index 75% rename from pkg/registry/apis/identity/legacy/testdata/mysql--query_team_bindings-team_1_bindings.sql rename to pkg/registry/apis/identity/legacy/testdata/mysql--team_bindings_query-team_1_bindings.sql index f33d0ee83cf..4dc43b4f936 100755 --- a/pkg/registry/apis/identity/legacy/testdata/mysql--query_team_bindings-team_1_bindings.sql +++ b/pkg/registry/apis/identity/legacy/testdata/mysql--team_bindings_query-team_1_bindings.sql @@ -1,4 +1,5 @@ -SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission FROM `grafana`.`team_member` tm +SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission +FROM `grafana`.`team_member` tm INNER JOIN `grafana`.`team` t ON tm.team_id = t.id INNER JOIN `grafana`.`user` u ON tm.user_id = u.id WHERE diff --git a/pkg/registry/apis/identity/legacy/testdata/mysql--query_team_bindings-team_bindings_page_1.sql b/pkg/registry/apis/identity/legacy/testdata/mysql--team_bindings_query-team_bindings_page_1.sql similarity index 80% rename from pkg/registry/apis/identity/legacy/testdata/mysql--query_team_bindings-team_bindings_page_1.sql rename to pkg/registry/apis/identity/legacy/testdata/mysql--team_bindings_query-team_bindings_page_1.sql index adf675a6dd6..be3d212eb9e 100755 --- a/pkg/registry/apis/identity/legacy/testdata/mysql--query_team_bindings-team_bindings_page_1.sql +++ b/pkg/registry/apis/identity/legacy/testdata/mysql--team_bindings_query-team_bindings_page_1.sql @@ -1,4 +1,5 @@ -SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission FROM `grafana`.`team_member` tm +SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission +FROM `grafana`.`team_member` tm INNER JOIN `grafana`.`team` t ON tm.team_id = t.id INNER JOIN `grafana`.`user` u ON tm.user_id = u.id WHERE diff --git a/pkg/registry/apis/identity/legacy/testdata/mysql--query_team_bindings-team_bindings_page_2.sql b/pkg/registry/apis/identity/legacy/testdata/mysql--team_bindings_query-team_bindings_page_2.sql similarity index 81% rename from pkg/registry/apis/identity/legacy/testdata/mysql--query_team_bindings-team_bindings_page_2.sql rename to pkg/registry/apis/identity/legacy/testdata/mysql--team_bindings_query-team_bindings_page_2.sql index 403c86ed591..ecbef2e0c01 100755 --- a/pkg/registry/apis/identity/legacy/testdata/mysql--query_team_bindings-team_bindings_page_2.sql +++ b/pkg/registry/apis/identity/legacy/testdata/mysql--team_bindings_query-team_bindings_page_2.sql @@ -1,4 +1,5 @@ -SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission FROM `grafana`.`team_member` tm +SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission +FROM `grafana`.`team_member` tm INNER JOIN `grafana`.`team` t ON tm.team_id = t.id INNER JOIN `grafana`.`user` u ON tm.user_id = u.id WHERE diff --git a/pkg/registry/apis/identity/legacy/testdata/mysql--query_team_members-team_1_members_page_1.sql b/pkg/registry/apis/identity/legacy/testdata/mysql--team_members_query-team_1_members_page_1.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/mysql--query_team_members-team_1_members_page_1.sql rename to pkg/registry/apis/identity/legacy/testdata/mysql--team_members_query-team_1_members_page_1.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/mysql--query_team_members-team_1_members_page_2.sql b/pkg/registry/apis/identity/legacy/testdata/mysql--team_members_query-team_1_members_page_2.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/mysql--query_team_members-team_1_members_page_2.sql rename to pkg/registry/apis/identity/legacy/testdata/mysql--team_members_query-team_1_members_page_2.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/mysql--query_teams-teams_page_1.sql b/pkg/registry/apis/identity/legacy/testdata/mysql--teams_query-teams_page_1.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/mysql--query_teams-teams_page_1.sql rename to pkg/registry/apis/identity/legacy/testdata/mysql--teams_query-teams_page_1.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/mysql--query_teams-teams_page_2.sql b/pkg/registry/apis/identity/legacy/testdata/mysql--teams_query-teams_page_2.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/mysql--query_teams-teams_page_2.sql rename to pkg/registry/apis/identity/legacy/testdata/mysql--teams_query-teams_page_2.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/mysql--query_teams-teams_uid.sql b/pkg/registry/apis/identity/legacy/testdata/mysql--teams_query-teams_uid.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/mysql--query_teams-teams_uid.sql rename to pkg/registry/apis/identity/legacy/testdata/mysql--teams_query-teams_uid.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/mysql--query_users-users_page_1.sql b/pkg/registry/apis/identity/legacy/testdata/mysql--users_query-users_page_1.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/mysql--query_users-users_page_1.sql rename to pkg/registry/apis/identity/legacy/testdata/mysql--users_query-users_page_1.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/mysql--query_users-users_page_2.sql b/pkg/registry/apis/identity/legacy/testdata/mysql--users_query-users_page_2.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/mysql--query_users-users_page_2.sql rename to pkg/registry/apis/identity/legacy/testdata/mysql--users_query-users_page_2.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/mysql--query_users-users_uid.sql b/pkg/registry/apis/identity/legacy/testdata/mysql--users_query-users_uid.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/mysql--query_users-users_uid.sql rename to pkg/registry/apis/identity/legacy/testdata/mysql--users_query-users_uid.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/postgres--query_display-display_ids.sql b/pkg/registry/apis/identity/legacy/testdata/postgres--display_query-display_ids.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/postgres--query_display-display_ids.sql rename to pkg/registry/apis/identity/legacy/testdata/postgres--display_query-display_ids.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/postgres--query_display-display_ids_uids.sql b/pkg/registry/apis/identity/legacy/testdata/postgres--display_query-display_ids_uids.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/postgres--query_display-display_ids_uids.sql rename to pkg/registry/apis/identity/legacy/testdata/postgres--display_query-display_ids_uids.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/postgres--query_display-display_uids.sql b/pkg/registry/apis/identity/legacy/testdata/postgres--display_query-display_uids.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/postgres--query_display-display_uids.sql rename to pkg/registry/apis/identity/legacy/testdata/postgres--display_query-display_uids.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/sqlite--query_team_bindings-team_1_bindings.sql b/pkg/registry/apis/identity/legacy/testdata/postgres--team_bindings_query-team_1_bindings.sql similarity index 75% rename from pkg/registry/apis/identity/legacy/testdata/sqlite--query_team_bindings-team_1_bindings.sql rename to pkg/registry/apis/identity/legacy/testdata/postgres--team_bindings_query-team_1_bindings.sql index 9a81f4214eb..82d10b5fd51 100755 --- a/pkg/registry/apis/identity/legacy/testdata/sqlite--query_team_bindings-team_1_bindings.sql +++ b/pkg/registry/apis/identity/legacy/testdata/postgres--team_bindings_query-team_1_bindings.sql @@ -1,4 +1,5 @@ -SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission FROM "grafana"."team_member" tm +SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission +FROM "grafana"."team_member" tm INNER JOIN "grafana"."team" t ON tm.team_id = t.id INNER JOIN "grafana"."user" u ON tm.user_id = u.id WHERE diff --git a/pkg/registry/apis/identity/legacy/testdata/postgres--query_team_bindings-team_bindings_page_1.sql b/pkg/registry/apis/identity/legacy/testdata/postgres--team_bindings_query-team_bindings_page_1.sql similarity index 80% rename from pkg/registry/apis/identity/legacy/testdata/postgres--query_team_bindings-team_bindings_page_1.sql rename to pkg/registry/apis/identity/legacy/testdata/postgres--team_bindings_query-team_bindings_page_1.sql index 99540dc991a..77e1182cde8 100755 --- a/pkg/registry/apis/identity/legacy/testdata/postgres--query_team_bindings-team_bindings_page_1.sql +++ b/pkg/registry/apis/identity/legacy/testdata/postgres--team_bindings_query-team_bindings_page_1.sql @@ -1,4 +1,5 @@ -SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission FROM "grafana"."team_member" tm +SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission +FROM "grafana"."team_member" tm INNER JOIN "grafana"."team" t ON tm.team_id = t.id INNER JOIN "grafana"."user" u ON tm.user_id = u.id WHERE diff --git a/pkg/registry/apis/identity/legacy/testdata/postgres--query_team_bindings-team_bindings_page_2.sql b/pkg/registry/apis/identity/legacy/testdata/postgres--team_bindings_query-team_bindings_page_2.sql similarity index 81% rename from pkg/registry/apis/identity/legacy/testdata/postgres--query_team_bindings-team_bindings_page_2.sql rename to pkg/registry/apis/identity/legacy/testdata/postgres--team_bindings_query-team_bindings_page_2.sql index 7c03e74ca30..2cec052d9da 100755 --- a/pkg/registry/apis/identity/legacy/testdata/postgres--query_team_bindings-team_bindings_page_2.sql +++ b/pkg/registry/apis/identity/legacy/testdata/postgres--team_bindings_query-team_bindings_page_2.sql @@ -1,4 +1,5 @@ -SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission FROM "grafana"."team_member" tm +SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission +FROM "grafana"."team_member" tm INNER JOIN "grafana"."team" t ON tm.team_id = t.id INNER JOIN "grafana"."user" u ON tm.user_id = u.id WHERE diff --git a/pkg/registry/apis/identity/legacy/testdata/postgres--query_team_members-team_1_members_page_1.sql b/pkg/registry/apis/identity/legacy/testdata/postgres--team_members_query-team_1_members_page_1.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/postgres--query_team_members-team_1_members_page_1.sql rename to pkg/registry/apis/identity/legacy/testdata/postgres--team_members_query-team_1_members_page_1.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/postgres--query_team_members-team_1_members_page_2.sql b/pkg/registry/apis/identity/legacy/testdata/postgres--team_members_query-team_1_members_page_2.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/postgres--query_team_members-team_1_members_page_2.sql rename to pkg/registry/apis/identity/legacy/testdata/postgres--team_members_query-team_1_members_page_2.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/postgres--query_teams-teams_page_1.sql b/pkg/registry/apis/identity/legacy/testdata/postgres--teams_query-teams_page_1.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/postgres--query_teams-teams_page_1.sql rename to pkg/registry/apis/identity/legacy/testdata/postgres--teams_query-teams_page_1.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/postgres--query_teams-teams_page_2.sql b/pkg/registry/apis/identity/legacy/testdata/postgres--teams_query-teams_page_2.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/postgres--query_teams-teams_page_2.sql rename to pkg/registry/apis/identity/legacy/testdata/postgres--teams_query-teams_page_2.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/postgres--query_teams-teams_uid.sql b/pkg/registry/apis/identity/legacy/testdata/postgres--teams_query-teams_uid.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/postgres--query_teams-teams_uid.sql rename to pkg/registry/apis/identity/legacy/testdata/postgres--teams_query-teams_uid.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/postgres--query_users-users_page_1.sql b/pkg/registry/apis/identity/legacy/testdata/postgres--users_query-users_page_1.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/postgres--query_users-users_page_1.sql rename to pkg/registry/apis/identity/legacy/testdata/postgres--users_query-users_page_1.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/postgres--query_users-users_page_2.sql b/pkg/registry/apis/identity/legacy/testdata/postgres--users_query-users_page_2.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/postgres--query_users-users_page_2.sql rename to pkg/registry/apis/identity/legacy/testdata/postgres--users_query-users_page_2.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/postgres--query_users-users_uid.sql b/pkg/registry/apis/identity/legacy/testdata/postgres--users_query-users_uid.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/postgres--query_users-users_uid.sql rename to pkg/registry/apis/identity/legacy/testdata/postgres--users_query-users_uid.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/sqlite--query_display-display_ids.sql b/pkg/registry/apis/identity/legacy/testdata/sqlite--display_query-display_ids.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/sqlite--query_display-display_ids.sql rename to pkg/registry/apis/identity/legacy/testdata/sqlite--display_query-display_ids.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/sqlite--query_display-display_ids_uids.sql b/pkg/registry/apis/identity/legacy/testdata/sqlite--display_query-display_ids_uids.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/sqlite--query_display-display_ids_uids.sql rename to pkg/registry/apis/identity/legacy/testdata/sqlite--display_query-display_ids_uids.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/sqlite--query_display-display_uids.sql b/pkg/registry/apis/identity/legacy/testdata/sqlite--display_query-display_uids.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/sqlite--query_display-display_uids.sql rename to pkg/registry/apis/identity/legacy/testdata/sqlite--display_query-display_uids.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/postgres--query_team_bindings-team_1_bindings.sql b/pkg/registry/apis/identity/legacy/testdata/sqlite--team_bindings_query-team_1_bindings.sql similarity index 75% rename from pkg/registry/apis/identity/legacy/testdata/postgres--query_team_bindings-team_1_bindings.sql rename to pkg/registry/apis/identity/legacy/testdata/sqlite--team_bindings_query-team_1_bindings.sql index 9a81f4214eb..82d10b5fd51 100755 --- a/pkg/registry/apis/identity/legacy/testdata/postgres--query_team_bindings-team_1_bindings.sql +++ b/pkg/registry/apis/identity/legacy/testdata/sqlite--team_bindings_query-team_1_bindings.sql @@ -1,4 +1,5 @@ -SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission FROM "grafana"."team_member" tm +SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission +FROM "grafana"."team_member" tm INNER JOIN "grafana"."team" t ON tm.team_id = t.id INNER JOIN "grafana"."user" u ON tm.user_id = u.id WHERE diff --git a/pkg/registry/apis/identity/legacy/testdata/sqlite--query_team_bindings-team_bindings_page_1.sql b/pkg/registry/apis/identity/legacy/testdata/sqlite--team_bindings_query-team_bindings_page_1.sql similarity index 80% rename from pkg/registry/apis/identity/legacy/testdata/sqlite--query_team_bindings-team_bindings_page_1.sql rename to pkg/registry/apis/identity/legacy/testdata/sqlite--team_bindings_query-team_bindings_page_1.sql index 99540dc991a..77e1182cde8 100755 --- a/pkg/registry/apis/identity/legacy/testdata/sqlite--query_team_bindings-team_bindings_page_1.sql +++ b/pkg/registry/apis/identity/legacy/testdata/sqlite--team_bindings_query-team_bindings_page_1.sql @@ -1,4 +1,5 @@ -SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission FROM "grafana"."team_member" tm +SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission +FROM "grafana"."team_member" tm INNER JOIN "grafana"."team" t ON tm.team_id = t.id INNER JOIN "grafana"."user" u ON tm.user_id = u.id WHERE diff --git a/pkg/registry/apis/identity/legacy/testdata/sqlite--query_team_bindings-team_bindings_page_2.sql b/pkg/registry/apis/identity/legacy/testdata/sqlite--team_bindings_query-team_bindings_page_2.sql similarity index 81% rename from pkg/registry/apis/identity/legacy/testdata/sqlite--query_team_bindings-team_bindings_page_2.sql rename to pkg/registry/apis/identity/legacy/testdata/sqlite--team_bindings_query-team_bindings_page_2.sql index 7c03e74ca30..2cec052d9da 100755 --- a/pkg/registry/apis/identity/legacy/testdata/sqlite--query_team_bindings-team_bindings_page_2.sql +++ b/pkg/registry/apis/identity/legacy/testdata/sqlite--team_bindings_query-team_bindings_page_2.sql @@ -1,4 +1,5 @@ -SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission FROM "grafana"."team_member" tm +SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission +FROM "grafana"."team_member" tm INNER JOIN "grafana"."team" t ON tm.team_id = t.id INNER JOIN "grafana"."user" u ON tm.user_id = u.id WHERE diff --git a/pkg/registry/apis/identity/legacy/testdata/sqlite--query_team_members-team_1_members_page_1.sql b/pkg/registry/apis/identity/legacy/testdata/sqlite--team_members_query-team_1_members_page_1.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/sqlite--query_team_members-team_1_members_page_1.sql rename to pkg/registry/apis/identity/legacy/testdata/sqlite--team_members_query-team_1_members_page_1.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/sqlite--query_team_members-team_1_members_page_2.sql b/pkg/registry/apis/identity/legacy/testdata/sqlite--team_members_query-team_1_members_page_2.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/sqlite--query_team_members-team_1_members_page_2.sql rename to pkg/registry/apis/identity/legacy/testdata/sqlite--team_members_query-team_1_members_page_2.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/sqlite--query_teams-teams_page_1.sql b/pkg/registry/apis/identity/legacy/testdata/sqlite--teams_query-teams_page_1.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/sqlite--query_teams-teams_page_1.sql rename to pkg/registry/apis/identity/legacy/testdata/sqlite--teams_query-teams_page_1.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/sqlite--query_teams-teams_page_2.sql b/pkg/registry/apis/identity/legacy/testdata/sqlite--teams_query-teams_page_2.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/sqlite--query_teams-teams_page_2.sql rename to pkg/registry/apis/identity/legacy/testdata/sqlite--teams_query-teams_page_2.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/sqlite--query_teams-teams_uid.sql b/pkg/registry/apis/identity/legacy/testdata/sqlite--teams_query-teams_uid.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/sqlite--query_teams-teams_uid.sql rename to pkg/registry/apis/identity/legacy/testdata/sqlite--teams_query-teams_uid.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/sqlite--query_users-users_page_1.sql b/pkg/registry/apis/identity/legacy/testdata/sqlite--users_query-users_page_1.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/sqlite--query_users-users_page_1.sql rename to pkg/registry/apis/identity/legacy/testdata/sqlite--users_query-users_page_1.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/sqlite--query_users-users_page_2.sql b/pkg/registry/apis/identity/legacy/testdata/sqlite--users_query-users_page_2.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/sqlite--query_users-users_page_2.sql rename to pkg/registry/apis/identity/legacy/testdata/sqlite--users_query-users_page_2.sql diff --git a/pkg/registry/apis/identity/legacy/testdata/sqlite--query_users-users_uid.sql b/pkg/registry/apis/identity/legacy/testdata/sqlite--users_query-users_uid.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/testdata/sqlite--query_users-users_uid.sql rename to pkg/registry/apis/identity/legacy/testdata/sqlite--users_query-users_uid.sql diff --git a/pkg/registry/apis/identity/legacy/types.go b/pkg/registry/apis/identity/legacy/types.go deleted file mode 100644 index 3d63f81cdac..00000000000 --- a/pkg/registry/apis/identity/legacy/types.go +++ /dev/null @@ -1,106 +0,0 @@ -package legacy - -import ( - "context" - "time" - - "github.com/grafana/authlib/claims" - "github.com/grafana/grafana/pkg/apimachinery/identity" - "github.com/grafana/grafana/pkg/registry/apis/identity/common" - "github.com/grafana/grafana/pkg/services/team" - "github.com/grafana/grafana/pkg/services/user" -) - -type ListUserQuery struct { - OrgID int64 - UID string - IsServiceAccount bool - - Pagination common.Pagination -} - -type ListUserResult struct { - Users []user.User - Continue int64 - RV int64 -} - -type GetUserDisplayQuery struct { - OrgID int64 - UIDs []string - IDs []int64 -} - -type ListTeamQuery struct { - OrgID int64 - UID string - - Pagination common.Pagination -} - -type ListTeamResult struct { - Teams []team.Team - Continue int64 - RV int64 -} - -type TeamMember struct { - ID int64 - TeamID int64 - TeamUID string - UserID int64 - UserUID string - Name string - Email string - Username string - External bool - Updated time.Time - Created time.Time - Permission team.PermissionType -} - -func (m TeamMember) MemberID() string { - return identity.NewTypedIDString(claims.TypeUser, m.UserUID) -} - -type TeamBinding struct { - TeamUID string - Members []TeamMember -} - -type ListTeamBindingsQuery struct { - // UID is team uid to list bindings for. If not set store should list bindings for all teams - UID string - OrgID int64 - Pagination common.Pagination -} - -type ListTeamBindingsResult struct { - Bindings []TeamBinding - Continue int64 - RV int64 -} - -type ListTeamMembersQuery struct { - UID string - OrgID int64 - Pagination common.Pagination -} - -type ListTeamMembersResult struct { - Continue int64 - Members []TeamMember -} - -// In every case, RBAC should be applied before calling, or before returning results to the requester -type LegacyIdentityStore interface { - GetDisplay(ctx context.Context, ns claims.NamespaceInfo, query GetUserDisplayQuery) (*ListUserResult, error) - - ListUsers(ctx context.Context, ns claims.NamespaceInfo, query ListUserQuery) (*ListUserResult, error) - - ListTeams(ctx context.Context, ns claims.NamespaceInfo, query ListTeamQuery) (*ListTeamResult, error) - ListTeamBindings(ctx context.Context, ns claims.NamespaceInfo, query ListTeamBindingsQuery) (*ListTeamBindingsResult, error) - ListTeamMembers(ctx context.Context, ns claims.NamespaceInfo, query ListTeamMembersQuery) (*ListTeamMembersResult, error) - - GetUserTeams(ctx context.Context, ns claims.NamespaceInfo, uid string) ([]team.Team, error) -} diff --git a/pkg/registry/apis/identity/legacy/user.go b/pkg/registry/apis/identity/legacy/user.go new file mode 100644 index 00000000000..7f5a8494940 --- /dev/null +++ b/pkg/registry/apis/identity/legacy/user.go @@ -0,0 +1,111 @@ +package legacy + +import ( + "context" + "fmt" + "text/template" + + "github.com/grafana/authlib/claims" + "github.com/grafana/grafana/pkg/registry/apis/identity/common" + "github.com/grafana/grafana/pkg/services/user" + "github.com/grafana/grafana/pkg/storage/legacysql" + "github.com/grafana/grafana/pkg/storage/unified/sql/sqltemplate" +) + +type ListUserQuery struct { + OrgID int64 + UID string + IsServiceAccount bool + + Pagination common.Pagination +} + +type ListUserResult struct { + Users []user.User + Continue int64 + RV int64 +} + +var sqlQueryUsersTemplate = mustTemplate("users_query.sql") + +func newListUser(sql *legacysql.LegacyDatabaseHelper, q *ListUserQuery) listUsersQuery { + return listUsersQuery{ + SQLTemplate: sqltemplate.New(sql.DialectForDriver()), + UserTable: sql.Table("user"), + OrgUserTable: sql.Table("org_user"), + Query: q, + } +} + +type listUsersQuery struct { + sqltemplate.SQLTemplate + Query *ListUserQuery + UserTable string + OrgUserTable string +} + +func (r listUsersQuery) Validate() error { + return nil // TODO +} + +// ListUsers implements LegacyIdentityStore. +func (s *legacySQLStore) ListUsers(ctx context.Context, ns claims.NamespaceInfo, query ListUserQuery) (*ListUserResult, error) { + // for continue + limit := int(query.Pagination.Limit) + query.Pagination.Limit += 1 + + query.OrgID = ns.OrgID + if ns.OrgID == 0 { + return nil, fmt.Errorf("expected non zero orgID") + } + + sql, err := s.sql(ctx) + if err != nil { + return nil, err + } + + res, err := s.queryUsers(ctx, sql, sqlQueryUsersTemplate, newListUser(sql, &query), limit) + if err == nil && query.UID != "" { + res.RV, err = sql.GetResourceVersion(ctx, "user", "updated") + } + + return res, err +} + +func (s *legacySQLStore) queryUsers(ctx context.Context, sql *legacysql.LegacyDatabaseHelper, t *template.Template, req sqltemplate.Args, limit int) (*ListUserResult, error) { + q, err := sqltemplate.Execute(t, req) + if err != nil { + return nil, fmt.Errorf("execute template %q: %w", t.Name(), err) + } + + res := &ListUserResult{} + rows, err := sql.DB.GetSqlxSession().Query(ctx, q, req.GetArgs()...) + defer func() { + if rows != nil { + _ = rows.Close() + } + }() + + if err == nil { + var lastID int64 + for rows.Next() { + u := user.User{} + err = rows.Scan(&u.OrgID, &u.ID, &u.UID, &u.Login, &u.Email, &u.Name, + &u.Created, &u.Updated, &u.IsServiceAccount, &u.IsDisabled, &u.IsAdmin, + ) + if err != nil { + return res, err + } + + lastID = u.ID + res.Users = append(res.Users, u) + if len(res.Users) > limit { + res.Users = res.Users[0 : len(res.Users)-1] + res.Continue = lastID + break + } + } + } + + return res, err +} diff --git a/pkg/registry/apis/identity/legacy/query_users.sql b/pkg/registry/apis/identity/legacy/users_query.sql similarity index 100% rename from pkg/registry/apis/identity/legacy/query_users.sql rename to pkg/registry/apis/identity/legacy/users_query.sql diff --git a/pkg/registry/apis/identity/user/display_store.go b/pkg/registry/apis/identity/user/display_store.go index 406e4c2e0c0..76a7c780890 100644 --- a/pkg/registry/apis/identity/user/display_store.go +++ b/pkg/registry/apis/identity/user/display_store.go @@ -81,7 +81,7 @@ func (r *LegacyDisplayStore) Connect(ctx context.Context, name string, _ runtime return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { keys := parseKeys(req.URL.Query()["key"]) - users, err := r.store.GetDisplay(ctx, ns, legacy.GetUserDisplayQuery{ + users, err := r.store.ListDisplay(ctx, ns, legacy.ListDisplayQuery{ OrgID: ns.OrgID, UIDs: keys.uids, IDs: keys.ids,