IAM: Handle NULL external_uid, is_provisioned correctly for Teams (#113219)

* Handle NULL external_uid correctly with MySQL

* Add NULL handling to is_provisioned column
This commit is contained in:
Misi
2025-10-30 15:50:40 +00:00
committed by GitHub
parent d6bcca2f7e
commit 44beedd09a
2 changed files with 47 additions and 5 deletions
+16 -5
View File
@@ -2,6 +2,7 @@ package legacy
import (
"context"
"database/sql"
"errors"
"fmt"
"time"
@@ -129,18 +130,18 @@ func (s *legacySQLStore) ListTeams(ctx context.Context, ns claims.NamespaceInfo,
return nil, fmt.Errorf("expected non zero orgID")
}
sql, err := s.sql(ctx)
sqlConn, err := s.sql(ctx)
if err != nil {
return nil, err
}
req := newListTeams(sql, &query)
req := newListTeams(sqlConn, &query)
q, err := sqltemplate.Execute(sqlQueryTeamsTemplate, req)
if err != nil {
return nil, fmt.Errorf("execute template %q: %w", sqlQueryTeamsTemplate.Name(), err)
}
rows, err := sql.DB.GetSqlxSession().Query(ctx, q, req.GetArgs()...)
rows, err := sqlConn.DB.GetSqlxSession().Query(ctx, q, req.GetArgs()...)
defer func() {
if rows != nil {
_ = rows.Close()
@@ -155,11 +156,21 @@ func (s *legacySQLStore) ListTeams(ctx context.Context, ns claims.NamespaceInfo,
var lastID int64
for rows.Next() {
t := team.Team{}
err = rows.Scan(&t.ID, &t.UID, &t.Name, &t.Email, &t.ExternalUID, &t.IsProvisioned, &t.Created, &t.Updated)
var externalUID sql.NullString
var isProvisioned sql.NullBool
err = rows.Scan(&t.ID, &t.UID, &t.Name, &t.Email, &externalUID, &isProvisioned, &t.Created, &t.Updated)
if err != nil {
return res, err
}
if externalUID.Valid {
t.ExternalUID = externalUID.String
}
if isProvisioned.Valid {
t.IsProvisioned = isProvisioned.Bool
}
lastID = t.ID
res.Teams = append(res.Teams, t)
if len(res.Teams) > int(query.Pagination.Limit)-1 {
@@ -170,7 +181,7 @@ func (s *legacySQLStore) ListTeams(ctx context.Context, ns claims.NamespaceInfo,
}
if query.UID == "" {
res.RV, err = sql.GetResourceVersion(ctx, "team", "updated")
res.RV, err = sqlConn.GetResourceVersion(ctx, "team", "updated")
}
return res, err
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"testing"
"time"
"github.com/stretchr/testify/require"
"k8s.io/apimachinery/pkg/api/errors"
@@ -222,6 +223,36 @@ func doTeamCRUDTestsUsingTheNewAPIs(t *testing.T, helper *apis.K8sTestHelper) {
require.Equal(t, createdUID, fetched.GetName())
require.Equal(t, "default", fetched.GetNamespace())
// Cleanup
err = teamClient.Resource.Delete(ctx, createdUID, metav1.DeleteOptions{})
require.NoError(t, err)
})
t.Run("should list teams correctly", func(t *testing.T) {
ctx := context.Background()
teamClient := helper.GetResourceClient(apis.ResourceClientArgs{
User: helper.Org1.Admin,
Namespace: helper.Namespacer(helper.Org1.Admin.Identity.GetOrgID()),
GVR: gvrTeams,
})
// For ensuring that it is able to list a team which has external_uid = null and is_provisioned = null
// only matters when legacy storage is involved
env := helper.GetEnv()
res, err := env.SQLStore.GetSqlxSession().Exec(ctx, "INSERT INTO team (org_id, uid, name, email, is_provisioned, external_uid, created, updated) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
helper.Org1.Admin.Identity.GetOrgID(), "t000000001", "List Team 1", "list-team-1@example.com", nil, nil, time.Now(), time.Now())
require.NoError(t, err)
require.NotNil(t, res)
list, err := teamClient.Resource.List(ctx, metav1.ListOptions{})
require.NoError(t, err)
require.NotNil(t, list)
// Cleanup
_, err = env.SQLStore.GetSqlxSession().Exec(ctx, "DELETE FROM team WHERE uid = ?", "t000000001")
require.NoError(t, err)
})
}