Commit 34f46d7f authored by ale's avatar ale

Allow the LDAP model to distinguish resource types based on subtree

Lets us tell mailing lists and newsletters apart as different resources.
parent 6e5e73c4
Pipeline #3978 passed with stages
in 4 minutes and 15 seconds
......@@ -174,7 +174,7 @@ func TestModel_GetUser_Resources(t *testing.T) {
}
}
func TestModel_GetUser_MailingLists(t *testing.T) {
func TestModel_GetUser_MailingListsAndNewsletters(t *testing.T) {
stop, _, user := startServerAndGetUser4(t)
defer stop()
......@@ -182,7 +182,13 @@ func TestModel_GetUser_MailingLists(t *testing.T) {
// The backend should find two lists, one of which has an alias as the owner.
lists := user.GetResourcesByType(as.ResourceTypeMailingList)
if l := len(lists); l != 2 {
t.Fatalf("test user has %d mailing lists, expected %d", l, 2)
t.Errorf("test user has %d mailing lists, expected %d", l, 2)
}
// The test user has 1 newsletter.
nls := user.GetResourcesByType(as.ResourceTypeNewsletter)
if l := len(nls); l != 1 {
t.Errorf("test user has %d newsletters, expected %d", l, 1)
}
}
......
......@@ -94,6 +94,7 @@ func setCommonResourceAttrs(entry *ldap.Entry, rsrc *as.Resource) {
func (reg *resourceRegistry) FromLDAP(entry *ldap.Entry) (rsrc *as.Resource, err error) {
// Since we don't know what resource type to expect, we try
// all known handlers until one returns a valid Resource.
// This is slightly dangerous unless all
for _, h := range reg.handlers {
rsrc, err = h.FromLDAP(entry)
if err == nil {
......@@ -117,7 +118,10 @@ type emailResourceHandler struct {
baseDN string
}
var errWrongObjectClass = errors.New("objectClass does not match")
var (
errWrongObjectClass = errors.New("objectClass does not match")
errWrongSubtree = errors.New("subtree does not match")
)
func (h *emailResourceHandler) MakeDN(user *as.User, rsrc *as.Resource) (string, error) {
if user == nil {
......@@ -166,9 +170,24 @@ func (h *emailResourceHandler) SearchQuery() *queryTemplate {
}
}
// Mailing list resource.
// Mailing list resource. They are stored on a separate LDAP subtree.
type mailingListResourceHandler struct {
baseDN string
// Keep around a parsed DN for the ou=Lists root, so we can
// easily call DN.AncestorOf in FromLDAP later.
listsDN *ldap.DN
}
func newMailingListResourceHandler(baseDN string) *mailingListResourceHandler {
dn, err := ldap.ParseDN(joinDN("ou=Lists", baseDN))
if err != nil {
panic(err)
}
return &mailingListResourceHandler{
baseDN: baseDN,
listsDN: dn,
}
}
func (h *mailingListResourceHandler) MakeDN(_ *as.User, rsrc *as.Resource) (string, error) {
......@@ -182,9 +201,18 @@ func (h *mailingListResourceHandler) GetOwner(rsrc *as.Resource) string {
}
func (h *mailingListResourceHandler) FromLDAP(entry *ldap.Entry) (*as.Resource, error) {
// Match on objectClass and subtree (the mailingList
// objectClass is also used by newsletters).
if !isObjectClass(entry, "mailingList") {
return nil, errWrongObjectClass
}
dn, err := ldap.ParseDN(entry.DN)
if err != nil {
panic(err)
}
if !h.listsDN.AncestorOf(dn) {
return nil, errWrongSubtree
}
listName := entry.GetAttributeValue("listName")
return &as.Resource{
......@@ -215,9 +243,25 @@ func (h *mailingListResourceHandler) SearchQuery() *queryTemplate {
}
}
// Newsletter resource.
// Newsletter resource. Like mailing lists, these are stored on their
// own separate subtree.
type newsletterResourceHandler struct {
baseDN string
// Keep around a parsed DN for the ou=Newsletters root, so we can
// easily call DN.AncestorOf in FromLDAP later.
newslettersDN *ldap.DN
}
func newNewsletterResourceHandler(baseDN string) *newsletterResourceHandler {
dn, err := ldap.ParseDN(joinDN("ou=Newsletters", baseDN))
if err != nil {
panic(err)
}
return &newsletterResourceHandler{
baseDN: baseDN,
newslettersDN: dn,
}
}
func (h *newsletterResourceHandler) MakeDN(_ *as.User, rsrc *as.Resource) (string, error) {
......@@ -231,9 +275,17 @@ func (h *newsletterResourceHandler) GetOwner(rsrc *as.Resource) string {
}
func (h *newsletterResourceHandler) FromLDAP(entry *ldap.Entry) (*as.Resource, error) {
// Match on objectClass and subtree.
if !isObjectClass(entry, "mailingList") {
return nil, errWrongObjectClass
}
dn, err := ldap.ParseDN(entry.DN)
if err != nil {
panic(err)
}
if !h.newslettersDN.AncestorOf(dn) {
return nil, errWrongSubtree
}
listName := entry.GetAttributeValue("listName")
return &as.Resource{
......@@ -506,8 +558,8 @@ func (h *databaseResourceHandler) SearchQuery() *queryTemplate {
func newDefaultResourceRegistry(baseDN string) *resourceRegistry {
reg := newResourceRegistry()
reg.register(as.ResourceTypeEmail, &emailResourceHandler{baseDN: baseDN})
reg.register(as.ResourceTypeMailingList, &mailingListResourceHandler{baseDN: baseDN})
reg.register(as.ResourceTypeNewsletter, &newsletterResourceHandler{baseDN: baseDN})
reg.register(as.ResourceTypeMailingList, newMailingListResourceHandler(baseDN))
reg.register(as.ResourceTypeNewsletter, newNewsletterResourceHandler(baseDN))
reg.register(as.ResourceTypeDAV, &webdavResourceHandler{baseDN: baseDN})
reg.register(as.ResourceTypeWebsite, &websiteResourceHandler{baseDN: baseDN})
reg.register(as.ResourceTypeDomain, &domainResourceHandler{baseDN: baseDN})
......
......@@ -14,3 +14,8 @@ objectclass: top
objectclass: organizationalUnit
ou: Lists
dn: ou=Newsletters,dc=example,dc=com
objectclass: top
objectclass: organizationalUnit
ou: Lists
......@@ -38,7 +38,7 @@ userPassword:: JGEyJDQkMzI3NjgkMSQwZDgyMzU1YjQ0Mzg0M2NmZDY4MjU1MzE4ZTVjYTdiZSRmN
dn: listName=list1@investici.org,ou=Lists,dc=example,dc=com
objectClass: mailingList
objectClass: top
listName: list@investici.org
listName: list1@investici.org
listDescription: Mailing list 1
public: no
status: active
......@@ -49,10 +49,21 @@ originalHost: host2
dn: listName=list2@investici.org,ou=Lists,dc=example,dc=com
objectClass: mailingList
objectClass: top
listName: list@investici.org
listName: list2@investici.org
listDescription: Mailing list 2
public: no
status: active
listOwner: quattroalias@investici.org
host: host2
originalHost: host2
dn: listName=newsletter1@investici.org,ou=Newsletters,dc=example,dc=com
objectClass: mailingList
objectClass: top
listName: newsletter1@investici.org
listDescription: Newsletter 1
public: no
status: active
listOwner: quattro@investici.org
host: host2
originalHost: host2
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment