You've already forked oncall
mirror of
https://github.com/linkedin/oncall.git
synced 2025-11-27 23:18:38 +02:00
Add team subscriptions
This commit is contained in:
committed by
Joe Gillotti
parent
7bb10a04d2
commit
2aee0c316c
@@ -417,6 +417,19 @@ CREATE TABLE IF NOT EXISTS `application` (
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `team_subscription` (
|
||||
`team_id` BIGINT(20) UNSIGNED NOT NULL,
|
||||
`subscription_id` BIGINT(20) UNSIGNED NOT NULL,
|
||||
`role_id` INT UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (`team_id`, `subscription_id`, `role_id`),
|
||||
INDEX `team_subscription_team_id_idx` (`team_id` ASC),
|
||||
CONSTRAINT `team_subscription_team_id_fk` FOREIGN KEY (`team_id`) REFERENCES `team` (`id`)
|
||||
ON DELETE CASCADE,
|
||||
CONSTRAINT `team_subscription_subscription_id_fk` FOREIGN KEY (`subscription_id`) REFERENCES `team` (`id`)
|
||||
ON DELETE CASCADE,
|
||||
INDEX `team_subscription_team_id_fk_idx` (`team_id` ASC)
|
||||
);
|
||||
|
||||
INSERT INTO `scheduler` ( `name`, `description`)
|
||||
VALUES ('default',
|
||||
'Default scheduling algorithm'),
|
||||
|
||||
@@ -179,7 +179,7 @@ def event(team, role):
|
||||
for ev in self.created:
|
||||
requests.delete(api_v0('events/%d' % ev))
|
||||
for t in self.teams:
|
||||
re = requests.get(api_v0('events?team=' + t))
|
||||
re = requests.get(api_v0('events?include_subscribed=false'), params={'team': t})
|
||||
for ev in re.json():
|
||||
requests.delete(api_v0('events/%d' % ev['id']))
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ def test_invalid_events():
|
||||
|
||||
|
||||
@prefix('test_events')
|
||||
def test_events(team, user, role):
|
||||
def test_events(event, team, user, role):
|
||||
team_name = team.create()
|
||||
team_name_2 = team.create()
|
||||
user_name = user.create()
|
||||
@@ -24,6 +24,8 @@ def test_events(team, user, role):
|
||||
user.add_to_team(user_name, team_name)
|
||||
user.add_to_team(user_name_2, team_name)
|
||||
user.add_to_team(user_name_2, team_name_2)
|
||||
event.teams.add(team_name)
|
||||
event.teams.add(team_name_2)
|
||||
|
||||
start, end = int(time.time()) + 100, int(time.time() + 36000)
|
||||
|
||||
|
||||
161
e2e/test_subscription.py
Normal file
161
e2e/test_subscription.py
Normal file
@@ -0,0 +1,161 @@
|
||||
import time
|
||||
import requests
|
||||
from testutils import prefix, api_v0
|
||||
|
||||
|
||||
@prefix('test_v0_sub')
|
||||
def test_api_v0_team_subscription(team, role):
|
||||
team_name = team.create()
|
||||
team_name_2 = team.create()
|
||||
team_name_3 = team.create()
|
||||
role_name = role.create()
|
||||
|
||||
re = requests.post(api_v0('teams/%s/subscriptions' % team_name), json={'role': role_name, 'subscription': team_name_2})
|
||||
assert re.status_code == 201
|
||||
re = requests.post(api_v0('teams/%s/subscriptions' % team_name), json={'role': role_name, 'subscription': team_name_3})
|
||||
assert re.status_code == 201
|
||||
|
||||
re = requests.get(api_v0('teams/%s/subscriptions' % team_name))
|
||||
assert re.status_code == 200
|
||||
data = re.json()
|
||||
assert team_name_2 in data
|
||||
assert team_name_3 in data
|
||||
assert len(data) == 2
|
||||
|
||||
re = requests.delete(api_v0('teams/%s/subscriptions/%s/%s' % (team_name, team_name_3, role_name)))
|
||||
assert re.status_code == 200
|
||||
|
||||
re = requests.get(api_v0('teams/%s/subscriptions' % team_name))
|
||||
assert re.status_code == 200
|
||||
data = re.json()
|
||||
assert team_name_2 in data
|
||||
assert len(data) == 1
|
||||
|
||||
|
||||
@prefix('test_v0_sub_events')
|
||||
def test_api_v0_subscription_events(user, role, team, event):
|
||||
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()) + 1000
|
||||
ev1 = event.create({'start': start,
|
||||
'end': start + 1000,
|
||||
'user': user_name,
|
||||
'team': team_name,
|
||||
'role': role_name})
|
||||
ev2 = event.create({'start': start + 1000,
|
||||
'end': start + 2000,
|
||||
'user': user_name,
|
||||
'team': team_name_2,
|
||||
'role': role_name})
|
||||
re = requests.post(api_v0('teams/%s/subscriptions' % team_name), json={'role': role_name, 'subscription': team_name_2})
|
||||
assert re.status_code == 201
|
||||
re = requests.get(api_v0('events?team__eq=%s' % team_name))
|
||||
ev_ids = [ev['id'] for ev in re.json()]
|
||||
assert ev1 in ev_ids
|
||||
assert ev2 in ev_ids
|
||||
|
||||
re = requests.get(api_v0('events?team__eq=%s&include_subscribed=False' % team_name))
|
||||
ev_ids = [ev['id'] for ev in re.json()]
|
||||
assert ev1 in ev_ids
|
||||
assert len(ev_ids) == 1
|
||||
|
||||
|
||||
@prefix('test_v0_sub_oncall')
|
||||
def test_v0_subscription_oncall(user, role, team, service, event):
|
||||
team_name = team.create()
|
||||
team_name_2 = team.create()
|
||||
service_name = service.create()
|
||||
service.associate_team(service_name, team_name)
|
||||
user_name = user.create()
|
||||
user_name_2 = user.create()
|
||||
role_name = role.create()
|
||||
user.add_to_team(user_name, team_name)
|
||||
user.add_to_team(user_name_2, team_name_2)
|
||||
re = requests.post(api_v0('teams/%s/subscriptions' % team_name), json={'role': role_name, 'subscription': team_name_2})
|
||||
assert re.status_code == 201
|
||||
start = int(time.time())
|
||||
|
||||
ev1 = event.create({'start': start,
|
||||
'end': start + 1000,
|
||||
'user': user_name,
|
||||
'team': team_name,
|
||||
'role': role_name})
|
||||
ev2 = event.create({'start': start,
|
||||
'end': start + 1000,
|
||||
'user': user_name_2,
|
||||
'team': team_name_2,
|
||||
'role': role_name})
|
||||
|
||||
re = requests.get(api_v0('services/%s/oncall/%s' % (service_name, role_name)))
|
||||
assert re.status_code == 200
|
||||
results = re.json()
|
||||
users = [ev['user'] for ev in results]
|
||||
assert user_name in users
|
||||
assert user_name_2 in users
|
||||
assert len(results) == 2
|
||||
|
||||
|
||||
@prefix('test_v0_sub_summary')
|
||||
def test_v0_subscription_summary(user, role, team, event):
|
||||
team_name = team.create()
|
||||
team_name_2 = team.create()
|
||||
user_name = user.create()
|
||||
user_name_2 = user.create()
|
||||
role_name = role.create()
|
||||
role_name_2 = role.create()
|
||||
user.add_to_team(user_name, team_name)
|
||||
user.add_to_team(user_name_2, team_name_2)
|
||||
|
||||
start, end = int(time.time()), int(time.time()+36000)
|
||||
|
||||
event_data_1 = {'start': start,
|
||||
'end': end,
|
||||
'user': user_name,
|
||||
'team': team_name,
|
||||
'role': role_name}
|
||||
event_data_2 = {'start': start - 5,
|
||||
'end': end - 5,
|
||||
'user': user_name_2,
|
||||
'team': team_name_2,
|
||||
'role': role_name_2}
|
||||
event_data_3 = {'start': start + 50000,
|
||||
'end': end + 50000,
|
||||
'user': user_name,
|
||||
'team': team_name,
|
||||
'role': role_name}
|
||||
event_data_4 = {'start': start + 50005,
|
||||
'end': end + 50005,
|
||||
'user': user_name_2,
|
||||
'team': team_name_2,
|
||||
'role': role_name_2}
|
||||
event_data_5 = {'start': start + 50001,
|
||||
'end': end + 50001,
|
||||
'user': user_name,
|
||||
'team': team_name,
|
||||
'role': role_name}
|
||||
|
||||
# Create current events
|
||||
event.create(event_data_1)
|
||||
event.create(event_data_2)
|
||||
# Create next events
|
||||
event.create(event_data_3)
|
||||
event.create(event_data_4)
|
||||
# Create extra future event that isn't the next event
|
||||
event.create(event_data_5)
|
||||
|
||||
re = requests.post(api_v0('teams/%s/subscriptions' % team_name), json={'role': role_name_2, 'subscription': team_name_2})
|
||||
assert re.status_code == 201
|
||||
|
||||
re = requests.get(api_v0('teams/%s/summary' % team_name))
|
||||
assert re.status_code == 200
|
||||
results = re.json()
|
||||
keys = ['start', 'end', 'role']
|
||||
|
||||
assert all(results['current'][role_name][0][key] == event_data_1[key] for key in keys)
|
||||
assert all(results['current'][role_name_2][0][key] == event_data_2[key] for key in keys)
|
||||
assert all(results['next'][role_name][0][key] == event_data_3[key] for key in keys)
|
||||
assert all(results['next'][role_name_2][0][key] == event_data_4[key] for key in keys)
|
||||
@@ -82,6 +82,10 @@ def init(application, config):
|
||||
from . import timezones
|
||||
application.add_route('/api/v0/timezones', timezones)
|
||||
|
||||
from . import team_subscription, team_subscriptions
|
||||
application.add_route('/api/v0/teams/{team}/subscriptions', team_subscriptions)
|
||||
application.add_route('/api/v0/teams/{team}/subscriptions/{subscription}/{role}', team_subscription)
|
||||
|
||||
# Optional Iris integration
|
||||
from . import iris_settings
|
||||
application.add_route('/api/v0/iris_settings', iris_settings)
|
||||
|
||||
@@ -66,6 +66,8 @@ constraints = {
|
||||
'user__endswith': '`user`.`name` LIKE CONCAT("%%", %s)'
|
||||
}
|
||||
|
||||
TEAM_PARAMS = {'team', 'team__eq', 'team__contains', 'team__startswith', 'team_endswith', 'team_id'}
|
||||
|
||||
|
||||
def on_get(req, resp):
|
||||
"""
|
||||
@@ -144,6 +146,10 @@ def on_get(req, resp):
|
||||
"""
|
||||
fields = req.get_param_as_list('fields', transform=columns.__getitem__)
|
||||
req.params.pop('fields', None)
|
||||
include_sub = req.get_param_as_bool('include_subscribed')
|
||||
if include_sub is None:
|
||||
include_sub = True
|
||||
req.params.pop('include_subscribed', None)
|
||||
cols = ', '.join(fields) if fields else all_columns
|
||||
if any(key not in constraints for key in req.params):
|
||||
raise HTTPBadRequest('Bad constraint param')
|
||||
@@ -154,17 +160,42 @@ def on_get(req, resp):
|
||||
|
||||
where_params = []
|
||||
where_vals = []
|
||||
for key in req.params:
|
||||
connection = db.connect()
|
||||
cursor = connection.cursor(db.DictCursor)
|
||||
|
||||
# Build where clause. If including subscriptions, deal with team parameters later
|
||||
params = req.params.viewkeys() - TEAM_PARAMS if include_sub else req.params
|
||||
for key in params:
|
||||
val = req.get_param(key)
|
||||
if key in constraints:
|
||||
where_params.append(constraints[key])
|
||||
where_vals.append(val)
|
||||
|
||||
# Deal with team subscriptions and team parameters
|
||||
team_where = []
|
||||
subs_vals = []
|
||||
team_params = req.params.viewkeys() & TEAM_PARAMS
|
||||
if include_sub and team_params:
|
||||
|
||||
for key in team_params:
|
||||
val = req.get_param(key)
|
||||
team_where.append(constraints[key])
|
||||
subs_vals.append(val)
|
||||
subs_and = ' AND '.join(team_where)
|
||||
cursor.execute('''SELECT `subscription_id`, `role_id` FROM `team_subscription`
|
||||
JOIN `team` ON `team_id` = `team`.`id`
|
||||
WHERE %s''' % subs_and,
|
||||
subs_vals)
|
||||
if cursor.rowcount != 0:
|
||||
# Check conditions are true for either team OR subscriber
|
||||
subs_and = '(%s OR (%s))' % (subs_and, ' OR '.join(['`team`.`id` = %s AND `role`.`id` = %s' %
|
||||
(row['subscription_id'], row['role_id']) for row in cursor]))
|
||||
where_params.append(subs_and)
|
||||
where_vals += subs_vals
|
||||
|
||||
where_query = ' AND '.join(where_params)
|
||||
if where_query:
|
||||
query = '%s WHERE %s' % (query, where_query)
|
||||
|
||||
connection = db.connect()
|
||||
cursor = connection.cursor(db.DictCursor)
|
||||
cursor.execute(query, where_vals)
|
||||
data = cursor.fetchall()
|
||||
cursor.close()
|
||||
|
||||
@@ -40,24 +40,43 @@ def on_get(req, resp, service, role=None):
|
||||
]
|
||||
|
||||
'''
|
||||
get_oncall_query = '''SELECT `user`.`full_name` AS `full_name`, `event`.`start`, `event`.`end`,
|
||||
`contact_mode`.`name` AS `mode`, `user_contact`.`destination`, `role`.`name` AS `role`,
|
||||
`team`.`name` AS `team`, `user`.`name` AS `user`
|
||||
FROM `service` JOIN `team_service` ON `service`.`id` = `team_service`.`service_id`
|
||||
JOIN `event` ON `event`.`team_id` = `team_service`.`team_id`
|
||||
JOIN `user` ON `user`.`id` = `event`.`user_id`
|
||||
JOIN `role` ON `role`.`id` = `event`.`role_id`
|
||||
JOIN `team` ON `team`.`id` = `event`.`team_id`
|
||||
LEFT JOIN `user_contact` ON `user`.`id` = `user_contact`.`user_id`
|
||||
LEFT JOIN `contact_mode` ON `contact_mode`.`id` = `user_contact`.`mode_id`
|
||||
WHERE UNIX_TIMESTAMP() BETWEEN `event`.`start` AND `event`.`end`
|
||||
AND `service`.`name` = %s '''
|
||||
query_params = [service]
|
||||
get_oncall_query = '''
|
||||
SELECT `user`.`full_name` AS `full_name`,
|
||||
`event`.`start`, `event`.`end`,
|
||||
`contact_mode`.`name` AS `mode`,
|
||||
`user_contact`.`destination`,
|
||||
`user`.`name` AS `user`,
|
||||
`team`.`name` AS `team`,
|
||||
`role`.`name` AS `role`
|
||||
FROM `event`
|
||||
JOIN `user` ON `event`.`user_id` = `user`.`id`
|
||||
JOIN `team` ON `event`.`team_id` = `team`.`id`
|
||||
JOIN `role` ON `role`.`id` = `event`.`role_id`
|
||||
LEFT JOIN `team_subscription` ON `subscription_id` = `team`.`id`
|
||||
AND `team_subscription`.`role_id` = `role`.`id`
|
||||
LEFT JOIN `user_contact` ON `user`.`id` = `user_contact`.`user_id`
|
||||
LEFT JOIN `contact_mode` ON `contact_mode`.`id` = `user_contact`.`mode_id`
|
||||
WHERE UNIX_TIMESTAMP() BETWEEN `event`.`start` AND `event`.`end`
|
||||
AND (`team`.`id` IN %s OR `team_subscription`.`team_id` IN %s)'''
|
||||
|
||||
query_params = []
|
||||
connection = db.connect()
|
||||
cursor = connection.cursor(db.DictCursor)
|
||||
# Get subscription teams for teams owning the service, along with the teams that own the service
|
||||
cursor.execute('''SELECT `team_id` FROM `team_service`
|
||||
JOIN `service` ON `service`.`id` = `team_service`.`service_id`
|
||||
WHERE `service`.`name` = %s''',
|
||||
service)
|
||||
team_ids = [row['team_id'] for row in cursor]
|
||||
if not team_ids:
|
||||
resp.body = json_dumps([])
|
||||
cursor.close()
|
||||
connection.close()
|
||||
return
|
||||
query_params += [team_ids, team_ids]
|
||||
if role is not None:
|
||||
get_oncall_query += ' AND `role`.`name` = %s'
|
||||
query_params.append(role)
|
||||
connection = db.connect()
|
||||
cursor = connection.cursor(db.DictCursor)
|
||||
cursor.execute(get_oncall_query, query_params)
|
||||
data = cursor.fetchall()
|
||||
ret = {}
|
||||
|
||||
@@ -64,15 +64,18 @@ def on_get(req, resp, team, role=None):
|
||||
JOIN `user` ON `event`.`user_id` = `user`.`id`
|
||||
JOIN `team` ON `event`.`team_id` = `team`.`id`
|
||||
JOIN `role` ON `role`.`id` = `event`.`role_id`
|
||||
LEFT JOIN `team_subscription` ON `subscription_id` = `team`.`id`
|
||||
AND `team_subscription`.`role_id` = `role`.`id`
|
||||
LEFT JOIN `team` `subscriber` ON `subscriber`.`id` = `team_subscription`.`team_id`
|
||||
LEFT JOIN `user_contact` ON `user`.`id` = `user_contact`.`user_id`
|
||||
LEFT JOIN `contact_mode` ON `contact_mode`.`id` = `user_contact`.`mode_id`
|
||||
WHERE UNIX_TIMESTAMP() BETWEEN `event`.`start` AND `event`.`end`
|
||||
AND `team`.`name` = %s'''
|
||||
|
||||
query_params = [team]
|
||||
AND (`team`.`name` = %s OR `subscriber`.`name` = %s)'''
|
||||
query_params = [team, team]
|
||||
if role is not None:
|
||||
get_oncall_query += 'AND `role`.`name` = %s'
|
||||
get_oncall_query += ' AND `role`.`name` = %s'
|
||||
query_params.append(role)
|
||||
|
||||
connection = db.connect()
|
||||
cursor = connection.cursor(db.DictCursor)
|
||||
cursor.execute(get_oncall_query, query_params)
|
||||
|
||||
22
src/oncall/api/v0/team_subscription.py
Normal file
22
src/oncall/api/v0/team_subscription.py
Normal file
@@ -0,0 +1,22 @@
|
||||
from ... import db
|
||||
from ...auth import login_required, check_team_auth
|
||||
from falcon import HTTPNotFound
|
||||
|
||||
|
||||
@login_required
|
||||
def on_delete(req, resp, team, subscription, role):
|
||||
check_team_auth(team, req)
|
||||
connection = db.connect()
|
||||
cursor = connection.cursor()
|
||||
|
||||
cursor.execute('''DELETE FROM `team_subscription`
|
||||
WHERE team_id = (SELECT `id` FROM `team` WHERE `name` = %s)
|
||||
AND `subscription_id` = (SELECT `id` FROM `team` WHERE `name` = %s)\
|
||||
AND `role_id` = (SELECT `id` FROM `role` WHERE `name` = %s)''',
|
||||
(team, subscription, role))
|
||||
deleted = cursor.rowcount
|
||||
connection.commit()
|
||||
cursor.close()
|
||||
connection.close()
|
||||
if deleted == 0:
|
||||
raise HTTPNotFound()
|
||||
58
src/oncall/api/v0/team_subscriptions.py
Normal file
58
src/oncall/api/v0/team_subscriptions.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from ... import db
|
||||
from ujson import dumps as json_dumps
|
||||
from falcon import HTTPError, HTTPBadRequest, HTTP_201
|
||||
from ...utils import load_json_body
|
||||
from ...auth import login_required, check_team_auth
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger('oncall-api')
|
||||
|
||||
|
||||
def on_get(req, resp, team):
|
||||
connection = db.connect()
|
||||
cursor = connection.cursor()
|
||||
cursor.execute('''SELECT `subscription`.`name`, `role`.`name` FROM `team`
|
||||
JOIN `team_subscription` ON `team`.`id` = `team_subscription`.`team_id`
|
||||
JOIN `team` `subscription` ON `subscription`.`id` = `team_subscription`.`subscription_id`
|
||||
JOIN `role` ON `role`.`id` = `team_subscription`.`role_id`
|
||||
WHERE `team`.`name` = %s''',
|
||||
team)
|
||||
data = [row[0] for row in cursor]
|
||||
cursor.close()
|
||||
connection.close()
|
||||
resp.body = json_dumps(data)
|
||||
|
||||
|
||||
@login_required
|
||||
def on_post(req, resp, team):
|
||||
data = load_json_body(req)
|
||||
check_team_auth(team, req)
|
||||
sub_name = data.get('subscription')
|
||||
role_name = data.get('role')
|
||||
if not sub_name or not role_name:
|
||||
raise HTTPBadRequest('Invalid subscription', 'Missing subscription name or role name')
|
||||
connection = db.connect()
|
||||
cursor = connection.cursor()
|
||||
try:
|
||||
cursor.execute('''INSERT INTO `team_subscription` (`team_id`, `subscription_id`, `role_id`) VALUES
|
||||
((SELECT `id` FROM `team` WHERE `name` = %s),
|
||||
(SELECT `id` FROM `team` WHERE `name` = %s),
|
||||
(SELECT `id` FROM `role` WHERE `name` = %s))''',
|
||||
(team, sub_name, role_name))
|
||||
except db.IntegrityError as e:
|
||||
err_msg = str(e.args[1])
|
||||
if err_msg == 'Column \'team_id\' cannot be null':
|
||||
err_msg = 'team "%s" not found' % team
|
||||
elif err_msg == 'Column \'role_id\' cannot be null':
|
||||
err_msg = 'role "%s" not found' % role_name
|
||||
elif err_msg == 'Column \'subscription_id\' cannot be null':
|
||||
err_msg = 'team "%s" not found' % sub_name
|
||||
logger.exception('Unknown integrity error in team_subscriptions')
|
||||
raise HTTPError('422 Unprocessable Entity', 'IntegrityError', err_msg)
|
||||
else:
|
||||
connection.commit()
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
resp.status = HTTP_201
|
||||
@@ -114,17 +114,32 @@ def on_get(req, resp, team):
|
||||
if cursor.rowcount < 1:
|
||||
raise HTTPNotFound()
|
||||
team_id = cursor.fetchone()['id']
|
||||
|
||||
current_query = '''
|
||||
SELECT `role`.`name` AS `role`, `user`.`full_name` AS `full_name`,
|
||||
`event`.`start`, `event`.`end`, `user`.`photo_url`, `event`.`user_id`
|
||||
SELECT `user`.`full_name` AS `full_name`,
|
||||
`user`.`photo_url`,
|
||||
`event`.`start`, `event`.`end`,
|
||||
`event`.`user_id`,
|
||||
`user`.`name` AS `user`,
|
||||
`team`.`name` AS `team`,
|
||||
`role`.`name` AS `role`
|
||||
FROM `event`
|
||||
JOIN `role` ON `event`.`role_id` = `role`.`id`
|
||||
JOIN `user` ON `event`.`user_id` = `user`.`id`
|
||||
WHERE `event`.`team_id` = %s
|
||||
AND UNIX_TIMESTAMP() >= `event`.`start`
|
||||
AND UNIX_TIMESTAMP() < `event`.`end`'''
|
||||
cursor.execute(current_query, team_id)
|
||||
JOIN `user` ON `event`.`user_id` = `user`.`id`
|
||||
JOIN `team` ON `event`.`team_id` = `team`.`id`
|
||||
JOIN `role` ON `role`.`id` = `event`.`role_id`
|
||||
WHERE UNIX_TIMESTAMP() BETWEEN `event`.`start` AND `event`.`end`'''
|
||||
team_where = '`team`.`id` = %s'
|
||||
cursor.execute('''SELECT `subscription_id`, `role_id` FROM `team_subscription`
|
||||
JOIN `team` ON `team_id` = `team`.`id`
|
||||
WHERE %s''' % team_where,
|
||||
team_id)
|
||||
|
||||
if cursor.rowcount != 0:
|
||||
# Check conditions are true for either team OR subscriber
|
||||
team_where = '(%s OR (%s))' % (team_where, ' OR '.join(['`event`.`team_id` = %s AND `event`.`role_id` = %s' %
|
||||
(row['subscription_id'], row['role_id']) for row in cursor]))
|
||||
|
||||
|
||||
cursor.execute(' AND '.join((current_query, team_where)), team_id)
|
||||
payload = {}
|
||||
users = set([])
|
||||
payload['current'] = defaultdict(list)
|
||||
@@ -133,18 +148,25 @@ def on_get(req, resp, team):
|
||||
users.add(event['user_id'])
|
||||
|
||||
next_query = '''
|
||||
SELECT `role`.`name` AS `role`, `user`.`full_name` AS `full_name`,
|
||||
`event`.`start`, `event`.`end`, `user`.`photo_url`, `event`.`user_id`
|
||||
SELECT `role`.`name` AS `role`,
|
||||
`user`.`full_name` AS `full_name`,
|
||||
`event`.`start`,
|
||||
`event`.`end`,
|
||||
`user`.`photo_url`,
|
||||
`event`.`user_id`,
|
||||
`event`.`role_id`,
|
||||
`event`.`team_id`
|
||||
FROM `event`
|
||||
JOIN `role` ON `event`.`role_id` = `role`.`id`
|
||||
JOIN `user` ON `event`.`user_id` = `user`.`id`
|
||||
JOIN (SELECT `role_id`, `team_id`, MIN(`start` - UNIX_TIMESTAMP()) AS dist
|
||||
FROM `event`
|
||||
WHERE `start` > UNIX_TIMESTAMP() AND `event`.`team_id` = %s
|
||||
GROUP BY role_id) AS t1
|
||||
ON `event`.`role_id` = `t1`.`role_id`
|
||||
AND `event`.`start` - UNIX_TIMESTAMP() = `t1`.dist
|
||||
AND `event`.`team_id` = `t1`.`team_id`'''
|
||||
JOIN `role` ON `event`.`role_id` = `role`.`id`
|
||||
JOIN `user` ON `event`.`user_id` = `user`.`id`
|
||||
|
||||
JOIN (SELECT `event`.`role_id`, `event`.`team_id`, MIN(`event`.`start` - UNIX_TIMESTAMP()) AS dist
|
||||
FROM `event` JOIN `team` ON `team`.`id` = `event`.`team_id`
|
||||
WHERE `start` > UNIX_TIMESTAMP() AND %s
|
||||
GROUP BY `event`.`role_id`, `event`.`team_id`) AS t1
|
||||
ON `event`.`role_id` = `t1`.`role_id`
|
||||
AND `event`.`start` - UNIX_TIMESTAMP() = `t1`.dist
|
||||
AND `event`.`team_id` = `t1`.`team_id`''' % team_where
|
||||
cursor.execute(next_query, team_id)
|
||||
payload['next'] = defaultdict(list)
|
||||
for event in cursor:
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
from ... import db
|
||||
from .events import all_columns
|
||||
from ujson import dumps as json_dumps
|
||||
from collections import defaultdict
|
||||
import operator
|
||||
|
||||
|
||||
def on_get(req, resp, user_name):
|
||||
@@ -47,29 +49,39 @@ def on_get(req, resp, user_name):
|
||||
|
||||
|
||||
'''
|
||||
connection = db.connect()
|
||||
cursor = connection.cursor(db.DictCursor)
|
||||
role = req.get_param('role', None)
|
||||
limit = req.get_param_as_int('limit', None)
|
||||
limit = req.get_param_as_int('limit')
|
||||
query_end = ' ORDER BY `event`.`start` ASC'
|
||||
query = '''SELECT %s, (SELECT COUNT(*) FROM `event` `counter`
|
||||
WHERE `counter`.`link_id` = `event`.`link_id`) AS num_events
|
||||
query = '''SELECT %s
|
||||
FROM `event`
|
||||
JOIN `user` ON `user`.`id` = `event`.`user_id`
|
||||
JOIN `team` ON `team`.`id` = `event`.`team_id`
|
||||
JOIN `role` ON `role`.`id` = `event`.`role_id`
|
||||
LEFT JOIN `event` `e2` ON `event`.link_id = `e2`.`link_id` AND `e2`.`start` < `event`.`start`
|
||||
WHERE `user`.`id` = (SELECT `id` FROM `user` WHERE `name` = %%s)
|
||||
AND `event`.`start` > UNIX_TIMESTAMP()
|
||||
AND `e2`.`start` IS NULL''' % all_columns
|
||||
AND `event`.`start` > UNIX_TIMESTAMP()''' % all_columns
|
||||
|
||||
query_params = [user_name]
|
||||
if role:
|
||||
query_end = ' AND `role`.`name` = %s' + query_end
|
||||
query_params.append(role)
|
||||
if limit:
|
||||
query_end += ' LIMIT %s'
|
||||
query_params.append(limit)
|
||||
connection = db.connect()
|
||||
cursor = connection.cursor(db.DictCursor)
|
||||
cursor.execute(query + query_end, query_params)
|
||||
data = cursor.fetchall()
|
||||
resp.body = json_dumps(data)
|
||||
cursor.close()
|
||||
connection.close()
|
||||
links = defaultdict(list)
|
||||
formatted = []
|
||||
for event in data:
|
||||
if event['link_id'] is None:
|
||||
formatted.append(event)
|
||||
else:
|
||||
links[event['link_id']].append(event)
|
||||
for events in links.itervalues():
|
||||
first_event = min(events, key=operator.itemgetter('start'))
|
||||
first_event['num_events'] = len(events)
|
||||
formatted.append(first_event)
|
||||
formatted = sorted(formatted, key=operator.itemgetter('start'))
|
||||
if limit is not None:
|
||||
formatted = formatted[:limit]
|
||||
resp.body = json_dumps(formatted)
|
||||
Reference in New Issue
Block a user