Add schedule shift type validation on create/preview (#2789)
Fixes https://github.com/grafana/oncall-private/issues/2089
This commit is contained in:
parent
ae60f65a55
commit
0335ba2e08
3 changed files with 85 additions and 2 deletions
|
|
@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Fix Slack acknowledgment reminders by @vadimkerr ([#2769](https://github.com/grafana/oncall/pull/2769))
|
||||
- Fix issue with updating "Require resolution note" setting by @Ferril ([#2782](https://github.com/grafana/oncall/pull/2782))
|
||||
- Don't send notifications about past SSRs when turning on info notifications by @vadimkerr ([#2783](https://github.com/grafana/oncall/pull/2783))
|
||||
- Add schedule shift type validation on create/preview ([#2789](https://github.com/grafana/oncall/pull/2789))
|
||||
|
||||
### Added
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from django.utils import timezone
|
||||
from rest_framework import serializers
|
||||
|
||||
from apps.schedules.models import CustomOnCallShift, OnCallSchedule
|
||||
from apps.schedules.models import CustomOnCallShift, OnCallSchedule, OnCallScheduleWeb
|
||||
from apps.user_management.models import User
|
||||
from common.api_helpers.custom_fields import (
|
||||
OrganizationFilteredPrimaryKeyRelatedField,
|
||||
|
|
@ -87,6 +87,11 @@ class OnCallShiftSerializer(EagerLoadingMixin, serializers.ModelSerializer):
|
|||
raise serializers.ValidationError(["Invalid day value."])
|
||||
return by_day
|
||||
|
||||
def _validate_type(self, schedule, event_type):
|
||||
if schedule and not isinstance(schedule, OnCallScheduleWeb) and event_type != CustomOnCallShift.TYPE_OVERRIDE:
|
||||
# if this is not related to a web schedule, only allow override web events
|
||||
raise serializers.ValidationError({"type": ["Invalid event type"]})
|
||||
|
||||
def validate_week_start(self, week_start):
|
||||
if week_start is None:
|
||||
week_start = CustomOnCallShift.MONDAY
|
||||
|
|
@ -158,6 +163,7 @@ class OnCallShiftSerializer(EagerLoadingMixin, serializers.ModelSerializer):
|
|||
"priority_level",
|
||||
"rotation_start",
|
||||
]
|
||||
self._validate_type(validated_data.get("schedule"), event_type)
|
||||
if event_type == CustomOnCallShift.TYPE_OVERRIDE:
|
||||
for field in fields_to_update_for_overrides:
|
||||
value = None
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from rest_framework.response import Response
|
|||
from rest_framework.test import APIClient
|
||||
|
||||
from apps.api.permissions import LegacyAccessControlRole
|
||||
from apps.schedules.models import CustomOnCallShift, OnCallSchedule, OnCallScheduleWeb
|
||||
from apps.schedules.models import CustomOnCallShift, OnCallSchedule, OnCallScheduleCalendar, OnCallScheduleWeb
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
|
|
@ -59,6 +59,46 @@ def test_create_on_call_shift_rotation(on_call_shift_internal_api_setup, make_us
|
|||
assert mock_refresh_schedule.called
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_create_on_call_shift_rotation_invalid_type(
|
||||
make_organization_and_user_with_plugin_token,
|
||||
make_schedule,
|
||||
make_user_auth_headers,
|
||||
):
|
||||
organization, user, token = make_organization_and_user_with_plugin_token()
|
||||
schedule = make_schedule(organization, schedule_class=OnCallScheduleCalendar)
|
||||
|
||||
client = APIClient()
|
||||
url = reverse("api-internal:oncall_shifts-list")
|
||||
start_date = timezone.now().replace(microsecond=0, tzinfo=None)
|
||||
|
||||
data = {
|
||||
"name": "Test Shift",
|
||||
"type": CustomOnCallShift.TYPE_ROLLING_USERS_EVENT,
|
||||
"schedule": schedule.public_primary_key,
|
||||
"priority_level": 1,
|
||||
"shift_start": start_date.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||
"shift_end": (start_date + timezone.timedelta(hours=2)).strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||
"rotation_start": start_date.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||
"until": None,
|
||||
"frequency": 1,
|
||||
"interval": 1,
|
||||
"by_day": [
|
||||
CustomOnCallShift.ICAL_WEEKDAY_MAP[CustomOnCallShift.MONDAY],
|
||||
CustomOnCallShift.ICAL_WEEKDAY_MAP[CustomOnCallShift.FRIDAY],
|
||||
],
|
||||
"week_start": CustomOnCallShift.ICAL_WEEKDAY_MAP[CustomOnCallShift.MONDAY],
|
||||
"rolling_users": [[user.public_primary_key]],
|
||||
}
|
||||
|
||||
with patch("apps.schedules.models.CustomOnCallShift.refresh_schedule") as mock_refresh_schedule:
|
||||
response = client.post(url, data, format="json", **make_user_auth_headers(user, token))
|
||||
|
||||
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
||||
assert response.data["type"][0] == "Invalid event type"
|
||||
assert not mock_refresh_schedule.called
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_create_on_call_shift_rotation_missing_users(on_call_shift_internal_api_setup, make_user_auth_headers):
|
||||
token, user1, user2, _, schedule = on_call_shift_internal_api_setup
|
||||
|
|
@ -1557,6 +1597,42 @@ def test_on_call_shift_preview(
|
|||
assert returned_events == expected_events
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_on_call_shift_preview_invalid_type(
|
||||
make_organization_and_user_with_plugin_token,
|
||||
make_user_auth_headers,
|
||||
make_schedule,
|
||||
):
|
||||
organization, user, token = make_organization_and_user_with_plugin_token()
|
||||
client = APIClient()
|
||||
|
||||
schedule = make_schedule(organization, schedule_class=OnCallScheduleCalendar)
|
||||
|
||||
now = timezone.now().replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
start_date = now - timezone.timedelta(days=7)
|
||||
request_date = start_date
|
||||
|
||||
url = "{}?date={}&days={}".format(
|
||||
reverse("api-internal:oncall_shifts-preview"), request_date.strftime("%Y-%m-%d"), 1
|
||||
)
|
||||
shift_start = (start_date + timezone.timedelta(hours=12)).strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
shift_end = (start_date + timezone.timedelta(hours=13)).strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
shift_data = {
|
||||
"schedule": schedule.public_primary_key,
|
||||
"type": CustomOnCallShift.TYPE_ROLLING_USERS_EVENT,
|
||||
"rotation_start": shift_start,
|
||||
"shift_start": shift_start,
|
||||
"shift_end": shift_end,
|
||||
"rolling_users": [[user.public_primary_key]],
|
||||
"priority_level": 2,
|
||||
"frequency": CustomOnCallShift.FREQUENCY_DAILY,
|
||||
"interval": 1,
|
||||
}
|
||||
response = client.post(url, shift_data, format="json", **make_user_auth_headers(user, token))
|
||||
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
||||
assert response.data["type"][0] == "Invalid event type"
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_on_call_shift_preview_without_users(
|
||||
make_organization_and_user_with_plugin_token,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue