Commit 9ebbc2f0 authored by Florent Chehab's avatar Florent Chehab

Moderation close close to working for university

parent f1c99e79
Pipeline #26534 failed with stages
in 1 minute and 38 seconds
......@@ -47,6 +47,8 @@ from backend.models.user import PreviousDeparture
from backend.models.user import PreviousDepartureFeedback
from backend.models.user import UserData
from backend.models.tools import PendingModeration
CLASSIC_MODELS = [
Country,
City,
......@@ -59,7 +61,8 @@ CLASSIC_MODELS = [
RecommendationList,
PreviousDeparture,
PreviousDepartureFeedback,
UserData
UserData,
PendingModeration
]
VERSIONNED_MODELS = [
......
# Generated by Django 2.0.3 on 2018-08-24 13:51
from django.conf import settings
import django.contrib.postgres.fields.jsonb
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('contenttypes', '0002_remove_content_type_name'),
('backend', '0003_auto_20180824_1011'),
]
operations = [
migrations.CreateModel(
name='PendingModeration',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('object_id', models.CharField(max_length=100)),
('content_object', django.contrib.postgres.fields.jsonb.JSONField()),
('delete', models.NullBooleanField(default=None)),
('approve', models.NullBooleanField(default=None)),
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
],
),
]
# Generated by Django 2.0.3 on 2018-08-24 13:53
import django.contrib.postgres.fields.jsonb
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('backend', '0004_pendingmoderation'),
]
operations = [
migrations.AlterField(
model_name='pendingmoderation',
name='content_object',
field=django.contrib.postgres.fields.jsonb.JSONField(default={}),
),
]
# Generated by Django 2.0.3 on 2018-08-24 13:58
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('backend', '0005_auto_20180824_1553'),
]
operations = [
migrations.RenameField(
model_name='pendingmoderation',
old_name='content_object',
new_name='new_object',
),
]
# Generated by Django 2.0.3 on 2018-08-24 15:41
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('backend', '0006_auto_20180824_1558'),
]
operations = [
migrations.RenameField(
model_name='pendingmoderation',
old_name='new_object',
new_name='object_to_moderate',
),
]
# Generated by Django 2.0.3 on 2018-08-24 19:28
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('backend', '0007_auto_20180824_1741'),
]
operations = [
migrations.RenameField(
model_name='pendingmoderation',
old_name='object_to_moderate',
new_name='new_object',
),
migrations.RemoveField(
model_name='pendingmoderation',
name='approve',
),
migrations.RemoveField(
model_name='pendingmoderation',
name='delete',
),
migrations.RemoveField(
model_name='university',
name='updated_at',
),
migrations.AddField(
model_name='university',
name='moderated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='moderated', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='university',
name='moderated_on',
field=models.DateTimeField(null=True),
),
migrations.AddField(
model_name='university',
name='updated_on',
field=models.DateTimeField(null=True),
),
migrations.AlterField(
model_name='campus',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='campusaccommodation',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='campuscultureandstudentlife',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='campusotherstuff',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='campustransport',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='cityotherstuff',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='cityphoto',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='citytourism',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='citytransport',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='countryculture',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='countrydri',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='countryhealthinsurance',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='countryotherinsurance',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='countryotherstuff',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='countryphoto',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='countryscholarship',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='countrytourism',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='countrytransport',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='countryvisaadministrative',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='university',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='updated', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='universitycourses',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='universityculture',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='universitydri',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='universityinfo',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='universityinsurance',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='universityotherstuff',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='universityphoto',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='universityscholarship',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='universitysemestersdates',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='universityspecialoffer',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
]
# Generated by Django 2.0.3 on 2018-08-24 20:18
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('backend', '0008_auto_20180824_2128'),
]
operations = [
migrations.AlterUniqueTogether(
name='pendingmoderation',
unique_together={('content_type', 'object_id')},
),
]
......@@ -4,3 +4,5 @@ from .scholarship import Scholarship # noqa: F401
from .photo import Photo # noqa: F401
from .driRestrictedModule import DriRestrictedModule, DriRestrictedModuleSerializer # noqa: F401
from .currency import Currency, CurrencyViewSet, CurrencySerializer # noqa: F401
from .myModel import MyModel, MyModelSerializer
# MyModelVersionned, MyModelVersionnedSerializer # noqa: F401
from django.db import models
from django.contrib.auth.models import User
from rest_framework import serializers
from backend.signals import new_revision_saved
import reversion
from django.utils import timezone
from backend.models.tools import PendingModeration, PendingModerationSerializer
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
class MyModel(models.Model):
"""
All models in the app deppend of this one !
"""
moderated_by = models.ForeignKey(
User, null=True, on_delete=models.SET_NULL, related_name='moderated')
moderated_on = models.DateTimeField(null=True)
updated_on = models.DateTimeField(null=True)
updated_by = models.ForeignKey(
User, null=True, on_delete=models.SET_NULL, related_name='updated')
class Meta:
abstract = True
# class MyModelVersionned(MyModel):
# class Meta:
# abstract = True
def is_member(group_name, user):
return user.groups.filter(name=group_name).exists()
def date_time_to_str(date):
s = serializers.DateTimeField()
class MyModelSerializer(serializers.ModelSerializer):
moderated_on = serializers.DateTimeField(
format="%Y-%m-%d %H:%M:%S", read_only=True)
updated_on = serializers.DateTimeField(
format="%Y-%m-%d %H:%M:%S", read_only=True)
# moderated_by = serializers.ReadOnlyField()
# updated_by = serializers.ReadOnlyField()
# TODO Changed
updated_by_username = serializers.SerializerMethodField(read_only=True)
def get_updated_by_username(self, obj):
if obj.updated_by:
return obj.updated_by.username
else:
return None
class Meta:
model = MyModel
def moderation_required(self):
user = self.context['request'].user
request = self.context['request']
if user.is_staff:
return False
if settings.MODERATION_ACTIVATED:
if request.method in ['POST', 'PUT']: # should be always the case
if is_member('Moderator', request.user):
return False
else:
return True
return False
def set_model_attr_no_moder(self, moderated_and_updated):
user = self.context['request'].user
now = timezone.now()
self.validated_data['moderated_by'] = user
self.validated_data['moderated_on'] = now
if moderated_and_updated:
self.validated_data['updated_by'] = user
self.validated_data['updated_on'] = now
def set_model_attr_for_moder(self):
user = self.context['request'].user
self.validated_data['updated_by'] = user.pk
self.validated_data['updated_on'] = timezone.now().strftime(
"%Y-%m-%d %H:%M:%S")
# also return the user because it's usefull...
return user
def clean_validated_data(self):
self.validated_data['moderated_by'] = None
self.validated_data['moderated_on'] = None
self.validated_data['updated_by'] = None
self.validated_data['updated_on'] = None
def save(self, **kwargs):
self.clean_validated_data()
if self.moderation_required():
print("Modération requise")
user = self.set_model_attr_for_moder()
if self.instance is None: # we need to create the main model
self.instance = super(
MyModelSerializer, self).save(**kwargs)
ct = ContentType.objects.get_for_model(self.Meta.model)
objs_pending_db = PendingModeration.objects.filter(
content_type=ct, object_id=self.instance.pk)
if len(objs_pending_db) > 0:
pending_instance = objs_pending_db[0]
pending_instance.new_object = self.validated_data
pending_instance.save()
else:
pending_instance = PendingModeration(
referenced_object=self.instance,
author=user,
new_object=self.validated_data
)
pending_instance.save()
return self.instance
else:
print("Pas besoin de modération")
if self.instance is None:
return super(MyModelSerializer, self).save(**kwargs)
else:
# We check if we don't have any moderation pending
moderated_and_updated = True
print(self.Meta.model)
ct = ContentType.objects.get_for_model(self.Meta.model)
objs_pending_db = PendingModeration.objects.filter(
content_type=ct, object_id=self.instance.pk)
print(len(objs_pending_db))
if len(objs_pending_db) > 0:
# obj_pending_db = objs_pending_db[0]
# there should be only one
# TODO add checks to know if moderator did some modifications or not
# Change updated_by and on accordingly
# if obj_pending_db.new_object == self.validated_date
# moderated_and_updated = False
objs_pending_db.delete()
self.set_model_attr_no_moder(moderated_and_updated)
print('Pas besoin de modération')
return super(MyModelSerializer, self).save(**kwargs)
# class MyModelVersionnedSerializer(MyModelSerializer):
# def save(self, **kwargs):
# user = self.set_model_attr()
# # Create a revision for the update or creation
# with reversion.create_revision():
# super(MyModelVersionnedSerializer, self).save(**kwargs)
# reversion.set_user(user)
# # Signal save to perform concat of revisions
# new_revision_saved.send(sender=self.__class__, obj=self.instance)
......@@ -9,7 +9,7 @@ class VersionnedModule(models.Model):
updated_at = models.DateTimeField(auto_now=True)
updated_by = models.ForeignKey(
User, null=True, blank=True, on_delete=models.SET_NULL)
User, null=True, on_delete=models.SET_NULL)
class Meta:
abstract = True
......
from .DictModeViewSet import DictModeViewSet # noqa: F401
from .usefullLinksField import UsefullLinksField # noqa: F401
from .validateWithRestFramework import validate_with_rest_framework # noqa: F401
from .pendingModeration import PendingModeration, PendingModerationSerializer, PendingModerationViewSet # noqa: F401
from .noDeleteIfNotAdmin import NoDeleteIfNotAdmin # noqa: F401
from rest_framework.permissions import BasePermission
class NoDeleteIfNotAdmin(BasePermission):
def has_permission(self, request, view):
if (not request.user.is_staff) and request.method == 'DELETE':
return False
return True
from django.db import models
from rest_framework import serializers, viewsets, permissions
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.postgres.fields import JSONField
from django.contrib.auth.models import User
class PendingModeration(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.CharField(max_length=100) # 100 should be ok
referenced_object = GenericForeignKey('content_type', 'object_id')
author = models.ForeignKey(User, on_delete=models.CASCADE)
new_object = JSONField(default={})
class Meta:
unique_together = ('content_type', 'object_id')
class PendingModerationSerializer(serializers.ModelSerializer):
class Meta:
model = PendingModeration
fields = '__all__'
class PendingModerationViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.IsAdminUser,)
queryset = PendingModeration.objects.all() # pylint: disable=E1101
serializer_class = PendingModerationSerializer
from django.db import models
from backend.models.module import VersionnedModule
from backend.models.module import MyModel
from backend.utils.friendly_path import friendly_path
path_and_rename = friendly_path("uploads/universities/logos/", 'name')
class University(VersionnedModule):
class University(MyModel):
"""
Model storing information about universities
"""
......
from backend.models.university import University
from rest_framework import serializers, viewsets, permissions
from backend.models.university.campus import CampusSerializer
from backend.models.tools import NoDeleteIfNotAdmin
from backend.models.module import MyModelSerializer
class UniversitySerializer(serializers.ModelSerializer):
class UniversitySerializer(MyModelSerializer):
univ_campus = CampusSerializer(many=True, read_only=True)
class Meta:
model = University
fields = ('name', 'acronym', 'logo', 'id', 'univ_campus')
fields = '__all__'
class UniversityViewSet(viewsets.ModelViewSet): # TODO switch to dict
permission_classes = (permissions.DjangoModelPermissions,)
queryset = University.objects.all().prefetch_related('univ_campus', 'univ_campus__updated_by') # pylint: disable=E1101
permission_classes = (
permissions.IsAuthenticated,
NoDeleteIfNotAdmin,
)
queryset = University.objects.all()\
.prefetch_related('univ_campus', 'univ_campus__updated_by') # pylint: disable=E1101
serializer_class = UniversitySerializer
......@@ -50,6 +50,8 @@ from backend.models.user import PreviousDepartureViewSet
from backend.models.user import PreviousDepartureFeedbackViewSet
from backend.models.user import UserDataViewSet
from backend.models.tools import PendingModerationViewSet
from rest_framework.documentation import include_docs_urls
......@@ -118,4 +120,6 @@ router.register(r'user/recommendation', RecommendationViewSet)
router.register(r'user/recommendations_list', RecommendationListViewSet)
router.register(r'user/data', UserDataViewSet)
router.register(r'pending_moderation', PendingModerationViewSet)
urlpatterns += [url(r'^api/', include(router.urls))]
......@@ -48,6 +48,9 @@ MIDDLEWARE = [
'general.middleware.LoginRequiredMiddleware',
]
# If we want to activate the moderation functionnalities
MODERATION_ACTIVATED = True
INTERNAL_IPS = ['127.0.0.1']
LOGIN_URL = '/user/login'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment