@@ -23,6 +23,7 @@ import ( | |||
"code.gitea.io/gitea/modules/base" | |||
"code.gitea.io/gitea/modules/git" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/optional" | |||
"code.gitea.io/gitea/modules/setting" | |||
"code.gitea.io/gitea/modules/structs" | |||
"code.gitea.io/gitea/modules/timeutil" | |||
@@ -139,21 +140,22 @@ func (at ActionType) InActions(actions ...string) bool { | |||
// repository. It implemented interface base.Actioner so that can be | |||
// used in template render. | |||
type Action struct { | |||
ID int64 `xorm:"pk autoincr"` | |||
UserID int64 `xorm:"INDEX"` // Receiver user id. | |||
OpType ActionType | |||
ActUserID int64 // Action user id. | |||
ActUser *user_model.User `xorm:"-"` | |||
RepoID int64 | |||
Repo *repo_model.Repository `xorm:"-"` | |||
CommentID int64 `xorm:"INDEX"` | |||
Comment *issues_model.Comment `xorm:"-"` | |||
Issue *issues_model.Issue `xorm:"-"` // get the issue id from content | |||
IsDeleted bool `xorm:"NOT NULL DEFAULT false"` | |||
RefName string | |||
IsPrivate bool `xorm:"NOT NULL DEFAULT false"` | |||
Content string `xorm:"TEXT"` | |||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||
ID int64 `xorm:"pk autoincr"` | |||
UserID int64 `xorm:"INDEX"` // Receiver user id. | |||
OpType ActionType | |||
ActUserID int64 // Action user id. | |||
ActUser *user_model.User `xorm:"-"` | |||
RepoID int64 | |||
Repo *repo_model.Repository `xorm:"-"` | |||
CommentID int64 `xorm:"INDEX"` | |||
Comment *issues_model.Comment `xorm:"-"` | |||
Issue *issues_model.Issue `xorm:"-"` // get the issue id from content | |||
IsDeleted bool `xorm:"NOT NULL DEFAULT false"` | |||
RefName string | |||
IsPrivate bool `xorm:"NOT NULL DEFAULT false"` | |||
IsPrivateView bool `xorm:"-"` | |||
Content string `xorm:"TEXT"` | |||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||
} | |||
func init() { | |||
@@ -457,23 +459,57 @@ func GetFeeds(ctx context.Context, opts GetFeedsOptions) (ActionList, int64, err | |||
opts.SetDefaultValues() | |||
sess = db.SetSessionPagination(sess, &opts) | |||
actions := make([]*Action, 0, opts.PageSize) | |||
actions := make(ActionList, 0, opts.PageSize) | |||
count, err := sess.Desc("`action`.created_unix").FindAndCount(&actions) | |||
if err != nil { | |||
return nil, 0, fmt.Errorf("FindAndCount: %w", err) | |||
} | |||
if err := ActionList(actions).LoadAttributes(ctx); err != nil { | |||
if err := actions.LoadAttributes(ctx); err != nil { | |||
return nil, 0, fmt.Errorf("LoadAttributes: %w", err) | |||
} | |||
if opts.Actor != nil && opts.RequestedUser != nil { | |||
isPrivateForActor := !opts.Actor.IsAdmin && opts.Actor.ID != opts.RequestedUser.ID | |||
// cache user repo read permissions | |||
canReadRepo := make(map[int64]optional.Option[bool], 0) | |||
for _, action := range actions { | |||
action.IsPrivateView = isPrivateForActor && action.IsPrivate | |||
if action.IsPrivateView && action.Repo.Owner.IsOrganization() { | |||
if !canReadRepo[action.Repo.ID].Has() { | |||
perm, err := access_model.GetUserRepoPermission(ctx, action.Repo, opts.Actor) | |||
if err != nil { | |||
return nil, 0, fmt.Errorf("GetUserRepoPermission: %w", err) | |||
} | |||
canRead := perm.CanRead(unit.TypeCode) | |||
action.IsPrivateView = !canRead | |||
canReadRepo[action.Repo.ID] = optional.Option[bool]{canRead} | |||
} | |||
action.IsPrivateView = !canReadRepo[action.Repo.ID].Value() | |||
} | |||
} | |||
} else { | |||
for _, action := range actions { | |||
action.IsPrivateView = action.IsPrivate | |||
} | |||
} | |||
return actions, count, nil | |||
} | |||
// ActivityReadable return whether doer can read activities of user | |||
func ActivityReadable(user, doer *user_model.User) bool { | |||
return !user.KeepActivityPrivate || | |||
doer != nil && (doer.IsAdmin || user.ID == doer.ID) | |||
if doer != nil && (doer.IsAdmin || user.ID == doer.ID) { | |||
return true | |||
} | |||
if user.ActivityVisibility.ShowNone() { | |||
return false | |||
} | |||
return true | |||
} | |||
func activityQueryCondition(ctx context.Context, opts GetFeedsOptions) (builder.Cond, error) { | |||
@@ -491,14 +527,17 @@ func activityQueryCondition(ctx context.Context, opts GetFeedsOptions) (builder. | |||
if opts.Actor == nil { | |||
cond = cond.And(builder.In("act_user_id", | |||
builder.Select("`user`.id").Where( | |||
builder.Eq{"keep_activity_private": false, "visibility": structs.VisibleTypePublic}, | |||
builder.Eq{"visibility": structs.VisibleTypePublic}, | |||
).Where( | |||
builder.Neq{"activity_visibility": structs.ActivityVisibilityNone}, | |||
).From("`user`"), | |||
)) | |||
} else if !opts.Actor.IsAdmin { | |||
uidCond := builder.Select("`user`.id").From("`user`").Where( | |||
builder.Eq{"keep_activity_private": false}. | |||
And(builder.In("visibility", structs.VisibleTypePublic, structs.VisibleTypeLimited))). | |||
Or(builder.Eq{"id": opts.Actor.ID}) | |||
builder.Neq{"activity_visibility": structs.ActivityVisibilityNone}, | |||
).Where( | |||
builder.In("visibility", structs.VisibleTypePublic, structs.VisibleTypeLimited), | |||
).Or(builder.Eq{"id": opts.Actor.ID}) | |||
if opts.RequestedUser != nil { | |||
if opts.RequestedUser.IsOrganization() { | |||
@@ -518,8 +557,9 @@ func activityQueryCondition(ctx context.Context, opts GetFeedsOptions) (builder. | |||
cond = cond.And(builder.In("act_user_id", uidCond)) | |||
} | |||
includePrivateRepos := opts.RequestedUser != nil && opts.RequestedUser.ActivityVisibility.ShowAll() | |||
// check readable repositories by doer/actor | |||
if opts.Actor == nil || !opts.Actor.IsAdmin { | |||
if !includePrivateRepos && (opts.Actor == nil || !opts.Actor.IsAdmin) { | |||
cond = cond.And(builder.In("repo_id", repo_model.AccessibleRepoIDsQuery(opts.Actor))) | |||
} | |||
@@ -15,6 +15,7 @@ import ( | |||
"code.gitea.io/gitea/models/unittest" | |||
user_model "code.gitea.io/gitea/models/user" | |||
"code.gitea.io/gitea/modules/setting" | |||
"code.gitea.io/gitea/modules/structs" | |||
"github.com/stretchr/testify/assert" | |||
) | |||
@@ -165,21 +166,21 @@ func TestActivityReadable(t *testing.T) { | |||
result: true, | |||
}, { | |||
desc: "anon should NOT see activity", | |||
user: &user_model.User{ID: 1, KeepActivityPrivate: true}, | |||
user: &user_model.User{ID: 1, ActivityVisibility: structs.ActivityVisibilityNone}, | |||
result: false, | |||
}, { | |||
desc: "user should see own activity if private too", | |||
user: &user_model.User{ID: 1, KeepActivityPrivate: true}, | |||
user: &user_model.User{ID: 1, ActivityVisibility: structs.ActivityVisibilityNone}, | |||
doer: &user_model.User{ID: 1}, | |||
result: true, | |||
}, { | |||
desc: "other user should NOT see activity", | |||
user: &user_model.User{ID: 1, KeepActivityPrivate: true}, | |||
user: &user_model.User{ID: 1, ActivityVisibility: structs.ActivityVisibilityNone}, | |||
doer: &user_model.User{ID: 2}, | |||
result: false, | |||
}, { | |||
desc: "admin should see activity", | |||
user: &user_model.User{ID: 1, KeepActivityPrivate: true}, | |||
user: &user_model.User{ID: 1, ActivityVisibility: structs.ActivityVisibilityNone}, | |||
doer: &user_model.User{ID: 2, IsAdmin: true}, | |||
result: true, | |||
}} |
@@ -35,7 +35,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 2 | |||
@@ -72,7 +72,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 3 | |||
@@ -109,7 +109,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 4 | |||
@@ -146,7 +146,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 5 | |||
@@ -183,7 +183,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 6 | |||
@@ -220,7 +220,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 7 | |||
@@ -257,7 +257,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 8 | |||
@@ -294,7 +294,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 9 | |||
@@ -331,7 +331,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 10 | |||
@@ -368,7 +368,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 11 | |||
@@ -405,7 +405,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 12 | |||
@@ -442,7 +442,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 13 | |||
@@ -479,7 +479,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 14 | |||
@@ -516,7 +516,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 15 | |||
@@ -553,7 +553,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 16 | |||
@@ -590,7 +590,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 17 | |||
@@ -627,7 +627,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 18 | |||
@@ -664,7 +664,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 19 | |||
@@ -701,7 +701,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 20 | |||
@@ -738,7 +738,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 21 | |||
@@ -775,7 +775,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 22 | |||
@@ -812,7 +812,7 @@ | |||
visibility: 1 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 23 | |||
@@ -849,7 +849,7 @@ | |||
visibility: 2 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 24 | |||
@@ -886,7 +886,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 25 | |||
@@ -923,7 +923,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 26 | |||
@@ -960,7 +960,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: true | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 27 | |||
@@ -997,7 +997,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 28 | |||
@@ -1034,7 +1034,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 29 | |||
@@ -1071,7 +1071,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 30 | |||
@@ -1108,7 +1108,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 31 | |||
@@ -1145,7 +1145,7 @@ | |||
visibility: 2 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 32 | |||
@@ -1182,7 +1182,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 33 | |||
@@ -1219,7 +1219,7 @@ | |||
visibility: 1 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 34 | |||
@@ -1257,7 +1257,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 35 | |||
@@ -1294,7 +1294,7 @@ | |||
visibility: 2 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 36 | |||
@@ -1331,7 +1331,7 @@ | |||
visibility: 1 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 37 | |||
@@ -1368,7 +1368,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 38 | |||
@@ -1405,7 +1405,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 39 | |||
@@ -1442,7 +1442,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 40 | |||
@@ -1479,7 +1479,7 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 | |||
- | |||
id: 41 | |||
@@ -1516,4 +1516,4 @@ | |||
visibility: 0 | |||
repo_admin_change_team_access: false | |||
theme: "" | |||
keep_activity_private: false | |||
activity_visibility: 0 |
@@ -143,9 +143,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 ''"` | |||
ActivityVisibility structs.ActivityVisibility `xorm:"NOT NULL DEFAULT 0"` | |||
} | |||
func init() { |
@@ -0,0 +1,50 @@ | |||
// Copyright 2024 The Gitea Authors. All rights reserved. | |||
// SPDX-License-Identifier: MIT | |||
package structs | |||
// ActivityVisibility defines the activities shown | |||
type ActivityVisibility int | |||
const ( | |||
// ActivityVisibilityPublic show public activities | |||
ActivityVisibilityPublic ActivityVisibility = iota | |||
// ActivityVisibilityAll shows all activities | |||
ActivityVisibilityAll | |||
// ActivityVisibilityNone show no activities | |||
ActivityVisibilityNone | |||
) | |||
// ActivityVisibilities is a map of ActivityVisibility types | |||
var ActivityVisibilities = map[string]ActivityVisibility{ | |||
"public": ActivityVisibilityPublic, | |||
"all": ActivityVisibilityAll, | |||
"none": ActivityVisibilityNone, | |||
} | |||
// ShowPublic returns true if ActivityVisibility is public | |||
func (vt ActivityVisibility) ShowPublic() bool { | |||
return vt == ActivityVisibilityPublic | |||
} | |||
// ShowAll returns true if ActivityVisibility is all | |||
func (vt ActivityVisibility) ShowAll() bool { | |||
return vt == ActivityVisibilityAll | |||
} | |||
// ShowNone returns true if ActivityVisibility is none | |||
func (vt ActivityVisibility) ShowNone() bool { | |||
return vt == ActivityVisibilityNone | |||
} | |||
// String provides the mode string of the visibility type (public, all, none) | |||
func (vt ActivityVisibility) String() string { | |||
for k, v := range ActivityVisibilities { | |||
if vt == v { | |||
return k | |||
} | |||
} | |||
return "" | |||
} |
@@ -78,8 +78,8 @@ type UserSettings struct { | |||
Theme string `json:"theme"` | |||
DiffViewStyle string `json:"diff_view_style"` | |||
// Privacy | |||
HideEmail bool `json:"hide_email"` | |||
HideActivity bool `json:"hide_activity"` | |||
HideEmail bool `json:"hide_email"` | |||
ActivityVisibility ActivityVisibility `json:"activity_visibility"` | |||
} | |||
// UserSettingsOptions represents options to change user settings | |||
@@ -93,8 +93,8 @@ type UserSettingsOptions struct { | |||
Theme *string `json:"theme"` | |||
DiffViewStyle *string `json:"diff_view_style"` | |||
// Privacy | |||
HideEmail *bool `json:"hide_email"` | |||
HideActivity *bool `json:"hide_activity"` | |||
HideEmail *bool `json:"hide_email"` | |||
ActivityVisibility *ActivityVisibility `json:"activity_visibility"` | |||
} | |||
// RenameUserOption options when renaming a user |
@@ -70,6 +70,8 @@ your_starred = Starred | |||
your_settings = Settings | |||
all = All | |||
none = None | |||
public = Public | |||
sources = Sources | |||
mirrors = Mirrors | |||
collaborative = Collaborative | |||
@@ -736,8 +738,11 @@ comment_type_group_project = Project | |||
comment_type_group_issue_ref = Issue reference | |||
saved_successfully = Your settings were saved successfully. | |||
privacy = Privacy | |||
keep_activity_private = Hide Activity from profile page | |||
keep_activity_private_popup = Makes the activity visible only for you and the admins | |||
activity_visibility_popup = Specify which activities are visible | |||
activity_visibility = Visible activities | |||
activity_visibility.public_popup = Only activies from repositories which can be accessed by the viewer are visible | |||
activity_visibility.all_popup = All activities are visibile, but activities from repositories which can't be accessed by the viewer are obfuscated and only shows how many activities were performed. | |||
activity_visibility.none_popup = Don't show activities (expect to admins) | |||
lookup_avatar_by_mail = Look Up Avatar by Email Address | |||
federated_avatar_lookup = Federated Avatar Lookup | |||
@@ -3353,6 +3358,8 @@ review_dismissed_reason = Reason: | |||
create_branch = created branch <a href="%[2]s">%[3]s</a> in <a href="%[1]s">%[4]s</a> | |||
starred_repo = starred <a href="%[1]s">%[2]s</a> | |||
watched_repo = started watching <a href="%[1]s">%[2]s</a> | |||
performed_1 = performed %d private action | |||
performed_n = performed %d private actions | |||
[tool] | |||
now = now |
@@ -46,15 +46,15 @@ func UpdateUserSettings(ctx *context.APIContext) { | |||
form := web.GetForm(ctx).(*api.UserSettingsOptions) | |||
opts := &user_service.UpdateOptions{ | |||
FullName: optional.FromPtr(form.FullName), | |||
Description: optional.FromPtr(form.Description), | |||
Website: optional.FromPtr(form.Website), | |||
Location: optional.FromPtr(form.Location), | |||
Language: optional.FromPtr(form.Language), | |||
Theme: optional.FromPtr(form.Theme), | |||
DiffViewStyle: optional.FromPtr(form.DiffViewStyle), | |||
KeepEmailPrivate: optional.FromPtr(form.HideEmail), | |||
KeepActivityPrivate: optional.FromPtr(form.HideActivity), | |||
FullName: optional.FromPtr(form.FullName), | |||
Description: optional.FromPtr(form.Description), | |||
Website: optional.FromPtr(form.Website), | |||
Location: optional.FromPtr(form.Location), | |||
Language: optional.FromPtr(form.Language), | |||
Theme: optional.FromPtr(form.Theme), | |||
DiffViewStyle: optional.FromPtr(form.DiffViewStyle), | |||
KeepEmailPrivate: optional.FromPtr(form.HideEmail), | |||
ActivityVisibility: optional.FromPtr(form.ActivityVisibility), | |||
} | |||
if err := user_service.UpdateUser(ctx, ctx.Doer, opts); err != nil { | |||
ctx.InternalServerError(err) |
@@ -75,14 +75,13 @@ func userProfile(ctx *context.Context) { | |||
profileDbRepo, profileGitRepo, profileReadmeBlob, profileClose := shared_user.FindUserProfileReadme(ctx, ctx.Doer) | |||
defer profileClose() | |||
showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID) | |||
prepareUserProfileTabData(ctx, showPrivate, profileDbRepo, profileGitRepo, profileReadmeBlob) | |||
prepareUserProfileTabData(ctx, profileDbRepo, profileGitRepo, profileReadmeBlob) | |||
// call PrepareContextForProfileBigAvatar later to avoid re-querying the NumFollowers & NumFollowing | |||
shared_user.PrepareContextForProfileBigAvatar(ctx) | |||
ctx.HTML(http.StatusOK, tplProfile) | |||
} | |||
func prepareUserProfileTabData(ctx *context.Context, showPrivate bool, profileDbRepo *repo_model.Repository, profileGitRepo *git.Repository, profileReadme *git.Blob) { | |||
func prepareUserProfileTabData(ctx *context.Context, profileDbRepo *repo_model.Repository, profileGitRepo *git.Repository, profileReadme *git.Blob) { | |||
// if there is a profile readme, default to "overview" page, otherwise, default to "repositories" page | |||
// if there is not a profile readme, the overview tab should be treated as the repositories tab | |||
tab := ctx.FormString("tab") | |||
@@ -190,7 +189,7 @@ func prepareUserProfileTabData(ctx *context.Context, showPrivate bool, profileDb | |||
items, count, err := activities_model.GetFeeds(ctx, activities_model.GetFeedsOptions{ | |||
RequestedUser: ctx.ContextUser, | |||
Actor: ctx.Doer, | |||
IncludePrivate: showPrivate, | |||
IncludePrivate: true, | |||
OnlyPerformedBy: true, | |||
IncludeDeleted: false, | |||
Date: date, |
@@ -88,13 +88,13 @@ func ProfilePost(ctx *context.Context) { | |||
} | |||
opts := &user_service.UpdateOptions{ | |||
FullName: optional.Some(form.FullName), | |||
KeepEmailPrivate: optional.Some(form.KeepEmailPrivate), | |||
Description: optional.Some(form.Description), | |||
Website: optional.Some(form.Website), | |||
Location: optional.Some(form.Location), | |||
Visibility: optional.Some(form.Visibility), | |||
KeepActivityPrivate: optional.Some(form.KeepActivityPrivate), | |||
FullName: optional.Some(form.FullName), | |||
KeepEmailPrivate: optional.Some(form.KeepEmailPrivate), | |||
Description: optional.Some(form.Description), | |||
Website: optional.Some(form.Website), | |||
Location: optional.Some(form.Location), | |||
Visibility: optional.Some(form.Visibility), | |||
ActivityVisibility: optional.Some(form.ActivityVisibility), | |||
} | |||
if err := user_service.UpdateUser(ctx, ctx.Doer, opts); err != nil { | |||
ctx.ServerError("UpdateUser", err) |
@@ -87,15 +87,15 @@ func toUser(ctx context.Context, user *user_model.User, signed, authed bool) *ap | |||
// User2UserSettings return UserSettings based on a user | |||
func User2UserSettings(user *user_model.User) api.UserSettings { | |||
return api.UserSettings{ | |||
FullName: user.FullName, | |||
Website: user.Website, | |||
Location: user.Location, | |||
Language: user.Language, | |||
Description: user.Description, | |||
Theme: user.Theme, | |||
HideEmail: user.KeepEmailPrivate, | |||
HideActivity: user.KeepActivityPrivate, | |||
DiffViewStyle: user.DiffViewStyle, | |||
FullName: user.FullName, | |||
Website: user.Website, | |||
Location: user.Location, | |||
Language: user.Language, | |||
Description: user.Description, | |||
Theme: user.Theme, | |||
HideEmail: user.KeepEmailPrivate, | |||
ActivityVisibility: user.ActivityVisibility, | |||
DiffViewStyle: user.DiffViewStyle, | |||
} | |||
} | |||
@@ -212,14 +212,14 @@ func (f *IntrospectTokenForm) Validate(req *http.Request, errs binding.Errors) b | |||
// UpdateProfileForm form for updating profile | |||
type UpdateProfileForm struct { | |||
Name string `binding:"Username;MaxSize(40)"` | |||
FullName string `binding:"MaxSize(100)"` | |||
KeepEmailPrivate bool | |||
Website string `binding:"ValidSiteUrl;MaxSize(255)"` | |||
Location string `binding:"MaxSize(50)"` | |||
Description string `binding:"MaxSize(255)"` | |||
Visibility structs.VisibleType | |||
KeepActivityPrivate bool | |||
Name string `binding:"Username;MaxSize(40)"` | |||
FullName string `binding:"MaxSize(100)"` | |||
KeepEmailPrivate bool | |||
Website string `binding:"ValidSiteUrl;MaxSize(255)"` | |||
Location string `binding:"MaxSize(50)"` | |||
Description string `binding:"MaxSize(255)"` | |||
Visibility structs.VisibleType | |||
ActivityVisibility structs.ActivityVisibility | |||
} | |||
// Validate validates the fields |
@@ -27,7 +27,7 @@ type UpdateOptions struct { | |||
MaxRepoCreation optional.Option[int] | |||
IsRestricted optional.Option[bool] | |||
Visibility optional.Option[structs.VisibleType] | |||
KeepActivityPrivate optional.Option[bool] | |||
ActivityVisibility optional.Option[structs.ActivityVisibility] | |||
Language optional.Option[string] | |||
Theme optional.Option[string] | |||
DiffViewStyle optional.Option[string] | |||
@@ -129,10 +129,10 @@ func UpdateUser(ctx context.Context, u *user_model.User, opts *UpdateOptions) er | |||
cols = append(cols, "visibility") | |||
} | |||
if opts.KeepActivityPrivate.Has() { | |||
u.KeepActivityPrivate = opts.KeepActivityPrivate.Value() | |||
if opts.ActivityVisibility.Has() { | |||
u.ActivityVisibility = opts.ActivityVisibility.Value() | |||
cols = append(cols, "keep_activity_private") | |||
cols = append(cols, "activity_visibility") | |||
} | |||
if opts.AllowCreateOrganization.Has() { |
@@ -40,7 +40,7 @@ func TestUpdateUser(t *testing.T) { | |||
IsActive: optional.Some(false), | |||
IsAdmin: optional.Some(true), | |||
Visibility: optional.Some(structs.VisibleTypePrivate), | |||
KeepActivityPrivate: optional.Some(true), | |||
ActivityVisibility: optional.Some(structs.ActivityVisibilityNone), | |||
Language: optional.Some("lang"), | |||
Theme: optional.Some("theme"), | |||
DiffViewStyle: optional.Some("split"), | |||
@@ -62,7 +62,7 @@ func TestUpdateUser(t *testing.T) { | |||
assert.Equal(t, opts.IsActive.Value(), user.IsActive) | |||
assert.Equal(t, opts.IsAdmin.Value(), user.IsAdmin) | |||
assert.Equal(t, opts.Visibility.Value(), user.Visibility) | |||
assert.Equal(t, opts.KeepActivityPrivate.Value(), user.KeepActivityPrivate) | |||
assert.Equal(t, opts.ActivityVisibility.Value(), user.ActivityVisibility) | |||
assert.Equal(t, opts.Language.Value(), user.Language) | |||
assert.Equal(t, opts.Theme.Value(), user.Theme) | |||
assert.Equal(t, opts.DiffViewStyle.Value(), user.DiffViewStyle) | |||
@@ -82,7 +82,7 @@ func TestUpdateUser(t *testing.T) { | |||
assert.Equal(t, opts.IsActive.Value(), user.IsActive) | |||
assert.Equal(t, opts.IsAdmin.Value(), user.IsAdmin) | |||
assert.Equal(t, opts.Visibility.Value(), user.Visibility) | |||
assert.Equal(t, opts.KeepActivityPrivate.Value(), user.KeepActivityPrivate) | |||
assert.Equal(t, opts.ActivityVisibility.Value(), user.ActivityVisibility) | |||
assert.Equal(t, opts.Language.Value(), user.Language) | |||
assert.Equal(t, opts.Theme.Value(), user.Theme) | |||
assert.Equal(t, opts.DiffViewStyle.Value(), user.DiffViewStyle) |
@@ -18006,6 +18006,12 @@ | |||
}, | |||
"x-go-package": "code.gitea.io/gitea/modules/structs" | |||
}, | |||
"ActivityVisibility": { | |||
"description": "ActivityVisibility defines the activities shown", | |||
"type": "integer", | |||
"format": "int64", | |||
"x-go-package": "code.gitea.io/gitea/modules/structs" | |||
}, | |||
"AddCollaboratorOption": { | |||
"description": "AddCollaboratorOption options when adding a user as a collaborator of a repository", | |||
"type": "object", | |||
@@ -24319,6 +24325,9 @@ | |||
"description": "UserSettings represents user settings", | |||
"type": "object", | |||
"properties": { | |||
"activity_visibility": { | |||
"$ref": "#/definitions/ActivityVisibility" | |||
}, | |||
"description": { | |||
"type": "string", | |||
"x-go-name": "Description" | |||
@@ -24331,10 +24340,6 @@ | |||
"type": "string", | |||
"x-go-name": "FullName" | |||
}, | |||
"hide_activity": { | |||
"type": "boolean", | |||
"x-go-name": "HideActivity" | |||
}, | |||
"hide_email": { | |||
"description": "Privacy", | |||
"type": "boolean", | |||
@@ -24363,6 +24368,9 @@ | |||
"description": "UserSettingsOptions represents options to change user settings", | |||
"type": "object", | |||
"properties": { | |||
"activity_visibility": { | |||
"$ref": "#/definitions/ActivityVisibility" | |||
}, | |||
"description": { | |||
"type": "string", | |||
"x-go-name": "Description" | |||
@@ -24375,10 +24383,6 @@ | |||
"type": "string", | |||
"x-go-name": "FullName" | |||
}, | |||
"hide_activity": { | |||
"type": "boolean", | |||
"x-go-name": "HideActivity" | |||
}, | |||
"hide_email": { | |||
"description": "Privacy", | |||
"type": "boolean", |
@@ -5,121 +5,144 @@ | |||
{{ctx.AvatarUtils.AvatarByAction .}} | |||
</div> | |||
<div class="flex-item-main tw-gap-2"> | |||
<div> | |||
{{if gt .ActUser.ID 0}} | |||
<a href="{{AppSubUrl}}/{{(.GetActUserName ctx) | PathEscape}}" title="{{.GetActDisplayNameTitle ctx}}">{{.GetActDisplayName ctx}}</a> | |||
{{else}} | |||
{{.ShortActUserName ctx}} | |||
{{end}} | |||
{{if .GetOpType.InActions "create_repo"}} | |||
{{ctx.Locale.Tr "action.create_repo" (.GetRepoLink ctx) (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "rename_repo"}} | |||
{{ctx.Locale.Tr "action.rename_repo" .GetContent (.GetRepoLink ctx) (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "commit_repo"}} | |||
{{if .Content}} | |||
{{ctx.Locale.Tr "action.commit_repo" (.GetRepoLink ctx) (.GetRefLink ctx) .GetBranch (.ShortRepoPath ctx)}} | |||
{{if .IsPrivateView}} | |||
<div> | |||
{{if gt .ActUser.ID 0}} | |||
<a href="{{AppSubUrl}}/{{(.GetActUserName ctx) | PathEscape}}" title="{{.GetActDisplayNameTitle ctx}}">{{.GetActDisplayName ctx}}</a> | |||
{{else}} | |||
{{ctx.Locale.Tr "action.create_branch" (.GetRepoLink ctx) (.GetRefLink ctx) .GetBranch (.ShortRepoPath ctx)}} | |||
{{.ShortActUserName ctx}} | |||
{{end}} | |||
{{$pushLength := 1}} | |||
{{if .GetOpType.InActions "commit_repo" "mirror_sync_push"}} | |||
{{$commitLength := (ActionContent2Commits .).Len}} | |||
{{if gt $commitLength $pushLength}} | |||
{{$pushLength = $commitLength}} | |||
{{end}} | |||
{{end}} | |||
{{ctx.Locale.TrN $pushLength "action.performed_1" "action.performed_n" $pushLength}} | |||
{{TimeSince .GetCreate ctx.Locale}} | |||
</div> | |||
{{else}} | |||
<div> | |||
{{if gt .ActUser.ID 0}} | |||
<a href="{{AppSubUrl}}/{{(.GetActUserName ctx) | PathEscape}}" title="{{.GetActDisplayNameTitle ctx}}">{{.GetActDisplayName ctx}}</a> | |||
{{else}} | |||
{{.ShortActUserName ctx}} | |||
{{end}} | |||
{{if .GetOpType.InActions "create_repo"}} | |||
{{ctx.Locale.Tr "action.create_repo" (.GetRepoLink ctx) (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "rename_repo"}} | |||
{{ctx.Locale.Tr "action.rename_repo" .GetContent (.GetRepoLink ctx) (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "commit_repo"}} | |||
{{if .Content}} | |||
{{ctx.Locale.Tr "action.commit_repo" (.GetRepoLink ctx) (.GetRefLink ctx) .GetBranch (.ShortRepoPath ctx)}} | |||
{{else}} | |||
{{ctx.Locale.Tr "action.create_branch" (.GetRepoLink ctx) (.GetRefLink ctx) .GetBranch (.ShortRepoPath ctx)}} | |||
{{end}} | |||
{{else if .GetOpType.InActions "create_issue"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.create_issue" (printf "%s/issues/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "create_pull_request"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.create_pull_request" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "transfer_repo"}} | |||
{{ctx.Locale.Tr "action.transfer_repo" .GetContent (.GetRepoLink ctx) (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "push_tag"}} | |||
{{ctx.Locale.Tr "action.push_tag" (.GetRepoLink ctx) (.GetRefLink ctx) .GetTag (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "comment_issue"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.comment_issue" (printf "%s/issues/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "merge_pull_request"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.merge_pull_request" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "close_issue"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.close_issue" (printf "%s/issues/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "reopen_issue"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.reopen_issue" (printf "%s/issues/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "close_pull_request"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.close_pull_request" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "reopen_pull_request"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.reopen_pull_request" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "delete_tag"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.delete_tag" (.GetRepoLink ctx) .GetTag (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "delete_branch"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.delete_branch" (.GetRepoLink ctx) .GetBranch (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "mirror_sync_push"}} | |||
{{ctx.Locale.Tr "action.mirror_sync_push" (.GetRepoLink ctx) (.GetRefLink ctx) .GetBranch (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "mirror_sync_create"}} | |||
{{ctx.Locale.Tr "action.mirror_sync_create" (.GetRepoLink ctx) (.GetRefLink ctx) .GetBranch (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "mirror_sync_delete"}} | |||
{{ctx.Locale.Tr "action.mirror_sync_delete" (.GetRepoLink ctx) .GetBranch (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "approve_pull_request"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.approve_pull_request" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "reject_pull_request"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.reject_pull_request" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "comment_pull"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.comment_pull" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "publish_release"}} | |||
{{$linkText := .Content | RenderEmoji $.Context}} | |||
{{ctx.Locale.Tr "action.publish_release" (.GetRepoLink ctx) (printf "%s/releases/tag/%s" (.GetRepoLink ctx) .GetTag) (.ShortRepoPath ctx) $linkText}} | |||
{{else if .GetOpType.InActions "review_dismissed"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{$reviewer := index .GetIssueInfos 1}} | |||
{{ctx.Locale.Tr "action.review_dismissed" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx) $reviewer}} | |||
{{end}} | |||
{{TimeSince .GetCreate ctx.Locale}} | |||
</div> | |||
{{if .GetOpType.InActions "commit_repo" "mirror_sync_push"}} | |||
{{$push := ActionContent2Commits .}} | |||
{{$repoLink := (.GetRepoLink ctx)}} | |||
{{$repo := .Repo}} | |||
<div class="tw-flex tw-flex-col tw-gap-1"> | |||
{{range $push.Commits}} | |||
{{$commitLink := printf "%s/commit/%s" $repoLink .Sha1}} | |||
<div class="flex-text-block"> | |||
<img class="ui avatar" src="{{$push.AvatarLink $.Context .AuthorEmail}}" title="{{.AuthorName}}" width="16" height="16"> | |||
<a class="ui sha label" href="{{$commitLink}}">{{ShortSha .Sha1}}</a> | |||
<span class="text truncate"> | |||
{{RenderCommitMessage $.Context .Message ($repo.ComposeMetas ctx)}} | |||
</span> | |||
</div> | |||
{{end}} | |||
</div> | |||
{{if and (gt $push.Len 1) $push.CompareURL}} | |||
<a href="{{AppSubUrl}}/{{$push.CompareURL}}">{{ctx.Locale.Tr "action.compare_commits" $push.Len}} »</a> | |||
{{end}} | |||
{{else if .GetOpType.InActions "create_issue"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.create_issue" (printf "%s/issues/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
<span class="text truncate issue title">{{index .GetIssueInfos 1 | RenderEmoji $.Context | RenderCodeBlock}}</span> | |||
{{else if .GetOpType.InActions "create_pull_request"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.create_pull_request" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "transfer_repo"}} | |||
{{ctx.Locale.Tr "action.transfer_repo" .GetContent (.GetRepoLink ctx) (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "push_tag"}} | |||
{{ctx.Locale.Tr "action.push_tag" (.GetRepoLink ctx) (.GetRefLink ctx) .GetTag (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "comment_issue"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.comment_issue" (printf "%s/issues/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "merge_pull_request"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.merge_pull_request" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "close_issue"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.close_issue" (printf "%s/issues/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "reopen_issue"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.reopen_issue" (printf "%s/issues/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "close_pull_request"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.close_pull_request" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "reopen_pull_request"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.reopen_pull_request" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "delete_tag"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.delete_tag" (.GetRepoLink ctx) .GetTag (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "delete_branch"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.delete_branch" (.GetRepoLink ctx) .GetBranch (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "mirror_sync_push"}} | |||
{{ctx.Locale.Tr "action.mirror_sync_push" (.GetRepoLink ctx) (.GetRefLink ctx) .GetBranch (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "mirror_sync_create"}} | |||
{{ctx.Locale.Tr "action.mirror_sync_create" (.GetRepoLink ctx) (.GetRefLink ctx) .GetBranch (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "mirror_sync_delete"}} | |||
{{ctx.Locale.Tr "action.mirror_sync_delete" (.GetRepoLink ctx) .GetBranch (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "approve_pull_request"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.approve_pull_request" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "reject_pull_request"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.reject_pull_request" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "comment_pull"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{ctx.Locale.Tr "action.comment_pull" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx)}} | |||
{{else if .GetOpType.InActions "publish_release"}} | |||
{{$linkText := .Content | RenderEmoji $.Context}} | |||
{{ctx.Locale.Tr "action.publish_release" (.GetRepoLink ctx) (printf "%s/releases/tag/%s" (.GetRepoLink ctx) .GetTag) (.ShortRepoPath ctx) $linkText}} | |||
{{else if .GetOpType.InActions "review_dismissed"}} | |||
{{$index := index .GetIssueInfos 0}} | |||
{{$reviewer := index .GetIssueInfos 1}} | |||
{{ctx.Locale.Tr "action.review_dismissed" (printf "%s/pulls/%s" (.GetRepoLink ctx) $index) $index (.ShortRepoPath ctx) $reviewer}} | |||
{{end}} | |||
{{TimeSince .GetCreate ctx.Locale}} | |||
</div> | |||
{{if .GetOpType.InActions "commit_repo" "mirror_sync_push"}} | |||
{{$push := ActionContent2Commits .}} | |||
{{$repoLink := (.GetRepoLink ctx)}} | |||
{{$repo := .Repo}} | |||
<div class="tw-flex tw-flex-col tw-gap-1"> | |||
{{range $push.Commits}} | |||
{{$commitLink := printf "%s/commit/%s" $repoLink .Sha1}} | |||
<div class="flex-text-block"> | |||
<img class="ui avatar" src="{{$push.AvatarLink $.Context .AuthorEmail}}" title="{{.AuthorName}}" width="16" height="16"> | |||
<a class="ui sha label" href="{{$commitLink}}">{{ShortSha .Sha1}}</a> | |||
<span class="text truncate"> | |||
{{RenderCommitMessage $.Context .Message ($repo.ComposeMetas ctx)}} | |||
</span> | |||
</div> | |||
<span class="text truncate issue title">{{index .GetIssueInfos 1 | RenderEmoji $.Context | RenderCodeBlock}}</span> | |||
{{else if .GetOpType.InActions "comment_issue" "approve_pull_request" "reject_pull_request" "comment_pull"}} | |||
<a href="{{.GetCommentLink ctx}}" class="text truncate issue title">{{(.GetIssueTitle ctx) | RenderEmoji $.Context | RenderCodeBlock}}</a> | |||
{{$comment := index .GetIssueInfos 1}} | |||
{{if $comment}} | |||
<div class="markup tw-text-14">{{RenderMarkdownToHtml ctx $comment}}</div> | |||
{{end}} | |||
</div> | |||
{{if and (gt $push.Len 1) $push.CompareURL}} | |||
<a href="{{AppSubUrl}}/{{$push.CompareURL}}">{{ctx.Locale.Tr "action.compare_commits" $push.Len}} »</a> | |||
{{end}} | |||
{{else if .GetOpType.InActions "create_issue"}} | |||
<span class="text truncate issue title">{{index .GetIssueInfos 1 | RenderEmoji $.Context | RenderCodeBlock}}</span> | |||
{{else if .GetOpType.InActions "create_pull_request"}} | |||
<span class="text truncate issue title">{{index .GetIssueInfos 1 | RenderEmoji $.Context | RenderCodeBlock}}</span> | |||
{{else if .GetOpType.InActions "comment_issue" "approve_pull_request" "reject_pull_request" "comment_pull"}} | |||
<a href="{{.GetCommentLink ctx}}" class="text truncate issue title">{{(.GetIssueTitle ctx) | RenderEmoji $.Context | RenderCodeBlock}}</a> | |||
{{$comment := index .GetIssueInfos 1}} | |||
{{if $comment}} | |||
<div class="markup tw-text-14">{{RenderMarkdownToHtml ctx $comment}}</div> | |||
{{else if .GetOpType.InActions "merge_pull_request"}} | |||
<div class="flex-item-body text black">{{index .GetIssueInfos 1}}</div> | |||
{{else if .GetOpType.InActions "close_issue" "reopen_issue" "close_pull_request" "reopen_pull_request"}} | |||
<span class="text truncate issue title">{{(.GetIssueTitle ctx) | RenderEmoji $.Context | RenderCodeBlock}}</span> | |||
{{else if .GetOpType.InActions "pull_review_dismissed"}} | |||
<div class="flex-item-body text black">{{ctx.Locale.Tr "action.review_dismissed_reason"}}</div> | |||
<div class="flex-item-body text black">{{index .GetIssueInfos 2 | RenderEmoji $.Context}}</div> | |||
{{end}} | |||
{{else if .GetOpType.InActions "merge_pull_request"}} | |||
<div class="flex-item-body text black">{{index .GetIssueInfos 1}}</div> | |||
{{else if .GetOpType.InActions "close_issue" "reopen_issue" "close_pull_request" "reopen_pull_request"}} | |||
<span class="text truncate issue title">{{(.GetIssueTitle ctx) | RenderEmoji $.Context | RenderCodeBlock}}</span> | |||
{{else if .GetOpType.InActions "pull_review_dismissed"}} | |||
<div class="flex-item-body text black">{{ctx.Locale.Tr "action.review_dismissed_reason"}}</div> | |||
<div class="flex-item-body text black">{{index .GetIssueInfos 2 | RenderEmoji $.Context}}</div> | |||
{{end}} | |||
</div> | |||
<div class="flex-item-trailing"> | |||
{{svg (printf "octicon-%s" (ActionIcon .GetOpType)) 32 "text grey tw-mr-1"}} | |||
{{if .IsPrivateView}} | |||
{{svg "octicon-lock" 32 "text grey tw-mr-1"}} | |||
{{else}} | |||
{{svg (printf "octicon-%s" (ActionIcon .GetOpType)) 32 "text grey tw-mr-1"}} | |||
{{end}} | |||
</div> | |||
</div> | |||
{{end}} |
@@ -8,13 +8,14 @@ | |||
<div class="ui twelve wide column tw-mb-4"> | |||
{{template "user/overview/header" .}} | |||
{{if eq .TabName "activity"}} | |||
{{if .ContextUser.KeepActivityPrivate}} | |||
{{if and .ContextUser.ActivityVisibility.ShowNone (not .IsAdmin) (ne .ContextUser.ID .SignedUserID)}} | |||
<div class="ui info message"> | |||
<p>{{ctx.Locale.Tr "user.disabled_public_activity"}}</p> | |||
</div> | |||
{{else}} | |||
{{template "user/heatmap" .}} | |||
{{template "user/dashboard/feeds" .}} | |||
{{end}} | |||
{{template "user/heatmap" .}} | |||
{{template "user/dashboard/feeds" .}} | |||
{{else if eq .TabName "stars"}} | |||
<div class="stars"> | |||
{{template "shared/repo_search" .}} |
@@ -71,17 +71,28 @@ | |||
</div> | |||
</div> | |||
<div class="field"> | |||
<div class="ui checkbox"> | |||
<label data-tooltip-content="{{ctx.Locale.Tr "settings.keep_email_private_popup" .SignedUser.GetPlaceholderEmail}}"><strong>{{ctx.Locale.Tr "settings.keep_email_private"}}</strong></label> | |||
<input name="keep_email_private" type="checkbox" {{if .SignedUser.KeepEmailPrivate}}checked{{end}}> | |||
<div class="inline field"> | |||
<span class="inline field" data-tooltip-content="{{ctx.Locale.Tr "settings.activity_visibility_popup"}}"><label>{{ctx.Locale.Tr "settings.activity_visibility"}}</label></span> | |||
<div class="ui selection type dropdown"> | |||
<input type="hidden" id="activity_visibility" name="activity_visibility" value="{{printf "%d" .SignedUser.ActivityVisibility}}"> | |||
<div class="text"> | |||
{{if .SignedUser.ActivityVisibility.ShowPublic}}{{ctx.Locale.Tr "public"}}{{end}} | |||
{{if .SignedUser.ActivityVisibility.ShowAll}}{{ctx.Locale.Tr "all"}}{{end}} | |||
{{if .SignedUser.ActivityVisibility.ShowNone}}{{ctx.Locale.Tr "none"}}{{end}} | |||
</div> | |||
{{svg "octicon-triangle-down" 14 "dropdown icon"}} | |||
<div class="menu"> | |||
<div class="item" data-tooltip-content="{{ctx.Locale.Tr "settings.activity_visibility.public_popup"}}" data-value="0">{{ctx.Locale.Tr "public"}}</div> | |||
<div class="item" data-tooltip-content="{{ctx.Locale.Tr "settings.activity_visibility.all_popup"}}" data-value="1">{{ctx.Locale.Tr "all"}}</div> | |||
<div class="item" data-tooltip-content="{{ctx.Locale.Tr "settings.activity_visibility.none_popup"}}" data-value="2">{{ctx.Locale.Tr "none"}}</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="field"> | |||
<div class="ui checkbox" id="keep-activity-private"> | |||
<label data-tooltip-content="{{ctx.Locale.Tr "settings.keep_activity_private_popup"}}"><strong>{{ctx.Locale.Tr "settings.keep_activity_private"}}</strong></label> | |||
<input name="keep_activity_private" type="checkbox" {{if .SignedUser.KeepActivityPrivate}}checked{{end}}> | |||
<div class="ui checkbox"> | |||
<label data-tooltip-content="{{ctx.Locale.Tr "settings.keep_email_private_popup" .SignedUser.GetPlaceholderEmail}}"><strong>{{ctx.Locale.Tr "settings.keep_email_private"}}</strong></label> | |||
<input name="keep_email_private" type="checkbox" {{if .SignedUser.KeepEmailPrivate}}checked{{end}}> | |||
</div> | |||
</div> | |||
@@ -48,11 +48,11 @@ func testPrivateActivityDoSomethingForActionEntries(t *testing.T) { | |||
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", | |||
"_csrf": GetCSRF(t, session, "/user/settings"), | |||
"name": privateActivityTestUser, | |||
"email": privateActivityTestUser + "@example.com", | |||
"language": "en-US", | |||
"activity_visibility": fmt.Sprintf("%d", api.ActivityVisibilityNone), | |||
}) | |||
session.MakeRequest(t, req, http.StatusSeeOther) | |||
} |