mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-23 00:57:44 +01:00
merged from master
This commit is contained in:
commit
87e6166547
@ -10,27 +10,30 @@ create table access (
|
||||
primary key (access_id)
|
||||
);
|
||||
|
||||
insert into access values
|
||||
( null, 'A', 'All access for the system'),
|
||||
( null, 'M', 'Management access for project'),
|
||||
( null, 'R', 'Read access for project'),
|
||||
( null, 'W', 'Write access for project'),
|
||||
( null, 'D', 'Delete access for project'),
|
||||
( null, 'S', 'Search access for project');
|
||||
insert into access (access_code, comment) values
|
||||
('M', 'Management access for project'),
|
||||
('R', 'Read access for project'),
|
||||
('W', 'Write access for project'),
|
||||
('D', 'Delete access for project'),
|
||||
('S', 'Search access for project');
|
||||
|
||||
|
||||
create table role (
|
||||
role_id int NOT NULL AUTO_INCREMENT,
|
||||
role_mask int DEFAULT 0 NOT NULL,
|
||||
role_code varchar(20),
|
||||
name varchar (20),
|
||||
primary key (role_id)
|
||||
);
|
||||
/*
|
||||
role mask is used for future enhancement when a project member can have multi-roles
|
||||
currently set to 0
|
||||
*/
|
||||
|
||||
insert into role values
|
||||
( null, 'AMDRWS', 'sysAdmin'),
|
||||
( null, 'MDRWS', 'projectAdmin'),
|
||||
( null, 'RWS', 'developer'),
|
||||
( null, 'RS', 'guest');
|
||||
insert into role (role_code, name) values
|
||||
('MDRWS', 'projectAdmin'),
|
||||
('RWS', 'developer'),
|
||||
('RS', 'guest');
|
||||
|
||||
|
||||
create table user (
|
||||
@ -43,20 +46,24 @@ create table user (
|
||||
deleted tinyint (1) DEFAULT 0 NOT NULL,
|
||||
reset_uuid varchar(40) DEFAULT NULL,
|
||||
salt varchar(40) DEFAULT NULL,
|
||||
sysadmin_flag tinyint (1),
|
||||
creation_time timestamp,
|
||||
update_time timestamp,
|
||||
primary key (user_id),
|
||||
UNIQUE (username),
|
||||
UNIQUE (email)
|
||||
);
|
||||
|
||||
insert into user values
|
||||
(1, 'admin', 'admin@example.com', '', 'system admin', 'admin user',0, null, ''),
|
||||
(2, 'anonymous', 'anonymous@example.com', '', 'anonymous user', 'anonymous user', 1, null, '');
|
||||
insert into user (username, email, password, realname, comment, deleted, sysadmin_flag, creation_time, update_time) values
|
||||
('admin', 'admin@example.com', '', 'system admin', 'admin user',0, 1, NOW(), NOW()),
|
||||
('anonymous', 'anonymous@example.com', '', 'anonymous user', 'anonymous user', 1, 0, NOW(), NOW());
|
||||
|
||||
create table project (
|
||||
project_id int NOT NULL AUTO_INCREMENT,
|
||||
owner_id int NOT NULL,
|
||||
name varchar (30) NOT NULL,
|
||||
creation_time timestamp,
|
||||
update_time timestamp,
|
||||
deleted tinyint (1) DEFAULT 0 NOT NULL,
|
||||
public tinyint (1) DEFAULT 0 NOT NULL,
|
||||
primary key (project_id),
|
||||
@ -64,32 +71,23 @@ create table project (
|
||||
UNIQUE (name)
|
||||
);
|
||||
|
||||
insert into project values
|
||||
(null, 1, 'library', NOW(), 0, 1);
|
||||
insert into project (owner_id, name, creation_time, update_time, public) values
|
||||
(1, 'library', NOW(), NOW(), 1);
|
||||
|
||||
create table project_role (
|
||||
pr_id int NOT NULL AUTO_INCREMENT,
|
||||
create table project_member (
|
||||
project_id int NOT NULL,
|
||||
role_id int NOT NULL,
|
||||
primary key (pr_id),
|
||||
FOREIGN KEY (role_id) REFERENCES role(role_id),
|
||||
FOREIGN KEY (project_id) REFERENCES project (project_id)
|
||||
);
|
||||
|
||||
insert into project_role values
|
||||
( 1,1,1 );
|
||||
|
||||
create table user_project_role (
|
||||
upr_id int NOT NULL AUTO_INCREMENT,
|
||||
user_id int NOT NULL,
|
||||
pr_id int NOT NULL,
|
||||
primary key (upr_id),
|
||||
FOREIGN KEY (user_id) REFERENCES user(user_id),
|
||||
FOREIGN KEY (pr_id) REFERENCES project_role (pr_id)
|
||||
);
|
||||
role int NOT NULL,
|
||||
creation_time timestamp,
|
||||
update_time timestamp,
|
||||
PRIMARY KEY (project_id, user_id),
|
||||
FOREIGN KEY (role) REFERENCES role(role_id),
|
||||
FOREIGN KEY (project_id) REFERENCES project(project_id),
|
||||
FOREIGN KEY (user_id) REFERENCES user(user_id)
|
||||
);
|
||||
|
||||
insert into user_project_role values
|
||||
( 1,1,1 );
|
||||
insert into project_member (project_id, user_id, role, creation_time, update_time) values
|
||||
(1, 1, 1, NOW(), NOW());
|
||||
|
||||
create table access_log (
|
||||
log_id int NOT NULL AUTO_INCREMENT,
|
||||
|
@ -9,3 +9,4 @@ AUTH_MODE=$auth_mode
|
||||
LDAP_URL=$ldap_url
|
||||
LDAP_BASE_DN=$ldap_basedn
|
||||
SELF_REGISTRATION=$self_registration
|
||||
LOG_LEVEL=debug
|
||||
|
@ -92,7 +92,7 @@ func (pma *ProjectMemberAPI) Get() {
|
||||
}
|
||||
pma.Data["json"] = userList
|
||||
} else { //return detail of a member
|
||||
roleList, err := dao.GetUserProjectRoles(models.User{UserID: pma.memberID}, pid)
|
||||
roleList, err := dao.GetUserProjectRoles(pma.memberID, pid)
|
||||
if err != nil {
|
||||
log.Errorf("Error occurred in GetUserProjectRoles, error: %v", err)
|
||||
pma.CustomAbort(http.StatusInternalServerError, "Internal error.")
|
||||
@ -115,17 +115,26 @@ func (pma *ProjectMemberAPI) Get() {
|
||||
// Post ...
|
||||
func (pma *ProjectMemberAPI) Post() {
|
||||
pid := pma.project.ProjectID
|
||||
userQuery := models.User{UserID: pma.currentUserID, RoleID: models.PROJECTADMIN}
|
||||
rolelist, err := dao.GetUserProjectRoles(userQuery, pid)
|
||||
|
||||
//userQuery := models.User{UserID: pma.currentUserID, RoleID: models.PROJECTADMIN}
|
||||
rolelist, err := dao.GetUserProjectRoles(pma.currentUserID, pid)
|
||||
if err != nil {
|
||||
log.Errorf("Error occurred in GetUserProjectRoles, error: %v", err)
|
||||
pma.CustomAbort(http.StatusInternalServerError, "Internal error.")
|
||||
}
|
||||
if len(rolelist) == 0 {
|
||||
log.Warningf("Current user, id: %d does not have project admin role for project, id: %d", pma.currentUserID, pid)
|
||||
hasProjectAdminRole := false
|
||||
for _, role := range rolelist {
|
||||
if role.RoleID == models.PROJECTADMIN {
|
||||
hasProjectAdminRole = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !hasProjectAdminRole {
|
||||
log.Warningf("Current user, id: %d does not have project admin role for project, id:", pma.currentUserID, pid)
|
||||
pma.RenderError(http.StatusForbidden, "")
|
||||
return
|
||||
}
|
||||
|
||||
var req memberReq
|
||||
pma.DecodeJSONReq(&req)
|
||||
username := req.Username
|
||||
@ -135,7 +144,7 @@ func (pma *ProjectMemberAPI) Post() {
|
||||
pma.RenderError(http.StatusNotFound, "User does not exist")
|
||||
return
|
||||
}
|
||||
rolelist, err = dao.GetUserProjectRoles(models.User{UserID: userID}, pid)
|
||||
rolelist, err = dao.GetUserProjectRoles(userID, pid)
|
||||
if err != nil {
|
||||
log.Errorf("Error occurred in GetUserProjectRoles, error: %v", err)
|
||||
pma.CustomAbort(http.StatusInternalServerError, "Internal error.")
|
||||
@ -147,7 +156,7 @@ func (pma *ProjectMemberAPI) Post() {
|
||||
}
|
||||
|
||||
for _, rid := range req.Roles {
|
||||
err = dao.AddUserProjectRole(userID, pid, int(rid))
|
||||
err = dao.AddProjectMember(pid, userID, int(rid))
|
||||
if err != nil {
|
||||
log.Errorf("Failed to update DB to add project user role, project id: %d, user id: %d, role id: %d", pid, userID, rid)
|
||||
pma.RenderError(http.StatusInternalServerError, "Failed to update data in database")
|
||||
@ -160,20 +169,28 @@ func (pma *ProjectMemberAPI) Post() {
|
||||
func (pma *ProjectMemberAPI) Put() {
|
||||
pid := pma.project.ProjectID
|
||||
mid := pma.memberID
|
||||
userQuery := models.User{UserID: pma.currentUserID, RoleID: models.PROJECTADMIN}
|
||||
rolelist, err := dao.GetUserProjectRoles(userQuery, pid)
|
||||
|
||||
rolelist, err := dao.GetUserProjectRoles(pma.currentUserID, pid)
|
||||
if err != nil {
|
||||
log.Errorf("Error occurred in GetUserProjectRoles, error: %v", err)
|
||||
pma.CustomAbort(http.StatusInternalServerError, "Internal error.")
|
||||
}
|
||||
if len(rolelist) == 0 {
|
||||
hasProjectAdminRole := false
|
||||
for _, role := range rolelist {
|
||||
if role.RoleID == models.PROJECTADMIN {
|
||||
hasProjectAdminRole = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !hasProjectAdminRole {
|
||||
log.Warningf("Current user, id: %d does not have project admin role for project, id: %d", pma.currentUserID, pid)
|
||||
pma.RenderError(http.StatusForbidden, "")
|
||||
return
|
||||
}
|
||||
var req memberReq
|
||||
pma.DecodeJSONReq(&req)
|
||||
roleList, err := dao.GetUserProjectRoles(models.User{UserID: mid}, pid)
|
||||
roleList, err := dao.GetUserProjectRoles(mid, pid)
|
||||
if len(roleList) == 0 {
|
||||
log.Warningf("User is not in project, user id: %d, project id: %d", mid, pid)
|
||||
pma.RenderError(http.StatusNotFound, "user not exist in project")
|
||||
@ -181,7 +198,7 @@ func (pma *ProjectMemberAPI) Put() {
|
||||
}
|
||||
//TODO: delete and insert should in one transaction
|
||||
//delete user project role record for the given user
|
||||
err = dao.DeleteUserProjectRoles(mid, pid)
|
||||
err = dao.DeleteProjectMember(pid, mid)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to delete project roles for user, user id: %d, project id: %d, error: %v", mid, pid, err)
|
||||
pma.RenderError(http.StatusInternalServerError, "Failed to update data in DB")
|
||||
@ -189,7 +206,7 @@ func (pma *ProjectMemberAPI) Put() {
|
||||
}
|
||||
//insert roles in request
|
||||
for _, rid := range req.Roles {
|
||||
err = dao.AddUserProjectRole(mid, pid, int(rid))
|
||||
err = dao.AddProjectMember(pid, mid, int(rid))
|
||||
if err != nil {
|
||||
log.Errorf("Failed to update DB to add project user role, project id: %d, user id: %d, role id: %d", pid, mid, rid)
|
||||
pma.RenderError(http.StatusInternalServerError, "Failed to update data in database")
|
||||
@ -202,14 +219,22 @@ func (pma *ProjectMemberAPI) Put() {
|
||||
func (pma *ProjectMemberAPI) Delete() {
|
||||
pid := pma.project.ProjectID
|
||||
mid := pma.memberID
|
||||
userQuery := models.User{UserID: pma.currentUserID, RoleID: models.PROJECTADMIN}
|
||||
rolelist, err := dao.GetUserProjectRoles(userQuery, pid)
|
||||
if len(rolelist) == 0 {
|
||||
|
||||
rolelist, err := dao.GetUserProjectRoles(pma.currentUserID, pid)
|
||||
hasProjectAdminRole := false
|
||||
for _, role := range rolelist {
|
||||
if role.RoleID == models.PROJECTADMIN {
|
||||
hasProjectAdminRole = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !hasProjectAdminRole {
|
||||
log.Warningf("Current user, id: %d does not have project admin role for project, id: %d", pma.currentUserID, pid)
|
||||
pma.RenderError(http.StatusForbidden, "")
|
||||
return
|
||||
}
|
||||
err = dao.DeleteUserProjectRoles(mid, pid)
|
||||
err = dao.DeleteProjectMember(pid, mid)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to delete project roles for user, user id: %d, project id: %d, error: %v", mid, pid, err)
|
||||
pma.RenderError(http.StatusInternalServerError, "Failed to update data in DB")
|
||||
|
@ -187,13 +187,21 @@ func (p *ProjectAPI) FilterAccessLog() {
|
||||
}
|
||||
|
||||
func isProjectAdmin(userID int, pid int64) bool {
|
||||
userQuery := models.User{UserID: userID, RoleID: models.PROJECTADMIN}
|
||||
rolelist, err := dao.GetUserProjectRoles(userQuery, pid)
|
||||
rolelist, err := dao.GetUserProjectRoles(userID, pid)
|
||||
if err != nil {
|
||||
log.Errorf("Error occurred in GetUserProjectRoles, returning false, error: %v", err)
|
||||
return false
|
||||
}
|
||||
return len(rolelist) > 0
|
||||
|
||||
hasProjectAdminRole := false
|
||||
for _, role := range rolelist {
|
||||
if role.RoleID == models.PROJECTADMIN {
|
||||
hasProjectAdminRole = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return hasProjectAdminRole
|
||||
}
|
||||
|
||||
func validateProjectReq(req projectReq) error {
|
||||
|
@ -30,7 +30,7 @@ func checkProjectPermission(userID int, projectID int64) bool {
|
||||
if exist {
|
||||
return true
|
||||
}
|
||||
roleList, err := dao.GetUserProjectRoles(models.User{UserID: userID}, projectID)
|
||||
roleList, err := dao.GetUserProjectRoles(userID, projectID)
|
||||
if err != nil {
|
||||
log.Errorf("Error occurred in GetUserProjectRoles, error: %v", err)
|
||||
return false
|
||||
|
@ -22,7 +22,6 @@ import (
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/beego/i18n"
|
||||
"github.com/vmware/harbor/models"
|
||||
)
|
||||
|
||||
// CommonController handles request from UI that doesn't expect a page, such as /login /logout ...
|
||||
@ -48,6 +47,7 @@ type langType struct {
|
||||
|
||||
const (
|
||||
defaultLang = "en-US"
|
||||
adminUserID = 1
|
||||
)
|
||||
|
||||
var supportLanguages map[string]langType
|
||||
@ -110,7 +110,7 @@ func (b *BaseController) Prepare() {
|
||||
|
||||
switch selfRegistration {
|
||||
case "on":
|
||||
if sessionUserID != nil && sessionUserID.(int) != models.SYSADMIN {
|
||||
if sessionUserID != nil && sessionUserID.(int) != adminUserID {
|
||||
enableAddUserByAdmin = false
|
||||
} else {
|
||||
enableAddUserByAdmin = true
|
||||
|
@ -21,7 +21,6 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/vmware/harbor/dao"
|
||||
"github.com/vmware/harbor/models"
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
)
|
||||
@ -69,7 +68,7 @@ func (idc *ItemDetailController) Get() {
|
||||
idc.Data["Username"] = idc.GetSession("username")
|
||||
idc.Data["UserId"] = userID
|
||||
|
||||
roleList, err := dao.GetUserProjectRoles(models.User{UserID: userID}, projectID)
|
||||
roleList, err := dao.GetUserProjectRoles(userID, projectID)
|
||||
if err != nil {
|
||||
beego.Error("Error occurred in GetUserProjectRoles:", err)
|
||||
idc.CustomAbort(http.StatusInternalServerError, "Internal error.")
|
||||
@ -86,9 +85,7 @@ func (idc *ItemDetailController) Get() {
|
||||
return
|
||||
}
|
||||
|
||||
if isAdmin {
|
||||
idc.Data["RoleId"] = models.SYSADMIN
|
||||
} else if len(roleList) > 0 {
|
||||
if len(roleList) > 0 {
|
||||
idc.Data["RoleId"] = roleList[0].RoleID
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ func (rc *RegisterController) Get() {
|
||||
|
||||
if enableAddUserByAdmin {
|
||||
sessionUserID := rc.GetSession("userId")
|
||||
if sessionUserID == nil || sessionUserID.(int) != models.SYSADMIN {
|
||||
if sessionUserID == nil || sessionUserID.(int) != adminUserID {
|
||||
log.Error("Self registration can only be used by admin user.\n")
|
||||
rc.Redirect("/signIn", http.StatusFound)
|
||||
}
|
||||
@ -60,7 +60,7 @@ func (rc *CommonController) SignUp() {
|
||||
|
||||
if enableAddUserByAdmin {
|
||||
sessionUserID := rc.GetSession("userId")
|
||||
if sessionUserID == nil || sessionUserID.(int) != models.SYSADMIN {
|
||||
if sessionUserID == nil || sessionUserID.(int) != adminUserID {
|
||||
log.Error("Self registration can only be used by admin user.\n")
|
||||
rc.Redirect("/signIn", http.StatusFound)
|
||||
}
|
||||
|
@ -16,9 +16,10 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net"
|
||||
|
||||
"github.com/vmware/harbor/utils/log"
|
||||
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
@ -88,7 +89,7 @@ func InitDB() {
|
||||
c.Close()
|
||||
ch <- 1
|
||||
} else {
|
||||
log.Printf("failed to connect to db, retry after 2 seconds...")
|
||||
log.Info("failed to connect to db, retry after 2 seconds...")
|
||||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
}
|
||||
|
165
dao/dao_test.go
165
dao/dao_test.go
@ -16,12 +16,12 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/vmware/harbor/utils/log"
|
||||
|
||||
"github.com/vmware/harbor/models"
|
||||
|
||||
"github.com/astaxie/beego/orm"
|
||||
@ -41,44 +41,61 @@ func execUpdate(o orm.Ormer, sql string, params interface{}) error {
|
||||
}
|
||||
|
||||
func clearUp(username string) {
|
||||
var err error
|
||||
|
||||
o := orm.NewOrm()
|
||||
o.Begin()
|
||||
err := execUpdate(o, `delete upr from user_project_role upr
|
||||
left join project_role pr on upr.pr_id = pr.pr_id
|
||||
left join project p on pr.project_id = p.project_id
|
||||
left join user u on u.user_id = p.owner_id
|
||||
where u.username = ?`, username)
|
||||
|
||||
err = execUpdate(o, `delete pm
|
||||
from project_member pm
|
||||
join user u
|
||||
on pm.user_id = u.user_id
|
||||
where u.username = ?`, username)
|
||||
if err != nil {
|
||||
o.Rollback()
|
||||
log.Println(err)
|
||||
log.Error(err)
|
||||
}
|
||||
err = execUpdate(o, `delete pr from project_role pr
|
||||
left join project p on pr.project_id = p.project_id
|
||||
left join user u on u.user_id = p.owner_id
|
||||
where u.username = ?`, username)
|
||||
|
||||
err = execUpdate(o, `delete pm
|
||||
from project_member pm
|
||||
join project p
|
||||
on pm.project_id = p.project_id
|
||||
where p.name = ?`, projectName)
|
||||
if err != nil {
|
||||
o.Rollback()
|
||||
log.Println(err)
|
||||
log.Error(err)
|
||||
}
|
||||
err = execUpdate(o, `delete a from access_log a
|
||||
left join user u on a.user_id = u.user_id
|
||||
where u.username = ?`, username)
|
||||
|
||||
err = execUpdate(o, `delete al
|
||||
from access_log al
|
||||
join user u
|
||||
on al.user_id = u.user_id
|
||||
where u.username = ?`, username)
|
||||
if err != nil {
|
||||
o.Rollback()
|
||||
log.Println(err)
|
||||
log.Error(err)
|
||||
}
|
||||
err = execUpdate(o, `delete p from project p
|
||||
left join user u on p.owner_id = u.user_id
|
||||
where u.username = ?`, username)
|
||||
|
||||
err = execUpdate(o, `delete al
|
||||
from access_log al
|
||||
join project p
|
||||
on al.project_id = p.project_id
|
||||
where p.name = ?`, projectName)
|
||||
if err != nil {
|
||||
o.Rollback()
|
||||
log.Println(err)
|
||||
log.Error(err)
|
||||
}
|
||||
err = execUpdate(o, `delete u from user u
|
||||
where u.username = ?`, username)
|
||||
|
||||
err = execUpdate(o, `delete from project where name = ?`, projectName)
|
||||
if err != nil {
|
||||
o.Rollback()
|
||||
log.Println(err)
|
||||
log.Error(err)
|
||||
}
|
||||
|
||||
err = execUpdate(o, `delete from user where username = ?`, username)
|
||||
if err != nil {
|
||||
o.Rollback()
|
||||
log.Error(err)
|
||||
}
|
||||
o.Commit()
|
||||
}
|
||||
@ -109,7 +126,7 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
dbPassword := os.Getenv("DB_PWD")
|
||||
|
||||
fmt.Printf("DB_HOST: %s, DB_USR: %s, DB_PORT: %s, DB_PWD: %s\n", dbHost, dbUser, dbPort, dbPassword)
|
||||
log.Infof("DB_HOST: %s, DB_USR: %s, DB_PORT: %s, DB_PWD: %s\n", dbHost, dbUser, dbPort, dbPassword)
|
||||
|
||||
os.Setenv("MYSQL_PORT_3306_TCP_ADDR", dbHost)
|
||||
os.Setenv("MYSQL_PORT_3306_TCP_PORT", dbPort)
|
||||
@ -379,32 +396,6 @@ func TestGetProject(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func getProjectRole(projectID int64) []models.Role {
|
||||
o := orm.NewOrm()
|
||||
var r []models.Role
|
||||
_, err := o.Raw(`select r.role_id, r.name
|
||||
from project_role pr
|
||||
left join role r on pr.role_id = r.role_id
|
||||
where project_id = ?`, projectID).QueryRows(&r)
|
||||
if err != nil {
|
||||
log.Printf("Error occurred in querying project_role: %v", err)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func TestCheckProjectRoles(t *testing.T) {
|
||||
r := getProjectRole(currentProject.ProjectID)
|
||||
if len(r) != 3 {
|
||||
t.Errorf("The length of project roles is not 3")
|
||||
}
|
||||
if r[1].RoleID != 3 {
|
||||
t.Errorf("The role id does not match, expected: 3, acutal: %d", r[1].RoleID)
|
||||
}
|
||||
if r[1].Name != "developer" {
|
||||
t.Errorf("The name of role id: 3 should be developer, actual:%s", r[1].Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAccessLog(t *testing.T) {
|
||||
queryAccessLog := models.AccessLog{
|
||||
UserID: currentUser.UserID,
|
||||
@ -546,25 +537,10 @@ func TestQueryProject(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func getUserProjectRole(projectID int64, userID int) []models.Role {
|
||||
o := orm.NewOrm()
|
||||
var r []models.Role
|
||||
_, err := o.Raw(`select r.role_id, r.name
|
||||
from user_project_role upr
|
||||
left join project_role pr on upr.pr_id = pr.pr_id
|
||||
left join role r on r.role_id = pr.role_id
|
||||
where pr.project_id = ? and upr.user_id = ?`, projectID, userID).QueryRows(&r)
|
||||
if err != nil {
|
||||
log.Fatalf("Error occurred in querying user_project_role: %v", err)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func TestGetUserProjectRoles(t *testing.T) {
|
||||
user := *currentUser
|
||||
r, err := GetUserProjectRoles(user, currentProject.ProjectID)
|
||||
r, err := GetUserProjectRoles(currentUser.UserID, currentProject.ProjectID)
|
||||
if err != nil {
|
||||
t.Errorf("Error happened in GetUserProjectRole: %v, user: %+v, project Id: %d", err, user, currentProject.ProjectID)
|
||||
t.Errorf("Error happened in GetUserProjectRole: %v, userID: %+v, project Id: %d", err, currentUser.UserID, currentProject.ProjectID)
|
||||
}
|
||||
|
||||
//Get the size of current user project role.
|
||||
@ -575,16 +551,6 @@ func TestGetUserProjectRoles(t *testing.T) {
|
||||
if r[0].Name != "projectAdmin" {
|
||||
t.Errorf("the expected rolename is: projectAdmin, actual: %s", r[0].Name)
|
||||
}
|
||||
user.RoleID = 1
|
||||
|
||||
r, err = GetUserProjectRoles(user, currentProject.ProjectID)
|
||||
if err != nil {
|
||||
t.Errorf("Error happened in GetUserProjectRole: %v, user: %+v, project Id: %d", err, user, currentProject.ProjectID)
|
||||
}
|
||||
//Get the size of current user project role.
|
||||
if len(r) != 0 {
|
||||
t.Errorf("The user, id: %d, should not have role id: 1 in project id: %d, actual role list: %v", currentUser.UserID, currentProject.ProjectID, r)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProjectPermission(t *testing.T) {
|
||||
@ -610,34 +576,43 @@ func TestQueryRelevantProjects(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAssignUserProjectRole(t *testing.T) {
|
||||
err := AddUserProjectRole(currentUser.UserID, currentProject.ProjectID, developer)
|
||||
func TestAddProjectMember(t *testing.T) {
|
||||
err := AddProjectMember(currentProject.ProjectID, 1, models.DEVELOPER)
|
||||
if err != nil {
|
||||
t.Errorf("Error occurred in AddUserProjectRole: %v", err)
|
||||
t.Errorf("Error occurred in AddProjectMember: %v", err)
|
||||
}
|
||||
|
||||
r := getUserProjectRole(currentProject.ProjectID, currentUser.UserID)
|
||||
|
||||
//Get the size of current user project role info.
|
||||
if len(r) != 2 {
|
||||
t.Errorf("Expected length of role list is 2, actual: %d", len(r))
|
||||
roles, err := GetUserProjectRoles(1, currentProject.ProjectID)
|
||||
if err != nil {
|
||||
t.Errorf("Error occurred in GetUserProjectRoles: %v", err)
|
||||
}
|
||||
|
||||
if r[1].RoleID != 3 {
|
||||
t.Errorf("Expected role id of the second role in list is 3, actual: %d", r[1].RoleID)
|
||||
flag := false
|
||||
for _, role := range roles {
|
||||
if role.Name == "developer" {
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !flag {
|
||||
t.Errorf("the user which ID is 1 does not have developer privileges")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteUserProjectRole(t *testing.T) {
|
||||
err := DeleteUserProjectRoles(currentUser.UserID, currentProject.ProjectID)
|
||||
func TestDeleteProjectMember(t *testing.T) {
|
||||
err := DeleteProjectMember(currentProject.ProjectID, 1)
|
||||
if err != nil {
|
||||
t.Errorf("Error occurred in DeleteUserProjectRoles: %v", err)
|
||||
t.Errorf("Error occurred in DeleteProjectMember: %v", err)
|
||||
}
|
||||
|
||||
r := getUserProjectRole(currentProject.ProjectID, currentUser.UserID)
|
||||
//Get the size of current user project role.
|
||||
if len(r) != 0 {
|
||||
t.Errorf("Expected role list length is 0, actual: %d, role list: %+v", len(r), r)
|
||||
roles, err := GetUserProjectRoles(1, currentProject.ProjectID)
|
||||
if err != nil {
|
||||
t.Errorf("Error occurred in GetUserProjectRoles: %v", err)
|
||||
}
|
||||
|
||||
if len(roles) != 0 {
|
||||
t.Errorf("delete record failed from table project_member")
|
||||
}
|
||||
}
|
||||
|
||||
|
100
dao/project.go
100
dao/project.go
@ -22,8 +22,8 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/astaxie/beego/orm"
|
||||
"github.com/vmware/harbor/utils/log"
|
||||
)
|
||||
|
||||
//TODO:transaction, return err
|
||||
@ -40,12 +40,13 @@ func AddProject(project models.Project) error {
|
||||
|
||||
o := orm.NewOrm()
|
||||
|
||||
p, err := o.Raw("insert into project (owner_id, name, creation_time, deleted, public) values (?, ?, now(), ?, ?)").Prepare()
|
||||
p, err := o.Raw("insert into project (owner_id, name, creation_time, update_time, deleted, public) values (?, ?, ?, ?, ?, ?)").Prepare()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r, err := p.Exec(project.OwnerID, project.Name, project.Deleted, project.Public)
|
||||
now := time.Now()
|
||||
r, err := p.Exec(project.OwnerID, project.Name, now, now, project.Deleted, project.Public)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -55,27 +56,7 @@ func AddProject(project models.Project) error {
|
||||
return err
|
||||
}
|
||||
|
||||
projectAdminRole := models.ProjectRole{ProjectID: projectID, RoleID: models.PROJECTADMIN}
|
||||
_, err = AddProjectRole(projectAdminRole)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
projectDeveloperRole := models.ProjectRole{ProjectID: projectID, RoleID: models.DEVELOPER}
|
||||
_, err = AddProjectRole(projectDeveloperRole)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
projectGuestRole := models.ProjectRole{ProjectID: projectID, RoleID: models.GUEST}
|
||||
_, err = AddProjectRole(projectGuestRole)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//Add all project roles, after that when assigning a user to a project just update the upr table
|
||||
err = AddUserProjectRole(project.OwnerID, projectID, models.PROJECTADMIN)
|
||||
if err != nil {
|
||||
if err = AddProjectMember(projectID, project.OwnerID, models.PROJECTADMIN); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -89,7 +70,7 @@ func AddProject(project models.Project) error {
|
||||
func IsProjectPublic(projectName string) bool {
|
||||
project, err := GetProjectByName(projectName)
|
||||
if err != nil {
|
||||
beego.Error("Error occurred in GetProjectByName:", err)
|
||||
log.Errorf("Error occurred in GetProjectByName: %v", err)
|
||||
return false
|
||||
}
|
||||
if project == nil {
|
||||
@ -103,11 +84,9 @@ func QueryProject(query models.Project) ([]models.Project, error) {
|
||||
o := orm.NewOrm()
|
||||
|
||||
sql := `select distinct
|
||||
p.project_id, p.owner_id, p.name,p.creation_time, p.public
|
||||
p.project_id, p.owner_id, p.name,p.creation_time, p.update_time, p.public
|
||||
from project p
|
||||
left join project_role pr on p.project_id = pr.project_id
|
||||
left join user_project_role upr on upr.pr_id = pr.pr_id
|
||||
left join user u on u.user_id = upr.user_id
|
||||
left join project_member pm on p.project_id = pm.project_id
|
||||
where p.deleted = 0 `
|
||||
|
||||
queryParam := make([]interface{}, 1)
|
||||
@ -116,8 +95,7 @@ func QueryProject(query models.Project) ([]models.Project, error) {
|
||||
sql += ` and p.public = ?`
|
||||
queryParam = append(queryParam, query.Public)
|
||||
} else if isAdmin, _ := IsAdminRole(query.UserID); isAdmin == false {
|
||||
sql += ` and (p.owner_id = ? or u.user_id = ?) `
|
||||
queryParam = append(queryParam, query.UserID)
|
||||
sql += ` and (pm.user_id = ?) `
|
||||
queryParam = append(queryParam, query.UserID)
|
||||
}
|
||||
|
||||
@ -161,60 +139,65 @@ func ProjectExists(nameOrID interface{}) (bool, error) {
|
||||
}
|
||||
|
||||
// GetProjectByID ...
|
||||
func GetProjectByID(projectID int64) (*models.Project, error) {
|
||||
func GetProjectByID(id int64) (*models.Project, error) {
|
||||
o := orm.NewOrm()
|
||||
|
||||
sql := `select p.project_id, p.name, u.username as owner_name, p.owner_id, p.creation_time, p.public
|
||||
sql := `select p.project_id, p.name, u.username as owner_name, p.owner_id, p.creation_time, p.update_time, p.public
|
||||
from project p left join user u on p.owner_id = u.user_id where p.deleted = 0 and p.project_id = ?`
|
||||
queryParam := make([]interface{}, 1)
|
||||
queryParam = append(queryParam, projectID)
|
||||
queryParam = append(queryParam, id)
|
||||
|
||||
p := []models.Project{}
|
||||
count, err := o.Raw(sql, queryParam).QueryRows(&p)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if count == 0 {
|
||||
return nil, nil
|
||||
} else {
|
||||
return &p[0], nil
|
||||
}
|
||||
|
||||
if count == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return &p[0], nil
|
||||
}
|
||||
|
||||
// GetProjectByName ...
|
||||
func GetProjectByName(projectName string) (*models.Project, error) {
|
||||
func GetProjectByName(name string) (*models.Project, error) {
|
||||
o := orm.NewOrm()
|
||||
var p []models.Project
|
||||
n, err := o.Raw(`select project_id, owner_id, name, deleted, public from project where name = ? and deleted = 0`, projectName).QueryRows(&p)
|
||||
n, err := o.Raw(`select * from project where name = ? and deleted = 0`, name).QueryRows(&p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if n == 0 {
|
||||
return nil, nil
|
||||
} else {
|
||||
return &p[0], nil
|
||||
}
|
||||
|
||||
if n == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return &p[0], nil
|
||||
}
|
||||
|
||||
// GetPermission gets roles that the user has according to the project.
|
||||
func GetPermission(username, projectName string) (string, error) {
|
||||
o := orm.NewOrm()
|
||||
|
||||
sql := "select r.role_code from role as r " +
|
||||
"inner join project_role as pr on r.role_id = pr.role_id " +
|
||||
"inner join user_project_role as ur on pr.pr_id = ur.pr_id " +
|
||||
"inner join user as u on u.user_id = ur.user_id " +
|
||||
"inner join project p on p.project_id = pr.project_id " +
|
||||
"where u.username = ? and p.name = ? and u.deleted = 0 and p.deleted = 0"
|
||||
sql := `select r.role_code from role as r
|
||||
inner join project_member as pm on r.role_id = pm.role
|
||||
inner join user as u on u.user_id = pm.user_id
|
||||
inner join project p on p.project_id = pm.project_id
|
||||
where u.username = ? and p.name = ? and u.deleted = 0 and p.deleted = 0`
|
||||
|
||||
var r []models.Role
|
||||
n, err := o.Raw(sql, username, projectName).QueryRows(&r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else if n == 0 {
|
||||
return "", nil
|
||||
} else {
|
||||
return r[0].RoleCode, nil
|
||||
}
|
||||
|
||||
if n == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return r[0].RoleCode, nil
|
||||
}
|
||||
|
||||
// ToggleProjectPublicity toggles the publicity of the project.
|
||||
@ -228,10 +211,11 @@ func ToggleProjectPublicity(projectID int64, publicity int) error {
|
||||
// QueryRelevantProjects returns all projects that the user is a member of.
|
||||
func QueryRelevantProjects(userID int) ([]models.Project, error) {
|
||||
o := orm.NewOrm()
|
||||
sql := `SELECT distinct p.project_id, p.name, p.public FROM registry.project p
|
||||
left join project_role pr on p.project_id = pr.project_id
|
||||
left join user_project_role upr on upr.pr_id = pr.pr_id
|
||||
where upr.user_id = ? or p.public = 1 and p.deleted = 0`
|
||||
sql := `select distinct p.project_id, p.name, p.public
|
||||
from project p
|
||||
left join project_member pm on p.project_id = pm.project_id
|
||||
left join user u on u.user_id = pm.user_id
|
||||
where u.user_id = ? or p.public = 1 and p.deleted = 0`
|
||||
var res []models.Project
|
||||
_, err := o.Raw(sql, userID).QueryRows(&res)
|
||||
if err != nil {
|
||||
|
@ -16,25 +16,56 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"github.com/vmware/harbor/models"
|
||||
|
||||
"github.com/astaxie/beego/orm"
|
||||
"github.com/vmware/harbor/models"
|
||||
)
|
||||
|
||||
// AddProjectMember inserts a record to table project_member
|
||||
func AddProjectMember(projectID int64, userID int, role int) error {
|
||||
o := orm.NewOrm()
|
||||
|
||||
sql := "insert into project_member (project_id, user_id , role) values (?, ?, ?)"
|
||||
|
||||
_, err := o.Raw(sql, projectID, userID, role).Exec()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateProjectMember updates the record in table project_member
|
||||
func UpdateProjectMember(projectID int64, userID int, role int) error {
|
||||
o := orm.NewOrm()
|
||||
|
||||
sql := "update project_member set role = ? where project_id = ? and user_id = ?"
|
||||
|
||||
_, err := o.Raw(sql, role, projectID, userID).Exec()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteProjectMember delete the record from table project_member
|
||||
func DeleteProjectMember(projectID int64, userID int) error {
|
||||
o := orm.NewOrm()
|
||||
|
||||
sql := "delete from project_member where project_id = ? and user_id = ?"
|
||||
|
||||
if _, err := o.Raw(sql, projectID, userID).Exec(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetUserByProject gets all members of the project.
|
||||
func GetUserByProject(projectID int64, queryUser models.User) ([]models.User, error) {
|
||||
o := orm.NewOrm()
|
||||
u := []models.User{}
|
||||
sql := `select
|
||||
u.user_id, u.username, r.name rolename, r.role_id
|
||||
from user u left join user_project_role upr
|
||||
on u.user_id = upr.user_id
|
||||
left join project_role pr
|
||||
on pr.pr_id = upr.pr_id
|
||||
left join role r
|
||||
on r.role_id = pr.role_id
|
||||
where u.deleted = 0
|
||||
and pr.project_id = ? `
|
||||
sql := `select u.user_id, u.username, r.name rolename, r.role_id
|
||||
from user u
|
||||
join project_member pm
|
||||
on pm.project_id = ? and u.user_id = pm.user_id
|
||||
join role r
|
||||
on pm.role = r.role_id
|
||||
where u.deleted = 0`
|
||||
|
||||
queryParam := make([]interface{}, 1)
|
||||
queryParam = append(queryParam, projectID)
|
@ -1,93 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2016 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 dao
|
||||
|
||||
import (
|
||||
"github.com/vmware/harbor/models"
|
||||
|
||||
"github.com/astaxie/beego/orm"
|
||||
)
|
||||
|
||||
// AddProjectRole ...
|
||||
func AddProjectRole(projectRole models.ProjectRole) (int64, error) {
|
||||
o := orm.NewOrm()
|
||||
p, err := o.Raw("insert into project_role (project_id, role_id) values (?, ?)").Prepare()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer p.Close()
|
||||
r, err := p.Exec(projectRole.ProjectID, projectRole.RoleID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
id, err := r.LastInsertId()
|
||||
return id, err
|
||||
}
|
||||
|
||||
// AddUserProjectRole inserts role information to table project_role and user_project_role.
|
||||
func AddUserProjectRole(userID int, projectID int64, roleID int) error {
|
||||
|
||||
o := orm.NewOrm()
|
||||
|
||||
var pr []models.ProjectRole
|
||||
|
||||
var prID int
|
||||
|
||||
sql := `select pr.pr_id, pr.project_id, pr.role_id from project_role pr where pr.project_id = ? and pr.role_id = ?`
|
||||
n, err := o.Raw(sql, projectID, roleID).QueryRows(&pr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if n == 0 { //project role not found, insert a pr record
|
||||
p, err := o.Raw("insert into project_role (project_id, role_id) values (?, ?)").Prepare()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer p.Close()
|
||||
r, err := p.Exec(projectID, roleID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
id, err := r.LastInsertId()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
prID = int(id)
|
||||
} else if n > 0 {
|
||||
prID = pr[0].PrID
|
||||
}
|
||||
p, err := o.Raw("insert into user_project_role (user_id, pr_id) values (?, ?)").Prepare()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer p.Close()
|
||||
_, err = p.Exec(userID, prID)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteUserProjectRoles ...
|
||||
func DeleteUserProjectRoles(userID int, projectID int64) error {
|
||||
o := orm.NewOrm()
|
||||
sql := `delete from user_project_role where user_id = ? and pr_id in
|
||||
(select pr_id from project_role where project_id = ?)`
|
||||
p, err := o.Raw(sql).Prepare()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = p.Exec(userID, projectID)
|
||||
return err
|
||||
}
|
@ -18,6 +18,7 @@ package dao
|
||||
import (
|
||||
"errors"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/vmware/harbor/models"
|
||||
"github.com/vmware/harbor/utils"
|
||||
@ -34,7 +35,8 @@ func Register(user models.User) (int64, error) {
|
||||
}
|
||||
|
||||
o := orm.NewOrm()
|
||||
p, err := o.Raw("insert into user (username, password, realname, email, comment, salt) values (?, ?, ?, ?, ?, ?)").Prepare()
|
||||
|
||||
p, err := o.Raw("insert into user (username, password, realname, email, comment, salt, sysadmin_flag, creation_time, update_time) values (?, ?, ?, ?, ?, ?, ?, ?, ?)").Prepare()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -45,7 +47,8 @@ func Register(user models.User) (int64, error) {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
r, err := p.Exec(user.Username, utils.Encrypt(user.Password, salt), user.Realname, user.Email, user.Comment, salt)
|
||||
now := time.Now()
|
||||
r, err := p.Exec(user.Username, utils.Encrypt(user.Password, salt), user.Realname, user.Email, user.Comment, salt, user.HasAdminRole, now, now)
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
59
dao/role.go
59
dao/role.go
@ -16,37 +16,28 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"github.com/vmware/harbor/models"
|
||||
"fmt"
|
||||
|
||||
"github.com/astaxie/beego/orm"
|
||||
"github.com/vmware/harbor/models"
|
||||
)
|
||||
|
||||
// GetUserProjectRoles returns roles that the user has according to the project.
|
||||
func GetUserProjectRoles(userQuery models.User, projectID int64) ([]models.Role, error) {
|
||||
func GetUserProjectRoles(userID int, projectID int64) ([]models.Role, error) {
|
||||
|
||||
o := orm.NewOrm()
|
||||
|
||||
sql := `select distinct r.role_id, r.role_code, r.name
|
||||
from role r
|
||||
left join project_role pr on r.role_id = pr.role_id
|
||||
left join user_project_role upr on pr.pr_id = upr.pr_id
|
||||
left join user u on u.user_id = upr.user_id
|
||||
where u.deleted = 0
|
||||
and u.user_id = ? `
|
||||
queryParam := make([]interface{}, 1)
|
||||
queryParam = append(queryParam, userQuery.UserID)
|
||||
|
||||
if projectID > 0 {
|
||||
sql += ` and pr.project_id = ? `
|
||||
queryParam = append(queryParam, projectID)
|
||||
}
|
||||
if userQuery.RoleID > 0 {
|
||||
sql += ` and r.role_id = ? `
|
||||
queryParam = append(queryParam, userQuery.RoleID)
|
||||
}
|
||||
sql := `select *
|
||||
from role
|
||||
where role_id =
|
||||
(
|
||||
select role
|
||||
from project_member
|
||||
where project_id = ? and user_id = ?
|
||||
)`
|
||||
|
||||
var roleList []models.Role
|
||||
_, err := o.Raw(sql, queryParam).QueryRows(&roleList)
|
||||
_, err := o.Raw(sql, projectID, userID).QueryRows(&roleList)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -54,13 +45,27 @@ func GetUserProjectRoles(userQuery models.User, projectID int64) ([]models.Role,
|
||||
return roleList, nil
|
||||
}
|
||||
|
||||
// IsAdminRole returns whether the user is admin.
|
||||
func IsAdminRole(userID int) (bool, error) {
|
||||
//role_id == 1 means the user is system admin
|
||||
userQuery := models.User{UserID: userID, RoleID: models.SYSADMIN}
|
||||
adminRoleList, err := GetUserProjectRoles(userQuery, 0)
|
||||
// IsAdminRole returns whether the user is admin.
|
||||
func IsAdminRole(userIDOrUsername interface{}) (bool, error) {
|
||||
u := models.User{}
|
||||
|
||||
switch v := userIDOrUsername.(type) {
|
||||
case int:
|
||||
u.UserID = v
|
||||
case string:
|
||||
u.Username = v
|
||||
default:
|
||||
return false, fmt.Errorf("invalid parameter, only int and string are supported: %v", userIDOrUsername)
|
||||
}
|
||||
|
||||
user, err := GetUser(u)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return len(adminRoleList) > 0, nil
|
||||
|
||||
if user == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return user.HasAdminRole == 1, nil
|
||||
}
|
||||
|
132
dao/user.go
132
dao/user.go
@ -22,8 +22,8 @@ import (
|
||||
"github.com/vmware/harbor/models"
|
||||
"github.com/vmware/harbor/utils"
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/astaxie/beego/orm"
|
||||
"github.com/vmware/harbor/utils/log"
|
||||
)
|
||||
|
||||
// GetUser ...
|
||||
@ -31,12 +31,8 @@ func GetUser(query models.User) (*models.User, error) {
|
||||
|
||||
o := orm.NewOrm()
|
||||
|
||||
sql := `select user_id, username, email, realname, reset_uuid, salt,
|
||||
ifnull((select pr.role_id
|
||||
from project_role pr
|
||||
left join user_project_role upr on upr.pr_id = pr.pr_id
|
||||
where pr.role_id = 1
|
||||
and upr.user_id = u.user_id),0) as has_admin_role
|
||||
sql := `select user_id, username, email, realname, comment, reset_uuid, salt,
|
||||
sysadmin_flag, creation_time, update_time
|
||||
from user u
|
||||
where deleted = 0 `
|
||||
queryParam := make([]interface{}, 1)
|
||||
@ -60,51 +56,54 @@ func GetUser(query models.User) (*models.User, error) {
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if n == 0 {
|
||||
return nil, nil
|
||||
} else {
|
||||
return &u[0], nil
|
||||
}
|
||||
if n == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return &u[0], nil
|
||||
}
|
||||
|
||||
// LoginByDb is used for user to login with database auth mode.
|
||||
func LoginByDb(auth models.AuthModel) (*models.User, error) {
|
||||
|
||||
query := models.User{Username: auth.Principal, Email: auth.Principal}
|
||||
|
||||
o := orm.NewOrm()
|
||||
var u []models.User
|
||||
n, err := o.Raw(`select username from user where (username = ? or email = ?)`, query.Username, query.Email).QueryRows(&u)
|
||||
|
||||
var users []models.User
|
||||
n, err := o.Raw(`select * from user where (username = ? or email = ?) and deleted = 0`,
|
||||
auth.Principal, auth.Principal).QueryRows(&users)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if n == 0 {
|
||||
beego.Warning("User does not exist. Principal:", auth.Principal)
|
||||
}
|
||||
if n == 0 {
|
||||
return nil, nil
|
||||
} else {
|
||||
u[0].Password = auth.Password
|
||||
return CheckUserPassword(u[0])
|
||||
}
|
||||
|
||||
user := users[0]
|
||||
|
||||
if user.Password != utils.Encrypt(auth.Password, user.Salt) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
user.Password = "" //do not return the password
|
||||
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
// ListUsers lists all users according to different conditions.
|
||||
func ListUsers(query models.User) ([]models.User, error) {
|
||||
o := orm.NewOrm()
|
||||
u := []models.User{}
|
||||
sql := `select u.user_id, u.username, u.email, ifnull((select pr.role_id
|
||||
from project_role pr
|
||||
left join user_project_role upr on upr.pr_id = pr.pr_id
|
||||
where pr.role_id = 1
|
||||
and upr.user_id = u.user_id),0) as has_admin_role
|
||||
from user u
|
||||
where u.deleted = 0 and u.user_id != 1 `
|
||||
sql := `select user_id, username, email, realname, comment, reset_uuid, salt,
|
||||
sysadmin_flag, creation_time, update_time
|
||||
from user u
|
||||
where u.deleted = 0 and u.user_id != 1 `
|
||||
|
||||
queryParam := make([]interface{}, 1)
|
||||
if query.Username != "" {
|
||||
sql += ` and u.username like ? `
|
||||
sql += ` and username like ? `
|
||||
queryParam = append(queryParam, query.Username)
|
||||
}
|
||||
sql += ` order by u.user_id desc `
|
||||
sql += ` order by user_id desc `
|
||||
|
||||
_, err := o.Raw(sql, queryParam).QueryRows(&u)
|
||||
return u, err
|
||||
@ -112,59 +111,50 @@ func ListUsers(query models.User) ([]models.User, error) {
|
||||
|
||||
// ToggleUserAdminRole gives a user admim role.
|
||||
func ToggleUserAdminRole(u models.User) error {
|
||||
|
||||
projectRole := models.ProjectRole{PrID: 1} //admin project role
|
||||
|
||||
o := orm.NewOrm()
|
||||
|
||||
var pr []models.ProjectRole
|
||||
sql := `update user set sysadmin_flag =not sysadmin_flag where user_id = ?`
|
||||
|
||||
n, err := o.Raw(`select user_id from user_project_role where user_id = ? and pr_id = ? `, u.UserID, projectRole.PrID).QueryRows(&pr)
|
||||
r, err := o.Raw(sql, u.UserID).Exec()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var sql string
|
||||
if n == 0 {
|
||||
sql = `insert into user_project_role (user_id, pr_id) values (?, ?)`
|
||||
} else {
|
||||
sql = `delete from user_project_role where user_id = ? and pr_id = ?`
|
||||
}
|
||||
|
||||
p, err := o.Raw(sql).Prepare()
|
||||
if err != nil {
|
||||
if _, err := r.RowsAffected(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer p.Close()
|
||||
_, err = p.Exec(u.UserID, projectRole.PrID)
|
||||
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChangeUserPassword ...
|
||||
func ChangeUserPassword(u models.User, oldPassword ...string) error {
|
||||
func ChangeUserPassword(u models.User, oldPassword ...string) (err error) {
|
||||
if len(oldPassword) > 1 {
|
||||
return errors.New("Wrong numbers of params.")
|
||||
}
|
||||
|
||||
o := orm.NewOrm()
|
||||
var err error
|
||||
|
||||
var r sql.Result
|
||||
if len(oldPassword) == 0 {
|
||||
//In some cases, it may no need to check old password, just as Linux change password policies.
|
||||
_, err = o.Raw(`update user set password=?, salt=? where user_id=?`, utils.Encrypt(u.Password, u.Salt), u.Salt, u.UserID).Exec()
|
||||
} else if len(oldPassword) == 1 {
|
||||
r, err = o.Raw(`update user set password=?, salt=? where user_id=? and password = ?`, utils.Encrypt(u.Password, u.Salt), u.Salt, u.UserID, utils.Encrypt(oldPassword[0], u.Salt)).Exec()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
count, err := r.RowsAffected()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if count == 0 {
|
||||
return errors.New("No record be changed, change password failed.")
|
||||
}
|
||||
r, err = o.Raw(`update user set password=?, salt=? where user_id=?`, utils.Encrypt(u.Password, u.Salt), u.Salt, u.UserID).Exec()
|
||||
} else {
|
||||
return errors.New("Wrong numbers of params.")
|
||||
r, err = o.Raw(`update user set password=?, salt=? where user_id=? and password = ?`, utils.Encrypt(u.Password, u.Salt), u.Salt, u.UserID, utils.Encrypt(oldPassword[0], u.Salt)).Exec()
|
||||
}
|
||||
return err
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c, err := r.RowsAffected()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c == 0 {
|
||||
return errors.New("No record has been modified, change password failed.")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResetUserPassword ...
|
||||
@ -181,7 +171,7 @@ func ResetUserPassword(u models.User) error {
|
||||
if count == 0 {
|
||||
return errors.New("No record be changed, reset password failed.")
|
||||
}
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateUserResetUUID ...
|
||||
@ -224,12 +214,14 @@ func CheckUserPassword(query models.User) (*models.User, error) {
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if n == 0 {
|
||||
beego.Warning("User principal does not match password. Current:", currentUser)
|
||||
return nil, nil
|
||||
} else {
|
||||
return &user[0], nil
|
||||
}
|
||||
|
||||
if n == 0 {
|
||||
log.Warning("User principal does not match password. Current:", currentUser)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return &user[0], nil
|
||||
}
|
||||
|
||||
// DeleteUser ...
|
||||
|
@ -32,4 +32,6 @@ type Project struct {
|
||||
Public int `orm:"column(public)"`
|
||||
//This field does not have correspondent column in DB, this is just for UI to disable button
|
||||
Togglable bool
|
||||
|
||||
UpdateTime time.Time `orm:"update_time" json:"update_time"`
|
||||
}
|
||||
|
@ -16,33 +16,19 @@
|
||||
package models
|
||||
|
||||
const (
|
||||
//SYSADMIN system administrator
|
||||
SYSADMIN = 1
|
||||
//PROJECTADMIN project administrator
|
||||
PROJECTADMIN = 2
|
||||
PROJECTADMIN = 1
|
||||
//DEVELOPER developer
|
||||
DEVELOPER = 3
|
||||
DEVELOPER = 2
|
||||
//GUEST guest
|
||||
GUEST = 4
|
||||
GUEST = 3
|
||||
)
|
||||
|
||||
// Role holds the details of a role.
|
||||
type Role struct {
|
||||
RoleID int `json:"role_id" orm:"column(role_id)"`
|
||||
RoleCode string `json:"role_code" orm:"column(role_code)"`
|
||||
Name string `json:"role_name" orm:"column(name)"`
|
||||
}
|
||||
RoleID int `orm:"column(role_id)" json:"role_id"`
|
||||
RoleCode string `orm:"column(role_code)" json:"role_code"`
|
||||
Name string `orm:"column(name)" json:"role_name"`
|
||||
|
||||
// ProjectRole holds information about the relationship of project and role.
|
||||
type ProjectRole struct {
|
||||
PrID int `orm:"column(pr_id)" json:"PrId"`
|
||||
ProjectID int64 `orm:"column(project_id)" json:"ProjectId"`
|
||||
RoleID int `orm:"column(role_id)" json:"RoleId"`
|
||||
}
|
||||
|
||||
// UserProjectRole holds information about relationship of user, project and role.
|
||||
type UserProjectRole struct {
|
||||
UprID int `orm:"column(upr_id)" json:"UprId"`
|
||||
UserID int `orm:"column(user_id)" json:"UserId"`
|
||||
PrID int64 `orm:"column(pr_id)" json:"PrId"`
|
||||
RoleMask int `orm:"role_mask" json:"role_mask"`
|
||||
}
|
||||
|
@ -15,6 +15,10 @@
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// User holds the details of a user.
|
||||
type User struct {
|
||||
UserID int `orm:"column(user_id)" json:"UserId"`
|
||||
@ -27,7 +31,10 @@ type User struct {
|
||||
Rolename string
|
||||
RoleID int `json:"RoleId"`
|
||||
RoleList []Role
|
||||
HasAdminRole int
|
||||
HasAdminRole int `orm:"column(sysadmin_flag)"`
|
||||
ResetUUID string `orm:"column(reset_uuid)" json:"ResetUuid"`
|
||||
Salt string `orm:"column(salt)"`
|
||||
|
||||
CreationTime time.Time `orm:"creation_time" json:"creation_time"`
|
||||
UpdateTime time.Time `orm:"update_time" json:"update_time"`
|
||||
}
|
||||
|
@ -46,6 +46,8 @@ func BuildRegistryURL(segments ...string) string {
|
||||
// RegistryAPIGet triggers GET request to the URL which is the endpoint of registry and returns the response body.
|
||||
// It will attach a valid jwt token to the request if registry requires.
|
||||
func RegistryAPIGet(url, username string) ([]byte, error) {
|
||||
|
||||
log.Debugf("Registry API url: %s", url)
|
||||
response, err := http.Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -59,8 +61,8 @@ func RegistryAPIGet(url, username string) ([]byte, error) {
|
||||
return result, nil
|
||||
} else if response.StatusCode == http.StatusUnauthorized {
|
||||
authenticate := response.Header.Get("WWW-Authenticate")
|
||||
log.Debugf("authenticate header: %s", authenticate)
|
||||
str := strings.Split(authenticate, " ")[1]
|
||||
log.Debugf("url: %s", url)
|
||||
var service string
|
||||
var scope string
|
||||
strs := strings.Split(str, ",")
|
||||
@ -71,8 +73,12 @@ func RegistryAPIGet(url, username string) ([]byte, error) {
|
||||
scope = s
|
||||
}
|
||||
}
|
||||
service = strings.Split(service, "\"")[1]
|
||||
scope = strings.Split(scope, "\"")[1]
|
||||
if arr := strings.Split(service, "\""); len(arr) > 1 {
|
||||
service = arr[1]
|
||||
}
|
||||
if arr := strings.Split(scope, "\""); len(arr) > 1 {
|
||||
scope = arr[1]
|
||||
}
|
||||
token, err := GenTokenForUI(username, service, scope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -332,7 +332,6 @@ jQuery(function(){
|
||||
getUserRoleCallback(userId);
|
||||
});
|
||||
$("#tblUser .glyphicon-trash").on("click", function(){
|
||||
var roleId = $(this).attr("roleid");
|
||||
var userId = $(this).attr("userid");
|
||||
new AjaxUtil({
|
||||
url: "/api/projects/" + $("#projectId").val() + "/members/" + userId,
|
||||
|
@ -197,15 +197,15 @@
|
||||
<label for="txtRole" class="control-label">{{i18n .Lang "role"}}:</label>
|
||||
<ul class="list-group" id="lstRole">
|
||||
<li class="list-group-item">
|
||||
<input type="radio" name="chooseRole" id="chkRole2" value="2">
|
||||
<input type="radio" name="chooseRole" id="chkRole2" value="1">
|
||||
<label for="chkRole2" class="control-label">Project Admin</label>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<input type="radio" name="chooseRole" id="chkRole3" value="3">
|
||||
<input type="radio" name="chooseRole" id="chkRole3" value="2">
|
||||
<label for="chkRole3" class="control-label">Developer</label>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<input type="radio" name="chooseRole" id="chkRole4" value="4">
|
||||
<input type="radio" name="chooseRole" id="chkRole4" value="3">
|
||||
<label for="chkRole4" class="control-label">Guest</label>
|
||||
</li>
|
||||
</ul>
|
||||
|
Loading…
Reference in New Issue
Block a user