Add support for assigning education users to schools

This commit is contained in:
Ralf Haferkamp
2022-12-15 19:36:19 +01:00
committed by Ralf Haferkamp
parent 80a2c72491
commit 336f128e71
2 changed files with 99 additions and 10 deletions

View File

@@ -15,11 +15,14 @@ import (
)
type educationConfig struct {
schoolBaseDN string
schoolFilter string
schoolObjectClass string
schoolScope int
schoolAttributeMap schoolAttributeMap
schoolBaseDN string
schoolFilter string
schoolObjectClass string
schoolScope int
// memberOfSchoolAttribute defines the AttributeType on the user/group objects
// which contains the school Id to which the user/group is assigned
memberOfSchoolAttribute string
schoolAttributeMap schoolAttributeMap
userObjectClass string
userAttributeMap educationUserAttributeMap
@@ -33,9 +36,10 @@ type schoolAttributeMap struct {
func defaultEducationConfig() educationConfig {
return educationConfig{
schoolObjectClass: "ocEducationSchool",
schoolScope: ldap.ScopeWholeSubtree,
schoolAttributeMap: newSchoolAttributeMap(),
schoolObjectClass: "ocEducationSchool",
schoolScope: ldap.ScopeWholeSubtree,
memberOfSchoolAttribute: "ocMemberOfSchool",
schoolAttributeMap: newSchoolAttributeMap(),
userObjectClass: "ocEducationUser",
userAttributeMap: newEducationUserAttributeMap(),
@@ -140,6 +144,8 @@ func (i *LDAP) DeleteEducationSchool(ctx context.Context, id string) error {
if err = i.conn.Del(&dr); err != nil {
return err
}
// TODO update any users that are member of this school
return nil
}
@@ -206,8 +212,48 @@ func (i *LDAP) GetEducationSchoolMembers(ctx context.Context, id string) ([]*lib
}
// AddMembersToEducationSchool adds new members (reference by a slice of IDs) to supplied school in the identity backend.
func (i *LDAP) AddMembersToEducationSchool(ctx context.Context, schoolID string, memberID []string) error {
return errNotImplemented
func (i *LDAP) AddMembersToEducationSchool(ctx context.Context, schoolID string, memberIDs []string) error {
logger := i.logger.SubloggerWithRequestID(ctx)
logger.Debug().Str("backend", "ldap").Msg("AddMembersToEducationSchool")
schoolEntry, err := i.getSchoolByID(schoolID)
if err != nil {
return err
}
if schoolEntry == nil {
return errNotFound
}
userEntries := make([]*ldap.Entry, 0, len(memberIDs))
for _, memberID := range memberIDs {
user, err := i.getEducationUserByNameOrID(memberID)
if err != nil {
i.logger.Warn().Str("userid", memberID).Msg("User does not exist")
return err
}
userEntries = append(userEntries, user)
}
for _, userEntry := range userEntries {
currentSchools := userEntry.GetEqualFoldAttributeValues(i.educationConfig.memberOfSchoolAttribute)
found := false
for _, currentSchool := range currentSchools {
if currentSchool == schoolID {
found = true
break
}
}
if !found {
mr := ldap.ModifyRequest{DN: userEntry.DN}
mr.Add(i.educationConfig.memberOfSchoolAttribute, []string{schoolID})
if err := i.conn.Modify(&mr); err != nil {
return err
}
}
}
return nil
}
// RemoveMemberFromEducationSchool removes a single member (by ID) from a school

View File

@@ -167,3 +167,46 @@ func TestGetEducationSchools(t *testing.T) {
lm.AssertNumberOfCalls(t, "Search", 1)
assert.Nil(t, err)
}
func TestAddMembersToEducationSchool(t *testing.T) {
lm := &mocks.Client{}
sr1 := &ldap.SearchRequest{
BaseDN: "",
Scope: 2,
SizeLimit: 1,
Filter: "(&(objectClass=ocEducationSchool)(owncloudUUID=abcd-defg))",
Attributes: []string{"ou", "owncloudUUID", "ocEducationSchoolNumber"},
Controls: []ldap.Control(nil),
}
sr2 := &ldap.SearchRequest{
BaseDN: "ou=people,dc=test",
Scope: 2,
SizeLimit: 1,
Filter: "(&(objectClass=ocEducationUser)(|(uid=abcd-defg)(entryUUID=abcd-defg)))",
Attributes: []string{"displayname", "entryUUID", "mail", "uid", "oCExternalIdentity", "userClass"},
Controls: []ldap.Control(nil),
}
sr3 := &ldap.SearchRequest{
BaseDN: "ou=people,dc=test",
Scope: 2,
SizeLimit: 1,
Filter: "(&(objectClass=ocEducationUser)(|(uid=does-not-exist)(entryUUID=does-not-exist)))",
Attributes: []string{"displayname", "entryUUID", "mail", "uid", "oCExternalIdentity", "userClass"},
Controls: []ldap.Control(nil),
}
lm.On("Search", sr1).Return(&ldap.SearchResult{Entries: []*ldap.Entry{schoolEntry, schoolEntry1}}, nil)
lm.On("Search", sr2).Return(&ldap.SearchResult{Entries: []*ldap.Entry{eduUserEntry}}, nil)
lm.On("Search", sr3).Return(&ldap.SearchResult{Entries: []*ldap.Entry{}}, nil)
lm.On("Modify", mock.Anything).Return(nil)
b, err := getMockedBackend(lm, eduConfig, &logger)
assert.Nil(t, err)
err = b.AddMembersToEducationSchool(context.Background(), "abcd-defg", []string{"does-not-exist"})
lm.AssertNumberOfCalls(t, "Search", 2)
assert.NotNil(t, err)
err = b.AddMembersToEducationSchool(context.Background(), "abcd-defg", []string{"abcd-defg", "does-not-exist"})
lm.AssertNumberOfCalls(t, "Search", 5)
assert.NotNil(t, err)
err = b.AddMembersToEducationSchool(context.Background(), "abcd-defg", []string{"abcd-defg"})
lm.AssertNumberOfCalls(t, "Search", 7)
assert.Nil(t, err)
}