Compare commits

...

2 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
0cc3e0acdb Fix: Shared Application Does Not Allow Login for Users Across All Linked Organizations
When using a shared application, users from organizations that have set the
shared app as their default application are now able to log in.

Changes:
- Add GetUserOrganizationForSharedApp() to resolve actual user org for shared apps
- Fix CheckLoginPermission() to allow users from orgs linked to the shared app
- Update Login() controller to resolve user org before user lookup for all methods"

Co-authored-by: hsluoyz <3787410+hsluoyz@users.noreply.github.com>
Agent-Logs-Url: https://github.com/casdoor/casdoor/sessions/4c4a727f-2dca-4e1c-9265-1cb7763d1378
2026-03-25 13:07:15 +00:00
copilot-swe-agent[bot]
2694251a2d Initial plan 2026-03-25 12:50:21 +00:00
3 changed files with 85 additions and 16 deletions

View File

@@ -535,14 +535,6 @@ func (c *ApiController) Login() {
if authForm.Username != "" {
var user *object.User
if authForm.SigninMethod == "Face ID" {
if user, err = object.GetUserByFields(authForm.Organization, authForm.Username); err != nil {
c.ResponseError(err.Error(), nil)
return
} else if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(authForm.Organization, authForm.Username)))
return
}
var application *object.Application
application, err = object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
if err != nil {
@@ -555,6 +547,20 @@ func (c *ApiController) Login() {
return
}
authForm.Organization, err = object.GetUserOrganizationForSharedApp(application, authForm.Organization, authForm.Username)
if err != nil {
c.ResponseError(err.Error(), nil)
return
}
if user, err = object.GetUserByFields(authForm.Organization, authForm.Username); err != nil {
c.ResponseError(err.Error(), nil)
return
} else if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(authForm.Organization, authForm.Username)))
return
}
if !application.IsFaceIdEnabled() {
c.ResponseError(c.T("auth:The login method: login with face is not enabled for the application"))
return
@@ -582,14 +588,6 @@ func (c *ApiController) Login() {
}
}
} else if authForm.Password == "" {
if user, err = object.GetUserByFields(authForm.Organization, authForm.Username); err != nil {
c.ResponseError(err.Error(), nil)
return
} else if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(authForm.Organization, authForm.Username)))
return
}
var application *object.Application
application, err = object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
if err != nil {
@@ -602,6 +600,20 @@ func (c *ApiController) Login() {
return
}
authForm.Organization, err = object.GetUserOrganizationForSharedApp(application, authForm.Organization, authForm.Username)
if err != nil {
c.ResponseError(err.Error(), nil)
return
}
if user, err = object.GetUserByFields(authForm.Organization, authForm.Username); err != nil {
c.ResponseError(err.Error(), nil)
return
} else if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(authForm.Organization, authForm.Username)))
return
}
verificationCodeType := object.GetVerifyType(authForm.Username)
if verificationCodeType == object.VerifyTypeEmail && !application.IsCodeSigninViaEmailEnabled() {
c.ResponseError(c.T("auth:The login method: login with email is not enabled for the application"))
@@ -719,6 +731,11 @@ func (c *ApiController) Login() {
} else {
isPasswordWithLdapEnabled = false
}
authForm.Organization, err = object.GetUserOrganizationForSharedApp(application, authForm.Organization, authForm.Username)
if err != nil {
c.ResponseError(err.Error())
return
}
user, err = object.CheckUserPassword(authForm.Organization, authForm.Username, password, c.GetAcceptLanguage(), enableCaptcha, isSigninViaLdap, isPasswordWithLdapEnabled)
}

View File

@@ -587,6 +587,17 @@ func CheckLoginPermission(userId string, application *Application) (bool, error)
return true, nil
}
// For shared applications, allow users from organizations that have this app as their default application
if application.IsShared && owner != application.Organization {
userOrg, err := getOrganization("admin", owner)
if err != nil {
return false, err
}
if userOrg != nil && userOrg.DefaultApplication == application.Name {
return true, nil
}
}
permissions, err := GetPermissions(application.Organization)
if err != nil {
return false, err

View File

@@ -103,6 +103,47 @@ func GetUserByFields(organization string, field string) (*User, error) {
return nil, nil
}
// GetUserOrganizationForSharedApp resolves the actual organization of a user when logging in via a shared application.
// If the user is not found in the specified organization and the application is shared,
// it searches in all organizations that have this app as their default application.
// Returns the resolved organization name.
func GetUserOrganizationForSharedApp(application *Application, organization string, username string) (string, error) {
if application == nil || !application.IsShared {
return organization, nil
}
// Check if user exists in the specified organization first
user, err := GetUserByFields(organization, username)
if err != nil {
return organization, err
}
if user != nil {
return organization, nil
}
// User not found in the default org, search in organizations that have this shared app as their default
organizations := []*Organization{}
err = ormer.Engine.Where("default_application=?", application.Name).Find(&organizations)
if err != nil {
return organization, err
}
for _, org := range organizations {
if org.Name == organization {
continue // Already checked
}
user, err = GetUserByFields(org.Name, username)
if err != nil {
return organization, err
}
if user != nil {
return org.Name, nil
}
}
return organization, nil
}
func SetUserField(user *User, field string, value string) (bool, error) {
bean := make(map[string]interface{})
if field == "password" {