From d50f3d8e7f01b4559d5ad093e4eb5cfd9fa932e3 Mon Sep 17 00:00:00 2001 From: Jian Qiu Date: Sat, 15 Aug 2026 00:16:19 +0800 Subject: [PATCH] feature: support idp driver attribtue_names (#25335) Co-authored-by: Qiu Jian --- cmd/climc/shell/identity/identityproviders.go | 13 ++++++++ pkg/apis/identity/identityprovider.go | 8 +++++ pkg/apis/identity/oidc.go | 2 ++ pkg/apis/identity/saml.go | 2 ++ pkg/keystone/driver/cas/class.go | 6 ++++ pkg/keystone/driver/driver.go | 1 + pkg/keystone/driver/ldap/class.go | 4 +++ pkg/keystone/driver/oauth2/alipay/alipay.go | 2 ++ pkg/keystone/driver/oauth2/alipay/factory.go | 8 +++++ .../driver/oauth2/bingoiam/factory.go | 14 ++++++++ pkg/keystone/driver/oauth2/class.go | 8 +++++ .../driver/oauth2/dingtalk/dingtalk.go | 2 ++ .../driver/oauth2/dingtalk/factory.go | 9 ++++++ pkg/keystone/driver/oauth2/feishu/factory.go | 14 +++++++- pkg/keystone/driver/oauth2/feishu/feishu.go | 5 ++- pkg/keystone/driver/oauth2/oauth2.go | 5 +-- .../driver/oauth2/qywechat/factory.go | 10 ++++++ pkg/keystone/driver/oauth2/types.go | 1 + pkg/keystone/driver/oauth2/wechat/factory.go | 8 +++++ pkg/keystone/driver/oauth2/wechat/wechat.go | 1 + pkg/keystone/driver/oidc/class.go | 14 ++++++++ pkg/keystone/driver/oidc/template.go | 21 ++++++++++++ pkg/keystone/driver/saml/class.go | 10 ++++++ pkg/keystone/driver/saml/template.go | 12 +++++++ pkg/keystone/driver/sql/class.go | 4 +++ pkg/keystone/models/assignments.go | 9 +++--- pkg/keystone/models/identity_provider.go | 32 +++++++++++++++++++ 27 files changed, 217 insertions(+), 8 deletions(-) diff --git a/cmd/climc/shell/identity/identityproviders.go b/cmd/climc/shell/identity/identityproviders.go index cc9d560cd4..fd7c5cca4c 100644 --- a/cmd/climc/shell/identity/identityproviders.go +++ b/cmd/climc/shell/identity/identityproviders.go @@ -775,4 +775,17 @@ func init() { printObject(result) return nil }) + + type IdentityProviderGetPropertyAttributeNamesOptions struct { + DRIVER string `help:"driver of idp to query" json:"driver" choices:"oidc|oauth2|saml|cas"` + TEMPLATE string `help:"template of idp to query" json:"template"` + } + R(&IdentityProviderGetPropertyAttributeNamesOptions{}, "idp-attribute-names", "Get property attribute names of a idp", func(s *mcclient.ClientSession, args *IdentityProviderGetPropertyAttributeNamesOptions) error { + result, err := modules.IdentityProviders.Get(s, "attribute-names", jsonutils.Marshal(args)) + if err != nil { + return err + } + printObject(result) + return nil + }) } diff --git a/pkg/apis/identity/identityprovider.go b/pkg/apis/identity/identityprovider.go index 218d9c4fb0..6a795c7611 100644 --- a/pkg/apis/identity/identityprovider.go +++ b/pkg/apis/identity/identityprovider.go @@ -104,6 +104,14 @@ type IdentityProviderCreateInput struct { IconUri string `json:"icon_uri"` } +type IdentityProviderPropertyAttributeNamesInput struct { + // 后端驱动名称 + Driver string `json:"driver"` + + // 模板名称 + Template string `json:"template"` +} + type GetIdpSamlMetadataInput struct { // 缩进展示SAML sp metadata Pretty *bool `json:"pretty"` diff --git a/pkg/apis/identity/oidc.go b/pkg/apis/identity/oidc.go index b53f0cd524..0ef0d25523 100644 --- a/pkg/apis/identity/oidc.go +++ b/pkg/apis/identity/oidc.go @@ -29,6 +29,8 @@ type SOIDCIdpConfigOptions struct { TimeoutSecs int `json:"timeout_secs"` SIdpAttributeOptions + + AttributeNames map[string]string `json:"attribute_names"` } type SOIDCDexConfigOptions struct { diff --git a/pkg/apis/identity/saml.go b/pkg/apis/identity/saml.go index f7135fb271..ce6d760ef8 100644 --- a/pkg/apis/identity/saml.go +++ b/pkg/apis/identity/saml.go @@ -43,6 +43,8 @@ type SSAMLIdpConfigOptions struct { SSAMLIdpBaseConfigOptions SIdpAttributeOptions + + AttributeNames map[string]string `json:"attribute_names"` } type SSAMLTestIdpConfigOptions struct { diff --git a/pkg/keystone/driver/cas/class.go b/pkg/keystone/driver/cas/class.go index 256f927bc7..4bc3bce9b6 100644 --- a/pkg/keystone/driver/cas/class.go +++ b/pkg/keystone/driver/cas/class.go @@ -98,6 +98,12 @@ func (self *SCASDriverClass) ValidateConfig(ctx context.Context, userCred mcclie return tconf, nil } +func (self *SCASDriverClass) AttributeNames(template string) (map[string]string, error) { + return map[string]string{ + "cas:user": "User name in CAS", + }, nil +} + func init() { driver.RegisterDriverClass(&SCASDriverClass{}) } diff --git a/pkg/keystone/driver/driver.go b/pkg/keystone/driver/driver.go index d5b71f57c2..410612d6e9 100644 --- a/pkg/keystone/driver/driver.go +++ b/pkg/keystone/driver/driver.go @@ -30,6 +30,7 @@ type IIdentityBackendClass interface { IsSso() bool GetDefaultIconUri(tmpName string) string ForceSyncUser() bool + AttributeNames(template string) (map[string]string, error) } type IIdentityBackend interface { diff --git a/pkg/keystone/driver/ldap/class.go b/pkg/keystone/driver/ldap/class.go index 3813d14848..8fce274e56 100644 --- a/pkg/keystone/driver/ldap/class.go +++ b/pkg/keystone/driver/ldap/class.go @@ -86,6 +86,10 @@ func (self *SLDAPDriverClass) ValidateConfig(ctx context.Context, userCred mccli return tconf, nil } +func (self *SLDAPDriverClass) AttributeNames(template string) (map[string]string, error) { + return nil, nil +} + func init() { driver.RegisterDriverClass(&SLDAPDriverClass{}) } diff --git a/pkg/keystone/driver/oauth2/alipay/alipay.go b/pkg/keystone/driver/oauth2/alipay/alipay.go index c217b7f8eb..f27bf3c6b2 100644 --- a/pkg/keystone/driver/oauth2/alipay/alipay.go +++ b/pkg/keystone/driver/oauth2/alipay/alipay.go @@ -73,5 +73,7 @@ func (drv *SAlipayOAuth2Driver) Authenticate(ctx context.Context, code string) ( attrs[k] = []string{v} } attrs["user_name"] = []string{fmt.Sprintf("alipay%s", userInfo["user_id"])} + attrs["user_id"] = []string{userInfo["user_id"]} + attrs["nick_name"] = []string{userInfo["nick_name"]} return attrs, nil } diff --git a/pkg/keystone/driver/oauth2/alipay/factory.go b/pkg/keystone/driver/oauth2/alipay/factory.go index b36901c967..71747d3f35 100644 --- a/pkg/keystone/driver/oauth2/alipay/factory.go +++ b/pkg/keystone/driver/oauth2/alipay/factory.go @@ -41,6 +41,14 @@ func (drv SAlipayDriverFactory) ValidateConfig(conf api.SOAuth2IdpConfigOptions) return nil } +func (drv SAlipayDriverFactory) AttributeNames() map[string]string { + return map[string]string{ + "user_name": "User name in Alipay", + "user_id": "User ID in Alipay", + "nick_name": "Nick name in Alipay", + } +} + func init() { oauth2.Register(&SAlipayDriverFactory{}) } diff --git a/pkg/keystone/driver/oauth2/bingoiam/factory.go b/pkg/keystone/driver/oauth2/bingoiam/factory.go index 68b9f2d130..81c1b74aad 100644 --- a/pkg/keystone/driver/oauth2/bingoiam/factory.go +++ b/pkg/keystone/driver/oauth2/bingoiam/factory.go @@ -45,6 +45,20 @@ func (drv SBingoIAMDriverFactory) ValidateConfig(conf api.SOAuth2IdpConfigOption return nil } +func (drv SBingoIAMDriverFactory) AttributeNames() map[string]string { + return map[string]string{ + "tenant_name": "Tenant name in BingoIAM", + "tenant_id": "Tenant ID in BingoIAM", + "name": "User name in BingoIAM", + "name_en": "English user name in BingoIAM", + "user_id": "User ID in BingoIAM", + "display_name": "Display name in BingoIAM", + "email": "Email in BingoIAM", + "mobile": "Mobile in BingoIAM", + "org_id": "Org ID in BingoIAM", + } +} + func init() { oauth2.Register(&SBingoIAMDriverFactory{}) } diff --git a/pkg/keystone/driver/oauth2/class.go b/pkg/keystone/driver/oauth2/class.go index de262d7c2e..4b3b72e59c 100644 --- a/pkg/keystone/driver/oauth2/class.go +++ b/pkg/keystone/driver/oauth2/class.go @@ -111,6 +111,14 @@ func (self *SOAuth2DriverClass) ValidateConfig(ctx context.Context, userCred mcc return tconf, nil } +func (self *SOAuth2DriverClass) AttributeNames(template string) (map[string]string, error) { + factory := findDriverFactory(template) + if factory == nil { + return nil, errors.Wrapf(httperrors.ErrNotSupported, "template %s not supported", template) + } + return factory.AttributeNames(), nil +} + func init() { driver.RegisterDriverClass(&SOAuth2DriverClass{}) } diff --git a/pkg/keystone/driver/oauth2/dingtalk/dingtalk.go b/pkg/keystone/driver/oauth2/dingtalk/dingtalk.go index b0932ca437..764829b87a 100644 --- a/pkg/keystone/driver/oauth2/dingtalk/dingtalk.go +++ b/pkg/keystone/driver/oauth2/dingtalk/dingtalk.go @@ -120,5 +120,7 @@ func (drv *SDingtalkOAuth2Driver) Authenticate(ctx context.Context, code string) ret := make(map[string][]string) ret["name"] = []string{data.Nick} ret["user_id"] = []string{data.Unionid} + ret["open_id"] = []string{data.Openid} + ret["union_id"] = []string{data.Unionid} return ret, nil } diff --git a/pkg/keystone/driver/oauth2/dingtalk/factory.go b/pkg/keystone/driver/oauth2/dingtalk/factory.go index 76e8bc3f84..00f28b555a 100644 --- a/pkg/keystone/driver/oauth2/dingtalk/factory.go +++ b/pkg/keystone/driver/oauth2/dingtalk/factory.go @@ -41,6 +41,15 @@ func (drv SDingtalkDriverFactory) ValidateConfig(conf api.SOAuth2IdpConfigOption return nil } +func (drv SDingtalkDriverFactory) AttributeNames() map[string]string { + return map[string]string{ + "name": "User name in Dingtalk", + "user_id": "UnionID in Dingtalk", + "open_id": "OpenID in Dingtalk", + "union_id": "UnionID in Dingtalk", + } +} + func init() { oauth2.Register(&SDingtalkDriverFactory{}) } diff --git a/pkg/keystone/driver/oauth2/feishu/factory.go b/pkg/keystone/driver/oauth2/feishu/factory.go index 6f7edb7cd4..ee8e1de53c 100644 --- a/pkg/keystone/driver/oauth2/feishu/factory.go +++ b/pkg/keystone/driver/oauth2/feishu/factory.go @@ -31,7 +31,7 @@ func (drv SFeishuDriverFactory) TemplateName() string { func (drv SFeishuDriverFactory) IdpAttributeOptions() api.SIdpAttributeOptions { return api.SIdpAttributeOptions{ - UserNameAttribute: "name_en", + UserNameAttribute: "name", UserIdAttribute: "user_id", UserDisplaynameAttribtue: "name", UserEmailAttribute: "email", @@ -43,6 +43,18 @@ func (drv SFeishuDriverFactory) ValidateConfig(conf api.SOAuth2IdpConfigOptions) return nil } +func (drv SFeishuDriverFactory) AttributeNames() map[string]string { + return map[string]string{ + "en_name": "User name in Feishu", + "user_id": "User ID in Feishu", + "name": "User name in Feishu", + "email": "Email in Feishu", + "mobile": "Mobile in Feishu", + "union_id": "Union ID in Feishu", + "open_id": "Open ID in Feishu", + } +} + func init() { oauth2.Register(&SFeishuDriverFactory{}) } diff --git a/pkg/keystone/driver/oauth2/feishu/feishu.go b/pkg/keystone/driver/oauth2/feishu/feishu.go index e1ac12fd32..0794e4bf97 100644 --- a/pkg/keystone/driver/oauth2/feishu/feishu.go +++ b/pkg/keystone/driver/oauth2/feishu/feishu.go @@ -76,6 +76,7 @@ type sAccessTokenData struct { Name string `json:"name"` EnName string `json:"en_name"` OpenID string `json:"open_id"` + UnionID string `json:"union_id"` TenantKey string `json:"tenant_key"` RefreshExpiresIn int64 `json:"refresh_expires_in"` RefreshToken string `json:"refresh_token"` @@ -177,8 +178,10 @@ func (drv *SFeishuOAuth2Driver) Authenticate(ctx context.Context, code string) ( ret := make(map[string][]string) ret["name"] = []string{userInfo.Name} ret["user_id"] = []string{userInfo.UserID} - ret["name_en"] = []string{accessData.EnName} + ret["en_name"] = []string{accessData.EnName} ret["email"] = []string{userInfo.Email} ret["mobile"] = []string{userInfo.Mobile} + ret["open_id"] = []string{accessData.OpenID} + ret["union_id"] = []string{accessData.UnionID} return ret, nil } diff --git a/pkg/keystone/driver/oauth2/oauth2.go b/pkg/keystone/driver/oauth2/oauth2.go index 9618fb3e52..64a1996dbc 100644 --- a/pkg/keystone/driver/oauth2/oauth2.go +++ b/pkg/keystone/driver/oauth2/oauth2.go @@ -80,8 +80,9 @@ func (self *SOAuth2Driver) Authenticate(ctx context.Context, ident mcclient.SAut if factory == nil { return nil, errors.Wrapf(httperrors.ErrNotSupported, "template %s not supported", self.Template) } - options := self.oauth2Config.SIdpAttributeOptions - options.Update(factory.IdpAttributeOptions()) + options := factory.IdpAttributeOptions() + options.Update(self.oauth2Config.SIdpAttributeOptions) + // options.Update(factory.IdpAttributeOptions()) driver := factory.NewDriver(self.oauth2Config.AppId, self.oauth2Config.Secret) ctx = context.WithValue(ctx, "config", self.SBaseIdentityDriver.Config) attrs, err := driver.Authenticate(ctx, ident.OAuth2.Code) diff --git a/pkg/keystone/driver/oauth2/qywechat/factory.go b/pkg/keystone/driver/oauth2/qywechat/factory.go index 9901619be9..c565a619cc 100644 --- a/pkg/keystone/driver/oauth2/qywechat/factory.go +++ b/pkg/keystone/driver/oauth2/qywechat/factory.go @@ -56,6 +56,16 @@ func (drv SQywxDriverFactory) ValidateConfig(conf api.SOAuth2IdpConfigOptions) e return nil } +func (drv SQywxDriverFactory) AttributeNames() map[string]string { + return map[string]string{ + "name": "User name in Wecom", + "user_id": "User ID in Wecom", + "displayname": "Display name in Wecom", + "email": "Email in Wecom", + "mobile": "Mobile in Wecom", + } +} + func init() { oauth2.Register(&SQywxDriverFactory{}) } diff --git a/pkg/keystone/driver/oauth2/types.go b/pkg/keystone/driver/oauth2/types.go index dcf7d12a59..14bb29785d 100644 --- a/pkg/keystone/driver/oauth2/types.go +++ b/pkg/keystone/driver/oauth2/types.go @@ -25,6 +25,7 @@ type IOAuth2DriverFactory interface { TemplateName() string IdpAttributeOptions() api.SIdpAttributeOptions ValidateConfig(conf api.SOAuth2IdpConfigOptions) error + AttributeNames() map[string]string } type IOAuth2Driver interface { diff --git a/pkg/keystone/driver/oauth2/wechat/factory.go b/pkg/keystone/driver/oauth2/wechat/factory.go index f5b79b550d..58359f30aa 100644 --- a/pkg/keystone/driver/oauth2/wechat/factory.go +++ b/pkg/keystone/driver/oauth2/wechat/factory.go @@ -41,6 +41,14 @@ func (drv SWechatDriverFactory) ValidateConfig(conf api.SOAuth2IdpConfigOptions) return nil } +func (drv SWechatDriverFactory) AttributeNames() map[string]string { + return map[string]string{ + "name": "User name", + "user_id": "OpenID of User in Wechat", + "union_id": "UnionID of User in Wechat", + } +} + func init() { oauth2.Register(&SWechatDriverFactory{}) } diff --git a/pkg/keystone/driver/oauth2/wechat/wechat.go b/pkg/keystone/driver/oauth2/wechat/wechat.go index 2e928cb787..b7e3577e47 100644 --- a/pkg/keystone/driver/oauth2/wechat/wechat.go +++ b/pkg/keystone/driver/oauth2/wechat/wechat.go @@ -150,5 +150,6 @@ func (drv *SWechatOAuth2Driver) Authenticate(ctx context.Context, code string) ( ret := make(map[string][]string) ret["name"] = []string{userInfo.Nickname} ret["user_id"] = []string{userInfo.Openid} + ret["union_id"] = []string{userInfo.Unionid} return ret, nil } diff --git a/pkg/keystone/driver/oidc/class.go b/pkg/keystone/driver/oidc/class.go index e4cbf1a6d6..f67649fc92 100644 --- a/pkg/keystone/driver/oidc/class.go +++ b/pkg/keystone/driver/oidc/class.go @@ -123,6 +123,20 @@ func (self *SOIDCDriverClass) ValidateConfig(ctx context.Context, userCred mccli return tconf, nil } +func (self *SOIDCDriverClass) AttributeNames(template string) (map[string]string, error) { + switch template { + case api.IdpTemplateDex: + return DexOIDCTemplate.AttributeNames, nil + case api.IdpTemplateGithub: + return GithubOIDCTemplate.AttributeNames, nil + case api.IdpTemplateAzureOAuth2: + return AzureADTemplate.AttributeNames, nil + case api.IdpTemplateGoogle: + return GoogleOIDCTemplate.AttributeNames, nil + } + return nil, nil +} + func init() { driver.RegisterDriverClass(&SOIDCDriverClass{}) } diff --git a/pkg/keystone/driver/oidc/template.go b/pkg/keystone/driver/oidc/template.go index d66bd8468d..a8b7eb99da 100644 --- a/pkg/keystone/driver/oidc/template.go +++ b/pkg/keystone/driver/oidc/template.go @@ -31,6 +31,11 @@ var ( UserEmailAttribute: "email", UserDisplaynameAttribtue: "name", }, + AttributeNames: map[string]string{ + "name": "User name in Dex", + "sub": "User ID in Dex", + "email": "User email in Dex", + }, } // https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/ // map[avatar_url:https://avatars1.githubusercontent.com/u/1121362?v=4 bio: blog:https://yunion.io collaborators:0 company:Yunion.io created_at:2011-10-12T04:18:27Z disk_usage:925302 email: events_url:https://api.github.com/users/swordqiu/events{/privacy} followers:13 followers_url:https://api.github.com/users/swordqiu/followers following:1 following_url:https://api.github.com/users/swordqiu/following{/other_user} gists_url:https://api.github.com/users/swordqiu/gists{/gist_id} gravatar_id: hireable: html_url:https://github.com/swordqiu @@ -51,6 +56,12 @@ var ( UserEmailAttribute: "email", UserDisplaynameAttribtue: "name", }, + AttributeNames: map[string]string{ + "name": "User name in Github", + "id": "User ID in Github", + "email": "User email in Github", + "login": "User login name in Github", + }, } // { @@ -71,6 +82,11 @@ var ( UserEmailAttribute: "email", UserDisplaynameAttribtue: "name", }, + AttributeNames: map[string]string{ + "name": "User name in Google", + "sub": "User ID in Google", + "email": "User email in Google", + }, } AzureADTemplate = api.SOIDCIdpConfigOptions{ @@ -86,5 +102,10 @@ var ( UserEmailAttribute: "email", UserDisplaynameAttribtue: "name", }, + AttributeNames: map[string]string{ + "name": "User name in Azure OAuth2", + "sub": "User ID in Azure OAuth2", + "email": "User email in Azure OAuth2", + }, } ) diff --git a/pkg/keystone/driver/saml/class.go b/pkg/keystone/driver/saml/class.go index 891854e698..142703f252 100644 --- a/pkg/keystone/driver/saml/class.go +++ b/pkg/keystone/driver/saml/class.go @@ -135,6 +135,16 @@ func (self *SSAMLDriverClass) ValidateConfig(ctx context.Context, userCred mccli return tconf, nil } +func (self *SSAMLDriverClass) AttributeNames(template string) (map[string]string, error) { + switch template { + case api.IdpTemplateSAMLTest: + return SAMLTestTemplate.AttributeNames, nil + case api.IdpTemplateAzureADSAML: + return AzureADTemplate.AttributeNames, nil + } + return nil, nil +} + func init() { driver.RegisterDriverClass(&SSAMLDriverClass{}) } diff --git a/pkg/keystone/driver/saml/template.go b/pkg/keystone/driver/saml/template.go index f425a66679..a99da89b7a 100644 --- a/pkg/keystone/driver/saml/template.go +++ b/pkg/keystone/driver/saml/template.go @@ -27,6 +27,12 @@ var ( UserEmailAttribute: "urn:oid:0.9.2342.19200300.100.1.3", UserMobileAttribute: "urn:oid:2.5.4.20", }, + AttributeNames: map[string]string{ + "urn:oid:0.9.2342.19200300.100.1.1": "User name", + "urn:oid:2.16.840.1.113730.3.1.241": "User display name", + "urn:oid:0.9.2342.19200300.100.1.3": "User email", + "urn:oid:2.5.4.20": "User mobile", + }, } AzureADTemplate = api.SSAMLIdpConfigOptions{ @@ -37,5 +43,11 @@ var ( UserEmailAttribute: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", UserMobileAttribute: "", }, + AttributeNames: map[string]string{ + "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "User name", + "http://schemas.microsoft.com/identity/claims/objectidentifier": "User ID", + "http://schemas.microsoft.com/identity/claims/displayname": "User display name", + "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress": "User email", + }, } ) diff --git a/pkg/keystone/driver/sql/class.go b/pkg/keystone/driver/sql/class.go index a288ae35d0..e064137cc7 100644 --- a/pkg/keystone/driver/sql/class.go +++ b/pkg/keystone/driver/sql/class.go @@ -56,6 +56,10 @@ func (self *SSQLDriverClass) ValidateConfig(ctx context.Context, userCred mcclie return conf, nil } +func (self *SSQLDriverClass) AttributeNames(template string) (map[string]string, error) { + return nil, nil +} + func init() { driver.RegisterDriverClass(&SSQLDriverClass{}) } diff --git a/pkg/keystone/models/assignments.go b/pkg/keystone/models/assignments.go index 7e04a14c71..33aa860635 100644 --- a/pkg/keystone/models/assignments.go +++ b/pkg/keystone/models/assignments.go @@ -252,7 +252,11 @@ func (manager *SAssignmentManager) fetchProjectRoleUserIdsQuery(projId, roleId s q1 = q1.Equals("role_id", roleId) } - assigns := AssignmentManager.Query().SubQuery() + assignsQ := AssignmentManager.Query() + if len(roleId) > 0 { + assignsQ = assignsQ.Equals("role_id", roleId) + } + assigns := assignsQ.SubQuery() usergroups := UsergroupManager.Query().SubQuery() q2 := usergroups.Query(usergroups.Field("user_id", "actor_id")) @@ -262,9 +266,6 @@ func (manager *SAssignmentManager) fetchProjectRoleUserIdsQuery(projId, roleId s q2 = q2.Filter(sqlchemy.Equals(assigns.Field("type"), api.AssignmentGroupProject)) q2 = q2.Filter(sqlchemy.Equals(assigns.Field("target_id"), projId)) q2 = q2.Filter(sqlchemy.IsFalse(assigns.Field("inherited"))) - if len(roleId) > 0 { - q2 = q2.Equals("role_id", roleId) - } union := sqlchemy.Union(q1, q2) return union.Query().Distinct() diff --git a/pkg/keystone/models/identity_provider.go b/pkg/keystone/models/identity_provider.go index 8617c61ac6..5e040a8faa 100644 --- a/pkg/keystone/models/identity_provider.go +++ b/pkg/keystone/models/identity_provider.go @@ -347,6 +347,38 @@ func (manager *SIdentityProviderManager) getDriveInstanceCount(drvName string) ( return manager.Query().Equals("driver", drvName).CountWithError() } +func (manager *SIdentityProviderManager) GetPropertyAttributeNames(ctx context.Context, userCred mcclient.TokenCredential, input api.IdentityProviderPropertyAttributeNamesInput) (jsonutils.JSONObject, error) { + var drvName string + + template := input.Template + if len(template) > 0 { + if _, ok := api.IdpTemplateDriver[template]; !ok { + return nil, httperrors.NewInputParameterError("invalid template") + } + drvName = api.IdpTemplateDriver[template] + input.Driver = drvName + } else { + drvName = input.Driver + if len(drvName) == 0 { + return nil, httperrors.NewInputParameterError("missing driver") + } + } + + drvCls := driver.GetDriverClass(drvName) + if drvCls == nil { + return nil, httperrors.NewInputParameterError("driver %s not supported", drvName) + } + + attrs, err := drvCls.AttributeNames(input.Template) + if err != nil { + return nil, errors.Wrap(err, "AttributeNames") + } + if len(attrs) == 0 { + return jsonutils.NewDict(), nil + } + return jsonutils.Marshal(attrs), nil +} + func (manager *SIdentityProviderManager) ValidateCreateData( ctx context.Context, userCred mcclient.TokenCredential,