def add_calendar(): """ Add a calendar to the database. This function is only accessible to admin of the webapp. """ if not flask.g.fas_user: return flask.redirect(flask.url_for("index")) if not is_admin(): flask.flash("You are not a fedocal admin, you are not allowed " "to add calendars.", "errors") return flask.redirect(flask.url_for("index")) form = forms.AddCalendarForm() # pylint: disable=E1101 if form.validate_on_submit(): calendarobj = Calendar( calendar_name=form.calendar_name.data, calendar_contact=form.calendar_contact.data, calendar_description=form.calendar_description.data, calendar_manager_group=form.calendar_manager_groups.data, calendar_admin_group=form.calendar_admin_groups.data, calendar_multiple_meetings=bool(form.calendar_multiple_meetings.data), calendar_regional_meetings=bool(form.calendar_regional_meetings.data), ) try: calendarobj.save(SESSION) SESSION.commit() except SQLAlchemyError, err: SESSION.rollback() print "add_calendar:", err flask.flash("Could not add this calendar to the database", "errors") return flask.render_template("add_calendar.html", form=form) flask.flash("Calendar added") return flask.redirect(flask.url_for("index"))
def add_meeting(calendar_name): """ Add a meeting to the database. This function is only available to CLA+1 member or members of the group administrating of the said calendar. :arg calendar_name, name of the calendar in which to add the meeting. """ if not flask.g.fas_user: return flask.redirect(flask.url_for("index")) calendarobj = Calendar.by_id(SESSION, calendar_name) if calendarobj.calendar_manager_group and not ( is_calendar_manager(calendarobj) or is_calendar_admin(calendarobj) or is_admin() ): flask.flash( "You are not one of the manager of this calendar, " "or one of its admins, you are not allowed to add " "new meetings.", "errors", ) return flask.redirect(flask.url_for("calendar", calendar_name=calendar_name)) form = forms.AddMeetingForm() tzone = get_timezone() calendarobj = Calendar.by_id(SESSION, calendar_name) # pylint: disable=E1101 if form.validate_on_submit(): try: fedocallib.add_meeting( session=SESSION, calendarobj=calendarobj, fas_user=flask.g.fas_user, meeting_name=form.meeting_name.data, meeting_date=form.meeting_date.data, meeting_date_end=form.meeting_date_end.data, meeting_time_start=form.meeting_time_start.data, meeting_time_stop=form.meeting_time_stop.data, comanager=form.comanager.data, meeting_information=form.information.data, meeting_region=form.meeting_region.data, tzone=get_timezone(), frequency=form.frequency.data, end_repeats=form.end_repeats.data, remind_when=form.remind_when.data, remind_who=form.remind_who.data, full_day=form.full_day.data, admin=is_admin(), ) except FedocalException, err: flask.flash(err, "warnings") return flask.render_template("add_meeting.html", calendar=calendarobj, form=form, tzone=tzone) except SQLAlchemyError, err: SESSION.rollback() print "add_meeting:", err flask.flash("Could not add this meeting to this calendar", "errors") return flask.render_template("add_meeting.html", calendar=calendarobj, form=form, tzone=tzone)
def index(): """ Displays the index page with containing the first calendar (by order of creation and if any) for the current week. """ calendars_enabled = Calendar.by_status(SESSION, 'Enabled') calendars_disabled = Calendar.by_status(SESSION, 'Disabled') auth_form = forms.LoginForm() admin = is_admin() return flask.render_template( 'index.html', calendars=calendars_enabled, calendars_table=chunks(calendars_enabled, 3), calendars_table2=chunks(calendars_disabled, 3), auth_form=auth_form, admin=admin)
def edit_calendar(calendar_name): """ Edit a specific calendar based on the calendar identifier. :arg calendar_name: the identifier of the calendar to edit. """ if not flask.g.fas_user: return flask.redirect(flask.url_for("index")) if not is_admin(): flask.flash("You are not a fedocal admin, you are not allowed " "to edit the calendar.", "errors") return flask.redirect(flask.url_for("index")) calendarobj = Calendar.by_id(SESSION, calendar_name) form = forms.AddCalendarForm() # pylint: disable=E1101 if form.validate_on_submit(): try: calendarobj.calendar_name = form.calendar_name.data calendarobj.calendar_contact = form.calendar_contact.data calendarobj.calendar_description = form.calendar_description.data calendarobj.calendar_manager_group = form.calendar_manager_groups.data calendarobj.calendar_admin_group = form.calendar_admin_groups.data calendarobj.calendar_multiple_meetings = bool(form.calendar_multiple_meetings.data) calendarobj.calendar_regional_meetings = bool(form.calendar_regional_meetings.data) calendarobj.save(SESSION) SESSION.commit() except SQLAlchemyError, err: SESSION.rollback() print "edit_calendar:", err flask.flash("Could not update this calendar.", "errors") return flask.render_template("edit_calendar.html", form=form, calendar=calendarobj) flask.flash("Calendar updated") return flask.redirect(flask.url_for("calendar", calendar_name=calendarobj.calendar_name))
def delete_calendar(calendar_name): """ Delete a specific calendar given its identifier. :arg calendar_name: the identifier of the calendar to delete. """ if not flask.g.fas_user: return flask.redirect(flask.url_for("index")) if not is_admin(): flask.flash("You are not a fedocal admin, you are not allowed " "to delete the calendar.", "errors") return flask.redirect(flask.url_for("index")) calendarobj = Calendar.by_id(SESSION, calendar_name) deleteform = forms.DeleteCalendarForm() # pylint: disable=E1101 if deleteform.validate_on_submit(): if deleteform.confirm_delete.data: calendarobj.delete(SESSION) try: SESSION.commit() except SQLAlchemyError, err: SESSION.rollback() print "delete_calendar:", err flask.flash("Could not delete this calendar.", "errors") flask.flash("Calendar deleted") return flask.redirect(flask.url_for("index"))
def delete_calendar(calendar_name): """ Delete a specific calendar given its identifier. :arg calendar_name: the identifier of the calendar to delete. """ if not flask.g.fas_user: return flask.redirect(flask.url_for('index')) if not is_admin(): flask.flash('You are not a fedocal admin, you are not allowed ' 'to delete the calendar.', 'errors') return flask.redirect(flask.url_for('index')) calendarobj = Calendar.by_id(SESSION, calendar_name) deleteform = forms.DeleteCalendarForm() # pylint: disable=E1101 if deleteform.validate_on_submit(): if deleteform.confirm_delete.data: calendarobj.delete(SESSION) try: SESSION.commit() except SQLAlchemyError, err: SESSION.rollback() print 'delete_calendar:', err flask.flash('Could not delete this calendar.', 'errors') flask.flash('Calendar deleted') fedmsg.publish(topic="calendar.delete", msg=dict( agent=flask.g.fas_user.username, calendar=calendarobj.to_json(), )) return flask.redirect(flask.url_for('index'))
def delete_meeting(meeting_id): """ Delete a specific meeting given its identifier. :arg meeting_id: the identifier of the meeting to delete. """ if not flask.g.fas_user: return flask.redirect(flask.url_for("index")) meeting = Meeting.by_id(SESSION, meeting_id) if not (is_meeting_manager(meeting) or is_calendar_admin(meeting.calendar) or is_admin()): flask.flash( "You are not one of the manager of this meeting, " "or an admin, you are not allowed to delete it.", "errors", ) return flask.redirect(flask.url_for("view_meeting", meeting_id=meeting_id)) calendars = Calendar.get_all(SESSION) deleteform = forms.DeleteMeetingForm() # pylint: disable=E1101 if deleteform.validate_on_submit(): if deleteform.confirm_delete.data: if deleteform.confirm_futher_delete.data: fedocallib.delete_recursive_meeting(SESSION, meeting) else: meeting.delete(SESSION) try: SESSION.commit() except SQLAlchemyError, err: SESSION.rollback() print "edit_meeting:", err flask.flash("Could not update this meeting.", "error") flask.flash("Meeting deleted") return flask.redirect(flask.url_for("calendar", calendar_name=meeting.calendar_name))
def inject_calendars(): """ With this decorator we add the list of all the calendars available to all the function, so the variable calendars is available in all templates. """ calendars = Calendar.get_all(SESSION) return dict(calendars=calendars)
def add_calendar(): """ Add a calendar to the database. This function is only accessible to admin of the webapp. """ if not flask.g.fas_user: return flask.redirect(flask.url_for('index')) if not is_admin(): flask.flash('You are not a fedocal admin, you are not allowed ' 'to add calendars.', 'errors') return flask.redirect(flask.url_for('index')) status = fedocallib.get_calendar_statuses(SESSION) form = forms.AddCalendarForm(status=status) # pylint: disable=E1101 if form.validate_on_submit(): calendarobj = Calendar( calendar_name=form.calendar_name.data, calendar_contact=form.calendar_contact.data, calendar_description=form.calendar_description.data, calendar_editor_group=form.calendar_editor_groups.data, calendar_admin_group=form.calendar_admin_groups.data, calendar_multiple_meetings=bool( form.calendar_multiple_meetings.data), calendar_regional_meetings=bool( form.calendar_regional_meetings.data), calendar_status=form.calendar_status.data ) try: calendarobj.save(SESSION) SESSION.commit() except SQLAlchemyError, err: SESSION.rollback() print 'add_calendar:', err flask.flash('Could not add this calendar to the database', 'errors') return flask.render_template('add_calendar.html', form=form) flask.flash('Calendar added') fedmsg.publish(topic="calendar.new", msg=dict( agent=flask.g.fas_user.username, calendar=calendarobj.to_json(), )) return flask.redirect(flask.url_for('index'))
def index(): """ Displays the index page with containing the first calendar (by order of creation and if any) for the current week. """ calendars = Calendar.get_all(SESSION) auth_form = forms.LoginForm() admin = is_admin() return flask.render_template( "index.html", calendars=calendars, calendars_table=chunks(calendars, 3), auth_form=auth_form, admin=admin )
def is_user_managing_in_calendar(session, calendar_name, fas_user): """ Returns True if the user is in a group set as editor of the calendar and False otherwise. It will also return True if there are no groups set as editor the calendar. :arg session: the database session to use :arg calendar_name: the name of the calendar of interest. :arg fas_user: a FAS user object with all the info. """ editor_groups = Calendar.get_editor_groups(session, calendar_name) admin_groups = Calendar.get_admin_groups(session, calendar_name) if not editor_groups: return True else: return len( set(editor_groups).intersection(set(fas_user.groups)) ) >= 1 or len( set(admin_groups).intersection(set(fas_user.groups)) ) >= 1
def edit_meeting(meeting_id): """ Edit a specific meeting based on the meeting identifier. :arg meeting_id: the identifier of the meeting to edit. """ if not flask.g.fas_user: return flask.redirect(flask.url_for("index")) meeting = Meeting.by_id(SESSION, meeting_id) calendarobj = Calendar.by_id(SESSION, meeting.calendar_name) if not (is_meeting_manager(meeting) or is_calendar_admin(meeting.calendarobj) or is_admin()): flask.flash( "You are not one of the manager of this meeting, " "or an admin, you are not allowed to edit it.", "errors" ) return flask.redirect(flask.url_for("view_meeting", meeting_id=meeting_id)) tzone = get_timezone() form = forms.AddMeetingForm() # pylint: disable=E1101 if form.validate_on_submit(): try: fedocallib.edit_meeting( session=SESSION, meeting=meeting, calendarobj=calendarobj, fas_user=flask.g.fas_user, meeting_name=form.meeting_name.data, meeting_date=form.meeting_date.data, meeting_date_end=None, meeting_time_start=form.meeting_time_start.data, meeting_time_stop=form.meeting_time_stop.data, comanager=form.comanager.data, meeting_information=form.information.data, meeting_region=form.meeting_region.data, tzone=get_timezone(), recursion_frequency=form.frequency.data, recursion_ends=form.end_repeats.data, remind_when=form.remind_when.data, remind_who=form.remind_who.data, full_day=form.full_day.data, edit_all_meeting=form.recursive_edit.data, admin=is_admin(), ) except FedocalException, err: flask.flash(err, "warnings") return flask.render_template( "edit_meeting.html", meeting=meeting, calendar=calendarobj, form=form, tzone=tzone ) except SQLAlchemyError, err: SESSION.rollback() print "edit_meeting:", err flask.flash("Could not update this meeting.", "errors") return flask.render_template( "edit_meeting.html", meeting=meeting, calendar=calendarobj, form=form, tzone=tzone )
def ical_all(): """ Returns a iCal feed of all calendars from today - 1 month to today + 6 month. """ startd = datetime.date.today() - datetime.timedelta(days=30) endd = datetime.date.today() + datetime.timedelta(days=180) ical = vobject.iCalendar() meetings = [] for calendar in Calendar.get_all(SESSION): meetings.extend(fedocallib.get_meetings_by_date(SESSION, calendar.calendar_name, startd, endd)) fedocallib.add_meetings_to_vcal(ical, meetings) return flask.Response(ical.serialize(), mimetype="text/calendar")
def calendar_list(calendar_name, year, month, day): """ Display in a list form all the meetings of a given calendar. By default it displays all the meetings of the current year but this can be more restricted to a month or even a day. :arg calendar_name: the name of the calendar that one would like to consult. :arg year: the year of the date one would like to consult. :arg month: the month of the date one would like to consult. :arg day: the day of the date one would like to consult. """ inyear = year if not year: inyear = datetime.date.today().year inmonth = month if not month: inmonth = 1 inday = day if not day: inday = 1 start_date = datetime.date(inyear, inmonth, inday) if not month and not day: end_date = start_date + relativedelta(years=+1) elif not day: end_date = start_date + relativedelta(months=+1) else: end_date = start_date + relativedelta(days=+1) calendarobj = Calendar.by_id(SESSION, calendar_name) tzone = get_timezone() meetings = fedocallib.get_by_date( SESSION, calendarobj, start_date, end_date, tzone) month_name = datetime.date.today().strftime('%B') auth_form = forms.LoginForm() admin = is_admin() curmonth_cal = fedocallib.get_html_monthly_cal( year=year, month=month, day=day, calendar_name=calendar_name) return flask.render_template( 'meeting_list.html', calendar=calendarobj, month=month_name, meetings=meetings, tzone=tzone, year=inyear, auth_form=auth_form, curmonth_cal=curmonth_cal, admin=admin)
def delete_meeting(meeting_id): """ Delete a specific meeting given its identifier. :arg meeting_id: the identifier of the meeting to delete. """ if not flask.g.fas_user: return flask.redirect(flask.url_for('index')) meeting = Meeting.by_id(SESSION, meeting_id) if meeting.calendar.calendar_status != 'Enabled': flask.flash('This calendar is "%s", you are not allowed to delete ' 'its meetings anymore.' % calendarobj.calendar_status, 'errors') return flask.redirect(flask.url_for('calendar', calendar_name=calendar_name)) if not (is_meeting_manager(meeting) or is_calendar_admin(meeting.calendar) or is_admin()): flask.flash('You are not one of the manager of this meeting, ' 'or an admin, you are not allowed to delete it.', 'errors') return flask.redirect(flask.url_for('view_meeting', meeting_id=meeting_id)) calendars = Calendar.get_all(SESSION) deleteform = forms.DeleteMeetingForm() # pylint: disable=E1101 if deleteform.validate_on_submit(): if deleteform.confirm_delete.data: if deleteform.confirm_futher_delete.data: fedocallib.delete_recursive_meeting(SESSION, meeting) else: meeting.delete(SESSION) try: SESSION.commit() except SQLAlchemyError, err: SESSION.rollback() print 'edit_meeting:', err flask.flash('Could not update this meeting.', 'error') flask.flash('Meeting deleted') fedmsg.publish(topic="meeting.delete", msg=dict( agent=flask.g.fas_user.username, meeting=meeting.to_json(), calendar=meeting.calendar.to_json(), )) return flask.redirect(flask.url_for( 'calendar', calendar_name=meeting.calendar_name))
def get_meetings_by_date_and_location( session, calendar, start_date, end_date, location): """ Return a list of meetings which have or will occur in between the two provided dates. :arg session: the database session to use :arg calendar: the name of the calendar of interest. :arg start_date: the date from which we would like to retrieve the meetings (this day is included in the selection). :arg start_date: the date until which we would like to retrieve the meetings (this day is excluded from the selection). :arg location: the location in which the meetings occurs. """ calendar = Calendar.by_id(session, calendar) return Meeting.get_by_date_and_location(session, calendar, start_date, end_date, location)
def edit_calendar(calendar_name): """ Edit a specific calendar based on the calendar identifier. :arg calendar_name: the identifier of the calendar to edit. """ if not flask.g.fas_user: return flask.redirect(flask.url_for('index')) if not is_admin(): flask.flash('You are not a fedocal admin, you are not allowed ' 'to edit the calendar.', 'errors') return flask.redirect(flask.url_for('index')) calendarobj = Calendar.by_id(SESSION, calendar_name) status = fedocallib.get_calendar_statuses(SESSION) form = forms.AddCalendarForm(status=status) # pylint: disable=E1101 if form.validate_on_submit(): try: calendarobj.calendar_name = form.calendar_name.data calendarobj.calendar_contact = form.calendar_contact.data calendarobj.calendar_description = form.calendar_description.data calendarobj.calendar_editor_group = \ form.calendar_editor_groups.data calendarobj.calendar_admin_group = \ form.calendar_admin_groups.data calendarobj.calendar_multiple_meetings = bool( form.calendar_multiple_meetings.data) calendarobj.calendar_regional_meetings = bool( form.calendar_regional_meetings.data) calendarobj.calendar_status = form.calendar_status.data calendarobj.save(SESSION) SESSION.commit() except SQLAlchemyError, err: SESSION.rollback() print 'edit_calendar:', err flask.flash('Could not update this calendar.', 'errors') return flask.render_template( 'edit_calendar.html', form=form, calendar=calendarobj) flask.flash('Calendar updated') fedmsg.publish(topic="calendar.update", msg=dict( agent=flask.g.fas_user.username, calendar=calendarobj.to_json(), )) return flask.redirect(flask.url_for( 'calendar', calendar_name=calendarobj.calendar_name))
def calendar(calendar_name, year, month, day): """ Display the week of a specific date for a specified calendar. :arg calendar_name: the name of the calendar that one would like to consult. :arg year: the year of the date one would like to consult. :arg month: the month of the date one would like to consult. :arg day: the day of the date one would like to consult. """ calendarobj = Calendar.by_id(SESSION, calendar_name) week_start = fedocallib.get_start_week(year, month, day) weekdays = fedocallib.get_week_days(year, month, day) tzone = get_timezone() meetings = fedocallib.get_meetings( SESSION, calendarobj, year, month, day, tzone=tzone) next_week = fedocallib.get_next_week( week_start.year, week_start.month, week_start.day) prev_week = fedocallib.get_previous_week( week_start.year, week_start.month, week_start.day) auth_form = forms.LoginForm() admin = is_admin() month_name = week_start.strftime('%B') day_index = None today = datetime.date.today() if today > week_start and today < week_start + datetime.timedelta(days=7): day_index = fedocallib.get_week_day_index( today.year, today.month, today.day) curmonth_cal = fedocallib.get_html_monthly_cal( year=year, month=month, day=day, calendar_name=calendar_name) return flask.render_template( 'agenda.html', calendar=calendarobj, month=month_name, weekdays=weekdays, day_index=day_index, meetings=meetings, tzone=tzone, next_week=next_week, prev_week=prev_week, auth_form=auth_form, curmonth_cal=curmonth_cal, admin=admin)
def api_meetings(): """ Retrieve meetings ================= The ``/api/meetings/`` endpoint returns the meetings meeting the provided criteria. Response format ---------------- Sample response: .. code-block:: javascript { "meetings": [ { "meeting_time_start": "23:00:00", "meeting_information": "", "meeting_time_stop": "23:00:00", "calendar_name": "test", "meeting_date_end": "2013-05-27", "meeting_manager": "pingou2,", "meeting_date": "2013-05-27", "meeting_name": "test1.5", "meeting_location": "None" }, { "meeting_time_start": "06:00:00", "meeting_information": "", "meeting_time_stop": "07:00:00", "calendar_name": "test", "meeting_date_end": "2013-05-28", "meeting_manager": "pingou,", "meeting_date": "2013-05-28", "meeting_name": "test3", "meeting_location": null } ], "arguments": { "start": "2013-05-04", "calendar": "test", "end": "2013-11-30", "region": null } } The ``arguments`` item in the root dictionary contains all possible arguments, and displays the value used (the default if the argument was not provided). Time arguments -------------- Below is a table describing what timeframe messages are received from depending on what combination of time options you provide. ========= ======= ================= ``start`` ``end`` Message timeframe ========= ======= ================= no no the last 30 days and the coming 180 days **yes** no from ``start`` until the coming 180 days no **yes** the last 30 days until ``end`` **yes** **yes** between ``start`` and ``end`` ========= ======= ================= ``start`` Return results starting at date ``start`` (prefered format is "+%Y-%m-%d" see ``date "+%Y-%m-%d"``). Default: 30 days ago ``date "+%Y-%m-%d" -d "30 days ago"`` ``end`` Return results ending at date ``end`` (prefered format is "+%Y-%m-%d" see ``date "+%Y-%m-%d"``). Default: coming 180 days ``date "+%Y-%m-%d" -d "180 days"`` Filter arguments ---------------- ``calendar`` Restrict the meetings to a specific calendar. Default: all calendars ``region`` Restrict the meeting to a specific region. If the calendar does not have support for regions enabled, no meetings will be found matching this criteria and no meetings will be returned. Default: all regions """ @flask.after_this_request def callback(response): """ Handle case the query was an JQuery ajax call. """ return check_callback(response) startd = flask.request.args.get('start', None) if startd is None: startd = datetime.date.today() - datetime.timedelta(days=30) else: try: startd = parser.parse(startd).date() except ValueError: output = {"meetings": [], "error": "Invalid start date format: %s" % startd} return flask.Response( response=json.dumps(output), status=400, mimetype='application/json') endd = flask.request.args.get('end', None) if endd is None: endd = datetime.date.today() + datetime.timedelta(days=180) else: try: endd = parser.parse(endd).date() except ValueError: output = {"meetings": [], "error": "Invalid end date format: %s" % endd} return flask.Response( response=json.dumps(output), status=400, mimetype='application/json') calendar_name = flask.request.args.get('calendar', None) location = flask.request.args.get('location', None) region = flask.request.args.get('region', None) location = location or region if calendar_name: calendarobj = Calendar.by_id(SESSION, calendar_name) if not calendarobj: output = {"meetings": [], "error": "Invalid calendar provided: %s" % calendar_name} return flask.Response( response=json.dumps(output), status=400, mimetype='application/json') status = 200 meetings = [] try: if calendar_name: if location: #print "calendar and region" meetings = fedocallib.get_meetings_by_date_and_location( SESSION, calendar_name, startd, endd, location) else: #print "calendar and no region" meetings = fedocallib.get_by_date( SESSION, calendarobj, startd, endd) else: meetings = [] if location: #print "no calendar and region" meetings.extend( fedocallib.get_by_date_at_location( SESSION, location, startd, endd) ) else: #print "no calendar and no region" for calendar in fedocallib.get_calendars(SESSION): meetings.extend(fedocallib.get_by_date( SESSION, calendar, startd, endd)) except SQLAlchemyError, err: # pragma: no cover status = 500 LOG.debug('Error in api_meetings') LOG.exception(err)
def api_user_shield(username, calendar_name): """ User shield =========== Provides a small image (a shield) displaying the status of the specified user on the specified calendar if the user is currently managing a meeting. Filter arguments ---------------- ``connector`` Changes the 'connector' text used in the image. Default: 'in' ``status`` Changes the 'status' text used in the image. Default: the name of the calendar checked ``always`` Booleans to specify whether to return an image if no meeting is found for the specified user on the specified calendar. Default: True Can be: False, 0, f If the user is not managing a meeting, instead of returning the image the endpoint raises a 404. """ connector = flask.request.args.get('connector', 'in') status = flask.request.args.get('status', calendar_name) always = flask.request.args.get('always', True) if str(always).lower() in ['0', 'false', 'f']: always = False else: always = True calendarobj = Calendar.by_id(SESSION, calendar_name) if not calendarobj: flask.abort(400, 'Invalid calendar provided') start_date = datetime.datetime.utcnow().date() end_date = start_date + datetime.timedelta(days=1) meetings = fedocallib.get_by_date( SESSION, calendarobj, start_date, end_date, tzone='UTC') green, red = 'brightgreen', 'red' template = 'https://img.shields.io/badge/%s-%s_%s-%s.png' output = None for meeting in meetings: usernames = [user.username for user in meeting.meeting_manager_user] if username in usernames: output = template % (username, connector, status, green) break if output: return flask.redirect(output) elif always: output = template % (username, "not " + connector, status, red) return flask.redirect(output) else: flask.abort(404)
def api_meetings(): """ Retrieve meetings ================= The ``/api/meetings/`` endpoint returns the meetings meeting the provided criteria. Response format ---------------- Sample response: .. code-block:: javascript { "meetings": [ { "meeting_time_start": "23:00:00", "meeting_information": "", "meeting_time_stop": "23:00:00", "calendar_name": "test", "meeting_date_end": "2013-05-27", "meeting_manager": [ "pingou2" ], "meeting_date": "2013-05-27", "meeting_name": "test1.5", "meeting_location": "None", "meeting_timezone": "UTC" }, { "meeting_time_start": "06:00:00", "meeting_information": "", "meeting_time_stop": "07:00:00", "calendar_name": "test", "meeting_date_end": "2013-05-28", "meeting_manager": [ "pingou" ], "meeting_date": "2013-05-28", "meeting_name": "test3", "meeting_location": null, "meeting_timezone": "UTC" } ], "arguments": { "start": "2013-05-04", "calendar": "test", "end": "2013-11-30", "region": null } } The ``meeting_time_start``, ``meeting_time_end``, ``meeting_date`` and ``meeting_date_end`` contain time in "UTC". The ``meeting_timezone`` indicates the timezone the meeting is registered with. If the ``meeting_timezone`` is not "UTC", the meeting time will change according to DST rules of the specified timezone. The ``arguments`` item in the root dictionary contains all possible arguments, and displays the value used (the default if the argument was not provided). Time arguments -------------- Below is a table describing what timeframe messages are received from depending on what combination of time options you provide. ========= ======= ================= ``start`` ``end`` Message timeframe ========= ======= ================= no no the last 30 days and the coming 180 days **yes** no from ``start`` until the coming 180 days no **yes** the last 30 days until ``end`` **yes** **yes** between ``start`` and ``end`` ========= ======= ================= ``start`` Return results starting at date ``start`` (prefered format is "+%Y-%m-%d" see ``date "+%Y-%m-%d"``). Default: 30 days ago ``date "+%Y-%m-%d" -d "30 days ago"`` ``end`` Return results ending at date ``end`` (prefered format is "+%Y-%m-%d" see ``date "+%Y-%m-%d"``). Default: coming 180 days ``date "+%Y-%m-%d" -d "180 days"`` Filter arguments ---------------- ``calendar`` Restrict the meetings to a specific calendar. Default: all calendars ``region`` Restrict the meeting to a specific region. If the calendar does not have support for regions enabled, no meetings will be found matching this criteria and no meetings will be returned. Default: all regions """ @flask.after_this_request def callback(response): """ Handle case the query was an JQuery ajax call. """ return check_callback(response) startd = flask.request.args.get('start', None) if startd is None: startd = datetime.date.today() - datetime.timedelta(days=30) else: try: startd = parser.parse(startd).date() except (ValueError, TypeError): output = {"meetings": [], "error": "Invalid start date format: %s" % startd} return flask.Response( response=json.dumps(output), status=400, mimetype='application/json') endd = flask.request.args.get('end', None) if endd is None: endd = datetime.date.today() + datetime.timedelta(days=180) else: try: endd = parser.parse(endd).date() except (ValueError, TypeError): output = {"meetings": [], "error": "Invalid end date format: %s" % endd} return flask.Response( response=json.dumps(output), status=400, mimetype='application/json') calendar_name = flask.request.args.get('calendar', None) location = flask.request.args.get('location', None) region = flask.request.args.get('region', None) location = location or region if calendar_name: calendarobj = Calendar.by_id(SESSION, calendar_name) if not calendarobj: output = { "meetings": [], "error": "Invalid calendar provided: %s" % calendar_name} return flask.Response( response=json.dumps(output), status=400, mimetype='application/json') status = 200 meetings = [] try: if calendar_name: if location: # print "calendar and region" meetings = fedocallib.get_meetings_by_date_and_location( SESSION, calendar_name, startd, endd, location) else: # print "calendar and no region" meetings = fedocallib.get_by_date( SESSION, calendarobj, startd, endd) else: meetings = [] if location: # print "no calendar and region" meetings.extend( fedocallib.get_by_date_at_location( SESSION, location, startd, endd) ) else: # print "no calendar and no region" for calendar in fedocallib.get_calendars(SESSION): meetings.extend(fedocallib.get_by_date( SESSION, calendar, startd, endd)) except SQLAlchemyError as err: # pragma: no cover status = 500 LOG.debug('Error in api_meetings') LOG.exception(err) output = {} output['arguments'] = { 'start': startd.strftime('%Y-%m-%d'), 'end': endd.strftime('%Y-%m-%d'), 'calendar': calendar_name, 'location': location, } meetings_json = [] for meeting in meetings: meetings_json.append(meeting.to_json()) output['meetings'] = meetings_json return flask.Response( response=json.dumps(output), status=status, mimetype='application/json' )
def edit_meeting(meeting_id): """ Edit a specific meeting based on the meeting identifier. :arg meeting_id: the identifier of the meeting to edit. """ if not flask.g.fas_user: return flask.redirect(flask.url_for('index')) meeting = Meeting.by_id(SESSION, meeting_id) calendarobj = Calendar.by_id(SESSION, meeting.calendar_name) if calendarobj.calendar_status != 'Enabled': flask.flash('This calendar is "%s", you are not allowed to edit its ' 'meetings anymore.' % calendarobj.calendar_status, 'errors') return flask.redirect(flask.url_for('calendar', calendar_name=calendar_name)) if not (is_meeting_manager(meeting) or is_calendar_admin(calendarobj) or is_admin()): flask.flash('You are not one of the manager of this meeting, ' 'or an admin, you are not allowed to edit it.', 'errors') return flask.redirect(flask.url_for('view_meeting', meeting_id=meeting_id)) tzone = get_timezone() form = forms.AddMeetingForm(timezone=tzone) # pylint: disable=E1101 if form.validate_on_submit(): tzone = form.meeting_timezone.data or tzone try: fedocallib.edit_meeting( session=SESSION, meeting=meeting, calendarobj=calendarobj, fas_user=flask.g.fas_user, meeting_name=form.meeting_name.data, meeting_date=form.meeting_date.data, meeting_date_end=None, meeting_time_start=form.meeting_time_start.data, meeting_time_stop=form.meeting_time_stop.data, comanager=form.comanager.data, meeting_information=form.information.data, meeting_region=form.meeting_region.data, tzone=tzone, recursion_frequency=form.frequency.data, recursion_ends=form.end_repeats.data, remind_when=form.remind_when.data, remind_who=form.remind_who.data, full_day=form.full_day.data, edit_all_meeting=form.recursive_edit.data, admin=is_admin()) except FedocalException, err: flask.flash(err, 'warnings') return flask.render_template( 'edit_meeting.html', meeting=meeting, calendar=calendarobj, form=form, tzone=tzone) except SQLAlchemyError, err: SESSION.rollback() print 'edit_meeting:', err flask.flash('Could not update this meeting.', 'errors') return flask.render_template( 'edit_meeting.html', meeting=meeting, calendar=calendarobj, form=form, tzone=tzone)
def get_calendars(session): """ Retrieve the list of Calendar from the database. """ return Calendar.get_all(session)
def api_user_shield(username, calendar_name): """ User shield =========== Provides a small image (a shield) displaying the status of the specified user on the specified calendar if the user is currently managing a meeting. Filter arguments ---------------- ``connector`` Changes the 'connector' text used in the image. Default: 'in' ``status`` Changes the 'status' text used in the image. Default: the name of the calendar checked ``always`` Booleans to specify whether to return an image if no meeting is found for the specified user on the specified calendar. Default: True Can be: False, 0, f If the user is not managing a meeting, instead of returning the image the endpoint raises a 404. """ connector = flask.request.args.get('connector', 'in') status = flask.request.args.get('status', calendar_name) always = flask.request.args.get('always', True) if str(always).lower() in ['0', 'false', 'f']: always = False else: always = True calendarobj = Calendar.by_id(SESSION, calendar_name) if not calendarobj: flask.abort(400, 'Invalid calendar provided') start_date = datetime.datetime.utcnow().date() end_date = start_date + datetime.timedelta(days=1) meetings = fedocallib.get_by_date( SESSION, calendarobj, start_date, end_date, tzone='UTC') green, red = 'brightgreen', 'red' ## We *would* use the canonical b.repl.ca url, but it doesn't support SSL ## the way that we need currently. So, instead we'll use the backend name ## to get around that. #template = 'http://b.repl.ca/v1/%s-%s_%s-%s.png' template = 'https://buckler-bowes.rhcloud.com/v1/%s-%s_%s-%s.png' output = None for meeting in meetings: usernames = [user.username for user in meeting.meeting_manager_user] if username in usernames: output = template % (username, connector, status, green) break if output: return flask.redirect(output) elif always: output = template % (username, "not " + connector, status, red) return flask.redirect(output) else: flask.abort(404)
def add_meeting(calendar_name): """ Add a meeting to the database. This function is only available to CLA+1 member or members of the group administrating of the said calendar. :arg calendar_name, name of the calendar in which to add the meeting. """ if not flask.g.fas_user: return flask.redirect(flask.url_for('index')) calendarobj = Calendar.by_id(SESSION, calendar_name) if calendarobj.calendar_status != 'Enabled': flask.flash('This calendar is "%s", you are not allowed to add ' 'meetings anymore.' % calendarobj.calendar_status, 'errors') return flask.redirect(flask.url_for('calendar', calendar_name=calendar_name)) if calendarobj.calendar_editor_group and \ not (is_calendar_manager(calendarobj) or is_calendar_admin(calendarobj) or is_admin()): flask.flash('You are not one of the editors of this calendar, ' 'or one of its admins, you are not allowed to add ' 'new meetings.', 'errors') return flask.redirect(flask.url_for('calendar', calendar_name=calendar_name)) tzone = get_timezone() form = forms.AddMeetingForm(timezone=tzone) calendarobj = Calendar.by_id(SESSION, calendar_name) # pylint: disable=E1101 if form.validate_on_submit(): tzone = form.meeting_timezone.data or tzone try: meeting = fedocallib.add_meeting( session=SESSION, calendarobj=calendarobj, fas_user=flask.g.fas_user, meeting_name=form.meeting_name.data, meeting_date=form.meeting_date.data, meeting_date_end=form.meeting_date_end.data, meeting_time_start=form.meeting_time_start.data, meeting_time_stop=form.meeting_time_stop.data, comanager=form.comanager.data, meeting_information=form.information.data, meeting_region=form.meeting_region.data, tzone=tzone, frequency=form.frequency.data, end_repeats=form.end_repeats.data, remind_when=form.remind_when.data, remind_who=form.remind_who.data, full_day=form.full_day.data, admin=is_admin()) except FedocalException, err: flask.flash(err, 'warnings') return flask.render_template( 'add_meeting.html', calendar=calendarobj, form=form, tzone=tzone) except SQLAlchemyError, err: SESSION.rollback() print 'add_meeting:', err flask.flash('Could not add this meeting to this calendar', 'errors') return flask.render_template( 'add_meeting.html', calendar=calendarobj, form=form, tzone=tzone)