Populate Repository.Owner in list/get store queries

ListReposVisible, GetRepositoryByName, and GetRepositoryByID left
Repository.Owner as nil because they only selected repository columns.
LEFT JOIN users in all three and populate Owner, so the API (and the
web UI's repositories table) can show the owner's username.
This commit is contained in:
2026-06-28 18:42:31 -05:00
parent c5e64cf63f
commit bff58fd842
+50 -10
View File
@@ -24,11 +24,13 @@ func (s *Store) CreateRepository(ctx context.Context, name, ownerUserID string,
} }
// ListReposVisible returns repositories visible to userID: owned, public, or // ListReposVisible returns repositories visible to userID: owned, public, or
// where the user is a member. // where the user is a member. Each repository's Owner is populated.
func (s *Store) ListReposVisible(ctx context.Context, userID string) ([]*models.Repository, error) { func (s *Store) ListReposVisible(ctx context.Context, userID string) ([]*models.Repository, error) {
rows, err := s.db.QueryContext(ctx, ` rows, err := s.db.QueryContext(ctx, `
SELECT DISTINCT r.id, r.name, r.owner_user_id, r.visibility, r.description, r.created_at, r.updated_at SELECT DISTINCT r.id, r.name, r.owner_user_id, r.visibility, r.description, r.created_at, r.updated_at,
u.id, u.username, u.is_admin, u.created_at, u.updated_at
FROM repositories r FROM repositories r
LEFT JOIN users u ON u.id = r.owner_user_id
WHERE r.owner_user_id = ? WHERE r.owner_user_id = ?
OR r.visibility = 'public' OR r.visibility = 'public'
OR EXISTS (SELECT 1 FROM repository_members m WHERE m.repository_id = r.id AND m.user_id = ?) OR EXISTS (SELECT 1 FROM repository_members m WHERE m.repository_id = r.id AND m.user_id = ?)
@@ -40,9 +42,25 @@ func (s *Store) ListReposVisible(ctx context.Context, userID string) ([]*models.
var out []*models.Repository var out []*models.Repository
for rows.Next() { for rows.Next() {
r := &models.Repository{} r := &models.Repository{}
if err := rows.Scan(&r.ID, &r.Name, &r.OwnerUserID, &r.Visibility, &r.Description, &r.CreatedAt, &r.UpdatedAt); err != nil { var (
ownerID sql.NullString
ownerUser sql.NullString
ownerAdmin sql.NullBool
ownerCreated sql.NullString
ownerUpdated sql.NullString
)
if err := rows.Scan(
&r.ID, &r.Name, &r.OwnerUserID, &r.Visibility, &r.Description, &r.CreatedAt, &r.UpdatedAt,
&ownerID, &ownerUser, &ownerAdmin, &ownerCreated, &ownerUpdated,
); err != nil {
return nil, err return nil, err
} }
if ownerID.Valid {
r.Owner = &models.User{
ID: ownerID.String, Username: ownerUser.String, IsAdmin: ownerAdmin.Bool,
CreatedAt: ownerCreated.String, UpdatedAt: ownerUpdated.String,
}
}
out = append(out, r) out = append(out, r)
} }
return out, rows.Err() return out, rows.Err()
@@ -79,31 +97,53 @@ func (s *Store) DeleteRepository(ctx context.Context, id string) error {
return nil return nil
} }
// GetRepositoryByName returns a repository by its unique name. // GetRepositoryByName returns a repository by its unique name, with Owner populated.
func (s *Store) GetRepositoryByName(ctx context.Context, name string) (*models.Repository, error) { func (s *Store) GetRepositoryByName(ctx context.Context, name string) (*models.Repository, error) {
row := s.db.QueryRowContext(ctx, row := s.db.QueryRowContext(ctx,
`SELECT id, name, owner_user_id, visibility, description, created_at, updated_at `SELECT r.id, r.name, r.owner_user_id, r.visibility, r.description, r.created_at, r.updated_at,
FROM repositories WHERE name = ?`, name) u.id, u.username, u.is_admin, u.created_at, u.updated_at
FROM repositories r
LEFT JOIN users u ON u.id = r.owner_user_id
WHERE r.name = ?`, name)
return scanRepo(row) return scanRepo(row)
} }
// GetRepositoryByID returns a repository by id. // GetRepositoryByID returns a repository by id, with Owner populated.
func (s *Store) GetRepositoryByID(ctx context.Context, id string) (*models.Repository, error) { func (s *Store) GetRepositoryByID(ctx context.Context, id string) (*models.Repository, error) {
row := s.db.QueryRowContext(ctx, row := s.db.QueryRowContext(ctx,
`SELECT id, name, owner_user_id, visibility, description, created_at, updated_at `SELECT r.id, r.name, r.owner_user_id, r.visibility, r.description, r.created_at, r.updated_at,
FROM repositories WHERE id = ?`, id) u.id, u.username, u.is_admin, u.created_at, u.updated_at
FROM repositories r
LEFT JOIN users u ON u.id = r.owner_user_id
WHERE r.id = ?`, id)
return scanRepo(row) return scanRepo(row)
} }
func scanRepo(row *sql.Row) (*models.Repository, error) { func scanRepo(row *sql.Row) (*models.Repository, error) {
r := &models.Repository{} r := &models.Repository{}
err := row.Scan(&r.ID, &r.Name, &r.OwnerUserID, &r.Visibility, &r.Description, &r.CreatedAt, &r.UpdatedAt) var (
ownerID sql.NullString
ownerUser sql.NullString
ownerAdmin sql.NullBool
ownerCreated sql.NullString
ownerUpdated sql.NullString
)
err := row.Scan(
&r.ID, &r.Name, &r.OwnerUserID, &r.Visibility, &r.Description, &r.CreatedAt, &r.UpdatedAt,
&ownerID, &ownerUser, &ownerAdmin, &ownerCreated, &ownerUpdated,
)
if isErrNoRows(err) { if isErrNoRows(err) {
return nil, ErrNotFound return nil, ErrNotFound
} }
if err != nil { if err != nil {
return nil, err return nil, err
} }
if ownerID.Valid {
r.Owner = &models.User{
ID: ownerID.String, Username: ownerUser.String, IsAdmin: ownerAdmin.Bool,
CreatedAt: ownerCreated.String, UpdatedAt: ownerUpdated.String,
}
}
return r, nil return r, nil
} }