chore: add "user_configs" db table (#16564)

This commit is contained in:
ケイラ
2025-03-05 10:46:03 -07:00
committed by GitHub
parent cc946f199d
commit 9041646b81
47 changed files with 786 additions and 394 deletions
+7 -9
View File
@@ -150,14 +150,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),
}
}
@@ -176,7 +175,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,
}
+15 -4
View File
@@ -2510,6 +2510,17 @@ 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) {
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)
}
func (q *querier) GetUserByEmailOrUsername(ctx context.Context, arg database.GetUserByEmailOrUsernameParams) (database.User, error) {
return fetch(q.log, q.auth, q.db.GetUserByEmailOrUsername)(ctx, arg)
}
@@ -4021,13 +4032,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)
}
+17 -4
View File
@@ -1522,13 +1522,26 @@ 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{
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{})
-1
View File
@@ -528,7 +528,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,
+60 -39
View File
@@ -55,44 +55,45 @@ 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),
InboxNotification: make([]database.InboxNotification, 0),
organizationMembers: make([]database.OrganizationMember, 0),
organizations: make([]database.Organization, 0),
inboxNotifications: make([]database.InboxNotification, 0),
parameterSchemas: make([]database.ParameterSchema, 0),
presets: make([]database.TemplateVersionPreset, 0),
presetParameters: make([]database.TemplateVersionPresetParameter, 0),
provisionerDaemons: make([]database.ProvisionerDaemon, 0),
provisionerKeys: make([]database.ProvisionerKey, 0),
workspaceAgents: make([]database.WorkspaceAgent, 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),
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.
@@ -207,7 +208,7 @@ type data struct {
notificationMessages []database.NotificationMessage
notificationPreferences []database.NotificationPreference
notificationReportGeneratorLogs []database.NotificationReportGeneratorLog
InboxNotification []database.InboxNotification
inboxNotifications []database.InboxNotification
oauth2ProviderApps []database.OAuth2ProviderApp
oauth2ProviderAppSecrets []database.OAuth2ProviderAppSecret
oauth2ProviderAppCodes []database.OAuth2ProviderAppCode
@@ -224,6 +225,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
@@ -899,7 +901,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,
@@ -1725,7 +1726,7 @@ func (q *FakeQuerier) CountUnreadInboxNotificationsByUserID(_ context.Context, u
defer q.mutex.RUnlock()
var count int64
for _, notification := range q.InboxNotification {
for _, notification := range q.inboxNotifications {
if notification.UserID != userID {
continue
}
@@ -3295,7 +3296,7 @@ func (q *FakeQuerier) GetFilteredInboxNotificationsByUserID(_ context.Context, a
defer q.mutex.RUnlock()
notifications := make([]database.InboxNotification, 0)
for _, notification := range q.InboxNotification {
for _, notification := range q.inboxNotifications {
if notification.UserID == arg.UserID {
for _, template := range arg.Templates {
templateFound := false
@@ -3531,7 +3532,7 @@ func (q *FakeQuerier) GetInboxNotificationByID(_ context.Context, id uuid.UUID)
q.mutex.RLock()
defer q.mutex.RUnlock()
for _, notification := range q.InboxNotification {
for _, notification := range q.inboxNotifications {
if notification.ID == id {
return notification, nil
}
@@ -3545,7 +3546,7 @@ func (q *FakeQuerier) GetInboxNotificationsByUserID(_ context.Context, params da
defer q.mutex.RUnlock()
notifications := make([]database.InboxNotification, 0)
for _, notification := range q.InboxNotification {
for _, notification := range q.inboxNotifications {
if notification.UserID == params.UserID {
notifications = append(notifications, notification)
}
@@ -6162,6 +6163,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
@@ -8211,7 +8226,7 @@ func (q *FakeQuerier) InsertInboxNotification(_ context.Context, arg database.In
CreatedAt: time.Now(),
}
q.InboxNotification = append(q.InboxNotification, notification)
q.inboxNotifications = append(q.inboxNotifications, notification)
return notification, nil
}
@@ -9938,9 +9953,9 @@ func (q *FakeQuerier) UpdateInboxNotificationReadStatus(_ context.Context, arg d
q.mutex.Lock()
defer q.mutex.Unlock()
for i := range q.InboxNotification {
if q.InboxNotification[i].ID == arg.ID {
q.InboxNotification[i].ReadAt = arg.ReadAt
for i := range q.inboxNotifications {
if q.inboxNotifications[i].ID == arg.ID {
q.inboxNotifications[i].ReadAt = arg.ReadAt
}
}
@@ -10454,24 +10469,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 {
@@ -12862,7 +12884,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,
+8 -1
View File
@@ -1403,6 +1403,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)
@@ -2551,7 +2558,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())
+17 -2
View File
@@ -2932,6 +2932,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()
@@ -5399,10 +5414,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
}
+12 -4
View File
@@ -849,7 +849,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,
@@ -859,8 +858,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.';
@@ -892,7 +889,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,
@@ -1547,6 +1543,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,
@@ -2199,6 +2201,9 @@ ALTER TABLE ONLY template_versions
ALTER TABLE ONLY templates
ADD CONSTRAINT templates_pkey PRIMARY KEY (id);
ALTER TABLE ONLY user_configs
ADD CONSTRAINT user_configs_pkey PRIMARY KEY (user_id, key);
ALTER TABLE ONLY user_deleted
ADD CONSTRAINT user_deleted_pkey PRIMARY KEY (id);
@@ -2613,6 +2618,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);
@@ -51,6 +51,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);
@@ -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
SET theme_preference = (SELECT value
FROM user_configs
WHERE user_configs.user_id = users.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).';
@@ -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,
PRIMARY KEY (user_id, key),
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
);
-- Copy "theme_preference" from "users" table
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;
+13 -14
View File
@@ -406,20 +406,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,
}
}
-2
View File
@@ -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,
@@ -505,7 +504,6 @@ func (q *sqlQuerier) GetAuthorizedAuditLogsOffset(ctx context.Context, arg GetAu
&i.UserRoles,
&i.UserAvatarUrl,
&i.UserDeleted,
&i.UserThemePreference,
&i.UserQuietHoursSchedule,
&i.OrganizationName,
&i.OrganizationDisplayName,
+6 -3
View File
@@ -2605,7 +2605,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"`
@@ -3176,8 +3175,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.
@@ -3188,6 +3185,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"`
+2 -1
View File
@@ -306,6 +306,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)
@@ -522,7 +523,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
+47 -63
View File
@@ -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,
@@ -608,7 +607,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"`
@@ -669,7 +667,6 @@ func (q *sqlQuerier) GetAuditLogsOffset(ctx context.Context, arg GetAuditLogsOff
&i.UserRoles,
&i.UserAvatarUrl,
&i.UserDeleted,
&i.UserThemePreference,
&i.UserQuietHoursSchedule,
&i.OrganizationName,
&i.OrganizationDisplayName,
@@ -1582,7 +1579,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) {
@@ -1608,7 +1605,6 @@ func (q *sqlQuerier) GetGroupMembers(ctx context.Context) ([]GroupMember, error)
&i.UserDeleted,
&i.UserLastSeenAt,
&i.UserQuietHoursSchedule,
&i.UserThemePreference,
&i.UserName,
&i.UserGithubComUserID,
&i.OrganizationID,
@@ -1629,7 +1625,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) {
@@ -1655,7 +1651,6 @@ func (q *sqlQuerier) GetGroupMembersByGroupID(ctx context.Context, groupID uuid.
&i.UserDeleted,
&i.UserLastSeenAt,
&i.UserQuietHoursSchedule,
&i.UserThemePreference,
&i.UserName,
&i.UserGithubComUserID,
&i.OrganizationID,
@@ -7777,7 +7772,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
@@ -11359,9 +11354,26 @@ 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, 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
@@ -11393,7 +11405,6 @@ func (q *sqlQuerier) GetUserByEmailOrUsername(ctx context.Context, arg GetUserBy
&i.Deleted,
&i.LastSeenAt,
&i.QuietHoursSchedule,
&i.ThemePreference,
&i.Name,
&i.GithubComUserID,
&i.HashedOneTimePasscode,
@@ -11404,7 +11415,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
@@ -11430,7 +11441,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,
@@ -11457,7 +11467,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
@@ -11567,7 +11577,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"`
@@ -11610,7 +11619,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,
@@ -11631,7 +11639,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
@@ -11660,7 +11668,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,
@@ -11698,7 +11705,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 {
@@ -11742,7 +11749,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,
@@ -11804,45 +11810,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 user_configs_pkey
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
}
@@ -11928,7 +11918,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 {
@@ -11954,7 +11944,6 @@ func (q *sqlQuerier) UpdateUserLastSeenAt(ctx context.Context, arg UpdateUserLas
&i.Deleted,
&i.LastSeenAt,
&i.QuietHoursSchedule,
&i.ThemePreference,
&i.Name,
&i.GithubComUserID,
&i.HashedOneTimePasscode,
@@ -11976,7 +11965,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 {
@@ -12001,7 +11990,6 @@ func (q *sqlQuerier) UpdateUserLoginType(ctx context.Context, arg UpdateUserLogi
&i.Deleted,
&i.LastSeenAt,
&i.QuietHoursSchedule,
&i.ThemePreference,
&i.Name,
&i.GithubComUserID,
&i.HashedOneTimePasscode,
@@ -12021,7 +12009,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 {
@@ -12057,7 +12045,6 @@ func (q *sqlQuerier) UpdateUserProfile(ctx context.Context, arg UpdateUserProfil
&i.Deleted,
&i.LastSeenAt,
&i.QuietHoursSchedule,
&i.ThemePreference,
&i.Name,
&i.GithubComUserID,
&i.HashedOneTimePasscode,
@@ -12073,7 +12060,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 {
@@ -12098,7 +12085,6 @@ func (q *sqlQuerier) UpdateUserQuietHoursSchedule(ctx context.Context, arg Updat
&i.Deleted,
&i.LastSeenAt,
&i.QuietHoursSchedule,
&i.ThemePreference,
&i.Name,
&i.GithubComUserID,
&i.HashedOneTimePasscode,
@@ -12115,7 +12101,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 {
@@ -12140,7 +12126,6 @@ func (q *sqlQuerier) UpdateUserRoles(ctx context.Context, arg UpdateUserRolesPar
&i.Deleted,
&i.LastSeenAt,
&i.QuietHoursSchedule,
&i.ThemePreference,
&i.Name,
&i.GithubComUserID,
&i.HashedOneTimePasscode,
@@ -12156,7 +12141,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 {
@@ -12182,7 +12167,6 @@ func (q *sqlQuerier) UpdateUserStatus(ctx context.Context, arg UpdateUserStatusP
&i.Deleted,
&i.LastSeenAt,
&i.QuietHoursSchedule,
&i.ThemePreference,
&i.Name,
&i.GithubComUserID,
&i.HashedOneTimePasscode,
-1
View File
@@ -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,
+20 -7
View File
@@ -98,14 +98,27 @@ SET
WHERE
id = $1;
-- name: UpdateUserAppearanceSettings :one
UPDATE
users
SET
theme_preference = $2,
updated_at = $3
-- name: GetUserAppearanceSettings :one
SELECT
value as theme_preference
FROM
user_configs
WHERE
id = $1
user_id = @user_id
AND key = 'theme_preference';
-- name: UpdateUserAppearanceSettings :one
INSERT INTO
user_configs (user_id, key, value)
VALUES
(@user_id, 'theme_preference', @theme_preference)
ON CONFLICT
ON CONSTRAINT user_configs_pkey
DO UPDATE
SET
value = @theme_preference
WHERE user_configs.user_id = @user_id
AND user_configs.key = 'theme_preference'
RETURNING *;
-- name: UpdateUserRoles :one
+1
View File
@@ -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);
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);