Пример #1
0
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)
Пример #2
0
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})
Пример #3
0
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)
Пример #4
0
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
Пример #5
0
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()
Пример #6
0
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()
Пример #7
0
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)
Пример #8
0
 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))
Пример #9
0
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)
Пример #10
0
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
Пример #11
0
 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]
             }
         }),
     ]
Пример #12
0
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
Пример #13
0
 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))
Пример #14
0
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
Пример #15
0
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)
Пример #16
0
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
Пример #17
0
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)
Пример #18
0
 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
Пример #19
0
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)
Пример #20
0
 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
         }),
     ]
Пример #21
0
 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
Пример #22
0
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
Пример #23
0
 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)
Пример #24
0
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
Пример #26
0
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)})
Пример #27
0
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)
Пример #28
0
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
Пример #29
0
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
Пример #30
0
 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
Пример #31
0
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)
Пример #32
0
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
Пример #33
0
 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
Пример #34
0
 def render(cls, abstract):
     return orig_string(abstract.submitter.title)
Пример #35
0
 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))
Пример #36
0
 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))
Пример #37
0
 def render(cls, abstract):
     return orig_string(abstract.submitter.title)