mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-29 21:54:13 +01:00
Merge branch 'master' into job-service
This commit is contained in:
commit
fd0d291931
@ -47,7 +47,7 @@ http {
|
|||||||
|
|
||||||
location /v2/ {
|
location /v2/ {
|
||||||
proxy_pass http://registry/v2/;
|
proxy_pass http://registry/v2/;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $http_host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ func (pma *ProjectMemberAPI) Get() {
|
|||||||
}
|
}
|
||||||
pma.Data["json"] = userList
|
pma.Data["json"] = userList
|
||||||
} else { //return detail of a member
|
} else { //return detail of a member
|
||||||
roleList, err := dao.GetUserProjectRoles(pma.memberID, pid)
|
roleList, err := listRoles(pma.memberID, pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Error occurred in GetUserProjectRoles, error: %v", err)
|
log.Errorf("Error occurred in GetUserProjectRoles, error: %v", err)
|
||||||
pma.CustomAbort(http.StatusInternalServerError, "Internal error.")
|
pma.CustomAbort(http.StatusInternalServerError, "Internal error.")
|
||||||
@ -241,3 +241,27 @@ func (pma *ProjectMemberAPI) Delete() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//sysadmin has all privileges to all projects
|
||||||
|
func listRoles(userID int, projectID int64) ([]models.Role, error) {
|
||||||
|
roles := make([]models.Role, 1)
|
||||||
|
isSysAdmin, err := dao.IsAdminRole(userID)
|
||||||
|
if err != nil {
|
||||||
|
return roles, err
|
||||||
|
}
|
||||||
|
if isSysAdmin {
|
||||||
|
role, err := dao.GetRoleByID(models.PROJECTADMIN)
|
||||||
|
if err != nil {
|
||||||
|
return roles, err
|
||||||
|
}
|
||||||
|
roles = append(roles, *role)
|
||||||
|
return roles, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
rs, err := dao.GetUserProjectRoles(userID, projectID)
|
||||||
|
if err != nil {
|
||||||
|
return roles, err
|
||||||
|
}
|
||||||
|
roles = append(roles, rs...)
|
||||||
|
return roles, nil
|
||||||
|
}
|
||||||
|
@ -190,6 +190,16 @@ func (p *ProjectAPI) FilterAccessLog() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isProjectAdmin(userID int, pid int64) bool {
|
func isProjectAdmin(userID int, pid int64) bool {
|
||||||
|
isSysAdmin, err := dao.IsAdminRole(userID)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Error occurred in IsAdminRole, returning false, error: %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if isSysAdmin {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
rolelist, err := dao.GetUserProjectRoles(userID, pid)
|
rolelist, err := dao.GetUserProjectRoles(userID, pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Error occurred in GetUserProjectRoles, returning false, error: %v", err)
|
log.Errorf("Error occurred in GetUserProjectRoles, returning false, error: %v", err)
|
||||||
|
@ -38,17 +38,36 @@ type searchResult struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get ...
|
// Get ...
|
||||||
func (n *SearchAPI) Get() {
|
func (s *SearchAPI) Get() {
|
||||||
userID, ok := n.GetSession("userId").(int)
|
userID, ok := s.GetSession("userId").(int)
|
||||||
if !ok {
|
if !ok {
|
||||||
userID = dao.NonExistUserID
|
userID = dao.NonExistUserID
|
||||||
}
|
}
|
||||||
keyword := n.GetString("q")
|
|
||||||
projects, err := dao.QueryRelevantProjects(userID)
|
keyword := s.GetString("q")
|
||||||
|
|
||||||
|
isSysAdmin, err := dao.IsAdminRole(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Failed to get projects of user id: %d, error: %v", userID, err)
|
log.Errorf("failed to check whether the user %d is system admin: %v", userID, err)
|
||||||
n.CustomAbort(http.StatusInternalServerError, "Failed to get project search result")
|
s.CustomAbort(http.StatusInternalServerError, "internal error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var projects []models.Project
|
||||||
|
|
||||||
|
if isSysAdmin {
|
||||||
|
projects, err = dao.GetAllProjects()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to get all projects: %v", err)
|
||||||
|
s.CustomAbort(http.StatusInternalServerError, "internal error")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
projects, err = dao.GetUserRelevantProjects(userID)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to get user %d 's relevant projects: %v", userID, err)
|
||||||
|
s.CustomAbort(http.StatusInternalServerError, "internal error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
projectSorter := &utils.ProjectSorter{Projects: projects}
|
projectSorter := &utils.ProjectSorter{Projects: projects}
|
||||||
sort.Sort(projectSorter)
|
sort.Sort(projectSorter)
|
||||||
projectResult := []map[string]interface{}{}
|
projectResult := []map[string]interface{}{}
|
||||||
@ -69,17 +88,17 @@ func (n *SearchAPI) Get() {
|
|||||||
repositories, err2 := svc_utils.GetRepoFromCache()
|
repositories, err2 := svc_utils.GetRepoFromCache()
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
log.Errorf("Failed to get repos from cache, error: %v", err2)
|
log.Errorf("Failed to get repos from cache, error: %v", err2)
|
||||||
n.CustomAbort(http.StatusInternalServerError, "Failed to get repositories search result")
|
s.CustomAbort(http.StatusInternalServerError, "Failed to get repositories search result")
|
||||||
}
|
}
|
||||||
sort.Strings(repositories)
|
sort.Strings(repositories)
|
||||||
repositoryResult := filterRepositories(repositories, projects, keyword)
|
repositoryResult := filterRepositories(repositories, projects, keyword)
|
||||||
result := &searchResult{Project: projectResult, Repository: repositoryResult}
|
result := &searchResult{Project: projectResult, Repository: repositoryResult}
|
||||||
n.Data["json"] = result
|
s.Data["json"] = result
|
||||||
n.ServeJSON()
|
s.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterRepositories(repositories []string, projects []models.Project, keyword string) []map[string]interface{} {
|
func filterRepositories(repositories []string, projects []models.Project, keyword string) []map[string]interface{} {
|
||||||
var i, j int = 0, 0
|
i, j := 0, 0
|
||||||
result := []map[string]interface{}{}
|
result := []map[string]interface{}{}
|
||||||
for i < len(repositories) && j < len(projects) {
|
for i < len(repositories) && j < len(projects) {
|
||||||
r := &utils.Repository{Name: repositories[i]}
|
r := &utils.Repository{Name: repositories[i]}
|
||||||
|
@ -351,7 +351,7 @@ func TestChangeUserPasswordWithIncorrectOldPassword(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestQueryRelevantProjectsWhenNoProjectAdded(t *testing.T) {
|
func TestQueryRelevantProjectsWhenNoProjectAdded(t *testing.T) {
|
||||||
projects, err := QueryRelevantProjects(currentUser.UserID)
|
projects, err := GetUserRelevantProjects(currentUser.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error occurred in QueryRelevantProjects: %v", err)
|
t.Errorf("Error occurred in QueryRelevantProjects: %v", err)
|
||||||
}
|
}
|
||||||
@ -629,10 +629,10 @@ func TestProjectPermission(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestQueryRelevantProjects(t *testing.T) {
|
func TestGetUserRelevantProjects(t *testing.T) {
|
||||||
projects, err := QueryRelevantProjects(currentUser.UserID)
|
projects, err := GetUserRelevantProjects(currentUser.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error occurred in QueryRelevantProjects: %v", err)
|
t.Errorf("Error occurred in GetUserRelevantProjects: %v", err)
|
||||||
}
|
}
|
||||||
if len(projects) != 2 {
|
if len(projects) != 2 {
|
||||||
t.Errorf("Expected length of relevant projects is 2, but actual: %d, the projects: %+v", len(projects), projects)
|
t.Errorf("Expected length of relevant projects is 2, but actual: %d, the projects: %+v", len(projects), projects)
|
||||||
@ -642,6 +642,19 @@ func TestQueryRelevantProjects(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetAllProjects(t *testing.T) {
|
||||||
|
projects, err := GetAllProjects()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error occurred in GetAllProjects: %v", err)
|
||||||
|
}
|
||||||
|
if len(projects) != 2 {
|
||||||
|
t.Errorf("Expected length of projects is 2, but actual: %d, the projects: %+v", len(projects), projects)
|
||||||
|
}
|
||||||
|
if projects[1].Name != projectName {
|
||||||
|
t.Errorf("Expected project name in the list: %s, actual: %s", projectName, projects[1].Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestAddProjectMember(t *testing.T) {
|
func TestAddProjectMember(t *testing.T) {
|
||||||
err := AddProjectMember(currentProject.ProjectID, 1, models.DEVELOPER)
|
err := AddProjectMember(currentProject.ProjectID, 1, models.DEVELOPER)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -208,18 +208,35 @@ func ToggleProjectPublicity(projectID int64, publicity int) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryRelevantProjects returns all projects that the user is a member of.
|
// GetUserRelevantProjects returns a project list,
|
||||||
func QueryRelevantProjects(userID int) ([]models.Project, error) {
|
// which satisfies the following conditions:
|
||||||
|
// 1. the project is not deleted
|
||||||
|
// 2. the prject is public or the user is a member of the project
|
||||||
|
func GetUserRelevantProjects(userID int) ([]models.Project, error) {
|
||||||
o := orm.NewOrm()
|
o := orm.NewOrm()
|
||||||
sql := `select distinct p.project_id, p.name, p.public
|
sql := `select distinct p.project_id, p.name, p.public
|
||||||
from project p
|
from project p
|
||||||
left join project_member pm on p.project_id = pm.project_id
|
left join project_member pm on p.project_id = pm.project_id
|
||||||
left join user u on u.user_id = pm.user_id
|
where (pm.user_id = ? or p.public = 1) and p.deleted = 0`
|
||||||
where u.user_id = ? or p.public = 1 and p.deleted = 0`
|
|
||||||
var res []models.Project
|
var projects []models.Project
|
||||||
_, err := o.Raw(sql, userID).QueryRows(&res)
|
|
||||||
if err != nil {
|
if _, err := o.Raw(sql, userID).QueryRows(&projects); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return res, err
|
|
||||||
|
return projects, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAllProjects returns all projects which are not deleted
|
||||||
|
func GetAllProjects() ([]models.Project, error) {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
sql := `select project_id, name, public
|
||||||
|
from project
|
||||||
|
where deleted = 0`
|
||||||
|
var projects []models.Project
|
||||||
|
if _, err := o.Raw(sql).QueryRows(&projects); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return projects, nil
|
||||||
}
|
}
|
||||||
|
15
dao/role.go
15
dao/role.go
@ -73,3 +73,18 @@ func IsAdminRole(userIDOrUsername interface{}) (bool, error) {
|
|||||||
|
|
||||||
return user.HasAdminRole == 1, nil
|
return user.HasAdminRole == 1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRoleByID ...
|
||||||
|
func GetRoleByID(id int) (*models.Role, error) {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
|
||||||
|
sql := `select *
|
||||||
|
from role
|
||||||
|
where role_id = ?`
|
||||||
|
|
||||||
|
var role models.Role
|
||||||
|
if err := o.Raw(sql, id).QueryRow(&role); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &role, nil
|
||||||
|
}
|
||||||
|
@ -207,7 +207,7 @@ $ rm -r /data/registry
|
|||||||
By default, the data of database and image files in the registry are persisted in the directory **/data/** of the target machine. When Harbor's containers are removed and recreated, the data remain unchanged. Harbor leverages rsyslog to collect the logs of each container, by default the log files are stored in the directory **/var/log/harbor/** on Harbor's host.
|
By default, the data of database and image files in the registry are persisted in the directory **/data/** of the target machine. When Harbor's containers are removed and recreated, the data remain unchanged. Harbor leverages rsyslog to collect the logs of each container, by default the log files are stored in the directory **/var/log/harbor/** on Harbor's host.
|
||||||
|
|
||||||
##Troubleshooting
|
##Troubleshooting
|
||||||
1.When setting up Harbor behind another nginx proxy or elastic load balancing, remove the below line if the proxy already has similar settings. Be sure to remove the line under these 3 sections: "location /", "location /v2/" and "location /service/".
|
1.When setting up Harbor behind another nginx proxy or elastic load balancing, remove the below line if the proxy already has similar settings. Be sure to edit Deploy/config/nginx/nginx.conf and remove the line under these 3 sections: "location /", "location /v2/" and "location /service/".
|
||||||
```
|
```
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
```
|
```
|
||||||
|
@ -574,7 +574,7 @@ paths:
|
|||||||
description: Retrieved tags from a relevant repository successfully.
|
description: Retrieved tags from a relevant repository successfully.
|
||||||
500:
|
500:
|
||||||
description: Unexpected internal errors.
|
description: Unexpected internal errors.
|
||||||
/repositories/manifest:
|
/repositories/manifests:
|
||||||
get:
|
get:
|
||||||
summary: Get manifests of a relevant repository.
|
summary: Get manifests of a relevant repository.
|
||||||
description: |
|
description: |
|
||||||
|
Loading…
Reference in New Issue
Block a user