From 1fef9503fd43b2d7a871a93f4219e7057842407e Mon Sep 17 00:00:00 2001
From: nd <git@notandy.de>
Date: Thu, 11 Mar 2021 15:24:02 +0100
Subject: [PATCH] always try to subscribe a user because the mailman api is
 inconsistent

---
 .../commands/syncldapmemberships.py           | 25 +++++++++++--------
 setup.py                                      |  2 +-
 2 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/postorius_ldap_membership_management/management/commands/syncldapmemberships.py b/postorius_ldap_membership_management/management/commands/syncldapmemberships.py
index 9de0fcb..a07d952 100644
--- a/postorius_ldap_membership_management/management/commands/syncldapmemberships.py
+++ b/postorius_ldap_membership_management/management/commands/syncldapmemberships.py
@@ -6,6 +6,8 @@ from django.core.management.base import BaseCommand
 from django_auth_ldap.config import LDAPSearch
 import django.conf
 
+from urllib.error import HTTPError
+
 from postorius.models import List, MailmanUser
 from postorius.utils import get_mailman_client
 
@@ -30,6 +32,7 @@ class Command(BaseCommand):
 		results = user_search.execute(conn)
 		ldap_users = [list(attr.values())[0][0] for dn, attr in results ]
 		django_users = get_user_model().objects.all()
+		backref_mapping = {'member': 'members', 'moderator': 'moderators', 'owner': 'owners'}
 		mm_users = {}
 
 		membership_settings = getattr(django.conf.settings, 'LDAP_MEMBERSHIP_SYNC', {})
@@ -42,6 +45,8 @@ class Command(BaseCommand):
 				mm_users[user.username].display_name = user.get_full_name()
 				mm_users[user.username].save()
 
+		mailman_id2username = {mm_users[i].user_id: i for i in mm_users}
+
 		for list_name in membership_settings:
 			ldap_setting = membership_settings[list_name].get('ldap', {})
 			for membership_type in ldap_setting:
@@ -56,9 +61,6 @@ class Command(BaseCommand):
 				# we refetch the mm_list each time because of wired caching problems
 				mm_list = client.get_list(list_name)
 
-				backref_mapping = {'member': 'members', 'moderator': 'moderators', 'owner': 'owners'}
-
-				mailman_id2username = {mm_users[i].user_id: i for i in mm_users}
 				mm_members = getattr(mm_list, backref_mapping[membership_type], [])
 				for mm_member in mm_members:
 					try:
@@ -77,14 +79,11 @@ class Command(BaseCommand):
 					try:
 						mm_user = mm_users[username]
 						displayname = mm_users[username].display_name or username
-						for mm_subscription in mm_user.subscriptions:
-							if mm_subscription.role == membership_type:
-								# user is already subscribed
-								break
-						else:
-							# user is not subscribed but should be subscribed -> subscribe
+						try:
+							# user might not be subscribed but should be subscribed -> subscribe
+							# we do not test if he is subscibed already because the mailman api is inconsistent and reports wrong state information for this...
+							# instead we always try to subscribe and catch the error if we are subscribed already
 							user_mail = mm_user.addresses[0].email
-							logger.warning("subscribe {} ( {} ) as {} on {}".format(username, user_mail, membership_type, list_name))
 							if membership_type == 'member':
 								mm_list.subscribe(user_mail,
 										display_name=displayname,
@@ -97,6 +96,12 @@ class Command(BaseCommand):
 							elif membership_type == 'owner':
 								mm_list.add_moderator(user_mail,
 										display_name=displayname)
+							logger.warning("subscribe {} ( {} ) as {} on {}".format(username, user_mail, membership_type, list_name))
+						except HTTPError as e:
+							# We get a http error if the user is already subscribed.
+							# It is silently ignored
+							if e.code == 409 and e.reason == b'Member already subscribed':
+								continue
 					except Exception as e:
 						logger.exception(e)
 						continue
diff --git a/setup.py b/setup.py
index 400351f..2fac7ae 100644
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,7 @@
 from setuptools import setup, find_packages
 
 setup(name='postorius_ldap_membership_management',
-	version='1.0',
+	version='1.1',
 	description='Sync subscriptions from ldap',
 	url='https://git.cccv.de:infra/uffd/postorius-ldap-membership-management',
 	author='Andreas Valder',
-- 
GitLab