From 524005b3b73d4eb7074b4d266ba454bfadfeae2b Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 13 Feb 2025 22:54:59 +0000 Subject: [PATCH 01/20] nom --- .../migrations/000293_user_configs.down.sql | 57 +++++++++++++++++ .../migrations/000293_user_configs.up.sql | 62 +++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 coderd/database/migrations/000293_user_configs.down.sql create mode 100644 coderd/database/migrations/000293_user_configs.up.sql diff --git a/coderd/database/migrations/000293_user_configs.down.sql b/coderd/database/migrations/000293_user_configs.down.sql new file mode 100644 index 0000000000000..e3fb8d9403cc7 --- /dev/null +++ b/coderd/database/migrations/000293_user_configs.down.sql @@ -0,0 +1,57 @@ +-- Put back "theme_preference" column +ALTER TABLE users ADD COLUMN IF NOT EXISTS + theme_preference text DEFAULT ''::text NOT NULL; + +-- Copy "theme_preference" back to "users" +UPDATE users (theme_preference) + SELECT value + FROM user_configs + WHERE users.id = user_configs.user_id + AND user_configs.key = 'theme_preference'; + +-- Drop the "user_configs" table. +DROP TABLE user_configs; + +-- Replace "group_members_expanded", and bring back with "theme_preference" +DROP VIEW group_members_expanded; +-- Taken from 000242_group_members_view.up.sql +CREATE VIEW + group_members_expanded +AS +-- If the group is a user made group, then we need to check the group_members table. +-- If it is the "Everyone" group, then we need to check the organization_members table. +WITH all_members AS ( + SELECT user_id, group_id FROM group_members + UNION + SELECT user_id, organization_id AS group_id FROM organization_members +) +SELECT + users.id AS user_id, + users.email AS user_email, + users.username AS user_username, + users.hashed_password AS user_hashed_password, + users.created_at AS user_created_at, + users.updated_at AS user_updated_at, + users.status AS user_status, + users.rbac_roles AS user_rbac_roles, + users.login_type AS user_login_type, + users.avatar_url AS user_avatar_url, + users.deleted AS user_deleted, + users.last_seen_at AS user_last_seen_at, + users.quiet_hours_schedule AS user_quiet_hours_schedule, + users.theme_preference AS user_theme_preference, + users.name AS user_name, + users.github_com_user_id AS user_github_com_user_id, + groups.organization_id AS organization_id, + groups.name AS group_name, + all_members.group_id AS group_id +FROM + all_members +JOIN + users ON users.id = all_members.user_id +JOIN + groups ON groups.id = all_members.group_id +WHERE + users.deleted = 'false'; + +COMMENT ON VIEW group_members_expanded IS 'Joins group members with user information, organization ID, group name. Includes both regular group members and organization members (as part of the "Everyone" group).'; diff --git a/coderd/database/migrations/000293_user_configs.up.sql b/coderd/database/migrations/000293_user_configs.up.sql new file mode 100644 index 0000000000000..931033f419236 --- /dev/null +++ b/coderd/database/migrations/000293_user_configs.up.sql @@ -0,0 +1,62 @@ +CREATE TABLE IF NOT EXISTS user_configs ( + user_id uuid NOT NULL, + key varchar(256) NOT NULL, + value text NOT NULL +); + +ALTER TABLE ONLY user_configs + ADD CONSTRAINT unique_key_per_user UNIQUE (user_id, key); + + +-- +INSERT INTO user_configs (user_id, key, value) + SELECT id, 'theme_preference', theme_preference + FROM users + WHERE users.theme_preference IS NOT NULL; + + +-- Replace "group_members_expanded" without "theme_preference" +DROP VIEW group_members_expanded; +-- Taken from 000242_group_members_view.up.sql +CREATE VIEW + group_members_expanded +AS +-- If the group is a user made group, then we need to check the group_members table. +-- If it is the "Everyone" group, then we need to check the organization_members table. +WITH all_members AS ( + SELECT user_id, group_id FROM group_members + UNION + SELECT user_id, organization_id AS group_id FROM organization_members +) +SELECT + users.id AS user_id, + users.email AS user_email, + users.username AS user_username, + users.hashed_password AS user_hashed_password, + users.created_at AS user_created_at, + users.updated_at AS user_updated_at, + users.status AS user_status, + users.rbac_roles AS user_rbac_roles, + users.login_type AS user_login_type, + users.avatar_url AS user_avatar_url, + users.deleted AS user_deleted, + users.last_seen_at AS user_last_seen_at, + users.quiet_hours_schedule AS user_quiet_hours_schedule, + users.name AS user_name, + users.github_com_user_id AS user_github_com_user_id, + groups.organization_id AS organization_id, + groups.name AS group_name, + all_members.group_id AS group_id +FROM + all_members +JOIN + users ON users.id = all_members.user_id +JOIN + groups ON groups.id = all_members.group_id +WHERE + users.deleted = 'false'; + +COMMENT ON VIEW group_members_expanded IS 'Joins group members with user information, organization ID, group name. Includes both regular group members and organization members (as part of the "Everyone" group).'; + +-- Drop the "theme_preference" column now that the view no longer depends on it. +ALTER TABLE users DROP COLUMN theme_preference; From eadd8508f32fe894779c04a9c8417e19e31b4c27 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 13 Feb 2025 23:58:33 +0000 Subject: [PATCH 02/20] =?UTF-8?q?=F0=9F=A7=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- coderd/audit.go | 1 - coderd/database/db2sdk/db2sdk.go | 16 ++-- coderd/database/dbauthz/dbauthz.go | 8 +- coderd/database/dbauthz/dbauthz_test.go | 12 ++- coderd/database/dbgen/dbgen.go | 1 - coderd/database/dbmem/dbmem.go | 63 ++++++++------- coderd/database/dbmetrics/querymetrics.go | 2 +- coderd/database/dbmock/dbmock.go | 4 +- coderd/database/dump.sql | 13 +++- coderd/database/modelmethods.go | 27 ++++--- coderd/database/modelqueries.go | 2 - coderd/database/models.go | 9 ++- coderd/database/querier.go | 2 +- coderd/database/queries.sql.go | 93 ++++++++--------------- coderd/database/queries/auditlogs.sql | 1 - coderd/database/queries/users.sql | 16 ++-- coderd/database/unique_constraint.go | 1 + coderd/users.go | 3 +- codersdk/users.go | 5 +- site/src/api/typesGenerated.ts | 1 - 20 files changed, 130 insertions(+), 150 deletions(-) diff --git a/coderd/audit.go b/coderd/audit.go index f764094782a2f..8e7e1717f3955 100644 --- a/coderd/audit.go +++ b/coderd/audit.go @@ -204,7 +204,6 @@ func (api *API) convertAuditLog(ctx context.Context, dblog database.GetAuditLogs Deleted: dblog.UserDeleted.Bool, LastSeenAt: dblog.UserLastSeenAt.Time, QuietHoursSchedule: dblog.UserQuietHoursSchedule.String, - ThemePreference: dblog.UserThemePreference.String, Name: dblog.UserName.String, }, []uuid.UUID{}) user = &sdkUser diff --git a/coderd/database/db2sdk/db2sdk.go b/coderd/database/db2sdk/db2sdk.go index 8d2a75960bd0e..ddd5089fcf0d6 100644 --- a/coderd/database/db2sdk/db2sdk.go +++ b/coderd/database/db2sdk/db2sdk.go @@ -149,14 +149,13 @@ func ReducedUser(user database.User) codersdk.ReducedUser { Username: user.Username, AvatarURL: user.AvatarURL, }, - Email: user.Email, - Name: user.Name, - CreatedAt: user.CreatedAt, - UpdatedAt: user.UpdatedAt, - LastSeenAt: user.LastSeenAt, - Status: codersdk.UserStatus(user.Status), - LoginType: codersdk.LoginType(user.LoginType), - ThemePreference: user.ThemePreference, + Email: user.Email, + Name: user.Name, + CreatedAt: user.CreatedAt, + UpdatedAt: user.UpdatedAt, + LastSeenAt: user.LastSeenAt, + Status: codersdk.UserStatus(user.Status), + LoginType: codersdk.LoginType(user.LoginType), } } @@ -175,7 +174,6 @@ func UserFromGroupMember(member database.GroupMember) database.User { Deleted: member.UserDeleted, LastSeenAt: member.UserLastSeenAt, QuietHoursSchedule: member.UserQuietHoursSchedule, - ThemePreference: member.UserThemePreference, Name: member.UserName, GithubComUserID: member.UserGithubComUserID, } diff --git a/coderd/database/dbauthz/dbauthz.go b/coderd/database/dbauthz/dbauthz.go index 545a94b0f678e..0701e2cd972bb 100644 --- a/coderd/database/dbauthz/dbauthz.go +++ b/coderd/database/dbauthz/dbauthz.go @@ -3911,13 +3911,13 @@ func (q *querier) UpdateTemplateWorkspacesLastUsedAt(ctx context.Context, arg da return fetchAndExec(q.log, q.auth, policy.ActionUpdate, fetch, q.db.UpdateTemplateWorkspacesLastUsedAt)(ctx, arg) } -func (q *querier) UpdateUserAppearanceSettings(ctx context.Context, arg database.UpdateUserAppearanceSettingsParams) (database.User, error) { - u, err := q.db.GetUserByID(ctx, arg.ID) +func (q *querier) UpdateUserAppearanceSettings(ctx context.Context, arg database.UpdateUserAppearanceSettingsParams) (database.UserConfig, error) { + u, err := q.db.GetUserByID(ctx, arg.UserID) if err != nil { - return database.User{}, err + return database.UserConfig{}, err } if err := q.authorizeContext(ctx, policy.ActionUpdatePersonal, u); err != nil { - return database.User{}, err + return database.UserConfig{}, err } return q.db.UpdateUserAppearanceSettings(ctx, arg) } diff --git a/coderd/database/dbauthz/dbauthz_test.go b/coderd/database/dbauthz/dbauthz_test.go index 46aa96bf1f7a9..afb87b2d8a8ca 100644 --- a/coderd/database/dbauthz/dbauthz_test.go +++ b/coderd/database/dbauthz/dbauthz_test.go @@ -1523,11 +1523,15 @@ func (s *MethodTestSuite) TestUser() { })) s.Run("UpdateUserAppearanceSettings", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) + uc := database.UserConfig{ + UserID: u.ID, + Key: "theme_preference", + Value: "dark", + } check.Args(database.UpdateUserAppearanceSettingsParams{ - ID: u.ID, - ThemePreference: u.ThemePreference, - UpdatedAt: u.UpdatedAt, - }).Asserts(u, policy.ActionUpdatePersonal).Returns(u) + UserID: u.ID, + ThemePreference: uc.Value, + }).Asserts(u, policy.ActionUpdatePersonal).Returns(uc) })) s.Run("UpdateUserStatus", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) diff --git a/coderd/database/dbgen/dbgen.go b/coderd/database/dbgen/dbgen.go index cfd360f740183..1f9eb841b6930 100644 --- a/coderd/database/dbgen/dbgen.go +++ b/coderd/database/dbgen/dbgen.go @@ -512,7 +512,6 @@ func GroupMember(t testing.TB, db database.Store, member database.GroupMemberTab UserDeleted: user.Deleted, UserLastSeenAt: user.LastSeenAt, UserQuietHoursSchedule: user.QuietHoursSchedule, - UserThemePreference: user.ThemePreference, UserName: user.Name, UserGithubComUserID: user.GithubComUserID, OrganizationID: group.OrganizationID, diff --git a/coderd/database/dbmem/dbmem.go b/coderd/database/dbmem/dbmem.go index 780a180f1ff35..2365617240453 100644 --- a/coderd/database/dbmem/dbmem.go +++ b/coderd/database/dbmem/dbmem.go @@ -55,43 +55,44 @@ func New() database.Store { mutex: &sync.RWMutex{}, data: &data{ apiKeys: make([]database.APIKey, 0), - organizationMembers: make([]database.OrganizationMember, 0), - organizations: make([]database.Organization, 0), - users: make([]database.User, 0), + auditLogs: make([]database.AuditLog, 0), + customRoles: make([]database.CustomRole, 0), dbcryptKeys: make([]database.DBCryptKey, 0), externalAuthLinks: make([]database.ExternalAuthLink, 0), - groups: make([]database.Group, 0), - groupMembers: make([]database.GroupMemberTable, 0), - auditLogs: make([]database.AuditLog, 0), files: make([]database.File, 0), gitSSHKey: make([]database.GitSSHKey, 0), + groups: make([]database.Group, 0), + groupMembers: make([]database.GroupMemberTable, 0), + licenses: make([]database.License, 0), + locks: map[int64]struct{}{}, notificationMessages: make([]database.NotificationMessage, 0), notificationPreferences: make([]database.NotificationPreference, 0), + organizationMembers: make([]database.OrganizationMember, 0), + organizations: make([]database.Organization, 0), parameterSchemas: make([]database.ParameterSchema, 0), + presets: make([]database.TemplateVersionPreset, 0), + presetParameters: make([]database.TemplateVersionPresetParameter, 0), provisionerDaemons: make([]database.ProvisionerDaemon, 0), + provisionerJobs: make([]database.ProvisionerJob, 0), + provisionerJobLogs: make([]database.ProvisionerJobLog, 0), provisionerKeys: make([]database.ProvisionerKey, 0), + runtimeConfig: map[string]string{}, + telemetryItems: make([]database.TelemetryItem, 0), + templateVersions: make([]database.TemplateVersionTable, 0), + templates: make([]database.TemplateTable, 0), + users: make([]database.User, 0), + userConfigs: make([]database.UserConfig, 0), + userStatusChanges: make([]database.UserStatusChange, 0), workspaceAgents: make([]database.WorkspaceAgent, 0), - provisionerJobLogs: make([]database.ProvisionerJobLog, 0), workspaceResources: make([]database.WorkspaceResource, 0), workspaceModules: make([]database.WorkspaceModule, 0), workspaceResourceMetadata: make([]database.WorkspaceResourceMetadatum, 0), - provisionerJobs: make([]database.ProvisionerJob, 0), - templateVersions: make([]database.TemplateVersionTable, 0), - templates: make([]database.TemplateTable, 0), workspaceAgentStats: make([]database.WorkspaceAgentStat, 0), workspaceAgentLogs: make([]database.WorkspaceAgentLog, 0), workspaceBuilds: make([]database.WorkspaceBuild, 0), workspaceApps: make([]database.WorkspaceApp, 0), workspaces: make([]database.WorkspaceTable, 0), - licenses: make([]database.License, 0), workspaceProxies: make([]database.WorkspaceProxy, 0), - customRoles: make([]database.CustomRole, 0), - locks: map[int64]struct{}{}, - runtimeConfig: map[string]string{}, - userStatusChanges: make([]database.UserStatusChange, 0), - telemetryItems: make([]database.TelemetryItem, 0), - presets: make([]database.TemplateVersionPreset, 0), - presetParameters: make([]database.TemplateVersionPresetParameter, 0), }, } // Always start with a default org. Matching migration 198. @@ -222,6 +223,7 @@ type data struct { templateVersionWorkspaceTags []database.TemplateVersionWorkspaceTag templates []database.TemplateTable templateUsageStats []database.TemplateUsageStat + userConfigs []database.UserConfig workspaceAgents []database.WorkspaceAgent workspaceAgentMetadata []database.WorkspaceAgentMetadatum workspaceAgentLogs []database.WorkspaceAgentLog @@ -888,7 +890,6 @@ func (q *FakeQuerier) getGroupMemberNoLock(ctx context.Context, userID, groupID UserDeleted: user.Deleted, UserLastSeenAt: user.LastSeenAt, UserQuietHoursSchedule: user.QuietHoursSchedule, - UserThemePreference: user.ThemePreference, UserName: user.Name, UserGithubComUserID: user.GithubComUserID, OrganizationID: orgID, @@ -10064,24 +10065,31 @@ func (q *FakeQuerier) UpdateTemplateWorkspacesLastUsedAt(_ context.Context, arg return nil } -func (q *FakeQuerier) UpdateUserAppearanceSettings(_ context.Context, arg database.UpdateUserAppearanceSettingsParams) (database.User, error) { +func (q *FakeQuerier) UpdateUserAppearanceSettings(_ context.Context, arg database.UpdateUserAppearanceSettingsParams) (database.UserConfig, error) { err := validateDatabaseType(arg) if err != nil { - return database.User{}, err + return database.UserConfig{}, err } q.mutex.Lock() defer q.mutex.Unlock() - for index, user := range q.users { - if user.ID != arg.ID { + for i, uc := range q.userConfigs { + if uc.UserID != arg.UserID || uc.Key != "theme_preference" { continue } - user.ThemePreference = arg.ThemePreference - q.users[index] = user - return user, nil + uc.Value = arg.ThemePreference + q.userConfigs[i] = uc + return uc, nil } - return database.User{}, sql.ErrNoRows + + uc := database.UserConfig{ + UserID: arg.UserID, + Key: "theme_preference", + Value: arg.ThemePreference, + } + q.userConfigs = append(q.userConfigs, uc) + return uc, nil } func (q *FakeQuerier) UpdateUserDeletedByID(_ context.Context, id uuid.UUID) error { @@ -12437,7 +12445,6 @@ func (q *FakeQuerier) GetAuthorizedAuditLogsOffset(ctx context.Context, arg data UserLastSeenAt: sql.NullTime{Time: user.LastSeenAt, Valid: userValid}, UserLoginType: database.NullLoginType{LoginType: user.LoginType, Valid: userValid}, UserDeleted: sql.NullBool{Bool: user.Deleted, Valid: userValid}, - UserThemePreference: sql.NullString{String: user.ThemePreference, Valid: userValid}, UserQuietHoursSchedule: sql.NullString{String: user.QuietHoursSchedule, Valid: userValid}, UserStatus: database.NullUserStatus{UserStatus: user.Status, Valid: userValid}, UserRoles: user.RBACRoles, diff --git a/coderd/database/dbmetrics/querymetrics.go b/coderd/database/dbmetrics/querymetrics.go index fc84f556aabfb..7d65310ad28d9 100644 --- a/coderd/database/dbmetrics/querymetrics.go +++ b/coderd/database/dbmetrics/querymetrics.go @@ -2471,7 +2471,7 @@ func (m queryMetricsStore) UpdateTemplateWorkspacesLastUsedAt(ctx context.Contex return r0 } -func (m queryMetricsStore) UpdateUserAppearanceSettings(ctx context.Context, arg database.UpdateUserAppearanceSettingsParams) (database.User, error) { +func (m queryMetricsStore) UpdateUserAppearanceSettings(ctx context.Context, arg database.UpdateUserAppearanceSettingsParams) (database.UserConfig, error) { start := time.Now() r0, r1 := m.s.UpdateUserAppearanceSettings(ctx, arg) m.queryLatencies.WithLabelValues("UpdateUserAppearanceSettings").Observe(time.Since(start).Seconds()) diff --git a/coderd/database/dbmock/dbmock.go b/coderd/database/dbmock/dbmock.go index d51631316a3cd..44e6b0f48f257 100644 --- a/coderd/database/dbmock/dbmock.go +++ b/coderd/database/dbmock/dbmock.go @@ -5251,10 +5251,10 @@ func (mr *MockStoreMockRecorder) UpdateTemplateWorkspacesLastUsedAt(ctx, arg any } // UpdateUserAppearanceSettings mocks base method. -func (m *MockStore) UpdateUserAppearanceSettings(ctx context.Context, arg database.UpdateUserAppearanceSettingsParams) (database.User, error) { +func (m *MockStore) UpdateUserAppearanceSettings(ctx context.Context, arg database.UpdateUserAppearanceSettingsParams) (database.UserConfig, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "UpdateUserAppearanceSettings", ctx, arg) - ret0, _ := ret[0].(database.User) + ret0, _ := ret[0].(database.UserConfig) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql index 20e7d14b57d01..f080df4f10ad7 100644 --- a/coderd/database/dump.sql +++ b/coderd/database/dump.sql @@ -764,7 +764,6 @@ CREATE TABLE users ( deleted boolean DEFAULT false NOT NULL, last_seen_at timestamp without time zone DEFAULT '0001-01-01 00:00:00'::timestamp without time zone NOT NULL, quiet_hours_schedule text DEFAULT ''::text NOT NULL, - theme_preference text DEFAULT ''::text NOT NULL, name text DEFAULT ''::text NOT NULL, github_com_user_id bigint, hashed_one_time_passcode bytea, @@ -774,8 +773,6 @@ CREATE TABLE users ( COMMENT ON COLUMN users.quiet_hours_schedule IS 'Daily (!) cron schedule (with optional CRON_TZ) signifying the start of the user''s quiet hours. If empty, the default quiet hours on the instance is used instead.'; -COMMENT ON COLUMN users.theme_preference IS '"" can be interpreted as "the user does not care", falling back to the default theme'; - COMMENT ON COLUMN users.name IS 'Name of the Coder user'; COMMENT ON COLUMN users.github_com_user_id IS 'The GitHub.com numerical user ID. At time of implementation, this is used to check if the user has starred the Coder repository.'; @@ -807,7 +804,6 @@ CREATE VIEW group_members_expanded AS users.deleted AS user_deleted, users.last_seen_at AS user_last_seen_at, users.quiet_hours_schedule AS user_quiet_hours_schedule, - users.theme_preference AS user_theme_preference, users.name AS user_name, users.github_com_user_id AS user_github_com_user_id, groups.organization_id, @@ -1448,6 +1444,12 @@ CREATE VIEW template_with_names AS COMMENT ON VIEW template_with_names IS 'Joins in the display name information such as username, avatar, and organization name.'; +CREATE TABLE user_configs ( + user_id uuid NOT NULL, + key character varying(256) NOT NULL, + value text NOT NULL +); + CREATE TABLE user_deleted ( id uuid DEFAULT gen_random_uuid() NOT NULL, user_id uuid NOT NULL, @@ -2094,6 +2096,9 @@ ALTER TABLE ONLY template_versions ALTER TABLE ONLY templates ADD CONSTRAINT templates_pkey PRIMARY KEY (id); +ALTER TABLE ONLY user_configs + ADD CONSTRAINT unique_key_per_user UNIQUE (user_id, key); + ALTER TABLE ONLY user_deleted ADD CONSTRAINT user_deleted_pkey PRIMARY KEY (id); diff --git a/coderd/database/modelmethods.go b/coderd/database/modelmethods.go index 63e03ccb27f40..025469316cdb8 100644 --- a/coderd/database/modelmethods.go +++ b/coderd/database/modelmethods.go @@ -398,20 +398,19 @@ func ConvertUserRows(rows []GetUsersRow) []User { users := make([]User, len(rows)) for i, r := range rows { users[i] = User{ - ID: r.ID, - Email: r.Email, - Username: r.Username, - Name: r.Name, - HashedPassword: r.HashedPassword, - CreatedAt: r.CreatedAt, - UpdatedAt: r.UpdatedAt, - Status: r.Status, - RBACRoles: r.RBACRoles, - LoginType: r.LoginType, - AvatarURL: r.AvatarURL, - Deleted: r.Deleted, - LastSeenAt: r.LastSeenAt, - ThemePreference: r.ThemePreference, + ID: r.ID, + Email: r.Email, + Username: r.Username, + Name: r.Name, + HashedPassword: r.HashedPassword, + CreatedAt: r.CreatedAt, + UpdatedAt: r.UpdatedAt, + Status: r.Status, + RBACRoles: r.RBACRoles, + LoginType: r.LoginType, + AvatarURL: r.AvatarURL, + Deleted: r.Deleted, + LastSeenAt: r.LastSeenAt, } } diff --git a/coderd/database/modelqueries.go b/coderd/database/modelqueries.go index 78f6285e3c11a..c5646ea61394d 100644 --- a/coderd/database/modelqueries.go +++ b/coderd/database/modelqueries.go @@ -417,7 +417,6 @@ func (q *sqlQuerier) GetAuthorizedUsers(ctx context.Context, arg GetUsersParams, &i.Deleted, &i.LastSeenAt, &i.QuietHoursSchedule, - &i.ThemePreference, &i.Name, &i.GithubComUserID, &i.HashedOneTimePasscode, @@ -504,7 +503,6 @@ func (q *sqlQuerier) GetAuthorizedAuditLogsOffset(ctx context.Context, arg GetAu &i.UserRoles, &i.UserAvatarUrl, &i.UserDeleted, - &i.UserThemePreference, &i.UserQuietHoursSchedule, &i.OrganizationName, &i.OrganizationDisplayName, diff --git a/coderd/database/models.go b/coderd/database/models.go index fc11e1f4f5ebe..1d07d8637d1b0 100644 --- a/coderd/database/models.go +++ b/coderd/database/models.go @@ -2468,7 +2468,6 @@ type GroupMember struct { UserDeleted bool `db:"user_deleted" json:"user_deleted"` UserLastSeenAt time.Time `db:"user_last_seen_at" json:"user_last_seen_at"` UserQuietHoursSchedule string `db:"user_quiet_hours_schedule" json:"user_quiet_hours_schedule"` - UserThemePreference string `db:"user_theme_preference" json:"user_theme_preference"` UserName string `db:"user_name" json:"user_name"` UserGithubComUserID sql.NullInt64 `db:"user_github_com_user_id" json:"user_github_com_user_id"` OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"` @@ -3025,8 +3024,6 @@ type User struct { LastSeenAt time.Time `db:"last_seen_at" json:"last_seen_at"` // Daily (!) cron schedule (with optional CRON_TZ) signifying the start of the user's quiet hours. If empty, the default quiet hours on the instance is used instead. QuietHoursSchedule string `db:"quiet_hours_schedule" json:"quiet_hours_schedule"` - // "" can be interpreted as "the user does not care", falling back to the default theme - ThemePreference string `db:"theme_preference" json:"theme_preference"` // Name of the Coder user Name string `db:"name" json:"name"` // The GitHub.com numerical user ID. At time of implementation, this is used to check if the user has starred the Coder repository. @@ -3037,6 +3034,12 @@ type User struct { OneTimePasscodeExpiresAt sql.NullTime `db:"one_time_passcode_expires_at" json:"one_time_passcode_expires_at"` } +type UserConfig struct { + UserID uuid.UUID `db:"user_id" json:"user_id"` + Key string `db:"key" json:"key"` + Value string `db:"value" json:"value"` +} + // Tracks when users were deleted type UserDeleted struct { ID uuid.UUID `db:"id" json:"id"` diff --git a/coderd/database/querier.go b/coderd/database/querier.go index 5f9856028b985..8ad30a5304169 100644 --- a/coderd/database/querier.go +++ b/coderd/database/querier.go @@ -498,7 +498,7 @@ type sqlcQuerier interface { UpdateTemplateVersionDescriptionByJobID(ctx context.Context, arg UpdateTemplateVersionDescriptionByJobIDParams) error UpdateTemplateVersionExternalAuthProvidersByJobID(ctx context.Context, arg UpdateTemplateVersionExternalAuthProvidersByJobIDParams) error UpdateTemplateWorkspacesLastUsedAt(ctx context.Context, arg UpdateTemplateWorkspacesLastUsedAtParams) error - UpdateUserAppearanceSettings(ctx context.Context, arg UpdateUserAppearanceSettingsParams) (User, error) + UpdateUserAppearanceSettings(ctx context.Context, arg UpdateUserAppearanceSettingsParams) (UserConfig, error) UpdateUserDeletedByID(ctx context.Context, id uuid.UUID) error UpdateUserGithubComUserID(ctx context.Context, arg UpdateUserGithubComUserIDParams) error UpdateUserHashedOneTimePasscode(ctx context.Context, arg UpdateUserHashedOneTimePasscodeParams) error diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index d8c2b3a77dacf..70f3d65486af1 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -457,7 +457,6 @@ SELECT users.rbac_roles AS user_roles, users.avatar_url AS user_avatar_url, users.deleted AS user_deleted, - users.theme_preference AS user_theme_preference, users.quiet_hours_schedule AS user_quiet_hours_schedule, COALESCE(organizations.name, '') AS organization_name, COALESCE(organizations.display_name, '') AS organization_display_name, @@ -601,7 +600,6 @@ type GetAuditLogsOffsetRow struct { UserRoles pq.StringArray `db:"user_roles" json:"user_roles"` UserAvatarUrl sql.NullString `db:"user_avatar_url" json:"user_avatar_url"` UserDeleted sql.NullBool `db:"user_deleted" json:"user_deleted"` - UserThemePreference sql.NullString `db:"user_theme_preference" json:"user_theme_preference"` UserQuietHoursSchedule sql.NullString `db:"user_quiet_hours_schedule" json:"user_quiet_hours_schedule"` OrganizationName string `db:"organization_name" json:"organization_name"` OrganizationDisplayName string `db:"organization_display_name" json:"organization_display_name"` @@ -661,7 +659,6 @@ func (q *sqlQuerier) GetAuditLogsOffset(ctx context.Context, arg GetAuditLogsOff &i.UserRoles, &i.UserAvatarUrl, &i.UserDeleted, - &i.UserThemePreference, &i.UserQuietHoursSchedule, &i.OrganizationName, &i.OrganizationDisplayName, @@ -1574,7 +1571,7 @@ func (q *sqlQuerier) DeleteGroupMemberFromGroup(ctx context.Context, arg DeleteG } const getGroupMembers = `-- name: GetGroupMembers :many -SELECT user_id, user_email, user_username, user_hashed_password, user_created_at, user_updated_at, user_status, user_rbac_roles, user_login_type, user_avatar_url, user_deleted, user_last_seen_at, user_quiet_hours_schedule, user_theme_preference, user_name, user_github_com_user_id, organization_id, group_name, group_id FROM group_members_expanded +SELECT user_id, user_email, user_username, user_hashed_password, user_created_at, user_updated_at, user_status, user_rbac_roles, user_login_type, user_avatar_url, user_deleted, user_last_seen_at, user_quiet_hours_schedule, user_name, user_github_com_user_id, organization_id, group_name, group_id FROM group_members_expanded ` func (q *sqlQuerier) GetGroupMembers(ctx context.Context) ([]GroupMember, error) { @@ -1600,7 +1597,6 @@ func (q *sqlQuerier) GetGroupMembers(ctx context.Context) ([]GroupMember, error) &i.UserDeleted, &i.UserLastSeenAt, &i.UserQuietHoursSchedule, - &i.UserThemePreference, &i.UserName, &i.UserGithubComUserID, &i.OrganizationID, @@ -1621,7 +1617,7 @@ func (q *sqlQuerier) GetGroupMembers(ctx context.Context) ([]GroupMember, error) } const getGroupMembersByGroupID = `-- name: GetGroupMembersByGroupID :many -SELECT user_id, user_email, user_username, user_hashed_password, user_created_at, user_updated_at, user_status, user_rbac_roles, user_login_type, user_avatar_url, user_deleted, user_last_seen_at, user_quiet_hours_schedule, user_theme_preference, user_name, user_github_com_user_id, organization_id, group_name, group_id FROM group_members_expanded WHERE group_id = $1 +SELECT user_id, user_email, user_username, user_hashed_password, user_created_at, user_updated_at, user_status, user_rbac_roles, user_login_type, user_avatar_url, user_deleted, user_last_seen_at, user_quiet_hours_schedule, user_name, user_github_com_user_id, organization_id, group_name, group_id FROM group_members_expanded WHERE group_id = $1 ` func (q *sqlQuerier) GetGroupMembersByGroupID(ctx context.Context, groupID uuid.UUID) ([]GroupMember, error) { @@ -1647,7 +1643,6 @@ func (q *sqlQuerier) GetGroupMembersByGroupID(ctx context.Context, groupID uuid. &i.UserDeleted, &i.UserLastSeenAt, &i.UserQuietHoursSchedule, - &i.UserThemePreference, &i.UserName, &i.UserGithubComUserID, &i.OrganizationID, @@ -7427,7 +7422,7 @@ FROM ( -- Select all groups this user is a member of. This will also include -- the "Everyone" group for organizations the user is a member of. - SELECT user_id, user_email, user_username, user_hashed_password, user_created_at, user_updated_at, user_status, user_rbac_roles, user_login_type, user_avatar_url, user_deleted, user_last_seen_at, user_quiet_hours_schedule, user_theme_preference, user_name, user_github_com_user_id, organization_id, group_name, group_id FROM group_members_expanded + SELECT user_id, user_email, user_username, user_hashed_password, user_created_at, user_updated_at, user_status, user_rbac_roles, user_login_type, user_avatar_url, user_deleted, user_last_seen_at, user_quiet_hours_schedule, user_name, user_github_com_user_id, organization_id, group_name, group_id FROM group_members_expanded WHERE $1 = user_id AND $2 = group_members_expanded.organization_id @@ -10972,7 +10967,7 @@ func (q *sqlQuerier) GetAuthorizationUserRoles(ctx context.Context, userID uuid. const getUserByEmailOrUsername = `-- name: GetUserByEmailOrUsername :one SELECT - id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, theme_preference, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at + id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at FROM users WHERE @@ -11004,7 +10999,6 @@ func (q *sqlQuerier) GetUserByEmailOrUsername(ctx context.Context, arg GetUserBy &i.Deleted, &i.LastSeenAt, &i.QuietHoursSchedule, - &i.ThemePreference, &i.Name, &i.GithubComUserID, &i.HashedOneTimePasscode, @@ -11015,7 +11009,7 @@ func (q *sqlQuerier) GetUserByEmailOrUsername(ctx context.Context, arg GetUserBy const getUserByID = `-- name: GetUserByID :one SELECT - id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, theme_preference, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at + id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at FROM users WHERE @@ -11041,7 +11035,6 @@ func (q *sqlQuerier) GetUserByID(ctx context.Context, id uuid.UUID) (User, error &i.Deleted, &i.LastSeenAt, &i.QuietHoursSchedule, - &i.ThemePreference, &i.Name, &i.GithubComUserID, &i.HashedOneTimePasscode, @@ -11068,7 +11061,7 @@ func (q *sqlQuerier) GetUserCount(ctx context.Context) (int64, error) { const getUsers = `-- name: GetUsers :many SELECT - id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, theme_preference, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at, COUNT(*) OVER() AS count + id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at, COUNT(*) OVER() AS count FROM users WHERE @@ -11178,7 +11171,6 @@ type GetUsersRow struct { Deleted bool `db:"deleted" json:"deleted"` LastSeenAt time.Time `db:"last_seen_at" json:"last_seen_at"` QuietHoursSchedule string `db:"quiet_hours_schedule" json:"quiet_hours_schedule"` - ThemePreference string `db:"theme_preference" json:"theme_preference"` Name string `db:"name" json:"name"` GithubComUserID sql.NullInt64 `db:"github_com_user_id" json:"github_com_user_id"` HashedOneTimePasscode []byte `db:"hashed_one_time_passcode" json:"hashed_one_time_passcode"` @@ -11221,7 +11213,6 @@ func (q *sqlQuerier) GetUsers(ctx context.Context, arg GetUsersParams) ([]GetUse &i.Deleted, &i.LastSeenAt, &i.QuietHoursSchedule, - &i.ThemePreference, &i.Name, &i.GithubComUserID, &i.HashedOneTimePasscode, @@ -11242,7 +11233,7 @@ func (q *sqlQuerier) GetUsers(ctx context.Context, arg GetUsersParams) ([]GetUse } const getUsersByIDs = `-- name: GetUsersByIDs :many -SELECT id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, theme_preference, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at FROM users WHERE id = ANY($1 :: uuid [ ]) +SELECT id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at FROM users WHERE id = ANY($1 :: uuid [ ]) ` // This shouldn't check for deleted, because it's frequently used @@ -11271,7 +11262,6 @@ func (q *sqlQuerier) GetUsersByIDs(ctx context.Context, ids []uuid.UUID) ([]User &i.Deleted, &i.LastSeenAt, &i.QuietHoursSchedule, - &i.ThemePreference, &i.Name, &i.GithubComUserID, &i.HashedOneTimePasscode, @@ -11309,7 +11299,7 @@ VALUES -- if the status passed in is empty, fallback to dormant, which is what -- we were doing before. COALESCE(NULLIF($10::text, '')::user_status, 'dormant'::user_status) - ) RETURNING id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, theme_preference, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at + ) RETURNING id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at ` type InsertUserParams struct { @@ -11353,7 +11343,6 @@ func (q *sqlQuerier) InsertUser(ctx context.Context, arg InsertUserParams) (User &i.Deleted, &i.LastSeenAt, &i.QuietHoursSchedule, - &i.ThemePreference, &i.Name, &i.GithubComUserID, &i.HashedOneTimePasscode, @@ -11415,45 +11404,29 @@ func (q *sqlQuerier) UpdateInactiveUsersToDormant(ctx context.Context, arg Updat } const updateUserAppearanceSettings = `-- name: UpdateUserAppearanceSettings :one -UPDATE - users +INSERT INTO + user_configs (user_id, key, value) +VALUES + ($1, 'theme_preference', $2) +ON CONFLICT + ON CONSTRAINT unique_key_per_user +DO UPDATE SET - theme_preference = $2, - updated_at = $3 -WHERE - id = $1 -RETURNING id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, theme_preference, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at + value = $2 +WHERE user_configs.user_id = $1 + AND user_configs.key = 'theme_preference' +RETURNING user_id, key, value ` type UpdateUserAppearanceSettingsParams struct { - ID uuid.UUID `db:"id" json:"id"` + UserID uuid.UUID `db:"user_id" json:"user_id"` ThemePreference string `db:"theme_preference" json:"theme_preference"` - UpdatedAt time.Time `db:"updated_at" json:"updated_at"` } -func (q *sqlQuerier) UpdateUserAppearanceSettings(ctx context.Context, arg UpdateUserAppearanceSettingsParams) (User, error) { - row := q.db.QueryRowContext(ctx, updateUserAppearanceSettings, arg.ID, arg.ThemePreference, arg.UpdatedAt) - var i User - err := row.Scan( - &i.ID, - &i.Email, - &i.Username, - &i.HashedPassword, - &i.CreatedAt, - &i.UpdatedAt, - &i.Status, - &i.RBACRoles, - &i.LoginType, - &i.AvatarURL, - &i.Deleted, - &i.LastSeenAt, - &i.QuietHoursSchedule, - &i.ThemePreference, - &i.Name, - &i.GithubComUserID, - &i.HashedOneTimePasscode, - &i.OneTimePasscodeExpiresAt, - ) +func (q *sqlQuerier) UpdateUserAppearanceSettings(ctx context.Context, arg UpdateUserAppearanceSettingsParams) (UserConfig, error) { + row := q.db.QueryRowContext(ctx, updateUserAppearanceSettings, arg.UserID, arg.ThemePreference) + var i UserConfig + err := row.Scan(&i.UserID, &i.Key, &i.Value) return i, err } @@ -11539,7 +11512,7 @@ SET last_seen_at = $2, updated_at = $3 WHERE - id = $1 RETURNING id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, theme_preference, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at + id = $1 RETURNING id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at ` type UpdateUserLastSeenAtParams struct { @@ -11565,7 +11538,6 @@ func (q *sqlQuerier) UpdateUserLastSeenAt(ctx context.Context, arg UpdateUserLas &i.Deleted, &i.LastSeenAt, &i.QuietHoursSchedule, - &i.ThemePreference, &i.Name, &i.GithubComUserID, &i.HashedOneTimePasscode, @@ -11587,7 +11559,7 @@ SET '':: bytea END WHERE - id = $2 RETURNING id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, theme_preference, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at + id = $2 RETURNING id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at ` type UpdateUserLoginTypeParams struct { @@ -11612,7 +11584,6 @@ func (q *sqlQuerier) UpdateUserLoginType(ctx context.Context, arg UpdateUserLogi &i.Deleted, &i.LastSeenAt, &i.QuietHoursSchedule, - &i.ThemePreference, &i.Name, &i.GithubComUserID, &i.HashedOneTimePasscode, @@ -11632,7 +11603,7 @@ SET name = $6 WHERE id = $1 -RETURNING id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, theme_preference, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at +RETURNING id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at ` type UpdateUserProfileParams struct { @@ -11668,7 +11639,6 @@ func (q *sqlQuerier) UpdateUserProfile(ctx context.Context, arg UpdateUserProfil &i.Deleted, &i.LastSeenAt, &i.QuietHoursSchedule, - &i.ThemePreference, &i.Name, &i.GithubComUserID, &i.HashedOneTimePasscode, @@ -11684,7 +11654,7 @@ SET quiet_hours_schedule = $2 WHERE id = $1 -RETURNING id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, theme_preference, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at +RETURNING id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at ` type UpdateUserQuietHoursScheduleParams struct { @@ -11709,7 +11679,6 @@ func (q *sqlQuerier) UpdateUserQuietHoursSchedule(ctx context.Context, arg Updat &i.Deleted, &i.LastSeenAt, &i.QuietHoursSchedule, - &i.ThemePreference, &i.Name, &i.GithubComUserID, &i.HashedOneTimePasscode, @@ -11726,7 +11695,7 @@ SET rbac_roles = ARRAY(SELECT DISTINCT UNNEST($1 :: text[])) WHERE id = $2 -RETURNING id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, theme_preference, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at +RETURNING id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at ` type UpdateUserRolesParams struct { @@ -11751,7 +11720,6 @@ func (q *sqlQuerier) UpdateUserRoles(ctx context.Context, arg UpdateUserRolesPar &i.Deleted, &i.LastSeenAt, &i.QuietHoursSchedule, - &i.ThemePreference, &i.Name, &i.GithubComUserID, &i.HashedOneTimePasscode, @@ -11767,7 +11735,7 @@ SET status = $2, updated_at = $3 WHERE - id = $1 RETURNING id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, theme_preference, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at + id = $1 RETURNING id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at ` type UpdateUserStatusParams struct { @@ -11793,7 +11761,6 @@ func (q *sqlQuerier) UpdateUserStatus(ctx context.Context, arg UpdateUserStatusP &i.Deleted, &i.LastSeenAt, &i.QuietHoursSchedule, - &i.ThemePreference, &i.Name, &i.GithubComUserID, &i.HashedOneTimePasscode, diff --git a/coderd/database/queries/auditlogs.sql b/coderd/database/queries/auditlogs.sql index 115bdcd4c8f6f..d23c90d7ce878 100644 --- a/coderd/database/queries/auditlogs.sql +++ b/coderd/database/queries/auditlogs.sql @@ -16,7 +16,6 @@ SELECT users.rbac_roles AS user_roles, users.avatar_url AS user_avatar_url, users.deleted AS user_deleted, - users.theme_preference AS user_theme_preference, users.quiet_hours_schedule AS user_quiet_hours_schedule, COALESCE(organizations.name, '') AS organization_name, COALESCE(organizations.display_name, '') AS organization_display_name, diff --git a/coderd/database/queries/users.sql b/coderd/database/queries/users.sql index 1f30a2c2c1d24..3caef9e70945a 100644 --- a/coderd/database/queries/users.sql +++ b/coderd/database/queries/users.sql @@ -99,13 +99,17 @@ WHERE id = $1; -- name: UpdateUserAppearanceSettings :one -UPDATE - users +INSERT INTO + user_configs (user_id, key, value) +VALUES + (@user_id, 'theme_preference', @theme_preference) +ON CONFLICT + ON CONSTRAINT unique_key_per_user +DO UPDATE SET - theme_preference = $2, - updated_at = $3 -WHERE - id = $1 + value = @theme_preference +WHERE user_configs.user_id = @user_id + AND user_configs.key = 'theme_preference' RETURNING *; -- name: UpdateUserRoles :one diff --git a/coderd/database/unique_constraint.go b/coderd/database/unique_constraint.go index ce427cf97c3bc..2132068aefe03 100644 --- a/coderd/database/unique_constraint.go +++ b/coderd/database/unique_constraint.go @@ -65,6 +65,7 @@ const ( UniqueTemplateVersionsPkey UniqueConstraint = "template_versions_pkey" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_pkey PRIMARY KEY (id); UniqueTemplateVersionsTemplateIDNameKey UniqueConstraint = "template_versions_template_id_name_key" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_template_id_name_key UNIQUE (template_id, name); UniqueTemplatesPkey UniqueConstraint = "templates_pkey" // ALTER TABLE ONLY templates ADD CONSTRAINT templates_pkey PRIMARY KEY (id); + UniqueUniqueKeyPerUser UniqueConstraint = "unique_key_per_user" // ALTER TABLE ONLY user_configs ADD CONSTRAINT unique_key_per_user UNIQUE (user_id, key); UniqueUserDeletedPkey UniqueConstraint = "user_deleted_pkey" // ALTER TABLE ONLY user_deleted ADD CONSTRAINT user_deleted_pkey PRIMARY KEY (id); UniqueUserLinksPkey UniqueConstraint = "user_links_pkey" // ALTER TABLE ONLY user_links ADD CONSTRAINT user_links_pkey PRIMARY KEY (user_id, login_type); UniqueUserStatusChangesPkey UniqueConstraint = "user_status_changes_pkey" // ALTER TABLE ONLY user_status_changes ADD CONSTRAINT user_status_changes_pkey PRIMARY KEY (id); diff --git a/coderd/users.go b/coderd/users.go index 964f18724449a..b379f5fbbbc2e 100644 --- a/coderd/users.go +++ b/coderd/users.go @@ -995,9 +995,8 @@ func (api *API) putUserAppearanceSettings(rw http.ResponseWriter, r *http.Reques } updatedUser, err := api.Database.UpdateUserAppearanceSettings(ctx, database.UpdateUserAppearanceSettingsParams{ - ID: user.ID, + UserID: user.ID, ThemePreference: params.ThemePreference, - UpdatedAt: dbtime.Now(), }) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ diff --git a/codersdk/users.go b/codersdk/users.go index 4dbdc0d4e4f91..db8f6e7f6d6de 100644 --- a/codersdk/users.go +++ b/codersdk/users.go @@ -54,9 +54,8 @@ type ReducedUser struct { UpdatedAt time.Time `json:"updated_at" table:"updated at" format:"date-time"` LastSeenAt time.Time `json:"last_seen_at" format:"date-time"` - Status UserStatus `json:"status" table:"status" enums:"active,suspended"` - LoginType LoginType `json:"login_type"` - ThemePreference string `json:"theme_preference"` + Status UserStatus `json:"status" table:"status" enums:"active,suspended"` + LoginType LoginType `json:"login_type"` } // User represents a user in Coder. diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 50b45ccd4d22f..d6f8c44c7e967 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1934,7 +1934,6 @@ export interface ReducedUser extends MinimalUser { readonly last_seen_at: string; readonly status: UserStatus; readonly login_type: LoginType; - readonly theme_preference: string; } // From codersdk/workspaceproxy.go From 4467aec2a83368a2a26a1e86e9399a3cf605ca16 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Fri, 14 Feb 2025 00:11:16 +0000 Subject: [PATCH 03/20] :) --- coderd/apidoc/docs.go | 19 ++++++------ coderd/apidoc/swagger.json | 19 ++++++------ coderd/users.go | 17 ++++------- codersdk/users.go | 4 +++ docs/admin/security/audit-logs.md | 2 +- docs/reference/api/audit.md | 1 - docs/reference/api/enterprise.md | 16 ---------- docs/reference/api/schemas.md | 50 ++++++++++++++++--------------- docs/reference/api/users.md | 36 +++------------------- enterprise/audit/table.go | 1 - site/src/api/typesGenerated.ts | 5 ++++ 11 files changed, 63 insertions(+), 107 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 6f09a0482dbd1..70803d6313c3d 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -6353,7 +6353,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/codersdk.User" + "$ref": "#/definitions/codersdk.UserAppearanceSettings" } } } @@ -13738,9 +13738,6 @@ const docTemplate = `{ } ] }, - "theme_preference": { - "type": "string" - }, "updated_at": { "type": "string", "format": "date-time" @@ -14601,9 +14598,6 @@ const docTemplate = `{ } ] }, - "theme_preference": { - "type": "string" - }, "updated_at": { "type": "string", "format": "date-time" @@ -15211,9 +15205,6 @@ const docTemplate = `{ } ] }, - "theme_preference": { - "type": "string" - }, "updated_at": { "type": "string", "format": "date-time" @@ -15284,6 +15275,14 @@ const docTemplate = `{ } } }, + "codersdk.UserAppearanceSettings": { + "type": "object", + "properties": { + "theme_preference": { + "type": "string" + } + } + }, "codersdk.UserLatency": { "type": "object", "properties": { diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index db682394ca04a..a31b69a8524bc 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -5605,7 +5605,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/codersdk.User" + "$ref": "#/definitions/codersdk.UserAppearanceSettings" } } } @@ -12425,9 +12425,6 @@ } ] }, - "theme_preference": { - "type": "string" - }, "updated_at": { "type": "string", "format": "date-time" @@ -13263,9 +13260,6 @@ } ] }, - "theme_preference": { - "type": "string" - }, "updated_at": { "type": "string", "format": "date-time" @@ -13825,9 +13819,6 @@ } ] }, - "theme_preference": { - "type": "string" - }, "updated_at": { "type": "string", "format": "date-time" @@ -13898,6 +13889,14 @@ } } }, + "codersdk.UserAppearanceSettings": { + "type": "object", + "properties": { + "theme_preference": { + "type": "string" + } + } + }, "codersdk.UserLatency": { "type": "object", "properties": { diff --git a/coderd/users.go b/coderd/users.go index b379f5fbbbc2e..fef791203d32d 100644 --- a/coderd/users.go +++ b/coderd/users.go @@ -981,7 +981,7 @@ func (api *API) notifyUserStatusChanged(ctx context.Context, actingUserName stri // @Tags Users // @Param user path string true "User ID, name, or me" // @Param request body codersdk.UpdateUserAppearanceSettingsRequest true "New appearance settings" -// @Success 200 {object} codersdk.User +// @Success 200 {object} codersdk.UserAppearanceSettings // @Router /users/{user}/appearance [put] func (api *API) putUserAppearanceSettings(rw http.ResponseWriter, r *http.Request) { var ( @@ -994,7 +994,7 @@ func (api *API) putUserAppearanceSettings(rw http.ResponseWriter, r *http.Reques return } - updatedUser, err := api.Database.UpdateUserAppearanceSettings(ctx, database.UpdateUserAppearanceSettingsParams{ + updatedSettings, err := api.Database.UpdateUserAppearanceSettings(ctx, database.UpdateUserAppearanceSettingsParams{ UserID: user.ID, ThemePreference: params.ThemePreference, }) @@ -1006,16 +1006,9 @@ func (api *API) putUserAppearanceSettings(rw http.ResponseWriter, r *http.Reques return } - organizationIDs, err := userOrganizationIDs(ctx, api, user) - if err != nil { - httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ - Message: "Internal error fetching user's organizations.", - Detail: err.Error(), - }) - return - } - - httpapi.Write(ctx, rw, http.StatusOK, db2sdk.User(updatedUser, organizationIDs)) + httpapi.Write(ctx, rw, http.StatusOK, codersdk.UserAppearanceSettings{ + ThemePreference: updatedSettings.Value, + }) } // @Summary Update user password diff --git a/codersdk/users.go b/codersdk/users.go index db8f6e7f6d6de..933a43460836a 100644 --- a/codersdk/users.go +++ b/codersdk/users.go @@ -186,6 +186,10 @@ type ValidateUserPasswordResponse struct { Details string `json:"details"` } +type UserAppearanceSettings struct { + ThemePreference string `json:"theme_preference"` +} + type UpdateUserAppearanceSettingsRequest struct { ThemePreference string `json:"theme_preference" validate:"required"` } diff --git a/docs/admin/security/audit-logs.md b/docs/admin/security/audit-logs.md index 2131e7746d2d6..852c8e86b2809 100644 --- a/docs/admin/security/audit-logs.md +++ b/docs/admin/security/audit-logs.md @@ -28,7 +28,7 @@ We track the following resources: | RoleSyncSettings
| |
FieldTracked
fieldtrue
mappingtrue
| | Template
write, delete | |
FieldTracked
active_version_idtrue
activity_bumptrue
allow_user_autostarttrue
allow_user_autostoptrue
allow_user_cancel_workspace_jobstrue
autostart_block_days_of_weektrue
autostop_requirement_days_of_weektrue
autostop_requirement_weekstrue
created_atfalse
created_bytrue
created_by_avatar_urlfalse
created_by_usernamefalse
default_ttltrue
deletedfalse
deprecatedtrue
descriptiontrue
display_nametrue
failure_ttltrue
group_acltrue
icontrue
idtrue
max_port_sharing_leveltrue
nametrue
organization_display_namefalse
organization_iconfalse
organization_idfalse
organization_namefalse
provisionertrue
require_active_versiontrue
time_til_dormanttrue
time_til_dormant_autodeletetrue
updated_atfalse
user_acltrue
| | TemplateVersion
create, write | |
FieldTracked
archivedtrue
created_atfalse
created_bytrue
created_by_avatar_urlfalse
created_by_usernamefalse
external_auth_providersfalse
idtrue
job_idfalse
messagefalse
nametrue
organization_idfalse
readmetrue
source_example_idfalse
template_idtrue
updated_atfalse
| -| User
create, write, delete | |
FieldTracked
avatar_urlfalse
created_atfalse
deletedtrue
emailtrue
github_com_user_idfalse
hashed_one_time_passcodefalse
hashed_passwordtrue
idtrue
last_seen_atfalse
login_typetrue
nametrue
one_time_passcode_expires_attrue
quiet_hours_scheduletrue
rbac_rolestrue
statustrue
theme_preferencefalse
updated_atfalse
usernametrue
| +| User
create, write, delete | |
FieldTracked
avatar_urlfalse
created_atfalse
deletedtrue
emailtrue
github_com_user_idfalse
hashed_one_time_passcodefalse
hashed_passwordtrue
idtrue
last_seen_atfalse
login_typetrue
nametrue
one_time_passcode_expires_attrue
quiet_hours_scheduletrue
rbac_rolestrue
statustrue
updated_atfalse
usernametrue
| | WorkspaceBuild
start, stop | |
FieldTracked
build_numberfalse
created_atfalse
daily_costfalse
deadlinefalse
idfalse
initiator_by_avatar_urlfalse
initiator_by_usernamefalse
initiator_idfalse
job_idfalse
max_deadlinefalse
provisioner_statefalse
reasonfalse
template_version_idtrue
template_version_preset_idfalse
transitionfalse
updated_atfalse
workspace_idfalse
| | WorkspaceProxy
| |
FieldTracked
created_attrue
deletedfalse
derp_enabledtrue
derp_onlytrue
display_nametrue
icontrue
idtrue
nametrue
region_idtrue
token_hashed_secrettrue
updated_atfalse
urltrue
versiontrue
wildcard_hostnametrue
| | WorkspaceTable
| |
FieldTracked
automatic_updatestrue
autostart_scheduletrue
created_atfalse
deletedfalse
deleting_attrue
dormant_attrue
favoritetrue
idtrue
last_used_atfalse
nametrue
next_start_attrue
organization_idfalse
owner_idtrue
template_idtrue
ttltrue
updated_atfalse
| diff --git a/docs/reference/api/audit.md b/docs/reference/api/audit.md index 3fc6e746f17c8..af13e9049d0b4 100644 --- a/docs/reference/api/audit.md +++ b/docs/reference/api/audit.md @@ -83,7 +83,6 @@ curl -X GET http://coder-server:8080/api/v2/audit?limit=0 \ } ], "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" }, diff --git a/docs/reference/api/enterprise.md b/docs/reference/api/enterprise.md index 282cf20ab252d..c18b0d5478b5e 100644 --- a/docs/reference/api/enterprise.md +++ b/docs/reference/api/enterprise.md @@ -219,7 +219,6 @@ curl -X GET http://coder-server:8080/api/v2/groups?organization=string&has_membe "login_type": "", "name": "string", "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -260,7 +259,6 @@ Status Code **200** | `»» login_type` | [codersdk.LoginType](schemas.md#codersdklogintype) | false | | | | `»» name` | string | false | | | | `»» status` | [codersdk.UserStatus](schemas.md#codersdkuserstatus) | false | | | -| `»» theme_preference` | string | false | | | | `»» updated_at` | string(date-time) | false | | | | `»» username` | string | true | | | | `» name` | string | false | | | @@ -326,7 +324,6 @@ curl -X GET http://coder-server:8080/api/v2/groups/{group} \ "login_type": "", "name": "string", "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -387,7 +384,6 @@ curl -X DELETE http://coder-server:8080/api/v2/groups/{group} \ "login_type": "", "name": "string", "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -467,7 +463,6 @@ curl -X PATCH http://coder-server:8080/api/v2/groups/{group} \ "login_type": "", "name": "string", "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -1230,7 +1225,6 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/groups "login_type": "", "name": "string", "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -1271,7 +1265,6 @@ Status Code **200** | `»» login_type` | [codersdk.LoginType](schemas.md#codersdklogintype) | false | | | | `»» name` | string | false | | | | `»» status` | [codersdk.UserStatus](schemas.md#codersdkuserstatus) | false | | | -| `»» theme_preference` | string | false | | | | `»» updated_at` | string(date-time) | false | | | | `»» username` | string | true | | | | `» name` | string | false | | | @@ -1350,7 +1343,6 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/groups "login_type": "", "name": "string", "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -1412,7 +1404,6 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/groups/ "login_type": "", "name": "string", "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -2655,7 +2646,6 @@ curl -X PUT http://coder-server:8080/api/v2/scim/v2/Users/{id} \ } ], "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -2745,7 +2735,6 @@ curl -X PATCH http://coder-server:8080/api/v2/scim/v2/Users/{id} \ } ], "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -3109,7 +3098,6 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/acl \ } ], "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -3143,7 +3131,6 @@ Status Code **200** | `»» name` | string | false | | | | `»» organization_id` | string | false | | | | `» status` | [codersdk.UserStatus](schemas.md#codersdkuserstatus) | false | | | -| `» theme_preference` | string | false | | | | `» updated_at` | string(date-time) | false | | | | `» username` | string | true | | | @@ -3266,7 +3253,6 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/acl/available \ "login_type": "", "name": "string", "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -3290,7 +3276,6 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/acl/available \ "login_type": "", "name": "string", "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -3325,7 +3310,6 @@ Status Code **200** | `»»» login_type` | [codersdk.LoginType](schemas.md#codersdklogintype) | false | | | | `»»» name` | string | false | | | | `»»» status` | [codersdk.UserStatus](schemas.md#codersdkuserstatus) | false | | | -| `»»» theme_preference` | string | false | | | | `»»» updated_at` | string(date-time) | false | | | | `»»» username` | string | true | | | | `»» name` | string | false | | | diff --git a/docs/reference/api/schemas.md b/docs/reference/api/schemas.md index 7b2759e281f8e..2f6633744b897 100644 --- a/docs/reference/api/schemas.md +++ b/docs/reference/api/schemas.md @@ -242,7 +242,6 @@ "login_type": "", "name": "string", "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -266,7 +265,6 @@ "login_type": "", "name": "string", "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -654,7 +652,6 @@ } ], "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" }, @@ -746,7 +743,6 @@ } ], "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" }, @@ -3056,7 +3052,6 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith } ], "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -3108,7 +3103,6 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith "login_type": "", "name": "string", "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -5149,7 +5143,6 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith "login_type": "", "name": "string", "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -5157,19 +5150,18 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith ### Properties -| Name | Type | Required | Restrictions | Description | -|--------------------|--------------------------------------------|----------|--------------|-------------| -| `avatar_url` | string | false | | | -| `created_at` | string | true | | | -| `email` | string | true | | | -| `id` | string | true | | | -| `last_seen_at` | string | false | | | -| `login_type` | [codersdk.LoginType](#codersdklogintype) | false | | | -| `name` | string | false | | | -| `status` | [codersdk.UserStatus](#codersdkuserstatus) | false | | | -| `theme_preference` | string | false | | | -| `updated_at` | string | false | | | -| `username` | string | true | | | +| Name | Type | Required | Restrictions | Description | +|----------------|--------------------------------------------|----------|--------------|-------------| +| `avatar_url` | string | false | | | +| `created_at` | string | true | | | +| `email` | string | true | | | +| `id` | string | true | | | +| `last_seen_at` | string | false | | | +| `login_type` | [codersdk.LoginType](#codersdklogintype) | false | | | +| `name` | string | false | | | +| `status` | [codersdk.UserStatus](#codersdkuserstatus) | false | | | +| `updated_at` | string | false | | | +| `username` | string | true | | | #### Enumerated Values @@ -6132,7 +6124,6 @@ Restarts will only happen on weekdays in this list on weeks which line up with W } ], "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -6153,7 +6144,6 @@ Restarts will only happen on weekdays in this list on weeks which line up with W | `role` | [codersdk.TemplateRole](#codersdktemplaterole) | false | | | | `roles` | array of [codersdk.SlimRole](#codersdkslimrole) | false | | | | `status` | [codersdk.UserStatus](#codersdkuserstatus) | false | | | -| `theme_preference` | string | false | | | | `updated_at` | string | false | | | | `username` | string | true | | | @@ -6832,7 +6822,6 @@ If the schedule is empty, the user will be updated to use the default schedule.| } ], "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -6852,7 +6841,6 @@ If the schedule is empty, the user will be updated to use the default schedule.| | `organization_ids` | array of string | false | | | | `roles` | array of [codersdk.SlimRole](#codersdkslimrole) | false | | | | `status` | [codersdk.UserStatus](#codersdkuserstatus) | false | | | -| `theme_preference` | string | false | | | | `updated_at` | string | false | | | | `username` | string | true | | | @@ -6950,6 +6938,20 @@ If the schedule is empty, the user will be updated to use the default schedule.| |----------|----------------------------------------------------------------------------|----------|--------------|-------------| | `report` | [codersdk.UserActivityInsightsReport](#codersdkuseractivityinsightsreport) | false | | | +## codersdk.UserAppearanceSettings + +```json +{ + "theme_preference": "string" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +|--------------------|--------|----------|--------------|-------------| +| `theme_preference` | string | false | | | + ## codersdk.UserLatency ```json diff --git a/docs/reference/api/users.md b/docs/reference/api/users.md index d8aac77cfa83b..67fe73b57c6f8 100644 --- a/docs/reference/api/users.md +++ b/docs/reference/api/users.md @@ -49,7 +49,6 @@ curl -X GET http://coder-server:8080/api/v2/users \ } ], "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -125,7 +124,6 @@ curl -X POST http://coder-server:8080/api/v2/users \ } ], "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -400,7 +398,6 @@ curl -X GET http://coder-server:8080/api/v2/users/{user} \ } ], "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -475,35 +472,15 @@ curl -X PUT http://coder-server:8080/api/v2/users/{user}/appearance \ ```json { - "avatar_url": "http://example.com", - "created_at": "2019-08-24T14:15:22Z", - "email": "user@example.com", - "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", - "last_seen_at": "2019-08-24T14:15:22Z", - "login_type": "", - "name": "string", - "organization_ids": [ - "497f6eca-6276-4993-bfeb-53cbbbba6f08" - ], - "roles": [ - { - "display_name": "string", - "name": "string", - "organization_id": "string" - } - ], - "status": "active", - "theme_preference": "string", - "updated_at": "2019-08-24T14:15:22Z", - "username": "string" + "theme_preference": "string" } ``` ### Responses -| Status | Meaning | Description | Schema | -|--------|---------------------------------------------------------|-------------|------------------------------------------| -| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.User](schemas.md#codersdkuser) | +| Status | Meaning | Description | Schema | +|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------| +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.UserAppearanceSettings](schemas.md#codersdkuserappearancesettings) | To perform this operation, you must be authenticated. [Learn more](authentication.md). @@ -1157,7 +1134,6 @@ curl -X PUT http://coder-server:8080/api/v2/users/{user}/profile \ } ], "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -1214,7 +1190,6 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/roles \ } ], "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -1283,7 +1258,6 @@ curl -X PUT http://coder-server:8080/api/v2/users/{user}/roles \ } ], "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -1340,7 +1314,6 @@ curl -X PUT http://coder-server:8080/api/v2/users/{user}/status/activate \ } ], "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -1397,7 +1370,6 @@ curl -X PUT http://coder-server:8080/api/v2/users/{user}/status/suspend \ } ], "status": "active", - "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } diff --git a/enterprise/audit/table.go b/enterprise/audit/table.go index d43b2e224e374..0c50f308d73b4 100644 --- a/enterprise/audit/table.go +++ b/enterprise/audit/table.go @@ -145,7 +145,6 @@ var auditableResourcesTypes = map[any]map[string]Action{ "last_seen_at": ActionIgnore, "deleted": ActionTrack, "quiet_hours_schedule": ActionTrack, - "theme_preference": ActionIgnore, "name": ActionTrack, "github_com_user_id": ActionIgnore, "hashed_one_time_passcode": ActionIgnore, diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index d6f8c44c7e967..dc3bd15731a2a 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -2760,6 +2760,11 @@ export interface UserActivityInsightsResponse { readonly report: UserActivityInsightsReport; } +// From codersdk/users.go +export interface UserAppearanceSettings { + readonly theme_preference: string; +} + // From codersdk/insights.go export interface UserLatency { readonly template_ids: readonly string[]; From c4d60a32f67d40148c2fe276803e44e436715fc2 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Fri, 14 Feb 2025 18:34:56 +0000 Subject: [PATCH 04/20] ah yes --- coderd/apidoc/docs.go | 35 +++++++ coderd/apidoc/swagger.json | 29 ++++++ coderd/coderd.go | 1 + coderd/database/dbauthz/dbauthz.go | 7 ++ coderd/database/dbmem/dbmem.go | 14 +++ coderd/database/dbmetrics/querymetrics.go | 7 ++ coderd/database/dbmock/dbmock.go | 15 +++ coderd/database/querier.go | 1 + coderd/database/queries.sql.go | 17 ++++ coderd/database/queries/users.sql | 9 ++ coderd/users.go | 29 ++++++ site/index.html | 93 ++++++++++--------- site/site.go | 32 +++++-- site/src/api/api.ts | 14 +-- site/src/api/queries/users.ts | 36 +++---- site/src/contexts/ThemeProvider.tsx | 16 ++-- site/src/hooks/useEmbeddedMetadata.test.ts | 10 ++ site/src/hooks/useEmbeddedMetadata.ts | 4 + .../AppearancePage/AppearancePage.tsx | 30 +++++- site/src/testHelpers/entities.ts | 7 +- 20 files changed, 316 insertions(+), 90 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 70803d6313c3d..70a0c8016f110 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -6314,6 +6314,41 @@ const docTemplate = `{ } }, "/users/{user}/appearance": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Update user appearance settings", + "operationId": "update-user-appearance-settings", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.UserAppearanceSettings" + } + } + } + }, "put": { "security": [ { diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index a31b69a8524bc..30c2ed28e067c 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -5572,6 +5572,35 @@ } }, "/users/{user}/appearance": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Update user appearance settings", + "operationId": "update-user-appearance-settings", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.UserAppearanceSettings" + } + } + } + }, "put": { "security": [ { diff --git a/coderd/coderd.go b/coderd/coderd.go index 8ff8c05ee75b2..a2b2c5c31bfe9 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -1124,6 +1124,7 @@ func New(options *Options) *API { r.Put("/suspend", api.putSuspendUserAccount()) r.Put("/activate", api.putActivateUserAccount()) }) + r.Get("/appearance", api.getUserAppearanceSettings) r.Put("/appearance", api.putUserAppearanceSettings) r.Route("/password", func(r chi.Router) { r.Use(httpmw.RateLimit(options.LoginRateLimit, time.Minute)) diff --git a/coderd/database/dbauthz/dbauthz.go b/coderd/database/dbauthz/dbauthz.go index 0701e2cd972bb..9cf14fc85a52a 100644 --- a/coderd/database/dbauthz/dbauthz.go +++ b/coderd/database/dbauthz/dbauthz.go @@ -2424,6 +2424,13 @@ func (q *querier) GetUserActivityInsights(ctx context.Context, arg database.GetU return q.db.GetUserActivityInsights(ctx, arg) } +func (q *querier) GetUserAppearanceSettings(ctx context.Context, userID uuid.UUID) (string, error) { + if err := q.authorizeContext(ctx, policy.ActionReadPersonal, rbac.ResourceUser); err != nil { + return "", err + } + return q.db.GetUserAppearanceSettings(ctx, userID) +} + func (q *querier) GetUserByEmailOrUsername(ctx context.Context, arg database.GetUserByEmailOrUsernameParams) (database.User, error) { return fetch(q.log, q.auth, q.db.GetUserByEmailOrUsername)(ctx, arg) } diff --git a/coderd/database/dbmem/dbmem.go b/coderd/database/dbmem/dbmem.go index 2365617240453..22eb1d2076f0b 100644 --- a/coderd/database/dbmem/dbmem.go +++ b/coderd/database/dbmem/dbmem.go @@ -5871,6 +5871,20 @@ func (q *FakeQuerier) GetUserActivityInsights(_ context.Context, arg database.Ge return rows, nil } +func (q *FakeQuerier) GetUserAppearanceSettings(_ context.Context, userID uuid.UUID) (string, error) { + q.mutex.RLock() + defer q.mutex.RUnlock() + + for _, uc := range q.userConfigs { + if uc.UserID != userID || uc.Key != "theme_preference" { + continue + } + return uc.Value, nil + } + + return "", sql.ErrNoRows +} + func (q *FakeQuerier) GetUserByEmailOrUsername(_ context.Context, arg database.GetUserByEmailOrUsernameParams) (database.User, error) { if err := validateDatabaseType(arg); err != nil { return database.User{}, err diff --git a/coderd/database/dbmetrics/querymetrics.go b/coderd/database/dbmetrics/querymetrics.go index 7d65310ad28d9..40088556c6f71 100644 --- a/coderd/database/dbmetrics/querymetrics.go +++ b/coderd/database/dbmetrics/querymetrics.go @@ -1351,6 +1351,13 @@ func (m queryMetricsStore) GetUserActivityInsights(ctx context.Context, arg data return r0, r1 } +func (m queryMetricsStore) GetUserAppearanceSettings(ctx context.Context, userID uuid.UUID) (string, error) { + start := time.Now() + r0, r1 := m.s.GetUserAppearanceSettings(ctx, userID) + m.queryLatencies.WithLabelValues("GetUserAppearanceSettings").Observe(time.Since(start).Seconds()) + return r0, r1 +} + func (m queryMetricsStore) GetUserByEmailOrUsername(ctx context.Context, arg database.GetUserByEmailOrUsernameParams) (database.User, error) { start := time.Now() user, err := m.s.GetUserByEmailOrUsername(ctx, arg) diff --git a/coderd/database/dbmock/dbmock.go b/coderd/database/dbmock/dbmock.go index 44e6b0f48f257..cbb98e45109b9 100644 --- a/coderd/database/dbmock/dbmock.go +++ b/coderd/database/dbmock/dbmock.go @@ -2841,6 +2841,21 @@ func (mr *MockStoreMockRecorder) GetUserActivityInsights(ctx, arg any) *gomock.C return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserActivityInsights", reflect.TypeOf((*MockStore)(nil).GetUserActivityInsights), ctx, arg) } +// GetUserAppearanceSettings mocks base method. +func (m *MockStore) GetUserAppearanceSettings(ctx context.Context, userID uuid.UUID) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetUserAppearanceSettings", ctx, userID) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetUserAppearanceSettings indicates an expected call of GetUserAppearanceSettings. +func (mr *MockStoreMockRecorder) GetUserAppearanceSettings(ctx, userID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserAppearanceSettings", reflect.TypeOf((*MockStore)(nil).GetUserAppearanceSettings), ctx, userID) +} + // GetUserByEmailOrUsername mocks base method. func (m *MockStore) GetUserByEmailOrUsername(ctx context.Context, arg database.GetUserByEmailOrUsernameParams) (database.User, error) { m.ctrl.T.Helper() diff --git a/coderd/database/querier.go b/coderd/database/querier.go index 8ad30a5304169..ecf52d196b767 100644 --- a/coderd/database/querier.go +++ b/coderd/database/querier.go @@ -286,6 +286,7 @@ type sqlcQuerier interface { // produces a bloated value if a user has used multiple templates // simultaneously. GetUserActivityInsights(ctx context.Context, arg GetUserActivityInsightsParams) ([]GetUserActivityInsightsRow, error) + GetUserAppearanceSettings(ctx context.Context, userID uuid.UUID) (string, error) GetUserByEmailOrUsername(ctx context.Context, arg GetUserByEmailOrUsernameParams) (User, error) GetUserByID(ctx context.Context, id uuid.UUID) (User, error) GetUserCount(ctx context.Context) (int64, error) diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index 70f3d65486af1..ef5f87b69fa1a 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -10965,6 +10965,23 @@ func (q *sqlQuerier) GetAuthorizationUserRoles(ctx context.Context, userID uuid. return i, err } +const getUserAppearanceSettings = `-- name: GetUserAppearanceSettings :one +SELECT + value as theme_preference +FROM + user_configs +WHERE + user_id = $1 + AND key = 'theme_preference' +` + +func (q *sqlQuerier) GetUserAppearanceSettings(ctx context.Context, userID uuid.UUID) (string, error) { + row := q.db.QueryRowContext(ctx, getUserAppearanceSettings, userID) + var theme_preference string + err := row.Scan(&theme_preference) + return theme_preference, err +} + const getUserByEmailOrUsername = `-- name: GetUserByEmailOrUsername :one SELECT id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at diff --git a/coderd/database/queries/users.sql b/coderd/database/queries/users.sql index 3caef9e70945a..c45aa83bd46e6 100644 --- a/coderd/database/queries/users.sql +++ b/coderd/database/queries/users.sql @@ -98,6 +98,15 @@ SET WHERE id = $1; +-- name: GetUserAppearanceSettings :one +SELECT + value as theme_preference +FROM + user_configs +WHERE + user_id = @user_id + AND key = 'theme_preference'; + -- name: UpdateUserAppearanceSettings :one INSERT INTO user_configs (user_id, key, value) diff --git a/coderd/users.go b/coderd/users.go index fef791203d32d..539e0dfe9f3af 100644 --- a/coderd/users.go +++ b/coderd/users.go @@ -973,6 +973,35 @@ func (api *API) notifyUserStatusChanged(ctx context.Context, actingUserName stri return nil } +// @Summary Update user appearance settings +// @ID update-user-appearance-settings +// @Security CoderSessionToken +// @Accept json +// @Produce json +// @Tags Users +// @Param user path string true "User ID, name, or me" +// @Success 200 {object} codersdk.UserAppearanceSettings +// @Router /users/{user}/appearance [get] +func (api *API) getUserAppearanceSettings(rw http.ResponseWriter, r *http.Request) { + var ( + ctx = r.Context() + user = httpmw.UserParam(r) + ) + + themePreference, err := api.Database.GetUserAppearanceSettings(ctx, user.ID) + if err != nil { + httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ + Message: "Internal error updating user.", + Detail: err.Error(), + }) + return + } + + httpapi.Write(ctx, rw, http.StatusOK, codersdk.UserAppearanceSettings{ + ThemePreference: themePreference, + }) +} + // @Summary Update user appearance settings // @ID update-user-appearance-settings // @Security CoderSessionToken diff --git a/site/index.html b/site/index.html index fff26338b21aa..b953abe052923 100644 --- a/site/index.html +++ b/site/index.html @@ -9,53 +9,54 @@ --> - - Coder - - - - - - - - - - - - - - - - - - + + Coder + + + + + + + + + + + + + + + + + + + -
- +
+ diff --git a/site/site.go b/site/site.go index 3a85f7b3963ad..3b42cf30aab9a 100644 --- a/site/site.go +++ b/site/site.go @@ -292,13 +292,14 @@ type htmlState struct { ApplicationName string LogoURL string - BuildInfo string - User string - Entitlements string - Appearance string - Experiments string - Regions string - DocsURL string + BuildInfo string + User string + Entitlements string + Appearance string + UserAppearance string + Experiments string + Regions string + DocsURL string } type csrfState struct { @@ -426,12 +427,18 @@ func (h *Handler) renderHTMLWithState(r *http.Request, filePath string, state ht var eg errgroup.Group var user database.User + var themePreference string orgIDs := []uuid.UUID{} eg.Go(func() error { var err error user, err = h.opts.Database.GetUserByID(ctx, apiKey.UserID) return err }) + eg.Go(func() error { + var err error + themePreference, err = h.opts.Database.GetUserAppearanceSettings(ctx, apiKey.UserID) + return err + }) eg.Go(func() error { memberIDs, err := h.opts.Database.GetOrganizationIDsByMemberIDs(ctx, []uuid.UUID{apiKey.UserID}) if errors.Is(err, sql.ErrNoRows) || len(memberIDs) == 0 { @@ -455,6 +462,17 @@ func (h *Handler) renderHTMLWithState(r *http.Request, filePath string, state ht } }() + wg.Add(1) + go func() { + defer wg.Done() + userAppearance, err := json.Marshal(codersdk.UserAppearanceSettings{ + ThemePreference: themePreference, + }) + if err == nil { + state.UserAppearance = html.EscapeString(string(userAppearance)) + } + }() + if h.Entitlements != nil { wg.Add(1) go func() { diff --git a/site/src/api/api.ts b/site/src/api/api.ts index 43051961fa7e7..7db51cd23c43f 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -1320,14 +1320,16 @@ class ApiMethods { return response.data; }; + getAppearanceSettings = + async (): Promise => { + const response = await this.axios.get("/api/v2/users/me/appearance"); + return response.data; + }; + updateAppearanceSettings = async ( - userId: string, data: TypesGen.UpdateUserAppearanceSettingsRequest, - ): Promise => { - const response = await this.axios.put( - `/api/v2/users/${userId}/appearance`, - data, - ); + ): Promise => { + const response = await this.axios.put("/api/v2/users/me/appearance", data); return response.data; }; diff --git a/site/src/api/queries/users.ts b/site/src/api/queries/users.ts index 77d879abe3258..5de828b6eac22 100644 --- a/site/src/api/queries/users.ts +++ b/site/src/api/queries/users.ts @@ -8,8 +8,8 @@ import type { UpdateUserPasswordRequest, UpdateUserProfileRequest, User, + UserAppearanceSettings, UsersRequest, - ValidateUserPasswordRequest, } from "api/typesGenerated"; import { type MetadataState, @@ -224,35 +224,39 @@ export const updateProfile = (userId: string) => { }; }; +const myAppearanceKey = ["me", "appearance"]; + +export const appearanceSettings = ( + metadata: MetadataState, +) => { + return cachedQuery({ + metadata, + queryKey: myAppearanceKey, + queryFn: API.getAppearanceSettings, + }); +}; + export const updateAppearanceSettings = ( - userId: string, queryClient: QueryClient, ): UseMutationOptions< - User, + UserAppearanceSettings, unknown, UpdateUserAppearanceSettingsRequest, unknown > => { return { - mutationFn: (req) => API.updateAppearanceSettings(userId, req), + mutationFn: (req) => API.updateAppearanceSettings(req), onMutate: async (patch) => { // Mutate the `queryClient` optimistically to make the theme switcher // more responsive. - const me: User | undefined = queryClient.getQueryData(meKey); - if (userId === "me" && me) { - queryClient.setQueryData(meKey, { - ...me, - theme_preference: patch.theme_preference, - }); - } + queryClient.setQueryData(myAppearanceKey, { + theme_preference: patch.theme_preference, + }); }, - onSuccess: async () => { + onSuccess: async () => // Could technically invalidate more, but we only ever care about the // `theme_preference` for the `me` query. - if (userId === "me") { - await queryClient.invalidateQueries(meKey); - } - }, + await queryClient.invalidateQueries(myAppearanceKey), }; }; diff --git a/site/src/contexts/ThemeProvider.tsx b/site/src/contexts/ThemeProvider.tsx index 8367e96e3cc64..4521ab71d7a74 100644 --- a/site/src/contexts/ThemeProvider.tsx +++ b/site/src/contexts/ThemeProvider.tsx @@ -7,26 +7,27 @@ import { StyledEngineProvider, // biome-ignore lint/nursery/noRestrictedImports: we extend the MUI theme } from "@mui/material/styles"; +import { appearanceSettings } from "api/queries/users"; +import { useEmbeddedMetadata } from "hooks/useEmbeddedMetadata"; import { type FC, type PropsWithChildren, type ReactNode, - useContext, useEffect, useMemo, useState, } from "react"; +import { useQuery } from "react-query"; import themes, { DEFAULT_THEME, type Theme } from "theme"; -import { AuthContext } from "./auth/AuthProvider"; /** * */ export const ThemeProvider: FC = ({ children }) => { - // We need to use the `AuthContext` directly, rather than the `useAuth` hook, - // because Storybook and many tests depend on this component, but do not provide - // an `AuthProvider`, and `useAuth` will throw in that case. - const user = useContext(AuthContext)?.user; + const { metadata } = useEmbeddedMetadata(); + const appearanceSettingsQuery = useQuery( + appearanceSettings(metadata.userAppearance), + ); const themeQuery = useMemo( () => window.matchMedia?.("(prefers-color-scheme: light)"), [], @@ -53,7 +54,8 @@ export const ThemeProvider: FC = ({ children }) => { }, [themeQuery]); // We might not be logged in yet, or the `theme_preference` could be an empty string. - const themePreference = user?.theme_preference || DEFAULT_THEME; + const themePreference = + appearanceSettingsQuery.data?.theme_preference || DEFAULT_THEME; // The janky casting here is find because of the much more type safe fallback // We need to support `themePreference` being wrong anyway because the database // value could be anything, like an empty string. diff --git a/site/src/hooks/useEmbeddedMetadata.test.ts b/site/src/hooks/useEmbeddedMetadata.test.ts index 75dd4eed8f235..aacb635ada3bf 100644 --- a/site/src/hooks/useEmbeddedMetadata.test.ts +++ b/site/src/hooks/useEmbeddedMetadata.test.ts @@ -6,6 +6,7 @@ import { MockEntitlements, MockExperiments, MockUser, + MockUserAppearanceSettings, } from "testHelpers/entities"; import { DEFAULT_METADATA_KEY, @@ -38,6 +39,7 @@ const mockDataForTags = { entitlements: MockEntitlements, experiments: MockExperiments, user: MockUser, + userAppearance: MockUserAppearanceSettings, regions: MockRegions, } as const satisfies Record; @@ -66,6 +68,10 @@ const emptyMetadata: RuntimeHtmlMetadata = { available: false, value: undefined, }, + userAppearance: { + available: false, + value: undefined, + }, }; const populatedMetadata: RuntimeHtmlMetadata = { @@ -93,6 +99,10 @@ const populatedMetadata: RuntimeHtmlMetadata = { available: true, value: MockUser, }, + userAppearance: { + available: true, + value: MockUserAppearanceSettings, + }, }; function seedInitialMetadata(metadataKey: string): () => void { diff --git a/site/src/hooks/useEmbeddedMetadata.ts b/site/src/hooks/useEmbeddedMetadata.ts index ac4fd50037ed3..35cd8614f408e 100644 --- a/site/src/hooks/useEmbeddedMetadata.ts +++ b/site/src/hooks/useEmbeddedMetadata.ts @@ -5,6 +5,7 @@ import type { Experiments, Region, User, + UserAppearanceSettings, } from "api/typesGenerated"; import { useMemo, useSyncExternalStore } from "react"; @@ -25,6 +26,7 @@ type AvailableMetadata = Readonly<{ user: User; experiments: Experiments; appearance: AppearanceConfig; + userAppearance: UserAppearanceSettings; entitlements: Entitlements; regions: readonly Region[]; "build-info": BuildInfoResponse; @@ -83,6 +85,8 @@ export class MetadataManager implements MetadataManagerApi { this.metadata = { user: this.registerValue("user"), appearance: this.registerValue("appearance"), + userAppearance: + this.registerValue("userAppearance"), entitlements: this.registerValue("entitlements"), experiments: this.registerValue("experiments"), "build-info": this.registerValue("build-info"), diff --git a/site/src/pages/UserSettingsPage/AppearancePage/AppearancePage.tsx b/site/src/pages/UserSettingsPage/AppearancePage/AppearancePage.tsx index dfa4519ab2d58..796a0d2ad0be6 100644 --- a/site/src/pages/UserSettingsPage/AppearancePage/AppearancePage.tsx +++ b/site/src/pages/UserSettingsPage/AppearancePage/AppearancePage.tsx @@ -1,19 +1,37 @@ import CircularProgress from "@mui/material/CircularProgress"; import { updateAppearanceSettings } from "api/queries/users"; +import { appearanceSettings } from "api/queries/users"; +import { ErrorAlert } from "components/Alert/ErrorAlert"; +import { Loader } from "components/Loader/Loader"; import { Stack } from "components/Stack/Stack"; -import { useAuthenticated } from "contexts/auth/RequireAuth"; +import { useEmbeddedMetadata } from "hooks/useEmbeddedMetadata"; import type { FC } from "react"; -import { useMutation, useQueryClient } from "react-query"; +import { useMutation, useQuery, useQueryClient } from "react-query"; import { Section } from "../Section"; import { AppearanceForm } from "./AppearanceForm"; export const AppearancePage: FC = () => { - const { user: me } = useAuthenticated(); const queryClient = useQueryClient(); const updateAppearanceSettingsMutation = useMutation( - updateAppearanceSettings("me", queryClient), + updateAppearanceSettings(queryClient), ); + const { metadata } = useEmbeddedMetadata(); + const appearanceSettingsQuery = useQuery( + appearanceSettings(metadata.userAppearance), + ); + + console.log(metadata.userAppearance); + console.log(appearanceSettingsQuery.data); + + if (appearanceSettingsQuery.isLoading) { + return ; + } + + if (!appearanceSettingsQuery.data) { + return ; + } + return ( <>
{
diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index a607df6bb87c9..b70195cc6879a 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -475,7 +475,6 @@ export const MockUser: TypesGen.User = { avatar_url: "https://avatars.githubusercontent.com/u/95932066?s=200&v=4", last_seen_at: "", login_type: "password", - theme_preference: "", name: "", }; @@ -496,7 +495,6 @@ export const MockUser2: TypesGen.User = { avatar_url: "", last_seen_at: "2022-09-14T19:12:21Z", login_type: "oidc", - theme_preference: "", name: "Mock User The Second", }; @@ -512,10 +510,13 @@ export const SuspendedMockUser: TypesGen.User = { avatar_url: "", last_seen_at: "", login_type: "password", - theme_preference: "", name: "", }; +export const MockUserAppearanceSettings: TypesGen.UserAppearanceSettings = { + theme_preference: "dark", +}; + export const MockOrganizationMember: TypesGen.OrganizationMemberWithUserData = { organization_id: MockOrganization.id, user_id: MockUser.id, From 2c3a3f36c372f87ef3b31195402b572559fd1c8b Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Fri, 14 Feb 2025 18:36:08 +0000 Subject: [PATCH 05/20] =?UTF-8?q?=F0=9F=A7=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pages/UserSettingsPage/AppearancePage/AppearancePage.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/site/src/pages/UserSettingsPage/AppearancePage/AppearancePage.tsx b/site/src/pages/UserSettingsPage/AppearancePage/AppearancePage.tsx index 796a0d2ad0be6..1379e42d0e909 100644 --- a/site/src/pages/UserSettingsPage/AppearancePage/AppearancePage.tsx +++ b/site/src/pages/UserSettingsPage/AppearancePage/AppearancePage.tsx @@ -21,9 +21,6 @@ export const AppearancePage: FC = () => { appearanceSettings(metadata.userAppearance), ); - console.log(metadata.userAppearance); - console.log(appearanceSettingsQuery.data); - if (appearanceSettingsQuery.isLoading) { return ; } From 1c6f7fee3fc8c152e312f65dfcf57927fb5e9729 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Fri, 14 Feb 2025 19:05:53 +0000 Subject: [PATCH 06/20] foreign key --- coderd/database/migrations/000293_user_configs.up.sql | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/coderd/database/migrations/000293_user_configs.up.sql b/coderd/database/migrations/000293_user_configs.up.sql index 931033f419236..e52654563f75d 100644 --- a/coderd/database/migrations/000293_user_configs.up.sql +++ b/coderd/database/migrations/000293_user_configs.up.sql @@ -1,7 +1,10 @@ CREATE TABLE IF NOT EXISTS user_configs ( - user_id uuid NOT NULL, - key varchar(256) NOT NULL, - value text NOT NULL + user_id uuid NOT NULL, + key varchar(256) NOT NULL, + value text NOT NULL, + + PRIMARY KEY (user_id, key), + FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ); ALTER TABLE ONLY user_configs From 76804ad4ed373823ca9729646e8e15531ea81363 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Fri, 14 Feb 2025 19:12:20 +0000 Subject: [PATCH 07/20] =?UTF-8?q?=F0=9F=A7=B9=F0=9F=A7=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- coderd/coderd.go | 2 +- coderd/database/dump.sql | 5 ++++- coderd/database/foreign_key_constraint.go | 1 + coderd/database/migrations/000293_user_configs.up.sql | 5 +---- coderd/database/queries.sql.go | 2 +- coderd/database/queries/users.sql | 2 +- coderd/database/unique_constraint.go | 2 +- coderd/users.go | 2 +- 8 files changed, 11 insertions(+), 10 deletions(-) diff --git a/coderd/coderd.go b/coderd/coderd.go index a2b2c5c31bfe9..083d158d8682e 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -1124,7 +1124,7 @@ func New(options *Options) *API { r.Put("/suspend", api.putSuspendUserAccount()) r.Put("/activate", api.putActivateUserAccount()) }) - r.Get("/appearance", api.getUserAppearanceSettings) + r.Get("/appearance", api.userAppearanceSettings) r.Put("/appearance", api.putUserAppearanceSettings) r.Route("/password", func(r chi.Router) { r.Use(httpmw.RateLimit(options.LoginRateLimit, time.Minute)) diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql index f080df4f10ad7..9401c8381b1db 100644 --- a/coderd/database/dump.sql +++ b/coderd/database/dump.sql @@ -2097,7 +2097,7 @@ ALTER TABLE ONLY templates ADD CONSTRAINT templates_pkey PRIMARY KEY (id); ALTER TABLE ONLY user_configs - ADD CONSTRAINT unique_key_per_user UNIQUE (user_id, key); + ADD CONSTRAINT user_configs_pkey PRIMARY KEY (user_id, key); ALTER TABLE ONLY user_deleted ADD CONSTRAINT user_deleted_pkey PRIMARY KEY (id); @@ -2501,6 +2501,9 @@ ALTER TABLE ONLY templates ALTER TABLE ONLY templates ADD CONSTRAINT templates_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE; +ALTER TABLE ONLY user_configs + ADD CONSTRAINT user_configs_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + ALTER TABLE ONLY user_deleted ADD CONSTRAINT user_deleted_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id); diff --git a/coderd/database/foreign_key_constraint.go b/coderd/database/foreign_key_constraint.go index 66c379a749e01..cd58a6aa2e831 100644 --- a/coderd/database/foreign_key_constraint.go +++ b/coderd/database/foreign_key_constraint.go @@ -49,6 +49,7 @@ const ( ForeignKeyTemplateVersionsTemplateID ForeignKeyConstraint = "template_versions_template_id_fkey" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_template_id_fkey FOREIGN KEY (template_id) REFERENCES templates(id) ON DELETE CASCADE; ForeignKeyTemplatesCreatedBy ForeignKeyConstraint = "templates_created_by_fkey" // ALTER TABLE ONLY templates ADD CONSTRAINT templates_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE RESTRICT; ForeignKeyTemplatesOrganizationID ForeignKeyConstraint = "templates_organization_id_fkey" // ALTER TABLE ONLY templates ADD CONSTRAINT templates_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE; + ForeignKeyUserConfigsUserID ForeignKeyConstraint = "user_configs_user_id_fkey" // ALTER TABLE ONLY user_configs ADD CONSTRAINT user_configs_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; ForeignKeyUserDeletedUserID ForeignKeyConstraint = "user_deleted_user_id_fkey" // ALTER TABLE ONLY user_deleted ADD CONSTRAINT user_deleted_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id); ForeignKeyUserLinksOauthAccessTokenKeyID ForeignKeyConstraint = "user_links_oauth_access_token_key_id_fkey" // ALTER TABLE ONLY user_links ADD CONSTRAINT user_links_oauth_access_token_key_id_fkey FOREIGN KEY (oauth_access_token_key_id) REFERENCES dbcrypt_keys(active_key_digest); ForeignKeyUserLinksOauthRefreshTokenKeyID ForeignKeyConstraint = "user_links_oauth_refresh_token_key_id_fkey" // ALTER TABLE ONLY user_links ADD CONSTRAINT user_links_oauth_refresh_token_key_id_fkey FOREIGN KEY (oauth_refresh_token_key_id) REFERENCES dbcrypt_keys(active_key_digest); diff --git a/coderd/database/migrations/000293_user_configs.up.sql b/coderd/database/migrations/000293_user_configs.up.sql index e52654563f75d..fb5db1d8e5f6e 100644 --- a/coderd/database/migrations/000293_user_configs.up.sql +++ b/coderd/database/migrations/000293_user_configs.up.sql @@ -7,11 +7,8 @@ CREATE TABLE IF NOT EXISTS user_configs ( FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ); -ALTER TABLE ONLY user_configs - ADD CONSTRAINT unique_key_per_user UNIQUE (user_id, key); - --- +-- Copy "theme_preference" from "users" table INSERT INTO user_configs (user_id, key, value) SELECT id, 'theme_preference', theme_preference FROM users diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index ef5f87b69fa1a..73b6435ee4e2a 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -11426,7 +11426,7 @@ INSERT INTO VALUES ($1, 'theme_preference', $2) ON CONFLICT - ON CONSTRAINT unique_key_per_user + ON CONSTRAINT user_configs_pkey DO UPDATE SET value = $2 diff --git a/coderd/database/queries/users.sql b/coderd/database/queries/users.sql index c45aa83bd46e6..79f19c1784155 100644 --- a/coderd/database/queries/users.sql +++ b/coderd/database/queries/users.sql @@ -113,7 +113,7 @@ INSERT INTO VALUES (@user_id, 'theme_preference', @theme_preference) ON CONFLICT - ON CONSTRAINT unique_key_per_user + ON CONSTRAINT user_configs_pkey DO UPDATE SET value = @theme_preference diff --git a/coderd/database/unique_constraint.go b/coderd/database/unique_constraint.go index 2132068aefe03..c86daa9aa167d 100644 --- a/coderd/database/unique_constraint.go +++ b/coderd/database/unique_constraint.go @@ -65,7 +65,7 @@ const ( UniqueTemplateVersionsPkey UniqueConstraint = "template_versions_pkey" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_pkey PRIMARY KEY (id); UniqueTemplateVersionsTemplateIDNameKey UniqueConstraint = "template_versions_template_id_name_key" // ALTER TABLE ONLY template_versions ADD CONSTRAINT template_versions_template_id_name_key UNIQUE (template_id, name); UniqueTemplatesPkey UniqueConstraint = "templates_pkey" // ALTER TABLE ONLY templates ADD CONSTRAINT templates_pkey PRIMARY KEY (id); - UniqueUniqueKeyPerUser UniqueConstraint = "unique_key_per_user" // ALTER TABLE ONLY user_configs ADD CONSTRAINT unique_key_per_user UNIQUE (user_id, key); + UniqueUserConfigsPkey UniqueConstraint = "user_configs_pkey" // ALTER TABLE ONLY user_configs ADD CONSTRAINT user_configs_pkey PRIMARY KEY (user_id, key); UniqueUserDeletedPkey UniqueConstraint = "user_deleted_pkey" // ALTER TABLE ONLY user_deleted ADD CONSTRAINT user_deleted_pkey PRIMARY KEY (id); UniqueUserLinksPkey UniqueConstraint = "user_links_pkey" // ALTER TABLE ONLY user_links ADD CONSTRAINT user_links_pkey PRIMARY KEY (user_id, login_type); UniqueUserStatusChangesPkey UniqueConstraint = "user_status_changes_pkey" // ALTER TABLE ONLY user_status_changes ADD CONSTRAINT user_status_changes_pkey PRIMARY KEY (id); diff --git a/coderd/users.go b/coderd/users.go index 539e0dfe9f3af..482de59c94a25 100644 --- a/coderd/users.go +++ b/coderd/users.go @@ -982,7 +982,7 @@ func (api *API) notifyUserStatusChanged(ctx context.Context, actingUserName stri // @Param user path string true "User ID, name, or me" // @Success 200 {object} codersdk.UserAppearanceSettings // @Router /users/{user}/appearance [get] -func (api *API) getUserAppearanceSettings(rw http.ResponseWriter, r *http.Request) { +func (api *API) userAppearanceSettings(rw http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() user = httpmw.UserParam(r) From d30d1ec9a06d21789e4c5fdbef7ceb7af9d9a1b1 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Fri, 14 Feb 2025 19:38:12 +0000 Subject: [PATCH 08/20] =?UTF-8?q?=F0=9F=8F=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cli/testdata/coder_users_list_--output_json.golden | 2 -- 1 file changed, 2 deletions(-) diff --git a/cli/testdata/coder_users_list_--output_json.golden b/cli/testdata/coder_users_list_--output_json.golden index fa82286acebbf..61b17e026d290 100644 --- a/cli/testdata/coder_users_list_--output_json.golden +++ b/cli/testdata/coder_users_list_--output_json.golden @@ -10,7 +10,6 @@ "last_seen_at": "====[timestamp]=====", "status": "active", "login_type": "password", - "theme_preference": "", "organization_ids": [ "===========[first org ID]===========" ], @@ -32,7 +31,6 @@ "last_seen_at": "====[timestamp]=====", "status": "dormant", "login_type": "password", - "theme_preference": "", "organization_ids": [ "===========[first org ID]===========" ], From 24d1ae02771ce7031a171bdfecbfcf398a195401 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Fri, 14 Feb 2025 19:46:56 +0000 Subject: [PATCH 09/20] mock new /appearance route --- site/src/testHelpers/handlers.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/site/src/testHelpers/handlers.ts b/site/src/testHelpers/handlers.ts index b458956b17a1d..e8dc9e2dedd3c 100644 --- a/site/src/testHelpers/handlers.ts +++ b/site/src/testHelpers/handlers.ts @@ -162,6 +162,9 @@ export const handlers = [ http.get("/api/v2/users/me", () => { return HttpResponse.json(M.MockUser); }), + http.get("/api/v2/users/me/appearance", () => { + return HttpResponse.json(M.MockUserAppearanceSettings); + }), http.get("/api/v2/users/me/keys", () => { return HttpResponse.json(M.MockAPIKey); }), From 929d70b93c1d1c4696a04a4d649f42626f47d06e Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Fri, 14 Feb 2025 21:34:57 +0000 Subject: [PATCH 10/20] fixies --- coderd/apidoc/docs.go | 4 ++-- coderd/apidoc/swagger.json | 4 ++-- coderd/database/dbauthz/dbauthz.go | 6 ++++- coderd/users.go | 6 ++--- docs/reference/api/users.md | 37 ++++++++++++++++++++++++++++++ 5 files changed, 49 insertions(+), 8 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 70a0c8016f110..a1f6a90a73b95 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -6329,8 +6329,8 @@ const docTemplate = `{ "tags": [ "Users" ], - "summary": "Update user appearance settings", - "operationId": "update-user-appearance-settings", + "summary": "Get user appearance settings", + "operationId": "get-user-appearance-settings", "parameters": [ { "type": "string", diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 30c2ed28e067c..fc5d23934bee8 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -5581,8 +5581,8 @@ "consumes": ["application/json"], "produces": ["application/json"], "tags": ["Users"], - "summary": "Update user appearance settings", - "operationId": "update-user-appearance-settings", + "summary": "Get user appearance settings", + "operationId": "get-user-appearance-settings", "parameters": [ { "type": "string", diff --git a/coderd/database/dbauthz/dbauthz.go b/coderd/database/dbauthz/dbauthz.go index 9cf14fc85a52a..46ef898e8148b 100644 --- a/coderd/database/dbauthz/dbauthz.go +++ b/coderd/database/dbauthz/dbauthz.go @@ -2425,7 +2425,11 @@ func (q *querier) GetUserActivityInsights(ctx context.Context, arg database.GetU } func (q *querier) GetUserAppearanceSettings(ctx context.Context, userID uuid.UUID) (string, error) { - if err := q.authorizeContext(ctx, policy.ActionReadPersonal, rbac.ResourceUser); err != nil { + u, err := q.db.GetUserByID(ctx, userID) + if err != nil { + return "", err + } + if err := q.authorizeContext(ctx, policy.ActionReadPersonal, u); err != nil { return "", err } return q.db.GetUserAppearanceSettings(ctx, userID) diff --git a/coderd/users.go b/coderd/users.go index 482de59c94a25..2507a313c1288 100644 --- a/coderd/users.go +++ b/coderd/users.go @@ -973,8 +973,8 @@ func (api *API) notifyUserStatusChanged(ctx context.Context, actingUserName stri return nil } -// @Summary Update user appearance settings -// @ID update-user-appearance-settings +// @Summary Get user appearance settings +// @ID get-user-appearance-settings // @Security CoderSessionToken // @Accept json // @Produce json @@ -1003,7 +1003,7 @@ func (api *API) userAppearanceSettings(rw http.ResponseWriter, r *http.Request) } // @Summary Update user appearance settings -// @ID update-user-appearance-settings +// @ID update-user-appearance-setting // @Security CoderSessionToken // @Accept json // @Produce json diff --git a/docs/reference/api/users.md b/docs/reference/api/users.md index 67fe73b57c6f8..60689ac012dc1 100644 --- a/docs/reference/api/users.md +++ b/docs/reference/api/users.md @@ -437,6 +437,43 @@ curl -X DELETE http://coder-server:8080/api/v2/users/{user} \ To perform this operation, you must be authenticated. [Learn more](authentication.md). +## Get user appearance settings + +### Code samples + +```shell +# Example request using curl +curl -X GET http://coder-server:8080/api/v2/users/{user}/appearance \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`GET /users/{user}/appearance` + +### Parameters + +| Name | In | Type | Required | Description | +|--------|------|--------|----------|----------------------| +| `user` | path | string | true | User ID, name, or me | + +### Example responses + +> 200 Response + +```json +{ + "theme_preference": "string" +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------| +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.UserAppearanceSettings](schemas.md#codersdkuserappearancesettings) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + ## Update user appearance settings ### Code samples From 766d0306baa78bb2e2913afc97e153b11ebb1524 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Fri, 14 Feb 2025 22:06:12 +0000 Subject: [PATCH 11/20] :^) --- .../components/FileUpload/FileUpload.test.tsx | 22 +++++++++---------- site/src/hooks/useClipboard.test.tsx | 7 +++--- .../AppearancePage/AppearancePage.test.tsx | 2 +- .../WorkspaceScheduleControls.test.tsx | 19 ++++------------ site/src/testHelpers/renderHelpers.tsx | 7 ++++-- 5 files changed, 24 insertions(+), 33 deletions(-) diff --git a/site/src/components/FileUpload/FileUpload.test.tsx b/site/src/components/FileUpload/FileUpload.test.tsx index 2ff94f355bcfe..e4e40a477cd26 100644 --- a/site/src/components/FileUpload/FileUpload.test.tsx +++ b/site/src/components/FileUpload/FileUpload.test.tsx @@ -1,20 +1,18 @@ -import { fireEvent, render, screen } from "@testing-library/react"; -import { ThemeProvider } from "contexts/ThemeProvider"; +import { fireEvent, screen } from "@testing-library/react"; import { FileUpload } from "./FileUpload"; +import { renderComponent } from "testHelpers/renderHelpers"; test("accepts files with the correct extension", async () => { const onUpload = jest.fn(); - render( - - - , + renderComponent( + , ); const dropZone = screen.getByTestId("drop-zone"); diff --git a/site/src/hooks/useClipboard.test.tsx b/site/src/hooks/useClipboard.test.tsx index f98c1d1154b86..316fa391f5a74 100644 --- a/site/src/hooks/useClipboard.test.tsx +++ b/site/src/hooks/useClipboard.test.tsx @@ -11,7 +11,7 @@ */ import { act, renderHook, screen } from "@testing-library/react"; import { GlobalSnackbar } from "components/GlobalSnackbar/GlobalSnackbar"; -import { ThemeProvider } from "contexts/ThemeProvider"; +import { ThemeOverride } from "contexts/ThemeProvider"; import { COPY_FAILED_MESSAGE, HTTP_FALLBACK_DATA_ID, @@ -19,6 +19,7 @@ import { type UseClipboardResult, useClipboard, } from "./useClipboard"; +import themes, { DEFAULT_THEME } from "theme"; // Need to mock console.error because we deliberately need to trigger errors in // the code to assert that it can recover from them, but we also don't want them @@ -121,10 +122,10 @@ function renderUseClipboard(inputs: TInput) { initialProps: inputs, wrapper: ({ children }) => ( // Need ThemeProvider because GlobalSnackbar uses theme - + {children} - + ), }, ); diff --git a/site/src/pages/UserSettingsPage/AppearancePage/AppearancePage.test.tsx b/site/src/pages/UserSettingsPage/AppearancePage/AppearancePage.test.tsx index e3eb0d9c12367..c48c265460a4e 100644 --- a/site/src/pages/UserSettingsPage/AppearancePage/AppearancePage.test.tsx +++ b/site/src/pages/UserSettingsPage/AppearancePage/AppearancePage.test.tsx @@ -34,7 +34,7 @@ describe("appearance page", () => { // Check if the API was called correctly expect(API.updateAppearanceSettings).toBeCalledTimes(1); - expect(API.updateAppearanceSettings).toHaveBeenCalledWith("me", { + expect(API.updateAppearanceSettings).toHaveBeenCalledWith({ theme_preference: "light", }); }); diff --git a/site/src/pages/WorkspacePage/WorkspaceScheduleControls.test.tsx b/site/src/pages/WorkspacePage/WorkspaceScheduleControls.test.tsx index 3d2f44602bd31..827d06cf1b96a 100644 --- a/site/src/pages/WorkspacePage/WorkspaceScheduleControls.test.tsx +++ b/site/src/pages/WorkspacePage/WorkspaceScheduleControls.test.tsx @@ -1,17 +1,15 @@ -import { render, screen } from "@testing-library/react"; +import { screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { API } from "api/api"; import { workspaceByOwnerAndName } from "api/queries/workspaces"; -import { GlobalSnackbar } from "components/GlobalSnackbar/GlobalSnackbar"; -import { ThemeProvider } from "contexts/ThemeProvider"; import dayjs from "dayjs"; import { http, HttpResponse } from "msw"; import type { FC } from "react"; -import { QueryClient, QueryClientProvider, useQuery } from "react-query"; -import { RouterProvider, createMemoryRouter } from "react-router-dom"; +import { useQuery } from "react-query"; import { MockTemplate, MockWorkspace } from "testHelpers/entities"; import { server } from "testHelpers/server"; import { WorkspaceScheduleControls } from "./WorkspaceScheduleControls"; +import { render } from "testHelpers/renderHelpers"; const Wrapper: FC = () => { const { data: workspace } = useQuery( @@ -45,16 +43,7 @@ const renderScheduleControls = async () => { }); }), ); - render( - - - }])} - /> - - - , - ); + render(); await screen.findByTestId("schedule-controls"); expect(screen.getByText("Stop in 3 hours")).toBeInTheDocument(); }; diff --git a/site/src/testHelpers/renderHelpers.tsx b/site/src/testHelpers/renderHelpers.tsx index 330919c7ef7f6..854fe0a94475b 100644 --- a/site/src/testHelpers/renderHelpers.tsx +++ b/site/src/testHelpers/renderHelpers.tsx @@ -5,7 +5,7 @@ import { } from "@testing-library/react"; import { AppProviders } from "App"; import type { ProxyProvider } from "contexts/ProxyContext"; -import { ThemeProvider } from "contexts/ThemeProvider"; +import { ThemeOverride } from "contexts/ThemeProvider"; import { RequireAuth } from "contexts/auth/RequireAuth"; import { DashboardLayout } from "modules/dashboard/DashboardLayout"; import type { DashboardProvider } from "modules/dashboard/DashboardProvider"; @@ -20,6 +20,7 @@ import { createMemoryRouter, } from "react-router-dom"; import { MockUser } from "./entities"; +import themes, { DEFAULT_THEME } from "theme"; export function createTestQueryClient() { // Helps create one query client for each test case, to make sure that tests @@ -245,6 +246,8 @@ export const waitForLoaderToBeRemoved = async (): Promise => { export const renderComponent = (component: React.ReactElement) => { return testingLibraryRender(component, { - wrapper: ({ children }) => {children}, + wrapper: ({ children }) => ( + {children} + ), }); }; From 57b6a489609929e6838ea8f22fb1dfee355916fa Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Fri, 14 Feb 2025 22:10:08 +0000 Subject: [PATCH 12/20] would you pls --- coderd/users.go | 2 +- site/src/components/FileUpload/FileUpload.test.tsx | 2 +- site/src/hooks/useClipboard.test.tsx | 2 +- site/src/pages/WorkspacePage/WorkspaceScheduleControls.test.tsx | 2 +- site/src/testHelpers/renderHelpers.tsx | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/coderd/users.go b/coderd/users.go index 2507a313c1288..2fc88d466be90 100644 --- a/coderd/users.go +++ b/coderd/users.go @@ -1003,7 +1003,7 @@ func (api *API) userAppearanceSettings(rw http.ResponseWriter, r *http.Request) } // @Summary Update user appearance settings -// @ID update-user-appearance-setting +// @ID update-user-appearance-settings // @Security CoderSessionToken // @Accept json // @Produce json diff --git a/site/src/components/FileUpload/FileUpload.test.tsx b/site/src/components/FileUpload/FileUpload.test.tsx index e4e40a477cd26..6292bc200a517 100644 --- a/site/src/components/FileUpload/FileUpload.test.tsx +++ b/site/src/components/FileUpload/FileUpload.test.tsx @@ -1,6 +1,6 @@ import { fireEvent, screen } from "@testing-library/react"; -import { FileUpload } from "./FileUpload"; import { renderComponent } from "testHelpers/renderHelpers"; +import { FileUpload } from "./FileUpload"; test("accepts files with the correct extension", async () => { const onUpload = jest.fn(); diff --git a/site/src/hooks/useClipboard.test.tsx b/site/src/hooks/useClipboard.test.tsx index 316fa391f5a74..1d4d2eb702a81 100644 --- a/site/src/hooks/useClipboard.test.tsx +++ b/site/src/hooks/useClipboard.test.tsx @@ -12,6 +12,7 @@ import { act, renderHook, screen } from "@testing-library/react"; import { GlobalSnackbar } from "components/GlobalSnackbar/GlobalSnackbar"; import { ThemeOverride } from "contexts/ThemeProvider"; +import themes, { DEFAULT_THEME } from "theme"; import { COPY_FAILED_MESSAGE, HTTP_FALLBACK_DATA_ID, @@ -19,7 +20,6 @@ import { type UseClipboardResult, useClipboard, } from "./useClipboard"; -import themes, { DEFAULT_THEME } from "theme"; // Need to mock console.error because we deliberately need to trigger errors in // the code to assert that it can recover from them, but we also don't want them diff --git a/site/src/pages/WorkspacePage/WorkspaceScheduleControls.test.tsx b/site/src/pages/WorkspacePage/WorkspaceScheduleControls.test.tsx index 827d06cf1b96a..225db7c8a44c0 100644 --- a/site/src/pages/WorkspacePage/WorkspaceScheduleControls.test.tsx +++ b/site/src/pages/WorkspacePage/WorkspaceScheduleControls.test.tsx @@ -7,9 +7,9 @@ import { http, HttpResponse } from "msw"; import type { FC } from "react"; import { useQuery } from "react-query"; import { MockTemplate, MockWorkspace } from "testHelpers/entities"; +import { render } from "testHelpers/renderHelpers"; import { server } from "testHelpers/server"; import { WorkspaceScheduleControls } from "./WorkspaceScheduleControls"; -import { render } from "testHelpers/renderHelpers"; const Wrapper: FC = () => { const { data: workspace } = useQuery( diff --git a/site/src/testHelpers/renderHelpers.tsx b/site/src/testHelpers/renderHelpers.tsx index 854fe0a94475b..eb76b481783da 100644 --- a/site/src/testHelpers/renderHelpers.tsx +++ b/site/src/testHelpers/renderHelpers.tsx @@ -19,8 +19,8 @@ import { RouterProvider, createMemoryRouter, } from "react-router-dom"; -import { MockUser } from "./entities"; import themes, { DEFAULT_THEME } from "theme"; +import { MockUser } from "./entities"; export function createTestQueryClient() { // Helps create one query client for each test case, to make sure that tests From 18447a3985bf29471485758f1cbdf1e1bf51e7ed Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Fri, 14 Feb 2025 22:25:20 +0000 Subject: [PATCH 13/20] take your test --- coderd/database/dbauthz/dbauthz_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/coderd/database/dbauthz/dbauthz_test.go b/coderd/database/dbauthz/dbauthz_test.go index afb87b2d8a8ca..2815a1700e364 100644 --- a/coderd/database/dbauthz/dbauthz_test.go +++ b/coderd/database/dbauthz/dbauthz_test.go @@ -1521,6 +1521,15 @@ func (s *MethodTestSuite) TestUser() { []database.GetUserWorkspaceBuildParametersRow{}, ) })) + s.Run("GetUserAppearanceSettings", s.Subtest(func(db database.Store, check *expects) { + ctx := context.Background() + u := dbgen.User(s.T(), db, database.User{}) + db.UpdateUserAppearanceSettings(ctx, database.UpdateUserAppearanceSettingsParams{ + UserID: u.ID, + ThemePreference: "light", + }) + check.Args(u.ID).Asserts(u, policy.ActionReadPersonal).Returns("light") + })) s.Run("UpdateUserAppearanceSettings", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) uc := database.UserConfig{ From 04c298c31466945593d7dc5aa869a4278e587ace Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Fri, 14 Feb 2025 22:41:35 +0000 Subject: [PATCH 14/20] :| --- coderd/apidoc/docs.go | 3 --- coderd/apidoc/swagger.json | 1 - coderd/users.go | 1 - 3 files changed, 5 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index a1f6a90a73b95..e4d348aa295e8 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -6320,9 +6320,6 @@ const docTemplate = `{ "CoderSessionToken": [] } ], - "consumes": [ - "application/json" - ], "produces": [ "application/json" ], diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index fc5d23934bee8..d3e062ca6a285 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -5578,7 +5578,6 @@ "CoderSessionToken": [] } ], - "consumes": ["application/json"], "produces": ["application/json"], "tags": ["Users"], "summary": "Get user appearance settings", diff --git a/coderd/users.go b/coderd/users.go index 2fc88d466be90..4e6f2be52729d 100644 --- a/coderd/users.go +++ b/coderd/users.go @@ -976,7 +976,6 @@ func (api *API) notifyUserStatusChanged(ctx context.Context, actingUserName stri // @Summary Get user appearance settings // @ID get-user-appearance-settings // @Security CoderSessionToken -// @Accept json // @Produce json // @Tags Users // @Param user path string true "User ID, name, or me" From bb1ac6e704a24d94e448996da485b47899246930 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Fri, 14 Feb 2025 22:53:28 +0000 Subject: [PATCH 15/20] ok --- coderd/users.go | 14 +++++++++----- site/site.go | 4 ++++ site/site_test.go | 3 +++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/coderd/users.go b/coderd/users.go index 4e6f2be52729d..97babd0ae7836 100644 --- a/coderd/users.go +++ b/coderd/users.go @@ -989,11 +989,15 @@ func (api *API) userAppearanceSettings(rw http.ResponseWriter, r *http.Request) themePreference, err := api.Database.GetUserAppearanceSettings(ctx, user.ID) if err != nil { - httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ - Message: "Internal error updating user.", - Detail: err.Error(), - }) - return + if !errors.Is(err, sql.ErrNoRows) { + httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ + Message: "Error reading user settings.", + Detail: err.Error(), + }) + return + } + + themePreference = "" } httpapi.Write(ctx, rw, http.StatusOK, codersdk.UserAppearanceSettings{ diff --git a/site/site.go b/site/site.go index 3b42cf30aab9a..eea4794c6c216 100644 --- a/site/site.go +++ b/site/site.go @@ -437,6 +437,10 @@ func (h *Handler) renderHTMLWithState(r *http.Request, filePath string, state ht eg.Go(func() error { var err error themePreference, err = h.opts.Database.GetUserAppearanceSettings(ctx, apiKey.UserID) + if errors.Is(err, sql.ErrNoRows) { + themePreference = "" + return nil + } return err }) eg.Go(func() error { diff --git a/site/site_test.go b/site/site_test.go index 63f3f9aa17226..ae03536981e82 100644 --- a/site/site_test.go +++ b/site/site_test.go @@ -65,6 +65,9 @@ func TestInjection(t *testing.T) { handler.ServeHTTP(rw, r) require.Equal(t, http.StatusOK, rw.Code) + fmt.Println("oh boy oh boy oh boy") + fmt.Println(rw.Body.String()) + fmt.Println("oh boy oh boy oh boy") var got codersdk.User err := json.Unmarshal([]byte(html.UnescapeString(rw.Body.String())), &got) require.NoError(t, err) From 8036b87e878fe810189bc4155bffbbca47ce391e Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Fri, 14 Feb 2025 22:56:28 +0000 Subject: [PATCH 16/20] - --- site/site_test.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/site/site_test.go b/site/site_test.go index ae03536981e82..63f3f9aa17226 100644 --- a/site/site_test.go +++ b/site/site_test.go @@ -65,9 +65,6 @@ func TestInjection(t *testing.T) { handler.ServeHTTP(rw, r) require.Equal(t, http.StatusOK, rw.Code) - fmt.Println("oh boy oh boy oh boy") - fmt.Println(rw.Body.String()) - fmt.Println("oh boy oh boy oh boy") var got codersdk.User err := json.Unmarshal([]byte(html.UnescapeString(rw.Body.String())), &got) require.NoError(t, err) From f694cfccbca895fee23e1c6d1d04efe512668c2d Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Fri, 14 Feb 2025 23:26:36 +0000 Subject: [PATCH 17/20] down --- coderd/database/migrations/000293_user_configs.down.sql | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/coderd/database/migrations/000293_user_configs.down.sql b/coderd/database/migrations/000293_user_configs.down.sql index e3fb8d9403cc7..c3ca42798ef98 100644 --- a/coderd/database/migrations/000293_user_configs.down.sql +++ b/coderd/database/migrations/000293_user_configs.down.sql @@ -3,11 +3,11 @@ ALTER TABLE users ADD COLUMN IF NOT EXISTS theme_preference text DEFAULT ''::text NOT NULL; -- Copy "theme_preference" back to "users" -UPDATE users (theme_preference) - SELECT value +UPDATE users + SET theme_preference = (SELECT value FROM user_configs - WHERE users.id = user_configs.user_id - AND user_configs.key = 'theme_preference'; + WHERE user_configs.user_id = users.id + AND user_configs.key = 'theme_preference'); -- Drop the "user_configs" table. DROP TABLE user_configs; From 67fb8acd1405d25b8aa2fcee1b4c51aa1364cdb9 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Wed, 19 Feb 2025 00:05:47 +0000 Subject: [PATCH 18/20] oops --- .../calling-module/calling-module.tfplan.json | 4 +-- .../calling-module.tfstate.json | 10 +++---- .../chaining-resources.tfplan.json | 4 +-- .../chaining-resources.tfstate.json | 10 +++---- .../conflicting-resources.tfplan.json | 4 +-- .../conflicting-resources.tfstate.json | 10 +++---- .../display-apps-disabled.tfplan.json | 4 +-- .../display-apps-disabled.tfstate.json | 8 +++--- .../display-apps/display-apps.tfplan.json | 4 +-- .../display-apps/display-apps.tfstate.json | 8 +++--- .../external-auth-providers.tfplan.json | 6 ++-- .../external-auth-providers.tfstate.json | 8 +++--- .../instance-id/instance-id.tfplan.json | 4 +-- .../instance-id/instance-id.tfstate.json | 12 ++++---- .../mapped-apps/mapped-apps.tfplan.json | 4 +-- .../mapped-apps/mapped-apps.tfstate.json | 16 +++++------ .../multiple-agents-multiple-apps.tfplan.json | 4 +-- ...multiple-agents-multiple-apps.tfstate.json | 26 ++++++++--------- .../multiple-agents-multiple-envs.tfplan.json | 4 +-- ...multiple-agents-multiple-envs.tfstate.json | 26 ++++++++--------- ...tiple-agents-multiple-monitors.tfplan.json | 4 +-- ...iple-agents-multiple-monitors.tfstate.json | 20 ++++++------- ...ltiple-agents-multiple-scripts.tfplan.json | 4 +-- ...tiple-agents-multiple-scripts.tfstate.json | 26 ++++++++--------- .../multiple-agents.tfplan.json | 4 +-- .../multiple-agents.tfstate.json | 20 ++++++------- .../multiple-apps/multiple-apps.tfplan.json | 4 +-- .../multiple-apps/multiple-apps.tfstate.json | 20 ++++++------- .../resource-metadata-duplicate.tfplan.json | 4 +-- .../resource-metadata-duplicate.tfstate.json | 16 +++++------ .../resource-metadata.tfplan.json | 4 +-- .../resource-metadata.tfstate.json | 12 ++++---- .../rich-parameters-order.tfplan.json | 10 +++---- .../rich-parameters-order.tfstate.json | 12 ++++---- .../rich-parameters-validation.tfplan.json | 18 ++++++------ .../rich-parameters-validation.tfstate.json | 20 ++++++------- .../rich-parameters.tfplan.json | 26 ++++++++--------- .../rich-parameters.tfstate.json | 28 +++++++++---------- 38 files changed, 214 insertions(+), 214 deletions(-) diff --git a/provisioner/terraform/testdata/calling-module/calling-module.tfplan.json b/provisioner/terraform/testdata/calling-module/calling-module.tfplan.json index d3c8d6bbd4792..8759627e35398 100644 --- a/provisioner/terraform/testdata/calling-module/calling-module.tfplan.json +++ b/provisioner/terraform/testdata/calling-module/calling-module.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "planned_values": { "root_module": { "resources": [ @@ -254,7 +254,7 @@ ] } ], - "timestamp": "2025-02-18T18:21:16Z", + "timestamp": "2025-02-18T10:58:12Z", "applyable": true, "complete": true, "errored": false diff --git a/provisioner/terraform/testdata/calling-module/calling-module.tfstate.json b/provisioner/terraform/testdata/calling-module/calling-module.tfstate.json index aab85b9b862e6..0286c44e0412b 100644 --- a/provisioner/terraform/testdata/calling-module/calling-module.tfstate.json +++ b/provisioner/terraform/testdata/calling-module/calling-module.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -26,7 +26,7 @@ } ], "env": null, - "id": "99813be0-d7b7-4a73-a751-73f98a1819fd", + "id": "6b8c1681-8d24-454f-9674-75aa10a78a66", "init_script": "", "metadata": [], "motd_file": null, @@ -35,7 +35,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "e00cfe7e-1e10-4ed5-8bd7-e5df9ce50e76", + "token": "b10f2c9a-2936-4d64-9d3c-3705fa094272", "troubleshooting_url": null }, "sensitive_values": { @@ -66,7 +66,7 @@ "outputs": { "script": "" }, - "random": "6991323013163911812" + "random": "2818431725852233027" }, "sensitive_values": { "inputs": {}, @@ -81,7 +81,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "7450673059056179011", + "id": "2514800225855033412", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.json b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.json index a7b0020fdbd5f..4f478962e7b97 100644 --- a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.json +++ b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "planned_values": { "root_module": { "resources": [ @@ -199,7 +199,7 @@ ] } }, - "timestamp": "2025-02-18T18:21:16Z", + "timestamp": "2025-02-18T10:58:12Z", "applyable": true, "complete": true, "errored": false diff --git a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.json b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.json index abbe48b1adaef..d51e2ecb81c71 100644 --- a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.json +++ b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -26,7 +26,7 @@ } ], "env": null, - "id": "abb9ab2c-a59b-4d45-92ce-4883a42a25a0", + "id": "a4c46a8c-dd2a-4913-8897-e77b24fdd7f1", "init_script": "", "metadata": [], "motd_file": null, @@ -35,7 +35,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "925aef90-3801-4158-bf9b-95ee2739d24b", + "token": "c263f7b6-c0e7-4106-b3fc-aefbe373ee7a", "troubleshooting_url": null }, "sensitive_values": { @@ -54,7 +54,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "1077607069181053633", + "id": "4299141049988455758", "triggers": null }, "sensitive_values": {}, @@ -71,7 +71,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "7753018043075213587", + "id": "8248139888152642631", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.json b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.json index b85b1f4e03a0a..57af82397bd20 100644 --- a/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.json +++ b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "planned_values": { "root_module": { "resources": [ @@ -199,7 +199,7 @@ ] } }, - "timestamp": "2025-02-18T18:21:16Z", + "timestamp": "2025-02-18T10:58:12Z", "applyable": true, "complete": true, "errored": false diff --git a/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.json b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.json index d364ad7e22bdd..f1e9760fcdac1 100644 --- a/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.json +++ b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -26,7 +26,7 @@ } ], "env": null, - "id": "a2967190-27de-4110-9800-8365b54c1f2b", + "id": "c5972861-13a8-4c3d-9e7b-c32aab3c5105", "init_script": "", "metadata": [], "motd_file": null, @@ -35,7 +35,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "ad2bfe66-fab4-4166-9829-138575dca918", + "token": "9c2883aa-0c0e-470f-a40c-588b47e663be", "troubleshooting_url": null }, "sensitive_values": { @@ -54,7 +54,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "4824924933868648791", + "id": "4167500156989566756", "triggers": null }, "sensitive_values": {}, @@ -70,7 +70,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "6383295970090695836", + "id": "2831408390006359178", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfplan.json b/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfplan.json index 9513f7c9dafdd..f715d1e5b36ef 100644 --- a/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfplan.json +++ b/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "planned_values": { "root_module": { "resources": [ @@ -198,7 +198,7 @@ ] } }, - "timestamp": "2025-02-18T18:21:16Z", + "timestamp": "2025-02-18T10:58:12Z", "applyable": true, "complete": true, "errored": false diff --git a/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfstate.json b/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfstate.json index 8d27f240a7fba..8127adf08deb5 100644 --- a/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfstate.json +++ b/provisioner/terraform/testdata/display-apps-disabled/display-apps-disabled.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -26,7 +26,7 @@ } ], "env": null, - "id": "69a948fe-0f7a-4a2f-a298-69af05f51e5e", + "id": "f145f4f8-1d6c-4a66-ba80-abbc077dfe1e", "init_script": "", "metadata": [], "motd_file": null, @@ -35,7 +35,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "9b8143bb-8bde-4d38-a7f4-0f6bd977a8e9", + "token": "612a69b3-4b07-4752-b930-ed7dd36dc926", "troubleshooting_url": null }, "sensitive_values": { @@ -54,7 +54,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "7433336070111935217", + "id": "3571714162665255692", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/display-apps/display-apps.tfplan.json b/provisioner/terraform/testdata/display-apps/display-apps.tfplan.json index 6531f7bd68560..b4b3e8d72cb07 100644 --- a/provisioner/terraform/testdata/display-apps/display-apps.tfplan.json +++ b/provisioner/terraform/testdata/display-apps/display-apps.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "planned_values": { "root_module": { "resources": [ @@ -198,7 +198,7 @@ ] } }, - "timestamp": "2025-02-18T18:21:16Z", + "timestamp": "2025-02-18T10:58:12Z", "applyable": true, "complete": true, "errored": false diff --git a/provisioner/terraform/testdata/display-apps/display-apps.tfstate.json b/provisioner/terraform/testdata/display-apps/display-apps.tfstate.json index b77b4f29d2c7c..53be3e3041729 100644 --- a/provisioner/terraform/testdata/display-apps/display-apps.tfstate.json +++ b/provisioner/terraform/testdata/display-apps/display-apps.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -26,7 +26,7 @@ } ], "env": null, - "id": "636f2be0-1b27-41ac-a956-21492da0dc39", + "id": "df983aa4-ad0a-458a-acd2-1d5c93e4e4d8", "init_script": "", "metadata": [], "motd_file": null, @@ -35,7 +35,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "0c53590c-daa7-4f8e-b880-fbd61b8de2e3", + "token": "c2ccd3c2-5ac3-46f5-9620-f1d4c633169f", "troubleshooting_url": null }, "sensitive_values": { @@ -54,7 +54,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "2200476559043400784", + "id": "4058093101918806466", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfplan.json b/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfplan.json index 1e49b9d9d34a4..fbd2636bfb68d 100644 --- a/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfplan.json +++ b/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "planned_values": { "root_module": { "resources": [ @@ -113,7 +113,7 @@ ], "prior_state": { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -222,7 +222,7 @@ ] } }, - "timestamp": "2025-02-18T18:21:16Z", + "timestamp": "2025-02-18T10:58:12Z", "applyable": true, "complete": true, "errored": false diff --git a/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfstate.json b/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfstate.json index 5a5ce2e321741..e439476cc9b52 100644 --- a/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfstate.json +++ b/provisioner/terraform/testdata/external-auth-providers/external-auth-providers.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -54,7 +54,7 @@ } ], "env": null, - "id": "9e757383-d864-4d62-a0f6-c97e84796094", + "id": "048746d5-8a05-4615-bdf3-5e0ecda12ba0", "init_script": "", "metadata": [], "motd_file": null, @@ -63,7 +63,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "310d28cf-0eb2-4a7c-859c-762bb505f5c4", + "token": "d2a64629-1d18-4704-a3b1-eae300a362d1", "troubleshooting_url": null }, "sensitive_values": { @@ -82,7 +82,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "1250995009519083999", + "id": "5369997016721085167", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/instance-id/instance-id.tfplan.json b/provisioner/terraform/testdata/instance-id/instance-id.tfplan.json index 200e924224b0d..7c929b496d8fd 100644 --- a/provisioner/terraform/testdata/instance-id/instance-id.tfplan.json +++ b/provisioner/terraform/testdata/instance-id/instance-id.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "planned_values": { "root_module": { "resources": [ @@ -219,7 +219,7 @@ ] } ], - "timestamp": "2025-02-18T18:21:16Z", + "timestamp": "2025-02-18T10:58:12Z", "applyable": true, "complete": true, "errored": false diff --git a/provisioner/terraform/testdata/instance-id/instance-id.tfstate.json b/provisioner/terraform/testdata/instance-id/instance-id.tfstate.json index df1ce2a76526e..7f7cdfa6a5055 100644 --- a/provisioner/terraform/testdata/instance-id/instance-id.tfstate.json +++ b/provisioner/terraform/testdata/instance-id/instance-id.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -26,7 +26,7 @@ } ], "env": null, - "id": "26597111-8ebc-4949-90b7-2722007692c7", + "id": "0b84fffb-d2ca-4048-bdab-7b84229bffba", "init_script": "", "metadata": [], "motd_file": null, @@ -35,7 +35,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "6c4915dd-1d22-42c7-b14c-f0369d570096", + "token": "05f05235-a62b-4634-841b-da7fe3763e2e", "troubleshooting_url": null }, "sensitive_values": { @@ -54,8 +54,8 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 0, "values": { - "agent_id": "26597111-8ebc-4949-90b7-2722007692c7", - "id": "119683f2-fe7d-4823-aced-0044dafb96f0", + "agent_id": "0b84fffb-d2ca-4048-bdab-7b84229bffba", + "id": "7d6e9d00-4cf9-4a38-9b4b-1eb6ba98b50c", "instance_id": "example" }, "sensitive_values": {}, @@ -71,7 +71,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "4260132288485152121", + "id": "446414716532401482", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfplan.json b/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfplan.json index b7ea8fafc508c..dfcf3ccc7b52f 100644 --- a/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfplan.json +++ b/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "planned_values": { "root_module": { "resources": [ @@ -321,7 +321,7 @@ ] } ], - "timestamp": "2025-02-18T18:21:16Z", + "timestamp": "2025-02-18T10:58:12Z", "applyable": true, "complete": true, "errored": false diff --git a/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfstate.json b/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfstate.json index bf794aa4b7fab..ae0acf1650825 100644 --- a/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfstate.json +++ b/provisioner/terraform/testdata/mapped-apps/mapped-apps.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -26,7 +26,7 @@ } ], "env": null, - "id": "23443da2-bde9-4591-839f-456da45f8189", + "id": "4b66f4b5-d235-4c57-8b50-7db3643f8070", "init_script": "", "metadata": [], "motd_file": null, @@ -35,7 +35,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "d4b3676c-fa3c-4f4f-88cf-fe93f72383ab", + "token": "a39963f7-3429-453f-b23f-961aa3590f06", "troubleshooting_url": null }, "sensitive_values": { @@ -55,14 +55,14 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 1, "values": { - "agent_id": "23443da2-bde9-4591-839f-456da45f8189", + "agent_id": "4b66f4b5-d235-4c57-8b50-7db3643f8070", "command": null, "display_name": "app1", "external": false, "healthcheck": [], "hidden": false, "icon": null, - "id": "474ac80e-7675-4055-9598-b1295acb7c12", + "id": "e67b9091-a454-42ce-85ee-df929f716c4f", "open_in": "slim-window", "order": null, "share": "owner", @@ -86,14 +86,14 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 1, "values": { - "agent_id": "23443da2-bde9-4591-839f-456da45f8189", + "agent_id": "4b66f4b5-d235-4c57-8b50-7db3643f8070", "command": null, "display_name": "app2", "external": false, "healthcheck": [], "hidden": false, "icon": null, - "id": "1290cc75-0ef0-4740-a29c-d96e170e647d", + "id": "84db109a-484c-42cc-b428-866458a99964", "open_in": "slim-window", "order": null, "share": "owner", @@ -116,7 +116,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "5053475313220856922", + "id": "800496923164467286", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/multiple-agents-multiple-apps/multiple-agents-multiple-apps.tfplan.json b/provisioner/terraform/testdata/multiple-agents-multiple-apps/multiple-agents-multiple-apps.tfplan.json index 9b659107549d6..4ba8c29b7fa77 100644 --- a/provisioner/terraform/testdata/multiple-agents-multiple-apps/multiple-agents-multiple-apps.tfplan.json +++ b/provisioner/terraform/testdata/multiple-agents-multiple-apps/multiple-agents-multiple-apps.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "planned_values": { "root_module": { "resources": [ @@ -575,7 +575,7 @@ ] } ], - "timestamp": "2025-02-18T18:21:16Z", + "timestamp": "2025-02-18T10:58:12Z", "applyable": true, "complete": true, "errored": false diff --git a/provisioner/terraform/testdata/multiple-agents-multiple-apps/multiple-agents-multiple-apps.tfstate.json b/provisioner/terraform/testdata/multiple-agents-multiple-apps/multiple-agents-multiple-apps.tfstate.json index a016997dd9bf8..7ffb9866b4c48 100644 --- a/provisioner/terraform/testdata/multiple-agents-multiple-apps/multiple-agents-multiple-apps.tfstate.json +++ b/provisioner/terraform/testdata/multiple-agents-multiple-apps/multiple-agents-multiple-apps.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -26,7 +26,7 @@ } ], "env": null, - "id": "b228504c-ad73-4c53-933c-c232043849b3", + "id": "9ba3ef14-bb43-4470-b019-129bf16eb0b2", "init_script": "", "metadata": [], "motd_file": null, @@ -35,7 +35,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "bc9f8c02-f208-48de-9114-93f58e1ebc58", + "token": "b40bdbf8-bf41-4822-a71e-03016079ddbe", "troubleshooting_url": null }, "sensitive_values": { @@ -68,7 +68,7 @@ } ], "env": null, - "id": "46fa750a-1796-4db4-a242-06e9cd95f0e2", + "id": "959048f4-3f1d-4cb0-93da-1dfacdbb7976", "init_script": "", "metadata": [], "motd_file": null, @@ -77,7 +77,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "91722f85-db71-4d9c-9e24-fd04ab44e4fb", + "token": "71ef9752-9257-478c-bf5e-c6713a9f5073", "troubleshooting_url": null }, "sensitive_values": { @@ -96,14 +96,14 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 1, "values": { - "agent_id": "b228504c-ad73-4c53-933c-c232043849b3", + "agent_id": "9ba3ef14-bb43-4470-b019-129bf16eb0b2", "command": null, "display_name": null, "external": false, "healthcheck": [], "hidden": false, "icon": null, - "id": "ad43457a-d53e-4858-af1c-8ac6b1f7e68e", + "id": "f125297a-130c-4c29-a1bf-905f95841fff", "open_in": "slim-window", "order": null, "share": "owner", @@ -126,7 +126,7 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 1, "values": { - "agent_id": "b228504c-ad73-4c53-933c-c232043849b3", + "agent_id": "9ba3ef14-bb43-4470-b019-129bf16eb0b2", "command": null, "display_name": null, "external": false, @@ -139,7 +139,7 @@ ], "hidden": false, "icon": null, - "id": "0d7a6598-0402-41c7-9e3a-934633f37e43", + "id": "687e66e5-4888-417d-8fbd-263764dc5011", "open_in": "slim-window", "order": null, "share": "owner", @@ -164,14 +164,14 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 1, "values": { - "agent_id": "46fa750a-1796-4db4-a242-06e9cd95f0e2", + "agent_id": "959048f4-3f1d-4cb0-93da-1dfacdbb7976", "command": null, "display_name": null, "external": false, "healthcheck": [], "hidden": false, "icon": null, - "id": "2e9fab10-5707-4150-811d-76debaca9cc2", + "id": "70f10886-fa90-4089-b290-c2d44c5073ae", "open_in": "slim-window", "order": null, "share": "owner", @@ -194,7 +194,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "5260983662585355730", + "id": "1056762545519872704", "triggers": null }, "sensitive_values": {}, @@ -210,7 +210,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "9030448048834232915", + "id": "784993046206959042", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/multiple-agents-multiple-envs/multiple-agents-multiple-envs.tfplan.json b/provisioner/terraform/testdata/multiple-agents-multiple-envs/multiple-agents-multiple-envs.tfplan.json index 22cf85bab1640..7fe81435861e4 100644 --- a/provisioner/terraform/testdata/multiple-agents-multiple-envs/multiple-agents-multiple-envs.tfplan.json +++ b/provisioner/terraform/testdata/multiple-agents-multiple-envs/multiple-agents-multiple-envs.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "planned_values": { "root_module": { "resources": [ @@ -472,7 +472,7 @@ ] } ], - "timestamp": "2025-02-18T18:21:16Z", + "timestamp": "2025-02-18T10:58:12Z", "applyable": true, "complete": true, "errored": false diff --git a/provisioner/terraform/testdata/multiple-agents-multiple-envs/multiple-agents-multiple-envs.tfstate.json b/provisioner/terraform/testdata/multiple-agents-multiple-envs/multiple-agents-multiple-envs.tfstate.json index 7dd7fc0036665..f7801ad37220c 100644 --- a/provisioner/terraform/testdata/multiple-agents-multiple-envs/multiple-agents-multiple-envs.tfstate.json +++ b/provisioner/terraform/testdata/multiple-agents-multiple-envs/multiple-agents-multiple-envs.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -26,7 +26,7 @@ } ], "env": null, - "id": "b2eb9a49-7e85-46b3-883b-cad8032817b9", + "id": "5494b9d3-a230-41a4-8f50-be69397ab4cf", "init_script": "", "metadata": [], "motd_file": null, @@ -35,7 +35,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "c076688b-1d3b-49e1-bc6a-e141373a18c1", + "token": "84f93622-75a4-4bf1-b806-b981066d4870", "troubleshooting_url": null }, "sensitive_values": { @@ -68,7 +68,7 @@ } ], "env": null, - "id": "0d10329b-746e-44e2-bd67-8b2328347f06", + "id": "a4cb672c-020b-4729-b451-c7fabba4669c", "init_script": "", "metadata": [], "motd_file": null, @@ -77,7 +77,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "68db82bf-2be6-4309-8b59-25df9a89a806", + "token": "2861b097-2ea6-4c3a-a64c-5a726b9e3700", "troubleshooting_url": null }, "sensitive_values": { @@ -96,8 +96,8 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 1, "values": { - "agent_id": "b2eb9a49-7e85-46b3-883b-cad8032817b9", - "id": "1488081e-64f1-4b99-9490-4311b9d6cb88", + "agent_id": "5494b9d3-a230-41a4-8f50-be69397ab4cf", + "id": "4ec31abd-b84a-45b6-80bd-c78eecf387f1", "name": "ENV_1", "value": "Env 1" }, @@ -114,8 +114,8 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 1, "values": { - "agent_id": "b2eb9a49-7e85-46b3-883b-cad8032817b9", - "id": "1479b961-3e81-4bb4-9f84-b03ea79631ac", + "agent_id": "5494b9d3-a230-41a4-8f50-be69397ab4cf", + "id": "c0f4dac3-2b1a-4903-a0f1-2743f2000f1b", "name": "ENV_2", "value": "Env 2" }, @@ -132,8 +132,8 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 1, "values": { - "agent_id": "0d10329b-746e-44e2-bd67-8b2328347f06", - "id": "85aeb657-7581-4f70-9849-bec5d8b8f396", + "agent_id": "a4cb672c-020b-4729-b451-c7fabba4669c", + "id": "e0ccf967-d767-4077-b521-20132af3217a", "name": "ENV_3", "value": "Env 3" }, @@ -150,7 +150,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "4160244480026169609", + "id": "7748417950448815454", "triggers": null }, "sensitive_values": {}, @@ -166,7 +166,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "9212471919710672321", + "id": "1466092153882814278", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/multiple-agents-multiple-monitors/multiple-agents-multiple-monitors.tfplan.json b/provisioner/terraform/testdata/multiple-agents-multiple-monitors/multiple-agents-multiple-monitors.tfplan.json index 6252194bfeb0a..b5481b4c89463 100644 --- a/provisioner/terraform/testdata/multiple-agents-multiple-monitors/multiple-agents-multiple-monitors.tfplan.json +++ b/provisioner/terraform/testdata/multiple-agents-multiple-monitors/multiple-agents-multiple-monitors.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "planned_values": { "root_module": { "resources": [ @@ -618,7 +618,7 @@ ] } ], - "timestamp": "2025-02-18T18:21:17Z", + "timestamp": "2025-02-18T10:58:12Z", "applyable": true, "complete": true, "errored": false diff --git a/provisioner/terraform/testdata/multiple-agents-multiple-monitors/multiple-agents-multiple-monitors.tfstate.json b/provisioner/terraform/testdata/multiple-agents-multiple-monitors/multiple-agents-multiple-monitors.tfstate.json index e78fba716b9c3..85ef0a7ccddad 100644 --- a/provisioner/terraform/testdata/multiple-agents-multiple-monitors/multiple-agents-multiple-monitors.tfstate.json +++ b/provisioner/terraform/testdata/multiple-agents-multiple-monitors/multiple-agents-multiple-monitors.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -26,7 +26,7 @@ } ], "env": null, - "id": "1e66fd1b-d220-4f86-b30c-32a9866c33d0", + "id": "9c36f8be-874a-40f6-a395-f37d6d910a83", "init_script": "", "metadata": [], "motd_file": null, @@ -46,7 +46,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "9f0bba2e-9c55-49f0-88cb-5a2a79d96540", + "token": "1bed5f78-a309-4049-9805-b5f52a17306d", "troubleshooting_url": null }, "sensitive_values": { @@ -87,7 +87,7 @@ } ], "env": null, - "id": "8e35ccdd-d7ba-4a51-8466-32eda77d9283", + "id": "23009046-30ce-40d4-81f4-f8e7726335a5", "init_script": "", "metadata": [], "motd_file": null, @@ -118,7 +118,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "ea281836-1a0e-4eca-a599-236c08a333b4", + "token": "3d40e367-25e5-43a3-8b7a-8528b31edbbd", "troubleshooting_url": null }, "sensitive_values": { @@ -148,14 +148,14 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 1, "values": { - "agent_id": "1e66fd1b-d220-4f86-b30c-32a9866c33d0", + "agent_id": "9c36f8be-874a-40f6-a395-f37d6d910a83", "command": null, "display_name": null, "external": false, "healthcheck": [], "hidden": false, "icon": null, - "id": "32b7f2f8-ca27-4ddd-94dd-6d8ef8f6cfba", + "id": "c8ff409a-d30d-4e62-a5a1-771f90d712ca", "open_in": "slim-window", "order": null, "share": "owner", @@ -178,7 +178,7 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 1, "values": { - "agent_id": "1e66fd1b-d220-4f86-b30c-32a9866c33d0", + "agent_id": "9c36f8be-874a-40f6-a395-f37d6d910a83", "command": null, "display_name": null, "external": false, @@ -191,7 +191,7 @@ ], "hidden": false, "icon": null, - "id": "3ef9f58a-8a2f-4be7-8134-c1ad6089f9e2", + "id": "23c1f02f-cc1a-4e64-b64f-dc2294781c14", "open_in": "slim-window", "order": null, "share": "owner", @@ -216,7 +216,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "3176283506982774871", + "id": "4679211063326469519", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/multiple-agents-multiple-scripts/multiple-agents-multiple-scripts.tfplan.json b/provisioner/terraform/testdata/multiple-agents-multiple-scripts/multiple-agents-multiple-scripts.tfplan.json index dd9ed0d4e6e39..628c97c8563ff 100644 --- a/provisioner/terraform/testdata/multiple-agents-multiple-scripts/multiple-agents-multiple-scripts.tfplan.json +++ b/provisioner/terraform/testdata/multiple-agents-multiple-scripts/multiple-agents-multiple-scripts.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "planned_values": { "root_module": { "resources": [ @@ -523,7 +523,7 @@ ] } ], - "timestamp": "2025-02-18T18:21:16Z", + "timestamp": "2025-02-18T10:58:12Z", "applyable": true, "complete": true, "errored": false diff --git a/provisioner/terraform/testdata/multiple-agents-multiple-scripts/multiple-agents-multiple-scripts.tfstate.json b/provisioner/terraform/testdata/multiple-agents-multiple-scripts/multiple-agents-multiple-scripts.tfstate.json index b228b10384554..918dccb57bd11 100644 --- a/provisioner/terraform/testdata/multiple-agents-multiple-scripts/multiple-agents-multiple-scripts.tfstate.json +++ b/provisioner/terraform/testdata/multiple-agents-multiple-scripts/multiple-agents-multiple-scripts.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -26,7 +26,7 @@ } ], "env": null, - "id": "08227630-d8d8-44a6-8d1a-c6b4e56220e6", + "id": "56eebdd7-8348-439a-8ee9-3cd9a4967479", "init_script": "", "metadata": [], "motd_file": null, @@ -35,7 +35,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "9e5b296e-3ce0-4cd8-af7d-8d702c96516e", + "token": "bc6f97e3-265d-49e9-b08b-e2bc38736da0", "troubleshooting_url": null }, "sensitive_values": { @@ -68,7 +68,7 @@ } ], "env": null, - "id": "2b0d2ea6-b448-4c31-a95d-163475818d8e", + "id": "36b8da5b-7a03-4da7-a081-f4ae599d7302", "init_script": "", "metadata": [], "motd_file": null, @@ -77,7 +77,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "81c60ec1-67f0-44d3-82af-41599fad84e1", + "token": "fa30098e-d8d2-4dad-87ad-3e0a328d2084", "troubleshooting_url": null }, "sensitive_values": { @@ -96,11 +96,11 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 1, "values": { - "agent_id": "08227630-d8d8-44a6-8d1a-c6b4e56220e6", + "agent_id": "56eebdd7-8348-439a-8ee9-3cd9a4967479", "cron": null, "display_name": "Foobar Script 1", "icon": null, - "id": "4350804c-b8b5-45c8-994e-8f7020b41b1c", + "id": "29d2f25b-f774-4bb8-9ef4-9aa03a4b3765", "log_path": null, "run_on_start": true, "run_on_stop": false, @@ -121,11 +121,11 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 1, "values": { - "agent_id": "08227630-d8d8-44a6-8d1a-c6b4e56220e6", + "agent_id": "56eebdd7-8348-439a-8ee9-3cd9a4967479", "cron": null, "display_name": "Foobar Script 2", "icon": null, - "id": "3b449c9e-48ab-4e7b-aa46-dd488ce1284c", + "id": "7e7a2376-3028-493c-8ce1-665efd6c5d9c", "log_path": null, "run_on_start": true, "run_on_stop": false, @@ -146,11 +146,11 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 1, "values": { - "agent_id": "2b0d2ea6-b448-4c31-a95d-163475818d8e", + "agent_id": "36b8da5b-7a03-4da7-a081-f4ae599d7302", "cron": null, "display_name": "Foobar Script 3", "icon": null, - "id": "2132fa1c-d2e9-4229-983f-2dfca88da420", + "id": "c6c46bde-7eff-462b-805b-82597a8095d2", "log_path": null, "run_on_start": true, "run_on_stop": false, @@ -171,7 +171,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "6203386614814118800", + "id": "3047178084751259009", "triggers": null }, "sensitive_values": {}, @@ -187,7 +187,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "3432231377698621412", + "id": "6983265822377125070", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.json b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.json index bfbdabe595cc8..bf0bd8b21d340 100644 --- a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.json +++ b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "planned_values": { "root_module": { "resources": [ @@ -431,7 +431,7 @@ ] } }, - "timestamp": "2025-02-18T18:21:16Z", + "timestamp": "2025-02-18T10:58:12Z", "applyable": true, "complete": true, "errored": false diff --git a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.json b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.json index 92835a1ab8f2c..71987deb178cc 100644 --- a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.json +++ b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -26,7 +26,7 @@ } ], "env": null, - "id": "a8594294-4a4c-4e78-95b2-569e9c050b60", + "id": "f65fcb62-ef69-44e8-b8eb-56224c9e9d6f", "init_script": "", "metadata": [], "motd_file": null, @@ -35,7 +35,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "4d6a9b4d-52f1-4243-b2b9-4d5a4f96f4bf", + "token": "57047ef7-1433-4938-a604-4dd2812b1039", "troubleshooting_url": null }, "sensitive_values": { @@ -68,7 +68,7 @@ } ], "env": null, - "id": "4724838a-a88e-45ea-a7ac-ee70a653cbfb", + "id": "d366a56f-2899-4e96-b0a1-3e97ac9bd834", "init_script": "", "metadata": [], "motd_file": "/etc/motd", @@ -77,7 +77,7 @@ "shutdown_script": "echo bye bye", "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "d579f2f2-db06-4fbc-9a8f-6d075d01e645", + "token": "59a6c328-d6ac-450d-a507-de6c14cb16d0", "troubleshooting_url": null }, "sensitive_values": { @@ -110,7 +110,7 @@ } ], "env": null, - "id": "349ebae6-324b-404a-a3b7-1a81c727a490", + "id": "907bbf6b-fa77-4138-a348-ef5d0fb98b15", "init_script": "", "metadata": [], "motd_file": null, @@ -119,7 +119,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "blocking", - "token": "0647e08f-8661-4d3b-8789-cccdcf3263e3", + "token": "7f0bb618-c82a-491b-891a-6d9f3abeeca0", "troubleshooting_url": "https://coder.com/troubleshoot" }, "sensitive_values": { @@ -152,7 +152,7 @@ } ], "env": null, - "id": "2309f077-2c30-497b-813b-bd0bba5c1bc3", + "id": "e9b11e47-0238-4915-9539-ac06617f3398", "init_script": "", "metadata": [], "motd_file": null, @@ -161,7 +161,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "b29e6471-68b5-41e8-a3c8-3192baab26c7", + "token": "102a2043-9a42-4490-b0b4-c4fb215552e0", "troubleshooting_url": null }, "sensitive_values": { @@ -180,7 +180,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "1888190210657376001", + "id": "2948336473894256689", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfplan.json b/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfplan.json index d6005bbc52040..3f18f84cf30ec 100644 --- a/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfplan.json +++ b/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "planned_values": { "root_module": { "resources": [ @@ -440,7 +440,7 @@ ] } ], - "timestamp": "2025-02-18T18:21:16Z", + "timestamp": "2025-02-18T10:58:12Z", "applyable": true, "complete": true, "errored": false diff --git a/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfstate.json b/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfstate.json index 63056d3ef93e8..9a21887d3ed4b 100644 --- a/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfstate.json +++ b/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -26,7 +26,7 @@ } ], "env": null, - "id": "623b33e1-6c61-4daf-b6b7-ac953454047f", + "id": "e7f1e434-ad52-4175-b8d1-4fab9fbe7891", "init_script": "", "metadata": [], "motd_file": null, @@ -35,7 +35,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "fc01cd68-f043-4530-a889-561b47f3ad98", + "token": "da1c4966-5bb7-459e-8b7e-ce1cf189e49d", "troubleshooting_url": null }, "sensitive_values": { @@ -54,14 +54,14 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 1, "values": { - "agent_id": "623b33e1-6c61-4daf-b6b7-ac953454047f", + "agent_id": "e7f1e434-ad52-4175-b8d1-4fab9fbe7891", "command": null, "display_name": null, "external": false, "healthcheck": [], "hidden": false, "icon": null, - "id": "3f23d7ed-6677-4eec-b9dc-d7fdb7c64dee", + "id": "41882acb-ad8c-4436-a756-e55160e2eba7", "open_in": "slim-window", "order": null, "share": "owner", @@ -84,7 +84,7 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 1, "values": { - "agent_id": "623b33e1-6c61-4daf-b6b7-ac953454047f", + "agent_id": "e7f1e434-ad52-4175-b8d1-4fab9fbe7891", "command": null, "display_name": null, "external": false, @@ -97,7 +97,7 @@ ], "hidden": false, "icon": null, - "id": "182cbdc1-246b-4b71-aa0b-4b5918e56d87", + "id": "28fb460e-746b-47b9-8c88-fc546f2ca6c4", "open_in": "slim-window", "order": null, "share": "owner", @@ -122,14 +122,14 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 1, "values": { - "agent_id": "623b33e1-6c61-4daf-b6b7-ac953454047f", + "agent_id": "e7f1e434-ad52-4175-b8d1-4fab9fbe7891", "command": null, "display_name": null, "external": false, "healthcheck": [], "hidden": false, "icon": null, - "id": "8862fa5e-846b-4fba-a5d9-892060809c1c", + "id": "2751d89f-6c41-4b50-9982-9270ba0660b0", "open_in": "slim-window", "order": null, "share": "owner", @@ -152,7 +152,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "6057067911545137976", + "id": "1493563047742372481", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfplan.json b/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfplan.json index a5138f9c49f24..078f6a63738f8 100644 --- a/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfplan.json +++ b/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "planned_values": { "root_module": { "resources": [ @@ -426,7 +426,7 @@ ] } ], - "timestamp": "2025-02-18T18:21:16Z", + "timestamp": "2025-02-18T10:58:12Z", "applyable": true, "complete": true, "errored": false diff --git a/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfstate.json b/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfstate.json index f5b3827ee4b4e..79b8ec551eb4d 100644 --- a/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfstate.json +++ b/provisioner/terraform/testdata/resource-metadata-duplicate/resource-metadata-duplicate.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -26,7 +26,7 @@ } ], "env": null, - "id": "dabcdac4-9d40-4ed3-8331-9f5b29c88b5a", + "id": "febc1e16-503f-42c3-b1ab-b067d172a860", "init_script": "", "metadata": [ { @@ -44,7 +44,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "7df37d19-71f4-4b8d-8ebb-9665787aff28", + "token": "2b609454-ea6a-4ec8-ba03-d305712894d1", "troubleshooting_url": null }, "sensitive_values": { @@ -68,7 +68,7 @@ "daily_cost": 29, "hide": true, "icon": "/icon/server.svg", - "id": "ed62b95e-6be8-4f94-a490-ea01e39c5a21", + "id": "0ea63fbe-3e81-4c34-9edc-c2b1ddc62c46", "item": [ { "is_null": false, @@ -83,7 +83,7 @@ "value": "" } ], - "resource_id": "1655456926645556376" + "resource_id": "856574543079218847" }, "sensitive_values": { "item": [ @@ -107,7 +107,7 @@ "daily_cost": 20, "hide": true, "icon": "/icon/server.svg", - "id": "1dc3e361-d9f8-44a1-8b95-1f8eb43147b6", + "id": "2a367f6b-b055-425c-bdc0-7c63cafdc146", "item": [ { "is_null": false, @@ -116,7 +116,7 @@ "value": "world" } ], - "resource_id": "1655456926645556376" + "resource_id": "856574543079218847" }, "sensitive_values": { "item": [ @@ -136,7 +136,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "1655456926645556376", + "id": "856574543079218847", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfplan.json b/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfplan.json index fd10694fb7599..f3f97e8b96897 100644 --- a/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfplan.json +++ b/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "planned_values": { "root_module": { "resources": [ @@ -378,7 +378,7 @@ ] } ], - "timestamp": "2025-02-18T18:21:16Z", + "timestamp": "2025-02-18T10:58:12Z", "applyable": true, "complete": true, "errored": false diff --git a/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfstate.json b/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfstate.json index 4b09a3d909406..5089c0b42e3e7 100644 --- a/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfstate.json +++ b/provisioner/terraform/testdata/resource-metadata/resource-metadata.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -26,7 +26,7 @@ } ], "env": null, - "id": "1f393aa3-fcce-4347-bcc1-8f0f832176fd", + "id": "bf7c9d15-6b61-4012-9cd8-10ba7ca9a4d8", "init_script": "", "metadata": [ { @@ -44,7 +44,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "ab5174ea-1047-4476-be51-57e81ffdd8ca", + "token": "91d4aa20-db80-4404-a68c-a19abeb4a5b9", "troubleshooting_url": null }, "sensitive_values": { @@ -68,7 +68,7 @@ "daily_cost": 29, "hide": true, "icon": "/icon/server.svg", - "id": "83beec7e-d68b-4712-96f3-0825092425b1", + "id": "b96f5efa-fe45-4a6a-9bd2-70e2063b7b2a", "item": [ { "is_null": false, @@ -95,7 +95,7 @@ "value": "squirrel" } ], - "resource_id": "4369933318739720708" + "resource_id": "978725577783936679" }, "sensitive_values": { "item": [ @@ -118,7 +118,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "4369933318739720708", + "id": "978725577783936679", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfplan.json b/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfplan.json index 901fd71ae6d5f..46ac62ce6f09e 100644 --- a/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfplan.json +++ b/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "planned_values": { "root_module": { "resources": [ @@ -113,7 +113,7 @@ ], "prior_state": { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -130,7 +130,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "b1e652cd-eb2c-4c6d-bc9c-3add380ffbe1", + "id": "b106fb5a-0ab1-4530-8cc0-9ff9a515dff4", "mutable": false, "name": "Example", "option": null, @@ -157,7 +157,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "af5ae8c5-fc90-4a04-9014-1708984a7b27", + "id": "5b1c2605-c7a4-4248-bf92-b761e36e0111", "mutable": false, "name": "Sample", "option": null, @@ -263,7 +263,7 @@ ] } }, - "timestamp": "2025-02-18T18:21:16Z", + "timestamp": "2025-02-18T10:58:12Z", "applyable": true, "complete": true, "errored": false diff --git a/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfstate.json b/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfstate.json index 1f5505dbaa0ac..bade7edb803c5 100644 --- a/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfstate.json +++ b/provisioner/terraform/testdata/rich-parameters-order/rich-parameters-order.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -17,7 +17,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "5aeb4a3f-99e0-4e07-b8c5-b20a2ad82b80", + "id": "3f56c659-fe68-47c3-9765-cd09abe69de7", "mutable": false, "name": "Example", "option": null, @@ -44,7 +44,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "cd792a6d-6456-46b2-afed-4893930efcb6", + "id": "2ecde94b-399a-43c7-b50a-3603895aff83", "mutable": false, "name": "Sample", "option": null, @@ -80,7 +80,7 @@ } ], "env": null, - "id": "0a162a13-6c04-402b-b568-d18ca061b63c", + "id": "a2171da1-5f68-446f-97e3-1c2755552840", "init_script": "", "metadata": [], "motd_file": null, @@ -89,7 +89,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "f15d5bd3-e9a3-40a0-8265-c2d7e46f841c", + "token": "a986f085-2697-4d95-a431-6545716ca36b", "troubleshooting_url": null }, "sensitive_values": { @@ -108,7 +108,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "4854678966366130580", + "id": "5482122353677678043", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfplan.json b/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfplan.json index 14b4604dd5574..1f7a216dc7a3f 100644 --- a/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfplan.json +++ b/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "planned_values": { "root_module": { "resources": [ @@ -113,7 +113,7 @@ ], "prior_state": { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -130,7 +130,7 @@ "display_name": null, "ephemeral": true, "icon": null, - "id": "5bb41b73-1b57-4054-82d6-a24e37f0e489", + "id": "65767637-5ffa-400f-be3f-f03868bd7070", "mutable": true, "name": "number_example", "option": null, @@ -157,7 +157,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "0906e50c-dae7-4a5f-b312-cc9acc58068b", + "id": "d8ee017a-1a92-43f2-aaa8-483573c08485", "mutable": false, "name": "number_example_max", "option": null, @@ -196,7 +196,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "86b42229-3aca-45f7-a815-986a42f75515", + "id": "1516f72d-71aa-4ae8-95b5-4dbcf999e173", "mutable": false, "name": "number_example_max_zero", "option": null, @@ -235,7 +235,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "9f920ec3-6c51-4264-bd95-ac6cdc2fce6b", + "id": "720ff4a2-4f26-42d5-a0f8-4e5c92b3133e", "mutable": false, "name": "number_example_min", "option": null, @@ -274,7 +274,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "9e89b197-3df0-46a8-925a-c523be8b38f7", + "id": "395bcef8-1f59-4a4f-b104-f0c4b6686193", "mutable": false, "name": "number_example_min_max", "option": null, @@ -313,7 +313,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "678a411a-91af-409e-b2aa-68e0cab28483", + "id": "29b2943d-e736-4635-a553-097ebe51e7ec", "mutable": false, "name": "number_example_min_zero", "option": null, @@ -545,7 +545,7 @@ ] } }, - "timestamp": "2025-02-18T18:21:16Z", + "timestamp": "2025-02-18T10:58:12Z", "applyable": true, "complete": true, "errored": false diff --git a/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfstate.json b/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfstate.json index fa86d8b2633a6..1580f18bb97d8 100644 --- a/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfstate.json +++ b/provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -17,7 +17,7 @@ "display_name": null, "ephemeral": true, "icon": null, - "id": "964932eb-2be8-4822-a0d4-38cc1259e01b", + "id": "35958620-8fa6-479e-b2aa-19202d594b03", "mutable": true, "name": "number_example", "option": null, @@ -44,7 +44,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "537335ac-ab4e-4a55-b5d9-48b005ec79e8", + "id": "518c5dad-6069-4c24-8e0b-1ee75a52da3b", "mutable": false, "name": "number_example_max", "option": null, @@ -83,7 +83,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "e127a1c4-3f28-4099-9fc1-ce3c5dd692b4", + "id": "050653a6-301b-4916-a871-32d007e1294d", "mutable": false, "name": "number_example_max_zero", "option": null, @@ -122,7 +122,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "51ab82c4-c8f7-4340-95bd-daf185c2943f", + "id": "4704cc0b-6c9d-422d-ba21-c488d780619e", "mutable": false, "name": "number_example_min", "option": null, @@ -161,7 +161,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "79d01b03-b0cf-4681-a73b-daf5ac609d4e", + "id": "a8575ac7-8cf3-4deb-a716-ab5a31467e0b", "mutable": false, "name": "number_example_min_max", "option": null, @@ -200,7 +200,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "c84de2b5-e02e-4a95-81bf-056f7b3ac9e4", + "id": "1efc1290-5939-401c-8287-7b8d6724cdb6", "mutable": false, "name": "number_example_min_zero", "option": null, @@ -248,7 +248,7 @@ } ], "env": null, - "id": "e1a0b1d6-c022-47df-8266-a1f825c95630", + "id": "356b8996-c71d-479a-b161-ac3828a1831e", "init_script": "", "metadata": [], "motd_file": null, @@ -257,7 +257,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "40aa41d9-9b4d-4627-95cf-b0812ab7197a", + "token": "27611e1a-9de5-433b-81e4-cbd9f92dfe06", "troubleshooting_url": null }, "sensitive_values": { @@ -276,7 +276,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "387589351868049923", + "id": "7456139785400247293", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfplan.json b/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfplan.json index f810ee9e7abd8..e6b5b1cab49dd 100644 --- a/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfplan.json +++ b/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfplan.json @@ -1,6 +1,6 @@ { "format_version": "1.2", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "planned_values": { "root_module": { "resources": [ @@ -113,7 +113,7 @@ ], "prior_state": { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -130,7 +130,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "52b500fb-d625-4ed7-a621-2d601dcef852", + "id": "14d20380-9100-4218-afca-15d066dec134", "mutable": false, "name": "Example", "option": [ @@ -174,7 +174,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "d9a89304-4ca4-48ab-aa1d-dd862a79f615", + "id": "fec66abe-d831-4095-8520-8a654ccf309a", "mutable": false, "name": "number_example", "option": null, @@ -201,7 +201,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "17ea5d4a-248f-4b9f-a645-afef54a4f5a0", + "id": "9e6cbf84-b49c-4c24-ad71-91195269ec84", "mutable": false, "name": "number_example_max_zero", "option": null, @@ -240,7 +240,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "eb1a6901-fb90-43f1-b573-509fde663d32", + "id": "5fbb470c-3814-4706-8fa6-c8c7e0f04c19", "mutable": false, "name": "number_example_min_max", "option": null, @@ -279,7 +279,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "7be51b9c-dc6e-4066-a57f-c169895080aa", + "id": "3790d994-f401-4e98-ad73-70b6f4e577d2", "mutable": false, "name": "number_example_min_zero", "option": null, @@ -318,7 +318,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "e8fb9b8b-9d14-4b87-9ec1-d5796a6c7d36", + "id": "26b3faa6-2eda-45f0-abbe-f4aba303f7cc", "mutable": false, "name": "Sample", "option": null, @@ -349,7 +349,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "9f121174-a611-47b6-9b1e-a03bd5c023d5", + "id": "6027c1aa-dae9-48d9-90f2-b66151bf3129", "mutable": true, "name": "First parameter from module", "option": null, @@ -376,7 +376,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "c41b68b8-f8b8-4d82-b259-6cab2a62f5ae", + "id": "62262115-184d-4e14-a756-bedb553405a9", "mutable": true, "name": "Second parameter from module", "option": null, @@ -408,7 +408,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "6bf5db78-d787-46c4-a36f-f1c1b479206f", + "id": "9ced5a2a-0e83-44fe-8088-6db4df59c15e", "mutable": true, "name": "First parameter from child module", "option": null, @@ -435,7 +435,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "30db357f-b819-4db0-ba3a-fe7bd3ed2b1a", + "id": "f9564821-9614-4931-b760-2b942d59214a", "mutable": true, "name": "Second parameter from child module", "option": null, @@ -788,7 +788,7 @@ } } }, - "timestamp": "2025-02-18T18:21:17Z", + "timestamp": "2025-02-18T10:58:12Z", "applyable": true, "complete": true, "errored": false diff --git a/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfstate.json b/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfstate.json index be9477bae7fdb..e83a026c81717 100644 --- a/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfstate.json +++ b/provisioner/terraform/testdata/rich-parameters/rich-parameters.tfstate.json @@ -1,6 +1,6 @@ { "format_version": "1.0", - "terraform_version": "1.9.8", + "terraform_version": "1.10.5", "values": { "root_module": { "resources": [ @@ -17,7 +17,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "bf439468-4a7b-44f2-a3c9-1f5ce22d5395", + "id": "bfd26633-f683-494b-8f71-1697c81488c3", "mutable": false, "name": "Example", "option": [ @@ -61,7 +61,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "a5b904c7-4304-4f53-b602-037e6c97d321", + "id": "53a78857-abc2-4447-8329-cc12e160aaba", "mutable": false, "name": "number_example", "option": null, @@ -88,7 +88,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "8af7500b-da86-4242-a351-a6cdeccdf174", + "id": "2ac0c3b2-f97f-47ad-beda-54264ba69422", "mutable": false, "name": "number_example_max_zero", "option": null, @@ -127,7 +127,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "af3488a7-2242-42e4-abec-e4e333523df5", + "id": "3b06ad67-0ab3-434c-b934-81e409e21565", "mutable": false, "name": "number_example_min_max", "option": null, @@ -166,7 +166,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "d9d7e087-99db-4a3d-88d6-07a7e80eebff", + "id": "6f7c9117-36e4-47d5-8f23-a4e495a62895", "mutable": false, "name": "number_example_min_zero", "option": null, @@ -205,7 +205,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "c000a6c6-4a97-41ef-b281-2fc6045f47c4", + "id": "5311db13-4521-4566-aac1-c70db8976ba5", "mutable": false, "name": "Sample", "option": null, @@ -241,7 +241,7 @@ } ], "env": null, - "id": "d408fac5-09cf-4435-bd19-395f98c1522e", + "id": "2d891d31-82ac-4fdd-b922-25c1dfac956c", "init_script": "", "metadata": [], "motd_file": null, @@ -250,7 +250,7 @@ "shutdown_script": null, "startup_script": null, "startup_script_behavior": "non-blocking", - "token": "1d0062ec-43ca-4c73-b9d9-01faa18c888f", + "token": "6942a4c6-24f6-42b5-bcc7-d3e26d00d950", "troubleshooting_url": null }, "sensitive_values": { @@ -269,7 +269,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "1399596486368633070", + "id": "6111468857109842799", "triggers": null }, "sensitive_values": {}, @@ -294,7 +294,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "193c4367-c1d3-45ff-903d-773980e7f930", + "id": "1adeea93-ddc4-4dd8-b328-e167161bbe84", "mutable": true, "name": "First parameter from module", "option": null, @@ -321,7 +321,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "d86af8d9-8d91-4161-9e29-02acb7a98c5e", + "id": "4bb326d9-cf43-4947-b26c-bb668a9f7a80", "mutable": true, "name": "Second parameter from module", "option": null, @@ -353,7 +353,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "bcf8f382-6ed3-4304-8ad0-b6fde8e0ae29", + "id": "a2b6d1e4-2e77-4eff-a81b-0fe285750824", "mutable": true, "name": "First parameter from child module", "option": null, @@ -380,7 +380,7 @@ "display_name": null, "ephemeral": false, "icon": null, - "id": "1db63f83-4d25-4ebb-9f20-ae34db766b2f", + "id": "9dac8aaa-ccf6-4c94-90d2-2009bfbbd596", "mutable": true, "name": "Second parameter from child module", "option": null, From 0590d77cb1514c383debbc49cc856c3bb95b886c Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 27 Feb 2025 18:01:03 +0000 Subject: [PATCH 19/20] fix migration numbers --- ...{000295_user_configs.down.sql => 000297_user_configs.down.sql} | 0 .../{000295_user_configs.up.sql => 000297_user_configs.up.sql} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename coderd/database/migrations/{000295_user_configs.down.sql => 000297_user_configs.down.sql} (100%) rename coderd/database/migrations/{000295_user_configs.up.sql => 000297_user_configs.up.sql} (100%) diff --git a/coderd/database/migrations/000295_user_configs.down.sql b/coderd/database/migrations/000297_user_configs.down.sql similarity index 100% rename from coderd/database/migrations/000295_user_configs.down.sql rename to coderd/database/migrations/000297_user_configs.down.sql diff --git a/coderd/database/migrations/000295_user_configs.up.sql b/coderd/database/migrations/000297_user_configs.up.sql similarity index 100% rename from coderd/database/migrations/000295_user_configs.up.sql rename to coderd/database/migrations/000297_user_configs.up.sql From 9360f54104a41738a7ab8d2ace097b7e2162ca10 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Wed, 5 Mar 2025 17:35:20 +0000 Subject: [PATCH 20/20] =?UTF-8?q?=F0=9F=A7=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- coderd/apidoc/docs.go | 12 +++ coderd/apidoc/swagger.json | 12 +++ ....down.sql => 000299_user_configs.down.sql} | 0 ...figs.up.sql => 000299_user_configs.up.sql} | 0 codersdk/users.go | 3 + docs/reference/api/audit.md | 1 + docs/reference/api/enterprise.md | 54 +++++++---- docs/reference/api/schemas.md | 94 +++++++++++-------- docs/reference/api/users.md | 8 ++ site/src/api/typesGenerated.ts | 1 + 10 files changed, 125 insertions(+), 60 deletions(-) rename coderd/database/migrations/{000297_user_configs.down.sql => 000299_user_configs.down.sql} (100%) rename coderd/database/migrations/{000297_user_configs.up.sql => 000299_user_configs.up.sql} (100%) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 820d10d6bb776..8f90cd5c205a2 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -13888,6 +13888,10 @@ const docTemplate = `{ } ] }, + "theme_preference": { + "description": "Deprecated: this value should be retrieved from\n` + "`" + `codersdk.UserPreferenceSettings` + "`" + ` instead.", + "type": "string" + }, "updated_at": { "type": "string", "format": "date-time" @@ -14752,6 +14756,10 @@ const docTemplate = `{ } ] }, + "theme_preference": { + "description": "Deprecated: this value should be retrieved from\n` + "`" + `codersdk.UserPreferenceSettings` + "`" + ` instead.", + "type": "string" + }, "updated_at": { "type": "string", "format": "date-time" @@ -15359,6 +15367,10 @@ const docTemplate = `{ } ] }, + "theme_preference": { + "description": "Deprecated: this value should be retrieved from\n` + "`" + `codersdk.UserPreferenceSettings` + "`" + ` instead.", + "type": "string" + }, "updated_at": { "type": "string", "format": "date-time" diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index cbb69b16306a9..fcfe56d3fc4aa 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -12565,6 +12565,10 @@ } ] }, + "theme_preference": { + "description": "Deprecated: this value should be retrieved from\n`codersdk.UserPreferenceSettings` instead.", + "type": "string" + }, "updated_at": { "type": "string", "format": "date-time" @@ -13404,6 +13408,10 @@ } ] }, + "theme_preference": { + "description": "Deprecated: this value should be retrieved from\n`codersdk.UserPreferenceSettings` instead.", + "type": "string" + }, "updated_at": { "type": "string", "format": "date-time" @@ -13963,6 +13971,10 @@ } ] }, + "theme_preference": { + "description": "Deprecated: this value should be retrieved from\n`codersdk.UserPreferenceSettings` instead.", + "type": "string" + }, "updated_at": { "type": "string", "format": "date-time" diff --git a/coderd/database/migrations/000297_user_configs.down.sql b/coderd/database/migrations/000299_user_configs.down.sql similarity index 100% rename from coderd/database/migrations/000297_user_configs.down.sql rename to coderd/database/migrations/000299_user_configs.down.sql diff --git a/coderd/database/migrations/000297_user_configs.up.sql b/coderd/database/migrations/000299_user_configs.up.sql similarity index 100% rename from coderd/database/migrations/000297_user_configs.up.sql rename to coderd/database/migrations/000299_user_configs.up.sql diff --git a/codersdk/users.go b/codersdk/users.go index b49b1afef318a..31854731a0ae1 100644 --- a/codersdk/users.go +++ b/codersdk/users.go @@ -56,6 +56,9 @@ type ReducedUser struct { Status UserStatus `json:"status" table:"status" enums:"active,suspended"` LoginType LoginType `json:"login_type"` + // Deprecated: this value should be retrieved from + // `codersdk.UserPreferenceSettings` instead. + ThemePreference string `json:"theme_preference,omitempty"` } // User represents a user in Coder. diff --git a/docs/reference/api/audit.md b/docs/reference/api/audit.md index af13e9049d0b4..3fc6e746f17c8 100644 --- a/docs/reference/api/audit.md +++ b/docs/reference/api/audit.md @@ -83,6 +83,7 @@ curl -X GET http://coder-server:8080/api/v2/audit?limit=0 \ } ], "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" }, diff --git a/docs/reference/api/enterprise.md b/docs/reference/api/enterprise.md index c18b0d5478b5e..152f331fc81d5 100644 --- a/docs/reference/api/enterprise.md +++ b/docs/reference/api/enterprise.md @@ -219,6 +219,7 @@ curl -X GET http://coder-server:8080/api/v2/groups?organization=string&has_membe "login_type": "", "name": "string", "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -259,6 +260,7 @@ Status Code **200** | `»» login_type` | [codersdk.LoginType](schemas.md#codersdklogintype) | false | | | | `»» name` | string | false | | | | `»» status` | [codersdk.UserStatus](schemas.md#codersdkuserstatus) | false | | | +| `»» theme_preference` | string | false | | Deprecated: this value should be retrieved from `codersdk.UserPreferenceSettings` instead. | | `»» updated_at` | string(date-time) | false | | | | `»» username` | string | true | | | | `» name` | string | false | | | @@ -324,6 +326,7 @@ curl -X GET http://coder-server:8080/api/v2/groups/{group} \ "login_type": "", "name": "string", "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -384,6 +387,7 @@ curl -X DELETE http://coder-server:8080/api/v2/groups/{group} \ "login_type": "", "name": "string", "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -463,6 +467,7 @@ curl -X PATCH http://coder-server:8080/api/v2/groups/{group} \ "login_type": "", "name": "string", "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -1225,6 +1230,7 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/groups "login_type": "", "name": "string", "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -1265,6 +1271,7 @@ Status Code **200** | `»» login_type` | [codersdk.LoginType](schemas.md#codersdklogintype) | false | | | | `»» name` | string | false | | | | `»» status` | [codersdk.UserStatus](schemas.md#codersdkuserstatus) | false | | | +| `»» theme_preference` | string | false | | Deprecated: this value should be retrieved from `codersdk.UserPreferenceSettings` instead. | | `»» updated_at` | string(date-time) | false | | | | `»» username` | string | true | | | | `» name` | string | false | | | @@ -1343,6 +1350,7 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/groups "login_type": "", "name": "string", "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -1404,6 +1412,7 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/groups/ "login_type": "", "name": "string", "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -2646,6 +2655,7 @@ curl -X PUT http://coder-server:8080/api/v2/scim/v2/Users/{id} \ } ], "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -2735,6 +2745,7 @@ curl -X PATCH http://coder-server:8080/api/v2/scim/v2/Users/{id} \ } ], "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -3098,6 +3109,7 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/acl \ } ], "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -3114,25 +3126,26 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/acl \ Status Code **200** -| Name | Type | Required | Restrictions | Description | -|----------------------|----------------------------------------------------------|----------|--------------|-------------| -| `[array item]` | array | false | | | -| `» avatar_url` | string(uri) | false | | | -| `» created_at` | string(date-time) | true | | | -| `» email` | string(email) | true | | | -| `» id` | string(uuid) | true | | | -| `» last_seen_at` | string(date-time) | false | | | -| `» login_type` | [codersdk.LoginType](schemas.md#codersdklogintype) | false | | | -| `» name` | string | false | | | -| `» organization_ids` | array | false | | | -| `» role` | [codersdk.TemplateRole](schemas.md#codersdktemplaterole) | false | | | -| `» roles` | array | false | | | -| `»» display_name` | string | false | | | -| `»» name` | string | false | | | -| `»» organization_id` | string | false | | | -| `» status` | [codersdk.UserStatus](schemas.md#codersdkuserstatus) | false | | | -| `» updated_at` | string(date-time) | false | | | -| `» username` | string | true | | | +| Name | Type | Required | Restrictions | Description | +|----------------------|----------------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------| +| `[array item]` | array | false | | | +| `» avatar_url` | string(uri) | false | | | +| `» created_at` | string(date-time) | true | | | +| `» email` | string(email) | true | | | +| `» id` | string(uuid) | true | | | +| `» last_seen_at` | string(date-time) | false | | | +| `» login_type` | [codersdk.LoginType](schemas.md#codersdklogintype) | false | | | +| `» name` | string | false | | | +| `» organization_ids` | array | false | | | +| `» role` | [codersdk.TemplateRole](schemas.md#codersdktemplaterole) | false | | | +| `» roles` | array | false | | | +| `»» display_name` | string | false | | | +| `»» name` | string | false | | | +| `»» organization_id` | string | false | | | +| `» status` | [codersdk.UserStatus](schemas.md#codersdkuserstatus) | false | | | +| `» theme_preference` | string | false | | Deprecated: this value should be retrieved from `codersdk.UserPreferenceSettings` instead. | +| `» updated_at` | string(date-time) | false | | | +| `» username` | string | true | | | #### Enumerated Values @@ -3253,6 +3266,7 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/acl/available \ "login_type": "", "name": "string", "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -3276,6 +3290,7 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/acl/available \ "login_type": "", "name": "string", "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -3310,6 +3325,7 @@ Status Code **200** | `»»» login_type` | [codersdk.LoginType](schemas.md#codersdklogintype) | false | | | | `»»» name` | string | false | | | | `»»» status` | [codersdk.UserStatus](schemas.md#codersdkuserstatus) | false | | | +| `»»» theme_preference` | string | false | | Deprecated: this value should be retrieved from `codersdk.UserPreferenceSettings` instead. | | `»»» updated_at` | string(date-time) | false | | | | `»»» username` | string | true | | | | `»» name` | string | false | | | diff --git a/docs/reference/api/schemas.md b/docs/reference/api/schemas.md index baf55a0fa48ac..9fa22af7356ae 100644 --- a/docs/reference/api/schemas.md +++ b/docs/reference/api/schemas.md @@ -242,6 +242,7 @@ "login_type": "", "name": "string", "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -265,6 +266,7 @@ "login_type": "", "name": "string", "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -656,6 +658,7 @@ } ], "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" }, @@ -747,6 +750,7 @@ } ], "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" }, @@ -3065,6 +3069,7 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith } ], "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -3132,6 +3137,7 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith "login_type": "", "name": "string", "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -5181,6 +5187,7 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith "login_type": "", "name": "string", "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -5188,18 +5195,19 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith ### Properties -| Name | Type | Required | Restrictions | Description | -|----------------|--------------------------------------------|----------|--------------|-------------| -| `avatar_url` | string | false | | | -| `created_at` | string | true | | | -| `email` | string | true | | | -| `id` | string | true | | | -| `last_seen_at` | string | false | | | -| `login_type` | [codersdk.LoginType](#codersdklogintype) | false | | | -| `name` | string | false | | | -| `status` | [codersdk.UserStatus](#codersdkuserstatus) | false | | | -| `updated_at` | string | false | | | -| `username` | string | true | | | +| Name | Type | Required | Restrictions | Description | +|--------------------|--------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------| +| `avatar_url` | string | false | | | +| `created_at` | string | true | | | +| `email` | string | true | | | +| `id` | string | true | | | +| `last_seen_at` | string | false | | | +| `login_type` | [codersdk.LoginType](#codersdklogintype) | false | | | +| `name` | string | false | | | +| `status` | [codersdk.UserStatus](#codersdkuserstatus) | false | | | +| `theme_preference` | string | false | | Deprecated: this value should be retrieved from `codersdk.UserPreferenceSettings` instead. | +| `updated_at` | string | false | | | +| `username` | string | true | | | #### Enumerated Values @@ -6164,6 +6172,7 @@ Restarts will only happen on weekdays in this list on weeks which line up with W } ], "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -6171,21 +6180,22 @@ Restarts will only happen on weekdays in this list on weeks which line up with W ### Properties -| Name | Type | Required | Restrictions | Description | -|--------------------|-------------------------------------------------|----------|--------------|-------------| -| `avatar_url` | string | false | | | -| `created_at` | string | true | | | -| `email` | string | true | | | -| `id` | string | true | | | -| `last_seen_at` | string | false | | | -| `login_type` | [codersdk.LoginType](#codersdklogintype) | false | | | -| `name` | string | false | | | -| `organization_ids` | array of string | false | | | -| `role` | [codersdk.TemplateRole](#codersdktemplaterole) | false | | | -| `roles` | array of [codersdk.SlimRole](#codersdkslimrole) | false | | | -| `status` | [codersdk.UserStatus](#codersdkuserstatus) | false | | | -| `updated_at` | string | false | | | -| `username` | string | true | | | +| Name | Type | Required | Restrictions | Description | +|--------------------|-------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------| +| `avatar_url` | string | false | | | +| `created_at` | string | true | | | +| `email` | string | true | | | +| `id` | string | true | | | +| `last_seen_at` | string | false | | | +| `login_type` | [codersdk.LoginType](#codersdklogintype) | false | | | +| `name` | string | false | | | +| `organization_ids` | array of string | false | | | +| `role` | [codersdk.TemplateRole](#codersdktemplaterole) | false | | | +| `roles` | array of [codersdk.SlimRole](#codersdkslimrole) | false | | | +| `status` | [codersdk.UserStatus](#codersdkuserstatus) | false | | | +| `theme_preference` | string | false | | Deprecated: this value should be retrieved from `codersdk.UserPreferenceSettings` instead. | +| `updated_at` | string | false | | | +| `username` | string | true | | | #### Enumerated Values @@ -6862,6 +6872,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| } ], "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -6869,20 +6880,21 @@ If the schedule is empty, the user will be updated to use the default schedule.| ### Properties -| Name | Type | Required | Restrictions | Description | -|--------------------|-------------------------------------------------|----------|--------------|-------------| -| `avatar_url` | string | false | | | -| `created_at` | string | true | | | -| `email` | string | true | | | -| `id` | string | true | | | -| `last_seen_at` | string | false | | | -| `login_type` | [codersdk.LoginType](#codersdklogintype) | false | | | -| `name` | string | false | | | -| `organization_ids` | array of string | false | | | -| `roles` | array of [codersdk.SlimRole](#codersdkslimrole) | false | | | -| `status` | [codersdk.UserStatus](#codersdkuserstatus) | false | | | -| `updated_at` | string | false | | | -| `username` | string | true | | | +| Name | Type | Required | Restrictions | Description | +|--------------------|-------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------| +| `avatar_url` | string | false | | | +| `created_at` | string | true | | | +| `email` | string | true | | | +| `id` | string | true | | | +| `last_seen_at` | string | false | | | +| `login_type` | [codersdk.LoginType](#codersdklogintype) | false | | | +| `name` | string | false | | | +| `organization_ids` | array of string | false | | | +| `roles` | array of [codersdk.SlimRole](#codersdkslimrole) | false | | | +| `status` | [codersdk.UserStatus](#codersdkuserstatus) | false | | | +| `theme_preference` | string | false | | Deprecated: this value should be retrieved from `codersdk.UserPreferenceSettings` instead. | +| `updated_at` | string | false | | | +| `username` | string | true | | | #### Enumerated Values diff --git a/docs/reference/api/users.md b/docs/reference/api/users.md index 275bad5ffc556..3f0c38571f7c4 100644 --- a/docs/reference/api/users.md +++ b/docs/reference/api/users.md @@ -49,6 +49,7 @@ curl -X GET http://coder-server:8080/api/v2/users \ } ], "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -124,6 +125,7 @@ curl -X POST http://coder-server:8080/api/v2/users \ } ], "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -434,6 +436,7 @@ curl -X GET http://coder-server:8080/api/v2/users/{user} \ } ], "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -1207,6 +1210,7 @@ curl -X PUT http://coder-server:8080/api/v2/users/{user}/profile \ } ], "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -1263,6 +1267,7 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/roles \ } ], "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -1331,6 +1336,7 @@ curl -X PUT http://coder-server:8080/api/v2/users/{user}/roles \ } ], "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -1387,6 +1393,7 @@ curl -X PUT http://coder-server:8080/api/v2/users/{user}/status/activate \ } ], "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } @@ -1443,6 +1450,7 @@ curl -X PUT http://coder-server:8080/api/v2/users/{user}/status/suspend \ } ], "status": "active", + "theme_preference": "string", "updated_at": "2019-08-24T14:15:22Z", "username": "string" } diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index d2f5cd073b085..222c07575b969 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1970,6 +1970,7 @@ export interface ReducedUser extends MinimalUser { readonly last_seen_at: string; readonly status: UserStatus; readonly login_type: LoginType; + readonly theme_preference?: string; } // From codersdk/workspaceproxy.go 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