Skip to content

feat: support multiple terminal fonts #17257

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Apr 7, 2025
20 changes: 20 additions & 0 deletions coderd/apidoc/docs.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 16 additions & 1 deletion coderd/apidoc/swagger.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

66 changes: 44 additions & 22 deletions coderd/database/dbauthz/dbauthz.go
Original file line number Diff line number Diff line change
Expand Up @@ -2711,17 +2711,6 @@ 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)
}
Expand Down Expand Up @@ -2794,6 +2783,28 @@ func (q *querier) GetUserStatusCounts(ctx context.Context, arg database.GetUserS
return q.db.GetUserStatusCounts(ctx, arg)
}

func (q *querier) GetUserTerminalFont(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.GetUserTerminalFont(ctx, userID)
}

func (q *querier) GetUserThemePreference(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.GetUserThemePreference(ctx, userID)
}

func (q *querier) GetUserWorkspaceBuildParameters(ctx context.Context, params database.GetUserWorkspaceBuildParametersParams) ([]database.GetUserWorkspaceBuildParametersRow, error) {
u, err := q.db.GetUserByID(ctx, params.OwnerID)
if err != nil {
Expand Down Expand Up @@ -4311,17 +4322,6 @@ 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.UserConfig, error) {
u, err := q.db.GetUserByID(ctx, arg.UserID)
if err != nil {
return database.UserConfig{}, err
}
if err := q.authorizeContext(ctx, policy.ActionUpdatePersonal, u); err != nil {
return database.UserConfig{}, err
}
return q.db.UpdateUserAppearanceSettings(ctx, arg)
}

func (q *querier) UpdateUserDeletedByID(ctx context.Context, id uuid.UUID) error {
return deleteQ(q.log, q.auth, q.db.GetUserByID, q.db.UpdateUserDeletedByID)(ctx, id)
}
Expand Down Expand Up @@ -4459,6 +4459,28 @@ func (q *querier) UpdateUserStatus(ctx context.Context, arg database.UpdateUserS
return updateWithReturn(q.log, q.auth, fetch, q.db.UpdateUserStatus)(ctx, arg)
}

func (q *querier) UpdateUserTerminalFont(ctx context.Context, arg database.UpdateUserTerminalFontParams) (database.UserConfig, error) {
u, err := q.db.GetUserByID(ctx, arg.UserID)
if err != nil {
return database.UserConfig{}, err
}
if err := q.authorizeContext(ctx, policy.ActionUpdatePersonal, u); err != nil {
return database.UserConfig{}, err
}
return q.db.UpdateUserTerminalFont(ctx, arg)
}

func (q *querier) UpdateUserThemePreference(ctx context.Context, arg database.UpdateUserThemePreferenceParams) (database.UserConfig, error) {
u, err := q.db.GetUserByID(ctx, arg.UserID)
if err != nil {
return database.UserConfig{}, err
}
if err := q.authorizeContext(ctx, policy.ActionUpdatePersonal, u); err != nil {
return database.UserConfig{}, err
}
return q.db.UpdateUserThemePreference(ctx, arg)
}

func (q *querier) UpdateVolumeResourceMonitor(ctx context.Context, arg database.UpdateVolumeResourceMonitorParams) error {
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil {
return err
Expand Down
29 changes: 25 additions & 4 deletions coderd/database/dbauthz/dbauthz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1630,27 +1630,48 @@ func (s *MethodTestSuite) TestUser() {
[]database.GetUserWorkspaceBuildParametersRow{},
)
}))
s.Run("GetUserAppearanceSettings", s.Subtest(func(db database.Store, check *expects) {
s.Run("GetUserThemePreference", s.Subtest(func(db database.Store, check *expects) {
ctx := context.Background()
u := dbgen.User(s.T(), db, database.User{})
db.UpdateUserAppearanceSettings(ctx, database.UpdateUserAppearanceSettingsParams{
db.UpdateUserThemePreference(ctx, database.UpdateUserThemePreferenceParams{
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) {
s.Run("UpdateUserThemePreference", 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{
check.Args(database.UpdateUserThemePreferenceParams{
UserID: u.ID,
ThemePreference: uc.Value,
}).Asserts(u, policy.ActionUpdatePersonal).Returns(uc)
}))
s.Run("GetUserTerminalFont", s.Subtest(func(db database.Store, check *expects) {
ctx := context.Background()
u := dbgen.User(s.T(), db, database.User{})
db.UpdateUserTerminalFont(ctx, database.UpdateUserTerminalFontParams{
UserID: u.ID,
TerminalFont: "ibm-plex-mono",
})
check.Args(u.ID).Asserts(u, policy.ActionReadPersonal).Returns("ibm-plex-mono")
}))
s.Run("UpdateUserTerminalFont", s.Subtest(func(db database.Store, check *expects) {
u := dbgen.User(s.T(), db, database.User{})
uc := database.UserConfig{
UserID: u.ID,
Key: "terminal_font",
Value: "ibm-plex-mono",
}
check.Args(database.UpdateUserTerminalFontParams{
UserID: u.ID,
TerminalFont: 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{})
check.Args(database.UpdateUserStatusParams{
Expand Down
123 changes: 82 additions & 41 deletions coderd/database/dbmem/dbmem.go
Original file line number Diff line number Diff line change
Expand Up @@ -6434,20 +6434,6 @@ 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
Expand Down Expand Up @@ -6660,6 +6646,34 @@ func (q *FakeQuerier) GetUserStatusCounts(_ context.Context, arg database.GetUse
return result, nil
}

func (q *FakeQuerier) GetUserTerminalFont(ctx 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 != "terminal_font" {
continue
}
return uc.Value, nil
}

return "", sql.ErrNoRows
}

func (q *FakeQuerier) GetUserThemePreference(_ 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) GetUserWorkspaceBuildParameters(_ context.Context, params database.GetUserWorkspaceBuildParametersParams) ([]database.GetUserWorkspaceBuildParametersRow, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()
Expand Down Expand Up @@ -10996,33 +11010,6 @@ func (q *FakeQuerier) UpdateTemplateWorkspacesLastUsedAt(_ context.Context, arg
return nil
}

func (q *FakeQuerier) UpdateUserAppearanceSettings(_ context.Context, arg database.UpdateUserAppearanceSettingsParams) (database.UserConfig, error) {
err := validateDatabaseType(arg)
if err != nil {
return database.UserConfig{}, err
}

q.mutex.Lock()
defer q.mutex.Unlock()

for i, uc := range q.userConfigs {
if uc.UserID != arg.UserID || uc.Key != "theme_preference" {
continue
}
uc.Value = arg.ThemePreference
q.userConfigs[i] = uc
return uc, nil
}

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 {
q.mutex.Lock()
defer q.mutex.Unlock()
Expand Down Expand Up @@ -11348,6 +11335,60 @@ func (q *FakeQuerier) UpdateUserStatus(_ context.Context, arg database.UpdateUse
return database.User{}, sql.ErrNoRows
}

func (q *FakeQuerier) UpdateUserTerminalFont(ctx context.Context, arg database.UpdateUserTerminalFontParams) (database.UserConfig, error) {
err := validateDatabaseType(arg)
if err != nil {
return database.UserConfig{}, err
}

q.mutex.Lock()
defer q.mutex.Unlock()

for i, uc := range q.userConfigs {
if uc.UserID != arg.UserID || uc.Key != "terminal_font" {
continue
}
uc.Value = arg.TerminalFont
q.userConfigs[i] = uc
return uc, nil
}

uc := database.UserConfig{
UserID: arg.UserID,
Key: "terminal_font",
Value: arg.TerminalFont,
}
q.userConfigs = append(q.userConfigs, uc)
return uc, nil
}

func (q *FakeQuerier) UpdateUserThemePreference(_ context.Context, arg database.UpdateUserThemePreferenceParams) (database.UserConfig, error) {
err := validateDatabaseType(arg)
if err != nil {
return database.UserConfig{}, err
}

q.mutex.Lock()
defer q.mutex.Unlock()

for i, uc := range q.userConfigs {
if uc.UserID != arg.UserID || uc.Key != "theme_preference" {
continue
}
uc.Value = arg.ThemePreference
q.userConfigs[i] = uc
return uc, nil
}

uc := database.UserConfig{
UserID: arg.UserID,
Key: "theme_preference",
Value: arg.ThemePreference,
}
q.userConfigs = append(q.userConfigs, uc)
return uc, nil
}

func (q *FakeQuerier) UpdateVolumeResourceMonitor(_ context.Context, arg database.UpdateVolumeResourceMonitorParams) error {
err := validateDatabaseType(arg)
if err != nil {
Expand Down
Loading
Loading