diff options
author | Lunny Xiao <xiaolunwen@gmail.com> | 2018-11-28 19:26:14 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-28 19:26:14 +0800 |
commit | eabbddcd98717ef20d8475e819f403c50f4a9787 (patch) | |
tree | efc525e7ec60d56d3bec72019febfa088a128b89 /routers/api/v1/repo | |
parent | 0222623be9fa4a56d870213f77b92139cefc2518 (diff) | |
download | gitea-eabbddcd98717ef20d8475e819f403c50f4a9787.tar.gz gitea-eabbddcd98717ef20d8475e819f403c50f4a9787.zip |
Restrict permission check on repositories and fix some problems (#5314)
* fix units permission problems
* fix some bugs and merge LoadUnits to repoAssignment
* refactor permission struct and add some copyright heads
* remove unused codes
* fix routes units check
* improve permission check
* add unit tests for permission
* fix typo
* fix tests
* fix some routes
* fix api permission check
* improve permission check
* fix some permission check
* fix tests
* fix tests
* improve some permission check
* fix some permission check
* refactor AccessLevel
* fix bug
* fix tests
* fix tests
* fix tests
* fix AccessLevel
* rename CanAccess
* fix tests
* fix comment
* fix bug
* add missing unit for test repos
* fix bug
* rename some functions
* fix routes check
Diffstat (limited to 'routers/api/v1/repo')
-rw-r--r-- | routers/api/v1/repo/collaborators.go | 18 | ||||
-rw-r--r-- | routers/api/v1/repo/file.go | 6 | ||||
-rw-r--r-- | routers/api/v1/repo/fork.go | 3 | ||||
-rw-r--r-- | routers/api/v1/repo/issue.go | 15 | ||||
-rw-r--r-- | routers/api/v1/repo/issue_label.go | 41 | ||||
-rw-r--r-- | routers/api/v1/repo/label.go | 16 | ||||
-rw-r--r-- | routers/api/v1/repo/pull.go | 15 | ||||
-rw-r--r-- | routers/api/v1/repo/release.go | 12 | ||||
-rw-r--r-- | routers/api/v1/repo/repo.go | 20 |
9 files changed, 48 insertions, 98 deletions
diff --git a/routers/api/v1/repo/collaborators.go b/routers/api/v1/repo/collaborators.go index c52472b0f8..2f254f7103 100644 --- a/routers/api/v1/repo/collaborators.go +++ b/routers/api/v1/repo/collaborators.go @@ -1,4 +1,5 @@ // Copyright 2016 The Gogs Authors. All rights reserved. +// Copyright 2018 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. @@ -34,10 +35,6 @@ func ListCollaborators(ctx *context.APIContext) { // responses: // "200": // "$ref": "#/responses/UserList" - if !ctx.Repo.IsWriter() { - ctx.Error(403, "", "User does not have push access") - return - } collaborators, err := ctx.Repo.Repository.GetCollaborators() if err != nil { ctx.Error(500, "ListCollaborators", err) @@ -78,10 +75,6 @@ func IsCollaborator(ctx *context.APIContext) { // "$ref": "#/responses/empty" // "404": // "$ref": "#/responses/empty" - if !ctx.Repo.IsWriter() { - ctx.Error(403, "", "User does not have push access") - return - } user, err := models.GetUserByName(ctx.Params(":collaborator")) if err != nil { if models.IsErrUserNotExist(err) { @@ -133,10 +126,6 @@ func AddCollaborator(ctx *context.APIContext, form api.AddCollaboratorOption) { // responses: // "204": // "$ref": "#/responses/empty" - if !ctx.Repo.IsWriter() { - ctx.Error(403, "", "User does not have push access") - return - } collaborator, err := models.GetUserByName(ctx.Params(":collaborator")) if err != nil { if models.IsErrUserNotExist(err) { @@ -193,11 +182,6 @@ func DeleteCollaborator(ctx *context.APIContext) { // responses: // "204": // "$ref": "#/responses/empty" - if !ctx.Repo.IsWriter() { - ctx.Error(403, "", "User does not have push access") - return - } - collaborator, err := models.GetUserByName(ctx.Params(":collaborator")) if err != nil { if models.IsErrUserNotExist(err) { diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go index 610247bc27..81f2332089 100644 --- a/routers/api/v1/repo/file.go +++ b/routers/api/v1/repo/file.go @@ -1,4 +1,5 @@ // Copyright 2014 The Gogs Authors. All rights reserved. +// Copyright 2018 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. @@ -38,11 +39,6 @@ func GetRawFile(ctx *context.APIContext) { // responses: // 200: // description: success - if !ctx.Repo.HasAccess() { - ctx.Status(404) - return - } - if ctx.Repo.Repository.IsBare { ctx.Status(404) return diff --git a/routers/api/v1/repo/fork.go b/routers/api/v1/repo/fork.go index 843559d523..d10f668712 100644 --- a/routers/api/v1/repo/fork.go +++ b/routers/api/v1/repo/fork.go @@ -7,7 +7,6 @@ package repo import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/routers/api/v1/utils" api "code.gitea.io/sdk/gitea" ) @@ -40,7 +39,7 @@ func ListForks(ctx *context.APIContext) { } apiForks := make([]*api.Repository, len(forks)) for i, fork := range forks { - access, err := models.AccessLevel(utils.UserID(ctx), fork) + access, err := models.AccessLevel(ctx.User, fork) if err != nil { ctx.Error(500, "AccessLevel", err) return diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index cd78135a62..7a8ed09b48 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -169,7 +169,7 @@ func CreateIssue(ctx *context.APIContext, form api.CreateIssueOption) { // "$ref": "#/responses/Issue" var deadlineUnix util.TimeStamp - if form.Deadline != nil && ctx.Repo.IsWriter() { + if form.Deadline != nil && ctx.Repo.CanWrite(models.UnitTypeIssues) { deadlineUnix = util.TimeStamp(form.Deadline.Unix()) } @@ -184,7 +184,7 @@ func CreateIssue(ctx *context.APIContext, form api.CreateIssueOption) { var assigneeIDs = make([]int64, 0) var err error - if ctx.Repo.IsWriter() { + if ctx.Repo.CanWrite(models.UnitTypeIssues) { issue.MilestoneID = form.Milestone assigneeIDs, err = models.MakeIDsFromAPIAssigneesToAdd(form.Assignee, form.Assignees) if err != nil { @@ -274,7 +274,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) { return } - if !issue.IsPoster(ctx.User.ID) && !ctx.Repo.IsWriter() { + if !issue.IsPoster(ctx.User.ID) && !ctx.Repo.CanWrite(models.UnitTypeIssues) { ctx.Status(403) return } @@ -288,7 +288,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) { // Update the deadline var deadlineUnix util.TimeStamp - if form.Deadline != nil && !form.Deadline.IsZero() && ctx.Repo.IsWriter() { + if form.Deadline != nil && !form.Deadline.IsZero() && ctx.Repo.CanWrite(models.UnitTypeIssues) { deadlineUnix = util.TimeStamp(form.Deadline.Unix()) } @@ -305,8 +305,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) { // Pass one or more user logins to replace the set of assignees on this Issue. // Send an empty array ([]) to clear all assignees from the Issue. - if ctx.Repo.IsWriter() && (form.Assignees != nil || form.Assignee != nil) { - + if ctx.Repo.CanWrite(models.UnitTypeIssues) && (form.Assignees != nil || form.Assignee != nil) { oneAssignee := "" if form.Assignee != nil { oneAssignee = *form.Assignee @@ -319,7 +318,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) { } } - if ctx.Repo.IsWriter() && form.Milestone != nil && + if ctx.Repo.CanWrite(models.UnitTypeIssues) && form.Milestone != nil && issue.MilestoneID != *form.Milestone { oldMilestoneID := issue.MilestoneID issue.MilestoneID = *form.Milestone @@ -403,7 +402,7 @@ func UpdateIssueDeadline(ctx *context.APIContext, form api.EditDeadlineOption) { return } - if !ctx.Repo.IsWriter() { + if !ctx.Repo.CanWrite(models.UnitTypeIssues) { ctx.Status(403) return } diff --git a/routers/api/v1/repo/issue_label.go b/routers/api/v1/repo/issue_label.go index 35defa25b5..715dd0ed77 100644 --- a/routers/api/v1/repo/issue_label.go +++ b/routers/api/v1/repo/issue_label.go @@ -1,4 +1,5 @@ // Copyright 2016 The Gogs Authors. All rights reserved. +// Copyright 2018 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. @@ -90,11 +91,6 @@ func AddIssueLabels(ctx *context.APIContext, form api.IssueLabelsOption) { // responses: // "200": // "$ref": "#/responses/LabelList" - if !ctx.Repo.IsWriter() { - ctx.Status(403) - return - } - issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if models.IsErrIssueNotExist(err) { @@ -105,6 +101,11 @@ func AddIssueLabels(ctx *context.APIContext, form api.IssueLabelsOption) { return } + if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) { + ctx.Status(403) + return + } + labels, err := models.GetLabelsInRepoByIDs(ctx.Repo.Repository.ID, form.Labels) if err != nil { ctx.Error(500, "GetLabelsInRepoByIDs", err) @@ -162,11 +163,6 @@ func DeleteIssueLabel(ctx *context.APIContext) { // responses: // "204": // "$ref": "#/responses/empty" - if !ctx.Repo.IsWriter() { - ctx.Status(403) - return - } - issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if models.IsErrIssueNotExist(err) { @@ -177,6 +173,11 @@ func DeleteIssueLabel(ctx *context.APIContext) { return } + if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) { + ctx.Status(403) + return + } + label, err := models.GetLabelInRepoByID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")) if err != nil { if models.IsErrLabelNotExist(err) { @@ -228,11 +229,6 @@ func ReplaceIssueLabels(ctx *context.APIContext, form api.IssueLabelsOption) { // responses: // "200": // "$ref": "#/responses/LabelList" - if !ctx.Repo.IsWriter() { - ctx.Status(403) - return - } - issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if models.IsErrIssueNotExist(err) { @@ -243,6 +239,11 @@ func ReplaceIssueLabels(ctx *context.APIContext, form api.IssueLabelsOption) { return } + if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) { + ctx.Status(403) + return + } + labels, err := models.GetLabelsInRepoByIDs(ctx.Repo.Repository.ID, form.Labels) if err != nil { ctx.Error(500, "GetLabelsInRepoByIDs", err) @@ -294,11 +295,6 @@ func ClearIssueLabels(ctx *context.APIContext) { // responses: // "204": // "$ref": "#/responses/empty" - if !ctx.Repo.IsWriter() { - ctx.Status(403) - return - } - issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) if err != nil { if models.IsErrIssueNotExist(err) { @@ -309,6 +305,11 @@ func ClearIssueLabels(ctx *context.APIContext) { return } + if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) { + ctx.Status(403) + return + } + if err := issue.ClearLabels(ctx.User); err != nil { ctx.Error(500, "ClearLabels", err) return diff --git a/routers/api/v1/repo/label.go b/routers/api/v1/repo/label.go index 359ccf0e41..df7a370041 100644 --- a/routers/api/v1/repo/label.go +++ b/routers/api/v1/repo/label.go @@ -1,4 +1,5 @@ // Copyright 2016 The Gogs Authors. All rights reserved. +// Copyright 2018 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. @@ -123,11 +124,6 @@ func CreateLabel(ctx *context.APIContext, form api.CreateLabelOption) { // responses: // "201": // "$ref": "#/responses/Label" - if !ctx.Repo.IsWriter() { - ctx.Status(403) - return - } - label := &models.Label{ Name: form.Name, Color: form.Color, @@ -173,11 +169,6 @@ func EditLabel(ctx *context.APIContext, form api.EditLabelOption) { // responses: // "200": // "$ref": "#/responses/Label" - if !ctx.Repo.IsWriter() { - ctx.Status(403) - return - } - label, err := models.GetLabelInRepoByID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")) if err != nil { if models.IsErrLabelNotExist(err) { @@ -226,11 +217,6 @@ func DeleteLabel(ctx *context.APIContext) { // responses: // "204": // "$ref": "#/responses/empty" - if !ctx.Repo.IsWriter() { - ctx.Status(403) - return - } - if err := models.DeleteLabel(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")); err != nil { ctx.Error(500, "DeleteLabel", err) return diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index 83ef886d7d..a0117794ad 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -351,7 +351,7 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) { pr.LoadIssue() issue := pr.Issue - if !issue.IsPoster(ctx.User.ID) && !ctx.Repo.IsWriter() { + if !issue.IsPoster(ctx.User.ID) && !ctx.Repo.CanWrite(models.UnitTypePullRequests) { ctx.Status(403) return } @@ -382,7 +382,7 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) { // Pass one or more user logins to replace the set of assignees on this Issue. // Send an empty array ([]) to clear all assignees from the Issue. - if ctx.Repo.IsWriter() && (form.Assignees != nil || len(form.Assignee) > 0) { + if ctx.Repo.CanWrite(models.UnitTypePullRequests) && (form.Assignees != nil || len(form.Assignee) > 0) { err = models.UpdateAPIAssignee(issue, form.Assignee, form.Assignees, ctx.User) if err != nil { @@ -395,7 +395,7 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) { } } - if ctx.Repo.IsWriter() && form.Milestone != 0 && + if ctx.Repo.CanWrite(models.UnitTypePullRequests) && form.Milestone != 0 && issue.MilestoneID != form.Milestone { oldMilestoneID := issue.MilestoneID issue.MilestoneID = form.Milestone @@ -405,7 +405,7 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) { } } - if ctx.Repo.IsWriter() && (form.Labels != nil && len(form.Labels) > 0) { + if ctx.Repo.CanWrite(models.UnitTypePullRequests) && (form.Labels != nil && len(form.Labels) > 0) { labels, err := models.GetLabelsInRepoByIDs(ctx.Repo.Repository.ID, form.Labels) if err != nil { ctx.Error(500, "GetLabelsInRepoByIDsError", err) @@ -663,7 +663,12 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) } } - if !ctx.User.IsWriterOfRepo(headRepo) && !ctx.User.IsAdmin { + perm, err := models.GetUserRepoPermission(headRepo, ctx.User) + if err != nil { + ctx.ServerError("GetUserRepoPermission", err) + return nil, nil, nil, nil, "", "" + } + if !perm.CanWrite(models.UnitTypeCode) { log.Trace("ParseCompareInfo[%d]: does not have write access or site admin", baseRepo.ID) ctx.Status(404) return nil, nil, nil, nil, "", "" diff --git a/routers/api/v1/repo/release.go b/routers/api/v1/repo/release.go index 282ff582c5..caa2905e93 100644 --- a/routers/api/v1/repo/release.go +++ b/routers/api/v1/repo/release.go @@ -122,10 +122,6 @@ func CreateRelease(ctx *context.APIContext, form api.CreateReleaseOption) { // responses: // "201": // "$ref": "#/responses/Release" - if ctx.Repo.AccessMode < models.AccessModeWrite { - ctx.Status(403) - return - } rel, err := models.GetRelease(ctx.Repo.Repository.ID, form.TagName) if err != nil { if !models.IsErrReleaseNotExist(err) { @@ -209,10 +205,6 @@ func EditRelease(ctx *context.APIContext, form api.EditReleaseOption) { // responses: // "200": // "$ref": "#/responses/Release" - if ctx.Repo.AccessMode < models.AccessModeWrite { - ctx.Status(403) - return - } id := ctx.ParamsInt64(":id") rel, err := models.GetReleaseByID(id) if err != nil && !models.IsErrReleaseNotExist(err) { @@ -285,10 +277,6 @@ func DeleteRelease(ctx *context.APIContext) { // responses: // "204": // "$ref": "#/responses/empty" - if ctx.Repo.AccessMode < models.AccessModeWrite { - ctx.Status(403) - return - } id := ctx.ParamsInt64(":id") rel, err := models.GetReleaseByID(id) if err != nil && !models.IsErrReleaseNotExist(err) { diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index bf6346eebd..6d8125a77f 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -1,4 +1,5 @@ // Copyright 2014 The Gogs Authors. All rights reserved. +// Copyright 2018 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. @@ -183,11 +184,6 @@ func Search(ctx *context.APIContext) { return } - var userID int64 - if ctx.IsSigned { - userID = ctx.User.ID - } - results := make([]*api.Repository, len(repos)) for i, repo := range repos { if err = repo.GetOwner(); err != nil { @@ -197,7 +193,7 @@ func Search(ctx *context.APIContext) { }) return } - accessMode, err := models.AccessLevel(userID, repo) + accessMode, err := models.AccessLevel(ctx.User, repo) if err != nil { ctx.JSON(500, api.SearchError{ OK: false, @@ -469,15 +465,15 @@ func GetByID(ctx *context.APIContext) { return } - access, err := models.AccessLevel(ctx.User.ID, repo) + perm, err := models.GetUserRepoPermission(repo, ctx.User) if err != nil { ctx.Error(500, "AccessLevel", err) return - } else if access < models.AccessModeRead { + } else if !perm.HasAccess() { ctx.Status(404) return } - ctx.JSON(200, repo.APIFormat(access)) + ctx.JSON(200, repo.APIFormat(perm.AccessMode)) } // Delete one repository @@ -503,10 +499,6 @@ func Delete(ctx *context.APIContext) { // "$ref": "#/responses/empty" // "403": // "$ref": "#/responses/forbidden" - if !ctx.Repo.IsAdmin() { - ctx.Error(403, "", "Must have admin rights") - return - } owner := ctx.Repo.Owner repo := ctx.Repo.Repository @@ -553,7 +545,7 @@ func MirrorSync(ctx *context.APIContext) { // "$ref": "#/responses/empty" repo := ctx.Repo.Repository - if !ctx.Repo.IsWriter() { + if !ctx.Repo.CanWrite(models.UnitTypeCode) { ctx.Error(403, "MirrorSync", "Must have write access") } |