Browse Source

Show owner/poster tags of comments and fix #1312

Unknwon 9 years ago
parent
commit
817b48ed1e

+ 0 - 1
README.md

@@ -97,7 +97,6 @@ There are 5 ways to install Gogs:
 - Mail Service, modules design is inspired by [WeTalk](https://github.com/beego/wetalk).
 - System Monitor Status is inspired by [GoBlog](https://github.com/fuxiaohei/goblog).
 - Thanks [lavachen](http://www.lavachen.cn/) and [Rocker](http://weibo.com/rocker1989) for designing Logo.
-- Thanks [gobuild.io](http://gobuild.io) for providing binary compile and download service.
 - Thanks [Crowdin](https://crowdin.com/project/gogs) for providing open source translation plan.
 
 ## Contributors

+ 0 - 1
README_ZH.md

@@ -67,7 +67,6 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自
 - 基于 [Macaron](https://github.com/Unknwon/macaron) 的路由与中间件机制。
 - 基于 [WeTalk](https://github.com/beego/wetalk) 修改的邮件服务和模块设计。
 - 基于 [GoBlog](https://github.com/fuxiaohei/goblog) 修改的系统监视状态。
-- 感谢 [gobuild.io](http://gobuild.io) 提供二进制编译与下载服务。
 - 感谢 [lavachen](http://www.lavachen.cn/) 和 [Rocker](http://weibo.com/rocker1989) 设计的 Logo。
 - 感谢 [Crowdin](https://crowdin.com/project/gogs) 提供免费的开源项目本地化支持。
 

+ 7 - 0
conf/locale/locale_en-US.ini

@@ -413,6 +413,13 @@ issues.reopen_issue = Reopen
 issues.reopen_comment_issue = Reopen and comment
 issues.create_comment = Comment
 issues.closed_at = `closed at <a id="%[1]s" href="#%[1]s">%[2]s</a>`
+issues.reopened_at = `reopened at <a id="%[1]s" href="#%[1]s">%[2]s</a>`
+issues.poster = Poster
+issues.admin = Admin
+issues.owner = Owner
+issues.not_signed_in = You must sign in to comment
+issues.sign_up_for_free = Sign up for free
+issues.sign_in_require_desc = to join this conversation. Already have an account? <a href="%s">Sign in to comment</a>
 issues.label_title = Label name
 issues.label_color = Label color
 issues.label_count = %d labels

+ 1 - 1
gogs.go

@@ -17,7 +17,7 @@ import (
 	"github.com/gogits/gogs/modules/setting"
 )
 
-const APP_VER = "0.6.4.0813 Beta"
+const APP_VER = "0.6.4.0814 Beta"
 
 func init() {
 	runtime.GOMAXPROCS(runtime.NumCPU())

+ 12 - 0
models/issue.go

@@ -1231,6 +1231,15 @@ const (
 	COMMENT_TYPE_PULL_REF
 )
 
+type CommentTag int
+
+const (
+	COMMENT_TAG_NONE CommentTag = iota
+	COMMENT_TAG_POSTER
+	COMMENT_TAG_ADMIN
+	COMMENT_TAG_OWNER
+)
+
 // Comment represents a comment in commit and issue page.
 type Comment struct {
 	ID              int64 `xorm:"pk autoincr"`
@@ -1245,6 +1254,9 @@ type Comment struct {
 	Created         time.Time `xorm:"CREATED"`
 
 	Attachments []*Attachment `xorm:"-"`
+
+	// For view issue page.
+	ShowTag CommentTag `xorm:"-"`
 }
 
 // HashTag returns unique hash tag for comment.

+ 2 - 2
models/repo.go

@@ -247,8 +247,8 @@ func (repo *Repository) HasAccess(u *User) bool {
 	return has
 }
 
-func (repo *Repository) IsOwnedBy(u *User) bool {
-	return repo.OwnerID == u.Id
+func (repo *Repository) IsOwnedBy(userID int64) bool {
+	return repo.OwnerID == userID
 }
 
 // DescriptionHtml does special handles to description and return HTML string.

+ 19 - 0
models/user.go

@@ -222,6 +222,25 @@ func (u *User) UploadAvatar(data []byte) error {
 	return sess.Commit()
 }
 
+// IsAdminOfRepo returns true if user has admin or higher access of repository.
+func (u *User) IsAdminOfRepo(repo *Repository) bool {
+	if err := repo.GetOwner(); err != nil {
+		log.Error(3, "GetOwner: %v", err)
+		return false
+	}
+
+	if repo.Owner.IsOrganization() {
+		has, err := HasAccess(u, repo, ACCESS_MODE_ADMIN)
+		if err != nil {
+			log.Error(3, "HasAccess: %v", err)
+			return false
+		}
+		return has
+	}
+
+	return repo.IsOwnedBy(u.Id)
+}
+
 // IsOrganization returns true if user is actually a organization.
 func (u *User) IsOrganization() bool {
 	return u.Type == ORGANIZATION

File diff suppressed because it is too large
+ 0 - 0
modules/bindata/bindata.go


+ 39 - 0
modules/middleware/auth.go

@@ -5,12 +5,16 @@
 package middleware
 
 import (
+	"fmt"
 	"net/url"
 
 	"github.com/Unknwon/macaron"
 	"github.com/macaron-contrib/csrf"
 
+	"github.com/gogits/gogs/models"
 	"github.com/gogits/gogs/modules/auth"
+	"github.com/gogits/gogs/modules/base"
+	"github.com/gogits/gogs/modules/log"
 	"github.com/gogits/gogs/modules/setting"
 )
 
@@ -21,6 +25,41 @@ type ToggleOptions struct {
 	DisableCsrf    bool
 }
 
+// AutoSignIn reads cookie and try to auto-login.
+func AutoSignIn(ctx *Context) (bool, error) {
+	uname := ctx.GetCookie(setting.CookieUserName)
+	if len(uname) == 0 {
+		return false, nil
+	}
+
+	isSucceed := false
+	defer func() {
+		if !isSucceed {
+			log.Trace("auto-login cookie cleared: %s", uname)
+			ctx.SetCookie(setting.CookieUserName, "", -1, setting.AppSubUrl)
+			ctx.SetCookie(setting.CookieRememberName, "", -1, setting.AppSubUrl)
+		}
+	}()
+
+	u, err := models.GetUserByName(uname)
+	if err != nil {
+		if !models.IsErrUserNotExist(err) {
+			return false, fmt.Errorf("GetUserByName: %v", err)
+		}
+		return false, nil
+	}
+
+	if val, _ := ctx.GetSuperSecureCookie(
+		base.EncodeMd5(u.Rands+u.Passwd), setting.CookieRememberName); val != u.Name {
+		return false, nil
+	}
+
+	isSucceed = true
+	ctx.Session.Set("uid", u.Id)
+	ctx.Session.Set("uname", u.Name)
+	return true, nil
+}
+
 func Toggle(options *ToggleOptions) macaron.Handler {
 	return func(ctx *Context) {
 		// Cannot view any page before installation.

+ 8 - 0
modules/middleware/context.go

@@ -197,6 +197,14 @@ func Contexter() macaron.Handler {
 
 		ctx.Data["PageStartTime"] = time.Now()
 
+		// Check auto-signin.
+		if sess.Get("uid") == nil {
+			if _, err := AutoSignIn(ctx); err != nil {
+				ctx.Handle(500, "AutoSignIn", err)
+				return
+			}
+		}
+
 		// Get user from session if logined.
 		ctx.User, ctx.IsBasicAuth = auth.SignedInUser(ctx.Req.Request, ctx.Session)
 

File diff suppressed because it is too large
+ 0 - 0
public/css/gogs.min.css


+ 8 - 0
public/less/_repository.less

@@ -180,6 +180,14 @@
 				.avatar {
 					width: @comment-avatar-width;
 				}
+				.tag {    
+					color: #767676;
+					margin-top: 3px;
+			    padding: 2px 5px;
+			    font-size: 12px;
+			    border: 1px solid rgba(0,0,0,0.1);
+			    border-radius: 3px;
+				}
 				.content {
 					margin-left: 4em;
 					.header {

+ 30 - 5
routers/repo/issue.go

@@ -427,7 +427,7 @@ func ViewIssue(ctx *middleware.Context) {
 	ctx.Data["Title"] = issue.Name
 
 	if err = issue.GetPoster(); err != nil {
-		ctx.Handle(500, "GetPoster: %v", err)
+		ctx.Handle(500, "GetPoster", err)
 		return
 	}
 	issue.RenderedContent = string(base.RenderMarkdown([]byte(issue.Content), ctx.Repo.RepoLink))
@@ -441,7 +441,7 @@ func ViewIssue(ctx *middleware.Context) {
 	if ctx.IsSigned {
 		// Update issue-user.
 		if err = issue.ReadBy(ctx.User.Id); err != nil {
-			ctx.Handle(500, "ReadBy: %v", err)
+			ctx.Handle(500, "ReadBy", err)
 			return
 		}
 
@@ -475,10 +475,35 @@ func ViewIssue(ctx *middleware.Context) {
 		}
 	}
 
+	var (
+		repo    = ctx.Repo.Repository
+		tag     models.CommentTag
+		ok      bool
+		marked  = make(map[int64]models.CommentTag)
+		comment *models.Comment
+	)
 	// Render comments.
-	for i := range issue.Comments {
-		if issue.Comments[i].Type == models.COMMENT_TYPE_COMMENT {
-			issue.Comments[i].RenderedContent = string(base.RenderMarkdown([]byte(issue.Comments[i].Content), ctx.Repo.RepoLink))
+	for _, comment = range issue.Comments {
+		if comment.Type == models.COMMENT_TYPE_COMMENT {
+			comment.RenderedContent = string(base.RenderMarkdown([]byte(comment.Content), ctx.Repo.RepoLink))
+
+			// Check tag.
+			tag, ok = marked[comment.PosterID]
+			if ok {
+				comment.ShowTag = tag
+				continue
+			}
+
+			if repo.IsOwnedBy(comment.PosterID) ||
+				(repo.Owner.IsOrganization() && repo.Owner.IsOwnedBy(comment.PosterID)) {
+				comment.ShowTag = models.COMMENT_TAG_OWNER
+			} else if comment.Poster.IsAdminOfRepo(repo) {
+				comment.ShowTag = models.COMMENT_TAG_ADMIN
+			} else if comment.PosterID == issue.PosterID {
+				comment.ShowTag = models.COMMENT_TAG_POSTER
+			}
+
+			marked[comment.PosterID] = comment.ShowTag
 		}
 	}
 

+ 9 - 36
routers/user/auth.go

@@ -42,49 +42,22 @@ func SignIn(ctx *middleware.Context) {
 	}
 
 	// Check auto-login.
-	uname := ctx.GetCookie(setting.CookieUserName)
-	if len(uname) == 0 {
-		ctx.HTML(200, SIGNIN)
-		return
-	}
-
-	isSucceed := false
-	defer func() {
-		if !isSucceed {
-			log.Trace("auto-login cookie cleared: %s", uname)
-			ctx.SetCookie(setting.CookieUserName, "", -1, setting.AppSubUrl)
-			ctx.SetCookie(setting.CookieRememberName, "", -1, setting.AppSubUrl)
-			return
-		}
-	}()
-
-	u, err := models.GetUserByName(uname)
+	isSucceed, err := middleware.AutoSignIn(ctx)
 	if err != nil {
-		if !models.IsErrUserNotExist(err) {
-			ctx.Handle(500, "GetUserByName", err)
-		} else {
-			ctx.HTML(200, SIGNIN)
-		}
-		return
-	}
-
-	if val, _ := ctx.GetSuperSecureCookie(
-		base.EncodeMd5(u.Rands+u.Passwd), setting.CookieRememberName); val != u.Name {
-		ctx.HTML(200, SIGNIN)
+		ctx.Handle(500, "AutoSignIn", err)
 		return
 	}
 
-	isSucceed = true
-
-	ctx.Session.Set("uid", u.Id)
-	ctx.Session.Set("uname", u.Name)
-	if redirectTo, _ := url.QueryUnescape(ctx.GetCookie("redirect_to")); len(redirectTo) > 0 {
-		ctx.SetCookie("redirect_to", "", -1, setting.AppSubUrl)
-		ctx.Redirect(redirectTo)
+	if isSucceed {
+		if redirectTo, _ := url.QueryUnescape(ctx.GetCookie("redirect_to")); len(redirectTo) > 0 {
+			ctx.SetCookie("redirect_to", "", -1, setting.AppSubUrl)
+			ctx.Redirect(redirectTo)
+		}
+		ctx.Redirect(setting.AppSubUrl + "/")
 		return
 	}
 
-	ctx.Redirect(setting.AppSubUrl + "/")
+	ctx.HTML(200, SIGNIN)
 }
 
 func SignInPost(ctx *middleware.Context, form auth.SignInForm) {

+ 1 - 1
templates/.VERSION

@@ -1 +1 @@
-0.6.4.0813 Beta
+0.6.4.0814 Beta

+ 21 - 3
templates/repo/issue/view_content.tmpl

@@ -22,8 +22,8 @@
 	<div class="twelve wide column comment-list">
   	<ui class="ui comments">
   		<div class="comment">
-		    <a class="avatar" href="{{.SignedUser.HomeLink}}">
-		      <img src="{{.SignedUser.AvatarLink}}">
+		    <a class="avatar" href="{{.Issue.Poster.HomeLink}}">
+		      <img src="{{.Issue.Poster.AvatarLink}}">
 		    </a>
 		    <div class="content">
 					<div class="ui top attached header">
@@ -63,6 +63,17 @@
 					<div class="ui top attached header">
 						<span class="text grey"><a href="{{.Poster.HomeLink}}">{{.Poster.Name}}</a> {{$.i18n.Tr "repo.issues.commented_at" .HashTag $createdStr | Safe}}</span>
 					  <div class="ui right actions">
+					  	{{if gt .ShowTag 0}}
+					  	<div class="tag">
+					  	{{if eq .ShowTag 1}}
+							{{$.i18n.Tr "repo.issues.poster"}}
+					  	{{else if eq .ShowTag 2}}
+							{{$.i18n.Tr "repo.issues.admin"}}
+					  	{{else if eq .ShowTag 3}}
+							{{$.i18n.Tr "repo.issues.owner"}}
+					  	{{end}}
+					  	</div>
+					  	{{end}}
 					  </div>
 					</div>
 			    <div class="ui attached segment markdown">
@@ -89,7 +100,7 @@
   			<a class="ui avatar image" href="{{.Poster.HomeLink}}">
   			  <img src="{{.Poster.AvatarLink}}">
   			</a>
-  			<span class="text grey"><a href="{{.Poster.HomeLink}}">{{.Poster.Name}}</a> {{$.i18n.Tr "repo.issues.closed_at" .EventTag $createdStr | Safe}}</span>
+  			<span class="text grey"><a href="{{.Poster.HomeLink}}">{{.Poster.Name}}</a> {{$.i18n.Tr "repo.issues.reopened_at" .EventTag $createdStr | Safe}}</span>
   		</div>
   		{{else if eq .Type 2}}
   		<div class="event">
@@ -103,6 +114,7 @@
 
   		{{end}}
 
+			{{if .IsSigned}}
 		  <div class="comment form">
 		    <a class="avatar" href="{{.SignedUser.HomeLink}}">
 		      <img src="{{.SignedUser.AvatarLink}}">
@@ -129,6 +141,12 @@
 			    </form>
 		    </div>
 		  </div>
+		  {{else}}
+		  <div class="ui warning message">
+		    <a href="/user/sign_up" class="ui green button">{{.i18n.Tr "repo.issues.sign_up_for_free"}}</a>
+		    {{.i18n.Tr "repo.issues.sign_in_require_desc" "/user/login" | Safe}}
+		  </div>
+		  {{end}}
   	</ui>
 	</div>
 

Some files were not shown because too many files changed in this diff