feat: add pronoun privacy option (#6773)

This commit contains UI changes, tests and migrations for a feature
that lets users optionally hide their pronouns from the general
public. This is useful if a person wants to disclose that
information to a smaller set of people on a local instance
belonging to a local community/association.

Co-authored-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Beowulf <beowulf@beocode.eu>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/6773
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Panagiotis "Ivory" Vasilopoulos <git@n0toose.net>
Co-committed-by: Panagiotis "Ivory" Vasilopoulos <git@n0toose.net>
This commit is contained in:
Panagiotis "Ivory" Vasilopoulos 2025-02-15 13:07:15 +00:00 committed by Gusted
parent 7104c73c96
commit a1486b0ee4
17 changed files with 158 additions and 25 deletions

View file

@ -45,6 +45,7 @@
full_name: ' < U<se>r Tw<o > >< '
email: user2@example.com
keep_email_private: true
keep_pronouns_private: true
email_notifications_preference: enabled
passwd: ZogKvWdyEx:password
passwd_hash_algo: dummy
@ -350,6 +351,7 @@
full_name: User Ten
email: user10@example.com
keep_email_private: false
keep_pronouns_private: true
email_notifications_preference: enabled
passwd: ZogKvWdyEx:password
passwd_hash_algo: dummy

View file

@ -92,6 +92,8 @@ var migrations = []*Migration{
NewMigration("Add `hash_blake2b` column to `package_blob` table", AddHashBlake2bToPackageBlob),
// v27 -> v28
NewMigration("Add `created_unix` column to `user_redirect` table", AddCreatedUnixToRedirect),
// v28 -> v29
NewMigration("Add pronoun privacy settings to user", AddHidePronounsOptionToUser),
}
// GetCurrentDBVersion returns the current Forgejo database version.

View file

@ -0,0 +1,15 @@
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgejo_migrations //nolint:revive
import "xorm.io/xorm"
func AddHidePronounsOptionToUser(x *xorm.Engine) error {
type User struct {
ID int64 `xorm:"pk autoincr"`
KeepPronounsPrivate bool `xorm:"NOT NULL DEFAULT false"`
}
return x.Sync(&User{})
}

View file

@ -154,6 +154,7 @@ type User struct {
DiffViewStyle string `xorm:"NOT NULL DEFAULT ''"`
Theme string `xorm:"NOT NULL DEFAULT ''"`
KeepActivityPrivate bool `xorm:"NOT NULL DEFAULT false"`
KeepPronounsPrivate bool `xorm:"NOT NULL DEFAULT false"`
EnableRepoUnitHints bool `xorm:"NOT NULL DEFAULT true"`
}
@ -500,6 +501,16 @@ func (u *User) GetCompleteName() string {
return u.Name
}
// GetPronouns returns an empty string, if the user has set to keep his
// pronouns private from non-logged in users, otherwise the pronouns
// are returned.
func (u *User) GetPronouns(signed bool) string {
if u.KeepPronounsPrivate && !signed {
return ""
}
return u.Pronouns
}
func gitSafeName(name string) string {
return strings.TrimSpace(strings.NewReplacer("\n", "", "<", "", ">", "").Replace(name))
}

View file

@ -795,3 +795,42 @@ func TestGetInactiveUsers(t *testing.T) {
require.NoError(t, err)
require.Empty(t, users)
}
func TestPronounsPrivacy(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
t.Run("EmptyPronounsIfNoneSet", func(t *testing.T) {
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
user.Pronouns = ""
user.KeepPronounsPrivate = false
assert.Equal(t, "", user.GetPronouns(false))
})
t.Run("EmptyPronounsIfSetButPrivateAndNotLoggedIn", func(t *testing.T) {
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
user.Pronouns = "any"
user.KeepPronounsPrivate = true
assert.Equal(t, "", user.GetPronouns(false))
})
t.Run("ReturnPronounsIfSetAndNotPrivateAndNotLoggedIn", func(t *testing.T) {
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
user.Pronouns = "any"
user.KeepPronounsPrivate = false
assert.Equal(t, "any", user.GetPronouns(false))
})
t.Run("ReturnPronounsIfSetAndPrivateAndLoggedIn", func(t *testing.T) {
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
user.Pronouns = "any"
user.KeepPronounsPrivate = false
assert.Equal(t, "any", user.GetPronouns(true))
})
t.Run("ReturnPronounsIfSetAndNotPrivateAndLoggedIn", func(t *testing.T) {
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
user.Pronouns = "any"
user.KeepPronounsPrivate = true
assert.Equal(t, "any", user.GetPronouns(true))
})
}