Show visibility status of email in own profile (#23900)

I've heard many reports of users getting scared when they see their own
email address for their own profile, as they believe that the email
field is also visible to other users. Currently, using Incognito mode
or going over the Settings is the only "reasonable" way to verify this
from the perspective of the user.

A locked padlock should be enough to indicate that the email is not
visible to anyone apart from the user and the admins. An unlocked
padlock is used if the email address is only shown to authenticated
users.

Some additional string-related changes in the Settings were introduced
as well to ensure consistency, and the comments in the relevant tests
were improved so as to allow for easier modifications in the future.

---

#### Screenshot (EDIT: Scroll down for more up-to-date screenshots)

***Please remove this section before merging.***


![image](https://user-images.githubusercontent.com/30193966/229572425-909894aa-a7d5-4bf3-92d3-23b1921dcc90.png)

This lock should only appear if the email address is explicitly hidden
using the `Hide Email Address` setting. The change was originally tested
on top of and designed for the Forgejo fork, but I don't expect any
problems to arise from this and I don't think that a
documentation-related change is strictly necessary.

---------

Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
n0toose 2023-04-08 10:05:21 +00:00 committed by GitHub
parent 3037922a9b
commit 5e1bd8af5f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 13 deletions

View file

@ -548,6 +548,8 @@ unfollow = Unfollow
heatmap.loading = Loading Heatmap… heatmap.loading = Loading Heatmap…
user_bio = Biography user_bio = Biography
disabled_public_activity = This user has disabled the public visibility of the activity. disabled_public_activity = This user has disabled the public visibility of the activity.
email_visibility.limited = Your email address is visible to all authenticated users
email_visibility.private = Your email address is only visible to you and administrators
form.name_reserved = The username '%s' is reserved. form.name_reserved = The username '%s' is reserved.
form.name_pattern_not_allowed = The pattern '%s' is not allowed in a username. form.name_pattern_not_allowed = The pattern '%s' is not allowed in a username.
@ -661,7 +663,7 @@ add_email_success = The new email address has been added.
email_preference_set_success = Email preference has been set successfully. email_preference_set_success = Email preference has been set successfully.
add_openid_success = The new OpenID address has been added. add_openid_success = The new OpenID address has been added.
keep_email_private = Hide Email Address keep_email_private = Hide Email Address
keep_email_private_popup = Your email address will be hidden from other users. keep_email_private_popup = Your email address will only be visible to you and the administrators
openid_desc = OpenID lets you delegate authentication to an external provider. openid_desc = OpenID lets you delegate authentication to an external provider.
manage_ssh_keys = Manage SSH Keys manage_ssh_keys = Manage SSH Keys
@ -842,9 +844,9 @@ email_notifications.andyourown = And Your Own Notifications
visibility = User visibility visibility = User visibility
visibility.public = Public visibility.public = Public
visibility.public_tooltip = Visible to all users visibility.public_tooltip = Visible to everyone
visibility.limited = Limited visibility.limited = Limited
visibility.limited_tooltip = Visible to logged in users only visibility.limited_tooltip = Visible to authenticated users only
visibility.private = Private visibility.private = Private
visibility.private_tooltip = Visible only to organization members visibility.private_tooltip = Visible only to organization members
@ -2421,7 +2423,7 @@ settings.permission = Permissions
settings.repoadminchangeteam = Repository admin can add and remove access for teams settings.repoadminchangeteam = Repository admin can add and remove access for teams
settings.visibility = Visibility settings.visibility = Visibility
settings.visibility.public = Public settings.visibility.public = Public
settings.visibility.limited = Limited (Visible to logged in users only) settings.visibility.limited = Limited (Visible to authenticated users only)
settings.visibility.limited_shortname = Limited settings.visibility.limited_shortname = Limited
settings.visibility.private = Private (Visible only to organization members) settings.visibility.private = Private (Visible only to organization members)
settings.visibility.private_shortname = Private settings.visibility.private_shortname = Private

View file

@ -30,11 +30,29 @@
{{if .Owner.Location}} {{if .Owner.Location}}
<li>{{svg "octicon-location"}} {{.Owner.Location}}</li> <li>{{svg "octicon-location"}} {{.Owner.Location}}</li>
{{end}} {{end}}
{{if .ShowUserEmail}} {{if (eq .SignedUserName .Owner.Name)}}
<li> <li>
{{svg "octicon-mail"}} {{svg "octicon-mail"}}
<a href="mailto:{{.Owner.Email}}" rel="nofollow">{{.Owner.Email}}</a> <a href="mailto:{{.Owner.Email}}" rel="nofollow">{{.Owner.Email}}</a>
<a href="{{AppSubUrl}}/user/settings#keep-email-private">
{{if .ShowUserEmail}}
<i class="ui right" data-tooltip-content="{{.locale.Tr "user.email_visibility.limited"}}">
{{svg "octicon-unlock"}}
</i>
{{else}}
<i class="ui right" data-tooltip-content="{{.locale.Tr "user.email_visibility.private"}}">
{{svg "octicon-lock"}}
</i>
{{end}}
</a>
</li> </li>
{{else}}
{{if .ShowUserEmail}}
<li>
{{svg "octicon-mail"}}
<a href="mailto:{{.Owner.Email}}" rel="nofollow">{{.Owner.Email}}</a>
</li>
{{end}}
{{end}} {{end}}
{{if .Owner.Website}} {{if .Owner.Website}}
<li> <li>

View file

@ -50,42 +50,42 @@ func TestSettingShowUserEmailProfile(t *testing.T) {
setting.UI.ShowUserEmail = true setting.UI.ShowUserEmail = true
// user1 can see self // user1 can see own visible email
session := loginUser(t, "user1") session := loginUser(t, "user1")
req := NewRequest(t, "GET", "/user1") req := NewRequest(t, "GET", "/user1")
resp := session.MakeRequest(t, req, http.StatusOK) resp := session.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body) htmlDoc := NewHTMLParser(t, resp.Body)
assert.Contains(t, htmlDoc.doc.Find(".user.profile").Text(), "user1@example.com") assert.Contains(t, htmlDoc.doc.Find(".user.profile").Text(), "user1@example.com")
// user1 can not see user2 // user1 can not see user2's hidden email
req = NewRequest(t, "GET", "/user2") req = NewRequest(t, "GET", "/user2")
resp = session.MakeRequest(t, req, http.StatusOK) resp = session.MakeRequest(t, req, http.StatusOK)
htmlDoc = NewHTMLParser(t, resp.Body) htmlDoc = NewHTMLParser(t, resp.Body)
// Should not contain even if the user visits their own profile page // Should only contain if the user visits their own profile page
assert.NotContains(t, htmlDoc.doc.Find(".user.profile").Text(), "user2@example.com") assert.NotContains(t, htmlDoc.doc.Find(".user.profile").Text(), "user2@example.com")
// user2 can see user1 // user2 can see user1's visible email
session = loginUser(t, "user2") session = loginUser(t, "user2")
req = NewRequest(t, "GET", "/user1") req = NewRequest(t, "GET", "/user1")
resp = session.MakeRequest(t, req, http.StatusOK) resp = session.MakeRequest(t, req, http.StatusOK)
htmlDoc = NewHTMLParser(t, resp.Body) htmlDoc = NewHTMLParser(t, resp.Body)
assert.Contains(t, htmlDoc.doc.Find(".user.profile").Text(), "user1@example.com") assert.Contains(t, htmlDoc.doc.Find(".user.profile").Text(), "user1@example.com")
// user2 can not see self // user2 can see own hidden email
session = loginUser(t, "user2") session = loginUser(t, "user2")
req = NewRequest(t, "GET", "/user2") req = NewRequest(t, "GET", "/user2")
resp = session.MakeRequest(t, req, http.StatusOK) resp = session.MakeRequest(t, req, http.StatusOK)
htmlDoc = NewHTMLParser(t, resp.Body) htmlDoc = NewHTMLParser(t, resp.Body)
assert.NotContains(t, htmlDoc.doc.Find(".user.profile").Text(), "user2@example.com") assert.Contains(t, htmlDoc.doc.Find(".user.profile").Text(), "user2@example.com")
setting.UI.ShowUserEmail = false setting.UI.ShowUserEmail = false
// user1 can not see self // user1 can see own (now hidden) email
session = loginUser(t, "user1") session = loginUser(t, "user1")
req = NewRequest(t, "GET", "/user1") req = NewRequest(t, "GET", "/user1")
resp = session.MakeRequest(t, req, http.StatusOK) resp = session.MakeRequest(t, req, http.StatusOK)
htmlDoc = NewHTMLParser(t, resp.Body) htmlDoc = NewHTMLParser(t, resp.Body)
assert.NotContains(t, htmlDoc.doc.Find(".user.profile").Text(), "user1@example.com") assert.Contains(t, htmlDoc.doc.Find(".user.profile").Text(), "user1@example.com")
setting.UI.ShowUserEmail = showUserEmail setting.UI.ShowUserEmail = showUserEmail
} }