mirror of
https://github.com/go-gitea/gitea
synced 2025-07-23 18:58:38 +00:00
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
This commit is contained in:
@@ -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) {
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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, "", ""
|
||||
|
@@ -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) {
|
||||
|
@@ -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")
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user