diff --git a/coderd/database/dbgen/dbgen.go b/coderd/database/dbgen/dbgen.go
index ae898d4f1fdc3..9c8696112dea8 100644
--- a/coderd/database/dbgen/dbgen.go
+++ b/coderd/database/dbgen/dbgen.go
@@ -788,16 +788,17 @@ func TemplateVersion(t testing.TB, db database.Store, orig database.TemplateVers
err := db.InTx(func(db database.Store) error {
versionID := takeFirst(orig.ID, uuid.New())
err := db.InsertTemplateVersion(genCtx, database.InsertTemplateVersionParams{
- ID: versionID,
- TemplateID: takeFirst(orig.TemplateID, uuid.NullUUID{}),
- OrganizationID: takeFirst(orig.OrganizationID, uuid.New()),
- CreatedAt: takeFirst(orig.CreatedAt, dbtime.Now()),
- UpdatedAt: takeFirst(orig.UpdatedAt, dbtime.Now()),
- Name: takeFirst(orig.Name, testutil.GetRandomName(t)),
- Message: orig.Message,
- Readme: takeFirst(orig.Readme, testutil.GetRandomName(t)),
- JobID: takeFirst(orig.JobID, uuid.New()),
- CreatedBy: takeFirst(orig.CreatedBy, uuid.New()),
+ ID: versionID,
+ TemplateID: takeFirst(orig.TemplateID, uuid.NullUUID{}),
+ OrganizationID: takeFirst(orig.OrganizationID, uuid.New()),
+ CreatedAt: takeFirst(orig.CreatedAt, dbtime.Now()),
+ UpdatedAt: takeFirst(orig.UpdatedAt, dbtime.Now()),
+ Name: takeFirst(orig.Name, testutil.GetRandomName(t)),
+ Message: orig.Message,
+ Readme: takeFirst(orig.Readme, testutil.GetRandomName(t)),
+ JobID: takeFirst(orig.JobID, uuid.New()),
+ CreatedBy: takeFirst(orig.CreatedBy, uuid.New()),
+ SourceExampleID: takeFirst(orig.SourceExampleID, sql.NullString{}),
})
if err != nil {
return err
diff --git a/coderd/database/dbmem/dbmem.go b/coderd/database/dbmem/dbmem.go
index 5583fff111648..765573b311a84 100644
--- a/coderd/database/dbmem/dbmem.go
+++ b/coderd/database/dbmem/dbmem.go
@@ -7699,16 +7699,17 @@ func (q *FakeQuerier) InsertTemplateVersion(_ context.Context, arg database.Inse
//nolint:gosimple
version := database.TemplateVersionTable{
- ID: arg.ID,
- TemplateID: arg.TemplateID,
- OrganizationID: arg.OrganizationID,
- CreatedAt: arg.CreatedAt,
- UpdatedAt: arg.UpdatedAt,
- Name: arg.Name,
- Message: arg.Message,
- Readme: arg.Readme,
- JobID: arg.JobID,
- CreatedBy: arg.CreatedBy,
+ ID: arg.ID,
+ TemplateID: arg.TemplateID,
+ OrganizationID: arg.OrganizationID,
+ CreatedAt: arg.CreatedAt,
+ UpdatedAt: arg.UpdatedAt,
+ Name: arg.Name,
+ Message: arg.Message,
+ Readme: arg.Readme,
+ JobID: arg.JobID,
+ CreatedBy: arg.CreatedBy,
+ SourceExampleID: arg.SourceExampleID,
}
q.templateVersions = append(q.templateVersions, version)
return nil
diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql
index 9919011579bde..eba9b7cf106d3 100644
--- a/coderd/database/dump.sql
+++ b/coderd/database/dump.sql
@@ -1217,7 +1217,8 @@ CREATE TABLE template_versions (
created_by uuid NOT NULL,
external_auth_providers jsonb DEFAULT '[]'::jsonb NOT NULL,
message character varying(1048576) DEFAULT ''::character varying NOT NULL,
- archived boolean DEFAULT false NOT NULL
+ archived boolean DEFAULT false NOT NULL,
+ source_example_id text
);
COMMENT ON COLUMN template_versions.external_auth_providers IS 'IDs of External auth providers for a specific template version';
@@ -1245,6 +1246,7 @@ CREATE VIEW template_version_with_user AS
template_versions.external_auth_providers,
template_versions.message,
template_versions.archived,
+ template_versions.source_example_id,
COALESCE(visible_users.avatar_url, ''::text) AS created_by_avatar_url,
COALESCE(visible_users.username, ''::text) AS created_by_username
FROM (template_versions
diff --git a/coderd/database/migrations/000277_template_version_example_ids.down.sql b/coderd/database/migrations/000277_template_version_example_ids.down.sql
new file mode 100644
index 0000000000000..ad961e9f635c7
--- /dev/null
+++ b/coderd/database/migrations/000277_template_version_example_ids.down.sql
@@ -0,0 +1,28 @@
+-- We cannot alter the column type while a view depends on it, so we drop it and recreate it.
+DROP VIEW template_version_with_user;
+
+ALTER TABLE
+ template_versions
+DROP COLUMN source_example_id;
+
+-- Recreate `template_version_with_user` as described in dump.sql
+CREATE VIEW template_version_with_user AS
+SELECT
+ template_versions.id,
+ template_versions.template_id,
+ template_versions.organization_id,
+ template_versions.created_at,
+ template_versions.updated_at,
+ template_versions.name,
+ template_versions.readme,
+ template_versions.job_id,
+ template_versions.created_by,
+ template_versions.external_auth_providers,
+ template_versions.message,
+ template_versions.archived,
+ COALESCE(visible_users.avatar_url, ''::text) AS created_by_avatar_url,
+ COALESCE(visible_users.username, ''::text) AS created_by_username
+FROM (template_versions
+ LEFT JOIN visible_users ON (template_versions.created_by = visible_users.id));
+
+COMMENT ON VIEW template_version_with_user IS 'Joins in the username + avatar url of the created by user.';
diff --git a/coderd/database/migrations/000277_template_version_example_ids.up.sql b/coderd/database/migrations/000277_template_version_example_ids.up.sql
new file mode 100644
index 0000000000000..aca34b31de5dc
--- /dev/null
+++ b/coderd/database/migrations/000277_template_version_example_ids.up.sql
@@ -0,0 +1,30 @@
+-- We cannot alter the column type while a view depends on it, so we drop it and recreate it.
+DROP VIEW template_version_with_user;
+
+ALTER TABLE
+ template_versions
+ADD
+ COLUMN source_example_id TEXT;
+
+-- Recreate `template_version_with_user` as described in dump.sql
+CREATE VIEW template_version_with_user AS
+SELECT
+ template_versions.id,
+ template_versions.template_id,
+ template_versions.organization_id,
+ template_versions.created_at,
+ template_versions.updated_at,
+ template_versions.name,
+ template_versions.readme,
+ template_versions.job_id,
+ template_versions.created_by,
+ template_versions.external_auth_providers,
+ template_versions.message,
+ template_versions.archived,
+ template_versions.source_example_id,
+ COALESCE(visible_users.avatar_url, ''::text) AS created_by_avatar_url,
+ COALESCE(visible_users.username, ''::text) AS created_by_username
+FROM (template_versions
+ LEFT JOIN visible_users ON (template_versions.created_by = visible_users.id));
+
+COMMENT ON VIEW template_version_with_user IS 'Joins in the username + avatar url of the created by user.';
diff --git a/coderd/database/models.go b/coderd/database/models.go
index af0a3122f7964..6b99245079950 100644
--- a/coderd/database/models.go
+++ b/coderd/database/models.go
@@ -2773,6 +2773,7 @@ type TemplateVersion struct {
ExternalAuthProviders json.RawMessage `db:"external_auth_providers" json:"external_auth_providers"`
Message string `db:"message" json:"message"`
Archived bool `db:"archived" json:"archived"`
+ SourceExampleID sql.NullString `db:"source_example_id" json:"source_example_id"`
CreatedByAvatarURL string `db:"created_by_avatar_url" json:"created_by_avatar_url"`
CreatedByUsername string `db:"created_by_username" json:"created_by_username"`
}
@@ -2826,8 +2827,9 @@ type TemplateVersionTable struct {
// IDs of External auth providers for a specific template version
ExternalAuthProviders json.RawMessage `db:"external_auth_providers" json:"external_auth_providers"`
// Message describing the changes in this version of the template, similar to a Git commit message. Like a commit message, this should be a short, high-level description of the changes in this version of the template. This message is immutable and should not be updated after the fact.
- Message string `db:"message" json:"message"`
- Archived bool `db:"archived" json:"archived"`
+ Message string `db:"message" json:"message"`
+ Archived bool `db:"archived" json:"archived"`
+ SourceExampleID sql.NullString `db:"source_example_id" json:"source_example_id"`
}
type TemplateVersionVariable struct {
diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go
index 4eec78cf97fba..33a3ce12a444d 100644
--- a/coderd/database/queries.sql.go
+++ b/coderd/database/queries.sql.go
@@ -8996,7 +8996,7 @@ FROM
-- Scope an archive to a single template and ignore already archived template versions
(
SELECT
- id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived
+ id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id
FROM
template_versions
WHERE
@@ -9097,7 +9097,7 @@ func (q *sqlQuerier) ArchiveUnusedTemplateVersions(ctx context.Context, arg Arch
const getPreviousTemplateVersion = `-- name: GetPreviousTemplateVersion :one
SELECT
- id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, created_by_avatar_url, created_by_username
+ id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, created_by_avatar_url, created_by_username
FROM
template_version_with_user AS template_versions
WHERE
@@ -9134,6 +9134,7 @@ func (q *sqlQuerier) GetPreviousTemplateVersion(ctx context.Context, arg GetPrev
&i.ExternalAuthProviders,
&i.Message,
&i.Archived,
+ &i.SourceExampleID,
&i.CreatedByAvatarURL,
&i.CreatedByUsername,
)
@@ -9142,7 +9143,7 @@ func (q *sqlQuerier) GetPreviousTemplateVersion(ctx context.Context, arg GetPrev
const getTemplateVersionByID = `-- name: GetTemplateVersionByID :one
SELECT
- id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, created_by_avatar_url, created_by_username
+ id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, created_by_avatar_url, created_by_username
FROM
template_version_with_user AS template_versions
WHERE
@@ -9165,6 +9166,7 @@ func (q *sqlQuerier) GetTemplateVersionByID(ctx context.Context, id uuid.UUID) (
&i.ExternalAuthProviders,
&i.Message,
&i.Archived,
+ &i.SourceExampleID,
&i.CreatedByAvatarURL,
&i.CreatedByUsername,
)
@@ -9173,7 +9175,7 @@ func (q *sqlQuerier) GetTemplateVersionByID(ctx context.Context, id uuid.UUID) (
const getTemplateVersionByJobID = `-- name: GetTemplateVersionByJobID :one
SELECT
- id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, created_by_avatar_url, created_by_username
+ id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, created_by_avatar_url, created_by_username
FROM
template_version_with_user AS template_versions
WHERE
@@ -9196,6 +9198,7 @@ func (q *sqlQuerier) GetTemplateVersionByJobID(ctx context.Context, jobID uuid.U
&i.ExternalAuthProviders,
&i.Message,
&i.Archived,
+ &i.SourceExampleID,
&i.CreatedByAvatarURL,
&i.CreatedByUsername,
)
@@ -9204,7 +9207,7 @@ func (q *sqlQuerier) GetTemplateVersionByJobID(ctx context.Context, jobID uuid.U
const getTemplateVersionByTemplateIDAndName = `-- name: GetTemplateVersionByTemplateIDAndName :one
SELECT
- id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, created_by_avatar_url, created_by_username
+ id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, created_by_avatar_url, created_by_username
FROM
template_version_with_user AS template_versions
WHERE
@@ -9233,6 +9236,7 @@ func (q *sqlQuerier) GetTemplateVersionByTemplateIDAndName(ctx context.Context,
&i.ExternalAuthProviders,
&i.Message,
&i.Archived,
+ &i.SourceExampleID,
&i.CreatedByAvatarURL,
&i.CreatedByUsername,
)
@@ -9241,7 +9245,7 @@ func (q *sqlQuerier) GetTemplateVersionByTemplateIDAndName(ctx context.Context,
const getTemplateVersionsByIDs = `-- name: GetTemplateVersionsByIDs :many
SELECT
- id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, created_by_avatar_url, created_by_username
+ id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, created_by_avatar_url, created_by_username
FROM
template_version_with_user AS template_versions
WHERE
@@ -9270,6 +9274,7 @@ func (q *sqlQuerier) GetTemplateVersionsByIDs(ctx context.Context, ids []uuid.UU
&i.ExternalAuthProviders,
&i.Message,
&i.Archived,
+ &i.SourceExampleID,
&i.CreatedByAvatarURL,
&i.CreatedByUsername,
); err != nil {
@@ -9288,7 +9293,7 @@ func (q *sqlQuerier) GetTemplateVersionsByIDs(ctx context.Context, ids []uuid.UU
const getTemplateVersionsByTemplateID = `-- name: GetTemplateVersionsByTemplateID :many
SELECT
- id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, created_by_avatar_url, created_by_username
+ id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, created_by_avatar_url, created_by_username
FROM
template_version_with_user AS template_versions
WHERE
@@ -9364,6 +9369,7 @@ func (q *sqlQuerier) GetTemplateVersionsByTemplateID(ctx context.Context, arg Ge
&i.ExternalAuthProviders,
&i.Message,
&i.Archived,
+ &i.SourceExampleID,
&i.CreatedByAvatarURL,
&i.CreatedByUsername,
); err != nil {
@@ -9381,7 +9387,7 @@ func (q *sqlQuerier) GetTemplateVersionsByTemplateID(ctx context.Context, arg Ge
}
const getTemplateVersionsCreatedAfter = `-- name: GetTemplateVersionsCreatedAfter :many
-SELECT id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, created_by_avatar_url, created_by_username FROM template_version_with_user AS template_versions WHERE created_at > $1
+SELECT id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, created_by_avatar_url, created_by_username FROM template_version_with_user AS template_versions WHERE created_at > $1
`
func (q *sqlQuerier) GetTemplateVersionsCreatedAfter(ctx context.Context, createdAt time.Time) ([]TemplateVersion, error) {
@@ -9406,6 +9412,7 @@ func (q *sqlQuerier) GetTemplateVersionsCreatedAfter(ctx context.Context, create
&i.ExternalAuthProviders,
&i.Message,
&i.Archived,
+ &i.SourceExampleID,
&i.CreatedByAvatarURL,
&i.CreatedByUsername,
); err != nil {
@@ -9434,23 +9441,25 @@ INSERT INTO
message,
readme,
job_id,
- created_by
+ created_by,
+ source_example_id
)
VALUES
- ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
+ ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
`
type InsertTemplateVersionParams struct {
- ID uuid.UUID `db:"id" json:"id"`
- TemplateID uuid.NullUUID `db:"template_id" json:"template_id"`
- OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
- CreatedAt time.Time `db:"created_at" json:"created_at"`
- UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
- Name string `db:"name" json:"name"`
- Message string `db:"message" json:"message"`
- Readme string `db:"readme" json:"readme"`
- JobID uuid.UUID `db:"job_id" json:"job_id"`
- CreatedBy uuid.UUID `db:"created_by" json:"created_by"`
+ ID uuid.UUID `db:"id" json:"id"`
+ TemplateID uuid.NullUUID `db:"template_id" json:"template_id"`
+ OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
+ CreatedAt time.Time `db:"created_at" json:"created_at"`
+ UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
+ Name string `db:"name" json:"name"`
+ Message string `db:"message" json:"message"`
+ Readme string `db:"readme" json:"readme"`
+ JobID uuid.UUID `db:"job_id" json:"job_id"`
+ CreatedBy uuid.UUID `db:"created_by" json:"created_by"`
+ SourceExampleID sql.NullString `db:"source_example_id" json:"source_example_id"`
}
func (q *sqlQuerier) InsertTemplateVersion(ctx context.Context, arg InsertTemplateVersionParams) error {
@@ -9465,6 +9474,7 @@ func (q *sqlQuerier) InsertTemplateVersion(ctx context.Context, arg InsertTempla
arg.Readme,
arg.JobID,
arg.CreatedBy,
+ arg.SourceExampleID,
)
return err
}
diff --git a/coderd/database/queries/templateversions.sql b/coderd/database/queries/templateversions.sql
index 094c1b6014de7..0436a7f9ba3b9 100644
--- a/coderd/database/queries/templateversions.sql
+++ b/coderd/database/queries/templateversions.sql
@@ -87,10 +87,11 @@ INSERT INTO
message,
readme,
job_id,
- created_by
+ created_by,
+ source_example_id
)
VALUES
- ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);
+ ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11);
-- name: UpdateTemplateVersionByID :exec
UPDATE
diff --git a/coderd/telemetry/telemetry.go b/coderd/telemetry/telemetry.go
index 8ad85b0b39982..233450c43d943 100644
--- a/coderd/telemetry/telemetry.go
+++ b/coderd/telemetry/telemetry.go
@@ -868,6 +868,9 @@ func ConvertTemplateVersion(version database.TemplateVersion) TemplateVersion {
if version.TemplateID.Valid {
snapVersion.TemplateID = &version.TemplateID.UUID
}
+ if version.SourceExampleID.Valid {
+ snapVersion.SourceExampleID = &version.SourceExampleID.String
+ }
return snapVersion
}
@@ -1116,11 +1119,12 @@ type Template struct {
}
type TemplateVersion struct {
- ID uuid.UUID `json:"id"`
- CreatedAt time.Time `json:"created_at"`
- TemplateID *uuid.UUID `json:"template_id,omitempty"`
- OrganizationID uuid.UUID `json:"organization_id"`
- JobID uuid.UUID `json:"job_id"`
+ ID uuid.UUID `json:"id"`
+ CreatedAt time.Time `json:"created_at"`
+ TemplateID *uuid.UUID `json:"template_id,omitempty"`
+ OrganizationID uuid.UUID `json:"organization_id"`
+ JobID uuid.UUID `json:"job_id"`
+ SourceExampleID *string `json:"source_example_id,omitempty"`
}
type ProvisionerJob struct {
diff --git a/coderd/telemetry/telemetry_test.go b/coderd/telemetry/telemetry_test.go
index 214d111a170a1..2b70cd2a6d2c3 100644
--- a/coderd/telemetry/telemetry_test.go
+++ b/coderd/telemetry/telemetry_test.go
@@ -1,6 +1,7 @@
package telemetry_test
import (
+ "database/sql"
"encoding/json"
"net/http"
"net/http/httptest"
@@ -48,6 +49,10 @@ func TestTelemetry(t *testing.T) {
_ = dbgen.Template(t, db, database.Template{
Provisioner: database.ProvisionerTypeTerraform,
})
+ sourceExampleID := uuid.NewString()
+ _ = dbgen.TemplateVersion(t, db, database.TemplateVersion{
+ SourceExampleID: sql.NullString{String: sourceExampleID, Valid: true},
+ })
_ = dbgen.TemplateVersion(t, db, database.TemplateVersion{})
user := dbgen.User(t, db, database.User{})
_ = dbgen.Workspace(t, db, database.WorkspaceTable{})
@@ -93,7 +98,7 @@ func TestTelemetry(t *testing.T) {
require.Len(t, snapshot.ProvisionerJobs, 1)
require.Len(t, snapshot.Licenses, 1)
require.Len(t, snapshot.Templates, 1)
- require.Len(t, snapshot.TemplateVersions, 1)
+ require.Len(t, snapshot.TemplateVersions, 2)
require.Len(t, snapshot.Users, 1)
require.Len(t, snapshot.Groups, 2)
// 1 member in the everyone group + 1 member in the custom group
@@ -111,6 +116,17 @@ func TestTelemetry(t *testing.T) {
require.Len(t, wsa.Subsystems, 2)
require.Equal(t, string(database.WorkspaceAgentSubsystemEnvbox), wsa.Subsystems[0])
require.Equal(t, string(database.WorkspaceAgentSubsystemExectrace), wsa.Subsystems[1])
+
+ tvs := snapshot.TemplateVersions
+ sort.Slice(tvs, func(i, j int) bool {
+ // Sort by SourceExampleID presence (non-nil comes before nil)
+ if (tvs[i].SourceExampleID != nil) != (tvs[j].SourceExampleID != nil) {
+ return tvs[i].SourceExampleID != nil
+ }
+ return false
+ })
+ require.Equal(t, tvs[0].SourceExampleID, &sourceExampleID)
+ require.Nil(t, tvs[1].SourceExampleID)
})
t.Run("HashedEmail", func(t *testing.T) {
t.Parallel()
diff --git a/coderd/templateversions.go b/coderd/templateversions.go
index a0609c42c33f9..12def3e5d681b 100644
--- a/coderd/templateversions.go
+++ b/coderd/templateversions.go
@@ -1582,6 +1582,10 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
Readme: "",
JobID: provisionerJob.ID,
CreatedBy: apiKey.UserID,
+ SourceExampleID: sql.NullString{
+ String: req.ExampleID,
+ Valid: req.ExampleID != "",
+ },
})
if err != nil {
if database.IsUniqueViolation(err, database.UniqueTemplateVersionsTemplateIDNameKey) {
diff --git a/coderd/templateversions_test.go b/coderd/templateversions_test.go
index 5ebbd0f41804f..5e96de10d5058 100644
--- a/coderd/templateversions_test.go
+++ b/coderd/templateversions_test.go
@@ -16,6 +16,7 @@ import (
"github.com/coder/coder/v2/coderd/audit"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/database"
+ "github.com/coder/coder/v2/coderd/database/dbauthz"
"github.com/coder/coder/v2/coderd/database/dbtestutil"
"github.com/coder/coder/v2/coderd/externalauth"
"github.com/coder/coder/v2/coderd/rbac"
@@ -134,7 +135,7 @@ func TestPostTemplateVersionsByOrganization(t *testing.T) {
t.Run("WithParameters", func(t *testing.T) {
t.Parallel()
auditor := audit.NewMock()
- client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true, Auditor: auditor})
+ client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{IncludeProvisionerDaemon: true, Auditor: auditor})
user := coderdtest.CreateFirstUser(t, client)
data, err := echo.Tar(&echo.Responses{
Parse: echo.ParseComplete,
@@ -160,11 +161,17 @@ func TestPostTemplateVersionsByOrganization(t *testing.T) {
require.Len(t, auditor.AuditLogs(), 2)
assert.Equal(t, database.AuditActionCreate, auditor.AuditLogs()[1].Action)
+
+ admin, err := client.User(ctx, user.UserID.String())
+ require.NoError(t, err)
+ tvDB, err := db.GetTemplateVersionByID(dbauthz.As(ctx, coderdtest.AuthzUserSubject(admin, user.OrganizationID)), version.ID)
+ require.NoError(t, err)
+ require.False(t, tvDB.SourceExampleID.Valid)
})
t.Run("Example", func(t *testing.T) {
t.Parallel()
- client := coderdtest.New(t, nil)
+ client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
@@ -205,6 +212,12 @@ func TestPostTemplateVersionsByOrganization(t *testing.T) {
require.NoError(t, err)
require.Equal(t, "my-example", tv.Name)
+ admin, err := client.User(ctx, user.UserID.String())
+ require.NoError(t, err)
+ tvDB, err := db.GetTemplateVersionByID(dbauthz.As(ctx, coderdtest.AuthzUserSubject(admin, user.OrganizationID)), tv.ID)
+ require.NoError(t, err)
+ require.Equal(t, ls[0].ID, tvDB.SourceExampleID.String)
+
// ensure the template tar was uploaded correctly
fl, ct, err := client.Download(ctx, tv.Job.FileID)
require.NoError(t, err)
diff --git a/docs/admin/security/audit-logs.md b/docs/admin/security/audit-logs.md
index 3ea4e145d13eb..db214b0e1443e 100644
--- a/docs/admin/security/audit-logs.md
+++ b/docs/admin/security/audit-logs.md
@@ -24,7 +24,7 @@ We track the following resources:
| OAuth2ProviderAppSecret
|
Field | Tracked |
---|
app_id | false |
created_at | false |
display_secret | false |
hashed_secret | false |
id | false |
last_used_at | false |
secret_prefix | false |
|
| Organization
| Field | Tracked |
---|
created_at | false |
description | true |
display_name | true |
icon | true |
id | false |
is_default | true |
name | true |
updated_at | true |
|
| Template
write, delete | Field | Tracked |
---|
active_version_id | true |
activity_bump | true |
allow_user_autostart | true |
allow_user_autostop | true |
allow_user_cancel_workspace_jobs | true |
autostart_block_days_of_week | true |
autostop_requirement_days_of_week | true |
autostop_requirement_weeks | true |
created_at | false |
created_by | true |
created_by_avatar_url | false |
created_by_username | false |
default_ttl | true |
deleted | false |
deprecated | true |
description | true |
display_name | true |
failure_ttl | true |
group_acl | true |
icon | true |
id | true |
max_port_sharing_level | true |
name | true |
organization_display_name | false |
organization_icon | false |
organization_id | false |
organization_name | false |
provisioner | true |
require_active_version | true |
time_til_dormant | true |
time_til_dormant_autodelete | true |
updated_at | false |
user_acl | true |
|
-| TemplateVersion
create, write | Field | Tracked |
---|
archived | true |
created_at | false |
created_by | true |
created_by_avatar_url | false |
created_by_username | false |
external_auth_providers | false |
id | true |
job_id | false |
message | false |
name | true |
organization_id | false |
readme | true |
template_id | true |
updated_at | false |
|
+| TemplateVersion
create, write | Field | Tracked |
---|
archived | true |
created_at | false |
created_by | true |
created_by_avatar_url | false |
created_by_username | false |
external_auth_providers | false |
id | true |
job_id | false |
message | false |
name | true |
organization_id | false |
readme | true |
source_example_id | false |
template_id | true |
updated_at | false |
|
| User
create, write, delete | Field | Tracked |
---|
avatar_url | false |
created_at | false |
deleted | true |
email | true |
github_com_user_id | false |
hashed_one_time_passcode | false |
hashed_password | true |
id | true |
last_seen_at | false |
login_type | true |
name | true |
one_time_passcode_expires_at | true |
quiet_hours_schedule | true |
rbac_roles | true |
status | true |
theme_preference | false |
updated_at | false |
username | true |
|
| WorkspaceBuild
start, stop | Field | Tracked |
---|
build_number | false |
created_at | false |
daily_cost | false |
deadline | false |
id | false |
initiator_by_avatar_url | false |
initiator_by_username | false |
initiator_id | false |
job_id | false |
max_deadline | false |
provisioner_state | false |
reason | false |
template_version_id | true |
transition | false |
updated_at | false |
workspace_id | false |
|
| WorkspaceProxy
| Field | Tracked |
---|
created_at | true |
deleted | false |
derp_enabled | true |
derp_only | true |
display_name | true |
icon | true |
id | true |
name | true |
region_id | true |
token_hashed_secret | true |
updated_at | false |
url | true |
version | true |
wildcard_hostname | true |
|
diff --git a/enterprise/audit/table.go b/enterprise/audit/table.go
index f9e74959f2a28..24f7dfa4b4fe0 100644
--- a/enterprise/audit/table.go
+++ b/enterprise/audit/table.go
@@ -127,6 +127,7 @@ var auditableResourcesTypes = map[any]map[string]Action{
"created_by_avatar_url": ActionIgnore,
"created_by_username": ActionIgnore,
"archived": ActionTrack,
+ "source_example_id": ActionIgnore, // Never changes.
},
&database.User{}: {
"id": ActionTrack,
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy