Commit 7cc17dfe authored by Florent Chehab's avatar Florent Chehab
Browse files

Big Update : moderation and viewset permissions centralized

parent e9e8ecbe
...@@ -5,7 +5,7 @@ install_backend: ...@@ -5,7 +5,7 @@ install_backend:
pip install -r requirements.txt --quiet pip install -r requirements.txt --quiet
generate_backend: generate_backend:
python ./backend/generate/generate_all.py export PYTHONPATH=$$PWD ; python ./backend/generate/generate_all.py
generate_frontend: generate_frontend:
python ./frontend/generate/generate_frontend_files.py python ./frontend/generate/generate_frontend_files.py
......
##### #####
# This python file is used to generate js files for redux # This python file is used to generate js files for redux
from django import template from django import template
import yaml
from os.path import join, realpath, dirname from os.path import join, realpath, dirname
from general.api import get_api_config
############ ############
# Need to do this first so that Django template engine is working # Need to do this first so that Django template engine is working
...@@ -44,7 +44,7 @@ saving_dir = realpath(current_dir + "/../") ...@@ -44,7 +44,7 @@ saving_dir = realpath(current_dir + "/../")
# API_BASE = "http://127.0.0.1:8000/api/" # API_BASE = "http://127.0.0.1:8000/api/"
api_config = yaml.load(read_file(join(current_dir, 'api_config.yml'))) api_config = get_api_config()
# Render urls.py # Render urls.py
template_path = join(templates_dir, 'urls.tpl') template_path = join(templates_dir, 'urls.tpl')
......
...@@ -9,11 +9,18 @@ from django.conf.urls import url, include ...@@ -9,11 +9,18 @@ from django.conf.urls import url, include
from django.conf import settings from django.conf import settings
from rest_framework import routers from rest_framework import routers
{% spaceless %} ALL_MODELS = []
{% for model in data %}{% if 'requires_testing' not in model or not model.requires_testing %} ALL_VIEWSETS = []
{% for model in data %}
{% if not model.requires_testing %}
from backend.models.{{model.import_location}} import {{model.viewset}} from backend.models.{{model.import_location}} import {{model.viewset}}
{% endif %}{% endfor %} ALL_VIEWSETS.append({{model.viewset}})
{% endspaceless %} {% if model.model is not None and not model.ignore_in_admin%}
from backend.models.{{model.import_location}} import {{model.model}}
ALL_MODELS.append({{model.model}})
{% endif %}
{% endif %}
{% endfor %}
from rest_framework.documentation import include_docs_urls from rest_framework.documentation import include_docs_urls
...@@ -24,19 +31,35 @@ urlpatterns = [ ...@@ -24,19 +31,35 @@ urlpatterns = [
router = routers.DefaultRouter() router = routers.DefaultRouter()
if settings.TESTING: if settings.TESTING:
{% for model in data %}{% if 'requires_testing' in model or model.requires_testing %} {% for model in data %}{% if model.requires_testing %}
from backend.models.{{model.import_location}} import {{model.viewset}} from backend.models.{{model.import_location}} import {{model.viewset}}
ALL_VIEWSETS.append({{model.viewset}})
{% if model.model is not None %}
from backend.models.{{model.import_location}} import {{model.model}}
ALL_MODELS.append({{model.model}})
{% endif %}
router.register( router.register(
r'{{model.api_end_point}}{% if 'api_attr' in model %}/{{model.api_attr}}{% endif %}', r'{{model.api_end_point}}{% if 'api_attr' in model %}/{{model.api_attr}}{% endif %}',
{{model.viewset}}{%if 'api_name' in model%},"{{model.api_name}}"{% endif %} {{model.viewset}}{%if 'api_name' in model%},"{{model.api_name}}"{% endif %}
){% endif %}{% endfor %} ){% endif %}{% endfor %}
{% for model in data %}{% if 'requires_testing' not in model or not model.requires_testing %} {% for model in data %}{% if not model.requires_testing %}
router.register( router.register(
r'{{model.api_end_point}}{% if 'api_attr' in model %}/{{model.api_attr}}{% endif %}', r'{{model.api_end_point}}{% if 'api_attr' in model %}/{{model.api_attr}}{% endif %}',
{{model.viewset}}{%if 'api_name' in model%},"{{model.api_name}}"{% endif %} {{model.viewset}}{%if 'api_name' in model%},"{{model.api_name}}"{% endif %}
){% endif %}{% endfor %} ){% endif %}{% endfor %}
urlpatterns += [url(r'^api/', include(router.urls))] urlpatterns += [url(r'^api/', include(router.urls))]
for model in ALL_MODELS:
if model.moderation_level is None:
raise Exception("You forgot to set the moderation_level variable in the model {}".format(str(model)))
from backend.permissions import DEFAULT_VIEWSET_PERMISSIONS
for viewset in ALL_VIEWSETS:
for p in DEFAULT_VIEWSET_PERMISSIONS:
v_p = viewset.permission_classes
if p not in v_p:
raise Exception("Permission_classes are not defined correctly in the viewset {}".format(str(viewset)))
{% endautoescape %} {% endautoescape %}
...@@ -2,9 +2,12 @@ from django.db import models ...@@ -2,9 +2,12 @@ from django.db import models
from rest_framework import serializers from rest_framework import serializers
from backend.models.location import Country from backend.models.location import Country
from backend.models.my_model import MyModel, MyModelSerializer, MyModelVersionnedViewSet from backend.models.my_model import MyModel, MyModelSerializer, MyModelVersionnedViewSet
from backend.utils import get_moderation_level, get_viewset_permissions
class City(MyModel): class City(MyModel):
moderation_level = get_moderation_level("City")
name = models.CharField(max_length=200) name = models.CharField(max_length=200)
local_name = models.CharField(max_length=200, null=True, blank=True) local_name = models.CharField(max_length=200, null=True, blank=True)
# We add an area to distinguish similarly named cities # We add an area to distinguish similarly named cities
...@@ -29,5 +32,6 @@ class CitySerializer(MyModelSerializer): ...@@ -29,5 +32,6 @@ class CitySerializer(MyModelSerializer):
class CityViewSet(MyModelVersionnedViewSet): class CityViewSet(MyModelVersionnedViewSet):
permission_classes = get_viewset_permissions("CityViewSet")
queryset = City.objects.all() # pylint: disable=E1101 queryset = City.objects.all() # pylint: disable=E1101
serializer_class = CitySerializer serializer_class = CitySerializer
from django.db import models from django.db import models
from backend.models.tag import TaggedItem, TaggedItemSerializer, TaggedItemViewSet from backend.models.tag import TaggedItem, TaggedItemSerializer, TaggedItemViewSet
from backend.models.location import City from backend.models.location import City
from backend.utils import get_moderation_level, get_viewset_permissions
class CityTaggedItem(TaggedItem): class CityTaggedItem(TaggedItem):
moderation_level = get_moderation_level("CityTaggedItem")
city = models.OneToOneField( city = models.OneToOneField(
City, on_delete=models.PROTECT, related_name='city_items', primary_key=True) City, on_delete=models.PROTECT, related_name='city_items', primary_key=True)
...@@ -22,6 +25,6 @@ class CityTaggedItemSerializer(TaggedItemSerializer): ...@@ -22,6 +25,6 @@ class CityTaggedItemSerializer(TaggedItemSerializer):
class CityTaggedItemViewSet(TaggedItemViewSet): class CityTaggedItemViewSet(TaggedItemViewSet):
permission_classes = get_viewset_permissions("CityTaggedItemViewSet")
queryset = CityTaggedItem.objects.all() # pylint: disable=E1101 queryset = CityTaggedItem.objects.all() # pylint: disable=E1101
serializer_class = CityTaggedItemSerializer serializer_class = CityTaggedItemSerializer
from django.db import models from django.db import models
from backend.models.my_model import MyModel, MyModelSerializer, MyModelVersionnedViewSet from backend.models.my_model import MyModel, MyModelSerializer, MyModelVersionnedViewSet
from backend.utils import get_moderation_level, get_viewset_permissions
# Data model based on : https://unstats.un.org/unsd/methodology/m49/overview/ # Data model based on : https://unstats.un.org/unsd/methodology/m49/overview/
class Country(MyModel): class Country(MyModel):
moderation_level = get_moderation_level("Country")
name = models.CharField(max_length=200) name = models.CharField(max_length=200)
iso_alpha2_code = models.CharField(primary_key=True, max_length=2) iso_alpha2_code = models.CharField(primary_key=True, max_length=2)
iso_alpha3_code = models.CharField( iso_alpha3_code = models.CharField(
...@@ -27,5 +29,6 @@ class CountrySerializer(MyModelSerializer): ...@@ -27,5 +29,6 @@ class CountrySerializer(MyModelSerializer):
class CountryViewSet(MyModelVersionnedViewSet): class CountryViewSet(MyModelVersionnedViewSet):
permission_classes = get_viewset_permissions("CountryViewSet")
queryset = Country.objects.all() # pylint: disable=E1101 queryset = Country.objects.all() # pylint: disable=E1101
serializer_class = CountrySerializer serializer_class = CountrySerializer
from django.db import models from django.db import models
from backend.models.location import Country from backend.models.location import Country
from backend.models.module import DriRestrictedModule, DriRestrictedModuleSerializer, DriRestrictedModuleViewSet from backend.models.module import DriRestrictedModule, DriRestrictedModuleSerializer, DriRestrictedModuleViewSet
from backend.utils import get_moderation_level, get_viewset_permissions
class CountryDri(DriRestrictedModule): class CountryDri(DriRestrictedModule):
moderation_level = get_moderation_level("CountryDri")
country = models.ManyToManyField( country = models.ManyToManyField(
Country, related_name="country_dri") Country, related_name="country_dri")
...@@ -20,5 +22,6 @@ class CountryDriSerializer(DriRestrictedModuleSerializer): ...@@ -20,5 +22,6 @@ class CountryDriSerializer(DriRestrictedModuleSerializer):
class CountryDriViewSet(DriRestrictedModuleViewSet): class CountryDriViewSet(DriRestrictedModuleViewSet):
permission_classes = get_viewset_permissions("CountryDriViewSet")
queryset = CountryDri.objects.all() # pylint: disable=E1101 queryset = CountryDri.objects.all() # pylint: disable=E1101
serializer_class = CountryDriSerializer serializer_class = CountryDriSerializer
from django.db import models from django.db import models
from backend.models.location import Country from backend.models.location import Country
from backend.models.module import Scholarship, ScholarshipSerializer, ScholarshipViewSet from backend.models.module import Scholarship, ScholarshipSerializer, ScholarshipViewSet
from backend.utils import get_moderation_level, get_viewset_permissions
class CountryScholarship(Scholarship): class CountryScholarship(Scholarship):
moderation_level = get_moderation_level("CountryScholarship")
country = models.ManyToManyField( country = models.ManyToManyField(
Country, related_name="country_scholarhip") Country, related_name="country_scholarhip")
...@@ -20,5 +22,6 @@ class CountryScholarshipSerializer(ScholarshipSerializer): ...@@ -20,5 +22,6 @@ class CountryScholarshipSerializer(ScholarshipSerializer):
class CountryScholarshipViewSet(ScholarshipViewSet): class CountryScholarshipViewSet(ScholarshipViewSet):
permission_classes = get_viewset_permissions("CountryScholarshipViewSet")
queryset = CountryScholarship.objects.all() # pylint: disable=E1101 queryset = CountryScholarship.objects.all() # pylint: disable=E1101
serializer_class = CountryScholarshipSerializer serializer_class = CountryScholarshipSerializer
from django.db import models from django.db import models
from backend.models.tag import TaggedItem, TaggedItemSerializer, TaggedItemViewSet from backend.models.tag import TaggedItem, TaggedItemSerializer, TaggedItemViewSet
from backend.models.location import Country from backend.models.location import Country
from backend.utils import get_moderation_level, get_viewset_permissions
class CountryTaggedItem(TaggedItem): class CountryTaggedItem(TaggedItem):
moderation_level = get_moderation_level("CountryTaggedItem")
country = models.OneToOneField( country = models.OneToOneField(
Country, on_delete=models.PROTECT, related_name='country_items', primary_key=True) Country, on_delete=models.PROTECT, related_name='country_items', primary_key=True)
...@@ -22,6 +24,6 @@ class CountryTaggedItemSerializer(TaggedItemSerializer): ...@@ -22,6 +24,6 @@ class CountryTaggedItemSerializer(TaggedItemSerializer):
class CountryTaggedItemViewSet(TaggedItemViewSet): class CountryTaggedItemViewSet(TaggedItemViewSet):
permission_classes = get_viewset_permissions("CountryTaggedItemViewSet")
queryset = CountryTaggedItem.objects.all() # pylint: disable=E1101 queryset = CountryTaggedItem.objects.all() # pylint: disable=E1101
serializer_class = CountryTaggedItemSerializer serializer_class = CountryTaggedItemSerializer
from django.db import models from django.db import models
from rest_framework import permissions
from django.core.validators import MinValueValidator from django.core.validators import MinValueValidator
from backend.models.my_model import MyModel, MyModelSerializer, MyModelViewSet from backend.models.my_model import MyModel, MyModelSerializer, MyModelViewSet
from backend.utils import get_moderation_level, get_viewset_permissions
class Currency(MyModel): class Currency(MyModel):
moderation_level = get_moderation_level("Currency")
code = models.CharField(primary_key=True, max_length=3) code = models.CharField(primary_key=True, max_length=3)
name = models.CharField(max_length=100) name = models.CharField(max_length=100)
symbol = models.CharField(null=True, blank=True, max_length=30) symbol = models.CharField(null=True, blank=True, max_length=30)
...@@ -22,6 +24,6 @@ class CurrencySerializer(MyModelSerializer): ...@@ -22,6 +24,6 @@ class CurrencySerializer(MyModelSerializer):
class CurrencyViewSet(MyModelViewSet): class CurrencyViewSet(MyModelViewSet):
permission_classes = (permissions.IsAdminUser,) # TODO : change permission_classes = get_viewset_permissions("CurrencyViewSet")
queryset = Currency.objects.all() # pylint: disable=E1101 queryset = Currency.objects.all() # pylint: disable=E1101
serializer_class = CurrencySerializer serializer_class = CurrencySerializer
...@@ -2,12 +2,14 @@ from .myModel import MyModel ...@@ -2,12 +2,14 @@ from .myModel import MyModel
from .myModelSerializer import MyModelSerializer from .myModelSerializer import MyModelSerializer
from .myModelViewSet import MyModelViewSet from .myModelViewSet import MyModelViewSet
from django.db import models from django.db import models
from backend.utils import get_moderation_level, get_viewset_permissions
class ForTestingModeration(MyModel): class ForTestingModeration(MyModel):
""" """
Simple model for testing purposes Simple model for testing purposes
""" """
moderation_level = get_moderation_level("ForTestingModeration")
aaa = models.CharField(max_length=100) aaa = models.CharField(max_length=100)
...@@ -24,5 +26,6 @@ class ForTestingModerationViewSet(MyModelViewSet): ...@@ -24,5 +26,6 @@ class ForTestingModerationViewSet(MyModelViewSet):
""" """
Same as above Same as above
""" """
permission_classes = get_viewset_permissions("ForTestingModerationViewSet")
serializer_class = ForTestingModerationSerializer serializer_class = ForTestingModerationSerializer
queryset = ForTestingModeration.objects.all() queryset = ForTestingModeration.objects.all()
from .myModelVersionned import MyModelVersionned, MyModelVersionnedSerializer, MyModelVersionnedViewSet from .myModelVersionned import MyModelVersionned, MyModelVersionnedSerializer, MyModelVersionnedViewSet
from django.db import models from django.db import models
import reversion import reversion
from backend.utils import get_moderation_level, get_viewset_permissions
@reversion.register() @reversion.register()
...@@ -8,6 +9,7 @@ class ForTestingVersioning(MyModelVersionned): ...@@ -8,6 +9,7 @@ class ForTestingVersioning(MyModelVersionned):
""" """
Simple model for testing purposes Simple model for testing purposes
""" """
moderation_level = get_moderation_level("ForTestingVersioning")
bbb = models.CharField(max_length=100) bbb = models.CharField(max_length=100)
@classmethod @classmethod
...@@ -28,5 +30,6 @@ class ForTestingVersioningViewSet(MyModelVersionnedViewSet): ...@@ -28,5 +30,6 @@ class ForTestingVersioningViewSet(MyModelVersionnedViewSet):
""" """
Same as above Same as above
""" """
permission_classes = get_viewset_permissions("ForTestingVersioningViewSet")
serializer_class = ForTestingVersioningSerializer serializer_class = ForTestingVersioningSerializer
queryset = ForTestingVersioning.objects.all() queryset = ForTestingVersioning.objects.all()
...@@ -23,3 +23,5 @@ class MyModel(models.Model): ...@@ -23,3 +23,5 @@ class MyModel(models.Model):
class Meta: class Meta:
abstract = True abstract = True
moderation_level = None
from backend.models.my_model import MyModel, MyModelSerializer, MyModelViewSet from backend.models.my_model import MyModel, MyModelSerializer, MyModelViewSet
from backend.signals import new_revision_saved from backend.signals import new_revision_saved
from rest_framework import serializers, permissions, mixins, viewsets from rest_framework import serializers, mixins, viewsets
import reversion import reversion
from reversion.models import Version from reversion.models import Version
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.core.serializers.base import DeserializationError from django.core.serializers.base import DeserializationError
from django.core import serializers as djangoSerializers from django.core import serializers as djangoSerializers
from backend.utils import get_viewset_permissions
class MyModelVersionned(MyModel): class MyModelVersionned(MyModel):
...@@ -81,7 +82,7 @@ class VersionSerializer(serializers.ModelSerializer): ...@@ -81,7 +82,7 @@ class VersionSerializer(serializers.ModelSerializer):
class VersionViewSet(mixins.ListModelMixin, class VersionViewSet(mixins.ListModelMixin,
viewsets.GenericViewSet): # TODO better presentation viewsets.GenericViewSet): # TODO better presentation
permission_classes = (permissions.IsAuthenticated,) permission_classes = get_viewset_permissions("VersionViewSet")
serializer_class = VersionSerializer serializer_class = VersionSerializer
def get_queryset(self): def get_queryset(self):
......
from rest_framework import permissions
from .myModelSerializer import MyModelSerializer from .myModelSerializer import MyModelSerializer
from backend.models.tools import NoDeleteIfNotAdmin from backend.permissions import DEFAULT_VIEWSET_PERMISSIONS
from backend.models.tools import DictModeViewSet from backend.models.tools import DictModeViewSet
class MyModelViewSet(DictModeViewSet): class MyModelViewSet(DictModeViewSet):
serializer_class = MyModelSerializer serializer_class = MyModelSerializer
permission_classes = ( permission_classes = DEFAULT_VIEWSET_PERMISSIONS
permissions.IsAuthenticated,
NoDeleteIfNotAdmin,
)
def get_queryset(self): def get_queryset(self):
""" """
......
from django.db import models from django.db import models
from rest_framework import serializers, viewsets, permissions from rest_framework import serializers, viewsets
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.postgres.fields import JSONField from django.contrib.postgres.fields import JSONField
from django.contrib.auth.models import User from django.contrib.auth.models import User
from backend.utils import get_viewset_permissions, get_moderation_level
class PendingModeration(models.Model): class PendingModeration(models.Model):
moderation_level = get_moderation_level("PendingModeration")
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.CharField(max_length=100) # 100 should be ok object_id = models.CharField(max_length=100) # 100 should be ok
referenced_object = GenericForeignKey('content_type', 'object_id') referenced_object = GenericForeignKey('content_type', 'object_id')
...@@ -36,6 +39,6 @@ class PendingModerationSerializer(serializers.ModelSerializer): ...@@ -36,6 +39,6 @@ class PendingModerationSerializer(serializers.ModelSerializer):
class PendingModerationViewSet(viewsets.ModelViewSet): class PendingModerationViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.IsAdminUser,) permission_classes = get_viewset_permissions("PendingModerationViewSet")
queryset = PendingModeration.objects.all() # pylint: disable=E1101 queryset = PendingModeration.objects.all() # pylint: disable=E1101
serializer_class = PendingModerationSerializer serializer_class = PendingModerationSerializer
from django.db import models from django.db import models
from backend.models.my_model import MyModel, MyModelSerializer, MyModelViewSet from backend.models.my_model import MyModel, MyModelSerializer, MyModelViewSet
from rest_framework import permissions from backend.utils import get_moderation_level, get_viewset_permissions
class Department(MyModel): class Department(MyModel):
moderation_level = get_moderation_level("Department")
code = models.CharField(primary_key=True, max_length=6) code = models.CharField(primary_key=True, max_length=6)
name = models.CharField(max_length=100) name = models.CharField(max_length=100)
active = models.BooleanField() active = models.BooleanField()
...@@ -16,6 +18,6 @@ class DepartmentSerializer(MyModelSerializer): ...@@ -16,6 +18,6 @@ class DepartmentSerializer(MyModelSerializer):
class DepartmentViewSet(MyModelViewSet): class DepartmentViewSet(MyModelViewSet):
permission_classes = (permissions.IsAdminUser,) permission_classes = get_viewset_permissions("DepartmentViewSet")
queryset = Department.objects.all() # pylint: disable=E1101 queryset = Department.objects.all() # pylint: disable=E1101
serializer_class = DepartmentSerializer serializer_class = DepartmentSerializer
from django.db import models from django.db import models
from rest_framework import permissions
from backend.models.university import University from backend.models.university import University
from backend.models.other_core import Semester, Specialty from backend.models.other_core import Semester, Specialty
from backend.models.my_model import MyModel, MyModelSerializer, MyModelViewSet from backend.models.my_model import MyModel, MyModelSerializer, MyModelViewSet
from backend.utils import get_moderation_level, get_viewset_permissions
class Offer(MyModel): class Offer(MyModel):
moderation_level = get_moderation_level("Offer")
semester = models.ForeignKey(Semester, on_delete=models.PROTECT) semester = models.ForeignKey(Semester, on_delete=models.PROTECT)
university = models.ForeignKey(University, on_delete=models.PROTECT) university = models.ForeignKey(University, on_delete=models.PROTECT)
...@@ -28,6 +29,6 @@ class OfferSerializer(MyModelSerializer): ...@@ -28,6 +29,6 @@ class OfferSerializer(MyModelSerializer):
class OfferViewSet(MyModelViewSet): class OfferViewSet(MyModelViewSet):
permission_classes = (permissions.IsAdminUser,) permission_classes = get_viewset_permissions("OfferViewSet")
queryset = Offer.objects.all() # pylint: disable=E1101 queryset = Offer.objects.all() # pylint: disable=E1101
serializer_class = OfferSerializer serializer_class = OfferSerializer
from django.db import models from django.db import models
from rest_framework import permissions
from backend.models.my_model import MyModel, MyModelSerializer, MyModelViewSet from backend.models.my_model import MyModel, MyModelSerializer, MyModelViewSet
from backend.utils import get_moderation_level, get_viewset_permissions
class Semester(MyModel): class Semester(MyModel):
moderation_level = get_moderation_level("Semester")
code = models.CharField(primary_key=True, max_length=6)