data: mark json config cell as invalid if not found in settings (#71168) #5

Merged
lguerin merged 1 commits from wip/71168-report-unkown-ConfigJsonCell into main 2022-12-12 18:08:33 +01:00
5 changed files with 82 additions and 4 deletions

View File

@ -26,6 +26,9 @@ class DataConfig(AppConfig):
from combo.data.models import CellBase
cell_classes = [c for c in self.get_models() if c in get_cell_classes()]
for cell in CellBase.get_cells(cell_filter=lambda x: x in cell_classes, page__snapshot__isnull=True):
for cell in CellBase.get_cells(
cell_filter=lambda x: x in cell_classes, page__snapshot__isnull=True, get_all_objects=True
):
if hasattr(cell, 'check_validity'):
cell.check_validity()

View File

@ -1040,6 +1040,7 @@ class CellBase(models.Model, metaclass=CellMeta):
select_related=None,
load_contenttypes=False,
cells_exclude=None,
get_all_objects=False,
**kwargs,
):
"""Returns the list of cells of various classes matching **kwargs"""
@ -1074,7 +1075,10 @@ class CellBase(models.Model, metaclass=CellMeta):
continue
if cell_filter and not cell_filter(klass):
continue
cells_queryset = klass.objects.filter(**kwargs)
manager = klass.objects
if get_all_objects and hasattr(klass, 'all_objects'):
manager = klass.all_objects
cells_queryset = manager.filter(**kwargs)
if cells_exclude:
cells_queryset = cells_queryset.exclude(cells_exclude)
if extra_filter:
@ -2360,10 +2364,15 @@ class ConfigJsonCellManager(models.Manager):
@register_cell_class
class ConfigJsonCell(JsonCellBase):
objects = ConfigJsonCellManager()
Review

Ce manager fait un queryset.filter(key__in=settings.JSON_CELL_TYPES.keys())
=> nécessité d'avoir un autre manager qui ne filtre pas sur les settings, pour le job cron, et pour la page de rapport des anomalies.

Ce manager fait un `queryset.filter(key__in=settings.JSON_CELL_TYPES.keys())` => nécessité d'avoir un autre manager qui ne filtre pas sur les settings, pour le job cron, et pour la page de rapport des anomalies.
all_objects = models.Manager()
key = models.CharField(max_length=50)
parameters = JSONField(blank=True, default=dict)
invalid_reason_codes = {
'settings_not_found': _('Cell not found in settings'),
}
def __str__(self):
return force_str(_('%s (JSON Cell)') % self.get_label())
@ -2383,6 +2392,8 @@ class ConfigJsonCell(JsonCellBase):
return l
def get_label(self):
if self.key not in settings.JSON_CELL_TYPES:
return _('Unknown ConfigJsonCell %s') % self.key
return settings.JSON_CELL_TYPES[self.key]['name']
def set_variant(self, variant):
@ -2465,6 +2476,18 @@ class ConfigJsonCell(JsonCellBase):
self.template_string = self.parameters['template_string']
return super().render(context)
def check_validity(self):
if self.key not in settings.JSON_CELL_TYPES:
self.mark_as_invalid('settings_not_found')
return
validity_info = self.get_validity_info()
if validity_info is None:
return
if validity_info.invalid_reason_code != 'settings_not_found':
# don't overwrite other invalid reasons
return
self.mark_as_valid()
@receiver(pre_save, sender=Page)
def create_redirects(sender, instance, raw, **kwargs):

View File

@ -185,7 +185,10 @@ site_import = SiteImportView.as_view()
def invalid_cell_report(request):
invalid_cells = CellBase.get_cells(
page__snapshot__isnull=True, validity_info__invalid_since__isnull=False, load_contenttypes=True
page__snapshot__isnull=True,
validity_info__invalid_since__isnull=False,
load_contenttypes=True,
get_all_objects=True,
)
# manual prefetch of cell pages (for ordering and placeholders)
all_pages_by_pk = {p.pk: p for p in Page.objects.filter(snapshot__isnull=True)}

View File

@ -1258,6 +1258,44 @@ def test_config_json_cell_validity(settings, context):
assert ValidityInfo.objects.exists() is False
def test_config_json_cell_check_validity(settings):
settings.JSON_CELL_TYPES = {
'test-config-json-cell': {
'name': 'Foobar',
},
}
page = Page.objects.create(title='example page', slug='example-page')
cell = ConfigJsonCell.objects.create(
page=page,
placeholder='content',
order=1,
key='test-config-json-cell',
)
cell.check_validity()
assert ValidityInfo.objects.exists() is False
settings.JSON_CELL_TYPES = {}
cell.check_validity()
validity_info = ValidityInfo.objects.latest('pk')
assert validity_info.invalid_reason_code == 'settings_not_found'
assert validity_info.invalid_since is not None
settings.JSON_CELL_TYPES = {
'test-config-json-cell': {
'name': 'Foobar',
},
}
validity_info.invalid_reason_code = 'foobar'
validity_info.save()
cell.check_validity()
assert ValidityInfo.objects.exists() is True
validity_info.invalid_reason_code = 'settings_not_found'
validity_info.save()
cell.check_validity()
assert ValidityInfo.objects.exists() is False
def test_json_force_async():
cell = JsonCell()
cell.url = 'http://example.net/test-force-async'
@ -1623,7 +1661,7 @@ def test_hourly():
for klass in cell_classes:
klass.objects.create(page=page, placeholder='content', order=0)
for klass in cell_classes:
if klass in [LinkCell, LinkListCell]:
if klass in [LinkCell, LinkListCell, ConfigJsonCell]:
with mock.patch('combo.data.models.%s.check_validity' % klass.__name__) as check_validity:
appconfig.hourly()
assert check_validity.call_args_list == [mock.call()]

View File

@ -1272,6 +1272,17 @@ def test_invalid_cell_report(app, admin_user):
resp = app.get('/manage/cells/invalid-report/')
assert resp.context['object_list'] == [cell]
# unknown config cell
cell2 = ConfigJsonCell.objects.create(
page=page,
placeholder='content',
order=1,
key='test-config-json-cell',
)
cell2.mark_as_invalid('settings_not_found')
resp = app.get('/manage/cells/invalid-report/')
assert resp.context['object_list'] == [cell, cell2]
def test_duplicate_page(app, admin_user):
page = Page.objects.create(