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

Big Update : moderation and viewset permissions centralized

parent e9e8ecbe
from rest_framework import permissions
class IsAdminOrReadOnly(permissions.BasePermission):
class IsStaffOrReadOnly(permissions.BasePermission):
def has_permission(self, request, view):
if request.user.is_staff:
......
from rest_framework.permissions import BasePermission
class NoDeleteIfNotAdmin(BasePermission):
class NoDeleteIfNotStaff(BasePermission):
def has_permission(self, request, view):
if (not request.user.is_staff) and request.method == 'DELETE':
......
......@@ -227,7 +227,8 @@ class ModerationTestCase(WithUserTestCase):
}
api_end_point = "/api/" + \
find_api_end_point_for_viewset("UniversityDriViewSet") + "/"
self._submit_post_test(self.authenticated_client,
print(api_end_point)
self._submit_post_test(self.dri_client,
data, api_end_point)
# instance = self._test_retreive_instance(data_1)
......
......@@ -29,6 +29,17 @@ class WithUserTestCase(TestCase):
cls.moderator_group.user_set.add(cls.moderator_user)
cls.moderator_group.save()
cls.dri_user = User.objects.create_user(
username='dri_member',
email='dri@dri.fr',
password=password
)
cls.dri_group = Group.objects.get_or_create(
name='DRI'
)[0]
cls.dri_group.user_set.add(cls.dri_user)
cls.dri_group.save()
cls.authenticated_user = User.objects.create_user(
username='authenticated_user',
email='authenticated@authenticated.fr',
......@@ -53,6 +64,12 @@ class WithUserTestCase(TestCase):
password=password
)
cls.dri_client = APIClient()
cls.dri_client.login(
username=cls.dri_user.username,
password=password
)
cls.authenticated_client = APIClient()
cls.authenticated_client.login(
username=cls.authenticated_user.username,
......
from .is_member import is_member # noqa: F401
from .file import read_file, write_file # noqa: F401
from .find_api_end_point_for_viewset import find_api_end_point_for_viewset # noqa: F401
from .get_moderation_level import get_moderation_level # noqa: F401
from .get_viewset_permissions import get_viewset_permissions # noqa: F401
import yaml
from os.path import join, realpath, dirname
from backend.utils import read_file
from general.api import get_api_config
def find_api_end_point_for_viewset(viewset_name):
current_dir = dirname(realpath(__file__))
api_config = yaml.load(
read_file(join(current_dir, '../generate/api_config.yml')))
api_config = get_api_config()
for obj in api_config:
if obj['viewset'] == viewset_name:
return obj['api_end_point']
......
import yaml
from os.path import join, realpath, dirname
def get_moderation_level(model):
current_dir = dirname(realpath(__file__))
api_file_loc = join(current_dir, '../../general/api/api_config.yml')
with open(api_file_loc, "r") as file:
api_config = yaml.load(file.read())
for obj in api_config:
if obj['model'] == model:
try:
return obj["moderation_level"]
except KeyError:
return 2
raise Exception("Model not found in API configuraiton, cannot process !")
import yaml
from os.path import join, realpath, dirname
from backend.permissions import IsOwner, IsStaffOrReadOnly, IsDriOrReadOnly
from rest_framework.permissions import IsAdminUser
from backend.permissions import DEFAULT_VIEWSET_PERMISSIONS
def get_viewset_permissions(viewset):
current_dir = dirname(realpath(__file__))
api_file_loc = join(current_dir, '../../general/api/api_config.yml')
with open(api_file_loc, "r") as file:
api_config = yaml.load(file.read())
for obj in api_config:
if obj['viewset'] == viewset:
try:
custom_permission = obj["viewset_permission"]
if custom_permission == "IsOwner":
permission = (IsOwner,)
elif custom_permission == "IsStaffOrReadOnly":
permission = (IsStaffOrReadOnly,)
elif custom_permission == "IsDriOrReadOnly":
permission = (IsDriOrReadOnly,)
elif custom_permission == "IsStaff":
permission = (IsAdminUser,)
else:
raise Exception(
"Permission not supported ! Dev what did you do ?")
return DEFAULT_VIEWSET_PERMISSIONS + permission
except KeyError:
return DEFAULT_VIEWSET_PERMISSIONS
raise Exception("Viewset not found in API configuraiton, cannot process !")
from .get_api_config import get_api_config # noqa: F401
......@@ -13,27 +13,50 @@
# requires_testing: boolean to tell if this viewset is only availble in
# a testing environment.
# Moderation levels are defined as follow :
# 0 : moderation will never be applied
# 1 : moderation will be on if the global settings for moderation is turned on
# 2 : (default for security reasons) moderation will always be on no matter what
# It is to be noted that staff members, dri members and moderators won't be subject to moderation !
# Dri might want to switch moderation on some models. TODO
# For viewset permissions we have the followings
#
# By default, every viewset will have :
# - isAuthentificated : to use the API the client needs to be authentificated
# - noDeleteIsNotStaff : nothing can be deleted except if you are a staff member
#
# Some viewsets may have more presice permissions
# - IsStaff
# - IsStaffOrReadOnly
# - IsDriOrReadOnly
# - IsOwner : (or )
#
- model: Country
viewset: CountryViewSet
import_location: location
api_end_point: countries
viewset_permission: IsStaffOrReadOnly
- model: City
viewset: CityViewSet
import_location: location
api_end_point: cities
moderation_level: 2
- model: University
viewset: UniversityViewSet
import_location: university
api_end_point: universities
moderation_level: 2
- model: Campus
viewset: CampusViewSet
import_location: university
api_end_point: campuses
versionned: true
moderation_level: 2
- model: UserData
......@@ -41,38 +64,51 @@
import_location: user
api_end_point: userData
api_name: user-data-detail
moderation_level: 0
viewset_permission: IsOwner
- model: Tag
viewset: TagViewSet
import_location: tag
api_end_point: tags
moderation_level: 2
viewset_permission: IsStaffOrReadOnly
- model: Currency
viewset: CurrencyViewSet
import_location: location
api_end_point: currencies
moderation_level: 2
viewset_permission: IsStaffOrReadOnly
- model: Department
viewset: DepartmentViewSet
import_location: other_core
api_end_point: departments
moderation_level: 2
viewset_permission: IsStaffOrReadOnly
- model: Specialty
viewset: SpecialtyViewSet
import_location: other_core
api_end_point: specialties
moderation_level: 2
viewset_permission: IsStaffOrReadOnly
- model: Semester
viewset: SemesterViewSet
import_location: other_core
api_end_point: semesters
moderation_level: 2
viewset_permission: IsStaffOrReadOnly
- model: Offer
viewset: OfferViewSet
import_location: other_core
api_end_point: offers
moderation_level: 2
viewset_permission: IsStaffOrReadOnly
- model: CountryTaggedItem
......@@ -91,6 +127,7 @@
viewset: CountryDriViewSet
import_location: location
api_end_point: countriesDri
viewset_permission: IsDriOrReadOnly
versionned: true
......@@ -131,6 +168,7 @@
viewset: UniversityDriViewSet
import_location: university
api_end_point: universitiesDri
viewset_permission: IsDriOrReadOnly
versionned: true
- model: null
......@@ -160,16 +198,19 @@
viewset: RecommendationViewSet
import_location: user
api_end_point: userRecommendations
moderation_level: 0
- model: RecommendationList
viewset: RecommendationListViewSet
import_location: user
api_end_point: userRecommendationLists
moderation_level: 0
- model: PreviousDeparture
viewset: PreviousDepartureViewSet
import_location: user
api_end_point: universitiesPreviousDepartures
moderation_level: 2
- model: PreviousDepartureFeedback
viewset: PreviousDepartureFeedbackViewSet
......@@ -182,6 +223,8 @@
viewset: PendingModerationViewSet
import_location: my_model
api_end_point: pendingModeration
viewset_permission: IsStaff
- model: Version
viewset: VersionViewSet
......@@ -195,11 +238,13 @@
viewset: ForTestingModerationViewSet
import_location: my_model
api_end_point: test/moderation
moderation_level: 1
requires_testing: true
- model: ForTestingVersioning
viewset: ForTestingVersioningViewSet
import_location: my_model
api_end_point: test/versioning
moderation_level: 1
requires_testing: true
# versionned: true don't put it here, it is manually handled with @register decorator
import yaml
from os.path import join, realpath, dirname
def get_api_config():
current_dir = dirname(realpath(__file__))
with open(join(current_dir, 'api_config.yml'), 'r') as f:
api_config = yaml.load(f)
# clean api_config (add default arguments)
DEFAULT_SETTINGS = {
"ignore_in_admin": False,
"requires_testing": False,
"moderation_lebel": 2
}
for obj in api_config:
for key in DEFAULT_SETTINGS:
if key not in obj:
obj[key] = DEFAULT_SETTINGS[key]
return api_config
Supports Markdown
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