agendas: fix import when unknown field found (#42523)

This commit is contained in:
Lauréline Guérin 2020-05-07 11:25:44 +02:00
parent cc6da3d0a8
commit 19af0088ff
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
2 changed files with 66 additions and 0 deletions

View File

@ -15,6 +15,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import copy
import datetime
import math
import requests
@ -24,6 +25,7 @@ import uuid
import django
from django.conf import settings
from django.contrib.auth.models import Group
from django.core.exceptions import FieldDoesNotExist
from django.core.exceptions import ValidationError
from django.db import models, transaction
from django.db.models import Count, Q, Case, When
@ -63,6 +65,17 @@ def generate_slug(instance, **query_filters):
return slug
def clean_import_data(cls, data):
cleaned_data = copy.deepcopy(data)
for param in data:
try:
cls._meta.get_field(param)
except FieldDoesNotExist:
# remove unknown fields
cleaned_data.pop(param)
return cleaned_data
class ICSError(Exception):
pass
@ -243,6 +256,7 @@ class Agenda(models.Model):
data[permission + '_role'] = Group.objects.get(name=permissions[permission])
except Group.DoesNotExist:
raise AgendaImportError(_('Missing "%s" role') % permissions[permission])
data = clean_import_data(cls, data)
agenda, created = cls.objects.get_or_create(slug=data['slug'], defaults=data)
if not created:
for k, v in data.items():
@ -387,6 +401,7 @@ class TimePeriod(models.Model):
@classmethod
def import_json(cls, data):
data = clean_import_data(cls, data)
return cls(**data)
def export_json(self):
@ -490,6 +505,7 @@ class MeetingType(models.Model):
@classmethod
def import_json(cls, data):
data = clean_import_data(cls, data)
meeting_type, created = cls.objects.get_or_create(
slug=data['slug'], agenda=data['agenda'], defaults=data
)
@ -624,6 +640,7 @@ class Event(models.Model):
data['start_datetime'] = make_aware(
datetime.datetime.strptime(data['start_datetime'], '%Y-%m-%d %H:%M:%S')
)
data = clean_import_data(cls, data)
if data.get('slug'):
event, created = cls.objects.get_or_create(slug=data['slug'], defaults=data)
if not created:
@ -754,6 +771,7 @@ class Desk(models.Model):
def import_json(cls, data):
timeperiods = data.pop('timeperiods', [])
exceptions = data.pop('exceptions', [])
data = clean_import_data(cls, data)
instance, created = cls.objects.get_or_create(slug=data['slug'], agenda=data['agenda'], defaults=data)
if not created:
for k, v in data.items():
@ -1005,6 +1023,7 @@ class TimePeriodException(models.Model):
for k, v in data.items():
if k.endswith('_datetime'):
data[k] = import_datetime(v)
data = clean_import_data(cls, data)
return cls(**data)
def export_json(self):

View File

@ -287,3 +287,50 @@ def test_import_export_desk_missing_fields(app, meetings_agenda):
import_site(payload)
assert TimePeriod.objects.exists() is False
assert TimePeriodException.objects.exists() is False
def test_import_export_desk_unknown_fields(app, some_data, meetings_agenda):
# add exception to meeting agenda
desk = meetings_agenda.desk_set.first()
tpx_start = make_aware(datetime.datetime(2017, 5, 22, 8, 0))
tpx_end = make_aware(datetime.datetime(2017, 5, 22, 12, 30))
TimePeriodException.objects.create(desk=desk, start_datetime=tpx_start, end_datetime=tpx_end)
# add permissions
group1 = Group.objects.create(name=u'group1')
group2 = Group.objects.create(name=u'group2')
meetings_agenda.view_role = group1
meetings_agenda.edit_role = group2
meetings_agenda.save()
# add event
Event.objects.create(
agenda=meetings_agenda, start_datetime=make_aware(datetime.datetime.now()), places=10
)
output = get_output_of_command('export_site')
payload = json.loads(output)
Agenda.objects.all().delete()
assert Agenda.objects.exists() is False
assert MeetingType.objects.exists() is False
assert Desk.objects.exists() is False
assert TimePeriod.objects.exists() is False
assert TimePeriodException.objects.exists() is False
# add unknown fields everywhere
for agenda in payload['agendas']:
agenda['unknown_field'] = 'foobar'
if 'meetingtypes' in agenda:
agenda['meetingtypes'][0]['unknown_field'] = 'foobar'
if 'desks' in agenda:
agenda['desks'][0]['unknown_field'] = 'foobar'
agenda['desks'][0]['timeperiods'][0]['unknown_field'] = 'foobar'
agenda['desks'][0]['exceptions'][0]['unknown_field'] = 'foobar'
if 'events' in agenda:
agenda['events'][0]['unknown_field'] = 'foobar'
import_site(payload)
assert Agenda.objects.exists() is True
assert MeetingType.objects.exists() is True
assert Desk.objects.exists() is True
assert TimePeriod.objects.exists() is True
assert TimePeriodException.objects.exists() is True