Implement "conversation lock" for issue comments (#5073)
	
		
	
				
					
				
			
							parent
							
								
									64ce159a6e
								
							
						
					
					
						commit
						44114b38e6
					
				@ -0,0 +1,51 @@ | 
				
			||||
// Copyright 2019 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 models | 
				
			||||
 | 
				
			||||
// IssueLockOptions defines options for locking and/or unlocking an issue/PR
 | 
				
			||||
type IssueLockOptions struct { | 
				
			||||
	Doer   *User | 
				
			||||
	Issue  *Issue | 
				
			||||
	Reason string | 
				
			||||
} | 
				
			||||
 | 
				
			||||
// LockIssue locks an issue. This would limit commenting abilities to
 | 
				
			||||
// users with write access to the repo
 | 
				
			||||
func LockIssue(opts *IssueLockOptions) error { | 
				
			||||
	return updateIssueLock(opts, true) | 
				
			||||
} | 
				
			||||
 | 
				
			||||
// UnlockIssue unlocks a previously locked issue.
 | 
				
			||||
func UnlockIssue(opts *IssueLockOptions) error { | 
				
			||||
	return updateIssueLock(opts, false) | 
				
			||||
} | 
				
			||||
 | 
				
			||||
func updateIssueLock(opts *IssueLockOptions, lock bool) error { | 
				
			||||
	if opts.Issue.IsLocked == lock { | 
				
			||||
		return nil | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	opts.Issue.IsLocked = lock | 
				
			||||
 | 
				
			||||
	var commentType CommentType | 
				
			||||
	if opts.Issue.IsLocked { | 
				
			||||
		commentType = CommentTypeLock | 
				
			||||
	} else { | 
				
			||||
		commentType = CommentTypeUnlock | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	if err := UpdateIssueCols(opts.Issue, "is_locked"); err != nil { | 
				
			||||
		return err | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	_, err := CreateComment(&CreateCommentOptions{ | 
				
			||||
		Doer:    opts.Doer, | 
				
			||||
		Issue:   opts.Issue, | 
				
			||||
		Repo:    opts.Issue.Repo, | 
				
			||||
		Type:    commentType, | 
				
			||||
		Content: opts.Reason, | 
				
			||||
	}) | 
				
			||||
	return err | 
				
			||||
} | 
				
			||||
@ -0,0 +1,18 @@ | 
				
			||||
// Copyright 2019 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 "github.com/go-xorm/xorm" | 
				
			||||
 | 
				
			||||
func addIsLockedToIssues(x *xorm.Engine) error { | 
				
			||||
	// Issue see models/issue.go
 | 
				
			||||
	type Issue struct { | 
				
			||||
		ID       int64 `xorm:"pk autoincr"` | 
				
			||||
		IsLocked bool  `xorm:"NOT NULL DEFAULT false"` | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	return x.Sync2(new(Issue)) | 
				
			||||
 | 
				
			||||
} | 
				
			||||
@ -0,0 +1,71 @@ | 
				
			||||
// Copyright 2019 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 repo | 
				
			||||
 | 
				
			||||
import ( | 
				
			||||
	"net/http" | 
				
			||||
 | 
				
			||||
	"code.gitea.io/gitea/models" | 
				
			||||
	"code.gitea.io/gitea/modules/auth" | 
				
			||||
	"code.gitea.io/gitea/modules/context" | 
				
			||||
) | 
				
			||||
 | 
				
			||||
// LockIssue locks an issue. This would limit commenting abilities to
 | 
				
			||||
// users with write access to the repo.
 | 
				
			||||
func LockIssue(ctx *context.Context, form auth.IssueLockForm) { | 
				
			||||
 | 
				
			||||
	issue := GetActionIssue(ctx) | 
				
			||||
	if ctx.Written() { | 
				
			||||
		return | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	if issue.IsLocked { | 
				
			||||
		ctx.Flash.Error(ctx.Tr("repo.issues.lock_duplicate")) | 
				
			||||
		ctx.Redirect(issue.HTMLURL()) | 
				
			||||
		return | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	if !form.HasValidReason() { | 
				
			||||
		ctx.Flash.Error(ctx.Tr("repo.issues.lock.unknown_reason")) | 
				
			||||
		ctx.Redirect(issue.HTMLURL()) | 
				
			||||
		return | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	if err := models.LockIssue(&models.IssueLockOptions{ | 
				
			||||
		Doer:   ctx.User, | 
				
			||||
		Issue:  issue, | 
				
			||||
		Reason: form.Reason, | 
				
			||||
	}); err != nil { | 
				
			||||
		ctx.ServerError("LockIssue", err) | 
				
			||||
		return | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	ctx.Redirect(issue.HTMLURL(), http.StatusSeeOther) | 
				
			||||
} | 
				
			||||
 | 
				
			||||
// UnlockIssue unlocks a previously locked issue.
 | 
				
			||||
func UnlockIssue(ctx *context.Context) { | 
				
			||||
 | 
				
			||||
	issue := GetActionIssue(ctx) | 
				
			||||
	if ctx.Written() { | 
				
			||||
		return | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	if !issue.IsLocked { | 
				
			||||
		ctx.Flash.Error(ctx.Tr("repo.issues.unlock_error")) | 
				
			||||
		ctx.Redirect(issue.HTMLURL()) | 
				
			||||
		return | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	if err := models.UnlockIssue(&models.IssueLockOptions{ | 
				
			||||
		Doer:  ctx.User, | 
				
			||||
		Issue: issue, | 
				
			||||
	}); err != nil { | 
				
			||||
		ctx.ServerError("UnlockIssue", err) | 
				
			||||
		return | 
				
			||||
	} | 
				
			||||
 | 
				
			||||
	ctx.Redirect(issue.HTMLURL(), http.StatusSeeOther) | 
				
			||||
} | 
				
			||||
					Loading…
					
					
				
		Reference in new issue