mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-06 05:01:10 -05:00
145 lines
4.0 KiB
Go
145 lines
4.0 KiB
Go
package ldapentry
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/go-ldap/ldap/v3"
|
|
"golang.org/x/text/cases"
|
|
)
|
|
|
|
func ApplyModify(old *ldap.Entry, mod *ldap.ModifyRequest) (newEntry *ldap.Entry, err error) {
|
|
oldDN, err := ldap.ParseDN(old.DN)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
rdn := oldDN.RDNs[0]
|
|
modDN, err := ldap.ParseDN(mod.DN)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// This shouldn't happen if we ge here (TM)
|
|
if !oldDN.EqualFold(modDN) {
|
|
return nil, ldap.NewError(ldap.LDAPResultUnwillingToPerform, errors.New("DNs do not match"))
|
|
}
|
|
|
|
casefold := cases.Fold()
|
|
newEntry = ldap.NewEntry(old.DN, map[string][]string{})
|
|
newEntry.Attributes = old.Attributes
|
|
for _, c := range mod.Changes {
|
|
nType := casefold.String(c.Modification.Type)
|
|
switch c.Operation {
|
|
case ldap.AddAttribute:
|
|
newValues := entryApplyModAdd(newEntry.GetEqualFoldAttributeValues(nType), c.Modification.Vals)
|
|
newEntry.Attributes = entryReplaceValues(newEntry.Attributes, c.Modification.Type, newValues)
|
|
|
|
case ldap.ReplaceAttribute:
|
|
// Modifies on RDN attributes need special care to make sure that the rdn Value is not removed
|
|
for _, rdnAttr := range rdn.Attributes {
|
|
if nType == casefold.String(rdnAttr.Type) {
|
|
rdnPresent := false
|
|
nRdnVal := casefold.String(rdnAttr.Value)
|
|
for _, newVal := range c.Modification.Vals {
|
|
if nRdnVal == casefold.String(newVal) {
|
|
rdnPresent = true
|
|
break
|
|
}
|
|
}
|
|
if !rdnPresent {
|
|
return nil, ldap.NewError(ldap.LDAPResultNotAllowedOnRDN, errors.New(""))
|
|
}
|
|
}
|
|
}
|
|
newEntry.Attributes = entryReplaceValues(newEntry.Attributes, c.Modification.Type, c.Modification.Vals)
|
|
case ldap.DeleteAttribute:
|
|
for _, rdnAttr := range rdn.Attributes {
|
|
// Modifies on RDN attributes need special care
|
|
if nType == casefold.String(rdnAttr.Type) {
|
|
if len(c.Modification.Vals) == 0 {
|
|
return nil, ldap.NewError(ldap.LDAPResultNotAllowedOnRDN, errors.New(""))
|
|
}
|
|
nRdnVal := casefold.String(rdnAttr.Value)
|
|
for _, delVal := range c.Modification.Vals {
|
|
if nRdnVal == casefold.String(delVal) {
|
|
return nil, ldap.NewError(ldap.LDAPResultNotAllowedOnRDN, errors.New(""))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
newValues := entryApplyModDelete(old.GetEqualFoldAttributeValues(nType), c.Modification.Vals)
|
|
newEntry.Attributes = entryReplaceValues(newEntry.Attributes, c.Modification.Type, newValues)
|
|
}
|
|
}
|
|
return newEntry, nil
|
|
}
|
|
|
|
func entryReplaceValues(ea []*ldap.EntryAttribute, attrType string, newValues []string) (updatedAttrs []*ldap.EntryAttribute) {
|
|
casefold := cases.Fold()
|
|
nType := casefold.String(attrType)
|
|
updated := false
|
|
for _, attr := range ea {
|
|
if casefold.String(attr.Name) == nType {
|
|
updated = true
|
|
if len(newValues) == 0 {
|
|
continue
|
|
}
|
|
updatedAttrs = append(updatedAttrs, ldap.NewEntryAttribute(attr.Name, newValues))
|
|
} else {
|
|
updatedAttrs = append(updatedAttrs, attr)
|
|
}
|
|
}
|
|
if !updated {
|
|
if len(newValues) != 0 {
|
|
updatedAttrs = append(updatedAttrs, ldap.NewEntryAttribute(attrType, newValues))
|
|
}
|
|
}
|
|
return updatedAttrs
|
|
}
|
|
|
|
func entryApplyModAdd(curVals, addVals []string) (newVals []string) {
|
|
newVals = curVals
|
|
casefold := cases.Fold()
|
|
for _, newVal := range addVals {
|
|
present := false
|
|
for _, val := range curVals {
|
|
if casefold.String(newVal) == casefold.String(val) {
|
|
present = true
|
|
break
|
|
}
|
|
}
|
|
if !present {
|
|
newVals = append(newVals, newVal)
|
|
}
|
|
}
|
|
return newVals
|
|
}
|
|
|
|
func entryApplyModDelete(curVals, delVals []string) (newVals []string) {
|
|
casefold := cases.Fold()
|
|
if len(delVals) == 0 {
|
|
return []string{}
|
|
}
|
|
for _, curVal := range curVals {
|
|
nCurVal := casefold.String(curVal)
|
|
keep := true
|
|
for _, del := range delVals {
|
|
if nCurVal == casefold.String(del) {
|
|
keep = false
|
|
break
|
|
}
|
|
}
|
|
if keep {
|
|
newVals = append(newVals, curVal)
|
|
}
|
|
}
|
|
return newVals
|
|
}
|
|
|
|
func EntryFromAddRequest(add *ldap.AddRequest) *ldap.Entry {
|
|
attrs := map[string][]string{}
|
|
|
|
for _, a := range add.Attributes {
|
|
attrs[a.Type] = a.Vals
|
|
}
|
|
return ldap.NewEntry(add.DN, attrs)
|
|
}
|