Skip to content

[WIP] confidential Issue #11099

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion models/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type Issue struct {
Milestone *Milestone `xorm:"-"`
Project *Project `xorm:"-"`
Priority int
Confidential bool
AssigneeID int64 `xorm:"-"`
Assignee *User `xorm:"-"`
IsClosed bool `xorm:"INDEX"`
Expand Down Expand Up @@ -1120,6 +1121,8 @@ type IssuesOptions struct {
IssueIDs []int64
UpdatedAfterUnix int64
UpdatedBeforeUnix int64
Confidential bool
Doer *User
// prioritize issues from this repo
PriorityRepoID int64
IsArchived util.OptionalBool
Expand Down Expand Up @@ -1248,6 +1251,11 @@ func (opts *IssuesOptions) setupSession(sess *xorm.Session) {
if len(opts.ExcludedLabelNames) > 0 {
sess.And(builder.NotIn("issue.id", BuildLabelNamesIssueIDsCondition(opts.ExcludedLabelNames)))
}
if !opts.Confidential || opts.Doer == nil {
sess.And("issue.confidential = ?", false)
} else {
//sess.And("issue.confidential = ?", true)
}
}

func applyReposCondition(sess *xorm.Session, repoIDs []int64) *xorm.Session {
Expand Down Expand Up @@ -1345,7 +1353,8 @@ func Issues(opts *IssuesOptions) ([]*Issue, error) {
return nil, fmt.Errorf("LoadAttributes: %v", err)
}

return issues, nil
issues, _, err := FilterConfidentialIssue(opts.Doer, issues)
return issues, err
}

// CountIssues number return of issues by given conditions.
Expand Down Expand Up @@ -1449,6 +1458,8 @@ type IssueStatsOptions struct {
ReviewRequestedID int64
IsPull util.OptionalBool
IssueIDs []int64
Doer *User
Confidential bool
}

// GetIssueStats returns issue statistic information by given conditions.
Expand Down
56 changes: 56 additions & 0 deletions models/issue_confidential.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package models

import (
"code.gitea.io/gitea/modules/util"
)

func FilterConfidentialIssue(doer *User, list IssueList) (IssueList, int, error) {
var cutoff int = 0
var err error
var allowed bool
result := make(IssueList, len(list))

for i := range list {
if list[i].Confidential {
allowed, err = UserAllowedToLookAtConfidentialIssue(doer, list[i])
if err != nil {
return nil, 0, err
}
if allowed {
result[i-cutoff] = list[i]
} else {
cutoff += 1
}
} else {
result[i-cutoff] = list[i]
}

}
return result[:len(list)-cutoff], cutoff, nil
}

func UserAllowedToLookAtConfidentialIssue(doer *User, issue *Issue) (bool, error) {
if doer == nil {
return false, nil
}

// Issue Creator is allowed
if issue.PosterID == doer.ID {
return true, nil
}

// Assignees are allowed
assignees, err := GetAssigneeIDsByIssue(issue.ID)
if err != nil {
return false, err
}
if util.IsInt64InSlice(doer.ID, assignees) {
return true, nil
}

// RepoAdmins are allowed
if err := issue.LoadRepo(); err != nil {
return false, err
}
return IsUserRepoAdmin(issue.Repo, doer)
}
7 changes: 5 additions & 2 deletions modules/structs/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ type Issue struct {
Ref string `json:"ref"`
Labels []*Label `json:"labels"`
Milestone *Milestone `json:"milestone"`
Confidential bool `json:"confidential"`
// deprecated
Assignee *User `json:"assignee"`
Assignees []*User `json:"assignees"`
Expand Down Expand Up @@ -87,8 +88,9 @@ type CreateIssueOption struct {
// milestone id
Milestone int64 `json:"milestone"`
// list of label ids
Labels []int64 `json:"labels"`
Closed bool `json:"closed"`
Labels []int64 `json:"labels"`
Closed bool `json:"closed"`
Confidential bool `json:"confidential"`
}

// EditIssueOption options for editing an issue
Expand All @@ -104,6 +106,7 @@ type EditIssueOption struct {
// swagger:strfmt date-time
Deadline *time.Time `json:"due_date"`
RemoveDeadline *bool `json:"unset_due_date"`
Confidential *bool `json:"confidential"`
}

// EditDeadlineOption options for creating a deadline
Expand Down
32 changes: 32 additions & 0 deletions routers/api/v1/repo/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ func SearchIssues(ctx *context.APIContext) {
SortType: "priorityrepo",
PriorityRepoID: ctx.QueryInt64("priority_repo_id"),
IsPull: isPull,
Doer: ctx.User,
Confidential: true,
UpdatedBeforeUnix: before,
UpdatedAfterUnix: since,
}
Expand Down Expand Up @@ -367,6 +369,8 @@ func ListIssues(ctx *context.APIContext) {
LabelIDs: labelIDs,
MilestoneIDs: mileIDs,
IsPull: isPull,
Doer: ctx.User,
Confidential: true,
}

if issues, err = models.Issues(issuesOpt); err != nil {
Expand Down Expand Up @@ -428,6 +432,16 @@ func GetIssue(ctx *context.APIContext) {
}
return
}

if allowed, err := models.UserAllowedToLookAtConfidentialIssue(ctx.User, issue); err != nil || !allowed {
if err != nil {
ctx.Error(http.StatusInternalServerError, "UserAllowedToLookAtConfidentialIssue", err)
} else {
ctx.Status(http.StatusForbidden)
}
return
}

ctx.JSON(http.StatusOK, convert.ToAPIIssue(issue))
}

Expand Down Expand Up @@ -611,6 +625,15 @@ func EditIssue(ctx *context.APIContext) {
return
}

if allowed, err := models.UserAllowedToLookAtConfidentialIssue(ctx.User, issue); err != nil || !allowed {
if err != nil {
ctx.Error(http.StatusInternalServerError, "UserAllowedToLookAtConfidentialIssue", err)
} else {
ctx.Status(http.StatusForbidden)
}
return
}

oldTitle := issue.Title
if len(form.Title) > 0 {
issue.Title = form.Title
Expand Down Expand Up @@ -760,6 +783,15 @@ func UpdateIssueDeadline(ctx *context.APIContext) {
return
}

if allowed, err := models.UserAllowedToLookAtConfidentialIssue(ctx.User, issue); err != nil || !allowed {
if err != nil {
ctx.Error(http.StatusInternalServerError, "UserAllowedToLookAtConfidentialIssue", err)
} else {
ctx.Status(http.StatusForbidden)
}
return
}

var deadlineUnix timeutil.TimeStamp
var deadline time.Time
if form.Deadline != nil && !form.Deadline.IsZero() {
Expand Down
40 changes: 40 additions & 0 deletions routers/api/v1/repo/issue_reaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,19 @@ func GetIssueCommentReactions(ctx *context.APIContext) {
return
}

if err := comment.LoadIssue(); err != nil {
ctx.InternalServerError(err)
return
}
if allowed, err := models.UserAllowedToLookAtConfidentialIssue(ctx.User, comment.Issue); err != nil || !allowed {
if err != nil {
ctx.InternalServerError(err)
} else {
ctx.Status(http.StatusForbidden)
}
return
}

reactions, err := models.FindCommentReactions(comment)
if err != nil {
ctx.Error(http.StatusInternalServerError, "FindIssueReactions", err)
Expand Down Expand Up @@ -195,6 +208,15 @@ func changeIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOp
return
}

if allowed, err := models.UserAllowedToLookAtConfidentialIssue(ctx.User, comment.Issue); err != nil || !allowed {
if err != nil {
ctx.InternalServerError(err)
} else {
ctx.Status(http.StatusForbidden)
}
return
}

if isCreateType {
// PostIssueCommentReaction part
reaction, err := models.CreateCommentReaction(ctx.User, comment.Issue, comment, form.Reaction)
Expand Down Expand Up @@ -285,6 +307,15 @@ func GetIssueReactions(ctx *context.APIContext) {
return
}

if allowed, err := models.UserAllowedToLookAtConfidentialIssue(ctx.User, issue); err != nil || !allowed {
if err != nil {
ctx.InternalServerError(err)
} else {
ctx.Status(http.StatusForbidden)
}
return
}

reactions, err := models.FindIssueReactions(issue, utils.GetListOptions(ctx))
if err != nil {
ctx.Error(http.StatusInternalServerError, "FindIssueReactions", err)
Expand Down Expand Up @@ -404,6 +435,15 @@ func changeIssueReaction(ctx *context.APIContext, form api.EditReactionOption, i
return
}

if allowed, err := models.UserAllowedToLookAtConfidentialIssue(ctx.User, issue); err != nil || !allowed {
if err != nil {
ctx.InternalServerError(err)
} else {
ctx.Status(http.StatusForbidden)
}
return
}

if isCreateType {
// PostIssueReaction part
reaction, err := models.CreateIssueReaction(ctx.User, issue, form.Reaction)
Expand Down
18 changes: 18 additions & 0 deletions routers/api/v1/repo/issue_subscription.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,15 @@ func setIssueSubscription(ctx *context.APIContext, watch bool) {
return
}

if allowed, err := models.UserAllowedToLookAtConfidentialIssue(ctx.User, issue); err != nil || !allowed {
if err != nil {
ctx.InternalServerError(err)
} else {
ctx.Status(http.StatusForbidden)
}
return
}

current, err := models.CheckIssueWatch(user, issue)
if err != nil {
ctx.Error(http.StatusInternalServerError, "CheckIssueWatch", err)
Expand Down Expand Up @@ -261,6 +270,15 @@ func GetIssueSubscribers(ctx *context.APIContext) {
return
}

if allowed, err := models.UserAllowedToLookAtConfidentialIssue(ctx.User, issue); err != nil || !allowed {
if err != nil {
ctx.InternalServerError(err)
} else {
ctx.Status(http.StatusForbidden)
}
return
}

iwl, err := models.GetIssueWatchers(issue.ID, utils.GetListOptions(ctx))
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetIssueWatchers", err)
Expand Down
4 changes: 4 additions & 0 deletions routers/repo/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
ReviewRequestedID: reviewRequestedID,
IsPull: isPullOption,
IssueIDs: issueIDs,
Doer: ctx.User,
Confidential: true,
})
if err != nil {
ctx.ServerError("GetIssueStats", err)
Expand Down Expand Up @@ -232,6 +234,8 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
LabelIDs: labelIDs,
SortType: sortType,
IssueIDs: issueIDs,
Doer: ctx.User,
Confidential: true,
})
if err != nil {
ctx.ServerError("Issues", err)
Expand Down
8 changes: 5 additions & 3 deletions routers/user/home.go
Original file line number Diff line number Diff line change
Expand Up @@ -412,9 +412,11 @@ func buildIssueOverview(ctx *context.Context, unitType models.UnitType) {

isPullList := unitType == models.UnitTypePullRequests
opts := &models.IssuesOptions{
IsPull: util.OptionalBoolOf(isPullList),
SortType: sortType,
IsArchived: util.OptionalBoolFalse,
IsPull: util.OptionalBoolOf(isPullList),
SortType: sortType,
IsArchived: util.OptionalBoolFalse,
Doer: ctx.User,
Confidential: true,
}

// Get repository IDs where User/Org/Team has access.
Expand Down