From 914ffa496f8e8e9948ca8c5596da6b0d3c17555d Mon Sep 17 00:00:00 2001
From: Unknown <joe2010xtmf@163.com>
Date: Thu, 8 May 2014 19:17:43 -0400
Subject: [PATCH] Show private repository activities in dashboard if has access

---
 models/access.go           |  3 +++
 models/action.go           |  4 ++--
 modules/middleware/repo.go |  4 ++--
 modules/workers/worker.go  | 10 ++++++++++
 routers/repo/issue.go      | 16 +++++++++++++---
 routers/user/home.go       | 30 ++++++++++++++++++++++++------
 6 files changed, 54 insertions(+), 13 deletions(-)
 create mode 100644 modules/workers/worker.go

diff --git a/models/access.go b/models/access.go
index 4f944517ed..4a202dc6bc 100644
--- a/models/access.go
+++ b/models/access.go
@@ -60,6 +60,9 @@ func UpdateAccessWithSession(sess *xorm.Session, access *Access) error {
 // HasAccess returns true if someone can read or write to given repository.
 // The repoName should be in format <username>/<reponame>.
 func HasAccess(uname, repoName string, mode int) (bool, error) {
+	if len(repoName) == 0 {
+		return false, nil
+	}
 	access := &Access{
 		UserName: strings.ToLower(uname),
 		RepoName: strings.ToLower(repoName),
diff --git a/models/action.go b/models/action.go
index 02639e5538..6c18d022d0 100644
--- a/models/action.go
+++ b/models/action.go
@@ -198,8 +198,8 @@ func TransferRepoAction(user, newUser *User, repo *Repository) (err error) {
 }
 
 // GetFeeds returns action list of given user in given context.
-func GetFeeds(userid, offset int64, isProfile bool) ([]Action, error) {
-	actions := make([]Action, 0, 20)
+func GetFeeds(userid, offset int64, isProfile bool) ([]*Action, error) {
+	actions := make([]*Action, 0, 20)
 	sess := orm.Limit(20, int(offset)).Desc("id").Where("user_id=?", userid)
 	if isProfile {
 		sess.Where("is_private=?", false).And("act_user_id=?", userid)
diff --git a/modules/middleware/repo.go b/modules/middleware/repo.go
index 53d4dae4f8..4a10edf881 100644
--- a/modules/middleware/repo.go
+++ b/modules/middleware/repo.go
@@ -50,7 +50,7 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler {
 
 		// Collaborators who have write access can be seen as owners.
 		if ctx.IsSigned {
-			ctx.Repo.IsOwner, err = models.HasAccess(ctx.User.Name, repoName, models.AU_WRITABLE)
+			ctx.Repo.IsOwner, err = models.HasAccess(ctx.User.Name, userName+"/"+repoName, models.AU_WRITABLE)
 			if err != nil {
 				ctx.Handle(500, "RepoAssignment(HasAccess)", err)
 				return
@@ -100,7 +100,7 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler {
 		}
 
 		// Check access.
-		if repo.IsPrivate {
+		if repo.IsPrivate && !ctx.Repo.IsOwner {
 			if ctx.User == nil {
 				ctx.Handle(404, "RepoAssignment(HasAccess)", nil)
 				return
diff --git a/modules/workers/worker.go b/modules/workers/worker.go
new file mode 100644
index 0000000000..97535b2b4d
--- /dev/null
+++ b/modules/workers/worker.go
@@ -0,0 +1,10 @@
+// Copyright 2014 The Gogs 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 workers
+
+// Work represents a background work interface of any kind.
+type Work interface {
+	Do() error
+}
diff --git a/routers/repo/issue.go b/routers/repo/issue.go
index 1f681c39fd..3343800663 100644
--- a/routers/repo/issue.go
+++ b/routers/repo/issue.go
@@ -178,10 +178,20 @@ func CreateIssuePost(ctx *middleware.Context, params martini.Params, form auth.C
 		}
 	}
 
+	act := &models.Action{
+		ActUserId:    ctx.User.Id,
+		ActUserName:  ctx.User.Name,
+		ActEmail:     ctx.User.Email,
+		OpType:       models.OP_CREATE_ISSUE,
+		Content:      fmt.Sprintf("%d|%s", issue.Index, issue.Name),
+		RepoId:       ctx.Repo.Repository.Id,
+		RepoUserName: ctx.Repo.Owner.Name,
+		RepoName:     ctx.Repo.Repository.Name,
+		RefName:      ctx.Repo.BranchName,
+		IsPrivate:    ctx.Repo.Repository.IsPrivate,
+	}
 	// Notify watchers.
-	if err := models.NotifyWatchers(&models.Action{ActUserId: ctx.User.Id, ActUserName: ctx.User.Name, ActEmail: ctx.User.Email,
-		OpType: models.OP_CREATE_ISSUE, Content: fmt.Sprintf("%d|%s", issue.Index, issue.Name),
-		RepoId: ctx.Repo.Repository.Id, RepoName: ctx.Repo.Repository.Name, RefName: ""}); err != nil {
+	if err := models.NotifyWatchers(act); err != nil {
 		ctx.Handle(500, "issue.CreateIssue(NotifyWatchers)", err)
 		return
 	}
diff --git a/routers/user/home.go b/routers/user/home.go
index 11ac1a8126..775df03752 100644
--- a/routers/user/home.go
+++ b/routers/user/home.go
@@ -27,11 +27,23 @@ func Dashboard(ctx *middleware.Context) {
 	}
 	ctx.Data["MyRepos"] = repos
 
-	feeds, err := models.GetFeeds(ctx.User.Id, 0, false)
+	actions, err := models.GetFeeds(ctx.User.Id, 0, false)
 	if err != nil {
 		ctx.Handle(500, "user.Dashboard", err)
 		return
 	}
+
+	feeds := make([]*models.Action, 0, len(actions))
+	for _, act := range actions {
+		if act.IsPrivate {
+			if has, _ := models.HasAccess(ctx.User.Name, act.RepoUserName+"/"+act.RepoName,
+				models.AU_READABLE); !has {
+				continue
+			}
+		}
+		feeds = append(feeds, act)
+	}
+
 	ctx.Data["Feeds"] = feeds
 	ctx.HTML(200, "user/dashboard")
 }
@@ -39,7 +51,6 @@ func Dashboard(ctx *middleware.Context) {
 func Profile(ctx *middleware.Context, params martini.Params) {
 	ctx.Data["Title"] = "Profile"
 
-	// TODO: Need to check view self or others.
 	user, err := models.GetUserByName(params["username"])
 	if err != nil {
 		ctx.Handle(500, "user.Profile", err)
@@ -95,12 +106,19 @@ func Feeds(ctx *middleware.Context, form auth.FeedsForm) {
 	actions, err := models.GetFeeds(form.UserId, form.Page*20, false)
 	if err != nil {
 		ctx.JSON(500, err)
+		return
 	}
 
-	feeds := make([]string, len(actions))
-	for i := range actions {
-		feeds[i] = fmt.Sprintf(TPL_FEED, base.ActionIcon(actions[i].OpType),
-			base.TimeSince(actions[i].Created), base.ActionDesc(actions[i]))
+	feeds := make([]string, 0, len(actions))
+	for _, act := range actions {
+		if act.IsPrivate {
+			if has, _ := models.HasAccess(ctx.User.Name, act.RepoUserName+"/"+act.RepoName,
+				models.AU_READABLE); !has {
+				continue
+			}
+		}
+		feeds = append(feeds, fmt.Sprintf(TPL_FEED, base.ActionIcon(act.OpType),
+			base.TimeSince(act.Created), base.ActionDesc(act)))
 	}
 	ctx.JSON(200, &feeds)
 }