diff --git a/src/core/api/base.go b/src/core/api/base.go index 90c4961dc..29874c7df 100644 --- a/src/core/api/base.go +++ b/src/core/api/base.go @@ -84,24 +84,20 @@ func (b *BaseController) RequireAuthenticated() bool { // HasProjectPermission returns true when the request has action permission on project subresource func (b *BaseController) HasProjectPermission(projectIDOrName interface{}, action rbac.Action, subresource ...rbac.Resource) (bool, error) { - projectID, projectName, err := utils.ParseProjectIDOrName(projectIDOrName) + _, _, err := utils.ParseProjectIDOrName(projectIDOrName) if err != nil { return false, err } - if projectName != "" { - project, err := b.ProjectMgr.Get(projectName) - if err != nil { - return false, err - } - if project == nil { - return false, errors.NotFoundError(nil).WithMessage("project %s not found", projectName) - } - - projectID = project.ProjectID + project, err := b.ProjectMgr.Get(projectIDOrName) + if err != nil { + return false, err + } + if project == nil { + return false, errors.NotFoundError(fmt.Errorf("project %v not found", projectIDOrName)) } - resource := rbac.NewProjectNamespace(projectID).Resource(subresource...) + resource := rbac.NewProjectNamespace(project.ProjectID).Resource(subresource...) if !b.SecurityCtx.Can(action, resource) { return false, nil } @@ -114,24 +110,42 @@ func (b *BaseController) HasProjectPermission(projectIDOrName interface{}, actio func (b *BaseController) RequireProjectAccess(projectIDOrName interface{}, action rbac.Action, subresource ...rbac.Resource) bool { hasPermission, err := b.HasProjectPermission(projectIDOrName, action, subresource...) if err != nil { - b.SendError(err) - + if errors.IsNotFoundErr(err) { + b.handleProjectNotFound(projectIDOrName) + } else { + b.SendError(err) + } return false } if !hasPermission { - if !b.SecurityCtx.IsAuthenticated() { - b.SendError(errors.UnauthorizedError(errors.New("Unauthorized"))) - } else { - b.SendError(errors.New(errors.New(b.SecurityCtx.GetUsername())).WithCode(errors.ForbiddenCode)) - } - + b.SendPermissionError() return false } return true } +// This should be called when a project is not found, if the caller is a system admin it returns 404. +// If it's regular user, it will render permission error +func (b *BaseController) handleProjectNotFound(projectIDOrName interface{}) { + if b.SecurityCtx.IsSysAdmin() { + b.SendNotFoundError(fmt.Errorf("project %v not found", projectIDOrName)) + } else { + b.SendPermissionError() + } +} + +// SendPermissionError is a shortcut for sending different http error based on authentication status. +func (b *BaseController) SendPermissionError() { + if !b.SecurityCtx.IsAuthenticated() { + b.SendUnAuthorizedError(errors.New("UnAuthorized")) + } else { + b.SendForbiddenError(errors.New(b.SecurityCtx.GetUsername())) + } + +} + // WriteJSONData writes the JSON data to the client. func (b *BaseController) WriteJSONData(object interface{}) { b.Data["json"] = object diff --git a/src/core/api/metadata.go b/src/core/api/metadata.go index a3d6fa68b..92084531e 100644 --- a/src/core/api/metadata.go +++ b/src/core/api/metadata.go @@ -69,7 +69,7 @@ func (m *MetadataAPI) Prepare() { } if project == nil { - m.SendNotFoundError(fmt.Errorf("project %d not found", id)) + m.handleProjectNotFound(id) return } diff --git a/src/core/api/metadata_test.go b/src/core/api/metadata_test.go index 97dd59181..2fd6d823a 100644 --- a/src/core/api/metadata_test.go +++ b/src/core/api/metadata_test.go @@ -65,10 +65,10 @@ func TestValidateProjectMetadata(t *testing.T) { func TestMetaAPI(t *testing.T) { client := newHarborAPI() - // non-exist project + // non-exist project, it should return 401 if user is not logged in. code, _, err := client.PostMeta(*unknownUsr, int64(1000), nil) require.Nil(t, err) - assert.Equal(t, http.StatusNotFound, code) + assert.Equal(t, http.StatusUnauthorized, code) // non-login code, _, err = client.PostMeta(*unknownUsr, int64(1), nil) diff --git a/src/core/api/project.go b/src/core/api/project.go index a73d3c28b..87c385404 100644 --- a/src/core/api/project.go +++ b/src/core/api/project.go @@ -79,7 +79,7 @@ func (p *ProjectAPI) Prepare() { } if project == nil { - p.SendNotFoundError(fmt.Errorf("project %d not found", id)) + p.handleProjectNotFound(id) return }