Commit b9500eb2 authored by Florent Chehab's avatar Florent Chehab

Refactor(json validation): moved to standard json-schema

* JSON validation in now performed against `json-schemas` which give a standard way of handling this.
* All previous validation moved to new setup (`useful_links` field & `TaggedItem` in particular)
* Tags handling slightly updated (schemas are now hardcoded in the app and not stored in db)
* All new validators are unitested 🎉
* A bit of documentation added

----
* Bumped backend image to version 0.2.1 with new python packages requirements
----

Fixes #112
Mentions #113 #57
parent 7b30fd5f
......@@ -17,7 +17,7 @@ stages:
check_back:
<<: *only-default
stage: check
image: registry.gitlab.utc.fr/rex-dri/rex-dri/backend:v0.2.0
image: registry.gitlab.utc.fr/rex-dri/rex-dri/backend:v0.2.1
before_script:
- make setup
script:
......@@ -44,7 +44,7 @@ check_front:
test_back:
<<: *only-default
stage: test
image: registry.gitlab.utc.fr/rex-dri/rex-dri/backend:v0.2.0
image: registry.gitlab.utc.fr/rex-dri/rex-dri/backend:v0.2.1
variables:
POSTGRES_DB: postgres
POSTGRES_USER: postgres
......@@ -79,7 +79,7 @@ test_frontend:
flake8:
<<: *only-default
stage: lint
image: registry.gitlab.utc.fr/rex-dri/rex-dri/backend:v0.2.0
image: registry.gitlab.utc.fr/rex-dri/rex-dri/backend:v0.2.1
script:
- cd backend && flake8
tags:
......
[
{
"name": "photos",
"config": {
"photos": {
"type": "photos",
"required": true
}
}
},
{
"name": "insurance",
"config": {}
},
{
"name": "transport",
"config": {}
},
{
"name": "accommodation",
"config": {}
},
{
"name": "student_life",
"config": {}
},
{
"name": "everyday_life",
"config": {}
},
{
"name": "other",
"config": {}
},
{
"name": "administrative",
"config": {}
},
{
"name": "culture",
"config": {}
},
{
"name": "tourism",
"config": {}
},
{
"name": "shared_comment",
"config": {}
},
{
"name": "specific_partnership",
"config": {}
}
"photos",
"insurance",
"transport",
"accommodation",
"student_life",
"everyday_life",
"other",
"administrative",
"culture",
"tourism",
"shared_comment",
"specific_partnership"
]
\ No newline at end of file
import json
import os
from base_app.models import User
from backend_app.models.tag import Tag
from base_app.models import User
from .loadGeneric import LoadGeneric
......@@ -17,12 +15,11 @@ class LoadTags(LoadGeneric):
self.admin = admin
def load(self):
tmp = os.path.join(os.path.realpath(__file__), "../../assets/tags.json")
tags_path = os.path.abspath(tmp)
with open(tags_path) as f:
tags = json.load(f)
for tag in tags:
t = Tag(name=tag["name"], config=tag["config"])
for tag_name in tags:
t = Tag(name=tag_name)
t.save()
self.add_info_and_save(t, self.admin)
......@@ -819,16 +819,7 @@ class Migration(migrations.Migration):
("has_pending_moderation", models.BooleanField(default=False)),
("name", models.CharField(max_length=200)),
("acronym", models.CharField(blank=True, default="", max_length=20)),
(
"logo",
models.URLField(
blank=True,
default="",
validators=[
backend_app.models.university.validate_extension_django
],
),
),
("logo", models.URLField(blank=True, default="")),
("website", models.URLField(blank=True, default="", max_length=300)),
("utc_id", models.IntegerField(unique=True)),
],
......
# Generated by Django 2.1.7 on 2019-04-16 20:34
import backend_app.fields
import backend_app.models.abstract.essentialModule
import backend_app.validation.validators
from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
replaces = [
("backend_app", "0001_initial"),
("backend_app", "0002_auto_20190405_2131"),
("backend_app", "0002_auto_20190324_2123"),
("backend_app", "0003_merge_20190406_1636"),
("backend_app", "0004_auto_20190407_1010"),
("backend_app", "0005_auto_20190416_2200"),
("backend_app", "0006_auto_20190416_2227"),
]
initial = True
dependencies = [
("contenttypes", "0002_remove_content_type_name"),
("base_app", "0001_initial"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name="Campus",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
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.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)),
(
"importance_level",
models.CharField(
choices=[
("-", "normal"),
("+", "important"),
("++", "IMPORTANT"),
],
default="-",
max_length=2,
),
),
("is_main_campus", models.BooleanField()),
("name", models.CharField(blank=True, default="", max_length=200)),
(
"lat",
models.DecimalField(
decimal_places=6,
max_digits=10,
validators=[
django.core.validators.MinValueValidator(-85.05112878),
django.core.validators.MaxValueValidator(85.05112878),
],
),
),
(
"lon",
models.DecimalField(
decimal_places=6,
max_digits=10,
validators=[
django.core.validators.MinValueValidator(-180),
django.core.validators.MaxValueValidator(180),
],
),
),
],
),
migrations.CreateModel(
name="CampusTaggedItem",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
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.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)),
(
"importance_level",
models.CharField(
choices=[
("-", "normal"),
("+", "important"),
("++", "IMPORTANT"),
],
default="-",
max_length=2,
),
),
("custom_content", backend_app.fields.JSONField(default=dict)),
(
"campus",
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
related_name="campus_tagged_items",
to="backend_app.Campus",
),
),
],
),
migrations.CreateModel(
name="City",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=200)),
(
"local_name",
models.CharField(blank=True, default="", max_length=200),
),
("area", models.CharField(blank=True, default="", max_length=200)),
],
options={"abstract": False},
),
migrations.CreateModel(
name="CityTaggedItem",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
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.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)),
(
"importance_level",
models.CharField(
choices=[
("-", "normal"),
("+", "important"),
("++", "IMPORTANT"),
],
default="-",
max_length=2,
),
),
("custom_content", backend_app.fields.JSONField(default=dict)),
(
"city",
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
related_name="city_tagged_items",
to="backend_app.City",
),
),
],
),
migrations.CreateModel(
name="Country",
fields=[
("name", models.CharField(max_length=200)),
(
"iso_alpha2_code",
models.CharField(max_length=2, primary_key=True, serialize=False),
),
(
"iso_alpha3_code",
models.CharField(blank=True, default="", max_length=3, unique=True),
),
("region_name", models.CharField(max_length=200)),
("region_un_code", models.CharField(max_length=3)),
(
"sub_region_name",
models.CharField(blank=True, default="", max_length=200),
),
(
"sub_region_un_code",
models.CharField(blank=True, default="", max_length=3),
),
(
"intermediate_region_name",
models.CharField(blank=True, default="", max_length=200),
),
(
"intermediate_region_un_code",
models.CharField(blank=True, default="", max_length=3),
),
],
options={"abstract": False},
),
migrations.CreateModel(
name="CountryDri",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
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.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)),
(
"importance_level",
models.CharField(
choices=[
("-", "normal"),
("+", "important"),
("++", "IMPORTANT"),
],
default="-",
max_length=2,
),
),
(
"countries",
models.ManyToManyField(
related_name="country_dri", to="backend_app.Country"
),
),
],
options={"abstract": False},
),
migrations.CreateModel(
name="CountryScholarship",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
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.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)),
(
"importance_level",
models.CharField(
choices=[
("-", "normal"),
("+", "important"),
("++", "IMPORTANT"),
],
default="-",
max_length=2,
),
),
("short_description", models.CharField(max_length=200)),
(
"other_advantages",
models.CharField(blank=True, default="", max_length=5000),
),
(
"frequency",
models.CharField(
blank=True,
choices=[
("w", "week"),
("m", "month"),
("s", "semester"),
("y", "year"),
("o", "one_shot"),
],
default="m",
max_length=1,
null=True,
),
),
(
"amount_min",
models.DecimalField(
decimal_places=2,
max_digits=20,
null=True,
validators=[django.core.validators.MinValueValidator(0)],
),
),
(
"amount_max",
models.DecimalField(
decimal_places=2,
max_digits=20,
null=True,
validators=[django.core.validators.MinValueValidator(0)],
),
),
(
"countries",
models.ManyToManyField(
related_name="country_scholarships", to="backend_app.Country"
),
),
],
options={"abstract": False},
),
migrations.CreateModel(
name="CountryTaggedItem",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
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.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)),
(
"importance_level",
models.CharField(
choices=[
("-", "normal"),
("+", "important"),
("++", "IMPORTANT"),
],
default="-",
max_length=2,
),
),
("custom_content", backend_app.fields.JSONField(default=dict)),
(
"country",
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
related_name="country_tagged_items",
to="backend_app.Country",
),
),
],
),
migrations.CreateModel(
name="Currency",
fields=[
(
"code",
models.CharField(max_length=3, primary_key=True, serialize=False),
),
("name", models.CharField(max_length=100)),
("symbol", models.CharField(blank=True, default="", max_length=30)),
(
"one_EUR_in_this_currency",
models.DecimalField(
decimal_places=6,
max_digits=20,
validators=[django.core.validators.MinValueValidator(0)],
),
),
],
options={"abstract": False},
),
migrations.CreateModel(
name="Department",
fields=[
(
"code",
models.CharField(max_length=6, primary_key=True, serialize=False),
),
("name", models.CharField(max_length=100)),
("active", models.BooleanField()),
],
options={"abstract": False},
),
migrations.CreateModel(
name="ForTestingModeration",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
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.essentialModule.validate_obj_model_lv,
],
),
),
("has_pending_moderation", models.BooleanField(default=False)),
("aaa", models.CharField(max_length=100)),
],
options={"abstract": False},
),
migrations.CreateModel(
name="ForTestingVersioning",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
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.essentialModule.validate_obj_model_lv,
],