From 3533dddc0c01f7dcf2d9999c2d004e2f56cf6774 Mon Sep 17 00:00:00 2001 From: Jonas Lochmann Date: Mon, 4 May 2020 02:00:00 +0200 Subject: [PATCH 01/10] Add hide activity option This closes https://github.com/go-gitea/gitea/issues/7927 --- models/action.go | 6 ++++++ models/migrations/migrations.go | 2 ++ models/migrations/v139.go | 22 ++++++++++++++++++++++ models/user.go | 5 +++-- models/user_heatmap.go | 5 +++++ modules/auth/user_form.go | 17 +++++++++-------- options/locale/locale_en-US.ini | 4 ++++ routers/user/home.go | 4 +++- routers/user/profile.go | 4 +++- routers/user/setting/profile.go | 1 + templates/user/profile.tmpl | 5 +++++ templates/user/settings/profile.tmpl | 7 +++++++ 12 files changed, 70 insertions(+), 12 deletions(-) create mode 100644 models/migrations/v139.go diff --git a/models/action.go b/models/action.go index fd49c6d4ed3d3..fbd70119b9635 100644 --- a/models/action.go +++ b/models/action.go @@ -319,6 +319,12 @@ func GetFeeds(opts GetFeedsOptions) ([]*Action, error) { cond = cond.And(builder.In("repo_id", AccessibleRepoIDsQuery(opts.Actor))) } + if (opts.Actor == nil || opts.Actor.IsAdmin == false) { + if (opts.RequestedUser.KeepActivityPrivate && actorID != opts.RequestedUser.ID) { + return make([]*Action, 0, 0), nil + } + } + cond = cond.And(builder.Eq{"user_id": opts.RequestedUser.ID}) if opts.OnlyPerformedBy { diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 6868aad7b190a..c049701dd29f2 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -210,6 +210,8 @@ var migrations = []Migration{ NewMigration("Add Branch Protection Block Outdated Branch", addBlockOnOutdatedBranch), // v138 -> v139 NewMigration("Add ResolveDoerID to Comment table", addResolveDoerIDCommentColumn), + // v139 -> 140 + NewMigration("Add KeepActivityPrivate to User table", addKeepActivityPrivateUserColumn), } // GetCurrentDBVersion returns the current db version diff --git a/models/migrations/v139.go b/models/migrations/v139.go new file mode 100644 index 0000000000000..b5824ecd48db2 --- /dev/null +++ b/models/migrations/v139.go @@ -0,0 +1,22 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package migrations + +import ( + "fmt" + + "xorm.io/xorm" +) + +func addKeepActivityPrivateUserColumn(x *xorm.Engine) error { + type User struct { + KeepActivityPrivate bool + } + + if err := x.Sync2(new(User)); err != nil { + return fmt.Errorf("Sync2: %v", err) + } + return nil +} diff --git a/models/user.go b/models/user.go index a89eb144cedc4..0d911eecd69d3 100644 --- a/models/user.go +++ b/models/user.go @@ -163,8 +163,9 @@ type User struct { RepoAdminChangeTeamAccess bool `xorm:"NOT NULL DEFAULT false"` // Preferences - DiffViewStyle string `xorm:"NOT NULL DEFAULT ''"` - Theme string `xorm:"NOT NULL DEFAULT ''"` + DiffViewStyle string `xorm:"NOT NULL DEFAULT ''"` + Theme string `xorm:"NOT NULL DEFAULT ''"` + KeepActivityPrivate bool `xorm:"NOT NULL DEFAULT false"` } // SearchOrganizationsOptions options to filter organizations diff --git a/models/user_heatmap.go b/models/user_heatmap.go index 3d9e0683fc786..7599edf9c3486 100644 --- a/models/user_heatmap.go +++ b/models/user_heatmap.go @@ -18,6 +18,11 @@ type UserHeatmapData struct { // GetUserHeatmapDataByUser returns an array of UserHeatmapData func GetUserHeatmapDataByUser(user *User) ([]*UserHeatmapData, error) { hdata := make([]*UserHeatmapData, 0) + + if (user.KeepActivityPrivate) { + return hdata, nil + } + var groupBy string var groupByName = "timestamp" // We need this extra case because mssql doesn't allow grouping by alias switch { diff --git a/modules/auth/user_form.go b/modules/auth/user_form.go index 228e17dce5921..0d799995762ff 100644 --- a/modules/auth/user_form.go +++ b/modules/auth/user_form.go @@ -196,14 +196,15 @@ func (f *AccessTokenForm) Validate(ctx *macaron.Context, errs binding.Errors) bi // UpdateProfileForm form for updating profile type UpdateProfileForm struct { - Name string `binding:"AlphaDashDot;MaxSize(40)"` - FullName string `binding:"MaxSize(100)"` - Email string `binding:"Required;Email;MaxSize(254)"` - KeepEmailPrivate bool - Website string `binding:"ValidUrl;MaxSize(255)"` - Location string `binding:"MaxSize(50)"` - Language string `binding:"Size(5)"` - Description string `binding:"MaxSize(255)"` + Name string `binding:"AlphaDashDot;MaxSize(40)"` + FullName string `binding:"MaxSize(100)"` + Email string `binding:"Required;Email;MaxSize(254)"` + KeepEmailPrivate bool + Website string `binding:"ValidUrl;MaxSize(255)"` + Location string `binding:"MaxSize(50)"` + Language string `binding:"Size(5)"` + Description string `binding:"MaxSize(255)"` + KeepActivityPrivate bool } // Validate validates the fields diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 4d01a6be968ce..9b9285aa5cef5 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -381,6 +381,7 @@ follow = Follow unfollow = Unfollow heatmap.loading = Loading Heatmap… user_bio = Biography +disabled_public_activity = This user has disabled the public visibility of the activity. Only the user itself and admins can see it. form.name_reserved = The username '%s' is reserved. form.name_pattern_not_allowed = The pattern '%s' is not allowed in a username. @@ -419,6 +420,9 @@ continue = Continue cancel = Cancel language = Language ui = Theme +privacy = Privacy +keep_activity_private = Hide the activity from the profile page +keep_activity_private_popup = Makes the activity visible only for you and the admins lookup_avatar_by_mail = Look Up Avatar by Email Address federated_avatar_lookup = Federated Avatar Lookup diff --git a/routers/user/home.go b/routers/user/home.go index 816968562fd60..72c568204b5ff 100644 --- a/routers/user/home.go +++ b/routers/user/home.go @@ -111,7 +111,9 @@ func Dashboard(ctx *context.Context) { ctx.Data["PageIsDashboard"] = true ctx.Data["PageIsNews"] = true ctx.Data["SearchLimit"] = setting.UI.User.RepoPagingNum - ctx.Data["EnableHeatmap"] = setting.Service.EnableUserHeatmap + // no heatmap access for admins; GetUserHeatmapDataByUser ignores the calling user + // so everyone would get the same empty heatmap + ctx.Data["EnableHeatmap"] = setting.Service.EnableUserHeatmap && ctxUser.KeepActivityPrivate == false ctx.Data["HeatmapUser"] = ctxUser.Name var err error diff --git a/routers/user/profile.go b/routers/user/profile.go index 215dff0084b15..51f1feb73b0c6 100644 --- a/routers/user/profile.go +++ b/routers/user/profile.go @@ -93,7 +93,9 @@ func Profile(ctx *context.Context) { ctx.Data["PageIsUserProfile"] = true ctx.Data["Owner"] = ctxUser ctx.Data["OpenIDs"] = openIDs - ctx.Data["EnableHeatmap"] = setting.Service.EnableUserHeatmap + // no heatmap access for admins; GetUserHeatmapDataByUser ignores the calling user + // so everyone would get the same empty heatmap + ctx.Data["EnableHeatmap"] = setting.Service.EnableUserHeatmap && ctxUser.KeepActivityPrivate == false ctx.Data["HeatmapUser"] = ctxUser.Name showPrivate := ctx.IsSigned && (ctx.User.IsAdmin || ctx.User.ID == ctxUser.ID) diff --git a/routers/user/setting/profile.go b/routers/user/setting/profile.go index d6f25f9135871..ba9ba2b257fa9 100644 --- a/routers/user/setting/profile.go +++ b/routers/user/setting/profile.go @@ -96,6 +96,7 @@ func ProfilePost(ctx *context.Context, form auth.UpdateProfileForm) { ctx.User.Location = form.Location ctx.User.Language = form.Language ctx.User.Description = form.Description + ctx.User.KeepActivityPrivate = form.KeepActivityPrivate if err := models.UpdateUserSetting(ctx.User); err != nil { if _, ok := err.(models.ErrEmailAlreadyUsed); ok { ctx.Flash.Error(ctx.Tr("form.email_been_used")) diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl index f3cac7befb9a0..7bdbec4c5282b 100644 --- a/templates/user/profile.tmpl +++ b/templates/user/profile.tmpl @@ -104,6 +104,11 @@ {{if eq .TabName "activity"}} + {{if .Owner.KeepActivityPrivate}} +
+

{{.i18n.Tr "user.disabled_public_activity"}}

+
+ {{end}} {{if .EnableHeatmap}}
diff --git a/templates/user/settings/profile.tmpl b/templates/user/settings/profile.tmpl index 995bdfd6381e6..b170c6757961e 100644 --- a/templates/user/settings/profile.tmpl +++ b/templates/user/settings/profile.tmpl @@ -58,6 +58,13 @@
+
+ +
+ + +
+
From 0786fb5ee586bd138ea246361336bceeb4b62e78 Mon Sep 17 00:00:00 2001 From: Jonas Lochmann Date: Mon, 4 May 2020 02:00:00 +0200 Subject: [PATCH 02/10] Adjust for linter --- models/action.go | 4 ++-- models/user.go | 6 +++--- models/user_heatmap.go | 2 +- routers/user/home.go | 2 +- routers/user/profile.go | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/models/action.go b/models/action.go index fbd70119b9635..a4eb3aca09738 100644 --- a/models/action.go +++ b/models/action.go @@ -319,8 +319,8 @@ func GetFeeds(opts GetFeedsOptions) ([]*Action, error) { cond = cond.And(builder.In("repo_id", AccessibleRepoIDsQuery(opts.Actor))) } - if (opts.Actor == nil || opts.Actor.IsAdmin == false) { - if (opts.RequestedUser.KeepActivityPrivate && actorID != opts.RequestedUser.ID) { + if opts.Actor == nil || opts.Actor.IsAdmin == false { + if opts.RequestedUser.KeepActivityPrivate && actorID != opts.RequestedUser.ID { return make([]*Action, 0, 0), nil } } diff --git a/models/user.go b/models/user.go index 0d911eecd69d3..9f558487d5af5 100644 --- a/models/user.go +++ b/models/user.go @@ -163,9 +163,9 @@ type User struct { RepoAdminChangeTeamAccess bool `xorm:"NOT NULL DEFAULT false"` // Preferences - DiffViewStyle string `xorm:"NOT NULL DEFAULT ''"` - Theme string `xorm:"NOT NULL DEFAULT ''"` - KeepActivityPrivate bool `xorm:"NOT NULL DEFAULT false"` + DiffViewStyle string `xorm:"NOT NULL DEFAULT ''"` + Theme string `xorm:"NOT NULL DEFAULT ''"` + KeepActivityPrivate bool `xorm:"NOT NULL DEFAULT false"` } // SearchOrganizationsOptions options to filter organizations diff --git a/models/user_heatmap.go b/models/user_heatmap.go index 7599edf9c3486..ce3ec029cae88 100644 --- a/models/user_heatmap.go +++ b/models/user_heatmap.go @@ -19,7 +19,7 @@ type UserHeatmapData struct { func GetUserHeatmapDataByUser(user *User) ([]*UserHeatmapData, error) { hdata := make([]*UserHeatmapData, 0) - if (user.KeepActivityPrivate) { + if user.KeepActivityPrivate { return hdata, nil } diff --git a/routers/user/home.go b/routers/user/home.go index 72c568204b5ff..4a1afd0b93286 100644 --- a/routers/user/home.go +++ b/routers/user/home.go @@ -113,7 +113,7 @@ func Dashboard(ctx *context.Context) { ctx.Data["SearchLimit"] = setting.UI.User.RepoPagingNum // no heatmap access for admins; GetUserHeatmapDataByUser ignores the calling user // so everyone would get the same empty heatmap - ctx.Data["EnableHeatmap"] = setting.Service.EnableUserHeatmap && ctxUser.KeepActivityPrivate == false + ctx.Data["EnableHeatmap"] = setting.Service.EnableUserHeatmap && !ctxUser.KeepActivityPrivate ctx.Data["HeatmapUser"] = ctxUser.Name var err error diff --git a/routers/user/profile.go b/routers/user/profile.go index 51f1feb73b0c6..82fab4ad87278 100644 --- a/routers/user/profile.go +++ b/routers/user/profile.go @@ -95,7 +95,7 @@ func Profile(ctx *context.Context) { ctx.Data["OpenIDs"] = openIDs // no heatmap access for admins; GetUserHeatmapDataByUser ignores the calling user // so everyone would get the same empty heatmap - ctx.Data["EnableHeatmap"] = setting.Service.EnableUserHeatmap && ctxUser.KeepActivityPrivate == false + ctx.Data["EnableHeatmap"] = setting.Service.EnableUserHeatmap && !ctxUser.KeepActivityPrivate ctx.Data["HeatmapUser"] = ctxUser.Name showPrivate := ctx.IsSigned && (ctx.User.IsAdmin || ctx.User.ID == ctxUser.ID) From 9b626570d83e7604fa6847957184972573550132 Mon Sep 17 00:00:00 2001 From: Jonas Lochmann Date: Mon, 4 May 2020 02:00:00 +0200 Subject: [PATCH 03/10] Adjust for linter --- models/action.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/models/action.go b/models/action.go index a4eb3aca09738..59ccdb2d4c871 100644 --- a/models/action.go +++ b/models/action.go @@ -319,9 +319,9 @@ func GetFeeds(opts GetFeedsOptions) ([]*Action, error) { cond = cond.And(builder.In("repo_id", AccessibleRepoIDsQuery(opts.Actor))) } - if opts.Actor == nil || opts.Actor.IsAdmin == false { + if opts.Actor == nil || !opts.Actor.IsAdmin { if opts.RequestedUser.KeepActivityPrivate && actorID != opts.RequestedUser.ID { - return make([]*Action, 0, 0), nil + return make([]*Action, 0), nil } } From e22de2b1bd0bf1fd1f96161f1b0502e13134f681 Mon Sep 17 00:00:00 2001 From: Jonas Lochmann Date: Mon, 11 May 2020 02:00:00 +0200 Subject: [PATCH 04/10] Add tests --- integrations/privateactivity_test.go | 414 +++++++++++++++++++++++++++ 1 file changed, 414 insertions(+) create mode 100644 integrations/privateactivity_test.go diff --git a/integrations/privateactivity_test.go b/integrations/privateactivity_test.go new file mode 100644 index 0000000000000..c88d9ad9ebd56 --- /dev/null +++ b/integrations/privateactivity_test.go @@ -0,0 +1,414 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package integrations + +import ( + "fmt" + "net/http" + "testing" + + "code.gitea.io/gitea/models" + api "code.gitea.io/gitea/modules/structs" + + "github.com/stretchr/testify/assert" +) + +const privateActivityTestAdmin = "user1" +const privateActivityTestUser = "user2" + +// user3 is an organization so it is not usable here +const privateActivityTestOtherUser = "user4" + +// activity helpers + +func testPrivateActivityDoSomethingForActionEntries(t *testing.T) { + repoBefore := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) + owner := models.AssertExistsAndLoadBean(t, &models.User{ID: repoBefore.OwnerID}).(*models.User) + + session := loginUser(t, privateActivityTestUser) + token := getTokenForLoggedInUser(t, session) + urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues?state=all&token=%s", owner.Name, repoBefore.Name, token) + req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateIssueOption{ + Body: "test", + Title: "test", + }) + session.MakeRequest(t, req, http.StatusCreated) +} + +// private activity helpers + +func testPrivateActivityHelperEnablePrivateActivity(t *testing.T) { + session := loginUser(t, privateActivityTestUser) + req := NewRequestWithValues(t, "POST", "/user/settings", map[string]string{ + "_csrf": GetCSRF(t, session, "/user/settings"), + "name": privateActivityTestUser, + "email": privateActivityTestUser + "@example.com", + "language": "en-us", + "keep_activity_private": "1", + }) + session.MakeRequest(t, req, http.StatusFound) +} + +func testPrivateActivityHelperHasVisibleActivitiesInHtmlDoc(htmlDoc *HTMLDoc) bool { + return htmlDoc.doc.Find(".feeds").Find(".news").Length() > 0 +} + +func testPrivateActivityHelperHasVisibleActivitiesFromSession(t *testing.T, session *TestSession) bool { + req := NewRequestf(t, "GET", "/%s?tab=activity", privateActivityTestUser) + resp := session.MakeRequest(t, req, http.StatusOK) + + htmlDoc := NewHTMLParser(t, resp.Body) + + return testPrivateActivityHelperHasVisibleActivitiesInHtmlDoc(htmlDoc) +} + +func testPrivateActivityHelperHasVisibleActivitiesFromPublic(t *testing.T) bool { + req := NewRequestf(t, "GET", "/%s?tab=activity", privateActivityTestUser) + resp := MakeRequest(t, req, http.StatusOK) + + htmlDoc := NewHTMLParser(t, resp.Body) + + return testPrivateActivityHelperHasVisibleActivitiesInHtmlDoc(htmlDoc) +} + +// heatmap UI helpers + +func testPrivateActivityHelperHasVisibleHeatmapInHtmlDoc(htmlDoc *HTMLDoc) bool { + return htmlDoc.doc.Find("#user-heatmap").Length() > 0 +} + +func testPrivateActivityHelperHasVisibleProfileHeatmapFromSession(t *testing.T, session *TestSession) bool { + req := NewRequestf(t, "GET", "/%s?tab=activity", privateActivityTestUser) + resp := session.MakeRequest(t, req, http.StatusOK) + + htmlDoc := NewHTMLParser(t, resp.Body) + + return testPrivateActivityHelperHasVisibleHeatmapInHtmlDoc(htmlDoc) +} + +func testPrivateActivityHelperHasVisibleDashboardHeatmapFromSession(t *testing.T, session *TestSession) bool { + req := NewRequest(t, "GET", "/") + resp := session.MakeRequest(t, req, http.StatusOK) + + htmlDoc := NewHTMLParser(t, resp.Body) + + return testPrivateActivityHelperHasVisibleHeatmapInHtmlDoc(htmlDoc) +} + +func testPrivateActivityHelperHasVisibleHeatmapFromPublic(t *testing.T) bool { + req := NewRequestf(t, "GET", "/%s?tab=activity", privateActivityTestUser) + resp := MakeRequest(t, req, http.StatusOK) + + htmlDoc := NewHTMLParser(t, resp.Body) + + return testPrivateActivityHelperHasVisibleHeatmapInHtmlDoc(htmlDoc) +} + +// heatmap API helpers + +func testPrivateActivityHelperHasHeatmapContentFromPublic(t *testing.T) bool { + req := NewRequestf(t, "GET", "/api/v1/users/%s/heatmap", privateActivityTestUser) + resp := MakeRequest(t, req, http.StatusOK) + + var items []*models.UserHeatmapData + DecodeJSON(t, resp, &items) + + return len(items) != 0 +} + +func testPrivateActivityHelperHasHeatmapContentFromSession(t *testing.T, session *TestSession) bool { + token := getTokenForLoggedInUser(t, session) + + req := NewRequestf(t, "GET", "/api/v1/users/%s/heatmap?token=%s", privateActivityTestUser, token) + resp := session.MakeRequest(t, req, http.StatusOK) + + var items []*models.UserHeatmapData + DecodeJSON(t, resp, &items) + + return len(items) != 0 +} + +// check activity visibility if the visibility is enabled + +func TestPrivateActivityNoVisibleForPublic(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + + visible := testPrivateActivityHelperHasVisibleActivitiesFromPublic(t) + + assert.True(t, visible, "user should have visible activities") +} + +func TestPrivateActivityNoVisibleForUserItself(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + + session := loginUser(t, privateActivityTestUser) + visible := testPrivateActivityHelperHasVisibleActivitiesFromSession(t, session) + + assert.True(t, visible, "user should have visible activities") +} + +func TestPrivateActivityNoVisibleForOtherUser(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + + session := loginUser(t, privateActivityTestOtherUser) + visible := testPrivateActivityHelperHasVisibleActivitiesFromSession(t, session) + + assert.True(t, visible, "user should have visible activities") +} + +func TestPrivateActivityNoVisibleForAdmin(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + + session := loginUser(t, privateActivityTestAdmin) + visible := testPrivateActivityHelperHasVisibleActivitiesFromSession(t, session) + + assert.True(t, visible, "user should have visible activities") +} + +// check activity visibility if the visibility is disabled + +func TestPrivateActivityYesInvisibleForPublic(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + testPrivateActivityHelperEnablePrivateActivity(t) + + visible := testPrivateActivityHelperHasVisibleActivitiesFromPublic(t) + + assert.False(t, visible, "user should have no visible activities") +} + +func TestPrivateActivityYesVisibleForUserItself(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + testPrivateActivityHelperEnablePrivateActivity(t) + + session := loginUser(t, privateActivityTestUser) + visible := testPrivateActivityHelperHasVisibleActivitiesFromSession(t, session) + + assert.True(t, visible, "user should have visible activities") +} + +func TestPrivateActivityYesInvisibleForOtherUser(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + testPrivateActivityHelperEnablePrivateActivity(t) + + session := loginUser(t, privateActivityTestOtherUser) + visible := testPrivateActivityHelperHasVisibleActivitiesFromSession(t, session) + + assert.False(t, visible, "user should have no visible activities") +} + +func TestPrivateActivityYesVisibleForAdmin(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + testPrivateActivityHelperEnablePrivateActivity(t) + + session := loginUser(t, privateActivityTestAdmin) + visible := testPrivateActivityHelperHasVisibleActivitiesFromSession(t, session) + + assert.True(t, visible, "user should have visible activities") +} + +// check heatmap visibility if the visibility is enabled + +func TestPrivateActivityNoHeatmapVisibleForPublic(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + + visible := testPrivateActivityHelperHasVisibleHeatmapFromPublic(t) + + assert.True(t, visible, "user should have visible heatmap") +} + +func TestPrivateActivityNoHeatmapVisibleForUserItselfAtProfile(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + + session := loginUser(t, privateActivityTestUser) + visible := testPrivateActivityHelperHasVisibleProfileHeatmapFromSession(t, session) + + assert.True(t, visible, "user should have visible heatmap") +} + +func TestPrivateActivityNoHeatmapVisibleForUserItselfAtDashboard(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + + session := loginUser(t, privateActivityTestUser) + visible := testPrivateActivityHelperHasVisibleDashboardHeatmapFromSession(t, session) + + assert.True(t, visible, "user should have visible heatmap") +} + +func TestPrivateActivityNoHeatmapVisibleForOtherUser(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + + session := loginUser(t, privateActivityTestOtherUser) + visible := testPrivateActivityHelperHasVisibleProfileHeatmapFromSession(t, session) + + assert.True(t, visible, "user should have visible heatmap") +} + +func TestPrivateActivityNoHeatmapVisibleForAdmin(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + + session := loginUser(t, privateActivityTestAdmin) + visible := testPrivateActivityHelperHasVisibleProfileHeatmapFromSession(t, session) + + assert.True(t, visible, "user should have visible heatmap") +} + +// check heatmap visibility if the visibility is disabled +// this behavior, in special the one for the admin, is +// due to the fact that the heatmap is the same for all viewers; +// otherwise, there is no reason for it + +func TestPrivateActivityYesHeatmapInvisibleForPublic(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + testPrivateActivityHelperEnablePrivateActivity(t) + + visible := testPrivateActivityHelperHasVisibleHeatmapFromPublic(t) + + assert.False(t, visible, "user should have no visible heatmap") +} + +func TestPrivateActivityYesHeatmapInvisibleForUserItselfAtProfile(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + testPrivateActivityHelperEnablePrivateActivity(t) + + session := loginUser(t, privateActivityTestUser) + visible := testPrivateActivityHelperHasVisibleProfileHeatmapFromSession(t, session) + + assert.False(t, visible, "user should have no visible heatmap") +} + +func TestPrivateActivityYesHeatmapInvisibleForUserItselfAtDashboard(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + testPrivateActivityHelperEnablePrivateActivity(t) + + session := loginUser(t, privateActivityTestUser) + visible := testPrivateActivityHelperHasVisibleDashboardHeatmapFromSession(t, session) + + assert.False(t, visible, "user should have no visible heatmap") +} + +func TestPrivateActivityYesHeatmapInvisibleForOtherUser(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + testPrivateActivityHelperEnablePrivateActivity(t) + + session := loginUser(t, privateActivityTestOtherUser) + visible := testPrivateActivityHelperHasVisibleProfileHeatmapFromSession(t, session) + + assert.False(t, visible, "user should have no visible heatmap") +} + +func TestPrivateActivityYesHeatmapInvsisibleForAdmin(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + testPrivateActivityHelperEnablePrivateActivity(t) + + session := loginUser(t, privateActivityTestAdmin) + visible := testPrivateActivityHelperHasVisibleProfileHeatmapFromSession(t, session) + + assert.False(t, visible, "user should have no visible heatmap") +} + +// check heatmap api provides content if the visibility is enabled + +func TestPrivateActivityNoHeatmapHasContentForPublic(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + + hasContent := testPrivateActivityHelperHasHeatmapContentFromPublic(t) + + assert.True(t, hasContent, "user should have heatmap content") +} + +func TestPrivateActivityNoHeatmapHasContentForUserItself(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + + session := loginUser(t, privateActivityTestUser) + hasContent := testPrivateActivityHelperHasHeatmapContentFromSession(t, session) + + assert.True(t, hasContent, "user should have heatmap content") +} + +func TestPrivateActivityNoHeatmapHasContentForOtherUser(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + + session := loginUser(t, privateActivityTestOtherUser) + hasContent := testPrivateActivityHelperHasHeatmapContentFromSession(t, session) + + assert.True(t, hasContent, "user should have heatmap content") +} + +func TestPrivateActivityNoHeatmapHasContentForAdmin(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + + session := loginUser(t, privateActivityTestAdmin) + hasContent := testPrivateActivityHelperHasHeatmapContentFromSession(t, session) + + assert.True(t, hasContent, "user should have heatmap content") +} + +// check heatmap api provides no content if the visibility is disabled +// this should be equal to the hidden heatmap at the UI + +func TestPrivateActivityYesHeatmapHasNoContentForPublic(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + testPrivateActivityHelperEnablePrivateActivity(t) + + hasContent := testPrivateActivityHelperHasHeatmapContentFromPublic(t) + + assert.False(t, hasContent, "user should have no heatmap content") +} + +func TestPrivateActivityYesHeatmapHasNoContentForUserItself(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + testPrivateActivityHelperEnablePrivateActivity(t) + + session := loginUser(t, privateActivityTestUser) + hasContent := testPrivateActivityHelperHasHeatmapContentFromSession(t, session) + + assert.False(t, hasContent, "user should have no heatmap content") +} + +func TestPrivateActivityYesHeatmapHasNoContentForOtherUser(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + testPrivateActivityHelperEnablePrivateActivity(t) + + session := loginUser(t, privateActivityTestOtherUser) + hasContent := testPrivateActivityHelperHasHeatmapContentFromSession(t, session) + + assert.False(t, hasContent, "user should have no heatmap content") +} + +func TestPrivateActivityYesHeatmapHasNoContentForAdmin(t *testing.T) { + defer prepareTestEnv(t)() + testPrivateActivityDoSomethingForActionEntries(t) + testPrivateActivityHelperEnablePrivateActivity(t) + + session := loginUser(t, privateActivityTestAdmin) + hasContent := testPrivateActivityHelperHasHeatmapContentFromSession(t, session) + + assert.False(t, hasContent, "user should have no heatmap content") +} From e2a1d9d8171712213cc7a9fda687f76279506a0c Mon Sep 17 00:00:00 2001 From: Jonas Lochmann Date: Mon, 11 May 2020 02:00:00 +0200 Subject: [PATCH 05/10] Remove info that admins can view the activity --- options/locale/locale_en-US.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 9b9285aa5cef5..6c3c23796b61f 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -381,7 +381,7 @@ follow = Follow unfollow = Unfollow heatmap.loading = Loading Heatmap… user_bio = Biography -disabled_public_activity = This user has disabled the public visibility of the activity. Only the user itself and admins can see it. +disabled_public_activity = This user has disabled the public visibility of the activity. form.name_reserved = The username '%s' is reserved. form.name_pattern_not_allowed = The pattern '%s' is not allowed in a username. From 61a8b2fd602a4aa89ed36d8c0c3ec895ffa6e493 Mon Sep 17 00:00:00 2001 From: Jonas Lochmann Date: Mon, 11 May 2020 02:00:00 +0200 Subject: [PATCH 06/10] Adjust new tests for linter --- integrations/privateactivity_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/integrations/privateactivity_test.go b/integrations/privateactivity_test.go index c88d9ad9ebd56..e9beb7c116a55 100644 --- a/integrations/privateactivity_test.go +++ b/integrations/privateactivity_test.go @@ -51,7 +51,7 @@ func testPrivateActivityHelperEnablePrivateActivity(t *testing.T) { session.MakeRequest(t, req, http.StatusFound) } -func testPrivateActivityHelperHasVisibleActivitiesInHtmlDoc(htmlDoc *HTMLDoc) bool { +func testPrivateActivityHelperHasVisibleActivitiesInHTMLDoc(htmlDoc *HTMLDoc) bool { return htmlDoc.doc.Find(".feeds").Find(".news").Length() > 0 } @@ -61,7 +61,7 @@ func testPrivateActivityHelperHasVisibleActivitiesFromSession(t *testing.T, sess htmlDoc := NewHTMLParser(t, resp.Body) - return testPrivateActivityHelperHasVisibleActivitiesInHtmlDoc(htmlDoc) + return testPrivateActivityHelperHasVisibleActivitiesInHTMLDoc(htmlDoc) } func testPrivateActivityHelperHasVisibleActivitiesFromPublic(t *testing.T) bool { @@ -70,12 +70,12 @@ func testPrivateActivityHelperHasVisibleActivitiesFromPublic(t *testing.T) bool htmlDoc := NewHTMLParser(t, resp.Body) - return testPrivateActivityHelperHasVisibleActivitiesInHtmlDoc(htmlDoc) + return testPrivateActivityHelperHasVisibleActivitiesInHTMLDoc(htmlDoc) } // heatmap UI helpers -func testPrivateActivityHelperHasVisibleHeatmapInHtmlDoc(htmlDoc *HTMLDoc) bool { +func testPrivateActivityHelperHasVisibleHeatmapInHTMLDoc(htmlDoc *HTMLDoc) bool { return htmlDoc.doc.Find("#user-heatmap").Length() > 0 } @@ -85,7 +85,7 @@ func testPrivateActivityHelperHasVisibleProfileHeatmapFromSession(t *testing.T, htmlDoc := NewHTMLParser(t, resp.Body) - return testPrivateActivityHelperHasVisibleHeatmapInHtmlDoc(htmlDoc) + return testPrivateActivityHelperHasVisibleHeatmapInHTMLDoc(htmlDoc) } func testPrivateActivityHelperHasVisibleDashboardHeatmapFromSession(t *testing.T, session *TestSession) bool { @@ -94,7 +94,7 @@ func testPrivateActivityHelperHasVisibleDashboardHeatmapFromSession(t *testing.T htmlDoc := NewHTMLParser(t, resp.Body) - return testPrivateActivityHelperHasVisibleHeatmapInHtmlDoc(htmlDoc) + return testPrivateActivityHelperHasVisibleHeatmapInHTMLDoc(htmlDoc) } func testPrivateActivityHelperHasVisibleHeatmapFromPublic(t *testing.T) bool { @@ -103,7 +103,7 @@ func testPrivateActivityHelperHasVisibleHeatmapFromPublic(t *testing.T) bool { htmlDoc := NewHTMLParser(t, resp.Body) - return testPrivateActivityHelperHasVisibleHeatmapInHtmlDoc(htmlDoc) + return testPrivateActivityHelperHasVisibleHeatmapInHTMLDoc(htmlDoc) } // heatmap API helpers From d94fa3fec9bdf39f44c33143d17f59bba2e3dbc5 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Fri, 5 Jun 2020 14:47:14 -0400 Subject: [PATCH 07/10] Rename v139.go to v140.go --- models/migrations/{v139.go => v140.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename models/migrations/{v139.go => v140.go} (100%) diff --git a/models/migrations/v139.go b/models/migrations/v140.go similarity index 100% rename from models/migrations/v139.go rename to models/migrations/v140.go From a54cce189a2db21449fe9d066473feb321a0c13b Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Fri, 5 Jun 2020 14:47:46 -0400 Subject: [PATCH 08/10] Rename v140.go to v141.go --- models/migrations/{v140.go => v141.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename models/migrations/{v140.go => v141.go} (100%) diff --git a/models/migrations/v140.go b/models/migrations/v141.go similarity index 100% rename from models/migrations/v140.go rename to models/migrations/v141.go From 535b4e58ea218bcdb17704077e89954f3c27c1a4 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Fri, 5 Jun 2020 14:51:42 -0400 Subject: [PATCH 09/10] properly indent --- templates/user/profile.tmpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl index cd5da455c4fe3..563bc78307c95 100644 --- a/templates/user/profile.tmpl +++ b/templates/user/profile.tmpl @@ -110,9 +110,9 @@ {{end}} {{if .EnableHeatmap}} - {{template "user/dashboard/heatmap" .}} -
- {{end}} + {{template "user/dashboard/heatmap" .}} +
+ {{end}}
{{template "user/dashboard/feeds" .}}
From fbf21e80109f128392a481694f2dcebf3c1fb4d7 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Fri, 5 Jun 2020 14:56:17 -0400 Subject: [PATCH 10/10] gofmt --- models/migrations/migrations.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 894da9dd6d2aa..432bcffb1bf59 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -214,7 +214,7 @@ var migrations = []Migration{ NewMigration("prepend refs/heads/ to issue refs", prependRefsHeadsToIssueRefs), // v140 -> v141 NewMigration("Save detected language file size to database instead of percent", fixLanguageStatsToSaveSize), - // v141 -> 142 + // v141 -> 142 NewMigration("Add KeepActivityPrivate to User table", addKeepActivityPrivateUserColumn), }