Commit 4c12f242 authored by Florent Chehab's avatar Florent Chehab
Browse files

feat(backend): complete refactoring of the backend

* Added new BaseModel /serializer/viewsets
* Change names of abstract models/serializers/viewsets
* Folder structure changed in tha backend
* Added some backend test
* Corrected bug related to moderation on non versionned modeles
* Corrected bug related to no post permissions
* Updated doc accordingly

Fixes #91
parent 710a5417
Pipeline #37109 passed with stages
in 4 minutes and 54 seconds
......@@ -11,3 +11,4 @@ htmlcov
.pytest_cache
database.db
database.db-journal
.idea
......@@ -4,15 +4,18 @@ from reversion_compare.admin import CompareVersionAdmin
from backend_app.config.models import get_models
from backend_app.checks import check_classic_models, check_versionned_models
VERSIONNED_MODELS = get_models(versionned=True, requires_testing=False)
CLASSIC_MODELS = get_models(versionned=False, requires_testing=False)
# We need to register testing models, otherwise we won't be able to test properly,
# Since no migrations would privide those models.
# So don't put requires_testing=True
VERSIONED_MODELS = get_models(versionned=True) # , requires_testing=False)
CLASSIC_MODELS = get_models(versionned=False) # , requires_testing=False)
#######
# Perform some dynamic checks
#######
check_classic_models(CLASSIC_MODELS)
check_versionned_models(VERSIONNED_MODELS)
check_versionned_models(VERSIONED_MODELS)
#######
# Register the models
......@@ -22,7 +25,6 @@ for Model in CLASSIC_MODELS:
# Register the model in the admin in a standard way
admin.site.register(Model)
for Model in VERSIONNED_MODELS:
for Model in VERSIONED_MODELS:
# Register the model in the admin with versioning
admin.site.register(Model, CompareVersionAdmin)
......@@ -5,6 +5,5 @@ class BackendAppConfig(AppConfig):
name = "backend_app"
def ready(self):
import backend_app.signals.__create_user_modules_post_create # noqa:F401
import backend_app.signals.__squash_revision_by_user # noqa:F401
import backend_app.signals.__create_univ_modules_post_save # noqa:F401
import backend_app.signals.squash_revisions # noqa:F401
import backend_app.signals.auto_creation # noqa:F401
import importlib
from typing import List, Optional, Union
from backend_app.models.abstract.versionedEssentialModule import (
VersionedEssentialModule,
)
from django.conf import settings
from backend_app.models.abstract.my_model.myModelVersionned import MyModelVersionned
from .utils import load_viewsets_config
......@@ -51,9 +52,9 @@ def get_models(
Model = Viewset.serializer_class.Meta.model
if versionned is not None:
if versionned and not issubclass(Model, MyModelVersionned):
if versionned and not issubclass(Model, VersionedEssentialModule):
continue
if not versionned and issubclass(Model, MyModelVersionned):
if not versionned and issubclass(Model, VersionedEssentialModule):
continue
out.append(Model)
......
......@@ -49,7 +49,7 @@ CampusViewSet:
UserDataViewSet:
import_location: user
import_location: userData
api_end_point: userData
api_name: user-data-detail
viewset_permission: IsOwner
......@@ -66,33 +66,33 @@ CurrencyViewSet:
viewset_permission: IsStaff | ReadOnly
DepartmentViewSet:
import_location: other_core
import_location: department
api_end_point: departments
viewset_permission: IsStaff | ReadOnly
SpecialtyViewSet:
import_location: other_core
import_location: specialty
api_end_point: specialties
viewset_permission: IsStaff | ReadOnly
OfferViewSet:
import_location: other_core
import_location: offer
api_end_point: offers
viewset_permission: IsStaff | ReadOnly
CountryTaggedItemViewSet:
import_location: country
import_location: countryTaggedItem
api_end_point: countryTaggedItems
api_attr: (?P<country_id>[a-zA-Z]+)
CountryScholarshipViewSet:
import_location: country
import_location: countryScholarship
api_end_point: countryScholarships
api_attr: (?P<country_id>[a-zA-Z]+)
CountryDriViewSet:
import_location: country
import_location: countryDri
api_end_point: countryDri
api_attr: (?P<country_id>[a-zA-Z]+)
viewset_permission: IsStaff | IsDri | NoPost
......@@ -100,34 +100,34 @@ CountryDriViewSet:
CityTaggedItemViewSet:
import_location: city
import_location: cityTaggedItem
api_end_point: cityTaggedItems
api_attr: (?P<city_id>[0-9]+)
UniversityTaggedItemViewSet:
import_location: university
import_location: universityTaggedItem
api_end_point: universityTaggedItems
api_attr: (?P<univ_id>[0-9]+)
UniversityScholarshipViewSet:
import_location: university
import_location: universityScholarship
api_end_point: universityScholarships
api_attr: (?P<univ_id>[0-9]+)
UniversityInfoViewSet:
import_location: university
import_location: universityInfo
viewset_permission: IsStaff | NoPost
api_end_point: universitiesInfo
UniversitySemestersDatesViewSet:
import_location: university
import_location: universitySemestersDates
api_end_point: universitiesSemestersDates
viewset_permission: IsStaff | NoPost
UniversityDriViewSet:
import_location: university
import_location: universityDri
api_end_point: universityDri
api_attr: (?P<univ_id>[0-9]+)
viewset_permission: IsStaff | IsDri | NoPost
......@@ -135,7 +135,7 @@ UniversityDriViewSet:
CampusTaggedItemViewSet:
import_location: campus
import_location: campusTaggedItem
api_end_point: campusTaggedItems
api_attr: (?P<campus_id>[0-9]+)
......@@ -147,50 +147,50 @@ MainCampusViewSet:
RecommendationViewSet:
import_location: user
import_location: recommendation
api_end_point: userRecommendations
RecommendationListViewSet:
import_location: user
import_location: recommendationList
api_end_point: userRecommendationLists
PreviousDepartureViewSet:
import_location: user
import_location: previousDeparture
api_end_point: universitiesPreviousDepartures
viewset_permission: ReadOnly
PreviousDepartureFeedbackViewSet:
import_location: user
import_location: previousDepartureFeedback
api_end_point: universitiesPreviousDepartureFeedback
PendingModerationViewSet:
import_location: abstract.my_model
import_location: pendingModeration
api_end_point: pendingModeration
viewset_permission: IsStaff
VersionViewSet:
import_location: abstract.my_model
import_location: version
api_end_point: versions
api_attr: (?P<content_type_id>[0-9]+)/(?P<object_pk>[0-9A-Za-z]+)
api_name: versionsList
viewset_permission: IsStaff | ReadOnly
PendingModerationObjViewSet:
import_location: abstract.my_model
import_location: pendingModeration
api_end_point: pendingModerationObj
api_attr: (?P<content_type_id>[0-9]+)/(?P<object_pk>[0-9A-Za-z]+)
api_name: pendingModerationObj
viewset_permission: ReadOnly
ForTestingModerationViewSet:
import_location: abstract.my_model
import_location: for_testing.moderation
api_end_point: test/moderation
requires_testing: true
ForTestingVersioningViewSet:
import_location: abstract.my_model
import_location: for_testing.versioning
api_end_point: test/versioning
requires_testing: true
from .mySerializerWithJSON import MySerializerWithJSON
__all__ = ["MySerializerWithJSON"]
......@@ -2,7 +2,7 @@ from base_app.models import User
from django.utils import timezone
import reversion
from backend_app.models.abstract.my_model import MyModel
from backend_app.models.abstract.essentialModule import EssentialModule
class LoadGeneric(object):
......@@ -10,7 +10,7 @@ class LoadGeneric(object):
"""
@classmethod
def add_info_and_save(cls, obj: MyModel, admin: User):
def add_info_and_save(cls, obj: EssentialModule, admin: User):
with reversion.create_revision():
obj.moderated_by = admin
obj.updated_by = admin
......
......@@ -2,16 +2,15 @@ from datetime import datetime
from base_app.models import User
from backend_app.models.country import Country, CountryScholarship
from backend_app.models.country import Country
from backend_app.models.countryScholarship import CountryScholarship
from backend_app.models.currency import Currency
from backend_app.models.tag import Tag
from backend_app.models.university import (
University,
UniversityDri,
UniversityInfo,
UniversitySemestersDates,
UniversityTaggedItem,
)
from backend_app.models.university import University
from backend_app.models.universityDri import UniversityDri
from backend_app.models.universityInfo import UniversityInfo
from backend_app.models.universitySemestersDates import UniversitySemestersDates
from backend_app.models.universityTaggedItem import UniversityTaggedItem
from .loadGeneric import LoadGeneric
......
# Generated by Django 2.1.7 on 2019-03-10 20:02
# Generated by Django 2.1.7 on 2019-03-23 14:30
import backend_app.fields
import backend_app.models.abstract.my_model.myModel
import backend_app.models.university.university
import backend_app.models.abstract.essentialModule
import backend_app.models.university
from django.conf import settings
import django.core.validators
from django.db import migrations, models
......@@ -11,19 +11,12 @@ import django.db.models.deletion
class Migration(migrations.Migration):
replaces = [
("backend_app", "0001_initial"),
("backend_app", "0002_auto_20190310_1726"),
("backend_app", "0003_auto_20190310_1731"),
("backend_app", "0004_auto_20190310_1756"),
]
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("contenttypes", "0002_remove_content_type_name"),
("base_app", "0001_initial"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
......@@ -47,10 +40,12 @@ class Migration(migrations.Migration):
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.my_model.myModel.validate_obj_model_lv,
backend_app.models.abstract.essentialModule.validate_obj_model_lv,
],
),
),
("has_pending_moderation", models.BooleanField(default=False)),
("nb_versions", models.PositiveIntegerField(default=0)),
("title", models.CharField(blank=True, default="", max_length=150)),
("comment", models.CharField(blank=True, default="", max_length=5000)),
("useful_links", backend_app.fields.JSONField(default=list)),
......@@ -112,10 +107,12 @@ class Migration(migrations.Migration):
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.my_model.myModel.validate_obj_model_lv,
backend_app.models.abstract.essentialModule.validate_obj_model_lv,
],
),
),
("has_pending_moderation", models.BooleanField(default=False)),
("nb_versions", models.PositiveIntegerField(default=0)),
("title", models.CharField(blank=True, default="", max_length=150)),
("comment", models.CharField(blank=True, default="", max_length=5000)),
("useful_links", backend_app.fields.JSONField(default=list)),
......@@ -154,18 +151,6 @@ class Migration(migrations.Migration):
verbose_name="ID",
),
),
("updated_on", models.DateTimeField(null=True)),
("moderated_on", models.DateTimeField(null=True)),
(
"obj_moderation_level",
models.SmallIntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.my_model.myModel.validate_obj_model_lv,
],
),
),
("name", models.CharField(max_length=200)),
(
"local_name",
......@@ -195,10 +180,12 @@ class Migration(migrations.Migration):
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.my_model.myModel.validate_obj_model_lv,
backend_app.models.abstract.essentialModule.validate_obj_model_lv,
],
),
),
("has_pending_moderation", models.BooleanField(default=False)),
("nb_versions", models.PositiveIntegerField(default=0)),
("title", models.CharField(blank=True, default="", max_length=150)),
("comment", models.CharField(blank=True, default="", max_length=5000)),
("useful_links", backend_app.fields.JSONField(default=list)),
......@@ -228,18 +215,6 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name="Country",
fields=[
("updated_on", models.DateTimeField(null=True)),
("moderated_on", models.DateTimeField(null=True)),
(
"obj_moderation_level",
models.SmallIntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.my_model.myModel.validate_obj_model_lv,
],
),
),
("name", models.CharField(max_length=200)),
(
"iso_alpha2_code",
......@@ -290,10 +265,12 @@ class Migration(migrations.Migration):
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.my_model.myModel.validate_obj_model_lv,
backend_app.models.abstract.essentialModule.validate_obj_model_lv,
],
),
),
("has_pending_moderation", models.BooleanField(default=False)),
("nb_versions", models.PositiveIntegerField(default=0)),
("title", models.CharField(blank=True, default="", max_length=150)),
("comment", models.CharField(blank=True, default="", max_length=5000)),
("useful_links", backend_app.fields.JSONField(default=list)),
......@@ -338,10 +315,12 @@ class Migration(migrations.Migration):
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.my_model.myModel.validate_obj_model_lv,
backend_app.models.abstract.essentialModule.validate_obj_model_lv,
],
),
),
("has_pending_moderation", models.BooleanField(default=False)),
("nb_versions", models.PositiveIntegerField(default=0)),
("title", models.CharField(blank=True, default="", max_length=150)),
("comment", models.CharField(blank=True, default="", max_length=5000)),
("useful_links", backend_app.fields.JSONField(default=list)),
......@@ -357,7 +336,7 @@ class Migration(migrations.Migration):
max_length=2,
),
),
("type", models.CharField(max_length=200)),
("short_description", models.CharField(max_length=200)),
(
"other_advantages",
models.CharField(blank=True, default="", max_length=5000),
......@@ -425,10 +404,12 @@ class Migration(migrations.Migration):
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.my_model.myModel.validate_obj_model_lv,
backend_app.models.abstract.essentialModule.validate_obj_model_lv,
],
),
),
("has_pending_moderation", models.BooleanField(default=False)),
("nb_versions", models.PositiveIntegerField(default=0)),
("title", models.CharField(blank=True, default="", max_length=150)),
("comment", models.CharField(blank=True, default="", max_length=5000)),
("useful_links", backend_app.fields.JSONField(default=list)),
......@@ -458,18 +439,6 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name="Currency",
fields=[
("updated_on", models.DateTimeField(null=True)),
("moderated_on", models.DateTimeField(null=True)),
(
"obj_moderation_level",
models.SmallIntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.my_model.myModel.validate_obj_model_lv,
],
),
),
(
"code",
models.CharField(max_length=3, primary_key=True, serialize=False),
......@@ -490,18 +459,6 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name="Department",
fields=[
("updated_on", models.DateTimeField(null=True)),
("moderated_on", models.DateTimeField(null=True)),
(
"obj_moderation_level",
models.SmallIntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.my_model.myModel.validate_obj_model_lv,
],
),
),
(
"code",
models.CharField(max_length=6, primary_key=True, serialize=False),
......@@ -531,10 +488,11 @@ class Migration(migrations.Migration):
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.my_model.myModel.validate_obj_model_lv,
backend_app.models.abstract.essentialModule.validate_obj_model_lv,
],
),
),
("has_pending_moderation", models.BooleanField(default=False)),
("aaa", models.CharField(max_length=100)),
],
options={"abstract": False},
......@@ -559,10 +517,12 @@ class Migration(migrations.Migration):
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.my_model.myModel.validate_obj_model_lv,
backend_app.models.abstract.essentialModule.validate_obj_model_lv,
],
),
),
("has_pending_moderation", models.BooleanField(default=False)),
("nb_versions", models.PositiveIntegerField(default=0)),
("bbb", models.CharField(max_length=100)),
],
options={"abstract": False},
......@@ -579,18 +539,6 @@ class Migration(migrations.Migration):
verbose_name="ID",
),
),
("updated_on", models.DateTimeField(null=True)),
("moderated_on", models.DateTimeField(null=True)),
(
"obj_moderation_level",
models.SmallIntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.my_model.myModel.validate_obj_model_lv,
],
),
),
("year", models.PositiveIntegerField(default=2018)),
(
"semester",
......@@ -653,10 +601,11 @@ class Migration(migrations.Migration):
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.my_model.myModel.validate_obj_model_lv,
backend_app.models.abstract.essentialModule.validate_obj_model_lv,
],
),
),
("has_pending_moderation", models.BooleanField(default=False)),
("Utc_departure_id", models.IntegerField()),
("year", models.PositiveIntegerField(default=2018)),
(
......@@ -692,10 +641,11 @@ class Migration(migrations.Migration):
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.my_model.myModel.validate_obj_model_lv,
backend_app.models.abstract.essentialModule.validate_obj_model_lv,
],
),
),
("has_pending_moderation", models.BooleanField(default=False)),
("is_anonymous", models.BooleanField(default=True)),
("is_public", models.BooleanField(default=False)),
(
......@@ -752,10 +702,11 @@ class Migration(migrations.Migration):
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.my_model.myModel.validate_obj_model_lv,
backend_app.models.abstract.essentialModule.validate_obj_model_lv,
],
),
),
("has_pending_moderation", models.BooleanField(default=False)),
("is_anonymous", models.BooleanField(default=True)),
("is_public", models.BooleanField(default=False)),
("order_in_list", models.PositiveIntegerField()),
......@@ -789,10 +740,11 @@ class Migration(migrations.Migration):
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.my_model.myModel.validate_obj_model_lv,
backend_app.models.abstract.essentialModule.validate_obj_model_lv,
],
),
),
("has_pending_moderation", models.BooleanField(default=False)),
("is_anonymous", models.BooleanField(default=True)),
("is_public", models.BooleanField(default=False)),
("public", models.BooleanField()),
......@@ -811,18 +763,6 @@ class Migration(migrations.Migration):
verbose_name="ID",
),
),
("updated_on", models.DateTimeField(null=True)),
("moderated_on", models.DateTimeField(null=True)),
(
"obj_moderation_level",
models.SmallIntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.my_model.myModel.validate_obj_model_lv,
],
),
),
("code", models.CharField(max_length=6)),
("name", models.CharField(max_length=100)),