db_role_refactor

This commit is contained in:
Wenkai Yin 2016-03-29 12:09:27 +08:00
parent ac5bbc4657
commit f1a2942f6a
11 changed files with 75 additions and 142 deletions

View File

@ -16,7 +16,6 @@
package api package api
import ( import (
"fmt"
"net/http" "net/http"
"strconv" "strconv"
@ -24,7 +23,6 @@ import (
"github.com/vmware/harbor/models" "github.com/vmware/harbor/models"
"github.com/astaxie/beego" "github.com/astaxie/beego"
"github.com/vmware/harbor/utils/log"
) )
// ProjectMemberAPI handles request to /api/projects/{}/members/{} // ProjectMemberAPI handles request to /api/projects/{}/members/{}
@ -95,7 +93,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(models.User{UserID: pma.memberID}, pid) roleList, err := dao.GetUserProjectRoles(pma.memberID, pid)
if err != nil { if err != nil {
beego.Error("Error occurred in GetUserProjectRoles:", err) beego.Error("Error occurred in GetUserProjectRoles:", err)
pma.CustomAbort(http.StatusInternalServerError, "Internal error.") pma.CustomAbort(http.StatusInternalServerError, "Internal error.")
@ -118,17 +116,27 @@ func (pma *ProjectMemberAPI) Get() {
// Post ... // Post ...
func (pma *ProjectMemberAPI) Post() { func (pma *ProjectMemberAPI) Post() {
pid := pma.project.ProjectID 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 { if err != nil {
beego.Error("Error occurred in GetUserProjectRoles:", err) beego.Error("Error occurred in GetUserProjectRoles:", err)
pma.CustomAbort(http.StatusInternalServerError, "Internal error.") 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 {
beego.Warning("Current user, id:", pma.currentUserID, "does not have project admin role for project, id:", pid) beego.Warning("Current user, id:", pma.currentUserID, "does not have project admin role for project, id:", pid)
pma.RenderError(http.StatusForbidden, "") pma.RenderError(http.StatusForbidden, "")
return return
} }
var req memberReq var req memberReq
pma.DecodeJSONReq(&req) pma.DecodeJSONReq(&req)
username := req.Username username := req.Username
@ -138,7 +146,7 @@ func (pma *ProjectMemberAPI) Post() {
pma.RenderError(http.StatusNotFound, "User does not exist") pma.RenderError(http.StatusNotFound, "User does not exist")
return return
} }
rolelist, err = dao.GetUserProjectRoles(models.User{UserID: userID}, pid) rolelist, err = dao.GetUserProjectRoles(userID, pid)
if err != nil { if err != nil {
beego.Error("Error occurred in GetUserProjectRoles:", err) beego.Error("Error occurred in GetUserProjectRoles:", err)
pma.CustomAbort(http.StatusInternalServerError, "Internal error.") pma.CustomAbort(http.StatusInternalServerError, "Internal error.")
@ -150,13 +158,7 @@ func (pma *ProjectMemberAPI) Post() {
} }
for _, rid := range req.Roles { for _, rid := range req.Roles {
role, err := dao.IntToRole(rid) err = dao.AddProjectMember(pid, userID, int(rid))
if err != nil {
log.Error(err)
pma.RenderError(http.StatusBadRequest, fmt.Sprintf("Invalid role: %d", rid))
}
err = dao.AddProjectMember(pid, userID, role)
if err != nil { if err != nil {
beego.Error("Failed to update DB to add project user role, project id:", pid, ", user id:", userID, ", role id:", rid) beego.Error("Failed to update DB to add project user role, project id:", pid, ", user id:", userID, ", role id:", rid)
pma.RenderError(http.StatusInternalServerError, "Failed to update data in database") pma.RenderError(http.StatusInternalServerError, "Failed to update data in database")
@ -169,20 +171,29 @@ func (pma *ProjectMemberAPI) Post() {
func (pma *ProjectMemberAPI) Put() { func (pma *ProjectMemberAPI) Put() {
pid := pma.project.ProjectID pid := pma.project.ProjectID
mid := pma.memberID 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 { if err != nil {
beego.Error("Error occurred in GetUserProjectRoles:", err) beego.Error("Error occurred in GetUserProjectRoles:", err)
pma.CustomAbort(http.StatusInternalServerError, "Internal error.") 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 {
beego.Warning("Current user, id:", pma.currentUserID, ", does not have project admin role for project, id:", pid) beego.Warning("Current user, id:", pma.currentUserID, ", does not have project admin role for project, id:", pid)
pma.RenderError(http.StatusForbidden, "") pma.RenderError(http.StatusForbidden, "")
return return
} }
var req memberReq var req memberReq
pma.DecodeJSONReq(&req) pma.DecodeJSONReq(&req)
roleList, err := dao.GetUserProjectRoles(models.User{UserID: mid}, pid) roleList, err := dao.GetUserProjectRoles(mid, pid)
if len(roleList) == 0 { if len(roleList) == 0 {
beego.Warning("User is not in project, user id:", mid, ", project id:", pid) beego.Warning("User is not in project, user id:", mid, ", project id:", pid)
pma.RenderError(http.StatusNotFound, "user not exist in project") pma.RenderError(http.StatusNotFound, "user not exist in project")
@ -198,13 +209,7 @@ func (pma *ProjectMemberAPI) Put() {
} }
//insert roles in request //insert roles in request
for _, rid := range req.Roles { for _, rid := range req.Roles {
role, err := dao.IntToRole(rid) err = dao.AddProjectMember(pid, mid, int(rid))
if err != nil {
log.Error(err)
pma.RenderError(http.StatusBadRequest, fmt.Sprintf("Invalid role: %d", rid))
}
err = dao.AddProjectMember(pid, mid, role)
if err != nil { if err != nil {
beego.Error("Failed to update DB to add project user role, project id:", pid, ", user id:", mid, ", role id:", rid) beego.Error("Failed to update DB to add project user role, project id:", pid, ", user id:", mid, ", role id:", rid)
pma.RenderError(http.StatusInternalServerError, "Failed to update data in database") pma.RenderError(http.StatusInternalServerError, "Failed to update data in database")
@ -217,9 +222,17 @@ func (pma *ProjectMemberAPI) Put() {
func (pma *ProjectMemberAPI) Delete() { func (pma *ProjectMemberAPI) Delete() {
pid := pma.project.ProjectID pid := pma.project.ProjectID
mid := pma.memberID 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 len(rolelist) == 0 { hasProjectAdminRole := false
for _, role := range rolelist {
if role.RoleID == models.PROJECTADMIN {
hasProjectAdminRole = true
break
}
}
if !hasProjectAdminRole {
beego.Warning("Current user, id:", pma.currentUserID, ", does not have project admin role for project, id:", pid) beego.Warning("Current user, id:", pma.currentUserID, ", does not have project admin role for project, id:", pid)
pma.RenderError(http.StatusForbidden, "") pma.RenderError(http.StatusForbidden, "")
return return

View File

@ -189,13 +189,21 @@ func (p *ProjectAPI) FilterAccessLog() {
} }
func isProjectAdmin(userID int, pid int64) bool { func isProjectAdmin(userID int, pid int64) bool {
userQuery := models.User{UserID: userID, RoleID: models.PROJECTADMIN} rolelist, err := dao.GetUserProjectRoles(userID, pid)
rolelist, err := dao.GetUserProjectRoles(userQuery, pid)
if err != nil { if err != nil {
beego.Error("Error occurred in GetUserProjectRoles:", err, ", returning false") beego.Error("Error occurred in GetUserProjectRoles:", err, ", returning false")
return false 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 { func validateProjectReq(req projectReq) error {

View File

@ -31,7 +31,7 @@ func checkProjectPermission(userID int, projectID int64) bool {
if exist { if exist {
return true return true
} }
roleList, err := dao.GetUserProjectRoles(models.User{UserID: userID}, projectID) roleList, err := dao.GetUserProjectRoles(userID, projectID)
if err != nil { if err != nil {
beego.Error("Error occurred in GetUserProjectRoles:", err) beego.Error("Error occurred in GetUserProjectRoles:", err)
return false return false

View File

@ -21,7 +21,6 @@ import (
"os" "os"
"github.com/vmware/harbor/dao" "github.com/vmware/harbor/dao"
"github.com/vmware/harbor/models"
"github.com/astaxie/beego" "github.com/astaxie/beego"
) )
@ -69,7 +68,7 @@ func (idc *ItemDetailController) Get() {
idc.Data["Username"] = idc.GetSession("username") idc.Data["Username"] = idc.GetSession("username")
idc.Data["UserId"] = userID idc.Data["UserId"] = userID
roleList, err := dao.GetUserProjectRoles(models.User{UserID: userID}, projectID) roleList, err := dao.GetUserProjectRoles(userID, projectID)
if err != nil { if err != nil {
beego.Error("Error occurred in GetUserProjectRoles:", err) beego.Error("Error occurred in GetUserProjectRoles:", err)
idc.CustomAbort(http.StatusInternalServerError, "Internal error.") idc.CustomAbort(http.StatusInternalServerError, "Internal error.")
@ -86,9 +85,7 @@ func (idc *ItemDetailController) Get() {
return return
} }
if isAdmin { if len(roleList) > 0 {
idc.Data["RoleId"] = models.SYSADMIN
} else if len(roleList) > 0 {
idc.Data["RoleId"] = roleList[0].RoleID idc.Data["RoleId"] = roleList[0].RoleID
} }
} }

View File

@ -539,10 +539,9 @@ func TestQueryProject(t *testing.T) {
} }
func TestGetUserProjectRoles(t *testing.T) { func TestGetUserProjectRoles(t *testing.T) {
user := *currentUser r, err := GetUserProjectRoles(currentUser.UserID, currentProject.ProjectID)
r, err := GetUserProjectRoles(user, currentProject.ProjectID)
if err != nil { 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. //Get the size of current user project role.
@ -579,12 +578,12 @@ func TestQueryRelevantProjects(t *testing.T) {
} }
func TestAddProjectMember(t *testing.T) { func TestAddProjectMember(t *testing.T) {
err := AddProjectMember(currentProject.ProjectID, 1, Developer) err := AddProjectMember(currentProject.ProjectID, 1, models.DEVELOPER)
if err != nil { if err != nil {
t.Errorf("Error occurred in AddProjectMember: %v", err) t.Errorf("Error occurred in AddProjectMember: %v", err)
} }
roles, err := GetUserProjectRoles(models.User{UserID: 1}, currentProject.ProjectID) roles, err := GetUserProjectRoles(1, currentProject.ProjectID)
if err != nil { if err != nil {
t.Errorf("Error occurred in GetUserProjectRoles: %v", err) t.Errorf("Error occurred in GetUserProjectRoles: %v", err)
} }
@ -608,7 +607,7 @@ func TestDeleteProjectMember(t *testing.T) {
t.Errorf("Error occurred in DeleteProjectMember: %v", err) t.Errorf("Error occurred in DeleteProjectMember: %v", err)
} }
roles, err := GetUserProjectRoles(models.User{UserID: 1}, currentProject.ProjectID) roles, err := GetUserProjectRoles(1, currentProject.ProjectID)
if err != nil { if err != nil {
t.Errorf("Error occurred in GetUserProjectRoles: %v", err) t.Errorf("Error occurred in GetUserProjectRoles: %v", err)
} }

View File

@ -56,7 +56,7 @@ func AddProject(project models.Project) error {
return err return err
} }
if err = AddProjectMember(projectID, project.OwnerID, ProjectAdmin); err != nil { if err = AddProjectMember(projectID, project.OwnerID, models.PROJECTADMIN); err != nil {
return err return err
} }

View File

@ -21,17 +21,12 @@ import (
) )
// AddProjectMember inserts a record to table project_member // AddProjectMember inserts a record to table project_member
func AddProjectMember(projectID int64, userID int, r role) error { func AddProjectMember(projectID int64, userID int, role int) error {
o := orm.NewOrm() o := orm.NewOrm()
sql := "insert into project_member (project_id, user_id , role) values (?, ?, ?)" sql := "insert into project_member (project_id, user_id , role) values (?, ?, ?)"
rr, err := getRole(r) if _, err := o.Raw(sql, projectID, userID, role).Exec(); err != nil {
if err != nil {
return err
}
if _, err = o.Raw(sql, projectID, userID, rr.RoleID).Exec(); err != nil {
return err return err
} }
@ -39,17 +34,12 @@ func AddProjectMember(projectID int64, userID int, r role) error {
} }
// UpdateProjectMember updates the record in table project_member // UpdateProjectMember updates the record in table project_member
func UpdateProjectMember(projectID int64, userID int, r role) error { func UpdateProjectMember(projectID int64, userID int, role int) error {
o := orm.NewOrm() o := orm.NewOrm()
sql := "update project_member set role = ? where project_id = ? and user_id = ?" sql := "update project_member set role = ? where project_id = ? and user_id = ?"
rr, err := getRole(r) if _, err := o.Raw(sql, role, projectID, userID).Exec(); err != nil {
if err != nil {
return err
}
if _, err := o.Raw(sql, rr.RoleID, projectID, userID).Exec(); err != nil {
return err return err
} }

View File

@ -16,41 +16,12 @@
package dao package dao
import ( import (
"fmt"
"github.com/vmware/harbor/models"
"github.com/astaxie/beego/orm" "github.com/astaxie/beego/orm"
"github.com/vmware/harbor/models"
) )
type role int
// Start from 2 to guarantee the compatibility with former code
const (
ProjectAdmin role = 2
Developer = 3
Guest = 4
)
var roleList = make(map[role]*models.Role)
// IntToRole is used to convert int to role.
func IntToRole(i int) (r role, err error) {
switch i {
case 2:
r = ProjectAdmin
case 3:
r = Developer
case 4:
r = Guest
default:
err = fmt.Errorf("no role is correspondent with the input: %d", i)
}
return
}
// GetUserProjectRoles returns roles that the user has according to the project. // 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() o := orm.NewOrm()
@ -62,11 +33,9 @@ func GetUserProjectRoles(userQuery models.User, projectID int64) ([]models.Role,
from project_member from project_member
where project_id = ? and user_id = ? where project_id = ? and user_id = ?
)` )`
queryParam := make([]interface{}, 1)
queryParam = append(queryParam, userQuery.UserID)
var roleList []models.Role var roleList []models.Role
_, err := o.Raw(sql, projectID, userQuery.UserID).QueryRows(&roleList) _, err := o.Raw(sql, projectID, userID).QueryRows(&roleList)
if err != nil { if err != nil {
return nil, err return nil, err
@ -88,42 +57,3 @@ func IsAdminRole(userID int) (bool, error) {
return user.HasAdminRole == 1, nil return user.HasAdminRole == 1, nil
} }
func getRole(r role) (*models.Role, error) {
if roleList[r] != nil {
return roleList[r], nil
}
o := orm.NewOrm()
var roles []*models.Role
sql := "select role_id, role_code, name, role_mask from role"
_, err := o.Raw(sql).QueryRows(&roles)
if err != nil {
return nil, err
}
for _, rr := range roles {
if rr.RoleCode == "MDRWS" {
roleList[ProjectAdmin] = rr
continue
}
if rr.RoleCode == "RWS" {
roleList[Developer] = rr
continue
}
if rr.RoleCode == "RS" {
roleList[Guest] = rr
continue
}
}
if roleList[r] == nil {
return nil, fmt.Errorf("unsupported role type: %v", r)
}
return roleList[r], nil
}

View File

@ -15,18 +15,15 @@
package models package models
/*
const ( const (
//SYSADMIN system administrator
SYSADMIN = 1
//PROJECTADMIN project administrator //PROJECTADMIN project administrator
PROJECTADMIN = 2 PROJECTADMIN = 1
//DEVELOPER developer //DEVELOPER developer
DEVELOPER = 3 DEVELOPER = 2
//GUEST guest //GUEST guest
GUEST = 4 GUEST = 3
) )
*/
// Role holds the details of a role. // Role holds the details of a role.
type Role struct { type Role struct {
RoleID int `orm:"column(role_id)" json:"role_id"` RoleID int `orm:"column(role_id)" json:"role_id"`

View File

@ -332,7 +332,6 @@ jQuery(function(){
getUserRoleCallback(userId); getUserRoleCallback(userId);
}); });
$("#tblUser .glyphicon-trash").on("click", function(){ $("#tblUser .glyphicon-trash").on("click", function(){
var roleId = $(this).attr("roleid");
var userId = $(this).attr("userid"); var userId = $(this).attr("userid");
new AjaxUtil({ new AjaxUtil({
url: "/api/projects/" + $("#projectId").val() + "/members/" + userId, url: "/api/projects/" + $("#projectId").val() + "/members/" + userId,

View File

@ -197,15 +197,15 @@
<label for="txtRole" class="control-label">{{i18n .Lang "role"}}:</label> <label for="txtRole" class="control-label">{{i18n .Lang "role"}}:</label>
<ul class="list-group" id="lstRole"> <ul class="list-group" id="lstRole">
<li class="list-group-item"> <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> <label for="chkRole2" class="control-label">Project Admin</label>
</li> </li>
<li class="list-group-item"> <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> <label for="chkRole3" class="control-label">Developer</label>
</li> </li>
<li class="list-group-item"> <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> <label for="chkRole4" class="control-label">Guest</label>
</li> </li>
</ul> </ul>