mirror of
https://github.com/coder/coder.git
synced 2025-07-09 11:45:56 +00:00
This aggregates stats periodically and sends them by agent ID to our telemetry server. It should help us identify which editors are primarily in use.
408 lines
17 KiB
Go
408 lines
17 KiB
Go
package dbauthz
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/coder/coder/coderd/database"
|
|
"github.com/coder/coder/coderd/rbac"
|
|
)
|
|
|
|
// GetWorkspaceAppsByAgentIDs
|
|
// The workspace/job is already fetched.
|
|
func (q *querier) GetWorkspaceAppsByAgentIDs(ctx context.Context, ids []uuid.UUID) ([]database.WorkspaceApp, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return nil, err
|
|
}
|
|
return q.db.GetWorkspaceAppsByAgentIDs(ctx, ids)
|
|
}
|
|
|
|
// GetWorkspaceAgentsByResourceIDs
|
|
// The workspace/job is already fetched.
|
|
func (q *querier) GetWorkspaceAgentsByResourceIDs(ctx context.Context, ids []uuid.UUID) ([]database.WorkspaceAgent, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return nil, err
|
|
}
|
|
return q.db.GetWorkspaceAgentsByResourceIDs(ctx, ids)
|
|
}
|
|
|
|
// GetWorkspaceResourceMetadataByResourceIDs is only used for build data.
|
|
// The workspace/job is already fetched.
|
|
func (q *querier) GetWorkspaceResourceMetadataByResourceIDs(ctx context.Context, ids []uuid.UUID) ([]database.WorkspaceResourceMetadatum, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return nil, err
|
|
}
|
|
return q.db.GetWorkspaceResourceMetadataByResourceIDs(ctx, ids)
|
|
}
|
|
|
|
// TODO: we need to add a provisioner job resource
|
|
func (q *querier) GetProvisionerJobsByIDs(ctx context.Context, ids []uuid.UUID) ([]database.ProvisionerJob, error) {
|
|
// if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
// return nil, err
|
|
// }
|
|
return q.db.GetProvisionerJobsByIDs(ctx, ids)
|
|
}
|
|
|
|
// GetTemplateVersionsByIDs is only used for workspace build data.
|
|
// The workspace is already fetched.
|
|
func (q *querier) GetTemplateVersionsByIDs(ctx context.Context, ids []uuid.UUID) ([]database.TemplateVersion, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return nil, err
|
|
}
|
|
return q.db.GetTemplateVersionsByIDs(ctx, ids)
|
|
}
|
|
|
|
// GetWorkspaceResourcesByJobIDs is only used for workspace build data.
|
|
// The workspace is already fetched.
|
|
// TODO: Find a way to replace this with proper authz.
|
|
func (q *querier) GetWorkspaceResourcesByJobIDs(ctx context.Context, ids []uuid.UUID) ([]database.WorkspaceResource, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return nil, err
|
|
}
|
|
return q.db.GetWorkspaceResourcesByJobIDs(ctx, ids)
|
|
}
|
|
|
|
func (q *querier) UpdateUserLinkedID(ctx context.Context, arg database.UpdateUserLinkedIDParams) (database.UserLink, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil {
|
|
return database.UserLink{}, err
|
|
}
|
|
return q.db.UpdateUserLinkedID(ctx, arg)
|
|
}
|
|
|
|
func (q *querier) GetUserLinkByLinkedID(ctx context.Context, linkedID string) (database.UserLink, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return database.UserLink{}, err
|
|
}
|
|
return q.db.GetUserLinkByLinkedID(ctx, linkedID)
|
|
}
|
|
|
|
func (q *querier) GetUserLinkByUserIDLoginType(ctx context.Context, arg database.GetUserLinkByUserIDLoginTypeParams) (database.UserLink, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return database.UserLink{}, err
|
|
}
|
|
return q.db.GetUserLinkByUserIDLoginType(ctx, arg)
|
|
}
|
|
|
|
func (q *querier) GetLatestWorkspaceBuilds(ctx context.Context) ([]database.WorkspaceBuild, error) {
|
|
// This function is a system function until we implement a join for workspace builds.
|
|
// This is because we need to query for all related workspaces to the returned builds.
|
|
// This is a very inefficient method of fetching the latest workspace builds.
|
|
// We should just join the rbac properties.
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return nil, err
|
|
}
|
|
return q.db.GetLatestWorkspaceBuilds(ctx)
|
|
}
|
|
|
|
// GetWorkspaceAgentByAuthToken is used in http middleware to get the workspace agent.
|
|
// This should only be used by a system user in that middleware.
|
|
func (q *querier) GetWorkspaceAgentByAuthToken(ctx context.Context, authToken uuid.UUID) (database.WorkspaceAgent, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return database.WorkspaceAgent{}, err
|
|
}
|
|
return q.db.GetWorkspaceAgentByAuthToken(ctx, authToken)
|
|
}
|
|
|
|
func (q *querier) GetActiveUserCount(ctx context.Context) (int64, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return 0, err
|
|
}
|
|
return q.db.GetActiveUserCount(ctx)
|
|
}
|
|
|
|
func (q *querier) GetUnexpiredLicenses(ctx context.Context) ([]database.License, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return nil, err
|
|
}
|
|
return q.db.GetUnexpiredLicenses(ctx)
|
|
}
|
|
|
|
func (q *querier) GetAuthorizationUserRoles(ctx context.Context, userID uuid.UUID) (database.GetAuthorizationUserRolesRow, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return database.GetAuthorizationUserRolesRow{}, err
|
|
}
|
|
return q.db.GetAuthorizationUserRoles(ctx, userID)
|
|
}
|
|
|
|
func (q *querier) GetDERPMeshKey(ctx context.Context) (string, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return "", err
|
|
}
|
|
return q.db.GetDERPMeshKey(ctx)
|
|
}
|
|
|
|
func (q *querier) InsertDERPMeshKey(ctx context.Context, value string) error {
|
|
if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil {
|
|
return err
|
|
}
|
|
return q.db.InsertDERPMeshKey(ctx, value)
|
|
}
|
|
|
|
func (q *querier) InsertDeploymentID(ctx context.Context, value string) error {
|
|
if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil {
|
|
return err
|
|
}
|
|
return q.db.InsertDeploymentID(ctx, value)
|
|
}
|
|
|
|
func (q *querier) InsertReplica(ctx context.Context, arg database.InsertReplicaParams) (database.Replica, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil {
|
|
return database.Replica{}, err
|
|
}
|
|
return q.db.InsertReplica(ctx, arg)
|
|
}
|
|
|
|
func (q *querier) UpdateReplica(ctx context.Context, arg database.UpdateReplicaParams) (database.Replica, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil {
|
|
return database.Replica{}, err
|
|
}
|
|
return q.db.UpdateReplica(ctx, arg)
|
|
}
|
|
|
|
func (q *querier) DeleteReplicasUpdatedBefore(ctx context.Context, updatedAt time.Time) error {
|
|
if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceSystem); err != nil {
|
|
return err
|
|
}
|
|
return q.db.DeleteReplicasUpdatedBefore(ctx, updatedAt)
|
|
}
|
|
|
|
func (q *querier) GetReplicasUpdatedAfter(ctx context.Context, updatedAt time.Time) ([]database.Replica, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return nil, err
|
|
}
|
|
return q.db.GetReplicasUpdatedAfter(ctx, updatedAt)
|
|
}
|
|
|
|
func (q *querier) GetUserCount(ctx context.Context) (int64, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return 0, err
|
|
}
|
|
return q.db.GetUserCount(ctx)
|
|
}
|
|
|
|
func (q *querier) GetTemplates(ctx context.Context) ([]database.Template, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return nil, err
|
|
}
|
|
return q.db.GetTemplates(ctx)
|
|
}
|
|
|
|
// Only used by metrics cache.
|
|
func (q *querier) GetTemplateAverageBuildTime(ctx context.Context, arg database.GetTemplateAverageBuildTimeParams) (database.GetTemplateAverageBuildTimeRow, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return database.GetTemplateAverageBuildTimeRow{}, err
|
|
}
|
|
return q.db.GetTemplateAverageBuildTime(ctx, arg)
|
|
}
|
|
|
|
// Only used by metrics cache.
|
|
func (q *querier) GetTemplateDAUs(ctx context.Context, templateID uuid.UUID) ([]database.GetTemplateDAUsRow, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return nil, err
|
|
}
|
|
return q.db.GetTemplateDAUs(ctx, templateID)
|
|
}
|
|
|
|
// Only used by metrics cache.
|
|
func (q *querier) GetDeploymentDAUs(ctx context.Context) ([]database.GetDeploymentDAUsRow, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return nil, err
|
|
}
|
|
return q.db.GetDeploymentDAUs(ctx)
|
|
}
|
|
|
|
// UpdateWorkspaceBuildCostByID is used by the provisioning system to update the cost of a workspace build.
|
|
func (q *querier) UpdateWorkspaceBuildCostByID(ctx context.Context, arg database.UpdateWorkspaceBuildCostByIDParams) (database.WorkspaceBuild, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil {
|
|
return database.WorkspaceBuild{}, err
|
|
}
|
|
return q.db.UpdateWorkspaceBuildCostByID(ctx, arg)
|
|
}
|
|
|
|
func (q *querier) InsertOrUpdateLastUpdateCheck(ctx context.Context, value string) error {
|
|
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil {
|
|
return err
|
|
}
|
|
return q.db.InsertOrUpdateLastUpdateCheck(ctx, value)
|
|
}
|
|
|
|
func (q *querier) GetLastUpdateCheck(ctx context.Context) (string, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return "", err
|
|
}
|
|
return q.db.GetLastUpdateCheck(ctx)
|
|
}
|
|
|
|
// Telemetry related functions. These functions are system functions for returning
|
|
// telemetry data. Never called by a user.
|
|
|
|
func (q *querier) GetWorkspaceBuildsCreatedAfter(ctx context.Context, createdAt time.Time) ([]database.WorkspaceBuild, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return nil, err
|
|
}
|
|
return q.db.GetWorkspaceBuildsCreatedAfter(ctx, createdAt)
|
|
}
|
|
|
|
func (q *querier) GetWorkspaceAgentsCreatedAfter(ctx context.Context, createdAt time.Time) ([]database.WorkspaceAgent, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return nil, err
|
|
}
|
|
return q.db.GetWorkspaceAgentsCreatedAfter(ctx, createdAt)
|
|
}
|
|
|
|
func (q *querier) GetWorkspaceAppsCreatedAfter(ctx context.Context, createdAt time.Time) ([]database.WorkspaceApp, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return nil, err
|
|
}
|
|
return q.db.GetWorkspaceAppsCreatedAfter(ctx, createdAt)
|
|
}
|
|
|
|
func (q *querier) GetWorkspaceResourcesCreatedAfter(ctx context.Context, createdAt time.Time) ([]database.WorkspaceResource, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return nil, err
|
|
}
|
|
return q.db.GetWorkspaceResourcesCreatedAfter(ctx, createdAt)
|
|
}
|
|
|
|
func (q *querier) GetWorkspaceResourceMetadataCreatedAfter(ctx context.Context, createdAt time.Time) ([]database.WorkspaceResourceMetadatum, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return nil, err
|
|
}
|
|
return q.db.GetWorkspaceResourceMetadataCreatedAfter(ctx, createdAt)
|
|
}
|
|
|
|
func (q *querier) DeleteOldWorkspaceAgentStats(ctx context.Context) error {
|
|
if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceSystem); err != nil {
|
|
return err
|
|
}
|
|
return q.db.DeleteOldWorkspaceAgentStats(ctx)
|
|
}
|
|
|
|
func (q *querier) GetDeploymentWorkspaceAgentStats(ctx context.Context, createdAfter time.Time) (database.GetDeploymentWorkspaceAgentStatsRow, error) {
|
|
return q.db.GetDeploymentWorkspaceAgentStats(ctx, createdAfter)
|
|
}
|
|
|
|
func (q *querier) GetWorkspaceAgentStats(ctx context.Context, createdAfter time.Time) ([]database.GetWorkspaceAgentStatsRow, error) {
|
|
return q.db.GetWorkspaceAgentStats(ctx, createdAfter)
|
|
}
|
|
|
|
func (q *querier) GetDeploymentWorkspaceStats(ctx context.Context) (database.GetDeploymentWorkspaceStatsRow, error) {
|
|
return q.db.GetDeploymentWorkspaceStats(ctx)
|
|
}
|
|
|
|
func (q *querier) GetParameterSchemasCreatedAfter(ctx context.Context, createdAt time.Time) ([]database.ParameterSchema, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
return nil, err
|
|
}
|
|
return q.db.GetParameterSchemasCreatedAfter(ctx, createdAt)
|
|
}
|
|
|
|
// TODO: We need to create a ProvisionerJob resource type
|
|
func (q *querier) GetProvisionerJobsCreatedAfter(ctx context.Context, createdAt time.Time) ([]database.ProvisionerJob, error) {
|
|
// if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
|
// return nil, err
|
|
// }
|
|
return q.db.GetProvisionerJobsCreatedAfter(ctx, createdAt)
|
|
}
|
|
|
|
// Provisionerd server functions
|
|
|
|
func (q *querier) InsertWorkspaceAgent(ctx context.Context, arg database.InsertWorkspaceAgentParams) (database.WorkspaceAgent, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil {
|
|
return database.WorkspaceAgent{}, err
|
|
}
|
|
return q.db.InsertWorkspaceAgent(ctx, arg)
|
|
}
|
|
|
|
func (q *querier) InsertWorkspaceApp(ctx context.Context, arg database.InsertWorkspaceAppParams) (database.WorkspaceApp, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil {
|
|
return database.WorkspaceApp{}, err
|
|
}
|
|
return q.db.InsertWorkspaceApp(ctx, arg)
|
|
}
|
|
|
|
func (q *querier) InsertWorkspaceResourceMetadata(ctx context.Context, arg database.InsertWorkspaceResourceMetadataParams) ([]database.WorkspaceResourceMetadatum, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil {
|
|
return nil, err
|
|
}
|
|
return q.db.InsertWorkspaceResourceMetadata(ctx, arg)
|
|
}
|
|
|
|
// TODO: We need to create a ProvisionerJob resource type
|
|
func (q *querier) AcquireProvisionerJob(ctx context.Context, arg database.AcquireProvisionerJobParams) (database.ProvisionerJob, error) {
|
|
// if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil {
|
|
// return database.ProvisionerJob{}, err
|
|
// }
|
|
return q.db.AcquireProvisionerJob(ctx, arg)
|
|
}
|
|
|
|
// TODO: We need to create a ProvisionerJob resource type
|
|
func (q *querier) UpdateProvisionerJobWithCompleteByID(ctx context.Context, arg database.UpdateProvisionerJobWithCompleteByIDParams) error {
|
|
// if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil {
|
|
// return err
|
|
// }
|
|
return q.db.UpdateProvisionerJobWithCompleteByID(ctx, arg)
|
|
}
|
|
|
|
// TODO: We need to create a ProvisionerJob resource type
|
|
func (q *querier) UpdateProvisionerJobByID(ctx context.Context, arg database.UpdateProvisionerJobByIDParams) error {
|
|
// if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil {
|
|
// return err
|
|
// }
|
|
return q.db.UpdateProvisionerJobByID(ctx, arg)
|
|
}
|
|
|
|
// TODO: We need to create a ProvisionerJob resource type
|
|
func (q *querier) InsertProvisionerJob(ctx context.Context, arg database.InsertProvisionerJobParams) (database.ProvisionerJob, error) {
|
|
// if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil {
|
|
// return database.ProvisionerJob{}, err
|
|
// }
|
|
return q.db.InsertProvisionerJob(ctx, arg)
|
|
}
|
|
|
|
// TODO: We need to create a ProvisionerJob resource type
|
|
func (q *querier) InsertProvisionerJobLogs(ctx context.Context, arg database.InsertProvisionerJobLogsParams) ([]database.ProvisionerJobLog, error) {
|
|
// if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil {
|
|
// return nil, err
|
|
// }
|
|
return q.db.InsertProvisionerJobLogs(ctx, arg)
|
|
}
|
|
|
|
// TODO: We need to create a ProvisionerDaemon resource type
|
|
func (q *querier) InsertProvisionerDaemon(ctx context.Context, arg database.InsertProvisionerDaemonParams) (database.ProvisionerDaemon, error) {
|
|
// if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil {
|
|
// return database.ProvisionerDaemon{}, err
|
|
// }
|
|
return q.db.InsertProvisionerDaemon(ctx, arg)
|
|
}
|
|
|
|
func (q *querier) InsertTemplateVersionParameter(ctx context.Context, arg database.InsertTemplateVersionParameterParams) (database.TemplateVersionParameter, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil {
|
|
return database.TemplateVersionParameter{}, err
|
|
}
|
|
return q.db.InsertTemplateVersionParameter(ctx, arg)
|
|
}
|
|
|
|
func (q *querier) InsertTemplateVersionVariable(ctx context.Context, arg database.InsertTemplateVersionVariableParams) (database.TemplateVersionVariable, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil {
|
|
return database.TemplateVersionVariable{}, err
|
|
}
|
|
return q.db.InsertTemplateVersionVariable(ctx, arg)
|
|
}
|
|
|
|
func (q *querier) InsertWorkspaceResource(ctx context.Context, arg database.InsertWorkspaceResourceParams) (database.WorkspaceResource, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil {
|
|
return database.WorkspaceResource{}, err
|
|
}
|
|
return q.db.InsertWorkspaceResource(ctx, arg)
|
|
}
|
|
|
|
func (q *querier) InsertParameterSchema(ctx context.Context, arg database.InsertParameterSchemaParams) (database.ParameterSchema, error) {
|
|
if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil {
|
|
return database.ParameterSchema{}, err
|
|
}
|
|
return q.db.InsertParameterSchema(ctx, arg)
|
|
}
|