Implement current security interfaces using ram

Signed-off-by: He Weiwei <hweiwei@vmware.com>
This commit is contained in:
He Weiwei 2019-01-16 16:08:17 +08:00
parent b5788f0695
commit ebd26c0105
15 changed files with 680 additions and 108 deletions

View File

@ -0,0 +1,57 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ram
import (
"fmt"
)
// Namespace the namespace interface
type Namespace interface {
// Kind returns the kind of namespace
Kind() string
// Resource returns new resource for subresources with the namespace
Resource(subresources ...Resource) Resource
// Identity returns identity attached with namespace
Identity() interface{}
// IsPublic returns true if namespace is public
IsPublic() bool
}
type projectNamespace struct {
projectIDOrName interface{}
isPublic bool
}
func (ns *projectNamespace) Kind() string {
return "project"
}
func (ns *projectNamespace) Resource(subresources ...Resource) Resource {
return Resource(fmt.Sprintf("/project/%v", ns.projectIDOrName)).Subresource(subresources...)
}
func (ns *projectNamespace) Identity() interface{} {
return ns.projectIDOrName
}
func (ns *projectNamespace) IsPublic() bool {
return ns.isPublic
}
// NewProjectNamespace returns namespace for project
func NewProjectNamespace(projectIDOrName interface{}, isPublic bool) Namespace {
return &projectNamespace{projectIDOrName: projectIDOrName, isPublic: isPublic}
}

View File

@ -0,0 +1,45 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ram
import (
"testing"
"github.com/stretchr/testify/suite"
)
type ProjectNamespaceTestSuite struct {
suite.Suite
}
func (suite *ProjectNamespaceTestSuite) TestResource() {
var namespace Namespace
namespace = &projectNamespace{projectIDOrName: int64(1)}
suite.Equal(namespace.Resource(Resource("image")), Resource("/project/1/image"))
}
func (suite *ProjectNamespaceTestSuite) TestIdentity() {
namespace, _ := Resource("/project/1/image").GetNamespace()
suite.Equal(namespace.Identity(), int64(1))
namespace, _ = Resource("/project/library/image").GetNamespace()
suite.Equal(namespace.Identity(), "library")
}
func TestProjectNamespaceTestSuite(t *testing.T) {
suite.Run(t, new(ProjectNamespaceTestSuite))
}

50
src/common/ram/parser.go Normal file
View File

@ -0,0 +1,50 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ram
import (
"errors"
"regexp"
"strconv"
)
var (
namespaceParsers = map[string]namespaceParser{
"project": projectNamespaceParser,
}
)
type namespaceParser func(resource Resource) (Namespace, error)
func projectNamespaceParser(resource Resource) (Namespace, error) {
parserRe := regexp.MustCompile("^/project/([^/]*)/?")
matches := parserRe.FindStringSubmatch(resource.String())
if len(matches) <= 1 {
return nil, errors.New("not support resource")
}
var projectIDOrName interface{}
id, err := strconv.ParseInt(matches[1], 10, 64)
if err == nil {
projectIDOrName = id
} else {
projectIDOrName = matches[1]
}
return &projectNamespace{projectIDOrName: projectIDOrName}, nil
}

View File

@ -0,0 +1,39 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ram
import (
"testing"
"github.com/stretchr/testify/suite"
)
type ProjectParserTestSuite struct {
suite.Suite
}
func (suite *ProjectParserTestSuite) TestParse() {
namespace, err := projectNamespaceParser(Resource("/project/1/image"))
suite.Equal(namespace, &projectNamespace{projectIDOrName: int64(1)})
suite.Nil(err)
namespace, err = projectNamespaceParser(Resource("/fake/1/image"))
suite.Nil(namespace)
suite.Error(err)
}
func TestProjectParserTestSuite(t *testing.T) {
suite.Run(t, new(ProjectParserTestSuite))
}

View File

@ -0,0 +1,33 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package project
import (
"github.com/goharbor/harbor/src/common/ram"
)
// const action variables
const (
ActionAll = ram.Action("*")
ActionPull = ram.Action("pull")
ActionPush = ram.Action("push")
ActionPushPull = ram.Action("push+pull")
)
// const resource variables
const (
ResourceAll = ram.Resource("*")
ResourceImage = ram.Resource("image")
)

View File

@ -0,0 +1,59 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package project
import (
"github.com/goharbor/harbor/src/common/ram"
)
var (
// subresource policies for public project
publicProjectPolicies = []*ram.Policy{
{Resource: ResourceImage, Action: ActionPull},
}
// subresource policies for system admin visitor
systemAdminProjectPolicies = []*ram.Policy{
{Resource: ResourceAll, Action: ActionAll},
}
)
func policiesForPublicProject(namespace ram.Namespace) []*ram.Policy {
policies := []*ram.Policy{}
for _, policy := range publicProjectPolicies {
policies = append(policies, &ram.Policy{
Resource: namespace.Resource(policy.Resource),
Action: policy.Action,
Effect: policy.Effect,
})
}
return policies
}
func policiesForSystemAdmin(namespace ram.Namespace) []*ram.Policy {
policies := []*ram.Policy{}
for _, policy := range systemAdminProjectPolicies {
policies = append(policies, &ram.Policy{
Resource: namespace.Resource(policy.Resource),
Action: policy.Action,
Effect: policy.Effect,
})
}
return policies
}

View File

@ -0,0 +1,82 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package project
import (
"github.com/goharbor/harbor/src/common/ram"
)
// visitorContext the context interface for the project visitor
type visitorContext interface {
IsAuthenticated() bool
// GetUsername returns the username of user related to the context
GetUsername() string
// IsSysAdmin returns whether the user is system admin
IsSysAdmin() bool
}
// visitor implement the ram.User interface for project visitor
type visitor struct {
ctx visitorContext
namespace ram.Namespace
projectRoles []int
}
// GetUserName returns username of the visitor
func (v *visitor) GetUserName() string {
// anonymous username for unauthenticated Visitor
if !v.ctx.IsAuthenticated() {
return "anonymous"
}
return v.ctx.GetUsername()
}
// GetPolicies returns policies of the visitor
func (v *visitor) GetPolicies() []*ram.Policy {
if v.ctx.IsSysAdmin() {
return policiesForSystemAdmin(v.namespace)
}
if v.namespace.IsPublic() {
return policiesForPublicProject(v.namespace)
}
return nil
}
// GetRoles returns roles of the visitor
func (v *visitor) GetRoles() []ram.Role {
if !v.ctx.IsAuthenticated() {
return nil
}
roles := []ram.Role{}
for _, roleID := range v.projectRoles {
roles = append(roles, &visitorRole{roleID: roleID, namespace: v.namespace})
}
return roles
}
// NewUser returns ram.User interface for the project visitor
func NewUser(ctx visitorContext, namespace ram.Namespace, projectRoles ...int) ram.User {
return &visitor{
ctx: ctx,
namespace: namespace,
projectRoles: projectRoles,
}
}

View File

@ -0,0 +1,79 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package project
import (
"github.com/goharbor/harbor/src/common"
"github.com/goharbor/harbor/src/common/ram"
)
var (
rolePoliciesMap = map[string][]*ram.Policy{
"projectAdmin": {
{Resource: ResourceImage, Action: ActionPushPull}, // compatible with security all perm of project
{Resource: ResourceImage, Action: ActionPush},
{Resource: ResourceImage, Action: ActionPull},
},
"developer": {
{Resource: ResourceImage, Action: ActionPush},
{Resource: ResourceImage, Action: ActionPull},
},
"guest": {
{Resource: ResourceImage, Action: ActionPull},
},
}
)
// visitorRole implement the ram.Role interface
type visitorRole struct {
namespace ram.Namespace
roleID int
}
// GetRoleName returns role name for the visitor role
func (role *visitorRole) GetRoleName() string {
switch role.roleID {
case common.RoleProjectAdmin:
return "projectAdmin"
case common.RoleDeveloper:
return "developer"
case common.RoleGuest:
return "guest"
default:
return ""
}
}
// GetPolicies returns policies for the visitor role
func (role *visitorRole) GetPolicies() []*ram.Policy {
policies := []*ram.Policy{}
roleName := role.GetRoleName()
if roleName == "" {
return policies
}
for _, policy := range rolePoliciesMap[roleName] {
policies = append(policies, &ram.Policy{
Resource: role.namespace.Resource(policy.Resource),
Action: policy.Action,
Effect: policy.Effect,
})
}
return policies
}

View File

@ -0,0 +1,44 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package project
import (
"testing"
"github.com/goharbor/harbor/src/common"
"github.com/stretchr/testify/suite"
)
type VisitorRoleTestSuite struct {
suite.Suite
}
func (suite *VisitorRoleTestSuite) TestGetRoleName() {
projectAdmin := visitorRole{roleID: common.RoleProjectAdmin}
suite.Equal(projectAdmin.GetRoleName(), "projectAdmin")
developer := visitorRole{roleID: common.RoleDeveloper}
suite.Equal(developer.GetRoleName(), "developer")
guest := visitorRole{roleID: common.RoleGuest}
suite.Equal(guest.GetRoleName(), "guest")
unknow := visitorRole{roleID: 404}
suite.Equal(unknow.GetRoleName(), "")
}
func TestVisitorRoleTestSuite(t *testing.T) {
suite.Run(t, new(VisitorRoleTestSuite))
}

View File

@ -0,0 +1,93 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package project
import (
"testing"
"github.com/goharbor/harbor/src/common"
"github.com/goharbor/harbor/src/common/ram"
"github.com/stretchr/testify/suite"
)
type fakeVisitorContext struct {
username string
isSysAdmin bool
}
func (ctx *fakeVisitorContext) IsAuthenticated() bool {
return ctx.username != ""
}
func (ctx *fakeVisitorContext) GetUsername() string {
return ctx.username
}
func (ctx *fakeVisitorContext) IsSysAdmin() bool {
return ctx.IsAuthenticated() && ctx.isSysAdmin
}
var (
anonymousCtx = &fakeVisitorContext{}
authenticatedCtx = &fakeVisitorContext{username: "user"}
sysAdminCtx = &fakeVisitorContext{username: "admin", isSysAdmin: true}
)
type VisitorTestSuite struct {
suite.Suite
}
func (suite *VisitorTestSuite) TestGetPolicies() {
namespace := ram.NewProjectNamespace("library", false)
publicNamespace := ram.NewProjectNamespace("library", true)
anonymous := NewUser(anonymousCtx, namespace)
suite.Nil(anonymous.GetPolicies())
anonymousForPublicProject := NewUser(anonymousCtx, publicNamespace)
suite.Equal(anonymousForPublicProject.GetPolicies(), policiesForPublicProject(publicNamespace))
authenticated := NewUser(authenticatedCtx, namespace)
suite.Nil(authenticated.GetPolicies())
authenticatedForPublicProject := NewUser(authenticatedCtx, publicNamespace)
suite.Equal(authenticatedForPublicProject.GetPolicies(), policiesForPublicProject(publicNamespace))
systemAdmin := NewUser(sysAdminCtx, namespace)
suite.Equal(systemAdmin.GetPolicies(), policiesForSystemAdmin(namespace))
systemAdminForPublicProject := NewUser(sysAdminCtx, publicNamespace)
suite.Equal(systemAdminForPublicProject.GetPolicies(), policiesForSystemAdmin(publicNamespace))
}
func (suite *VisitorTestSuite) TestGetRoles() {
namespace := ram.NewProjectNamespace("library", false)
anonymous := NewUser(anonymousCtx, namespace)
suite.Nil(anonymous.GetRoles())
authenticated := NewUser(authenticatedCtx, namespace)
suite.Empty(authenticated.GetRoles())
authenticated = NewUser(authenticatedCtx, namespace, common.RoleProjectAdmin)
suite.Len(authenticated.GetRoles(), 1)
authenticated = NewUser(authenticatedCtx, namespace, common.RoleProjectAdmin, common.RoleDeveloper)
suite.Len(authenticated.GetRoles(), 2)
}
func TestVisitorTestSuite(t *testing.T) {
suite.Run(t, new(VisitorTestSuite))
}

View File

@ -15,6 +15,7 @@
package ram
import (
"fmt"
"path"
)
@ -43,6 +44,18 @@ func (res Resource) Subresource(resources ...Resource) Resource {
return Resource(path.Join(elements...))
}
// GetNamespace returns namespace from resource
func (res Resource) GetNamespace() (Namespace, error) {
for _, parser := range namespaceParsers {
namespace, err := parser(res)
if err == nil {
return namespace, nil
}
}
return nil, fmt.Errorf("no namespace found for %s", res)
}
// Action the type of action
type Action string

View File

@ -15,6 +15,7 @@
package ram
import (
"reflect"
"testing"
)
@ -355,3 +356,37 @@ func TestResource_Subresource(t *testing.T) {
})
}
}
func TestResource_GetNamespace(t *testing.T) {
tests := []struct {
name string
res Resource
want Namespace
wantErr bool
}{
{
name: "project namespace",
res: Resource("/project/1"),
want: &projectNamespace{int64(1), false},
wantErr: false,
},
{
name: "unknow namespace",
res: Resource("/unknow/1"),
want: nil,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := tt.res.GetNamespace()
if (err != nil) != tt.wantErr {
t.Errorf("Resource.GetNamespace() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Resource.GetNamespace() = %v, want %v", got, tt.want)
}
})
}
}

View File

@ -15,10 +15,10 @@
package admiral
import (
"github.com/goharbor/harbor/src/common"
"github.com/goharbor/harbor/src/common/models"
"github.com/goharbor/harbor/src/common/ram"
"github.com/goharbor/harbor/src/common/ram/project"
"github.com/goharbor/harbor/src/common/security/admiral/authcontext"
"github.com/goharbor/harbor/src/common/utils/log"
"github.com/goharbor/harbor/src/core/promgr"
)
@ -71,70 +71,33 @@ func (s *SecurityContext) IsSolutionUser() bool {
// HasReadPerm returns whether the user has read permission to the project
func (s *SecurityContext) HasReadPerm(projectIDOrName interface{}) bool {
public, err := s.pm.IsPublic(projectIDOrName)
if err != nil {
log.Errorf("failed to check the public of project %v: %v",
projectIDOrName, err)
return false
}
if public {
return true
}
// private project
if !s.IsAuthenticated() {
return false
}
// system admin
if s.IsSysAdmin() {
return true
}
roles := s.GetProjectRoles(projectIDOrName)
return len(roles) > 0
isPublicProject, _ := s.pm.IsPublic(projectIDOrName)
return s.Can(project.ActionPull, ram.NewProjectNamespace(projectIDOrName, isPublicProject).Resource(project.ResourceImage))
}
// HasWritePerm returns whether the user has write permission to the project
func (s *SecurityContext) HasWritePerm(projectIDOrName interface{}) bool {
if !s.IsAuthenticated() {
return false
}
// system admin
if s.IsSysAdmin() {
return true
}
roles := s.GetProjectRoles(projectIDOrName)
for _, role := range roles {
switch role {
case common.RoleProjectAdmin,
common.RoleDeveloper:
return true
}
}
return false
isPublicProject, _ := s.pm.IsPublic(projectIDOrName)
return s.Can(project.ActionPush, ram.NewProjectNamespace(projectIDOrName, isPublicProject).Resource(project.ResourceImage))
}
// HasAllPerm returns whether the user has all permissions to the project
func (s *SecurityContext) HasAllPerm(projectIDOrName interface{}) bool {
if !s.IsAuthenticated() {
return false
}
isPublicProject, _ := s.pm.IsPublic(projectIDOrName)
return s.Can(project.ActionPushPull, ram.NewProjectNamespace(projectIDOrName, isPublicProject).Resource(project.ResourceImage))
}
// system admin
if s.IsSysAdmin() {
return true
}
roles := s.GetProjectRoles(projectIDOrName)
for _, role := range roles {
switch role {
case common.RoleProjectAdmin:
return true
// Can returns whether the user can do action on resource
func (s *SecurityContext) Can(action ram.Action, resource ram.Resource) bool {
ns, err := resource.GetNamespace()
if err == nil {
switch ns.Kind() {
case "project":
projectIDOrName := ns.Identity()
isPublicProject, _ := s.pm.IsPublic(projectIDOrName)
projectNamespace := ram.NewProjectNamespace(projectIDOrName, isPublicProject)
user := project.NewUser(s, projectNamespace, s.GetProjectRoles(projectIDOrName)...)
return ram.HasPermission(user, resource, action)
}
}

View File

@ -19,6 +19,8 @@ import (
"github.com/goharbor/harbor/src/common/dao"
"github.com/goharbor/harbor/src/common/dao/group"
"github.com/goharbor/harbor/src/common/models"
"github.com/goharbor/harbor/src/common/ram"
"github.com/goharbor/harbor/src/common/ram/project"
"github.com/goharbor/harbor/src/common/utils/log"
"github.com/goharbor/harbor/src/core/promgr"
)
@ -67,67 +69,36 @@ func (s *SecurityContext) IsSolutionUser() bool {
// HasReadPerm returns whether the user has read permission to the project
func (s *SecurityContext) HasReadPerm(projectIDOrName interface{}) bool {
// public project
public, err := s.pm.IsPublic(projectIDOrName)
if err != nil {
log.Errorf("failed to check the public of project %v: %v",
projectIDOrName, err)
return false
}
if public {
return true
}
// private project
if !s.IsAuthenticated() {
return false
}
// system admin
if s.IsSysAdmin() {
return true
}
roles := s.GetProjectRoles(projectIDOrName)
return len(roles) > 0
isPublicProject, _ := s.pm.IsPublic(projectIDOrName)
return s.Can(project.ActionPull, ram.NewProjectNamespace(projectIDOrName, isPublicProject).Resource(project.ResourceImage))
}
// HasWritePerm returns whether the user has write permission to the project
func (s *SecurityContext) HasWritePerm(projectIDOrName interface{}) bool {
if !s.IsAuthenticated() {
return false
}
// system admin
if s.IsSysAdmin() {
return true
}
roles := s.GetProjectRoles(projectIDOrName)
for _, role := range roles {
switch role {
case common.RoleProjectAdmin,
common.RoleDeveloper:
return true
}
}
return false
isPublicProject, _ := s.pm.IsPublic(projectIDOrName)
return s.Can(project.ActionPush, ram.NewProjectNamespace(projectIDOrName, isPublicProject).Resource(project.ResourceImage))
}
// HasAllPerm returns whether the user has all permissions to the project
func (s *SecurityContext) HasAllPerm(projectIDOrName interface{}) bool {
if !s.IsAuthenticated() {
return false
}
// system admin
if s.IsSysAdmin() {
return true
}
roles := s.GetProjectRoles(projectIDOrName)
for _, role := range roles {
switch role {
case common.RoleProjectAdmin:
return true
isPublicProject, _ := s.pm.IsPublic(projectIDOrName)
return s.Can(project.ActionPushPull, ram.NewProjectNamespace(projectIDOrName, isPublicProject).Resource(project.ResourceImage))
}
// Can returns whether the user can do action on resource
func (s *SecurityContext) Can(action ram.Action, resource ram.Resource) bool {
ns, err := resource.GetNamespace()
if err == nil {
switch ns.Kind() {
case "project":
projectIDOrName := ns.Identity()
isPublicProject, _ := s.pm.IsPublic(projectIDOrName)
projectNamespace := ram.NewProjectNamespace(projectIDOrName, isPublicProject)
user := project.NewUser(s, projectNamespace, s.GetProjectRoles(projectIDOrName)...)
return ram.HasPermission(user, resource, action)
}
}
return false
}

View File

@ -19,6 +19,7 @@ import (
"github.com/goharbor/harbor/src/common"
"github.com/goharbor/harbor/src/common/models"
"github.com/goharbor/harbor/src/common/ram"
"github.com/goharbor/harbor/src/common/secret"
"github.com/goharbor/harbor/src/common/utils/log"
)
@ -97,6 +98,14 @@ func (s *SecurityContext) HasAllPerm(projectIDOrName interface{}) bool {
return s.store.GetUsername(s.secret) == secret.JobserviceUser || s.store.GetUsername(s.secret) == secret.CoreUser
}
// Can returns whether the user can do action on resource
func (s *SecurityContext) Can(action ram.Action, resource ram.Resource) bool {
if s.store == nil {
return false
}
return s.store.GetUsername(s.secret) == secret.JobserviceUser || s.store.GetUsername(s.secret) == secret.CoreUser
}
// GetMyProjects ...
func (s *SecurityContext) GetMyProjects() ([]*models.Project, error) {
return nil, fmt.Errorf("GetMyProjects is unsupported")