mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-23 09:08:26 +01:00
Add interfaces to implement project level policy (#3271)
* add interfaces to implement project level policy
This commit is contained in:
parent
0982dff6ed
commit
e79334a445
39
src/common/models/pro_meta.go
Normal file
39
src/common/models/pro_meta.go
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
|
||||
//
|
||||
// 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 models
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// keys of project metadata
|
||||
const (
|
||||
ProMetaPublic = "public"
|
||||
ProMetaEnableContentTrust = "enable_content_trust"
|
||||
ProMetaPreventVul = "prevent_vul"
|
||||
ProMetaSeverity = "severity"
|
||||
ProMetaAutoScan = "auto_scan"
|
||||
)
|
||||
|
||||
// ProjectMetadata holds the metadata of a project.
|
||||
type ProjectMetadata struct {
|
||||
ID int64 `orm:"pk;auto;column(id)" json:"id"`
|
||||
ProjectID int64 `orm:"column(project_id)" json:"project_id"`
|
||||
Name string `orm:"column(name)" json:"name"`
|
||||
Value string `orm:"column(value)" json:"value"`
|
||||
CreationTime time.Time `orm:"column(creation_time)" json:"creation_time"`
|
||||
UpdateTime time.Time `orm:"column(update_time)" json:"update_time"`
|
||||
Deleted int `orm:"column(deleted)" json:"deleted"`
|
||||
}
|
@ -21,24 +21,25 @@ import (
|
||||
// Project holds the details of a project.
|
||||
// TODO remove useless attrs
|
||||
type Project struct {
|
||||
ProjectID int64 `orm:"pk;auto;column(project_id)" json:"project_id"`
|
||||
OwnerID int `orm:"column(owner_id)" json:"owner_id"`
|
||||
Name string `orm:"column(name)" json:"name"`
|
||||
CreationTime time.Time `orm:"column(creation_time)" json:"creation_time"`
|
||||
CreationTimeStr string `orm:"-" json:"creation_time_str"`
|
||||
Deleted int `orm:"column(deleted)" json:"deleted"`
|
||||
//UserID int `json:"UserId"`
|
||||
OwnerName string `orm:"-" json:"owner_name"`
|
||||
Public int `orm:"column(public)" json:"public"`
|
||||
//This field does not have correspondent column in DB, this is just for UI to disable button
|
||||
Togglable bool `orm:"-"`
|
||||
UpdateTime time.Time `orm:"update_time" json:"update_time"`
|
||||
Role int `orm:"-" json:"current_user_role_id"`
|
||||
RepoCount int `orm:"-" json:"repo_count"`
|
||||
EnableContentTrust bool `orm:"-" json:"enable_content_trust"`
|
||||
PreventVulnerableImagesFromRunning bool `orm:"-" json:"prevent_vulnerable_images_from_running"`
|
||||
PreventVulnerableImagesFromRunningSeverity string `orm:"-" json:"prevent_vulnerable_images_from_running_severity"`
|
||||
AutomaticallyScanImagesOnPush bool `orm:"-" json:"automatically_scan_images_on_push"`
|
||||
ProjectID int64 `orm:"pk;auto;column(project_id)" json:"project_id"`
|
||||
OwnerID int `orm:"column(owner_id)" json:"owner_id"`
|
||||
Name string `orm:"column(name)" json:"name"`
|
||||
CreationTime time.Time `orm:"column(creation_time)" json:"creation_time"`
|
||||
UpdateTime time.Time `orm:"update_time" json:"update_time"`
|
||||
Deleted int `orm:"column(deleted)" json:"deleted"`
|
||||
CreationTimeStr string `orm:"-" json:"creation_time_str"`
|
||||
OwnerName string `orm:"-" json:"owner_name"`
|
||||
Togglable bool `orm:"-"`
|
||||
Role int `orm:"-" json:"current_user_role_id"`
|
||||
RepoCount int `orm:"-" json:"repo_count"`
|
||||
Metadata map[string]interface{} `orm:"-" json:"metadata"`
|
||||
|
||||
// TODO remove
|
||||
Public int `orm:"column(public)" json:"public"`
|
||||
EnableContentTrust bool `orm:"-" json:"enable_content_trust"`
|
||||
PreventVulnerableImagesFromRunning bool `orm:"-" json:"prevent_vulnerable_images_from_running"`
|
||||
PreventVulnerableImagesFromRunningSeverity string `orm:"-" json:"prevent_vulnerable_images_from_running_severity"`
|
||||
AutomaticallyScanImagesOnPush bool `orm:"-" json:"automatically_scan_images_on_push"`
|
||||
}
|
||||
|
||||
// ProjectSorter holds an array of projects
|
||||
@ -109,3 +110,9 @@ type ProjectRequest struct {
|
||||
PreventVulnerableImagesFromRunningSeverity string `json:"prevent_vulnerable_images_from_running_severity"`
|
||||
AutomaticallyScanImagesOnPush bool `json:"automatically_scan_images_on_push"`
|
||||
}
|
||||
|
||||
// ProjectQueryResult ...
|
||||
type ProjectQueryResult struct {
|
||||
Total int64
|
||||
Projects []*Project
|
||||
}
|
||||
|
@ -26,11 +26,11 @@ import (
|
||||
// auth context and project manager
|
||||
type SecurityContext struct {
|
||||
ctx *authcontext.AuthContext
|
||||
pm promgr.ProMgr
|
||||
pm promgr.ProjectManager
|
||||
}
|
||||
|
||||
// NewSecurityContext ...
|
||||
func NewSecurityContext(ctx *authcontext.AuthContext, pm promgr.ProMgr) *SecurityContext {
|
||||
func NewSecurityContext(ctx *authcontext.AuthContext, pm promgr.ProjectManager) *SecurityContext {
|
||||
return &SecurityContext{
|
||||
ctx: ctx,
|
||||
pm: pm,
|
||||
|
@ -25,11 +25,11 @@ import (
|
||||
// SecurityContext implements security.Context interface based on database
|
||||
type SecurityContext struct {
|
||||
user *models.User
|
||||
pm promgr.ProMgr
|
||||
pm promgr.ProjectManager
|
||||
}
|
||||
|
||||
// NewSecurityContext ...
|
||||
func NewSecurityContext(user *models.User, pm promgr.ProMgr) *SecurityContext {
|
||||
func NewSecurityContext(user *models.User, pm promgr.ProjectManager) *SecurityContext {
|
||||
return &SecurityContext{
|
||||
user: user,
|
||||
pm: pm,
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
"github.com/vmware/harbor/src/common/dao"
|
||||
"github.com/vmware/harbor/src/common/models"
|
||||
"github.com/vmware/harbor/src/common/utils/log"
|
||||
"github.com/vmware/harbor/src/ui/promgr"
|
||||
"github.com/vmware/harbor/src/ui/promgr/pmsdriver/local"
|
||||
)
|
||||
|
||||
@ -47,7 +48,7 @@ var (
|
||||
Email: "guestUser@vmware.com",
|
||||
}
|
||||
|
||||
pm = &local.ProjectManager{}
|
||||
pm = promgr.NewDefaultProjectManager(local.NewDriver(), true)
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
@ -159,19 +159,10 @@ func ParseProjectIDOrName(value interface{}) (int64, string, error) {
|
||||
case int:
|
||||
i := value.(int)
|
||||
id = int64(i)
|
||||
if id == 0 {
|
||||
return 0, "", fmt.Errorf("invalid ID: 0")
|
||||
}
|
||||
case int64:
|
||||
id = value.(int64)
|
||||
if id == 0 {
|
||||
return 0, "", fmt.Errorf("invalid ID: 0")
|
||||
}
|
||||
case string:
|
||||
name = value.(string)
|
||||
if len(name) == 0 {
|
||||
return 0, "", fmt.Errorf("empty name")
|
||||
}
|
||||
default:
|
||||
return 0, "", fmt.Errorf("unsupported type")
|
||||
}
|
||||
|
@ -217,14 +217,6 @@ func TestParseHarborIDOrName(t *testing.T) {
|
||||
id, name, err := ParseProjectIDOrName(nil)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
// invalid ID
|
||||
id, name, err = ParseProjectIDOrName(0)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
// invalid name
|
||||
id, name, err = ParseProjectIDOrName("")
|
||||
assert.NotNil(t, err)
|
||||
|
||||
// valid int ID
|
||||
id, name, err = ParseProjectIDOrName(1)
|
||||
assert.Nil(t, err)
|
||||
|
@ -31,7 +31,7 @@ type BaseController struct {
|
||||
SecurityCtx security.Context
|
||||
// ProjectMgr is the project manager which abstracts the operations
|
||||
// related to projects
|
||||
ProjectMgr promgr.ProMgr
|
||||
ProjectMgr promgr.ProjectManager
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -109,7 +109,7 @@ func (p *ProjectAPI) Post() {
|
||||
return
|
||||
}
|
||||
|
||||
exist, err := p.ProjectMgr.Exist(pro.Name)
|
||||
exist, err := p.ProjectMgr.Exists(pro.Name)
|
||||
if err != nil {
|
||||
p.ParseAndHandleError(fmt.Sprintf("failed to check the existence of project %s",
|
||||
pro.Name), err)
|
||||
@ -325,19 +325,13 @@ func (p *ProjectAPI) List() {
|
||||
}
|
||||
}
|
||||
|
||||
total, err := p.ProjectMgr.GetTotal(query, base)
|
||||
result, err := p.ProjectMgr.List(query, base)
|
||||
if err != nil {
|
||||
p.ParseAndHandleError("failed to get total of projects", err)
|
||||
p.ParseAndHandleError("failed to list projects", err)
|
||||
return
|
||||
}
|
||||
|
||||
projects, err := p.ProjectMgr.GetAll(query, base)
|
||||
if err != nil {
|
||||
p.ParseAndHandleError("failed to get projects", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, project := range projects {
|
||||
for _, project := range result.Projects {
|
||||
if p.SecurityCtx.IsAuthenticated() {
|
||||
roles := p.SecurityCtx.GetProjectRoles(project.ProjectID)
|
||||
if len(roles) != 0 {
|
||||
@ -359,8 +353,8 @@ func (p *ProjectAPI) List() {
|
||||
project.RepoCount = len(repos)
|
||||
}
|
||||
|
||||
p.SetPaginationHeader(total, page, size)
|
||||
p.Data["json"] = projects
|
||||
p.SetPaginationHeader(result.Total, page, size)
|
||||
p.Data["json"] = result.Projects
|
||||
p.ServeJSON()
|
||||
}
|
||||
|
||||
@ -385,7 +379,9 @@ func (p *ProjectAPI) ToggleProjectPublic() {
|
||||
|
||||
if err := p.ProjectMgr.Update(p.project.ProjectID,
|
||||
&models.Project{
|
||||
Public: req.Public,
|
||||
Metadata: map[string]interface{}{
|
||||
models.ProMetaPublic: req.Public,
|
||||
},
|
||||
}); err != nil {
|
||||
p.ParseAndHandleError(fmt.Sprintf("failed to update project %d",
|
||||
p.project.ProjectID), err)
|
||||
|
@ -84,7 +84,7 @@ func (ra *RepositoryAPI) Get() {
|
||||
return
|
||||
}
|
||||
|
||||
exist, err := ra.ProjectMgr.Exist(projectID)
|
||||
exist, err := ra.ProjectMgr.Exists(projectID)
|
||||
if err != nil {
|
||||
ra.ParseAndHandleError(fmt.Sprintf("failed to check the existence of project %d",
|
||||
projectID), err)
|
||||
@ -335,7 +335,7 @@ func (ra *RepositoryAPI) GetTags() {
|
||||
repoName := ra.GetString(":splat")
|
||||
|
||||
projectName, _ := utils.ParseRepository(repoName)
|
||||
exist, err := ra.ProjectMgr.Exist(projectName)
|
||||
exist, err := ra.ProjectMgr.Exists(projectName)
|
||||
if err != nil {
|
||||
ra.ParseAndHandleError(fmt.Sprintf("failed to check the existence of project %s",
|
||||
projectName), err)
|
||||
@ -478,7 +478,7 @@ func (ra *RepositoryAPI) GetManifests() {
|
||||
}
|
||||
|
||||
projectName, _ := utils.ParseRepository(repoName)
|
||||
exist, err := ra.ProjectMgr.Exist(projectName)
|
||||
exist, err := ra.ProjectMgr.Exists(projectName)
|
||||
if err != nil {
|
||||
ra.ParseAndHandleError(fmt.Sprintf("failed to check the existence of project %s",
|
||||
projectName), err)
|
||||
@ -610,7 +610,7 @@ func (ra *RepositoryAPI) GetSignatures() {
|
||||
repoName := ra.GetString(":splat")
|
||||
|
||||
projectName, _ := utils.ParseRepository(repoName)
|
||||
exist, err := ra.ProjectMgr.Exist(projectName)
|
||||
exist, err := ra.ProjectMgr.Exists(projectName)
|
||||
if err != nil {
|
||||
ra.ParseAndHandleError(fmt.Sprintf("failed to check the existence of project %s",
|
||||
projectName), err)
|
||||
@ -651,7 +651,7 @@ func (ra *RepositoryAPI) ScanImage() {
|
||||
repoName := ra.GetString(":splat")
|
||||
tag := ra.GetString(":tag")
|
||||
projectName, _ := utils.ParseRepository(repoName)
|
||||
exist, err := ra.ProjectMgr.Exist(projectName)
|
||||
exist, err := ra.ProjectMgr.Exists(projectName)
|
||||
if err != nil {
|
||||
ra.ParseAndHandleError(fmt.Sprintf("failed to check the existence of project %s",
|
||||
projectName), err)
|
||||
@ -794,7 +794,7 @@ func getSignatures(username, repository string) (map[string][]notary.Target, err
|
||||
|
||||
func (ra *RepositoryAPI) checkExistence(repository, tag string) (bool, string, error) {
|
||||
project, _ := utils.ParseRepository(repository)
|
||||
exist, err := ra.ProjectMgr.Exist(project)
|
||||
exist, err := ra.ProjectMgr.Exists(project)
|
||||
if err != nil {
|
||||
return false, "", err
|
||||
}
|
||||
|
@ -48,11 +48,12 @@ func (s *SearchAPI) Get() {
|
||||
var err error
|
||||
|
||||
if isSysAdmin {
|
||||
projects, err = s.ProjectMgr.GetAll(nil)
|
||||
result, err := s.ProjectMgr.List(nil)
|
||||
if err != nil {
|
||||
s.ParseAndHandleError("failed to get projects", err)
|
||||
return
|
||||
}
|
||||
projects = result.Projects
|
||||
} else {
|
||||
projects, err = s.ProjectMgr.GetPublic()
|
||||
if err != nil {
|
||||
|
@ -77,15 +77,15 @@ func (s *StatisticAPI) Get() {
|
||||
statistic[PubRC] = n
|
||||
|
||||
if s.SecurityCtx.IsSysAdmin() {
|
||||
n, err := s.ProjectMgr.GetTotal(nil)
|
||||
result, err := s.ProjectMgr.List(nil)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get total of projects: %v", err)
|
||||
s.CustomAbort(http.StatusInternalServerError, "")
|
||||
}
|
||||
statistic[TPC] = n
|
||||
statistic[PriPC] = n - statistic[PubPC]
|
||||
statistic[TPC] = result.Total
|
||||
statistic[PriPC] = result.Total - statistic[PubPC]
|
||||
|
||||
n, err = dao.GetTotalOfRepositories("")
|
||||
n, err := dao.GetTotalOfRepositories("")
|
||||
if err != nil {
|
||||
log.Errorf("failed to get total of repositories: %v", err)
|
||||
s.CustomAbort(http.StatusInternalServerError, "")
|
||||
@ -94,7 +94,7 @@ func (s *StatisticAPI) Get() {
|
||||
statistic[PriRC] = n - statistic[PubRC]
|
||||
} else {
|
||||
value := false
|
||||
projects, err := s.ProjectMgr.GetAll(&models.ProjectQueryParam{
|
||||
result, err := s.ProjectMgr.List(&models.ProjectQueryParam{
|
||||
Public: &value,
|
||||
Member: &models.MemberQuery{
|
||||
Name: s.username,
|
||||
@ -106,10 +106,10 @@ func (s *StatisticAPI) Get() {
|
||||
return
|
||||
}
|
||||
|
||||
statistic[PriPC] = (int64)(len(projects))
|
||||
statistic[PriPC] = result.Total
|
||||
|
||||
ids := []int64{}
|
||||
for _, p := range projects {
|
||||
for _, p := range result.Projects {
|
||||
ids = append(ids, p.ProjectID)
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,7 @@ func postReplicationAction(policyID int64, acton string) error {
|
||||
}
|
||||
|
||||
// SyncRegistry syncs the repositories of registry with database.
|
||||
func SyncRegistry(pm promgr.ProMgr) error {
|
||||
func SyncRegistry(pm promgr.ProjectManager) error {
|
||||
|
||||
log.Infof("Start syncing repositories from registry to DB... ")
|
||||
|
||||
@ -254,7 +254,7 @@ func catalog() ([]string, error) {
|
||||
}
|
||||
|
||||
func diffRepos(reposInRegistry []string, reposInDB []string,
|
||||
pm promgr.ProMgr) ([]string, []string, error) {
|
||||
pm promgr.ProjectManager) ([]string, []string, error) {
|
||||
var needsAdd []string
|
||||
var needsDel []string
|
||||
|
||||
@ -359,9 +359,9 @@ func diffRepos(reposInRegistry []string, reposInDB []string,
|
||||
return needsAdd, needsDel, nil
|
||||
}
|
||||
|
||||
func projectExists(pm promgr.ProMgr, repository string) (bool, error) {
|
||||
func projectExists(pm promgr.ProjectManager, repository string) (bool, error) {
|
||||
project, _ := utils.ParseRepository(repository)
|
||||
return pm.Exist(project)
|
||||
return pm.Exists(project)
|
||||
}
|
||||
|
||||
func initRegistryClient() (r *registry.Registry, err error) {
|
||||
|
@ -15,7 +15,7 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
//"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
@ -30,6 +30,7 @@ import (
|
||||
"github.com/vmware/harbor/src/common/secret"
|
||||
"github.com/vmware/harbor/src/common/utils/log"
|
||||
"github.com/vmware/harbor/src/ui/promgr"
|
||||
"github.com/vmware/harbor/src/ui/promgr/pmsdriver"
|
||||
"github.com/vmware/harbor/src/ui/promgr/pmsdriver/admiral"
|
||||
"github.com/vmware/harbor/src/ui/promgr/pmsdriver/local"
|
||||
)
|
||||
@ -46,7 +47,7 @@ var (
|
||||
// AdminserverClient is a client for adminserver
|
||||
AdminserverClient client.Client
|
||||
// GlobalProjectMgr is initialized based on the deploy mode
|
||||
GlobalProjectMgr promgr.ProMgr
|
||||
GlobalProjectMgr promgr.ProjectManager
|
||||
mg *comcfg.Manager
|
||||
keyProvider comcfg.KeyProvider
|
||||
// AdmiralClient is initialized only under integration deploy mode
|
||||
@ -105,34 +106,41 @@ func initSecretStore() {
|
||||
}
|
||||
|
||||
func initProjectManager() {
|
||||
if !WithAdmiral() {
|
||||
var driver pmsdriver.PMSDriver
|
||||
if WithAdmiral() {
|
||||
// TODO add support for admiral
|
||||
/*
|
||||
// integration with admiral
|
||||
log.Info("initializing the project manager based on PMS...")
|
||||
// TODO read ca/cert file and pass it to the TLS config
|
||||
AdmiralClient = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
path := os.Getenv("SERVICE_TOKEN_FILE_PATH")
|
||||
if len(path) == 0 {
|
||||
path = defaultTokenFilePath
|
||||
}
|
||||
log.Infof("service token file path: %s", path)
|
||||
TokenReader = &admiral.FileTokenReader{
|
||||
Path: path,
|
||||
}
|
||||
GlobalProjectMgr = admiral.NewProjectManager(AdmiralClient,
|
||||
AdmiralEndpoint(), TokenReader)
|
||||
*/
|
||||
GlobalProjectMgr = nil
|
||||
} else {
|
||||
// standalone
|
||||
log.Info("initializing the project manager based on database...")
|
||||
GlobalProjectMgr = &local.ProjectManager{}
|
||||
return
|
||||
log.Info("initializing the project manager based on local database...")
|
||||
driver = local.NewDriver()
|
||||
// TODO move the statement out of the else block when admiral driver is completed
|
||||
GlobalProjectMgr = promgr.NewDefaultProjectManager(driver, true)
|
||||
}
|
||||
|
||||
// integration with admiral
|
||||
log.Info("initializing the project manager based on PMS...")
|
||||
// TODO read ca/cert file and pass it to the TLS config
|
||||
AdmiralClient = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
path := os.Getenv("SERVICE_TOKEN_FILE_PATH")
|
||||
if len(path) == 0 {
|
||||
path = defaultTokenFilePath
|
||||
}
|
||||
log.Infof("service token file path: %s", path)
|
||||
TokenReader = &admiral.FileTokenReader{
|
||||
Path: path,
|
||||
}
|
||||
GlobalProjectMgr = admiral.NewProjectManager(AdmiralClient,
|
||||
AdmiralEndpoint(), TokenReader)
|
||||
}
|
||||
|
||||
// Load configurations
|
||||
@ -379,6 +387,7 @@ func AdmiralEndpoint() string {
|
||||
log.Errorf("Failed to get configuration, will return empty string as admiral's endpoint, error: %v", err)
|
||||
return ""
|
||||
}
|
||||
|
||||
if e, ok := cfg[common.AdmiralEndpoint].(string); !ok || e == "NA" {
|
||||
return ""
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ import (
|
||||
"github.com/vmware/harbor/src/ui/auth"
|
||||
"github.com/vmware/harbor/src/ui/config"
|
||||
"github.com/vmware/harbor/src/ui/promgr"
|
||||
"github.com/vmware/harbor/src/ui/promgr/pmsdriver/admiral"
|
||||
//"github.com/vmware/harbor/src/ui/promgr/pmsdriver/admiral"
|
||||
)
|
||||
|
||||
type key string
|
||||
@ -264,11 +264,16 @@ func (t *tokenReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
log.Debug("creating PMS project manager...")
|
||||
pm := admiral.NewProjectManager(config.AdmiralClient,
|
||||
config.AdmiralEndpoint(), &admiral.RawTokenReader{
|
||||
Token: token,
|
||||
})
|
||||
/*
|
||||
log.Debug("creating PMS project manager...")
|
||||
pm := admiral.NewProjectManager(config.AdmiralClient,
|
||||
config.AdmiralEndpoint(), &admiral.RawTokenReader{
|
||||
Token: token,
|
||||
})
|
||||
*/
|
||||
// TODO create the DefaultProjectManager with the real admiral PMSDriver
|
||||
pm := promgr.NewDefaultProjectManager(nil, false)
|
||||
|
||||
log.Debug("creating admiral security context...")
|
||||
securCtx := admr.NewSecurityContext(authContext, pm)
|
||||
setSecurCtxAndPM(ctx.Request, securCtx, pm)
|
||||
@ -283,12 +288,16 @@ func (u *unauthorizedReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
|
||||
log.Debug("user information is nil")
|
||||
|
||||
var securCtx security.Context
|
||||
var pm promgr.ProMgr
|
||||
var pm promgr.ProjectManager
|
||||
if config.WithAdmiral() {
|
||||
// integration with admiral
|
||||
log.Debug("creating PMS project manager...")
|
||||
pm = admiral.NewProjectManager(config.AdmiralClient,
|
||||
config.AdmiralEndpoint(), nil)
|
||||
/*
|
||||
log.Debug("creating PMS project manager...")
|
||||
pm = admiral.NewProjectManager(config.AdmiralClient,
|
||||
config.AdmiralEndpoint(), nil)
|
||||
*/
|
||||
// TODO create the DefaultProjectManager with the real admiral PMSDriver
|
||||
pm = promgr.NewDefaultProjectManager(nil, false)
|
||||
log.Debug("creating admiral security context...")
|
||||
securCtx = admr.NewSecurityContext(nil, pm)
|
||||
} else {
|
||||
@ -302,7 +311,7 @@ func (u *unauthorizedReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func setSecurCtxAndPM(req *http.Request, ctx security.Context, pm promgr.ProMgr) {
|
||||
func setSecurCtxAndPM(req *http.Request, ctx security.Context, pm promgr.ProjectManager) {
|
||||
addToReqContext(req, securCtxKey, ctx)
|
||||
addToReqContext(req, pmKey, pm)
|
||||
}
|
||||
@ -331,7 +340,7 @@ func GetSecurityContext(req *http.Request) (security.Context, error) {
|
||||
}
|
||||
|
||||
// GetProjectManager tries to get project manager from request and returns it
|
||||
func GetProjectManager(req *http.Request) (promgr.ProMgr, error) {
|
||||
func GetProjectManager(req *http.Request) (promgr.ProjectManager, error) {
|
||||
if req == nil {
|
||||
return nil, fmt.Errorf("request is nil")
|
||||
}
|
||||
@ -341,7 +350,7 @@ func GetProjectManager(req *http.Request) (promgr.ProMgr, error) {
|
||||
return nil, fmt.Errorf("the project manager got from request is nil")
|
||||
}
|
||||
|
||||
p, ok := pm.(promgr.ProMgr)
|
||||
p, ok := pm.(promgr.ProjectManager)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("the variable got from request is not project manager type")
|
||||
}
|
||||
|
@ -316,9 +316,9 @@ func TestGetProjectManager(t *testing.T) {
|
||||
req, err = http.NewRequest("", "", nil)
|
||||
assert.Nil(t, err)
|
||||
req = req.WithContext(context.WithValue(req.Context(),
|
||||
pmKey, &driver_local.ProjectManager{}))
|
||||
pmKey, promgr.NewDefaultProjectManager(driver_local.NewDriver(), true)))
|
||||
pm, err = GetProjectManager(req)
|
||||
assert.Nil(t, err)
|
||||
_, ok := pm.(promgr.ProMgr)
|
||||
_, ok := pm.(promgr.ProjectManager)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
|
65
src/ui/promgr/metamgr/metamgr.go
Normal file
65
src/ui/promgr/metamgr/metamgr.go
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
|
||||
//
|
||||
// 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 metamgr
|
||||
|
||||
import (
|
||||
"github.com/vmware/harbor/src/common/dao"
|
||||
"github.com/vmware/harbor/src/common/models"
|
||||
)
|
||||
|
||||
// ProjectMetadataManaegr defines the operations that a project metadata manager should
|
||||
// implement
|
||||
type ProjectMetadataManaegr interface {
|
||||
// Add metadatas for project specified by projectID
|
||||
Add(projectID int64, meta map[string]interface{}) error
|
||||
// Delete metadatas whose keys are specified in parameter meta, if it
|
||||
// is absent, delete all
|
||||
Delete(projecdtID int64, meta ...[]string) error
|
||||
// Update metadatas
|
||||
Update(projectID int64, meta map[string]interface{}) error
|
||||
// Get metadatas whose keys are specified in parameter meta, if it is
|
||||
// absent, get all
|
||||
Get(projectID int64, meta ...[]string) (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
type defaultProjectMetadataManaegr struct{}
|
||||
|
||||
// NewDefaultProjectMetadataManager ...
|
||||
func NewDefaultProjectMetadataManager() ProjectMetadataManaegr {
|
||||
return &defaultProjectMetadataManaegr{}
|
||||
}
|
||||
|
||||
// TODO add implement
|
||||
func (d *defaultProjectMetadataManaegr) Add(projectID int64, meta map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *defaultProjectMetadataManaegr) Delete(projectID int64, meta ...[]string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *defaultProjectMetadataManaegr) Update(projectID int64, meta map[string]interface{}) error {
|
||||
// TODO remove the logic
|
||||
public, ok := meta[models.ProMetaPublic]
|
||||
if ok {
|
||||
return dao.ToggleProjectPublicity(projectID, public.(int))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *defaultProjectMetadataManaegr) Get(projectID int64, meta ...[]string) (map[string]interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
17
src/ui/promgr/metamgr/metamgr_test.go
Normal file
17
src/ui/promgr/metamgr/metamgr_test.go
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
|
||||
//
|
||||
// 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 metamgr
|
||||
|
||||
// TODO add test cases
|
@ -196,7 +196,7 @@ func TestGet(t *testing.T) {
|
||||
|
||||
// get by invalid ID
|
||||
project, err := pm.Get(int64(0))
|
||||
assert.NotNil(t, err)
|
||||
assert.Nil(t, err)
|
||||
assert.Nil(t, project)
|
||||
|
||||
// get by invalid name
|
||||
|
36
src/ui/promgr/pmsdriver/driver.go
Normal file
36
src/ui/promgr/pmsdriver/driver.go
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
|
||||
//
|
||||
// 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 pmsdriver
|
||||
|
||||
import (
|
||||
"github.com/vmware/harbor/src/common/models"
|
||||
)
|
||||
|
||||
// PMSDriver defines the operations that a project management service driver
|
||||
// should implement
|
||||
type PMSDriver interface {
|
||||
// Get a project by ID or name
|
||||
Get(projectIDOrName interface{}) (*models.Project, error)
|
||||
// Create a project
|
||||
Create(*models.Project) (int64, error)
|
||||
// Delete a project by ID or name
|
||||
Delete(projectIDOrName interface{}) error
|
||||
// Update the properties of a project
|
||||
Update(projectIDOrName interface{}, project *models.Project) error
|
||||
// List lists projects according to the query conditions
|
||||
// TODO remove base
|
||||
List(query *models.ProjectQueryParam,
|
||||
base ...*models.BaseProjectCollection) (*models.ProjectQueryResult, error)
|
||||
}
|
@ -21,61 +21,39 @@ import (
|
||||
|
||||
"github.com/vmware/harbor/src/common/dao"
|
||||
"github.com/vmware/harbor/src/common/models"
|
||||
"github.com/vmware/harbor/src/common/utils"
|
||||
errutil "github.com/vmware/harbor/src/common/utils/error"
|
||||
"github.com/vmware/harbor/src/common/utils/log"
|
||||
"github.com/vmware/harbor/src/ui/promgr/pmsdriver"
|
||||
)
|
||||
|
||||
const dupProjectPattern = `Duplicate entry '\w+' for key 'name'`
|
||||
|
||||
// ProjectManager implements pm.PM interface based on database
|
||||
type ProjectManager struct{}
|
||||
type driver struct {
|
||||
}
|
||||
|
||||
// NewDriver returns an instance of driver
|
||||
func NewDriver() pmsdriver.PMSDriver {
|
||||
return &driver{}
|
||||
}
|
||||
|
||||
// Get ...
|
||||
func (p *ProjectManager) Get(projectIDOrName interface{}) (
|
||||
func (d *driver) Get(projectIDOrName interface{}) (
|
||||
*models.Project, error) {
|
||||
switch projectIDOrName.(type) {
|
||||
case string:
|
||||
return dao.GetProjectByName(projectIDOrName.(string))
|
||||
case int64:
|
||||
return dao.GetProjectByID(projectIDOrName.(int64))
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported type of %v, must be string or int64", projectIDOrName)
|
||||
}
|
||||
}
|
||||
|
||||
// Exist ...
|
||||
func (p *ProjectManager) Exist(projectIDOrName interface{}) (bool, error) {
|
||||
project, err := p.Get(projectIDOrName)
|
||||
id, name, err := utils.ParseProjectIDOrName(projectIDOrName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return project != nil, nil
|
||||
}
|
||||
|
||||
// IsPublic returns whether the project is public or not
|
||||
func (p *ProjectManager) IsPublic(projectIDOrName interface{}) (bool, error) {
|
||||
project, err := p.Get(projectIDOrName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if project == nil {
|
||||
return false, nil
|
||||
if id > 0 {
|
||||
return dao.GetProjectByID(id)
|
||||
}
|
||||
|
||||
return project.Public == 1, nil
|
||||
}
|
||||
|
||||
// GetPublic returns all public projects
|
||||
func (p *ProjectManager) GetPublic() ([]*models.Project, error) {
|
||||
t := true
|
||||
return p.GetAll(&models.ProjectQueryParam{
|
||||
Public: &t,
|
||||
})
|
||||
return dao.GetProjectByName(name)
|
||||
}
|
||||
|
||||
// Create ...
|
||||
func (p *ProjectManager) Create(project *models.Project) (int64, error) {
|
||||
func (d *driver) Create(project *models.Project) (int64, error) {
|
||||
if project == nil {
|
||||
return 0, fmt.Errorf("project is nil")
|
||||
}
|
||||
@ -128,10 +106,13 @@ func (p *ProjectManager) Create(project *models.Project) (int64, error) {
|
||||
}
|
||||
|
||||
// Delete ...
|
||||
func (p *ProjectManager) Delete(projectIDOrName interface{}) error {
|
||||
id, ok := projectIDOrName.(int64)
|
||||
if !ok {
|
||||
project, err := p.Get(projectIDOrName)
|
||||
func (d *driver) Delete(projectIDOrName interface{}) error {
|
||||
id, name, err := utils.ParseProjectIDOrName(projectIDOrName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(name) > 0 {
|
||||
project, err := dao.GetProjectByName(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -142,27 +123,31 @@ func (p *ProjectManager) Delete(projectIDOrName interface{}) error {
|
||||
}
|
||||
|
||||
// Update ...
|
||||
func (p *ProjectManager) Update(projectIDOrName interface{},
|
||||
func (d *driver) Update(projectIDOrName interface{},
|
||||
project *models.Project) error {
|
||||
id, ok := projectIDOrName.(int64)
|
||||
if !ok {
|
||||
pro, err := p.Get(projectIDOrName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
id = pro.ProjectID
|
||||
// nil implement
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO remove base
|
||||
// List returns a project list according to the query parameters
|
||||
func (d *driver) List(query *models.ProjectQueryParam,
|
||||
base ...*models.BaseProjectCollection) (
|
||||
*models.ProjectQueryResult, error) {
|
||||
total, err := dao.GetTotalOfProjects(query, base...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dao.ToggleProjectPublicity(id, project.Public)
|
||||
projects, err := dao.GetProjects(query, base...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &models.ProjectQueryResult{
|
||||
Total: total,
|
||||
Projects: projects,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetAll returns a project list according to the query parameters
|
||||
func (p *ProjectManager) GetAll(query *models.ProjectQueryParam, base ...*models.BaseProjectCollection) (
|
||||
[]*models.Project, error) {
|
||||
return dao.GetProjects(query, base...)
|
||||
}
|
||||
|
||||
// GetTotal returns the total count according to the query parameters
|
||||
func (p *ProjectManager) GetTotal(query *models.ProjectQueryParam, base ...*models.BaseProjectCollection) (
|
||||
int64, error) {
|
||||
return dao.GetTotalOfProjects(query, base...)
|
||||
func (d *driver) EnableExternalMetaMgr() bool {
|
||||
return true
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
pm := &ProjectManager{}
|
||||
pm := &driver{}
|
||||
|
||||
// project name
|
||||
project, err := pm.Get("library")
|
||||
@ -95,45 +95,8 @@ func TestGet(t *testing.T) {
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestExist(t *testing.T) {
|
||||
pm := &ProjectManager{}
|
||||
|
||||
// exist project
|
||||
exist, err := pm.Exist("library")
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, exist)
|
||||
|
||||
// non-exist project
|
||||
exist, err = pm.Exist("non-exist-project")
|
||||
assert.Nil(t, err)
|
||||
assert.False(t, exist)
|
||||
}
|
||||
|
||||
func TestIsPublic(t *testing.T) {
|
||||
pms := &ProjectManager{}
|
||||
// public project
|
||||
public, err := pms.IsPublic("library")
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, public)
|
||||
// non exist project
|
||||
public, err = pms.IsPublic("non_exist_project")
|
||||
assert.Nil(t, err)
|
||||
assert.False(t, public)
|
||||
}
|
||||
|
||||
func TestGetPublic(t *testing.T) {
|
||||
pm := &ProjectManager{}
|
||||
projects, err := pm.GetPublic()
|
||||
assert.Nil(t, err)
|
||||
assert.NotEqual(t, 0, len(projects))
|
||||
|
||||
for _, project := range projects {
|
||||
assert.Equal(t, 1, project.Public)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateAndDelete(t *testing.T) {
|
||||
pm := &ProjectManager{}
|
||||
pm := &driver{}
|
||||
|
||||
// nil project
|
||||
_, err := pm.Create(nil)
|
||||
@ -183,63 +146,12 @@ func TestCreateAndDelete(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdate(t *testing.T) {
|
||||
pm := &ProjectManager{}
|
||||
|
||||
id, err := pm.Create(&models.Project{
|
||||
Name: "test",
|
||||
OwnerID: 1,
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
defer pm.Delete(id)
|
||||
|
||||
project, err := pm.Get(id)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 0, project.Public)
|
||||
|
||||
project.Public = 1
|
||||
assert.Nil(t, pm.Update(id, project))
|
||||
|
||||
project, err = pm.Get(id)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 1, project.Public)
|
||||
pm := &driver{}
|
||||
assert.Nil(t, pm.Update(1, nil))
|
||||
}
|
||||
|
||||
func TestGetTotal(t *testing.T) {
|
||||
pm := &ProjectManager{}
|
||||
|
||||
id, err := pm.Create(&models.Project{
|
||||
Name: "get_total_test",
|
||||
OwnerID: 1,
|
||||
Public: 1,
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
defer pm.Delete(id)
|
||||
|
||||
// get by name
|
||||
total, err := pm.GetTotal(&models.ProjectQueryParam{
|
||||
Name: "get_total_test",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, int64(1), total)
|
||||
|
||||
// get by owner
|
||||
total, err = pm.GetTotal(&models.ProjectQueryParam{
|
||||
Owner: "admin",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotEqual(t, 0, total)
|
||||
|
||||
// get by public
|
||||
value := true
|
||||
total, err = pm.GetTotal(&models.ProjectQueryParam{
|
||||
Public: &value,
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotEqual(t, 0, total)
|
||||
}
|
||||
|
||||
func TestGetAll(t *testing.T) {
|
||||
pm := &ProjectManager{}
|
||||
func TestList(t *testing.T) {
|
||||
pm := &driver{}
|
||||
|
||||
id, err := pm.Create(&models.Project{
|
||||
Name: "get_all_test",
|
||||
@ -250,19 +162,19 @@ func TestGetAll(t *testing.T) {
|
||||
defer pm.Delete(id)
|
||||
|
||||
// get by name
|
||||
projects, err := pm.GetAll(&models.ProjectQueryParam{
|
||||
result, err := pm.List(&models.ProjectQueryParam{
|
||||
Name: "get_all_test",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, id, projects[0].ProjectID)
|
||||
assert.Equal(t, id, result.Projects[0].ProjectID)
|
||||
|
||||
// get by owner
|
||||
projects, err = pm.GetAll(&models.ProjectQueryParam{
|
||||
result, err = pm.List(&models.ProjectQueryParam{
|
||||
Owner: "admin",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
exist := false
|
||||
for _, project := range projects {
|
||||
for _, project := range result.Projects {
|
||||
if project.ProjectID == id {
|
||||
exist = true
|
||||
break
|
||||
@ -272,12 +184,12 @@ func TestGetAll(t *testing.T) {
|
||||
|
||||
// get by public
|
||||
value := true
|
||||
projects, err = pm.GetAll(&models.ProjectQueryParam{
|
||||
result, err = pm.List(&models.ProjectQueryParam{
|
||||
Public: &value,
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
exist = false
|
||||
for _, project := range projects {
|
||||
for _, project := range result.Projects {
|
||||
if project.ProjectID == id {
|
||||
exist = true
|
||||
break
|
||||
|
@ -15,22 +15,158 @@
|
||||
package promgr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/vmware/harbor/src/common/models"
|
||||
"github.com/vmware/harbor/src/common/utils/log"
|
||||
"github.com/vmware/harbor/src/ui/promgr/metamgr"
|
||||
"github.com/vmware/harbor/src/ui/promgr/pmsdriver"
|
||||
)
|
||||
|
||||
// ProMgr is the project mamager which abstracts the operations related
|
||||
// ProjectManager is the project mamager which abstracts the operations related
|
||||
// to projects
|
||||
type ProMgr interface {
|
||||
type ProjectManager interface {
|
||||
Get(projectIDOrName interface{}) (*models.Project, error)
|
||||
IsPublic(projectIDOrName interface{}) (bool, error)
|
||||
Exist(projectIDOrName interface{}) (bool, error)
|
||||
// get all public project
|
||||
GetPublic() ([]*models.Project, error)
|
||||
Create(*models.Project) (int64, error)
|
||||
Delete(projectIDOrName interface{}) error
|
||||
Update(projectIDOrName interface{}, project *models.Project) error
|
||||
// GetAll returns a project list according to the query parameters
|
||||
GetAll(query *models.ProjectQueryParam, base ...*models.BaseProjectCollection) ([]*models.Project, error)
|
||||
// GetTotal returns the total count according to the query parameters
|
||||
GetTotal(query *models.ProjectQueryParam, base ...*models.BaseProjectCollection) (int64, error)
|
||||
// TODO remove base
|
||||
List(query *models.ProjectQueryParam,
|
||||
base ...*models.BaseProjectCollection) (*models.ProjectQueryResult, error)
|
||||
IsPublic(projectIDOrName interface{}) (bool, error)
|
||||
Exists(projectIDOrName interface{}) (bool, error)
|
||||
// get all public project
|
||||
GetPublic() ([]*models.Project, error)
|
||||
}
|
||||
|
||||
type defaultProjectManager struct {
|
||||
pmsDriver pmsdriver.PMSDriver
|
||||
metaMgrEnabled bool // if metaMgrEnabled is enabled, metaMgr will be used to CURD metadata
|
||||
metaMgr metamgr.ProjectMetadataManaegr
|
||||
}
|
||||
|
||||
// NewDefaultProjectManager returns an instance of defaultProjectManager,
|
||||
// if metaMgrEnabled is true, a project metadata manager will be created
|
||||
// and used to CURD metadata
|
||||
func NewDefaultProjectManager(driver pmsdriver.PMSDriver, metaMgrEnabled bool) ProjectManager {
|
||||
mgr := &defaultProjectManager{
|
||||
pmsDriver: driver,
|
||||
metaMgrEnabled: metaMgrEnabled,
|
||||
}
|
||||
if metaMgrEnabled {
|
||||
mgr.metaMgr = metamgr.NewDefaultProjectMetadataManager()
|
||||
}
|
||||
return mgr
|
||||
}
|
||||
|
||||
func (d *defaultProjectManager) Get(projectIDOrName interface{}) (*models.Project, error) {
|
||||
project, err := d.pmsDriver.Get(projectIDOrName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if project != nil && d.metaMgrEnabled {
|
||||
meta, err := d.metaMgr.Get(project.ProjectID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(project.Metadata) == 0 {
|
||||
project.Metadata = make(map[string]interface{})
|
||||
}
|
||||
for k, v := range meta {
|
||||
project.Metadata[k] = v
|
||||
}
|
||||
}
|
||||
return project, nil
|
||||
}
|
||||
func (d *defaultProjectManager) Create(project *models.Project) (int64, error) {
|
||||
id, err := d.pmsDriver.Create(project)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(project.Metadata) > 0 && d.metaMgrEnabled {
|
||||
if err = d.metaMgr.Add(id, project.Metadata); err != nil {
|
||||
log.Errorf("failed to add metadata for project %s: %v", project.Name, err)
|
||||
}
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (d *defaultProjectManager) Delete(projectIDOrName interface{}) error {
|
||||
project, err := d.Get(projectIDOrName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if project == nil {
|
||||
return nil
|
||||
}
|
||||
if project.Metadata != nil && d.metaMgrEnabled {
|
||||
if err = d.metaMgr.Delete(project.ProjectID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return d.pmsDriver.Delete(project.ProjectID)
|
||||
}
|
||||
|
||||
func (d *defaultProjectManager) Update(projectIDOrName interface{}, project *models.Project) error {
|
||||
if len(project.Metadata) > 0 && d.metaMgrEnabled {
|
||||
pro, err := d.Get(projectIDOrName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if pro == nil {
|
||||
return fmt.Errorf("project %v not found", projectIDOrName)
|
||||
}
|
||||
if err = d.metaMgr.Update(pro.ProjectID, project.Metadata); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return d.pmsDriver.Update(projectIDOrName, project)
|
||||
}
|
||||
|
||||
// TODO remove base
|
||||
func (d *defaultProjectManager) List(query *models.ProjectQueryParam,
|
||||
base ...*models.BaseProjectCollection) (*models.ProjectQueryResult, error) {
|
||||
result, err := d.pmsDriver.List(query, base...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d.metaMgrEnabled {
|
||||
for _, project := range result.Projects {
|
||||
meta, err := d.metaMgr.Get(project.ProjectID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
project.Metadata = meta
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (d *defaultProjectManager) IsPublic(projectIDOrName interface{}) (bool, error) {
|
||||
project, err := d.Get(projectIDOrName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if project == nil {
|
||||
return false, nil
|
||||
}
|
||||
return project.Public == 1, nil
|
||||
}
|
||||
|
||||
func (d *defaultProjectManager) Exists(projectIDOrName interface{}) (bool, error) {
|
||||
project, err := d.Get(projectIDOrName)
|
||||
return project != nil, err
|
||||
}
|
||||
|
||||
func (d *defaultProjectManager) GetPublic() ([]*models.Project, error) {
|
||||
value := true
|
||||
result, err := d.List(&models.ProjectQueryParam{
|
||||
Public: &value,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.Projects, nil
|
||||
}
|
||||
|
120
src/ui/promgr/promgr_test.go
Normal file
120
src/ui/promgr/promgr_test.go
Normal file
@ -0,0 +1,120 @@
|
||||
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
|
||||
//
|
||||
// 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 promgr
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/vmware/harbor/src/common/models"
|
||||
"github.com/vmware/harbor/src/ui/promgr/pmsdriver"
|
||||
)
|
||||
|
||||
type fakePMSDriver struct {
|
||||
project *models.Project
|
||||
}
|
||||
|
||||
func newFakePMSDriver() pmsdriver.PMSDriver {
|
||||
return &fakePMSDriver{
|
||||
project: &models.Project{
|
||||
ProjectID: 1,
|
||||
Name: "library",
|
||||
Public: 1,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (f *fakePMSDriver) Get(projectIDOrName interface{}) (*models.Project, error) {
|
||||
return f.project, nil
|
||||
}
|
||||
|
||||
func (f *fakePMSDriver) Create(*models.Project) (int64, error) {
|
||||
return 1, nil
|
||||
}
|
||||
|
||||
func (f *fakePMSDriver) Delete(projectIDOrName interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *fakePMSDriver) Update(projectIDOrName interface{}, project *models.Project) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *fakePMSDriver) List(query *models.ProjectQueryParam,
|
||||
base ...*models.BaseProjectCollection) (*models.ProjectQueryResult, error) {
|
||||
return &models.ProjectQueryResult{
|
||||
Total: 1,
|
||||
Projects: []*models.Project{f.project},
|
||||
}, nil
|
||||
}
|
||||
|
||||
var (
|
||||
proMgr = NewDefaultProjectManager(newFakePMSDriver(), false)
|
||||
)
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
project, err := proMgr.Get(1)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, int64(1), project.ProjectID)
|
||||
}
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
id, err := proMgr.Create(&models.Project{
|
||||
Name: "library",
|
||||
OwnerID: 1,
|
||||
})
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, int64(1), id)
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
assert.Nil(t, proMgr.Delete(1))
|
||||
}
|
||||
|
||||
func TestUpdate(t *testing.T) {
|
||||
assert.Nil(t, proMgr.Update(1,
|
||||
&models.Project{
|
||||
Metadata: map[string]interface{}{
|
||||
models.ProMetaPublic: true,
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
result, err := proMgr.List(nil)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, int64(1), result.Total)
|
||||
assert.Equal(t, int64(1), result.Projects[0].ProjectID)
|
||||
}
|
||||
|
||||
func TestIsPublic(t *testing.T) {
|
||||
public, err := proMgr.IsPublic(1)
|
||||
require.Nil(t, err)
|
||||
assert.True(t, public)
|
||||
}
|
||||
|
||||
func TestExist(t *testing.T) {
|
||||
exist, err := proMgr.Exists(1)
|
||||
require.Nil(t, err)
|
||||
assert.True(t, exist)
|
||||
}
|
||||
|
||||
func TestGetPublic(t *testing.T) {
|
||||
projects, err := proMgr.GetPublic()
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 1, len(projects))
|
||||
assert.Equal(t, 1, projects[0].Public)
|
||||
}
|
@ -2,14 +2,14 @@ package proxy
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
//"github.com/stretchr/testify/require"
|
||||
"github.com/vmware/harbor/src/adminserver/client"
|
||||
"github.com/vmware/harbor/src/common"
|
||||
"github.com/vmware/harbor/src/common/models"
|
||||
notarytest "github.com/vmware/harbor/src/common/utils/notary/test"
|
||||
utilstest "github.com/vmware/harbor/src/common/utils/test"
|
||||
"github.com/vmware/harbor/src/ui/config"
|
||||
"github.com/vmware/harbor/src/ui/promgr/pmsdriver/admiral"
|
||||
//"github.com/vmware/harbor/src/ui/promgr/pmsdriver/admiral"
|
||||
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@ -128,6 +128,8 @@ func TestEnvPolicyChecker(t *testing.T) {
|
||||
assert.Equal(sev, models.SevNone)
|
||||
}
|
||||
|
||||
// TODO uncheck after admiral pms driver is implemented
|
||||
/*
|
||||
func TestPMSPolicyChecker(t *testing.T) {
|
||||
var defaultConfigAdmiral = map[string]interface{}{
|
||||
common.ExtEndpoint: "https://" + endpoint,
|
||||
@ -147,7 +149,6 @@ func TestPMSPolicyChecker(t *testing.T) {
|
||||
if err := config.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
pm := admiral.NewProjectManager(http.DefaultClient,
|
||||
admiralEndpoint, &admiral.RawTokenReader{
|
||||
Token: "token",
|
||||
@ -175,7 +176,7 @@ func TestPMSPolicyChecker(t *testing.T) {
|
||||
assert.False(t, projectVulnerableEnabled)
|
||||
assert.Equal(t, projectVulnerableSeverity, models.SevLow)
|
||||
}
|
||||
|
||||
*/
|
||||
func TestMatchNotaryDigest(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
//The data from common/utils/notary/helper_test.go
|
||||
|
@ -88,7 +88,7 @@ func (ec envPolicyChecker) vulnerablePolicy(name string) (bool, models.Severity)
|
||||
}
|
||||
|
||||
type pmsPolicyChecker struct {
|
||||
pm promgr.ProMgr
|
||||
pm promgr.ProjectManager
|
||||
}
|
||||
|
||||
func (pc pmsPolicyChecker) contentTrustEnabled(name string) bool {
|
||||
@ -109,7 +109,7 @@ func (pc pmsPolicyChecker) vulnerablePolicy(name string) (bool, models.Severity)
|
||||
}
|
||||
|
||||
// newPMSPolicyChecker returns an instance of an pmsPolicyChecker
|
||||
func newPMSPolicyChecker(pm promgr.ProMgr) policyChecker {
|
||||
func newPMSPolicyChecker(pm promgr.ProjectManager) policyChecker {
|
||||
return &pmsPolicyChecker{
|
||||
pm: pm,
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ func GetResourceActions(scopes []string) []*token.ResourceActions {
|
||||
|
||||
//filterAccess iterate a list of resource actions and try to use the filter that matches the resource type to filter the actions.
|
||||
func filterAccess(access []*token.ResourceActions, ctx security.Context,
|
||||
pm promgr.ProMgr, filters map[string]accessFilter) error {
|
||||
pm promgr.ProjectManager, filters map[string]accessFilter) error {
|
||||
var err error
|
||||
for _, a := range access {
|
||||
f, ok := filters[a.Type]
|
||||
|
@ -127,13 +127,13 @@ func parseImg(s string) (*image, error) {
|
||||
|
||||
// An accessFilter will filter access based on userinfo
|
||||
type accessFilter interface {
|
||||
filter(ctx security.Context, pm promgr.ProMgr, a *token.ResourceActions) error
|
||||
filter(ctx security.Context, pm promgr.ProjectManager, a *token.ResourceActions) error
|
||||
}
|
||||
|
||||
type registryFilter struct {
|
||||
}
|
||||
|
||||
func (reg registryFilter) filter(ctx security.Context, pm promgr.ProMgr,
|
||||
func (reg registryFilter) filter(ctx security.Context, pm promgr.ProjectManager,
|
||||
a *token.ResourceActions) error {
|
||||
//Do not filter if the request is to access registry catalog
|
||||
if a.Name != "catalog" {
|
||||
@ -151,7 +151,7 @@ type repositoryFilter struct {
|
||||
parser imageParser
|
||||
}
|
||||
|
||||
func (rep repositoryFilter) filter(ctx security.Context, pm promgr.ProMgr,
|
||||
func (rep repositoryFilter) filter(ctx security.Context, pm promgr.ProjectManager,
|
||||
a *token.ResourceActions) error {
|
||||
//clear action list to assign to new acess element after perm check.
|
||||
img, err := rep.parser.parse(a.Name)
|
||||
@ -161,7 +161,7 @@ func (rep repositoryFilter) filter(ctx security.Context, pm promgr.ProMgr,
|
||||
project := img.namespace
|
||||
permission := ""
|
||||
|
||||
exist, err := pm.Exist(project)
|
||||
exist, err := pm.Exists(project)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user