Commit 0e4c1aef authored by Florent Chehab's avatar Florent Chehab Committed by Florent Chehab

removed(all TODOs):

Some of them were simply removed, oter were fixed.
From now on, the use of TODO is not permitted in the code.
parent 5530363c
Pipeline #36624 passed with stages
in 4 minutes and 54 seconds
[flake8] [flake8]
# E501 line too long # E501 line too long
ignore = E501,W503 ignore = E501,W503
exclude =
env/*
node_modules/*
base_app/settings/development.py
from .load_all import load_all # We firest need to define ASSETS_PATH to prevent cyclic imports
from os import path
__all__ = ["load_all"] ASSETS_PATH = path.join(path.realpath(__file__), "../assets/") # noqa: E402
from .load_all import load_all # noqa: E402
__all__ = ["load_all", "ASSETS_PATH"]
"Pays","Ville","Nom de l'établissement"
"Allemagne","Hamburg","Technische Universitat Hamburg"
"Allemagne","Ilmenau","Technische Universitat Ilmenau"
"Argentine","Buenos Aires","Universidad Del Salvador"
"Australie","Victoria","Swinburne University Of Technology"
"Autriche","Graz","Technische Universitat Graz"
"Belgique","Gent","Universiteit Gent"
"Brésil","Belo Horizonte","Universidade Federal De Minas Gerais"
"Brésil","Campina Grande","Universidade Federal De Campina Grande"
"Brésil","Campinas-Sao Paulo","Universidade Estadual De Campinas (Unicamp)"
"Brésil","Caxias Do Sul","Universidade Caxias Do Sul"
"Brésil","Curitiba","Pontificia Universidade Catolica Do Parana"
"Brésil","Curitiba","Universidade Federal Do Parana"
"Brésil","Curitiba","Universidade Tecnologica Federal Do Parana"
"Brésil","Florianópolis","Universidade Federal De Santa Catarina"
"Brésil","Itajuba","Universidade Federal De Itajuba"
"Brésil","João Pessoa","Universidade Federal Da Paraiba"
"Brésil","Juiz De Fora","Universidade Federal Juiz De Fora"
"Brésil","Lavras","Universidade Federal De Lavras (Ufla)"
"Brésil","Maringa","Universidad Estadual De Maringa"
"Brésil","Recife","Universidade Federal De Pernambuco"
"Brésil","Rio De Janeiro","Universidade Federal De Rio De Janeiro"
"Brésil","Santa Rita Do Sapucaí","Instituto Nacional De Telecommunicaçoes-Inatel"
"Brésil","Sao Paulo","Escola Politecnica Da Universidade De Sao Paulo"
"Brésil","Uberlandia","Universidade Federal De Uberlandia"
"Bulgarie","Sofia","Technical University Of Sofia"
"Bulgarie","Sofia","University Of Chemical Engineering And Mettalurgy"
"Chili","Iquique","Universidad Arturo Prat"
"Chili","Valparaiso","Pontificia Universidad Catolica De Valparaiso"
"Chili","Valparaiso","Universidad De Valparaiso"
"Chili","Valparaiso","Universidad Tecnica Federico Santa Maria"
"Colombie","Bogota","Escuela Colombiana De Ingenieria"
"Colombie","Bucaramanga","Universidad Autonoma De Bucaramanga"
"Colombie","Medellin","Universidad Eafit"
"Coree Du Sud","Daejeon","Kaist Korea Advanced Institute Of Science And Technology"
"Coree Du Sud","Pohang","Pohang University Of Science And Technology"
"Coree Du Sud","Seoul","Hanyang University"
"Coree Du Sud","Seoul","Kookmin University"
"Coree Du Sud","Seoul","Seoul National University Of Science And Technology Seoultech"
"Equateur","Quito","Escuela Politecnica Nacional De Quito"
"Espagne","Barcelone","Universitat Politecnica De Catalunya - Fib-Upc"
"Espagne","Bellatera","Universidad Autonoma De Barcelona"
"Espagne","Lleida","Universidad De Lleida"
"Espagne","Madrid","Universidad Politecnica De Madrid (Etsiinf)"
"Espagne","Murcia","Universidad De Murcia"
"Espagne","Valencia","Universitat Politecnica De Valencia Etsinf"
"Espagne","Zaragoza","Universidad De Zaragoza"
"Finlande","Oulu","Oulu University Of Applied Sciences"
"Finlande","Tampere","Tampere University Of Technology"
"Islande","Reykjavik","Reykjavik University (Ru)"
"Italie","Arcavacata","Universita Della Calabria"
"Italie","Bologna","Universita Di Bologna"
"Italie","Fisciano","Universita Degli Studi Di Salerno"
"Italie","Genova","Universita Degli Studi Di Genova"
"Italie","Milan","Politecnico Di Milano"
"Italie","Modena","Universita Degli Studi Di Modena E Regio Emilia"
"Italie","Napoli","Universita Degli Studi Di Napoli Federico Ii"
"Japon","Chiba","Chiba Institute Of Technology"
"Japon","Chiba","Chiba University"
"Japon","Sendai","Tohoku University"
"Liban","Beyrouth","Universite Libanaise"
"Liban","Kaslik","Université Saint-Esprit De Kaslik"
"Mexique","Aguascalientes","Universidad Autonoma De Aguascalientes"
"Mexique","Ciudad Del Carmen, Campeche","Universidad Autonoma Del Carmen"
"Mexique","Guanajuato","Universidad De Guanajuato"
"Mexique","Merida Yucatan","Universidad Anahuac Mayab"
"Mexique","Mexico","Instituto Politecnico Nacional"
"Mexique","Mexico","Universidad Iberoamericana"
"Mexique","Monterrey","Itesm - Tec De Monterrrey"
"Mexique","Pueblar, Pue","Upaep"
"Mexique","Zacatepec De Hidalgo","Instituto Tecnologico De Zacatepec"
"Norvege","Trondheim","Norwegian University Of Science And Technology"
"Pays-Bas","Enschede","University Twente"
"Pologne","Cracovie","Agh - University Of Science And Technology"
"Pologne","Cracovie","Politechnika Krakowska"
"Pologne","Lodz","Lodz University Of Technology"
"Portugal","Covilhã","Universidade Da Beira Interior"
"République PopulaireDe Chine","Hong Kong","City University Of Hong Kong"
"République PopulaireDe Chine","Shanghaï","Universite De Technologie Sino-Europeenne De L'Universite De Shanghai (Utseus)"
"Republique Tcheque","Prague","Czech Technical University Of Technology"
"Slovaquie","Kosice","Technical University Of Kosice"
"Suede","Goteborg","Chalmers University Of Technology"
"Suede","Lulea","Lulea University Of Technology"
"Suisse","Lausanne","Ecole Polytechnique Federale De Lausanne"
"Taiwan","Hsinchu","National Chiao Tung University"
"Taiwan","Taipei","National Taiwan University Of Science And Technology"
"""
Script to insert the country data in the database
IT HAS TO BE RUN INSIDE ./manage.py shell
TODO YURK. Use pandas @florent !!
"""
import csv
import os
import time
import reverse_geocoder as rg
from geopy.geocoders import Nominatim
tmp = os.path.join(os.path.realpath(__file__), "../../assets/destinations.csv")
destinations_path = os.path.abspath(tmp)
tmp = os.path.join(
os.path.realpath(__file__), "../../assets/destinations_extracted.csv"
)
destinations_extracted_path = os.path.abspath(tmp)
if not os.path.isfile(destinations_path):
print(destinations_path)
raise Exception("Missing file containing country data")
with open(destinations_path, "rt") as input:
with open(destinations_extracted_path, "w") as output:
print("ini")
reader = csv.reader(input)
spamwriter = csv.writer(output, quoting=csv.QUOTE_NONNUMERIC)
geolocator = Nominatim()
failed = []
i = 0
for row in reader:
# handle the header
if i == 0:
header = ["university", "city", "country", "lat", "lon"]
spamwriter.writerow(header)
i += 1
else:
query = row[2] # + ', ' + row[1] + ', ' + row[0]
while True:
try:
location = geolocator.geocode(query)
break
except: # noqa: E722
print("error during query, retrying")
time.sleep(0.5)
if location is not None:
coord = (location.latitude, location.longitude)
res = rg.search(coord, verbose=False)
line = [
row[2],
row[1],
res[0]["cc"],
location.latitude,
location.longitude,
]
print(line)
spamwriter.writerow(line)
else:
failed.append(query)
print(failed)
...@@ -6,6 +6,7 @@ from .loadTags import LoadTags ...@@ -6,6 +6,7 @@ from .loadTags import LoadTags
from .loadCurrencies import LoadCurrencies from .loadCurrencies import LoadCurrencies
from .loadUniversityEx import LoadUniversityEx from .loadUniversityEx import LoadUniversityEx
__all__ = [ __all__ = [
"LoadGroups", "LoadGroups",
"LoadAdminUser", "LoadAdminUser",
...@@ -15,5 +16,3 @@ __all__ = [ ...@@ -15,5 +16,3 @@ __all__ = [
"LoadCurrencies", "LoadCurrencies",
"LoadUniversityEx", "LoadUniversityEx",
] ]
# TODO in all loading files, use a path to the assets folder define somewhere else.
...@@ -6,7 +6,7 @@ class LoadAdminUser(object): ...@@ -6,7 +6,7 @@ class LoadAdminUser(object):
def __init__(self): def __init__(self):
""" """
Creating admin user by creating a user and setting is_staff is True Creating admin user by creating a user and setting is_staff is True
didn't enable access to the admin system for an unkown reason. didn't enable access to the admin system for an unknown reason.
Need to use create_superuser. Need to use create_superuser.
""" """
user = User.objects.filter(username="admin") user = User.objects.filter(username="admin")
......
import os from os.path import abspath, join
from base_app.models import User
import pandas as pd import pandas as pd
from backend_app.load_data import ASSETS_PATH
from backend_app.models.country import Country from backend_app.models.country import Country
from base_app.models import User
from .loadGeneric import LoadGeneric from .loadGeneric import LoadGeneric
...@@ -17,12 +17,8 @@ class LoadCountries(LoadGeneric): ...@@ -17,12 +17,8 @@ class LoadCountries(LoadGeneric):
self.admin = admin self.admin = admin
def load(self): def load(self):
tmp = os.path.join(os.path.realpath(__file__), "../../assets/country.csv") country_file_loc = abspath(join(ASSETS_PATH, "country.csv"))
country_file_loc = os.path.abspath(tmp) conv_alpha_file_loc = abspath(join(ASSETS_PATH, "alpha-conv-table.csv"))
tmp = os.path.join(
os.path.realpath(__file__), "../../assets/alpha-conv-table.csv"
)
conv_alpha_file_loc = os.path.abspath(tmp)
country_pd = pd.read_csv( country_pd = pd.read_csv(
country_file_loc, sep=",", header=0, dtype=object country_file_loc, sep=",", header=0, dtype=object
......
import csv import csv
import os
from decimal import Decimal from decimal import Decimal
from os.path import abspath, join
from base_app.models import User from backend_app.load_data import ASSETS_PATH
from backend_app.models.currency import Currency from backend_app.models.currency import Currency
from base_app.models import User
from .loadGeneric import LoadGeneric from .loadGeneric import LoadGeneric
...@@ -18,8 +18,7 @@ class LoadCurrencies(LoadGeneric): ...@@ -18,8 +18,7 @@ class LoadCurrencies(LoadGeneric):
self.admin = admin self.admin = admin
def load(self): def load(self):
tmp = os.path.join(os.path.realpath(__file__), "../../assets/currencies.csv") currencies_file_loc = abspath(join(ASSETS_PATH, "currencies.csv"))
currencies_file_loc = os.path.abspath(tmp)
with open(currencies_file_loc) as csvfile: with open(currencies_file_loc) as csvfile:
reader = csv.reader(csvfile, quotechar='"') reader = csv.reader(csvfile, quotechar='"')
......
import os from os.path import abspath, join
from base_app.models import User
import pandas as pd import pandas as pd
from backend_app.load_data import ASSETS_PATH
from backend_app.models.campus import Campus from backend_app.models.campus import Campus
from backend_app.models.city import City from backend_app.models.city import City
from backend_app.models.country import Country from backend_app.models.country import Country
from backend_app.models.university import University from backend_app.models.university import University
from base_app.models import User
from .loadGeneric import LoadGeneric from .loadGeneric import LoadGeneric
...@@ -20,11 +20,7 @@ class LoadUniversities(LoadGeneric): ...@@ -20,11 +20,7 @@ class LoadUniversities(LoadGeneric):
self.admin = admin self.admin = admin
def load(self): def load(self):
destinations_path = abspath(join(ASSETS_PATH, "destinations_extracted.csv"))
tmp = os.path.join(
os.path.realpath(__file__), "../../assets/destinations_extracted.csv"
)
destinations_path = os.path.abspath(tmp)
data = pd.read_csv(destinations_path, sep=",", header=0, dtype=object).fillna( data = pd.read_csv(destinations_path, sep=",", header=0, dtype=object).fillna(
"" ""
......
...@@ -57,7 +57,7 @@ class LoadUniversityEx(LoadGeneric): ...@@ -57,7 +57,7 @@ class LoadUniversityEx(LoadGeneric):
country_scholarship = CountryScholarship( country_scholarship = CountryScholarship(
title="Swiss European Mobility Programme", title="Swiss European Mobility Programme",
type="Bourse du gouvernement suisse", short_description="Bourse du gouvernement suisse",
currency=CHF, currency=CHF,
frequency="s", frequency="s",
amount_min=2200, amount_min=2200,
......
This source diff could not be displayed because it is too large. You can view the blob instead.
# Generated by Django 2.1.7 on 2019-03-16 11:20
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [("backend_app", "0001_new-initial")]
operations = [
migrations.RenameField(
model_name="countryscholarship",
old_name="type",
new_name="short_description",
),
migrations.RenameField(
model_name="universityscholarship",
old_name="type",
new_name="short_description",
),
]
...@@ -78,7 +78,7 @@ class MyModelSerializer(MySerializerWithJSON): ...@@ -78,7 +78,7 @@ class MyModelSerializer(MySerializerWithJSON):
""" """
Validate `MyModel` fields and enforce certain field at the backend level. Validate `MyModel` fields and enforce certain field at the backend level.
TODO unit test this Checks that the requested moderation level is not higher than the one of the user.
""" """
if "obj_moderation_level" in attrs: if "obj_moderation_level" in attrs:
...@@ -99,10 +99,14 @@ class MyModelSerializer(MySerializerWithJSON): ...@@ -99,10 +99,14 @@ class MyModelSerializer(MySerializerWithJSON):
return attrs return attrs
def set_model_attr_no_moder(self, user, moderated_and_updated): def set_model_attrs_for_moderation_and_update(
self, user, moderated_and_updated: bool
):
""" """
TODO Overrides model attributes regarding moderation and update.
TODO: rename ? The moderated field is set to the request user. The moderated_on field is reset to now.
If there was an updated, the updated_by field and updated_on field are also reset.
""" """
now = timezone.now() now = timezone.now()
self.override_validated_data({"moderated_by": user, "moderated_on": now}) self.override_validated_data({"moderated_by": user, "moderated_on": now})
...@@ -182,7 +186,9 @@ class MyModelSerializer(MySerializerWithJSON): ...@@ -182,7 +186,9 @@ class MyModelSerializer(MySerializerWithJSON):
moderated_and_updated = True moderated_and_updated = True
if self.instance is None: if self.instance is None:
self.set_model_attr_no_moder(user, moderated_and_updated) self.set_model_attrs_for_moderation_and_update(
user, moderated_and_updated
)
instance = super().save(*args, **kwargs) instance = super().save(*args, **kwargs)
else: else:
try: try:
...@@ -208,7 +214,9 @@ class MyModelSerializer(MySerializerWithJSON): ...@@ -208,7 +214,9 @@ class MyModelSerializer(MySerializerWithJSON):
except PendingModeration.DoesNotExist: except PendingModeration.DoesNotExist:
pass pass
self.set_model_attr_no_moder(user, moderated_and_updated) self.set_model_attrs_for_moderation_and_update(
user, moderated_and_updated
)
instance = super().save(*args, **kwargs) instance = super().save(*args, **kwargs)
# Performance optimization to know if has pending moderation # Performance optimization to know if has pending moderation
......
...@@ -84,7 +84,6 @@ class VersionSerializer(MySerializerWithJSON): ...@@ -84,7 +84,6 @@ class VersionSerializer(MySerializerWithJSON):
def get_data(self, obj): def get_data(self, obj):
""" """
Serilizer for the data field Serilizer for the data field
TODO test
""" """
data = obj.serialized_data data = obj.serialized_data
...@@ -99,7 +98,9 @@ class VersionSerializer(MySerializerWithJSON): ...@@ -99,7 +98,9 @@ class VersionSerializer(MySerializerWithJSON):
new_context["view"].action = "list" new_context["view"].action = "list"
return obj_serializer(tmp.object, context=new_context).data return obj_serializer(tmp.object, context=new_context).data
except (DeserializationError, djangoSerializers.SerializerDoesNotExist): except (DeserializationError, djangoSerializers.SerializerDoesNotExist):
obj.delete() # The version is not valid regarding the model, we should delete it ! # The version is not valid regarding the model, we should delete it !
# This might be due to an updated model.
obj.delete()
# Might result in inconsistent nb of versions but that's fine. # Might result in inconsistent nb of versions but that's fine.
return None return None
...@@ -111,7 +112,6 @@ class VersionSerializer(MySerializerWithJSON): ...@@ -111,7 +112,6 @@ class VersionSerializer(MySerializerWithJSON):
class VersionViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): class VersionViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
""" """
Viewset for the versions Viewset for the versions
TODO better presentation
""" """
permission_classes = get_viewset_permissions("VersionViewSet") permission_classes = get_viewset_permissions("VersionViewSet")
......
...@@ -23,8 +23,7 @@ class Scholarship(BasicModule): ...@@ -23,8 +23,7 @@ class Scholarship(BasicModule):
Abstract model for scholarships Abstract model for scholarships
""" """
# TODO change this, don't use python primitive short_description = models.CharField(max_length=200)
type = models.CharField(max_length=200)
currency = models.ForeignKey(Currency, null=True, on_delete=models.PROTECT) currency = models.ForeignKey(Currency, null=True, on_delete=models.PROTECT)
other_advantages = models.CharField(default="", blank=True, max_length=5000) other_advantages = models.CharField(default="", blank=True, max_length=5000)
...@@ -65,11 +64,13 @@ class ScholarshipSerializer(BasicModuleSerializer): ...@@ -65,11 +64,13 @@ class ScholarshipSerializer(BasicModuleSerializer):
raise serializers.ValidationError( raise serializers.ValidationError(
"A currency must be specified when there is a value" "A currency must be specified when there is a value"
) )
if attrs["amount_max"] is not None: if (
if attrs["amount_max"] < attrs["amount_min"]: attrs["amount_max"] is not None
raise serializers.ValidationError( and attrs["amount_max"] < attrs["amount_min"]
"amount_max should be greater or equal than amount_min" ):
) raise serializers.ValidationError(
"amount_max should be greater or equal than amount_min"
)
return attrs return attrs
......
...@@ -18,8 +18,6 @@ class Specialty(MyModel): ...@@ -18,8 +18,6 @@ class Specialty(MyModel):
class Meta: class Meta:
unique_together = ("code", "department") unique_together = ("code", "department")
# TODO add documentation : you should add departement.
class SpecialtySerializer(MyModelSerializer): class SpecialtySerializer(MyModelSerializer):
class Meta: class Meta:
......
...@@ -10,7 +10,7 @@ from backend_app.utils import get_viewset_permissions, get_model_config ...@@ -10,7 +10,7 @@ from backend_app.utils import get_viewset_permissions, get_model_config
class Tag(MyModel): class Tag(MyModel):
""" """
TODO description Model to store available "tags" in the app.
""" """
model_config = get_model_config("Tag") model_config = get_model_config("Tag")
......
...@@ -25,8 +25,6 @@ class PreviousDeparture(MyModel): ...@@ -25,8 +25,6 @@ class PreviousDeparture(MyModel):
is_anonymous = models.BooleanField() is_anonymous = models.BooleanField()
courses = JSONField(null=True) # Store data from ENT courses = JSONField(null=True) # Store data from ENT
# TODO ask the DSI to return an anonymous ID with data so
# when someone delete the link and relink we can rematch the data
class PreviousDepartureSerializer(MyModelSerializer): class PreviousDepartureSerializer(MyModelSerializer):
...@@ -39,4 +37,3 @@ class PreviousDepartureViewSet(MyModelViewSet): ...@@ -39,4 +37,3 @@ class PreviousDepartureViewSet(MyModelViewSet):
permission_classes = get_viewset_permissions("PreviousDepartureViewSet") permission_classes = get_viewset_permissions("PreviousDepartureViewSet")
queryset = PreviousDeparture.objects.all() # pylint: disable=E1101 queryset = PreviousDeparture.objects.all() # pylint: disable=E1101
serializer_class = PreviousDepartureSerializer serializer_class = PreviousDepartureSerializer
# todo if is_anonymous set user to null
...@@ -20,7 +20,6 @@ class PreviousDepartureFeedback(UserRestrictedModule): ...@@ -20,7 +20,6 @@ class PreviousDepartureFeedback(UserRestrictedModule):
integration_comment = models.CharField(default="", blank=True, max_length=5000) integration_comment = models.CharField(default="", blank=True, max_length=5000)
adequation_grate = models.PositiveIntegerField(validators=[MaxValueValidator(20)]) adequation_grate = models.PositiveIntegerField(validators=[MaxValueValidator(20)])
integration_grade = models.PositiveIntegerField(validators=[MaxValueValidator(20)]) integration_grade = models.PositiveIntegerField(validators=[MaxValueValidator(20)])
# TODO check on save that courses are coherent with Previous Departure
class PreviousDepartureFeedbackSerializer(UserRestrictedModuleSerializer): class PreviousDepartureFeedbackSerializer(UserRestrictedModuleSerializer):
......
...@@ -39,4 +39,3 @@ class RecommendationViewSet(UserRestrictedModuleViewSet): ...@@ -39,4 +39,3 @@ class RecommendationViewSet(UserRestrictedModuleViewSet):
permission_classes = get_viewset_permissions("RecommendationViewSet") permission_classes = get_viewset_permissions("RecommendationViewSet")
queryset = Recommendation.objects.all() # pylint: disable=E1101 queryset = Recommendation.objects.all() # pylint: disable=E1101
serializer_class = RecommendationSerializer serializer_class = RecommendationSerializer
# TODO PERMISSIOIN
...@@ -10,7 +10,6 @@ from backend_app.models.abstract.my_model import ( ...@@ -10,7 +10,6 @@ from backend_app.models.abstract.my_model import (
class UserRestrictedModule(MyModel): class UserRestrictedModule(MyModel):
""" """
TODO move to abstract folder ?
""" """
# RGPD made easy with CASCADE # RGPD made easy with CASCADE
...@@ -27,9 +26,7 @@ class UserRestrictedModule(MyModel): ...@@ -27,9 +26,7 @@ class UserRestrictedModule(MyModel):
class UserRestrictedModuleSerializer(MyModelSerializer): class UserRestrictedModuleSerializer(MyModelSerializer):
owner = serializers.HiddenField( owner = serializers.HiddenField(default=serializers.CurrentUserDefault())
default=serializers.CurrentUserDefault()
) # TODO check that this works
class Meta: class Meta:
model = UserRestrictedModule model = UserRestrictedModule
......
...@@ -4,7 +4,8 @@ from backend_app.utils import is_member ...@@ -4,7 +4,8 @@ from backend_app.utils import is_member
class IsDriOrNoPost(permissions.BasePermission): class IsDriOrNoPost(permissions.BasePermission):
""" """
TODO Permission to disallow POST to viewset if request user is not a
member of the DRI group or a staff.
""" """
def has_permission(self, request, view): def has_permission(self, request, view):
......
...@@ -4,7 +4,8 @@ from backend_app.utils import is_member ...@@ -4,7 +4,8 @@ from backend_app.utils import is_member
class IsDriOrReadOnly(permissions.BasePermission): class IsDriOrReadOnly(permissions.BasePermission):
""" """
TODO Permission to make a viewset readonly unless the request user
is a member of the DRI group or staff.
""" """
def has_permission(self, request, view): def has_permission(self, request, view):
......
...@@ -3,7 +3,7 @@ from rest_framework import permissions ...@@ -3,7 +3,7 @@ from rest_framework import permissions
class NoPostIfNotStaff(permissions.BasePermission): class NoPostIfNotStaff(permissions.BasePermission):
""" """
TODO Permission to allow POST request to a viewset only if the user is a member of the staff.
""" """
def has_permission(self, request, view): def has_permission(self, request, view):
......
...@@ -5,7 +5,5 @@ from base_app.models import User ...@@ -5,7 +5,5 @@ from base_app.models import User
def does_user_have_moderation_rights(user: User) -> bool: def does_user_have_moderation_rights(user: User) -> bool:
""" """
Function to know if a user is staff or member of DRI or member of the moderator group. Function to know if a user is staff or member of DRI or member of the moderator group.
TODO unit test
""" """
return user.is_staff or is_member("DRI", user) or is_member("Moderators", user) return user.is_staff or is_member("DRI", user) or is_member("Moderators", user)
...@@ -6,7 +6,6 @@ from shared import OBJ_MODERATION_PERMISSIONS ...@@ -6,7 +6,6 @@ from shared import OBJ_MODERATION_PERMISSIONS
def get_user_level(user: User) -> int: def get_user_level(user: User) -> int:
""" """
Returns the user level as int. Returns the user level as int.
TODO unit test
""" """
if user.is_staff: if user.is_staff:
return OBJ_MODERATION_PERMISSIONS["staff"] return OBJ_MODERATION_PERMISSIONS["staff"]
......
...@@ -4,8 +4,6 @@ from base_app.models import User ...@@ -4,8 +4,6 @@ from base_app.models import User
def is_member(group_name: str, user: User) -> bool: def is_member(group_name: str, user: User) -> bool:
""" """
Function to know if a user is part of a specific group. Function to know if a user is part of a specific group.