mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-23 10:45:45 +01:00
update
This commit is contained in:
parent
e1c1b8ec34
commit
b5279ea1f1
@ -17,6 +17,7 @@ package rbac
|
||||
import (
|
||||
"github.com/vmware/harbor/src/common"
|
||||
"github.com/vmware/harbor/src/common/models"
|
||||
"github.com/vmware/harbor/src/common/utils/log"
|
||||
"github.com/vmware/harbor/src/ui/projectmanager"
|
||||
)
|
||||
|
||||
@ -60,12 +61,25 @@ func (s *SecurityContext) IsSysAdmin() bool {
|
||||
// HasReadPerm returns whether the user has read permission to the project
|
||||
func (s *SecurityContext) HasReadPerm(projectIDOrName interface{}) bool {
|
||||
// not exist
|
||||
if !s.pm.Exist(projectIDOrName) {
|
||||
exist, err := s.pm.Exist(projectIDOrName)
|
||||
if err != nil {
|
||||
log.Errorf("failed to check the existence of project %v: %v",
|
||||
projectIDOrName, err)
|
||||
return false
|
||||
}
|
||||
|
||||
if !exist {
|
||||
return false
|
||||
}
|
||||
|
||||
// public project
|
||||
if s.pm.IsPublic(projectIDOrName) {
|
||||
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
|
||||
}
|
||||
|
||||
@ -79,7 +93,13 @@ func (s *SecurityContext) HasReadPerm(projectIDOrName interface{}) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
roles := s.pm.GetRoles(s.GetUsername(), projectIDOrName)
|
||||
roles, err := s.pm.GetRoles(s.GetUsername(), projectIDOrName)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get roles of user %s to project %v: %v",
|
||||
s.GetUsername(), projectIDOrName, err)
|
||||
return false
|
||||
}
|
||||
|
||||
for _, role := range roles {
|
||||
switch role {
|
||||
case common.RoleProjectAdmin,
|
||||
@ -99,7 +119,14 @@ func (s *SecurityContext) HasWritePerm(projectIDOrName interface{}) bool {
|
||||
}
|
||||
|
||||
// project does not exist
|
||||
if !s.pm.Exist(projectIDOrName) {
|
||||
exist, err := s.pm.Exist(projectIDOrName)
|
||||
if err != nil {
|
||||
log.Errorf("failed to check the existence of project %v: %v",
|
||||
projectIDOrName, err)
|
||||
return false
|
||||
}
|
||||
|
||||
if !exist {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -108,7 +135,13 @@ func (s *SecurityContext) HasWritePerm(projectIDOrName interface{}) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
roles := s.pm.GetRoles(s.GetUsername(), projectIDOrName)
|
||||
roles, err := s.pm.GetRoles(s.GetUsername(), projectIDOrName)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get roles of user %s to project %v: %v",
|
||||
s.GetUsername(), projectIDOrName, err)
|
||||
return false
|
||||
}
|
||||
|
||||
for _, role := range roles {
|
||||
switch role {
|
||||
case common.RoleProjectAdmin,
|
||||
@ -127,7 +160,14 @@ func (s *SecurityContext) HasAllPerm(projectIDOrName interface{}) bool {
|
||||
}
|
||||
|
||||
// project does not exist
|
||||
if !s.pm.Exist(projectIDOrName) {
|
||||
exist, err := s.pm.Exist(projectIDOrName)
|
||||
if err != nil {
|
||||
log.Errorf("failed to check the existence of project %v: %v",
|
||||
projectIDOrName, err)
|
||||
return false
|
||||
}
|
||||
|
||||
if !exist {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -136,7 +176,13 @@ func (s *SecurityContext) HasAllPerm(projectIDOrName interface{}) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
roles := s.pm.GetRoles(s.GetUsername(), projectIDOrName)
|
||||
roles, err := s.pm.GetRoles(s.GetUsername(), projectIDOrName)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get roles of user %s to project %v: %v",
|
||||
s.GetUsername(), projectIDOrName, err)
|
||||
return false
|
||||
}
|
||||
|
||||
for _, role := range roles {
|
||||
switch role {
|
||||
case common.RoleProjectAdmin:
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/vmware/harbor/src/common"
|
||||
"github.com/vmware/harbor/src/common/models"
|
||||
"github.com/vmware/harbor/src/ui/projectmanager"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -52,42 +53,42 @@ type fakePM struct {
|
||||
roles map[string][]int
|
||||
}
|
||||
|
||||
func (f *fakePM) IsPublic(projectIDOrName interface{}) bool {
|
||||
func (f *fakePM) IsPublic(projectIDOrName interface{}) (bool, error) {
|
||||
for _, project := range f.projects {
|
||||
if project.Name == projectIDOrName.(string) {
|
||||
return project.Public == 1
|
||||
return project.Public == 1, nil
|
||||
}
|
||||
}
|
||||
return false
|
||||
return false, nil
|
||||
}
|
||||
func (f *fakePM) GetRoles(username string, projectIDOrName interface{}) []int {
|
||||
return f.roles[projectIDOrName.(string)]
|
||||
func (f *fakePM) GetRoles(username string, projectIDOrName interface{}) ([]int, error) {
|
||||
return f.roles[projectIDOrName.(string)], nil
|
||||
}
|
||||
func (f *fakePM) Get(projectIDOrName interface{}) *models.Project {
|
||||
func (f *fakePM) Get(projectIDOrName interface{}) (*models.Project, error) {
|
||||
for _, project := range f.projects {
|
||||
if project.Name == projectIDOrName.(string) {
|
||||
return project
|
||||
return project, nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
func (f *fakePM) Exist(projectIDOrName interface{}) bool {
|
||||
func (f *fakePM) Exist(projectIDOrName interface{}) (bool, error) {
|
||||
for _, project := range f.projects {
|
||||
if project.Name == projectIDOrName.(string) {
|
||||
return true
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// nil implement
|
||||
func (f *fakePM) GetPublic() []*models.Project {
|
||||
return []*models.Project{}
|
||||
func (f *fakePM) GetPublic() ([]*models.Project, error) {
|
||||
return []*models.Project{}, nil
|
||||
}
|
||||
|
||||
// nil implement
|
||||
func (f *fakePM) GetByMember(username string) []*models.Project {
|
||||
return []*models.Project{}
|
||||
func (f *fakePM) GetByMember(username string) ([]*models.Project, error) {
|
||||
return []*models.Project{}, nil
|
||||
}
|
||||
|
||||
// nil implement
|
||||
@ -106,9 +107,13 @@ func (f *fakePM) Update(projectIDOrName interface{}, project *models.Project) er
|
||||
}
|
||||
|
||||
// nil implement
|
||||
func (f *fakePM) GetAll(owner, name, public, member string, role int, page,
|
||||
size int64) ([]*models.Project, int64) {
|
||||
return []*models.Project{}, 0
|
||||
func (f *fakePM) GetAll(*projectmanager.QueryParam) ([]*models.Project, error) {
|
||||
return []*models.Project{}, nil
|
||||
}
|
||||
|
||||
// nil implement
|
||||
func (f *fakePM) GetTotal(*projectmanager.QueryParam) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func TestIsAuthenticated(t *testing.T) {
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
"github.com/vmware/harbor/src/common/models"
|
||||
"github.com/vmware/harbor/src/common/utils/log"
|
||||
"github.com/vmware/harbor/src/ui/config"
|
||||
"github.com/vmware/harbor/src/ui/projectmanager"
|
||||
|
||||
"strconv"
|
||||
"time"
|
||||
@ -32,6 +33,7 @@ import (
|
||||
// ProjectAPI handles request to /api/projects/{} /api/projects/{}/logs
|
||||
type ProjectAPI struct {
|
||||
BaseController
|
||||
project *models.Project
|
||||
}
|
||||
|
||||
type projectReq struct {
|
||||
@ -44,6 +46,38 @@ const projectNameMinLen int = 2
|
||||
const restrictedNameChars = `[a-z0-9]+(?:[._-][a-z0-9]+)*`
|
||||
const dupProjectPattern = `Duplicate entry '\w+' for key 'name'`
|
||||
|
||||
// Prepare validates the URL and the user
|
||||
func (p *ProjectAPI) Prepare() {
|
||||
p.BaseController.Prepare()
|
||||
if len(p.GetStringFromPath(":id")) != 0 {
|
||||
id, err := p.GetInt64FromPath(":id")
|
||||
if err != nil || id <= 0 {
|
||||
text := "invalid project ID: "
|
||||
if err != nil {
|
||||
text += err.Error()
|
||||
} else {
|
||||
text += fmt.Sprintf("%d", id)
|
||||
}
|
||||
p.HandleBadRequest(text)
|
||||
return
|
||||
}
|
||||
|
||||
project, err := p.ProjectMgr.Get(id)
|
||||
if err != nil {
|
||||
p.HandleInternalServerError(fmt.Sprintf("failed to get project %d: %v",
|
||||
id, err))
|
||||
return
|
||||
}
|
||||
|
||||
if project == nil {
|
||||
p.HandleNotFound(fmt.Sprintf("project %d not found", id))
|
||||
return
|
||||
}
|
||||
|
||||
p.project = project
|
||||
}
|
||||
}
|
||||
|
||||
// Post ...
|
||||
func (p *ProjectAPI) Post() {
|
||||
if !p.SecurityCtx.IsAuthenticated() {
|
||||
@ -70,7 +104,13 @@ func (p *ProjectAPI) Post() {
|
||||
return
|
||||
}
|
||||
|
||||
if p.ProjectMgr.Exist(pro.ProjectName) {
|
||||
exist, err := p.ProjectMgr.Exist(pro.ProjectName)
|
||||
if err != nil {
|
||||
p.HandleInternalServerError(fmt.Sprintf("failed to check the existence of project %s: %v",
|
||||
pro.ProjectName, err))
|
||||
return
|
||||
}
|
||||
if exist {
|
||||
p.RenderError(http.StatusConflict, "")
|
||||
return
|
||||
}
|
||||
@ -117,7 +157,13 @@ func (p *ProjectAPI) Head() {
|
||||
return
|
||||
}
|
||||
|
||||
project := p.ProjectMgr.Get(name)
|
||||
project, err := p.ProjectMgr.Get(name)
|
||||
if err != nil {
|
||||
p.HandleInternalServerError(fmt.Sprintf("failed to get project %s: %v",
|
||||
name, err))
|
||||
return
|
||||
}
|
||||
|
||||
if project == nil {
|
||||
p.HandleNotFound(fmt.Sprintf("project %s not found", name))
|
||||
return
|
||||
@ -126,99 +172,63 @@ func (p *ProjectAPI) Head() {
|
||||
|
||||
// Get ...
|
||||
func (p *ProjectAPI) Get() {
|
||||
id, err := p.GetInt64FromPath(":id")
|
||||
if err != nil || id <= 0 {
|
||||
text := "invalid project ID: "
|
||||
if err != nil {
|
||||
text += err.Error()
|
||||
} else {
|
||||
text += fmt.Sprintf("%d", id)
|
||||
}
|
||||
p.HandleBadRequest(text)
|
||||
return
|
||||
}
|
||||
|
||||
project := p.ProjectMgr.Get(id)
|
||||
if project == nil {
|
||||
p.HandleNotFound(fmt.Sprintf("project %d not found", id))
|
||||
return
|
||||
}
|
||||
|
||||
if project.Public == 0 {
|
||||
if p.project.Public == 0 {
|
||||
if !p.SecurityCtx.IsAuthenticated() {
|
||||
p.HandleUnauthorized()
|
||||
return
|
||||
}
|
||||
|
||||
if !p.SecurityCtx.HasReadPerm(id) {
|
||||
if !p.SecurityCtx.HasReadPerm(p.project.ProjectID) {
|
||||
p.HandleForbidden(p.SecurityCtx.GetUsername())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
p.Data["json"] = project
|
||||
p.Data["json"] = p.project
|
||||
p.ServeJSON()
|
||||
}
|
||||
|
||||
// Delete ...
|
||||
func (p *ProjectAPI) Delete() {
|
||||
id, err := p.GetInt64FromPath(":id")
|
||||
if err != nil || id <= 0 {
|
||||
text := "invalid project ID: "
|
||||
if err != nil {
|
||||
text += err.Error()
|
||||
} else {
|
||||
text += fmt.Sprintf("%d", id)
|
||||
}
|
||||
p.HandleBadRequest(text)
|
||||
return
|
||||
}
|
||||
|
||||
project := p.ProjectMgr.Get(id)
|
||||
if project == nil {
|
||||
p.HandleNotFound(fmt.Sprintf("project %d not found", id))
|
||||
return
|
||||
}
|
||||
|
||||
if !p.SecurityCtx.IsAuthenticated() {
|
||||
p.HandleUnauthorized()
|
||||
return
|
||||
}
|
||||
|
||||
if !p.SecurityCtx.HasAllPerm(id) {
|
||||
if !p.SecurityCtx.HasAllPerm(p.project.ProjectID) {
|
||||
p.HandleForbidden(p.SecurityCtx.GetUsername())
|
||||
return
|
||||
}
|
||||
|
||||
contains, err := projectContainsRepo(project.Name)
|
||||
contains, err := projectContainsRepo(p.project.Name)
|
||||
if err != nil {
|
||||
log.Errorf("failed to check whether project %s contains any repository: %v", project.Name, err)
|
||||
log.Errorf("failed to check whether project %s contains any repository: %v", p.project.Name, err)
|
||||
p.CustomAbort(http.StatusInternalServerError, "")
|
||||
}
|
||||
if contains {
|
||||
p.CustomAbort(http.StatusPreconditionFailed, "project contains repositores, can not be deleted")
|
||||
}
|
||||
|
||||
contains, err = projectContainsPolicy(id)
|
||||
contains, err = projectContainsPolicy(p.project.ProjectID)
|
||||
if err != nil {
|
||||
log.Errorf("failed to check whether project %s contains any policy: %v", project.Name, err)
|
||||
log.Errorf("failed to check whether project %s contains any policy: %v", p.project.Name, err)
|
||||
p.CustomAbort(http.StatusInternalServerError, "")
|
||||
}
|
||||
if contains {
|
||||
p.CustomAbort(http.StatusPreconditionFailed, "project contains policies, can not be deleted")
|
||||
}
|
||||
|
||||
if err = p.ProjectMgr.Delete(id); err != nil {
|
||||
if err = p.ProjectMgr.Delete(p.project.ProjectID); err != nil {
|
||||
p.HandleInternalServerError(
|
||||
fmt.Sprintf("failed to delete project %d: %v", id, err))
|
||||
fmt.Sprintf("failed to delete project %d: %v", p.project.ProjectID, err))
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := dao.AddAccessLog(models.AccessLog{
|
||||
Username: p.SecurityCtx.GetUsername(),
|
||||
ProjectID: id,
|
||||
RepoName: project.Name + "/",
|
||||
ProjectID: p.project.ProjectID,
|
||||
RepoName: p.project.Name + "/",
|
||||
RepoTag: "N/A",
|
||||
Operation: "delete",
|
||||
OpTime: time.Now(),
|
||||
@ -250,53 +260,61 @@ func projectContainsPolicy(id int64) (bool, error) {
|
||||
// TODO refacter pattern to:
|
||||
// /api/repositories?owner=xxx&name=xxx&public=true&member=xxx&role=1&page=1&size=3
|
||||
func (p *ProjectAPI) List() {
|
||||
query := &projectmanager.QueryParam{}
|
||||
|
||||
// query conditions:
|
||||
var (
|
||||
owner string // the username of project owner
|
||||
name string // the project name
|
||||
public string // the project is public or not
|
||||
member string // the username of the member
|
||||
role int // role of the member specified by member parameter
|
||||
page int64 // pagination
|
||||
size int64 // pagination
|
||||
)
|
||||
|
||||
name = p.GetString("project_name")
|
||||
public = p.GetString("is_public")
|
||||
query.Name = p.GetString("project_name")
|
||||
public := p.GetString("is_public")
|
||||
if len(public) != 0 {
|
||||
if public != "0" && public != "1" {
|
||||
p.HandleBadRequest("is_public should be 0 or 1")
|
||||
return
|
||||
}
|
||||
if public == "1" {
|
||||
public = "true"
|
||||
query.Public = "true"
|
||||
}
|
||||
}
|
||||
|
||||
page, size = p.GetPaginationParams()
|
||||
|
||||
if public != "true" {
|
||||
if query.Public != "true" {
|
||||
//if the request is not for public projects, user must login or provide credential
|
||||
if !p.SecurityCtx.IsAuthenticated() {
|
||||
p.HandleUnauthorized()
|
||||
return
|
||||
}
|
||||
|
||||
public = ""
|
||||
member = p.SecurityCtx.GetUsername()
|
||||
|
||||
if p.SecurityCtx.IsSysAdmin() {
|
||||
member = ""
|
||||
if !p.SecurityCtx.IsSysAdmin() {
|
||||
query.Member = &projectmanager.Member{
|
||||
Name: p.SecurityCtx.GetUsername(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
projects, total := p.ProjectMgr.GetAll(owner, name, public, member,
|
||||
role, page, size)
|
||||
total, err := p.ProjectMgr.GetTotal(query)
|
||||
if err != nil {
|
||||
p.HandleInternalServerError(fmt.Sprintf("failed to get total of projects: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
page, size := p.GetPaginationParams()
|
||||
query.Pagination = &projectmanager.Pagination{
|
||||
Page: page,
|
||||
Size: size,
|
||||
}
|
||||
|
||||
projects, err := p.ProjectMgr.GetAll(query)
|
||||
if err != nil {
|
||||
p.HandleInternalServerError(fmt.Sprintf("failed to get projects: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
for _, project := range projects {
|
||||
if public != "true" {
|
||||
roles := p.ProjectMgr.GetRoles(p.SecurityCtx.GetUsername(), project.ProjectID)
|
||||
if query.Public != "true" {
|
||||
roles, err := p.ProjectMgr.GetRoles(p.SecurityCtx.GetUsername(), project.ProjectID)
|
||||
if err != nil {
|
||||
p.HandleInternalServerError(fmt.Sprintf("failed to get roles of user %s to project %d: %v",
|
||||
p.SecurityCtx.GetUsername(), project.ProjectID, err))
|
||||
return
|
||||
}
|
||||
|
||||
if len(roles) != 0 {
|
||||
project.Role = roles[0]
|
||||
}
|
||||
@ -323,30 +341,12 @@ func (p *ProjectAPI) List() {
|
||||
|
||||
// ToggleProjectPublic ...
|
||||
func (p *ProjectAPI) ToggleProjectPublic() {
|
||||
id, err := p.GetInt64FromPath(":id")
|
||||
if err != nil || id <= 0 {
|
||||
text := "invalid project ID: "
|
||||
if err != nil {
|
||||
text += err.Error()
|
||||
} else {
|
||||
text += fmt.Sprintf("%d", id)
|
||||
}
|
||||
p.HandleBadRequest(text)
|
||||
return
|
||||
}
|
||||
|
||||
project := p.ProjectMgr.Get(id)
|
||||
if project == nil {
|
||||
p.HandleNotFound(fmt.Sprintf("project %d not found", id))
|
||||
return
|
||||
}
|
||||
|
||||
if !p.SecurityCtx.IsAuthenticated() {
|
||||
p.HandleUnauthorized()
|
||||
return
|
||||
}
|
||||
|
||||
if !p.SecurityCtx.HasAllPerm(id) {
|
||||
if !p.SecurityCtx.HasAllPerm(p.project.ProjectID) {
|
||||
p.HandleForbidden(p.SecurityCtx.GetUsername())
|
||||
return
|
||||
}
|
||||
@ -358,40 +358,24 @@ func (p *ProjectAPI) ToggleProjectPublic() {
|
||||
return
|
||||
}
|
||||
|
||||
if err := p.ProjectMgr.Update(id, &models.Project{
|
||||
Public: req.Public,
|
||||
}); err != nil {
|
||||
p.HandleInternalServerError(fmt.Sprintf("failed to update project %d: %v", id, err))
|
||||
if err := p.ProjectMgr.Update(p.project.ProjectID,
|
||||
&models.Project{
|
||||
Public: req.Public,
|
||||
}); err != nil {
|
||||
p.HandleInternalServerError(fmt.Sprintf("failed to update project %d: %v",
|
||||
p.project.ProjectID, err))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// FilterAccessLog handles GET to /api/projects/{}/logs
|
||||
func (p *ProjectAPI) FilterAccessLog() {
|
||||
id, err := p.GetInt64FromPath(":id")
|
||||
if err != nil || id <= 0 {
|
||||
text := "invalid project ID: "
|
||||
if err != nil {
|
||||
text += err.Error()
|
||||
} else {
|
||||
text += fmt.Sprintf("%d", id)
|
||||
}
|
||||
p.HandleBadRequest(text)
|
||||
return
|
||||
}
|
||||
|
||||
project := p.ProjectMgr.Get(id)
|
||||
if project == nil {
|
||||
p.HandleNotFound(fmt.Sprintf("project %d not found", id))
|
||||
return
|
||||
}
|
||||
|
||||
if !p.SecurityCtx.IsAuthenticated() {
|
||||
p.HandleUnauthorized()
|
||||
return
|
||||
}
|
||||
|
||||
if !p.SecurityCtx.HasReadPerm(id) {
|
||||
if !p.SecurityCtx.HasReadPerm(p.project.ProjectID) {
|
||||
p.HandleForbidden(p.SecurityCtx.GetUsername())
|
||||
return
|
||||
}
|
||||
@ -399,7 +383,7 @@ func (p *ProjectAPI) FilterAccessLog() {
|
||||
var query models.AccessLog
|
||||
p.DecodeJSONReq(&query)
|
||||
|
||||
query.ProjectID = id
|
||||
query.ProjectID = p.project.ProjectID
|
||||
query.BeginTime = time.Unix(query.BeginTimestamp, 0)
|
||||
query.EndTime = time.Unix(query.EndTimestamp, 0)
|
||||
|
||||
|
@ -69,7 +69,14 @@ func (ra *RepositoryAPI) Get() {
|
||||
return
|
||||
}
|
||||
|
||||
if !ra.ProjectMgr.Exist(projectID) {
|
||||
exist, err := ra.ProjectMgr.Exist(projectID)
|
||||
if err != nil {
|
||||
ra.HandleInternalServerError(fmt.Sprintf("failed to check the existence of project %d: %v",
|
||||
projectID, err))
|
||||
return
|
||||
}
|
||||
|
||||
if !exist {
|
||||
ra.HandleNotFound(fmt.Sprintf("project %d not found", projectID))
|
||||
return
|
||||
}
|
||||
@ -146,7 +153,14 @@ func (ra *RepositoryAPI) Delete() {
|
||||
repoName := ra.GetString(":splat")
|
||||
|
||||
projectName, _ := utils.ParseRepository(repoName)
|
||||
if !ra.ProjectMgr.Exist(projectName) {
|
||||
exist, err := ra.ProjectMgr.Exist(projectName)
|
||||
if err != nil {
|
||||
ra.HandleInternalServerError(fmt.Sprintf("failed to check the existence of project %s: %v",
|
||||
projectName, err))
|
||||
return
|
||||
}
|
||||
|
||||
if !exist {
|
||||
ra.HandleNotFound(fmt.Sprintf("project %s not found", projectName))
|
||||
return
|
||||
}
|
||||
@ -236,7 +250,18 @@ func (ra *RepositoryAPI) Delete() {
|
||||
go TriggerReplicationByRepository(repoName, []string{t}, models.RepOpDelete)
|
||||
|
||||
go func(tag string) {
|
||||
project := ra.ProjectMgr.Get(projectName)
|
||||
project, err := ra.ProjectMgr.Get(projectName)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get the project %s: %v",
|
||||
projectName, err)
|
||||
return
|
||||
}
|
||||
|
||||
if project == nil {
|
||||
log.Error("project %s not found", projectName)
|
||||
return
|
||||
}
|
||||
|
||||
if err := dao.AddAccessLog(models.AccessLog{
|
||||
Username: ra.SecurityCtx.GetUsername(),
|
||||
ProjectID: project.ProjectID,
|
||||
@ -250,7 +275,7 @@ func (ra *RepositoryAPI) Delete() {
|
||||
}(t)
|
||||
}
|
||||
|
||||
exist, err := repositoryExist(repoName, rc)
|
||||
exist, err = repositoryExist(repoName, rc)
|
||||
if err != nil {
|
||||
log.Errorf("failed to check the existence of repository %s: %v", repoName, err)
|
||||
ra.CustomAbort(http.StatusInternalServerError, "")
|
||||
@ -268,7 +293,14 @@ func (ra *RepositoryAPI) GetTags() {
|
||||
repoName := ra.GetString(":splat")
|
||||
|
||||
projectName, _ := utils.ParseRepository(repoName)
|
||||
if !ra.ProjectMgr.Exist(projectName) {
|
||||
exist, err := ra.ProjectMgr.Exist(projectName)
|
||||
if err != nil {
|
||||
ra.HandleInternalServerError(fmt.Sprintf("failed to check the existence of project %s: %v",
|
||||
projectName, err))
|
||||
return
|
||||
}
|
||||
|
||||
if !exist {
|
||||
ra.HandleNotFound(fmt.Sprintf("project %s not found", projectName))
|
||||
return
|
||||
}
|
||||
@ -360,7 +392,14 @@ func (ra *RepositoryAPI) GetManifests() {
|
||||
}
|
||||
|
||||
projectName, _ := utils.ParseRepository(repoName)
|
||||
if !ra.ProjectMgr.Exist(projectName) {
|
||||
exist, err := ra.ProjectMgr.Exist(projectName)
|
||||
if err != nil {
|
||||
ra.HandleInternalServerError(fmt.Sprintf("failed to check the existence of project %s: %v",
|
||||
projectName, err))
|
||||
return
|
||||
}
|
||||
|
||||
if !exist {
|
||||
ra.HandleNotFound(fmt.Sprintf("project %s not found", projectName))
|
||||
return
|
||||
}
|
||||
@ -455,10 +494,19 @@ func (ra *RepositoryAPI) GetTopRepos() {
|
||||
}
|
||||
|
||||
projectIDs := []int64{}
|
||||
projects := ra.ProjectMgr.GetPublic()
|
||||
projects, err := ra.ProjectMgr.GetPublic()
|
||||
if err != nil {
|
||||
log.Errorf("failed to get the public projects: %v", err)
|
||||
return
|
||||
}
|
||||
if ra.SecurityCtx.IsAuthenticated() {
|
||||
projects = append(projects, ra.ProjectMgr.GetByMember(
|
||||
ra.SecurityCtx.GetUsername())...)
|
||||
list, err := ra.ProjectMgr.GetByMember(ra.SecurityCtx.GetUsername())
|
||||
if err != nil {
|
||||
log.Errorf("failed to get projects which the user %s is a member of: %v",
|
||||
ra.SecurityCtx.GetUsername(), err)
|
||||
return
|
||||
}
|
||||
projects = append(projects, list...)
|
||||
}
|
||||
|
||||
for _, project := range projects {
|
||||
|
@ -21,77 +21,74 @@ import (
|
||||
"github.com/vmware/harbor/src/common"
|
||||
"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/projectmanager"
|
||||
)
|
||||
|
||||
// ProjectManager implements pm.PM interface based on database
|
||||
type ProjectManager struct{}
|
||||
|
||||
// Get ...
|
||||
func (p *ProjectManager) Get(projectIDOrName interface{}) *models.Project {
|
||||
func (p *ProjectManager) Get(projectIDOrName interface{}) (
|
||||
*models.Project, error) {
|
||||
switch projectIDOrName.(type) {
|
||||
case string:
|
||||
name := projectIDOrName.(string)
|
||||
project, err := dao.GetProjectByName(name)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get project %s: %v", name, err)
|
||||
return nil
|
||||
}
|
||||
return project
|
||||
return dao.GetProjectByName(projectIDOrName.(string))
|
||||
case int64:
|
||||
id := projectIDOrName.(int64)
|
||||
project, err := dao.GetProjectByID(id)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get project %d: %v", id, err)
|
||||
return nil
|
||||
}
|
||||
return project
|
||||
return dao.GetProjectByID(projectIDOrName.(int64))
|
||||
default:
|
||||
log.Errorf("unsupported type of %v, must be string or int64", projectIDOrName)
|
||||
return nil
|
||||
return nil, fmt.Errorf("unsupported type of %v, must be string or int64", projectIDOrName)
|
||||
}
|
||||
}
|
||||
|
||||
// Exist ...
|
||||
func (p *ProjectManager) Exist(projectIDOrName interface{}) bool {
|
||||
return p.Get(projectIDOrName) != nil
|
||||
func (p *ProjectManager) Exist(projectIDOrName interface{}) (bool, error) {
|
||||
project, err := p.Get(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 {
|
||||
project := p.Get(projectIDOrName)
|
||||
if project == nil {
|
||||
return false
|
||||
func (p *ProjectManager) IsPublic(projectIDOrName interface{}) (bool, error) {
|
||||
project, err := p.Get(projectIDOrName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return project.Public == 1
|
||||
if project == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return project.Public == 1, nil
|
||||
}
|
||||
|
||||
// GetRoles return a role list which contains the user's roles to the project
|
||||
func (p *ProjectManager) GetRoles(username string, projectIDOrName interface{}) []int {
|
||||
func (p *ProjectManager) GetRoles(username string, projectIDOrName interface{}) ([]int, error) {
|
||||
roles := []int{}
|
||||
|
||||
user, err := dao.GetUser(models.User{
|
||||
Username: username,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("failed to get user %s: %v", username, err)
|
||||
return roles
|
||||
return nil, fmt.Errorf("failed to get user %s: %v",
|
||||
username, err)
|
||||
}
|
||||
if user == nil {
|
||||
return roles
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
project := p.Get(projectIDOrName)
|
||||
project, err := p.Get(projectIDOrName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if project == nil {
|
||||
return roles
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
roleList, err := dao.GetUserProjectRoles(user.UserID, project.ProjectID)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get roles for user %d to project %d: %v",
|
||||
user.UserID, project.ProjectID, err)
|
||||
return roles
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, role := range roleList {
|
||||
@ -105,17 +102,24 @@ func (p *ProjectManager) GetRoles(username string, projectIDOrName interface{})
|
||||
}
|
||||
}
|
||||
|
||||
return roles
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
// GetPublic returns all public projects
|
||||
func (p *ProjectManager) GetPublic() []*models.Project {
|
||||
return filter("", "", "true", "", 0, 0, 0)
|
||||
func (p *ProjectManager) GetPublic() ([]*models.Project, error) {
|
||||
return p.GetAll(&projectmanager.QueryParam{
|
||||
Public: "true",
|
||||
})
|
||||
}
|
||||
|
||||
// GetByMember returns all projects which the user is a member of
|
||||
func (p *ProjectManager) GetByMember(username string) []*models.Project {
|
||||
return filter("", "", "", username, 0, 0, 0)
|
||||
func (p *ProjectManager) GetByMember(username string) (
|
||||
[]*models.Project, error) {
|
||||
return p.GetAll(&projectmanager.QueryParam{
|
||||
Member: &projectmanager.Member{
|
||||
Name: username,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Create ...
|
||||
@ -161,9 +165,9 @@ func (p *ProjectManager) Create(project *models.Project) (int64, error) {
|
||||
func (p *ProjectManager) Delete(projectIDOrName interface{}) error {
|
||||
id, ok := projectIDOrName.(int64)
|
||||
if !ok {
|
||||
project := p.Get(projectIDOrName)
|
||||
if project == nil {
|
||||
return fmt.Errorf(fmt.Sprintf("project %v not found", projectIDOrName))
|
||||
project, err := p.Get(projectIDOrName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
id = project.ProjectID
|
||||
}
|
||||
@ -176,41 +180,66 @@ func (p *ProjectManager) Update(projectIDOrName interface{},
|
||||
project *models.Project) error {
|
||||
id, ok := projectIDOrName.(int64)
|
||||
if !ok {
|
||||
pro := p.Get(projectIDOrName)
|
||||
if pro == nil {
|
||||
return fmt.Errorf(fmt.Sprintf("project %v not found", projectIDOrName))
|
||||
pro, err := p.Get(projectIDOrName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
id = pro.ProjectID
|
||||
}
|
||||
return dao.ToggleProjectPublicity(id, project.Public)
|
||||
}
|
||||
|
||||
// GetAll ...
|
||||
func (p *ProjectManager) GetAll(owner, name, public, member string,
|
||||
role int, page, size int64) ([]*models.Project, int64) {
|
||||
total, err := dao.GetTotalOfProjects(owner, name, public, member, role)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get total of projects: %v", err)
|
||||
return []*models.Project{}, 0
|
||||
// GetAll returns a project list according to the query parameters
|
||||
func (p *ProjectManager) GetAll(query *projectmanager.QueryParam) (
|
||||
[]*models.Project, error) {
|
||||
|
||||
var (
|
||||
owner string
|
||||
name string
|
||||
public string
|
||||
member string
|
||||
role int
|
||||
page int64
|
||||
size int64
|
||||
)
|
||||
|
||||
if query != nil {
|
||||
owner = query.Owner
|
||||
name = query.Name
|
||||
public = query.Public
|
||||
if query.Member != nil {
|
||||
member = query.Member.Name
|
||||
role = query.Member.Role
|
||||
}
|
||||
if query.Pagination != nil {
|
||||
page = query.Pagination.Page
|
||||
size = query.Pagination.Size
|
||||
}
|
||||
}
|
||||
|
||||
return filter(owner, name, public, member, role, page, size), total
|
||||
return dao.GetProjects(owner, name, public, member, role, page, size)
|
||||
}
|
||||
|
||||
func filter(owner, name, public, member string,
|
||||
role int, page, size int64) []*models.Project {
|
||||
projects := []*models.Project{}
|
||||
// GetTotal returns the total count according to the query parameters
|
||||
func (p *ProjectManager) GetTotal(query *projectmanager.QueryParam) (
|
||||
int64, error) {
|
||||
var (
|
||||
owner string
|
||||
name string
|
||||
public string
|
||||
member string
|
||||
role int
|
||||
)
|
||||
|
||||
list, err := dao.GetProjects(owner, name, public, member, role,
|
||||
page, size)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get projects: %v", err)
|
||||
return projects
|
||||
if query != nil {
|
||||
owner = query.Owner
|
||||
name = query.Name
|
||||
public = query.Public
|
||||
if query.Member != nil {
|
||||
member = query.Member.Name
|
||||
role = query.Member.Role
|
||||
}
|
||||
}
|
||||
|
||||
if len(list) != 0 {
|
||||
projects = append(projects, list...)
|
||||
}
|
||||
|
||||
return projects
|
||||
return dao.GetTotalOfProjects(owner, name, public, member, role)
|
||||
}
|
||||
|
@ -24,6 +24,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/projectmanager"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
@ -74,62 +75,76 @@ func TestGet(t *testing.T) {
|
||||
pm := &ProjectManager{}
|
||||
|
||||
// project name
|
||||
project := pm.Get("library")
|
||||
project, err := pm.Get("library")
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, project)
|
||||
assert.Equal(t, "library", project.Name)
|
||||
|
||||
// project ID
|
||||
project = pm.Get(int64(1))
|
||||
project, err = pm.Get(int64(1))
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, project)
|
||||
assert.Equal(t, int64(1), project.ProjectID)
|
||||
|
||||
// non-exist project
|
||||
project = pm.Get("non-exist-project")
|
||||
project, err = pm.Get("non-exist-project")
|
||||
assert.Nil(t, err)
|
||||
assert.Nil(t, project)
|
||||
|
||||
// invalid type
|
||||
project = pm.Get(true)
|
||||
assert.Nil(t, project)
|
||||
project, err = pm.Get(true)
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestExist(t *testing.T) {
|
||||
pm := &ProjectManager{}
|
||||
|
||||
// exist project
|
||||
assert.True(t, pm.Exist("library"))
|
||||
exist, err := pm.Exist("library")
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, exist)
|
||||
|
||||
// non-exist project
|
||||
assert.False(t, pm.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
|
||||
assert.True(t, pms.IsPublic("library"))
|
||||
public, err := pms.IsPublic("library")
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, public)
|
||||
// non exist project
|
||||
assert.False(t, pms.IsPublic("non_exist_project"))
|
||||
public, err = pms.IsPublic("non_exist_project")
|
||||
assert.Nil(t, err)
|
||||
assert.False(t, public)
|
||||
}
|
||||
|
||||
func TestGetRoles(t *testing.T) {
|
||||
pm := &ProjectManager{}
|
||||
|
||||
// non exist user
|
||||
assert.Equal(t, []int{},
|
||||
pm.GetRoles("non_exist_user", int64(1)))
|
||||
roles, err := pm.GetRoles("non_exist_user", int64(1))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, []int{}, roles)
|
||||
|
||||
// exist project
|
||||
assert.Equal(t, []int{common.RoleProjectAdmin},
|
||||
pm.GetRoles("admin", "library"))
|
||||
roles, err = pm.GetRoles("admin", "library")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, []int{common.RoleProjectAdmin}, roles)
|
||||
|
||||
// non-exist project
|
||||
assert.Equal(t, []int{},
|
||||
pm.GetRoles("admin", "non_exist_project"))
|
||||
roles, err = pm.GetRoles("admin", "non_exist_project")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, []int{}, roles)
|
||||
}
|
||||
|
||||
func TestGetPublic(t *testing.T) {
|
||||
pm := &ProjectManager{}
|
||||
projects := pm.GetPublic()
|
||||
|
||||
projects, err := pm.GetPublic()
|
||||
assert.Nil(t, err)
|
||||
assert.NotEqual(t, 0, len(projects))
|
||||
|
||||
for _, project := range projects {
|
||||
@ -139,7 +154,8 @@ func TestGetPublic(t *testing.T) {
|
||||
|
||||
func TestGetByMember(t *testing.T) {
|
||||
pm := &ProjectManager{}
|
||||
projects := pm.GetByMember("admin")
|
||||
projects, err := pm.GetByMember("admin")
|
||||
assert.Nil(t, err)
|
||||
assert.NotEqual(t, 0, len(projects))
|
||||
}
|
||||
|
||||
@ -190,16 +206,51 @@ func TestUpdate(t *testing.T) {
|
||||
assert.Nil(t, err)
|
||||
defer pm.Delete(id)
|
||||
|
||||
project := pm.Get(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 = pm.Get(id)
|
||||
project, err = pm.Get(id)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 1, project.Public)
|
||||
}
|
||||
|
||||
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(&projectmanager.QueryParam{
|
||||
Name: "get_total_test",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, int64(1), total)
|
||||
|
||||
// get by owner
|
||||
total, err = pm.GetTotal(&projectmanager.QueryParam{
|
||||
Owner: "admin",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotEqual(t, 0, total)
|
||||
|
||||
// get by public
|
||||
total, err = pm.GetTotal(&projectmanager.QueryParam{
|
||||
Public: "true",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.NotEqual(t, 0, total)
|
||||
}
|
||||
|
||||
func TestGetAll(t *testing.T) {
|
||||
pm := &ProjectManager{}
|
||||
|
||||
@ -212,13 +263,17 @@ func TestGetAll(t *testing.T) {
|
||||
defer pm.Delete(id)
|
||||
|
||||
// get by name
|
||||
projects, total := pm.GetAll("", "get_all_test", "", "", 0, 0, 0)
|
||||
assert.Equal(t, int64(1), total)
|
||||
projects, err := pm.GetAll(&projectmanager.QueryParam{
|
||||
Name: "get_all_test",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, id, projects[0].ProjectID)
|
||||
|
||||
// get by owner
|
||||
projects, total = pm.GetAll("admin", "", "", "", 0, 0, 0)
|
||||
assert.NotEqual(t, 0, total)
|
||||
projects, err = pm.GetAll(&projectmanager.QueryParam{
|
||||
Owner: "admin",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
exist := false
|
||||
for _, project := range projects {
|
||||
if project.ProjectID == id {
|
||||
@ -229,8 +284,10 @@ func TestGetAll(t *testing.T) {
|
||||
assert.True(t, exist)
|
||||
|
||||
// get by public
|
||||
projects, total = pm.GetAll("", "", "true", "", 0, 0, 0)
|
||||
assert.NotEqual(t, 0, total)
|
||||
projects, err = pm.GetAll(&projectmanager.QueryParam{
|
||||
Public: "true",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
exist = false
|
||||
for _, project := range projects {
|
||||
if project.ProjectID == id {
|
||||
|
@ -18,28 +18,43 @@ import (
|
||||
"github.com/vmware/harbor/src/common/models"
|
||||
)
|
||||
|
||||
// QueryParam can be used to set query parameters when listing projects
|
||||
type QueryParam struct {
|
||||
Name string // the name of project
|
||||
Owner string // the username of project owner
|
||||
Public string // the project is public or not, can be "ture","false" and ""
|
||||
Member *Member // the member of project
|
||||
Pagination *Pagination // pagination information
|
||||
}
|
||||
|
||||
// Member fitler by member's username and role
|
||||
type Member struct {
|
||||
Name string // the username of member
|
||||
Role int // the role of the member has to the project
|
||||
}
|
||||
|
||||
// Pagination ...
|
||||
type Pagination struct {
|
||||
Page int64
|
||||
Size int64
|
||||
}
|
||||
|
||||
// ProjectManager is the project mamager which abstracts the operations related
|
||||
// to projects
|
||||
type ProjectManager interface {
|
||||
Get(projectIDOrName interface{}) *models.Project
|
||||
IsPublic(projectIDOrName interface{}) bool
|
||||
Exist(projectIDOrName interface{}) bool
|
||||
GetRoles(username string, projectIDOrName interface{}) []int
|
||||
Get(projectIDOrName interface{}) (*models.Project, error)
|
||||
IsPublic(projectIDOrName interface{}) (bool, error)
|
||||
Exist(projectIDOrName interface{}) (bool, error)
|
||||
GetRoles(username string, projectIDOrName interface{}) ([]int, error)
|
||||
// get all public project
|
||||
GetPublic() []*models.Project
|
||||
GetPublic() ([]*models.Project, error)
|
||||
// get projects which the user is a member of
|
||||
GetByMember(username string) []*models.Project
|
||||
GetByMember(username string) ([]*models.Project, error)
|
||||
Create(*models.Project) (int64, error)
|
||||
Delete(projectIDOrName interface{}) error
|
||||
Update(projectIDOrName interface{}, project *models.Project) error
|
||||
// GetAll returns a project list and the total count according to
|
||||
// the query conditions:
|
||||
// owner: username of owner
|
||||
// name: name of project
|
||||
// public: public or not, can be "true", "false" or ""
|
||||
// member: username of the member
|
||||
// role: the role of member specified by member parameter
|
||||
// page, size: pagination parameters
|
||||
GetAll(owner, name, public, member string, role int, page,
|
||||
size int64) ([]*models.Project, int64)
|
||||
// GetAll returns a project list according to the query parameters
|
||||
GetAll(query *QueryParam) ([]*models.Project, error)
|
||||
// GetTotal returns the total count according to the query parameters
|
||||
GetTotal(query *QueryParam) (int64, error)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user