Skip to content

Commit

Permalink
Add new query param "excludedTeams" to iCal API endpoint (#406)
Browse files Browse the repository at this point in the history
* Add new query param "excludedTeams" to iCal API endpoint

* stylecheck

* assert number of events
  • Loading branch information
nickeidler authored Oct 2, 2023
1 parent cde5a22 commit 636e887
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 4 deletions.
38 changes: 38 additions & 0 deletions e2e/test_ical.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,44 @@ def test_user_ical(event, team, user, role):
assert start == calendar.timegm(component.get('dtstart').dt.timetuple())
assert end == calendar.timegm(component.get('dtend').dt.timetuple())

@prefix('test_user_ical_exclude_team')
def test_user_ical_exclude_team(event, team, user, role):
team_name = team.create()
team_name_2 = team.create()
user_name = user.create()
role_name = role.create()
user.add_to_team(user_name, team_name)
user.add_to_team(user_name, team_name_2)

start = int(time.time()) + 100
end = start + 1000

ev1 = event.create({'start': start,
'end': end,
'user': user_name,
'team': team_name,
'role': role_name})
ev2 = event.create({'start': start + 100,
'end': end + 100,
'user': user_name,
'team': team_name_2,
'role': role_name})

re = requests.get(api_v0('users/%s/ical?excludedTeams=%s' % (user_name, team_name_2)))
cal = re.content
# Parse icalendar, make sure event info is correct (excluded team's event should not be present)
ical = icalendar.Calendar.from_ical(re.content)
num_events = 0
for component in ical.walk():
if component.name == 'VEVENT':
num_events += 1
assert user_name in component.get('description')
assert team_name_2 not in component.get('summary')
assert start == calendar.timegm(component.get('dtstart').dt.timetuple())
assert end == calendar.timegm(component.get('dtend').dt.timetuple())
# Make sure that there is only 1 event parsed (excluded team event not included)
assert num_events == 1


@prefix('test_team_ical')
def test_team_ical(event, team, user, role):
Expand Down
3 changes: 2 additions & 1 deletion src/oncall/api/v0/public_ical.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def on_get(req, resp, key):
"""
roles = req.get_param_as_list('roles')
excluded_teams = req.get_param_as_list('excludedTeams')

name_and_type = get_name_and_type_from_key(key)
if name_and_type is None:
Expand All @@ -26,7 +27,7 @@ def on_get(req, resp, key):
start = int(time.time())
events = []
if type == 'user':
events = get_user_events(name, start, roles=roles)
events = get_user_events(name, start, roles=roles, excluded_teams=excluded_teams)
elif type == 'team':
events = get_team_events(name, start, roles=roles, include_subscribed=True)

Expand Down
11 changes: 11 additions & 0 deletions src/oncall/api/v0/teams.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@
}


def get_team_ids(cursor, team_names):
if not team_names:
return []

team_query = 'SELECT DISTINCT `id` FROM `team` WHERE `name` IN ({0})'.format(
','.join(['%s'] * len(team_names)))
# we need prepared statements here because team_names come from user input
cursor.execute(team_query, team_names)
return [row['id'] for row in cursor]


def on_get(req, resp):
'''
Search for team names. Allows filtering based on a number of parameters, detailed below.
Expand Down
15 changes: 12 additions & 3 deletions src/oncall/api/v0/user_ical.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
import time
from . import ical
from .roles import get_role_ids
from .teams import get_team_ids
from ... import db


def get_user_events(user_name, start, roles=None):
def get_user_events(user_name, start, roles=None, excluded_teams=None):
connection = db.connect()
cursor = connection.cursor(db.DictCursor)

Expand All @@ -17,6 +18,13 @@ def get_user_events(user_name, start, roles=None):
role_condition = ' AND `event`.`role_id` IN ({0})'.format(
','.join(map(str, role_ids)))

excluded_teams_condition = ''
excluded_team_ids = get_team_ids(cursor, excluded_teams)
if excluded_team_ids:
excluded_teams_condition = ' AND `event`.`team_id` NOT IN ({0})'.format(
','.join(map(str, excluded_team_ids))
)

query = '''
SELECT
`event`.`id`,
Expand All @@ -32,7 +40,7 @@ def get_user_events(user_name, start, roles=None):
WHERE
`event`.`end` > %s AND
`user`.`name` = %s
''' + role_condition
''' + role_condition + excluded_teams_condition

cursor.execute(query, (start, user_name))

Expand Down Expand Up @@ -66,7 +74,8 @@ def on_get(req, resp, user_name):
if contact is None:
contact = True
roles = req.get_param_as_list('roles')
excluded_teams = req.get_param_as_list('excludedTeams')

events = get_user_events(user_name, start, roles=roles)
events = get_user_events(user_name, start, roles=roles, excluded_teams=excluded_teams)
resp.body = ical.events_to_ical(events, user_name, contact)
resp.set_header('Content-Type', 'text/calendar')

0 comments on commit 636e887

Please sign in to comment.