Merge pull request #5836 from swordqiu/hotfix/qj-cas-project-name-regexp-issue

fix: cas auto create project fetch failure
This commit is contained in:
Zexi Li
2020-04-16 23:59:33 +08:00
committed by GitHub
4 changed files with 44 additions and 21 deletions
+14 -8
View File
@@ -27,6 +27,7 @@ import (
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/identity"
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/keystone/driver"
"yunion.io/x/onecloud/pkg/keystone/models"
@@ -148,22 +149,27 @@ func (self *SCASDriver) Authenticate(ctx context.Context, ident mcclient.SAuthen
return nil, errors.Wrap(err, "models.UserManager.FetchUserExtended")
}
self.userTryJoinProject(ctx, usr, domain, resp)
self.userTryJoinProject(ctx, usr, domain.Id, resp)
return extUser, nil
}
func (self *SCASDriver) userTryJoinProject(ctx context.Context, usr *models.SUser, domain *models.SDomain, resp []byte) {
func (self *SCASDriver) userTryJoinProject(ctx context.Context, usr *models.SUser, domainId string, resp []byte) {
var err error
var targetProject *models.SProject
log.Debugf("userTryJoinProject resp %s proj %s", string(resp), self.casConfig.CasProjectAttribute)
if !consts.GetNonDefaultDomainProjects() {
domainId = api.DEFAULT_DOMAIN_ID
}
if len(self.casConfig.CasProjectAttribute) > 0 {
projName := fetchAttribute(resp, self.casConfig.CasProjectAttribute)
if len(projName) > 0 {
targetProject, err = models.ProjectManager.FetchProject("", projName, domain.Id, domain.Name)
casProjName := fetchAttribute(resp, self.casConfig.CasProjectAttribute)
if len(casProjName) > 0 {
projName := models.NormalizeProjectName(casProjName)
targetProject, err = models.ProjectManager.FetchProject("", projName, domainId, "")
if err != nil {
log.Errorf("fetch project %s fail %s", projName, err)
if errors.Cause(err) == sql.ErrNoRows && self.casConfig.AutoCreateCasProject.IsTrue() {
targetProject, err = models.ProjectManager.NewProject(ctx, projName, "cas project", domain)
targetProject, err = models.ProjectManager.NewProject(ctx, projName, "cas project", domainId)
if err != nil {
log.Errorf("auto create project %s fail %s", projName, err)
}
@@ -183,7 +189,7 @@ func (self *SCASDriver) userTryJoinProject(ctx context.Context, usr *models.SUse
if len(self.casConfig.CasRoleAttribute) > 0 {
roleName := fetchAttribute(resp, self.casConfig.CasRoleAttribute)
if len(roleName) > 0 {
targetRole, err = models.RoleManager.FetchRole("", roleName, domain.Id, domain.Name)
targetRole, err = models.RoleManager.FetchRole("", roleName, domainId, "")
if err != nil {
log.Errorf("fetch role %s fail %s", roleName, err)
}
@@ -205,7 +211,7 @@ func (self *SCASDriver) userTryJoinProject(ctx context.Context, usr *models.SUse
}
func fetchAttribute(heystack []byte, name string) string {
pattern := regexp.MustCompile(fmt.Sprintf(`<%s>(\w+)</%s>`, name, name))
pattern := regexp.MustCompile(fmt.Sprintf(`<%s>([^<]*)</%s>`, name, name))
result := pattern.FindAllStringSubmatch(string(heystack), -1)
if len(result) > 0 && len(result[0]) > 1 {
return strings.TrimSpace(result[0][1])
+23 -6
View File
@@ -48,15 +48,32 @@ func TestXmlUnmarshal(t *testing.T) {
}
func TestFetchAttribute(t *testing.T) {
xmlstr := `<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
cases := []struct {
Xml string
Key string
Want string
}{
{
Xml: `<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
<cas:authenticationSuccess>
<cas:user>casuser</cas:user>
<cas:proj>casproj</cas:proj>
</cas:authenticationSuccess>
</cas:serviceResponse>`
got := fetchAttribute([]byte(xmlstr), "cas:proj")
want := "casproj"
if got != want {
t.Errorf("want %s got %s", want, got)
</cas:serviceResponse>`,
Key: "cas:proj",
Want: "casproj",
},
{
Xml: `<?xml version="1.0" encoding="UTF-8"?>
<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas"><cas:authenticationSuccess><cas:user>lcftest0416</cas:user><cas:proj>周凌测试无线公司1112342</cas:proj></cas:authenticationSuccess></cas:serviceResponse>`,
Key: "cas:proj",
Want: "周凌测试无线公司1112342",
},
}
for _, c := range cases {
got := fetchAttribute([]byte(c.Xml), c.Key)
if got != c.Want {
t.Errorf("want %s got %s", c.Want, got)
}
}
}
+1 -1
View File
@@ -776,7 +776,7 @@ func (self *SIdentityProvider) SyncOrCreateDomain(ctx context.Context, extId str
_, err := ProjectManager.NewProject(ctx,
fmt.Sprintf("%s_default_project", extName),
fmt.Sprintf("Default project for domain %s", extName),
domain,
domain.Id,
)
if err != nil {
log.Errorf("ProjectManager.NewProject fail %s", err)
+6 -6
View File
@@ -627,16 +627,16 @@ func (project *SProject) GetUsages() []db.IUsage {
}
}
func (manager *SProjectManager) NewProject(ctx context.Context, name string, desc string, domain *SDomain) (*SProject, error) {
lockman.LockClass(ctx, manager, domain.Id)
defer lockman.ReleaseClass(ctx, manager, domain.Id)
func (manager *SProjectManager) NewProject(ctx context.Context, name string, desc string, domainId string) (*SProject, error) {
lockman.LockClass(ctx, manager, domainId)
defer lockman.ReleaseClass(ctx, manager, domainId)
project := &SProject{}
project.SetModelManager(ProjectManager, project)
projectName := NormalizeProjectName(name)
ownerId := &db.SOwnerId{}
if manager.NamespaceScope() == rbacutils.ScopeDomain {
ownerId.DomainId = domain.Id
ownerId.DomainId = domainId
}
newName, err := db.GenerateName(ProjectManager, ownerId, projectName)
if err != nil {
@@ -645,10 +645,10 @@ func (manager *SProjectManager) NewProject(ctx context.Context, name string, des
newName = projectName
}
project.Name = newName
project.DomainId = domain.Id
project.DomainId = domainId
project.Description = desc
project.IsDomain = tristate.False
project.ParentId = domain.Id
project.ParentId = domainId
err = ProjectManager.TableSpec().Insert(project)
if err != nil {
return nil, errors.Wrap(err, "Insert")