Skip to content

Commit

Permalink
Add cloner for event roles
Browse files Browse the repository at this point in the history
  • Loading branch information
ThiefMaster committed Oct 2, 2019
1 parent 5b9d35b commit e85042b
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ Bugfixes
- Fix confirmation prompt when disabling conference menu customizations
(:issue:`4085`)
- Fix incorrect days shown as weekend in in room booking for some locales
- Fix ACL entries referencing event roles from the old event when cloning an
event with event roles in the ACL (:issue:`4090`)

Version 2.2.2
-------------
Expand Down
13 changes: 11 additions & 2 deletions indico/core/db/sqlalchemy/principals.py
Original file line number Diff line number Diff line change
Expand Up @@ -565,18 +565,27 @@ def __eq__(self, other):
return db.and_(self.cls.type == other.principal_type, *criteria)


def clone_principals(cls, principals):
def clone_principals(cls, principals, event_role_map=None):
"""Clone a list of principals.
:param cls: the principal type to use (a `PrincipalMixin` subclass)
:param principals: a collection of these principals
:param event_role_map: the mapping from old to new event roles.
if omitted, event roles are skipped
:return: A new set of principals that can be added to an object
"""
rv = set()
assert all(isinstance(x, cls) for x in principals)
attrs = get_simple_column_attrs(cls) | {'user', 'local_group', 'ip_network_group', 'event_role'}
attrs = get_simple_column_attrs(cls) | {'user', 'local_group', 'ip_network_group'}
for old_principal in principals:
event_role = None
if old_principal.type == PrincipalType.event_role:
if event_role_map is None:
continue
event_role = event_role_map[old_principal.event_role]
principal = cls()
principal.populate_from_dict({attr: getattr(old_principal, attr) for attr in attrs})
if event_role:
principal.event_role = event_role
rv.add(principal)
return rv
4 changes: 3 additions & 1 deletion indico/modules/events/clone.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,10 @@ class EventProtectionCloner(EventCloner):
name = 'event_protection'
friendly_name = _('ACLs and protection settings')
is_default = True
uses = {'event_roles'}

def run(self, new_event, cloners, shared_data):
self._event_role_map = shared_data['event_roles']['event_role_map'] if 'event_roles' in cloners else None
with db.session.no_autoflush:
self._clone_protection(new_event)
self._clone_session_coordinator_privs(new_event)
Expand All @@ -120,4 +122,4 @@ def _clone_session_coordinator_privs(self, new_event):
})

def _clone_acl(self, new_event):
new_event.acl_entries = clone_principals(EventPrincipal, self.old_event.acl_entries)
new_event.acl_entries = clone_principals(EventPrincipal, self.old_event.acl_entries, self._event_role_map)
4 changes: 3 additions & 1 deletion indico/modules/events/contributions/clone.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class ContributionCloner(EventCloner):
name = 'contributions'
friendly_name = _('Contributions')
requires = {'event_persons', 'sessions', 'contribution_types', 'contribution_fields'}
uses = {'event_roles'}
is_internal = True

# We do not override `is_available` as we have cloners depending
Expand Down Expand Up @@ -112,6 +113,7 @@ def clone_single_contribution(cls, contribution, preserve_session=False):
return new_contribution

def run(self, new_event, cloners, shared_data):
self._event_role_map = shared_data['event_roles']['event_role_map'] if 'event_roles' in cloners else None
self._person_map = shared_data['event_persons']['person_map']
self._session_map = shared_data['sessions']['session_map']
self._session_block_map = shared_data['sessions']['session_block_map']
Expand All @@ -132,7 +134,7 @@ def _create_new_contribution(self, event, old_contrib, preserve_session=True, ex
new_contrib = Contribution()
new_contrib.populate_from_attrs(old_contrib, attrs)
new_contrib.subcontributions = list(self._clone_subcontribs(old_contrib.subcontributions))
new_contrib.acl_entries = clone_principals(ContributionPrincipal, old_contrib.acl_entries)
new_contrib.acl_entries = clone_principals(ContributionPrincipal, old_contrib.acl_entries, self._event_role_map)
new_contrib.references = list(self._clone_references(ContributionReference, old_contrib.references))
new_contrib.person_links = list(self._clone_person_links(ContributionPersonLink, old_contrib.person_links))
new_contrib.field_values = list(self._clone_fields(old_contrib.field_values))
Expand Down
6 changes: 6 additions & 0 deletions indico/modules/events/roles/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ def _sidemenu_items(sender, event, **kwargs):
if event.can_manage(session.user):
roles_section = 'organization' if event.type == 'conference' else 'advanced'
return SideMenuItem('roles', _('Roles Setup'), url_for('event_roles.manage', event), section=roles_section)


@signals.event_management.get_cloners.connect
def _get_event_roles_cloner(sender, **kwargs):
from indico.modules.events.roles.clone import EventRoleCloner
return EventRoleCloner
46 changes: 46 additions & 0 deletions indico/modules/events/roles/clone.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# This file is part of Indico.
# Copyright (C) 2002 - 2019 CERN
#
# Indico is free software; you can redistribute it and/or
# modify it under the terms of the MIT License; see the
# LICENSE file for more details.

from __future__ import unicode_literals

from indico.core.db import db
from indico.core.db.sqlalchemy.util.models import get_simple_column_attrs
from indico.core.db.sqlalchemy.util.session import no_autoflush
from indico.modules.events.cloning import EventCloner
from indico.modules.events.models.events import EventType
from indico.modules.events.models.roles import EventRole
from indico.util.i18n import _


class EventRoleCloner(EventCloner):
name = 'event_roles'
friendly_name = _('Event roles')
is_default = True

@property
def is_visible(self):
return self.old_event.type_ == EventType.conference

@property
def is_available(self):
return bool(self.old_event.roles)

def run(self, new_event, cloners, shared_data):
self._event_role_map = {}
self._clone_event_roles(new_event)
db.session.flush()
return {'event_role_map': self._event_role_map}

@no_autoflush
def _clone_event_roles(self, new_event):
attrs = get_simple_column_attrs(EventRole) | {'members'}
for old_event_role in self.old_event.roles:
event_role = EventRole()
event_role.populate_from_attrs(old_event_role, attrs)
new_event.roles.append(event_role)
self._event_role_map[old_event_role] = event_role
print self._event_role_map
4 changes: 3 additions & 1 deletion indico/modules/events/sessions/clone.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ class SessionCloner(EventCloner):
name = 'sessions'
friendly_name = _('Sessions')
requires = {'event_persons'}
uses = {'event_roles'}
is_internal = True

# We do not override `is_available` as we have cloners depending
# on this internal cloner even if it won't clone anything.

def run(self, new_event, cloners, shared_data):
self._event_role_map = shared_data['event_roles']['event_role_map'] if 'event_roles' in cloners else None
self._person_map = shared_data['event_persons']['person_map']
self._session_map = {}
self._session_block_map = {}
Expand All @@ -50,7 +52,7 @@ def _clone_sessions(self, new_event):
sess = Session()
sess.populate_from_attrs(old_sess, attrs)
sess.blocks = list(self._clone_session_blocks(old_sess.blocks))
sess.acl_entries = clone_principals(SessionPrincipal, old_sess.acl_entries)
sess.acl_entries = clone_principals(SessionPrincipal, old_sess.acl_entries, self._event_role_map)
new_event.sessions.append(sess)
self._session_map[old_sess] = sess

Expand Down

0 comments on commit e85042b

Please sign in to comment.