Calendar Export of a whole category with some protected events

Hi,

a user of our organization is synchronizing his calendar with the .ics of a whole Category. In this category there are some protected events where regular users (like him) cannot access. As a result, every day we receive hundreds of emails notifying about the error on the support email account:

“Unexpected Exception occurred at indico.cells.es: ‘NoneType’ object is not iterable”

Is there any way to prevent this? We can not grant permissions to all the events to regular users and we can not move these protected events to other categories.

Thanks!
Isidre

Please provide the full traceback.

This is one of the errors:

2025-03-05 07:03:14,116  22b41b9b1f4947e3  -       indico.flask - ERROR errors.py:110 -- 'NoneType' object is not iterable

Traceback (most recent call last):
  File "/opt/indico/.venv/lib/python3.9/site-packages/flask/app.py", line 1484, in full_dispatch_request
    rv = self.dispatch_request()
  File "/opt/indico/.venv/lib/python3.9/site-packages/flask/app.py", line 1469, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/web/http_api/handlers.py", line 223, in handler
    res = hook(user)
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/web/http_api/hooks/base.py", line 185, in __call__
    is_response, resultList, complete, extra = self._perform(user, func, extra_func)
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/web/http_api/hooks/base.py", line 163, in _perform
    resultList, complete = self._performCall(func, user)
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/web/http_api/hooks/base.py", line 149, in _performCall
    res = func(user)
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/modules/events/api.py", line 133, in export_categ
    return expInt.category(id_list, self._format)
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/modules/events/api.py", line 494, in category
    buf = serialize_categories_ical(idlist, self.user,
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/modules/categories/serialize.py", line 60, in serialize_categories_ical
    return BytesIO(events_to_ical(events, user))
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/modules/events/ical.py", line 213, in events_to_ical
    if not skip_access_check and not event.can_access(user):
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/util/caching.py", line 54, in memoizer
    cache[key] = f(*args, **kwargs)
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/core/db/sqlalchemy/protection.py", line 203, in can_access
    if any(user in entry.principal for entry in iter_acl(self.acl_entries)):
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/core/db/sqlalchemy/protection.py", line 203, in <genexpr>
    if any(user in entry.principal for entry in iter_acl(self.acl_entries)):
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/modules/groups/core.py", line 67, in __contains__
    return self.has_member(user)
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/modules/groups/core.py", line 229, in has_member
    rv = any(x[1] in self.group for x in user.iter_identifiers(check_providers=True, providers={self.provider}))
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/modules/groups/core.py", line 229, in <genexpr>
    rv = any(x[1] in self.group for x in user.iter_identifiers(check_providers=True, providers={self.provider}))
  File "/opt/indico/.venv/lib/python3.9/site-packages/flask_multipass/group.py", line 51, in __contains__
    return self.has_member(identifier)
  File "/opt/indico/.venv/lib/python3.9/site-packages/flask_multipass/providers/ldap/providers.py", line 136, in has_member
    return any(group_sid in token_groups for group_sid in group_sids)
TypeError: 'NoneType' object is not iterable

{'data': {'get': {'apikey': 'xxxx',
                  'from': '-31d'},
          'headers': {'Accept-Encoding': 'gzip, deflate, br',
                      'Connection': 'Keep-Alive',
                      'From': '',
                      'Host': 'indico.cells.es',
                      'User-Agent': 'Google-Calendar-Importer',
                      'X-Forwarded-For': 'xxx',
                      'X-Forwarded-Host': 'indico.cells.es',
                      'X-Forwarded-Server': 'indicodmz.cells.es'},
          'json': None,
          'post': {},
          'url': {'path': 'categ/3.ics', 'prefix': 'export'}},
 'endpoint': 'api.httpapi',
 'id': '22b41b9b1f4947e3',
 'ip': 'xxx',
 'method': 'GET',
 'referrer': None,
 'rh': None,
 'time': '2025-03-05T07:03:14.127245',
 'url': 'https://indico.cells.es/export/categ/3.ics?from=-31d&apikey=xxx',
 'user': None,
 'user_agent': 'Google-Calendar-Importer'}

//////////////////////////////////////

And this is another one, both seems to be related to the calendar syncronization:

2025-03-05 06:11:58,025  3d03dba87ded4529  1074    indico.flask - ERROR errors.py:110 -- 'NoneType' object is not iterable

Traceback (most recent call last):
  File "/opt/indico/.venv/lib/python3.9/site-packages/flask/app.py", line 1484, in full_dispatch_request
    rv = self.dispatch_request()
  File "/opt/indico/.venv/lib/python3.9/site-packages/flask/app.py", line 1469, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/web/flask/util.py", line 79, in wrapper
    return obj().process()
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/web/rh.py", line 285, in process
    res = self._do_process()
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/web/rh.py", line 256, in _do_process
    rv = self._process()
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/modules/categories/controllers/display.py", line 370, in _process
    buf = serialize_categories_ical([self.category.id], session.user,
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/modules/categories/serialize.py", line 60, in serialize_categories_ical
    return BytesIO(events_to_ical(events, user))
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/modules/events/ical.py", line 213, in events_to_ical
    if not skip_access_check and not event.can_access(user):
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/util/caching.py", line 54, in memoizer
    cache[key] = f(*args, **kwargs)
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/core/db/sqlalchemy/protection.py", line 203, in can_access
    if any(user in entry.principal for entry in iter_acl(self.acl_entries)):
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/core/db/sqlalchemy/protection.py", line 203, in <genexpr>
    if any(user in entry.principal for entry in iter_acl(self.acl_entries)):
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/modules/groups/core.py", line 67, in __contains__
    return self.has_member(user)
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/modules/groups/core.py", line 229, in has_member
    rv = any(x[1] in self.group for x in user.iter_identifiers(check_providers=True, providers={self.provider}))
  File "/opt/indico/.venv/lib/python3.9/site-packages/indico/modules/groups/core.py", line 229, in <genexpr>
    rv = any(x[1] in self.group for x in user.iter_identifiers(check_providers=True, providers={self.provider}))
  File "/opt/indico/.venv/lib/python3.9/site-packages/flask_multipass/group.py", line 51, in __contains__
    return self.has_member(identifier)
  File "/opt/indico/.venv/lib/python3.9/site-packages/flask_multipass/providers/ldap/providers.py", line 136, in has_member
    return any(group_sid in token_groups for group_sid in group_sids)
TypeError: 'NoneType' object is not iterable

{'data': {'get': {'user_token': 'xxx'},
          'headers': {'Accept-Encoding': 'gzip, deflate, br',
                      'Connection': 'Keep-Alive',
                      'From': '',
                      'Host': 'indico.cells.es',
                      'User-Agent': 'Google-Calendar-Importer',
                      'X-Forwarded-For': 'xxxx',
                      'X-Forwarded-Host': 'indico.cells.es',
                      'X-Forwarded-Server': 'indicodmz.cells.es'},
          'json': None,
          'post': {},
          'url': {'category_id': 3}},
 'endpoint': 'categories.export_ical',
 'id': '3d03dba87ded4529',
 'ip': 'xxx',
 'method': 'GET',
 'referrer': None,
 'rh': 'RHExportCategoryICAL',
 'time': '2025-03-05T06:11:58.045552',
 'url': 'https://indico.cells.es/category/3/events.ics?user_token=xxx',
 'user': {'email': 'j.....@cells.es', 'id': 1074, 'name': 'J...........z'},
 'user_agent': 'Google-Calendar-Importer'}

OK, so the error comes from the LDAP code. Also, you use a very outdated version of Indico (3.2.8, current release is 3.3.5). You need to update: Upgrade — Indico 3.3.5 documentation

FWIW, the error you get MAY have been fixed in the meantime. I don’t know. But I’d prefer you to first update your Indico instance and then, if it still happens, come back to us. Also because, being in LDAP code, it would be quite hard for us to reproduce/test.

Just to make sure there’s no misconfiguration: What LDAP server are you using? Active Directory or something else?

In any case, here’s a POSSIBLE fix - feel free to apply the change directly on the server (and then restart indico-uwsgi.service) to try it:

diff --git a/flask_multipass/providers/ldap/providers.py b/flask_multipass/providers/ldap/providers.py
index dcce6e4..2d3722d 100644
--- a/flask_multipass/providers/ldap/providers.py
+++ b/flask_multipass/providers/ldap/providers.py
@@ -142,7 +142,7 @@ class LDAPGroup(Group):
                 return False
             if self.ldap_settings['ad_group_style']:
                 _group_dn, group_data = get_group_by_id(self.name, attributes=['objectSid'])
-                group_sids = group_data.get('objectSid')
+                group_sids = group_data.get('objectSid', [])
                 token_groups = get_token_groups_from_user_dn(user_dn)
                 return any(group_sid in token_groups for group_sid in group_sids)
             else:

The full path to the file on your server is /opt/indico/.venv/lib/python3.9/site-packages/flask_multipass/providers/ldap/providers.py.

BTW, your error reports were not properly sanitized and included sensitive data such as API keys and user tokens. You should revoke that API key and invalidate token-based links for the user. Note that this also means that the user will need to get new URLs to use in their calendar.

Hi,

we have applied the fix in the providers.py. It works, we have not received any error report since then.

We are going to upgrade in the following weeks.

Thanks for your help!
Isidre