[MM-62412] Block login of SAML users if no connected LDAP user is found (#29786)

Этот коммит содержится в:
Ben Schumacher
2025-04-17 14:06:23 +02:00
коммит произвёл GitHub
родитель b548a8f336
Коммит 00a242b879
3 изменённых файлов: 41 добавлений и 77 удалений

Просмотреть файл

@@ -11,9 +11,8 @@ import (
type LdapInterface interface { type LdapInterface interface {
DoLogin(c request.CTX, id string, password string) (*model.User, *model.AppError) DoLogin(c request.CTX, id string, password string) (*model.User, *model.AppError)
GetUser(c request.CTX, id string) (*model.User, *model.AppError) GetUser(c request.CTX, id string) (*model.User, *model.AppError)
GetLDAPUserForMMUser(rctx request.CTX, mmUser *model.User) (*model.User, string, *model.AppError)
GetUserAttributes(rctx request.CTX, id string, attributes []string) (map[string]string, *model.AppError) GetUserAttributes(rctx request.CTX, id string, attributes []string) (map[string]string, *model.AppError)
CheckPassword(c request.CTX, id string, password string) *model.AppError
CheckPasswordAuthData(c request.CTX, authData string, password string) *model.AppError
CheckProviderAttributes(c request.CTX, LS *model.LdapSettings, ouser *model.User, patch *model.UserPatch) string CheckProviderAttributes(c request.CTX, LS *model.LdapSettings, ouser *model.User, patch *model.UserPatch) string
SwitchToLdap(c request.CTX, userID, ldapID, ldapPassword string) *model.AppError SwitchToLdap(c request.CTX, userID, ldapID, ldapPassword string) *model.AppError
StartSynchronizeJob(c request.CTX, waitForJobToFinish bool, includeRemovedMembers bool) (*model.Job, *model.AppError) StartSynchronizeJob(c request.CTX, waitForJobToFinish bool, includeRemovedMembers bool) (*model.Job, *model.AppError)
@@ -21,10 +20,8 @@ type LdapInterface interface {
MigrateIDAttribute(c request.CTX, toAttribute string) error MigrateIDAttribute(c request.CTX, toAttribute string) error
GetGroup(rctx request.CTX, groupUID string) (*model.Group, *model.AppError) GetGroup(rctx request.CTX, groupUID string) (*model.Group, *model.AppError)
GetAllGroupsPage(rctx request.CTX, page int, perPage int, opts model.LdapGroupSearchOpts) ([]*model.Group, int, *model.AppError) GetAllGroupsPage(rctx request.CTX, page int, perPage int, opts model.LdapGroupSearchOpts) ([]*model.Group, int, *model.AppError)
FirstLoginSync(c request.CTX, user *model.User, userAuthService, userAuthData, email string) *model.AppError FirstLoginSync(c request.CTX, user *model.User) *model.AppError
UpdateProfilePictureIfNecessary(request.CTX, model.User, model.Session) UpdateProfilePictureIfNecessary(request.CTX, model.User, model.Session)
GetADLdapIdFromSAMLId(c request.CTX, authData string) string
GetSAMLIdFromADLdapId(c request.CTX, authData string) string
} }
type LdapDiagnosticInterface interface { type LdapDiagnosticInterface interface {

Просмотреть файл

@@ -15,46 +15,6 @@ type LdapInterface struct {
mock.Mock mock.Mock
} }
// CheckPassword provides a mock function with given fields: c, id, password
func (_m *LdapInterface) CheckPassword(c request.CTX, id string, password string) *model.AppError {
ret := _m.Called(c, id, password)
if len(ret) == 0 {
panic("no return value specified for CheckPassword")
}
var r0 *model.AppError
if rf, ok := ret.Get(0).(func(request.CTX, string, string) *model.AppError); ok {
r0 = rf(c, id, password)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*model.AppError)
}
}
return r0
}
// CheckPasswordAuthData provides a mock function with given fields: c, authData, password
func (_m *LdapInterface) CheckPasswordAuthData(c request.CTX, authData string, password string) *model.AppError {
ret := _m.Called(c, authData, password)
if len(ret) == 0 {
panic("no return value specified for CheckPasswordAuthData")
}
var r0 *model.AppError
if rf, ok := ret.Get(0).(func(request.CTX, string, string) *model.AppError); ok {
r0 = rf(c, authData, password)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*model.AppError)
}
}
return r0
}
// CheckProviderAttributes provides a mock function with given fields: c, LS, ouser, patch // CheckProviderAttributes provides a mock function with given fields: c, LS, ouser, patch
func (_m *LdapInterface) CheckProviderAttributes(c request.CTX, LS *model.LdapSettings, ouser *model.User, patch *model.UserPatch) string { func (_m *LdapInterface) CheckProviderAttributes(c request.CTX, LS *model.LdapSettings, ouser *model.User, patch *model.UserPatch) string {
ret := _m.Called(c, LS, ouser, patch) ret := _m.Called(c, LS, ouser, patch)
@@ -105,17 +65,17 @@ func (_m *LdapInterface) DoLogin(c request.CTX, id string, password string) (*mo
return r0, r1 return r0, r1
} }
// FirstLoginSync provides a mock function with given fields: c, user, userAuthService, userAuthData, email // FirstLoginSync provides a mock function with given fields: c, user
func (_m *LdapInterface) FirstLoginSync(c request.CTX, user *model.User, userAuthService string, userAuthData string, email string) *model.AppError { func (_m *LdapInterface) FirstLoginSync(c request.CTX, user *model.User) *model.AppError {
ret := _m.Called(c, user, userAuthService, userAuthData, email) ret := _m.Called(c, user)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for FirstLoginSync") panic("no return value specified for FirstLoginSync")
} }
var r0 *model.AppError var r0 *model.AppError
if rf, ok := ret.Get(0).(func(request.CTX, *model.User, string, string, string) *model.AppError); ok { if rf, ok := ret.Get(0).(func(request.CTX, *model.User) *model.AppError); ok {
r0 = rf(c, user, userAuthService, userAuthData, email) r0 = rf(c, user)
} else { } else {
if ret.Get(0) != nil { if ret.Get(0) != nil {
r0 = ret.Get(0).(*model.AppError) r0 = ret.Get(0).(*model.AppError)
@@ -125,24 +85,6 @@ func (_m *LdapInterface) FirstLoginSync(c request.CTX, user *model.User, userAut
return r0 return r0
} }
// GetADLdapIdFromSAMLId provides a mock function with given fields: c, authData
func (_m *LdapInterface) GetADLdapIdFromSAMLId(c request.CTX, authData string) string {
ret := _m.Called(c, authData)
if len(ret) == 0 {
panic("no return value specified for GetADLdapIdFromSAMLId")
}
var r0 string
if rf, ok := ret.Get(0).(func(request.CTX, string) string); ok {
r0 = rf(c, authData)
} else {
r0 = ret.Get(0).(string)
}
return r0
}
// GetAllGroupsPage provides a mock function with given fields: rctx, page, perPage, opts // GetAllGroupsPage provides a mock function with given fields: rctx, page, perPage, opts
func (_m *LdapInterface) GetAllGroupsPage(rctx request.CTX, page int, perPage int, opts model.LdapGroupSearchOpts) ([]*model.Group, int, *model.AppError) { func (_m *LdapInterface) GetAllGroupsPage(rctx request.CTX, page int, perPage int, opts model.LdapGroupSearchOpts) ([]*model.Group, int, *model.AppError) {
ret := _m.Called(rctx, page, perPage, opts) ret := _m.Called(rctx, page, perPage, opts)
@@ -246,22 +188,43 @@ func (_m *LdapInterface) GetGroup(rctx request.CTX, groupUID string) (*model.Gro
return r0, r1 return r0, r1
} }
// GetSAMLIdFromADLdapId provides a mock function with given fields: c, authData // GetLDAPUserForMMUser provides a mock function with given fields: rctx, mmUser
func (_m *LdapInterface) GetSAMLIdFromADLdapId(c request.CTX, authData string) string { func (_m *LdapInterface) GetLDAPUserForMMUser(rctx request.CTX, mmUser *model.User) (*model.User, string, *model.AppError) {
ret := _m.Called(c, authData) ret := _m.Called(rctx, mmUser)
if len(ret) == 0 { if len(ret) == 0 {
panic("no return value specified for GetSAMLIdFromADLdapId") panic("no return value specified for GetLDAPUserForMMUser")
} }
var r0 string var r0 *model.User
if rf, ok := ret.Get(0).(func(request.CTX, string) string); ok { var r1 string
r0 = rf(c, authData) var r2 *model.AppError
if rf, ok := ret.Get(0).(func(request.CTX, *model.User) (*model.User, string, *model.AppError)); ok {
return rf(rctx, mmUser)
}
if rf, ok := ret.Get(0).(func(request.CTX, *model.User) *model.User); ok {
r0 = rf(rctx, mmUser)
} else { } else {
r0 = ret.Get(0).(string) if ret.Get(0) != nil {
r0 = ret.Get(0).(*model.User)
}
} }
return r0 if rf, ok := ret.Get(1).(func(request.CTX, *model.User) string); ok {
r1 = rf(rctx, mmUser)
} else {
r1 = ret.Get(1).(string)
}
if rf, ok := ret.Get(2).(func(request.CTX, *model.User) *model.AppError); ok {
r2 = rf(rctx, mmUser)
} else {
if ret.Get(2) != nil {
r2 = ret.Get(2).(*model.AppError)
}
}
return r0, r1, r2
} }
// GetUser provides a mock function with given fields: c, id // GetUser provides a mock function with given fields: c, id

Просмотреть файл

@@ -8364,6 +8364,10 @@
"id": "ent.saml.license_disable.app_error", "id": "ent.saml.license_disable.app_error",
"translation": "Your license does not support SAML authentication." "translation": "Your license does not support SAML authentication."
}, },
{
"id": "ent.saml.login.ldap_user_missing",
"translation": "No user registered on AD/LDAP server that matches the SAML user."
},
{ {
"id": "ent.saml.metadata.app_error", "id": "ent.saml.metadata.app_error",
"translation": "An error occurred while building Service Provider Metadata." "translation": "An error occurred while building Service Provider Metadata."