Ejemplo n.º 1
0
def duplicate(event_id=None):
    """Event duplication.

    This page does not duplicates the event but create a new event form with field
    prefilled with antoher event data. When user will click on "Submit", it will act as
    a duplication.

    :param int event_id: Primary key of the event to duplicate.
    """
    if not current_user.can_create_events():
        flash("Accès restreint, rôle insuffisant.", "error")
        return redirect(url_for("event.index"))

    event = Event.query.get(event_id)

    if event == None:
        flash("Pas d'événement à dupliquer", "error")
        return redirect(url_for("event.index"))

    form = EventForm(obj=event)
    form.setup_leader_actions()
    form.duplicate_photo.data = event_id

    return render_template(
        "editevent.html",
        form=form,
        event=event,
        action=url_for("event.manage_event"),
    )
Ejemplo n.º 2
0
def autocomplete_users():
    """API endpoint to list users for autocomplete.

    At least 2 characters are required to make a name search.

    :param string q: Search string.
    :param int l: Maximum number of returned items.
    :return: A tuple:

        - JSON containing information describe in AutocompleteUserSchema
        - HTTP return code : 200
        - additional header (content as JSON)
    :rtype: (string, int, dict)
    """
    if not current_user.can_create_events():
        abort(403)

    q = request.args.get("q")
    if q is None or (len(q) < 2):
        found_users = []
    else:
        limit = request.args.get("l", type=int) or 8
        found_users = find_users_by_fuzzy_name(q, limit)

    content = json.dumps(AutocompleteUserSchema(many=True).dump(found_users))
    return content, 200, {"content-type": "application/json"}
Ejemplo n.º 3
0
def autocomplete_users():

    if not current_user.can_create_events():
        abort(403)

    q = request.args.get('q')
    if q is None or (len(q) < 2):
        found_users = []
    else:
        found_users = find_users_by_fuzzy_name(q)

    content = json.dumps(AutocompleteUserSchema(many=True).dump(found_users))
    return content, 200, {'content-type': 'application/json'}
Ejemplo n.º 4
0
def filter_hidden_events(query):
    """Update a SQLAlchemy query object with a filter that
    removes Event with a status that the current use is not allowed to see

     - Moderators can see all events
     - Normal users cannot see 'Pending' events
     - Activity supervisors can see 'Pending' events for the activities that
       they supervise
     - Leaders can see the events that they lead

    :param query: The original query
    :type query: :py:class:`sqlalchemy.orm.query.Query`
    :return: The filtered query
    :rtype: :py:class:`sqlalchemy.orm.query.Query`
    """
    # Display pending events only to relevant persons
    if not current_user.is_authenticated:
        # Not logged users see no pending event
        query = query.filter(Event.status != EventStatus.Pending)
    elif current_user.is_moderator():
        # Admin see all pending events (no filter)
        pass
    else:
        # Regular user can see non Pending
        query_filter = Event.status != EventStatus.Pending

        # If user is a supervisor, it can see Pending events of its activities
        if current_user.is_supervisor():
            # Supervisors can see all sup
            activities = current_user.get_supervised_activities()
            activities_ids = [a.id for a in activities]
            supervised = Event.activity_types.any(
                ActivityType.id.in_(activities_ids))
            query_filter = or_(query_filter, supervised)

        # If user can create event, it can see its pending events
        if current_user.can_create_events():
            lead = Event.leaders.any(id=current_user.id)
            query_filter = or_(query_filter, lead)

        # After filter construction, it is applied to the query
        query = query.filter(query_filter)
    return query
Ejemplo n.º 5
0
def duplicate(event_id=None):
    if not current_user.can_create_events():
        flash('Accès restreint, rôle insuffisant.', 'error')
        return redirect(url_for('event.index'))

    event = Event.query.get(event_id)

    if event == None:
        flash('Pas d\'évènement à dupliquer', 'error')
        return redirect(url_for('event.index'))

    choices = activity_choices(event.activity_types, event.leaders)
    form = EventForm(choices, obj=event)
    form.type.data = str(event.activity_types[0].id)
    form.duplicate_photo.data = event_id

    return render_template('editevent.html',
                           conf=current_app.config,
                           form=form,
                           action=url_for('event.manage_event'))
Ejemplo n.º 6
0
def duplicate(event_id=None):
    if not current_user.can_create_events():
        flash("Accès restreint, rôle insuffisant.", "error")
        return redirect(url_for("event.index"))

    event = Event.query.get(event_id)

    if event == None:
        flash("Pas d'évènement à dupliquer", "error")
        return redirect(url_for("event.index"))

    form = EventForm(event, obj=event)
    form.setup_leader_actions()
    form.duplicate_photo.data = event_id

    return render_template(
        "editevent.html",
        conf=current_app.config,
        form=form,
        event=event,
        action=url_for("event.manage_event"),
    )
Ejemplo n.º 7
0
def manage_event(event_id=None):
    if not current_user.can_create_events():
        flash("Accès restreint, rôle insuffisant.", "error")
        return redirect(url_for("event.index"))

    event = Event.query.get(event_id) if event_id is not None else Event()
    form = EventForm(event, CombinedMultiDict((request.files, request.form)))

    if not form.is_submitted():
        if event_id is None:
            form = EventForm(event)
            form.set_default_description()
        elif not form.is_submitted():
            form = EventForm(event, obj=event)
        form.setup_leader_actions()
        return render_template("editevent.html",
                               conf=current_app.config,
                               event=event,
                               form=form)

    # Fetch existing readers leaders minus removed ones
    previous_leaders = []
    tentative_leaders = []
    has_removed_leaders = False
    seen_ids = set()
    for action in form.leader_actions:
        leader_id = int(action.data["leader_id"])
        seen_ids.add(leader_id)

        leader = User.query.get(leader_id)
        if leader is None or not leader.can_create_events():
            flash("Encadrant invalide")
            continue

        previous_leaders.append(leader)
        if action.data["delete"]:
            has_removed_leaders = True
        else:
            tentative_leaders.append(leader)

    if event_id is None:
        # Event is not created yet, get current leaders from submitted form
        form.set_current_leaders(previous_leaders)
        form.update_choices(event)
    else:
        # Protect ourselves against form data manipulation
        # We should have a form entry for all existing leaders
        for existing_leader in event.leaders:
            if not existing_leader.id in seen_ids:
                flash("Données incohérentes.", "error")
                return redirect(url_for("event.index"))

    # Add new leader
    new_leader_id = int(form.add_leader.data)
    if new_leader_id > 0:
        leader = User.query.get(new_leader_id)
        if leader is None or not leader.can_create_events():
            flash("Encadrant invalide")
        else:
            tentative_leaders.append(leader)

    # Check that the main leader still exists
    event.main_leader_id = int(form.main_leader_id.data)
    if not any(l.id == event.main_leader_id for l in tentative_leaders):
        flash("Un encadrant responsable doit être défini")

        return render_template("editevent.html",
                               conf=current_app.config,
                               event=event,
                               form=form)

    # The 'Update leaders' button has been clicked
    # Do not process the remainder of the form
    if form.update_leaders.data:
        # Check that the set of leaders is valid for current activities
        if not has_removed_leaders or accept_event_leaders(
                event, tentative_leaders):
            form.set_current_leaders(tentative_leaders)
            form.update_choices(event)
            form.setup_leader_actions()
            if not event_id is None:
                event.leaders = tentative_leaders
                db.session.add(event)
                db.session.commit()

        return render_template("editevent.html",
                               conf=current_app.config,
                               event=event,
                               form=form)

    if not form.validate():
        return render_template("editevent.html",
                               conf=current_app.config,
                               event=event,
                               form=form)

    form.populate_obj(event)

    # The 'Update event button has been clicked'
    # Custom validators
    valid = True
    if not event.starts_before_ends():
        flash("La date de début doit être antérieure à la date de fin")
        valid = False
    if event.num_online_slots > 0:
        if not event.has_defined_registration_date():
            flash(
                "Les date de début ou fin d'ouverture ou de fermeture d'inscription ne peuvent être nulles."
            )
            valid = False
        else:
            if not event.opens_before_closes():
                flash(
                    "Les inscriptions internet doivent ouvrir avant de terminer"
                )
                valid = False
            if not event.closes_before_starts():
                # May need to be relaxed for special events. See #159
                flash(
                    "Les inscriptions internet doivent se terminer avant le début de l'événement"
                )
                valid = False
            elif not event.opens_before_ends():
                flash(
                    "Les inscriptions internet doivent ouvrir avant la fin de l'événement"
                )
                valid = False
        if event.num_slots < event.num_online_slots:
            flash(
                "Le nombre de places internet ne doit pas dépasser le nombre de places total"
            )
            valid = False
    elif event.num_online_slots < 0:
        flash("Le nombre de places par internet ne peut être négatif")
        valid = False

    if not valid:
        return render_template("editevent.html",
                               conf=current_app.config,
                               event=event,
                               form=form)

    event.set_rendered_description(event.description)

    # For now enforce single activity type
    activity_type = ActivityType.query.filter_by(id=event.type).first()
    has_new_activity = activity_type not in event.activity_types
    if has_new_activity:
        event.activity_types.clear()
        event.activity_types.append(activity_type)

    # We have changed activity or removed a leader
    # Check that there is a valid leader
    if has_new_activity or has_removed_leaders:
        if not accept_event_leaders(event, tentative_leaders):
            return render_template("editevent.html",
                                   conf=current_app.config,
                                   event=event,
                                   form=form)
    event.leaders = tentative_leaders

    # We have to save new event before add the photo, or id is not defined
    db.session.add(event)
    db.session.commit()

    # If no photo is sen, we don't do anything, especially if a photo is
    # already existing
    if form.photo_file.data is not None:
        event.save_photo(form.photo_file.data)
        db.session.add(event)
        db.session.commit()
    elif form.duplicate_photo.data != "":
        duplicated_event = Event.query.get(form.duplicate_photo.data)
        if duplicated_event != None:
            event.photo = duplicated_event.photo
            db.session.add(event)
            db.session.commit()

    if event_id is None:
        # This is a new event, send notification to supervisor
        send_new_event_notification(event)

    return redirect(url_for("event.view_event", event_id=event.id))
Ejemplo n.º 8
0
def events():
    page = int(request.args.get('page'))
    size = int(request.args.get('size'))

    # Initialize query
    query = Event.query

    # Display pending events only to relevant persons
    if not current_user.is_authenticated:
        # Not logged users see no pending event
        query = query.filter(Event.status != EventStatus.Pending)
    elif current_user.is_admin():
        # Admin see all pending events (no filter)
        pass
    else:
        # Regular user can see non Pending
        filter = Event.status != EventStatus.Pending

        # If user is a supervisor, it can see Pending events of its activities
        if current_user.is_supervisor():
            # Supervisors can see all sup
            activities = current_user.get_supervised_activities()
            activities_ids = [a.id for a in activities]
            supervised = Event.activity_types.any(
                ActivityType.id.in_(activities_ids))
            filter = or_(filter, supervised)

        # If user can create event, it can see its pending events
        if current_user.can_create_events():
            lead = Event.leaders.any(id=current_user.id)
            filter = or_(filter, lead)

        # After filter construction, it is applied to the query
        query = query.filter(filter)

    # Process all filters.
    # All filter are added as AND
    i = 0
    while f'filters[{i}][field]' in request.args:
        value = request.args.get(f'filters[{i}][value]')
        field = request.args.get(f'filters[{i}][field]')

        if field == 'activity_type':
            filter = Event.activity_types.any(short=value)
        if field == 'end':
            filter = Event.end >= value
        if field == 'status':
            filter = Event.status == value

        query = query.filter(filter)
        # Get next filter
        i += 1

    # Process first sorter only
    if f'sorters[0][field]' in request.args:
        sort_field = request.args.get('sorters[0][field]')
        sort_dir = request.args.get('sorters[0][dir]')
        order = desc(sort_field) if sort_dir == 'desc' else sort_field
        query = query.order_by(order)

    paginated_events = query.paginate(page, size, False)
    data = EventSchema(many=True).dump(paginated_events.items)
    response = {'data': data, "last_page": paginated_events.pages}

    return json.dumps(response), 200, {'content-type': 'application/json'}
Ejemplo n.º 9
0
def manage_event(event_id=None):
    """Event creation and modification page.

    If an ``event_id`` is given, it is a modification of an existing event.

    :param int event_id: Primary key of the event to manage.
    """
    if not current_user.can_create_events():
        flash("Accès restreint, rôle insuffisant.", "error")
        return redirect(url_for("event.index"))

    event = Event.query.get(event_id) if event_id is not None else Event()

    if event is not None and not event.has_edit_rights(current_user):
        flash("Accès restreint.", "error")
        return redirect(url_for("event.index"))

    current_status = event.status
    form = EventForm(CombinedMultiDict((request.files, request.form)))

    if not form.is_submitted():
        if event_id is None:
            form = EventForm()
            form.set_default_values()
        else:
            form = EventForm(obj=event)
        form.setup_leader_actions()
        return render_template("editevent.html", event=event, form=form)

    # Get current activites from form
    tentative_activities = form.current_activities()

    requires_activity = form.current_event_type().requires_activity
    if requires_activity and len(tentative_activities) == 0:
        flash(
            f"Un événement de type {form.current_event_type().name} requiert au moins une activité",
            "error",
        )
        return render_template("editevent.html", event=event, form=form)

    # Fetch existing readers leaders minus removed ones
    previous_leaders = []
    tentative_leaders = []
    has_removed_leaders = False
    for action in form.leader_actions:
        leader_id = int(action.data["leader_id"])

        leader = User.query.get(leader_id)
        if leader is None or not leader.can_create_events():
            flash("Encadrant invalide")
            continue

        previous_leaders.append(leader)
        if action.data["delete"]:
            has_removed_leaders = True
        else:
            tentative_leaders.append(leader)

    # Set current leaders from submitted form
    form.set_current_leaders(previous_leaders)
    form.update_choices()

    # Update activities only
    # Do not process the remainder of the form
    if int(form.update_activity.data):
        # Check that the set of leaders is valid for current activities
        validate_event_leaders(
            tentative_activities, previous_leaders, form.multi_activities_mode.data
        )
        return render_template("editevent.html", event=event, form=form)

    # Add new leader
    new_leader_id = int(form.add_leader.data)
    if new_leader_id > 0:
        leader = User.query.get(new_leader_id)
        if leader is None or not leader.can_create_events():
            flash("Encadrant invalide")
        else:
            tentative_leaders.append(leader)

    # Check that the main leader still exists

    try:
        main_leader_id = int(form.main_leader_id.data)
    except (TypeError, ValueError):
        main_leader_id = None
    if not any(l.id == main_leader_id for l in tentative_leaders):
        flash("Un encadrant responsable doit être défini")
        return render_template("editevent.html", event=event, form=form)

    # Update leaders only
    # Do not process the remainder of the form
    if has_removed_leaders or int(form.update_leaders.data):
        # Check that the set of leaders is valid for current activities
        if validate_event_leaders(
            tentative_activities,
            tentative_leaders,
            form.multi_activities_mode.data,
        ):
            form.set_current_leaders(tentative_leaders)
            form.update_choices()
            form.setup_leader_actions()

        return render_template("editevent.html", event=event, form=form)

    # The 'Update event' button has been clicked
    # Populate object, run custom validators

    if not form.validate():
        return render_template("editevent.html", event=event, form=form)

    # Do not populate the real event as errors may still be raised and we do not want
    # SQLAlchemy to flush the temp data
    trial_event = Event()
    form.populate_obj(trial_event)

    if not validate_dates_and_slots(trial_event):
        return render_template("editevent.html", event=event, form=form)

    has_new_activity = any(a not in event.activity_types for a in tentative_activities)

    tentative_leaders_set = set(tentative_leaders)
    existing_leaders_set = set(event.leaders)
    has_changed_leaders = any(tentative_leaders_set ^ existing_leaders_set)

    # We have added a new activity or added/removed leaders
    # Check that the leaders are still valid
    if has_new_activity or has_changed_leaders:
        if not validate_event_leaders(
            tentative_activities,
            tentative_leaders,
            form.multi_activities_mode.data,
        ):
            return render_template("editevent.html", event=event, form=form)

    # If event has not been created yet use current activities to check rights
    if event_id is None:
        event.activity_types = tentative_activities

    # Check that we have not removed leaders that we don't have the right to
    removed_leaders = existing_leaders_set - tentative_leaders_set
    for removed_leader in removed_leaders:
        if not event.can_remove_leader(current_user, removed_leader):
            flash(
                f"Impossible de supprimer l'encadrant: {removed_leader.full_name()}",
                "error",
            )
            return render_template("editevent.html", event=event, form=form)

    # All good! Apply changes
    form.populate_obj(event)
    event.activity_types = tentative_activities
    event.leaders = tentative_leaders

    # Remove registration associated to leaders (#327)
    if has_changed_leaders:
        for leader in event.leaders:
            leader_registrations = event.existing_registrations(leader)
            if any(leader_registrations):
                flash(
                    f"{leader.full_name()} a été désinscrit(e) de l'événement car il/elle a été ajouté(e) comme encadrant(e)."
                )
            for registration in leader_registrations:
                event.registrations.remove(registration)

    event.set_rendered_description(event.description)

    # Update tags (brute option: purge all and create new)
    event.tag_refs.clear()
    for tag in form.tag_list.data:
        event.tag_refs.append(EventTag(tag))

    # We have to save new event before add the photo, or id is not defined
    db.session.add(event)
    db.session.commit()

    # If no photo is sent, we don't do anything, especially if a photo is
    # already existing
    if form.photo_file.data is not None:
        event.save_photo(form.photo_file.data)
        db.session.add(event)
        db.session.commit()
    elif form.duplicate_photo.data != "":
        duplicated_event = Event.query.get(form.duplicate_photo.data)
        if duplicated_event != None:
            event.photo = duplicated_event.photo
            db.session.add(event)
            db.session.commit()

    if event_id is None:
        # This is a new event, send notification to supervisor
        send_new_event_notification(event)
    else:
        # This is a modified event and the status has changed from Confirmed to Cancelled.
        # then, a notification is sent to supervisors
        if (
            current_status == EventStatus.Confirmed
            and event.status == EventStatus.Cancelled
        ):
            send_cancelled_event_notification(current_user.full_name(), event)

    return redirect(url_for("event.view_event", event_id=event.id))
Ejemplo n.º 10
0
def manage_event(event_id=None):
    if not current_user.can_create_events():
        flash("Accès restreint, rôle insuffisant.", "error")
        return redirect(url_for("event.index"))

    event = Event.query.get(event_id) if event_id is not None else Event()
    form = EventForm(CombinedMultiDict((request.files, request.form)))

    if not form.is_submitted():
        if event_id is None:
            form = EventForm()
            form.set_default_description()
        else:
            form = EventForm(obj=event)
        form.setup_leader_actions()
        return render_template("editevent.html",
                               conf=current_app.config,
                               event=event,
                               form=form)

    # Get current activites from form
    tentative_activities = form.current_activities()

    # Fetch existing readers leaders minus removed ones
    previous_leaders = []
    tentative_leaders = []
    has_removed_leaders = False
    for action in form.leader_actions:
        leader_id = int(action.data["leader_id"])

        leader = User.query.get(leader_id)
        if leader is None or not leader.can_create_events():
            flash("Encadrant invalide")
            continue

        previous_leaders.append(leader)
        if action.data["delete"]:
            has_removed_leaders = True
        else:
            tentative_leaders.append(leader)

    # Set current leaders from submitted form
    form.set_current_leaders(previous_leaders)
    form.update_choices()

    # Update activities only
    # Do not process the remainder of the form
    if int(form.update_activity.data):
        # Check that the set of leaders is valid for current activities
        validate_event_leaders(tentative_activities, previous_leaders,
                               form.multi_activities_mode.data)
        return render_template("editevent.html",
                               conf=current_app.config,
                               event=event,
                               form=form)

    # Add new leader
    new_leader_id = int(form.add_leader.data)
    if new_leader_id > 0:
        leader = User.query.get(new_leader_id)
        if leader is None or not leader.can_create_events():
            flash("Encadrant invalide")
        else:
            tentative_leaders.append(leader)

    # Check that the main leader still exists
    event.main_leader_id = int(form.main_leader_id.data)
    if not any(l.id == event.main_leader_id for l in tentative_leaders):
        flash("Un encadrant responsable doit être défini")

        return render_template("editevent.html",
                               conf=current_app.config,
                               event=event,
                               form=form)

    # Update leaders only
    # Do not process the remainder of the form
    if has_removed_leaders or int(form.update_leaders.data):
        # Check that the set of leaders is valid for current activities
        if validate_event_leaders(
                tentative_activities,
                tentative_leaders,
                form.multi_activities_mode.data,
        ):
            form.set_current_leaders(tentative_leaders)
            form.update_choices()
            form.setup_leader_actions()

        return render_template("editevent.html",
                               conf=current_app.config,
                               event=event,
                               form=form)

    # The 'Update event' button has been clicked
    # Populate object, run custom validators

    if not form.validate():
        return render_template("editevent.html",
                               conf=current_app.config,
                               event=event,
                               form=form)
    form.populate_obj(event)

    if not validate_dates_and_slots(event):
        return render_template("editevent.html",
                               conf=current_app.config,
                               event=event,
                               form=form)

    has_new_activity = any(a not in event.activity_types
                           for a in tentative_activities)

    tentative_leaders_set = set(tentative_leaders)
    existing_leaders_set = set(event.leaders)
    has_changed_leaders = any(tentative_leaders_set ^ existing_leaders_set)

    # We have added a new activity or added/removed leaders
    # Check that the leaders are still valid
    if has_new_activity or has_changed_leaders:
        if not validate_event_leaders(
                tentative_activities,
                tentative_leaders,
                form.multi_activities_mode.data,
        ):
            return render_template("editevent.html",
                                   conf=current_app.config,
                                   event=event,
                                   form=form)

    # If event has not been created yet user current activities to check rights
    if event_id is None:
        event.activity_types = tentative_activities

    # Check that we have not removed leaders that we don't have the right to
    removed_leaders = existing_leaders_set - tentative_leaders_set
    for removed_leader in removed_leaders:
        if not event.can_remove_leader(current_user, removed_leader):
            flash(
                "Impossible de supprimer l'encadrant: {}".format(
                    removed_leader.full_name()),
                "error",
            )
            return render_template("editevent.html",
                                   conf=current_app.config,
                                   event=event,
                                   form=form)

    # All good! Apply changes
    event.activity_types = tentative_activities
    event.leaders = tentative_leaders

    event.set_rendered_description(event.description)

    # We have to save new event before add the photo, or id is not defined
    db.session.add(event)
    db.session.commit()

    # If no photo is sent, we don't do anything, especially if a photo is
    # already existing
    if form.photo_file.data is not None:
        event.save_photo(form.photo_file.data)
        db.session.add(event)
        db.session.commit()
    elif form.duplicate_photo.data != "":
        duplicated_event = Event.query.get(form.duplicate_photo.data)
        if duplicated_event != None:
            event.photo = duplicated_event.photo
            db.session.add(event)
            db.session.commit()

    if event_id is None:
        # This is a new event, send notification to supervisor
        send_new_event_notification(event)

    return redirect(url_for("event.view_event", event_id=event.id))
Ejemplo n.º 11
0
def manage_event(event_id=None):
    if not current_user.can_create_events():
        flash('Accès restreint, rôle insuffisant.', 'error')
        return redirect(url_for('event.index'))

    event = Event.query.get(event_id) if event_id is not None else Event()
    choices = activity_choices(event.activity_types, event.leaders)

    form = EventForm(choices, CombinedMultiDict((request.files, request.form)))

    if not form.is_submitted():
        form = EventForm(choices, obj=event)
        if not event_id is None:
            form.type.data = str(event.activity_types[0].id)

        return render_template('editevent.html',
                               conf=current_app.config,
                               form=form)

    form.populate_obj(event)

    # Validate dates
    valid = True
    if not event.starts_before_ends():
        flash('La date de début doit être antérieure à la date de fin')
        valid = False
    if event.num_online_slots > 0:
        if not event.has_defined_registration_date():
            flash(
                "Les date de début ou fin d\'ouverture ou de fermeture d'inscription ne peuvent être nulles."
            )
            valid = False
        else:
            if not event.opens_before_closes():
                flash(
                    'Les inscriptions internet doivent ouvrir avant de terminer'
                )
                valid = False
            if not event.opens_before_ends():
                flash(
                    'Les inscriptions internet doivent ouvrir avant la fin de l\'événement'
                )
                valid = False
        if event.num_slots < event.num_online_slots:
            flash(
                'Le nombre de places internet ne doit pas dépasser le nombre de places total'
            )
            valid = False
    elif event.num_online_slots < 0:
        flash('Le nombre de places par internet ne peut être négatif')
        valid = False

    if not valid:
        return render_template('editevent.html',
                               conf=current_app.config,
                               form=form)

    event.set_rendered_description(event.description)

    # Only set ourselves as leader if there weren't any
    if not any(event.leaders):
        event.leaders.append(current_user)

    # For now enforce single activity type
    activity_type = ActivityType.query.filter_by(id=event.type).first()
    if activity_type not in event.activity_types:
        event.activity_types.clear()
        event.activity_types.append(activity_type)

        # We are changing the activity, check that there is a valid leader
        if not current_user.is_moderator() and not event.has_valid_leaders():
            flash('Encadrant invalide pour cette activité')
            return render_template('editevent.html',
                                   conf=current_app.config,
                                   form=form)

    # We have to save new event before add the photo, or id is not defined
    db.session.add(event)
    db.session.commit()

    # If no photo is sen, we don't do anything, especially if a photo is
    # already existing
    if (form.photo_file.data is not None):
        event.save_photo(form.photo_file.data)
        db.session.add(event)
        db.session.commit()
    elif form.duplicate_photo.data != "":
        duplicated_event = Event.query.get(form.duplicate_photo.data)
        if duplicated_event != None:
            event.photo = duplicated_event.photo
            db.session.add(event)
            db.session.commit()

    if event_id is None:
        # This is a new event, send notification to supervisor
        send_new_event_notification(event)

    return redirect(url_for('event.view_event', event_id=event.id))
Ejemplo n.º 12
0
def events():
    page = int(request.args.get("page"))
    size = int(request.args.get("size"))

    # Initialize query
    query = Event.query

    # Display pending events only to relevant persons
    if not current_user.is_authenticated:
        # Not logged users see no pending event
        query = query.filter(Event.status != EventStatus.Pending)
    elif current_user.is_admin():
        # Admin see all pending events (no filter)
        pass
    else:
        # Regular user can see non Pending
        query_filter = Event.status != EventStatus.Pending

        # If user is a supervisor, it can see Pending events of its activities
        if current_user.is_supervisor():
            # Supervisors can see all sup
            activities = current_user.get_supervised_activities()
            activities_ids = [a.id for a in activities]
            supervised = Event.activity_types.any(
                ActivityType.id.in_(activities_ids))
            query_filter = or_(query_filter, supervised)

        # If user can create event, it can see its pending events
        if current_user.can_create_events():
            lead = Event.leaders.any(id=current_user.id)
            query_filter = or_(query_filter, lead)

        # After filter construction, it is applied to the query
        query = query.filter(query_filter)

    # Process all filters.
    # All filter are added as AND
    i = 0
    while f"filters[{i}][field]" in request.args:
        value = request.args.get(f"filters[{i}][value]")
        filter_type = request.args.get(f"filters[{i}][type]")
        field = request.args.get(f"filters[{i}][field]")

        if field == "status":
            value = getattr(EventStatus, value)

        query_filter = None
        if field == "activity_type":
            query_filter = Event.activity_types.any(short=value)
        elif field == "end":
            if filter_type == ">=":
                query_filter = Event.end >= current_time()
        elif field == "status":
            if filter_type == "=":
                query_filter = Event.status == value
            elif filter_type == "!=":
                query_filter = Event.status != value

        if query_filter is not None:
            query = query.filter(query_filter)
        # Get next filter
        i += 1

    # Process first sorter only
    if "sorters[0][field]" in request.args:
        sort_field = request.args.get("sorters[0][field]")
        sort_dir = request.args.get("sorters[0][dir]")
        order = desc(sort_field) if sort_dir == "desc" else sort_field
        query = query.order_by(order)

    paginated_events = query.paginate(page, size, False)
    data = EventSchema(many=True).dump(paginated_events.items)
    response = {"data": data, "last_page": paginated_events.pages}

    return json.dumps(response), 200, {"content-type": "application/json"}