mirror of
https://github.com/coder/coder.git
synced 2025-07-18 14:17:22 +00:00
chore: remove parallel queries in the same transaction (#18489)
Parallel concurrent queries cannot be run in the same tx Was getting this error: https://stackoverflow.com/questions/78472996/go-postgres-pq-unexpected-parse-response-c-with-queryrow
This commit is contained in:
@ -9,7 +9,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/coder/coder/v2/apiversion"
|
||||
@ -244,8 +243,6 @@ func (r *dynamicRenderer) getWorkspaceOwnerData(ctx context.Context, ownerID uui
|
||||
return nil // already fetched
|
||||
}
|
||||
|
||||
var g errgroup.Group
|
||||
|
||||
// You only need to be able to read the organization member to get the owner
|
||||
// data. Only the terraform files can therefore leak more information than the
|
||||
// caller should have access to. All this info should be public assuming you can
|
||||
@ -266,72 +263,54 @@ func (r *dynamicRenderer) getWorkspaceOwnerData(ctx context.Context, ownerID uui
|
||||
return xerrors.Errorf("fetch user: %w", err)
|
||||
}
|
||||
|
||||
var ownerRoles []previewtypes.WorkspaceOwnerRBACRole
|
||||
g.Go(func() error {
|
||||
// nolint:gocritic // This is kind of the wrong query to use here, but it
|
||||
// matches how the provisioner currently works. We should figure out
|
||||
// something that needs less escalation but has the correct behavior.
|
||||
row, err := r.db.GetAuthorizationUserRoles(dbauthz.AsProvisionerd(ctx), ownerID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
roles, err := row.RoleNames()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ownerRoles = make([]previewtypes.WorkspaceOwnerRBACRole, 0, len(roles))
|
||||
for _, it := range roles {
|
||||
if it.OrganizationID != uuid.Nil && it.OrganizationID != r.data.templateVersion.OrganizationID {
|
||||
continue
|
||||
}
|
||||
var orgID string
|
||||
if it.OrganizationID != uuid.Nil {
|
||||
orgID = it.OrganizationID.String()
|
||||
}
|
||||
ownerRoles = append(ownerRoles, previewtypes.WorkspaceOwnerRBACRole{
|
||||
Name: it.Name,
|
||||
OrgID: orgID,
|
||||
})
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
var publicKey string
|
||||
g.Go(func() error {
|
||||
// The correct public key has to be sent. This will not be leaked
|
||||
// unless the template leaks it.
|
||||
// nolint:gocritic
|
||||
key, err := r.db.GetGitSSHKey(dbauthz.AsProvisionerd(ctx), ownerID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
publicKey = key.PublicKey
|
||||
return nil
|
||||
})
|
||||
|
||||
var groupNames []string
|
||||
g.Go(func() error {
|
||||
// The groups need to be sent to preview. These groups are not exposed to the
|
||||
// user, unless the template does it through the parameters. Regardless, we need
|
||||
// the correct groups, and a user might not have read access.
|
||||
// nolint:gocritic
|
||||
groups, err := r.db.GetGroups(dbauthz.AsProvisionerd(ctx), database.GetGroupsParams{
|
||||
OrganizationID: r.data.templateVersion.OrganizationID,
|
||||
HasMemberID: ownerID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
groupNames = make([]string, 0, len(groups))
|
||||
for _, it := range groups {
|
||||
groupNames = append(groupNames, it.Group.Name)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
err = g.Wait()
|
||||
// nolint:gocritic // This is kind of the wrong query to use here, but it
|
||||
// matches how the provisioner currently works. We should figure out
|
||||
// something that needs less escalation but has the correct behavior.
|
||||
row, err := r.db.GetAuthorizationUserRoles(dbauthz.AsProvisionerd(ctx), ownerID)
|
||||
if err != nil {
|
||||
return err
|
||||
return xerrors.Errorf("user roles: %w", err)
|
||||
}
|
||||
roles, err := row.RoleNames()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("expand roles: %w", err)
|
||||
}
|
||||
ownerRoles := make([]previewtypes.WorkspaceOwnerRBACRole, 0, len(roles))
|
||||
for _, it := range roles {
|
||||
if it.OrganizationID != uuid.Nil && it.OrganizationID != r.data.templateVersion.OrganizationID {
|
||||
continue
|
||||
}
|
||||
var orgID string
|
||||
if it.OrganizationID != uuid.Nil {
|
||||
orgID = it.OrganizationID.String()
|
||||
}
|
||||
ownerRoles = append(ownerRoles, previewtypes.WorkspaceOwnerRBACRole{
|
||||
Name: it.Name,
|
||||
OrgID: orgID,
|
||||
})
|
||||
}
|
||||
|
||||
// The correct public key has to be sent. This will not be leaked
|
||||
// unless the template leaks it.
|
||||
// nolint:gocritic
|
||||
key, err := r.db.GetGitSSHKey(dbauthz.AsProvisionerd(ctx), ownerID)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("ssh key: %w", err)
|
||||
}
|
||||
|
||||
// The groups need to be sent to preview. These groups are not exposed to the
|
||||
// user, unless the template does it through the parameters. Regardless, we need
|
||||
// the correct groups, and a user might not have read access.
|
||||
// nolint:gocritic
|
||||
groups, err := r.db.GetGroups(dbauthz.AsProvisionerd(ctx), database.GetGroupsParams{
|
||||
OrganizationID: r.data.templateVersion.OrganizationID,
|
||||
HasMemberID: ownerID,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("groups: %w", err)
|
||||
}
|
||||
groupNames := make([]string, 0, len(groups))
|
||||
for _, it := range groups {
|
||||
groupNames = append(groupNames, it.Group.Name)
|
||||
}
|
||||
|
||||
r.currentOwner = &previewtypes.WorkspaceOwner{
|
||||
@ -341,7 +320,7 @@ func (r *dynamicRenderer) getWorkspaceOwnerData(ctx context.Context, ownerID uui
|
||||
Email: mem.Email,
|
||||
LoginType: string(user.LoginType),
|
||||
RBACRoles: ownerRoles,
|
||||
SSHPublicKey: publicKey,
|
||||
SSHPublicKey: key.PublicKey,
|
||||
Groups: groupNames,
|
||||
}
|
||||
return nil
|
||||
|
Reference in New Issue
Block a user