mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-20 09:15:19 +01:00
Put user info into session (#4885)
Fix the following issues. 1) GroupList is not found in SecurityContext user info 2) Retrieve multiple memberof information from LDAP. 3) If user is in two groups with guest, administrator role separately, display the max privilege role.
This commit is contained in:
parent
6a7ba4609f
commit
d3930ae17c
@ -292,8 +292,10 @@ func GetRolesByLDAPGroup(projectID int64, groupDNCondition string) ([]int, error
|
|||||||
return roles, nil
|
return roles, nil
|
||||||
}
|
}
|
||||||
o := GetOrmer()
|
o := GetOrmer()
|
||||||
|
//Because an LDAP user can be memberof multiple groups,
|
||||||
|
//the role is in descent order (1-admin, 2-developer, 3-guest), use min to select the max privilege role.
|
||||||
sql := fmt.Sprintf(
|
sql := fmt.Sprintf(
|
||||||
`select pm.role from project_member pm
|
`select min(pm.role) from project_member pm
|
||||||
left join user_group ug on pm.entity_type = 'g' and pm.entity_id = ug.id
|
left join user_group ug on pm.entity_type = 'g' and pm.entity_id = ug.id
|
||||||
where ug.ldap_group_dn in ( %s ) and pm.project_id = ? `,
|
where ug.ldap_group_dn in ( %s ) and pm.project_id = ? `,
|
||||||
groupDNCondition)
|
groupDNCondition)
|
||||||
@ -302,5 +304,9 @@ func GetRolesByLDAPGroup(projectID int64, groupDNCondition string) ([]int, error
|
|||||||
log.Warningf("Error in GetRolesByLDAPGroup, error: %v", err)
|
log.Warningf("Error in GetRolesByLDAPGroup, error: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
//If there is no row selected, the min returns an empty row, to avoid return 0 as role
|
||||||
|
if len(roles) == 1 && roles[0] == 0 {
|
||||||
|
return []int{}, nil
|
||||||
|
}
|
||||||
return roles, nil
|
return roles, nil
|
||||||
}
|
}
|
||||||
|
@ -202,7 +202,10 @@ func (session *Session) SearchUser(username string) ([]models.LdapUser, error) {
|
|||||||
case "email":
|
case "email":
|
||||||
u.Email = val
|
u.Email = val
|
||||||
case "memberof":
|
case "memberof":
|
||||||
groupDNList = append(groupDNList, val)
|
for _, dnItem := range attr.Values {
|
||||||
|
groupDNList = append(groupDNList, strings.TrimSpace(dnItem))
|
||||||
|
log.Debugf("Found memberof %v", dnItem)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
u.GroupDNList = groupDNList
|
u.GroupDNList = groupDNList
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,8 @@ func (l *Auth) Authenticate(m models.AuthModel) (*models.User, error) {
|
|||||||
|
|
||||||
ldapUsers, err := ldapSession.SearchUser(p)
|
ldapUsers, err := ldapSession.SearchUser(p)
|
||||||
|
|
||||||
|
log.Debugf("Found ldap user %+v", ldapUsers[0])
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warningf("ldap search fail: %v", err)
|
log.Warningf("ldap search fail: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -69,10 +69,7 @@ func (cc *CommonController) Login() {
|
|||||||
if user == nil {
|
if user == nil {
|
||||||
cc.CustomAbort(http.StatusUnauthorized, "")
|
cc.CustomAbort(http.StatusUnauthorized, "")
|
||||||
}
|
}
|
||||||
|
cc.SetSession("user", *user)
|
||||||
cc.SetSession("userId", user.UserID)
|
|
||||||
cc.SetSession("username", user.Username)
|
|
||||||
cc.SetSession("isSysAdmin", user.HasAdminRole)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogOut Habor UI
|
// LogOut Habor UI
|
||||||
|
@ -215,7 +215,6 @@ func (b *basicAuthReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
|
|||||||
pm := config.GlobalProjectMgr
|
pm := config.GlobalProjectMgr
|
||||||
log.Debug("creating local database security context...")
|
log.Debug("creating local database security context...")
|
||||||
securCtx := local.NewSecurityContext(user, pm)
|
securCtx := local.NewSecurityContext(user, pm)
|
||||||
|
|
||||||
setSecurCtxAndPM(ctx.Request, securCtx, pm)
|
setSecurCtxAndPM(ctx.Request, securCtx, pm)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -223,24 +222,25 @@ func (b *basicAuthReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
|
|||||||
type sessionReqCtxModifier struct{}
|
type sessionReqCtxModifier struct{}
|
||||||
|
|
||||||
func (s *sessionReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
|
func (s *sessionReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
|
||||||
username := ctx.Input.Session("username")
|
var user models.User
|
||||||
if username == nil {
|
userInterface := ctx.Input.Session("user")
|
||||||
|
|
||||||
|
if userInterface == nil {
|
||||||
|
log.Debug("can not get user information from session")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug("got user information from session")
|
log.Debug("got user information from session")
|
||||||
user := &models.User{
|
user, ok := userInterface.(models.User)
|
||||||
Username: username.(string),
|
if !ok {
|
||||||
|
log.Info("can not get user information from session")
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
isSysAdmin := ctx.Input.Session("isSysAdmin")
|
log.Debug("Getting user %+v", user)
|
||||||
if isSysAdmin != nil && isSysAdmin.(bool) {
|
|
||||||
user.HasAdminRole = true
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debug("using local database project manager")
|
log.Debug("using local database project manager")
|
||||||
pm := config.GlobalProjectMgr
|
pm := config.GlobalProjectMgr
|
||||||
log.Debug("creating local database security context...")
|
log.Debug("creating local database security context...")
|
||||||
securCtx := local.NewSecurityContext(user, pm)
|
securCtx := local.NewSecurityContext(&user, pm)
|
||||||
|
|
||||||
setSecurCtxAndPM(ctx.Request, securCtx, pm)
|
setSecurCtxAndPM(ctx.Request, securCtx, pm)
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ import (
|
|||||||
"github.com/astaxie/beego/session"
|
"github.com/astaxie/beego/session"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/vmware/harbor/src/common/dao"
|
"github.com/vmware/harbor/src/common/dao"
|
||||||
|
"github.com/vmware/harbor/src/common/models"
|
||||||
commonsecret "github.com/vmware/harbor/src/common/secret"
|
commonsecret "github.com/vmware/harbor/src/common/secret"
|
||||||
"github.com/vmware/harbor/src/common/security"
|
"github.com/vmware/harbor/src/common/security"
|
||||||
"github.com/vmware/harbor/src/common/security/local"
|
"github.com/vmware/harbor/src/common/security/local"
|
||||||
@ -146,6 +147,12 @@ func TestBasicAuthReqCtxModifier(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSessionReqCtxModifier(t *testing.T) {
|
func TestSessionReqCtxModifier(t *testing.T) {
|
||||||
|
user := models.User{
|
||||||
|
Username: "admin",
|
||||||
|
UserID: 1,
|
||||||
|
Email: "admin@example.com",
|
||||||
|
HasAdminRole: true,
|
||||||
|
}
|
||||||
req, err := http.NewRequest(http.MethodGet,
|
req, err := http.NewRequest(http.MethodGet,
|
||||||
"http://127.0.0.1/api/projects/", nil)
|
"http://127.0.0.1/api/projects/", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -155,10 +162,7 @@ func TestSessionReqCtxModifier(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create session store: %v", err)
|
t.Fatalf("failed to create session store: %v", err)
|
||||||
}
|
}
|
||||||
if err = store.Set("username", "admin"); err != nil {
|
if err = store.Set("user", user); err != nil {
|
||||||
t.Fatalf("failed to set session: %v", err)
|
|
||||||
}
|
|
||||||
if err = store.Set("isSysAdmin", true); err != nil {
|
|
||||||
t.Fatalf("failed to set session: %v", err)
|
t.Fatalf("failed to set session: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,6 +188,41 @@ func TestSessionReqCtxModifier(t *testing.T) {
|
|||||||
assert.Equal(t, "admin", s.GetUsername())
|
assert.Equal(t, "admin", s.GetUsername())
|
||||||
assert.True(t, s.IsSysAdmin())
|
assert.True(t, s.IsSysAdmin())
|
||||||
assert.NotNil(t, projectManager(ctx))
|
assert.NotNil(t, projectManager(ctx))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSessionReqCtxModifierFailed(t *testing.T) {
|
||||||
|
user := "admin"
|
||||||
|
req, err := http.NewRequest(http.MethodGet,
|
||||||
|
"http://127.0.0.1/api/projects/", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create request: %v", req)
|
||||||
|
}
|
||||||
|
store, err := beego.GlobalSessions.SessionStart(httptest.NewRecorder(), req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create session store: %v", err)
|
||||||
|
}
|
||||||
|
if err = store.Set("user", user); err != nil {
|
||||||
|
t.Fatalf("failed to set session: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err = http.NewRequest(http.MethodGet,
|
||||||
|
"http://127.0.0.1/api/projects/", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create request: %v", req)
|
||||||
|
}
|
||||||
|
addSessionIDToCookie(req, store.SessionID())
|
||||||
|
|
||||||
|
ctx, err := newContext(req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to crate context: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
modifier := &sessionReqCtxModifier{}
|
||||||
|
modified := modifier.Modify(ctx)
|
||||||
|
|
||||||
|
assert.False(t, modified)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO add test case
|
// TODO add test case
|
||||||
|
Loading…
Reference in New Issue
Block a user