def update_reviewing_roles(event, users, contributions, role, assign): role_map = { PaperReviewingRole.judge: attrgetter('paper_judges'), PaperReviewingRole.content_reviewer: attrgetter('paper_content_reviewers'), PaperReviewingRole.layout_reviewer: attrgetter('paper_layout_reviewers'), } for contrib in contributions: role_group = role_map[role](contrib) for user in users: if assign: role_group.add(user) else: role_group.discard(user) contrib_ids = ['#{}'.format(c.friendly_id) for c in sorted(contributions, key=attrgetter('friendly_id'))] log_data = {'Users': ', '.join(sorted(person.full_name for person in users)), 'Contributions': ', '.join(contrib_ids)} roles_to_notify = paper_reviewing_settings.get(event, 'notify_on_assigned_contrib') if role in roles_to_notify: for user in users: notify_paper_assignment(user, role, contributions, event, assign) if assign: event.log(EventLogRealm.reviewing, EventLogKind.positive, 'Papers', 'Papers assigned ({})'.format(orig_string(role.title)), session.user, data=log_data) else: event.log(EventLogRealm.reviewing, EventLogKind.negative, 'Papers', 'Papers unassigned ({})'.format(orig_string(role.title)), session.user, data=log_data) db.session.flush() logger.info('Paper reviewing roles in event %r updated by %r', event, session.user)
def log_registration_updated(registration, previous_state, **kwargs): """Log the registration status change to the event log.""" if not previous_state: return previous_state_title = orig_string(previous_state.title) if (previous_state == RegistrationState.pending and registration.state in (RegistrationState.complete, RegistrationState.unpaid)): log_text = 'Registration for "{}" has been approved' kind = EventLogKind.positive elif previous_state == RegistrationState.pending and registration.state == RegistrationState.rejected: log_text = 'Registration for "{}" has been rejected' kind = EventLogKind.negative elif previous_state == RegistrationState.unpaid and registration.state == RegistrationState.complete: log_text = 'Registration for "{}" has been paid' kind = EventLogKind.positive elif previous_state == RegistrationState.complete and registration.state == RegistrationState.unpaid: log_text = 'Registration for "{}" has been marked as not paid' kind = EventLogKind.negative elif registration.state == RegistrationState.withdrawn: log_text = 'Registration for "{}" has been withdrawn' kind = EventLogKind.negative else: state_title = orig_string(registration.state.title).lower() log_text = 'Registration for "{{}}" has been changed from {} to {}'.format( previous_state_title.lower(), state_title) kind = EventLogKind.change registration.log(EventLogRealm.participants, kind, 'Registration', log_text.format(registration.full_name), session.user, data={'Previous state': previous_state_title})
def update_reviewing_roles(event, users, contributions, role, assign): role_map = { PaperReviewingRole.judge: attrgetter('paper_judges'), PaperReviewingRole.content_reviewer: attrgetter('paper_content_reviewers'), PaperReviewingRole.layout_reviewer: attrgetter('paper_layout_reviewers'), } for contrib in contributions: role_group = role_map[role](contrib) for user in users: if assign: role_group.add(user) else: role_group.discard(user) contrib_ids = ['#{}'.format(c.friendly_id) for c in sorted(contributions, key=attrgetter('friendly_id'))] log_data = {'Users': ', '.join(sorted(person.full_name for person in users)), 'Contributions': ', '.join(contrib_ids)} roles_to_notify = paper_reviewing_settings.get(event, 'notify_on_assigned_contrib') if role in roles_to_notify: for user in users: notify_paper_assignment(user, role, contributions, event, assign) if assign: event.log(EventLogRealm.management, EventLogKind.positive, 'Papers', 'Papers assigned ({})'.format(orig_string(role.title)), session.user, data=log_data) else: event.log(EventLogRealm.management, EventLogKind.negative, 'Papers', 'Papers unassigned ({})'.format(orig_string(role.title)), session.user, data=log_data) db.session.flush() logger.info('Paper reviewing roles in event %r updated by %r', event, session.user)
def create_review(paper, review_type, user, review_data, questions_data): review = PaperReview(revision=paper.last_revision, type=review_type.instance, user=user) review.populate_from_dict(review_data) log_data = {} for question in paper.event.cfp.get_questions_for_review_type( review_type.instance): value = questions_data[f'question_{question.id}'] review.ratings.append(PaperReviewRating(question=question, value=value)) log_data[question.title] = question.field.get_friendly_value(value) db.session.flush() notify_paper_review_submission(review) logger.info("Paper %r received a review of type %s by %r", paper, review_type.instance.name, user) log_data.update({ 'Type': orig_string(review_type.title), 'Action': orig_string(review.proposed_action.title), 'Comment': review.comment }) paper.event.log( EventLogRealm.reviewing, EventLogKind.positive, 'Papers', f'Paper for contribution {paper.contribution.verbose_title} reviewed', user, data=log_data) return review
def unassign_editor(editable): editor = editable.editor editable.editor = None logger.info('Editor %r has been unassigned from %r', editor, editable) log_data = { 'Editor': editor.full_name, 'Editable type': orig_string(editable.type.title), 'Editable': editable.contribution.title } log_msg = '"{}" ({}) unassigned from {}'.format(editable.contribution.title, orig_string(editable.type.title), editor.full_name) editable.log(EventLogRealm.management, EventLogKind.negative, 'Editing', log_msg, session.user, data=log_data) db.session.flush()
def assign_editor(editable, editor): old_editor = editable.editor editable.editor = editor logger.info('Editable %r assigned to editor %r', editable, editor) log_data = { 'Editor': editor.full_name, 'Editable type': orig_string(editable.type.title), 'Editable': editable.contribution.title } if old_editor: log_data['Previous editor'] = old_editor.full_name log_msg = '"{}" ({}) assigned to {}'.format(editable.contribution.title, orig_string(editable.type.title), editor.full_name) editable.log(EventLogRealm.management, EventLogKind.positive, 'Editing', log_msg, session.user, data=log_data) db.session.flush()
def set_reviewing_state(event, reviewing_type, enable): event.cfp.set_reviewing_state(reviewing_type, enable) action = 'enabled' if enable else 'disabled' logger.info("Reviewing type '%s' for event %r %s by %r", reviewing_type.name, event, action, session.user) event.log(EventLogRealm.reviewing, EventLogKind.positive if enable else EventLogKind.negative, 'Papers', "{} {} reviewing".format("Enabled" if enable else "Disabled", orig_string(reviewing_type.title.lower())), session.user)
def _format_roles(roles): roles = set(roles) return ', '.join( sorted( orig_string(role.friendly_name) for role in available_roles.itervalues() if role.name in roles))
def clone_into_event(source_event, target_event, cloners): """Clone data into an existing event. Runs all required cloners. :param source_event: The `Event` to clone data from; :param target_event: The `Event` to clone data into; :param cloners: A set containing the names of all enabled cloners. """ # Run the modular cloning system g.importing_event = True EventCloner.run_cloners(source_event, target_event, cloners, event_exists=True) del g.importing_event signals.event.imported.send(target_event, source_event=source_event) cloner_classes = {c.name: c for c in get_event_cloners().values()} target_event.log(EventLogRealm.event, LogKind.change, 'Event', 'Data imported', session.user, data={ 'Modules': ', '.join( orig_string(cloner_classes[c].friendly_name) for c in cloners if not cloner_classes[c].is_internal) }) return target_event
def FIELD_DATA(cls): title_item = {'price': 0, 'is_billable': False, 'places_limit': 0, 'is_enabled': True} return [ (cls.first_name, { 'title': cls.first_name.get_title(), 'input_type': 'text' }), (cls.last_name, { 'title': cls.last_name.get_title(), 'input_type': 'text' }), (cls.email, { 'title': cls.email.get_title(), 'input_type': 'email' }), (cls.affiliation, { 'title': cls.affiliation.get_title(), 'input_type': 'text' }), # Fields disabled by default start in position 1000 to avoid problems reordering (cls.address, { 'title': cls.address.get_title(), 'input_type': 'textarea', 'is_enabled': False, 'position': 1000 }), (cls.country, { 'title': cls.country.get_title(), 'input_type': 'country', 'is_enabled': False, 'position': 1001 }), (cls.phone, { 'title': cls.phone.get_title(), 'input_type': 'phone', 'is_enabled': False, 'position': 1002 }), (cls.position, { 'title': cls.position.get_title(), 'input_type': 'text', 'is_enabled': False, 'position': 1003 }), (cls.title, { 'title': cls.title.get_title(), 'input_type': 'single_choice', 'is_enabled': False, 'position': 1004, 'data': { 'item_type': 'dropdown', 'with_extra_slots': False, 'choices': [dict(title_item, id=str(uuid4()), caption=orig_string(t.title)) for t in UserTitle if t] } }), ]
def create_abstract_review(abstract, track, user, review_data, questions_data): review = AbstractReview(abstract=abstract, track=track, user=user) review.populate_from_dict(review_data) log_data = {} for question in abstract.event.abstract_review_questions: value = questions_data['question_{}'.format(question.id)] review.ratings.append(AbstractReviewRating(question=question, value=value)) log_data[question.title] = question.field.get_friendly_value(value) db.session.flush() logger.info("Abstract %s received a review by %s for track %s", abstract, user, track) log_data.update({ 'Track': track.title, 'Action': orig_string(review.proposed_action.title), 'Comment': review.comment }) if review.proposed_action == AbstractAction.accept: log_data['Contribution type'] = (review.proposed_contribution_type.name if review.proposed_contribution_type else None) elif review.proposed_action == AbstractAction.change_tracks: log_data['Other tracks'] = sorted(t.title for t in review.proposed_tracks) elif review.proposed_action in {AbstractAction.mark_as_duplicate, AbstractAction.merge}: log_data['Other abstract'] = review.proposed_related_abstract.verbose_title abstract.event.log(EventLogRealm.reviewing, EventLogKind.positive, 'Abstracts', 'Abstract {} reviewed'.format(abstract.verbose_title), user, data=log_data) return review
def _format_permissions(permissions): permissions = set(permissions) return ', '.join( sorted( orig_string(p.friendly_name) for p in available_permissions.values() if p.name in permissions))
def create_abstract_review(abstract, track, user, review_data, questions_data): review = AbstractReview(abstract=abstract, track=track, user=user) review.populate_from_dict(review_data) log_data = {} for question in abstract.event.abstract_review_questions: value = int(questions_data['question_{}'.format(question.id)]) review.ratings.append(AbstractReviewRating(question=question, value=value)) log_data[question.text] = value db.session.flush() logger.info("Abstract %s received a review by %s for track %s", abstract, user, track) log_data.update({ 'Track': track.title, 'Action': orig_string(review.proposed_action.title), 'Comment': review.comment }) if review.proposed_action == AbstractAction.accept: log_data['Contribution type'] = (review.proposed_contribution_type.name if review.proposed_contribution_type else None) elif review.proposed_action == AbstractAction.change_tracks: log_data['Other tracks'] = sorted(t.title for t in review.proposed_tracks) elif review.proposed_action in {AbstractAction.mark_as_duplicate, AbstractAction.merge}: log_data['Other abstract'] = review.proposed_related_abstract.verbose_title abstract.event.log(EventLogRealm.management, EventLogKind.positive, 'Abstracts', 'Abstract {} reviewed'.format(abstract.verbose_title), user, data=log_data) return review
def judge_abstract(abstract, abstract_data, judgment, judge, contrib_session=None, merge_persons=False, send_notifications=False): from indico.modules.events.tracks.models.tracks import Track abstract.judge = judge abstract.judgment_dt = now_utc() abstract.judgment_comment = abstract_data['judgment_comment'] log_data = {'Judgment': orig_string(judgment.title)} if judgment == AbstractAction.accept: abstract.state = AbstractState.accepted abstract.accepted_track = abstract_data.get('accepted_track') if abstract_data.get('override_contrib_type') or abstract_data.get('accepted_contrib_type'): abstract.accepted_contrib_type = abstract_data.get('accepted_contrib_type') else: abstract.accepted_contrib_type = abstract.submitted_contrib_type if not abstract.contribution: abstract.contribution = create_contribution_from_abstract(abstract, contrib_session) if abstract.accepted_track: log_data['Track'] = abstract.accepted_track.title if abstract.accepted_contrib_type: log_data['Type'] = abstract.accepted_contrib_type.name from indico.modules.events.contributions.models.limits import ContributionLimit from sqlalchemy import func if not abstract.accepted_contrib_type: raise Exception("The contribution type is missing.") limit_obj = ContributionLimit.query.filter_by(event_id=abstract.event.id, track_id=(None if not abstract.accepted_track else abstract.accepted_track.id), type_id=abstract.accepted_contrib_type.id).first() limit = None if not limit_obj else limit_obj.value val = Abstract.query.filter_by(event_id=abstract.event.id, accepted_track_id=(None if not abstract.accepted_track else abstract.accepted_track.id), accepted_contrib_type_id=abstract.accepted_contrib_type.id).count() if limit and val >= limit+1: raise Exception("Abstract admission limit of <b>%s</b> has been reached for type <i>'%s'</i> on track <i>'%s'</i>." " Please either reset a previous judgement or report this." % (limit, abstract.accepted_contrib_type.name, 'No track' if not abstract.accepted_track else abstract.accepted_track.title)) elif judgment == AbstractAction.reject: abstract.state = AbstractState.rejected elif judgment == AbstractAction.mark_as_duplicate: abstract.state = AbstractState.duplicate abstract.duplicate_of = abstract_data['duplicate_of'] log_data['Duplicate of'] = abstract.duplicate_of.verbose_title elif judgment == AbstractAction.merge: abstract.state = AbstractState.merged abstract.merged_into = abstract_data['merged_into'] log_data['Merged into'] = abstract.merged_into.verbose_title log_data['Merge authors'] = merge_persons if merge_persons: _merge_person_links(abstract.merged_into, abstract) db.session.flush() if send_notifications: log_data['Notifications sent'] = send_abstract_notifications(abstract) logger.info('Abstract %s judged by %s', abstract, judge) abstract.event.log(EventLogRealm.management, EventLogKind.change, 'Abstracts', 'Abstract {} judged'.format(abstract.verbose_title), judge, data=log_data)
def make_diff_log(changes, fields): """Create a value for log data containing change information. :param changes: a dict mapping attributes to ``(old, new)`` tuples :param fields: a dict mapping attributes to field metadata. for simple cases this may be a string with the human-friendly title, for more advanced fields it should be a dict containing ``title``, a ``type`` string and a ``convert`` callback which will be invoked with a tuple containing the old and new value """ data = {'_diff': True} for key, field_data in fields.iteritems(): try: change = changes[key] except KeyError: continue if isinstance(field_data, basestring): field_data = {'title': field_data} title = field_data['title'] convert = field_data.get('convert') attr = field_data.get('attr') default = field_data.get('default') type_ = field_data.get('type') not_none_change = [x for x in change if x is not None] if attr: change = [ getattr(x, attr) if x is not None else '' for x in change ] if convert: change = convert(change) if type_ is not None: # when we have an explicit type specified don't do any # guessing/conversions pass elif not_none_change and all( isinstance(x, Enum) for x in not_none_change): type_ = 'enum' change = [ orig_string(getattr(x, 'title', x.name)) if x is not None else default for x in change ] elif all(isinstance(x, (int, long, float)) for x in change): type_ = 'number' elif all(isinstance(x, (list, tuple)) for x in change): type_ = 'list' elif all(isinstance(x, set) for x in change): type_ = 'list' change = map(sorted, change) elif all(isinstance(x, bool) for x in change): type_ = 'bool' elif all(isinstance(x, datetime) for x in change): type_ = 'datetime' change = [x.isoformat() for x in change] else: type_ = 'text' change = map(unicode, map(orig_string, change)) data[title] = list(change) + [type_] return data
def judge_paper(paper, judgment, comment, judge): if judgment == PaperAction.accept: paper.state = PaperRevisionState.accepted elif judgment == PaperAction.reject: paper.state = PaperRevisionState.rejected elif judgment == PaperAction.to_be_corrected: paper.state = PaperRevisionState.to_be_corrected paper.last_revision.judgment_comment = comment paper.last_revision.judge = judge paper.last_revision.judgment_dt = now_utc() db.session.flush() log_data = {'New state': orig_string(judgment.title)} notify_paper_judgment(paper) logger.info('Paper %r was judged by %r to %s', paper, judge, orig_string(judgment.title)) paper.event.log(EventLogRealm.reviewing, EventLogKind.change, 'Papers', 'Paper "{}" was judged'.format(orig_string(paper.verbose_title)), judge, data=log_data)
def _process_PUT(self): self.event.log( EventLogRealm.management, EventLogKind.positive, 'Editing', 'Opened {} editing'.format(orig_string(self.editable_type.title)), session.user) editable_type_settings[self.editable_type].set(self.event, 'editing_enabled', True) return '', 204
def judge_paper(paper, judgment, comment, judge): if judgment == PaperAction.accept: paper.state = PaperRevisionState.accepted elif judgment == PaperAction.reject: paper.state = PaperRevisionState.rejected elif judgment == PaperAction.to_be_corrected: paper.state = PaperRevisionState.to_be_corrected paper.last_revision.judgment_comment = comment paper.last_revision.judge = judge paper.last_revision.judgment_dt = now_utc() db.session.flush() log_data = {'New state': orig_string(judgment.title)} notify_paper_judgment(paper) logger.info('Paper %r was judged by %r to %s', paper, judge, orig_string(judgment.title)) paper.event.log(EventLogRealm.reviewing, EventLogKind.change, 'Papers', f'Paper "{orig_string(paper.verbose_title)}" was judged', judge, data=log_data)
def FIELD_DATA(cls): title_item = {'price': 0, 'is_billable': False, 'places_limit': 0, 'is_enabled': True} return [ (cls.title, { 'title': cls.title.get_title(), 'input_type': 'single_choice', 'data': { 'item_type': 'dropdown', 'with_extra_slots': False, 'choices': [dict(title_item, id=unicode(uuid4()), caption=orig_string(t.title)) for t in UserTitle if t] } }), (cls.first_name, { 'title': cls.first_name.get_title(), 'input_type': 'text' }), (cls.last_name, { 'title': cls.last_name.get_title(), 'input_type': 'text' }), (cls.email, { 'title': cls.email.get_title(), 'input_type': 'email' }), (cls.affiliation, { 'title': cls.affiliation.get_title(), 'input_type': 'text' }), # Fields disabled by default start in position 1000 to avoid problems reordering (cls.address, { 'title': cls.address.get_title(), 'input_type': 'textarea', 'is_enabled': False, 'position': 1000 }), (cls.country, { 'title': cls.country.get_title(), 'input_type': 'country', 'is_enabled': False, 'position': 1001 }), (cls.phone, { 'title': cls.phone.get_title(), 'input_type': 'phone', 'is_enabled': False, 'position': 1002 }), (cls.position, { 'title': cls.position.get_title(), 'input_type': 'text', 'is_enabled': False, 'position': 1003 }), ]
def _process_DELETE(self): self.event.log( EventLogRealm.management, EventLogKind.negative, 'Editing', 'Closed {} editing'.format(orig_string(self.editable_type.title)), session.user) editable_type_settings[self.editable_type].set(self.event, 'editing_enabled', False) return '', 204
def create_review(paper, review_type, user, review_data, questions_data): review = PaperReview(revision=paper.last_revision, type=review_type.instance, user=user) review.populate_from_dict(review_data) log_data = {} for question in paper.event.cfp.get_questions_for_review_type(review_type.instance): value = questions_data['question_{}'.format(question.id)] review.ratings.append(PaperReviewRating(question=question, value=value)) log_data[question.title] = question.field.get_friendly_value(value) db.session.flush() notify_paper_review_submission(review) logger.info("Paper %r received a review of type %s by %r", paper, review_type.instance.name, user) log_data.update({ 'Type': orig_string(review_type.title), 'Action': orig_string(review.proposed_action.title), 'Comment': review.comment }) paper.event.log(EventLogRealm.reviewing, EventLogKind.positive, 'Papers', 'Paper for contribution {} reviewed'.format(paper.contribution.verbose_title), user, data=log_data) return review
def build_field_metadata(cls, field): if field.short_name == 'name_format': return { 'title': orig_string(field.label.text), 'default': orig_string(field.none) } elif field.short_name == 'theme': choices = { k if k else None: orig_string(v) for k, v in field.choices } return { 'title': orig_string(field.label.text), 'type': 'string', 'convert': lambda changes: [choices[x] for x in changes] } elif field.short_name == 'timetable_theme': choices = {k if k else None: v for k, v in field.choices} return { 'title': orig_string(field.label.text), 'type': 'string', 'convert': lambda changes: [choices[x] for x in changes] } else: return orig_string(field.label.text)
def update_session_coordinator_privs(event, data): changes = {} for priv, enabled in data.iteritems(): setting = COORDINATOR_PRIV_SETTINGS[priv] if session_settings.get(event, setting) == enabled: continue session_settings.set(event, setting, enabled) changes[priv] = (not enabled, enabled) db.session.flush() logger.info('Session coordinator privs of event %r updated with %r by %r', event, data, session.user) if changes: log_fields = {priv: orig_string(title) for priv, title in COORDINATOR_PRIV_TITLES.iteritems()} event.log(EventLogRealm.management, EventLogKind.change, 'Sessions', 'Coordinator privileges updated', session.user, data={'Changes': make_diff_log(changes, log_fields)})
def _get_reviewer_data(self, revision): if not revision.is_last_revision: return None data = dict(revision.get_reviewer_render_data(self.context.get('user'))) review_type_schema = PaperReviewTypeSchema() for name in ('groups', 'missing_groups', 'reviewed_groups'): data[name] = [review_type_schema.dump(item.instance) for item in data[name]] reviews = {} for key, value in data['reviews'].items(): reviews[orig_string(key.instance.title)] = paper_review_schema.dump(value) data['reviews'] = reviews return data
def judge_abstract(abstract, abstract_data, judgment, judge, contrib_session=None, merge_persons=False, send_notifications=False): abstract.judge = judge abstract.judgment_dt = now_utc() abstract.judgment_comment = abstract_data['judgment_comment'] log_data = {'Judgment': orig_string(judgment.title)} if judgment == AbstractAction.accept: abstract.state = AbstractState.accepted abstract.accepted_track = abstract_data.get('accepted_track') if abstract_data.get('override_contrib_type') or abstract_data.get( 'accepted_contrib_type'): abstract.accepted_contrib_type = abstract_data.get( 'accepted_contrib_type') else: abstract.accepted_contrib_type = abstract.submitted_contrib_type if not abstract.contribution: abstract.contribution = create_contribution_from_abstract( abstract, contrib_session) if abstract.accepted_track: log_data['Track'] = abstract.accepted_track.title if abstract.accepted_contrib_type: log_data['Type'] = abstract.accepted_contrib_type.name elif judgment == AbstractAction.reject: abstract.state = AbstractState.rejected elif judgment == AbstractAction.mark_as_duplicate: abstract.state = AbstractState.duplicate abstract.duplicate_of = abstract_data['duplicate_of'] log_data['Duplicate of'] = abstract.duplicate_of.verbose_title elif judgment == AbstractAction.merge: abstract.state = AbstractState.merged abstract.merged_into = abstract_data['merged_into'] log_data['Merged into'] = abstract.merged_into.verbose_title log_data['Merge authors'] = merge_persons if merge_persons: _merge_person_links(abstract.merged_into, abstract) db.session.flush() if send_notifications: log_data['Notifications sent'] = send_abstract_notifications(abstract) logger.info('Abstract %s judged by %s', abstract, judge) abstract.event.log(EventLogRealm.reviewing, EventLogKind.change, 'Abstracts', 'Abstract {} judged'.format(abstract.verbose_title), judge, data=log_data)
def make_diff_log(changes, fields): """Create a value for log data containing change information. :param changes: a dict mapping attributes to ``(old, new)`` tuples :param fields: a dict mapping attributes to field metadata. for simple cases this may be a string with the human-friendly title, for more advanced fields it should be a dict containing ``title``, a ``type`` string and a ``convert`` callback which will be invoked with a tuple containing the old and new value """ data = {'_diff': True} for key, field_data in fields.iteritems(): try: change = changes[key] except KeyError: continue if isinstance(field_data, basestring): field_data = {'title': field_data} title = field_data['title'] convert = field_data.get('convert') type_ = field_data.get('type') if convert: change = convert(change) if type_ is not None: # when we have an explicit type specified don't do any # guessing/conversions pass elif all(isinstance(x, Enum) for x in change): type_ = 'enum' change = [orig_string(getattr(x, 'title', x.name)) for x in change] elif all(isinstance(x, (int, long, float)) for x in change): type_ = 'number' elif all(isinstance(x, (list, tuple)) for x in change): type_ = 'list' elif all(isinstance(x, set) for x in change): type_ = 'list' change = map(sorted, change) elif all(isinstance(x, bool) for x in change): type_ = 'bool' elif all(isinstance(x, datetime) for x in change): type_ = 'datetime' change = [x.isoformat() for x in change] else: type_ = 'text' change = map(unicode, map(orig_string, change)) data[title] = list(change) + [type_] return data
def make_diff_log(changes, fields): """Create a value for log data containing change information. :param: a dict mapping attributes to ``(old, new)`` tuples :param: a dict mapping attributes to field metadata. for simple cases this may be a string with the human-friendly title, for more advanced fields it should be a dict containing ``title``, a ``type`` string and a ``convert`` callback which will be invoked with a tuple containing the old and new value :param: a dict overriding type information for attributes. can be a string or a function that takes a tuple with the old/new value and returns a ``(type, changes)`` tuple """ data = {"_diff": True} for key, field_data in fields.iteritems(): try: change = changes[key] except KeyError: continue if isinstance(field_data, basestring): field_data = {"title": field_data} title = field_data["title"] convert = field_data.get("convert") type_ = field_data.get("type") if convert: change = convert(change) if type_ is not None: # when we have an explicit type specified don't do any # guessing/conversions pass elif all(isinstance(x, Enum) for x in change): type_ = "enum" change = [orig_string(getattr(x, "title", x.name)) for x in change] elif all(isinstance(x, (int, long, float)) for x in change): type_ = "number" elif all(isinstance(x, (list, tuple)) for x in change): type_ = "list" elif all(isinstance(x, set) for x in change): type_ = "list" change = map(sorted, change) elif all(isinstance(x, bool) for x in change): type_ = "bool" else: type_ = "text" change = map(unicode, map(orig_string, change)) data[title] = list(change) + [type_] return data
def _get_person_link(self, data, extra_data=None): extra_data = extra_data or {} person = get_event_person( self.event, data, create_untrusted_persons=self.create_untrusted_persons, allow_external=True) person_data = { 'title': next((x.value for x in UserTitle if data.get('title') == orig_string(x.title)), UserTitle.none), 'first_name': data.get('firstName', ''), 'last_name': data['familyName'], 'affiliation': data.get('affiliation', ''), 'address': data.get('address', ''), 'phone': data.get('phone', ''), 'display_order': data['displayOrder'] } person_data.update(extra_data) person_link = None if self.object and inspect(person).persistent: person_link = self.person_link_cls.find_first(person=person, object=self.object) if not person_link: person_link = self.person_link_cls(person=person) person_link.populate_from_dict(person_data) email = data.get('email', '').lower() if email != person_link.email: if not self.event or not self.event.persons.filter_by( email=email).first(): person_link.person.email = email person_link.person.user = get_user_by_email(email) if inspect(person).persistent: signals.event.person_updated.send(person_link.person) else: raise UserValueError( _('There is already a person with the email {}').format( email)) return person_link
def judge_abstract(abstract, abstract_data, judgment, judge, contrib_session=None, merge_persons=False, send_notifications=False): abstract.judge = judge abstract.judgment_dt = now_utc() abstract.judgment_comment = abstract_data['judgment_comment'] log_data = {'Judgment': orig_string(judgment.title)} if judgment == AbstractAction.accept: abstract.state = AbstractState.accepted abstract.accepted_track = abstract_data.get('accepted_track') if abstract_data.get('override_contrib_type') or abstract_data.get('accepted_contrib_type'): abstract.accepted_contrib_type = abstract_data.get('accepted_contrib_type') else: abstract.accepted_contrib_type = abstract.submitted_contrib_type if not abstract.contribution: abstract.contribution = create_contribution_from_abstract(abstract, contrib_session) if abstract.accepted_track: log_data['Track'] = abstract.accepted_track.title if abstract.accepted_contrib_type: log_data['Type'] = abstract.accepted_contrib_type.name elif judgment == AbstractAction.reject: abstract.state = AbstractState.rejected elif judgment == AbstractAction.mark_as_duplicate: abstract.state = AbstractState.duplicate abstract.duplicate_of = abstract_data['duplicate_of'] log_data['Duplicate of'] = abstract.duplicate_of.verbose_title elif judgment == AbstractAction.merge: abstract.state = AbstractState.merged abstract.merged_into = abstract_data['merged_into'] log_data['Merged into'] = abstract.merged_into.verbose_title log_data['Merge authors'] = merge_persons if merge_persons: _merge_person_links(abstract.merged_into, abstract) db.session.flush() if send_notifications: log_data['Notifications sent'] = send_abstract_notifications(abstract) logger.info('Abstract %s judged by %s', abstract, judge) abstract.event.log(EventLogRealm.reviewing, EventLogKind.change, 'Abstracts', 'Abstract {} judged'.format(abstract.verbose_title), judge, data=log_data)
def create_event(category, event_type, data, add_creator_as_manager=True, features=None, cloning=False): """Create a new event. :param category: The category in which to create the event :param event_type: An `EventType` value :param data: A dict containing data used to populate the event :param add_creator_as_manager: Whether the creator (current user) should be added as a manager :param features: A list of features that will be enabled for the event. If set, only those features will be used and the default feature set for the event type will be ignored. :param cloning: Whether the event is created via cloning or not """ from indico.modules.rb.operations.bookings import create_booking_for_event event = Event(category=category, type_=event_type) data.setdefault('creator', session.user) theme = data.pop('theme', None) create_booking = data.pop('create_booking', False) person_link_data = data.pop('person_link_data', {}) event.populate_from_dict(data) db.session.flush() event.person_link_data = person_link_data if theme is not None: layout_settings.set(event, 'timetable_theme', theme) if add_creator_as_manager: with event.logging_disabled: event.update_principal(event.creator, full_access=True) if features is not None: features_event_settings.set(event, 'enabled', features) db.session.flush() signals.event.created.send(event, cloning=cloning) logger.info('Event %r created in %r by %r ', event, category, session.user) sep = ' \N{RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK} ' event.log(EventLogRealm.event, LogKind.positive, 'Event', 'Event created', session.user, data={ 'Category': sep.join(category.chain_titles) if category else None }) if category: category.log(CategoryLogRealm.events, LogKind.positive, 'Content', f'Event created: "{event.title}"', session.user, data={ 'ID': event.id, 'Type': orig_string(event.type_.title) }) db.session.flush() if create_booking: room_id = data['location_data'].pop('room_id', None) if room_id: booking = create_booking_for_event(room_id, event) if booking: logger.info('Booking %r created for event %r', booking, event) log_data = { 'Room': booking.room.full_name, 'Date': booking.start_dt.strftime('%d/%m/%Y'), 'Times': '{} - {}'.format(booking.start_dt.strftime('%H:%M'), booking.end_dt.strftime('%H:%M')) } event.log(EventLogRealm.event, LogKind.positive, 'Event', 'Room booked for the event', session.user, data=log_data) db.session.flush() return event
def _get_person_link(self, data, extra_data=None): extra_data = extra_data or {} person = get_event_person(self.event, data, create_untrusted_persons=self.create_untrusted_persons, allow_external=True) person_data = {'title': next((x.value for x in UserTitle if data.get('title') == orig_string(x.title)), UserTitle.none), 'first_name': data.get('firstName', ''), 'last_name': data['familyName'], 'affiliation': data.get('affiliation', ''), 'address': data.get('address', ''), 'phone': data.get('phone', ''), 'display_order': data['displayOrder']} person_data.update(extra_data) person_link = None if self.object and inspect(person).persistent: person_link = self.person_link_cls.find_first(person=person, object=self.object) if not person_link: person_link = self.person_link_cls(person=person) person_link.populate_from_dict(person_data) email = data.get('email', '').lower() if email != person_link.email: if not self.event or not self.event.persons.filter_by(email=email).first(): person_link.person.email = email person_link.person.user = get_user_by_email(email) if inspect(person).persistent: signals.event.person_updated.send(person_link.person) else: raise UserValueError(_('There is already a person with the email {}').format(email)) return person_link
def render(cls, abstract): return orig_string(abstract.submitter.title)
def _format_permissions(permissions): permissions = set(permissions) return ', '.join(sorted(orig_string(p.friendly_name) for p in available_permissions.itervalues() if p.name in permissions))
def _format_roles(roles): roles = set(roles) return ', '.join(sorted(orig_string(role.friendly_name) for role in available_roles.itervalues() if role.name in roles))