feat(ui): better activity messages for cases of private profiles (#5638)
* added a message for the case where the user's profile is private but the Public activity is not hidden The activity is still hidden anyway because the profile is private, but previously the message would say: `Your activity is visible to everyone, except for interactions in private spaces...` which I would consider as a flaw of the original implementation. Now it will say: `Your activity is only visible to you and the instance administrators because your profile is private...` * started showing the message for admins that the activity they see should remain private in the case where the whole profile is private, not just the activity tab. Previously it would say: This activity is visible to everyone, but as an administrator you can also see interactions in private spaces.` which I would also consider as a flaw of the original implementation. Now it will say: `This activity is visible to you because you're an administrator, but the user wants it to remain private.` * added test cases * bumped up the number of our GPL-licensed files Preview For both screenshots, Forgejo would previously display misinformation. Change 1: User viewing their private profile, but activity isn't configured as hidden https://codeberg.org/attachments/6659c80c-15dd-48be-a379-db737fd1dd5e Change 2: Admin viewing user's private profile https://codeberg.org/attachments/220da57f-b658-4474-9ad2-049e8438a0af Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/5638 Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org> Reviewed-by: Gusted <gusted@noreply.codeberg.org>
This commit is contained in:
parent
f298bf125a
commit
3e1d5cc447
4 changed files with 41 additions and 6 deletions
|
@ -712,6 +712,7 @@ public_activity.visibility_hint.self_public = Your activity is visible to everyo
|
||||||
public_activity.visibility_hint.admin_public = This activity is visible to everyone, but as an administrator you can also see interactions in private spaces.
|
public_activity.visibility_hint.admin_public = This activity is visible to everyone, but as an administrator you can also see interactions in private spaces.
|
||||||
public_activity.visibility_hint.self_private = Your activity is only visible to you and the instance administrators. <a href="%s">Configure</a>.
|
public_activity.visibility_hint.self_private = Your activity is only visible to you and the instance administrators. <a href="%s">Configure</a>.
|
||||||
public_activity.visibility_hint.admin_private = This activity is visible to you because you're an administrator, but the user wants it to remain private.
|
public_activity.visibility_hint.admin_private = This activity is visible to you because you're an administrator, but the user wants it to remain private.
|
||||||
|
public_activity.visibility_hint.self_private_profile = Your activity is only visible to you and the instance administrators because your profile is private. <a href="%s">Configure</a>.
|
||||||
|
|
||||||
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.
|
||||||
|
|
|
@ -13,14 +13,18 @@
|
||||||
<p id="visibility-hint">
|
<p id="visibility-hint">
|
||||||
{{if .ContextUser.KeepActivityPrivate}}
|
{{if .ContextUser.KeepActivityPrivate}}
|
||||||
{{ctx.Locale.Tr "user.public_activity.visibility_hint.self_private" "/user/settings#keep-activity-private"}}
|
{{ctx.Locale.Tr "user.public_activity.visibility_hint.self_private" "/user/settings#keep-activity-private"}}
|
||||||
|
{{else}}
|
||||||
|
{{if eq .ContextUser.Visibility 2}}
|
||||||
|
{{ctx.Locale.Tr "user.public_activity.visibility_hint.self_private_profile" "/user/settings#visibility-setting"}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{ctx.Locale.Tr "user.public_activity.visibility_hint.self_public" "/user/settings#keep-activity-private"}}
|
{{ctx.Locale.Tr "user.public_activity.visibility_hint.self_public" "/user/settings#keep-activity-private"}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
{{end}}
|
||||||
</p>
|
</p>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{if .IsAdmin}}
|
{{if .IsAdmin}}
|
||||||
<div id="visibility-hint" class="ui info message">
|
<div id="visibility-hint" class="ui info message">
|
||||||
{{if .ContextUser.KeepActivityPrivate}}
|
{{if or .ContextUser.KeepActivityPrivate (eq .ContextUser.Visibility 2)}}
|
||||||
{{ctx.Locale.Tr "user.public_activity.visibility_hint.admin_private"}}
|
{{ctx.Locale.Tr "user.public_activity.visibility_hint.admin_private"}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{ctx.Locale.Tr "user.public_activity.visibility_hint.admin_public"}}
|
{{ctx.Locale.Tr "user.public_activity.visibility_hint.admin_public"}}
|
||||||
|
|
|
@ -76,7 +76,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="inline field {{if .Err_Visibility}}error{{end}}">
|
<div class="inline field {{if .Err_Visibility}}error{{end}}">
|
||||||
<span class="inline required field"><label>{{ctx.Locale.Tr "settings.visibility"}}</label></span>
|
<span class="inline required field" id="visibility-setting"><label>{{ctx.Locale.Tr "settings.visibility"}}</label></span>
|
||||||
<div class="ui selection type dropdown">
|
<div class="ui selection type dropdown">
|
||||||
{{if .SignedUser.Visibility.IsPublic}}<input type="hidden" id="visibility" name="visibility" value="0">{{end}}
|
{{if .SignedUser.Visibility.IsPublic}}<input type="hidden" id="visibility" name="visibility" value="0">{{end}}
|
||||||
{{if .SignedUser.Visibility.IsLimited}}<input type="hidden" id="visibility" name="visibility" value="1">{{end}}
|
{{if .SignedUser.Visibility.IsLimited}}<input type="hidden" id="visibility" name="visibility" value="1">{{end}}
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/structs"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,6 +19,9 @@ import (
|
||||||
// - Public activity tab
|
// - Public activity tab
|
||||||
// - Banner/hint in the tab
|
// - Banner/hint in the tab
|
||||||
// - "Configure" link in the hint
|
// - "Configure" link in the hint
|
||||||
|
// These elements might depend on the following:
|
||||||
|
// - Profile visibility
|
||||||
|
// - Public activity visibility
|
||||||
func TestUserProfileActivity(t *testing.T) {
|
func TestUserProfileActivity(t *testing.T) {
|
||||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||||
// This test needs multiple users with different access statuses to check for all possible states
|
// This test needs multiple users with different access statuses to check for all possible states
|
||||||
|
@ -24,7 +30,7 @@ func TestUserProfileActivity(t *testing.T) {
|
||||||
// Activity availability should be the same for guest and another non-admin user, so this is not tested separately
|
// Activity availability should be the same for guest and another non-admin user, so this is not tested separately
|
||||||
userGuest := emptyTestSession(t)
|
userGuest := emptyTestSession(t)
|
||||||
|
|
||||||
// = Public =
|
// = Public profile, public activity =
|
||||||
|
|
||||||
// Set activity visibility of user2 to public. This is the default, but won't hurt to set it before testing.
|
// Set activity visibility of user2 to public. This is the default, but won't hurt to set it before testing.
|
||||||
testChangeUserActivityVisibility(t, userRegular, "off")
|
testChangeUserActivityVisibility(t, userRegular, "off")
|
||||||
|
@ -48,7 +54,22 @@ func TestUserProfileActivity(t *testing.T) {
|
||||||
assert.EqualValues(t, "/user2?tab=activity", activityLink)
|
assert.EqualValues(t, "/user2?tab=activity", activityLink)
|
||||||
}
|
}
|
||||||
|
|
||||||
// = Private =
|
// = Private profile, but public activity =
|
||||||
|
|
||||||
|
// Set profile visibility of user2 to private
|
||||||
|
testChangeUserProfileVisibility(t, userRegular, structs.VisibleTypePrivate)
|
||||||
|
|
||||||
|
// When profile activity is configured as public, but the profile is private, tell the user about this and link to visibility settings.
|
||||||
|
hintLink = testUser2ActivityVisibility(t, userRegular, "Your activity is only visible to you and the instance administrators because your profile is private. Configure.", true)
|
||||||
|
assert.EqualValues(t, "/user/settings#visibility-setting", hintLink)
|
||||||
|
|
||||||
|
// When the profile is private, tell the admin about this.
|
||||||
|
testUser2ActivityVisibility(t, userAdmin, "This activity is visible to you because you're an administrator, but the user wants it to remain private.", true)
|
||||||
|
|
||||||
|
// Set profile visibility of user2 back to public
|
||||||
|
testChangeUserProfileVisibility(t, userRegular, structs.VisibleTypePublic)
|
||||||
|
|
||||||
|
// = Private acitivty =
|
||||||
|
|
||||||
// Set activity visibility of user2 to private
|
// Set activity visibility of user2 to private
|
||||||
testChangeUserActivityVisibility(t, userRegular, "on")
|
testChangeUserActivityVisibility(t, userRegular, "on")
|
||||||
|
@ -78,6 +99,15 @@ func testChangeUserActivityVisibility(t *testing.T, session *TestSession, newSta
|
||||||
}), http.StatusSeeOther)
|
}), http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// testChangeUserProfileVisibility allows to easily change visibility of user's profile
|
||||||
|
func testChangeUserProfileVisibility(t *testing.T, session *TestSession, newValue structs.VisibleType) {
|
||||||
|
t.Helper()
|
||||||
|
session.MakeRequest(t, NewRequestWithValues(t, "POST", "/user/settings", map[string]string{
|
||||||
|
"_csrf": GetCSRF(t, session, "/user/settings"),
|
||||||
|
"visibility": strconv.Itoa(int(newValue)),
|
||||||
|
}), http.StatusSeeOther)
|
||||||
|
}
|
||||||
|
|
||||||
// testUser2ActivityVisibility checks visibility of UI elements on /<user>?tab=activity
|
// testUser2ActivityVisibility checks visibility of UI elements on /<user>?tab=activity
|
||||||
// It also returns the account visibility link if it is present on the page.
|
// It also returns the account visibility link if it is present on the page.
|
||||||
func testUser2ActivityVisibility(t *testing.T, session *TestSession, hint string, availability bool) string {
|
func testUser2ActivityVisibility(t *testing.T, session *TestSession, hint string, availability bool) string {
|
||||||
|
|
Loading…
Reference in a new issue