mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
Fix Editor filter and view permissions
This commit is contained in:
parent
f4c2731b72
commit
93d56ef4fa
|
@ -1,5 +1,5 @@
|
|||
''' Custom Permission classes.
|
||||
Hierarchy: Anonymous -> User -> Editor -> Owner -> Admin
|
||||
Hierarchy: Anyone -> User -> Editor -> Owner -> Admin
|
||||
'''
|
||||
from typing import Any, cast
|
||||
|
||||
|
@ -66,6 +66,16 @@ class ItemEditor(ItemOwner):
|
|||
return super().has_object_permission(request, view, obj)
|
||||
|
||||
|
||||
class ItemAnyone(ItemEditor):
|
||||
''' Item permission: Anyone if public. '''
|
||||
|
||||
def has_object_permission(self, request: Request, view: APIView, obj: Any) -> bool:
|
||||
item = _extract_item(obj)
|
||||
if item.access_policy == m.AccessPolicy.PUBLIC:
|
||||
return True
|
||||
return super().has_object_permission(request, view, obj)
|
||||
|
||||
|
||||
class EditorMixin(APIView):
|
||||
''' Editor permissions mixin for API views. '''
|
||||
|
||||
|
|
|
@ -36,7 +36,9 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
'load_trs', 'cst_create', 'cst_delete_multiple',
|
||||
'reset_aliases', 'cst_rename', 'cst_substitute'
|
||||
]:
|
||||
permission_list = [permissions.ItemOwner]
|
||||
permission_list = [permissions.ItemEditor]
|
||||
elif self.action in ['contents', 'details', 'export_trs', 'resolve', 'check']:
|
||||
permission_list = [permissions.ItemAnyone]
|
||||
else:
|
||||
permission_list = [permissions.Anyone]
|
||||
return [permission() for permission in permission_list]
|
||||
|
|
|
@ -3,7 +3,7 @@ from django.contrib.auth import authenticate
|
|||
from django.contrib.auth.password_validation import validate_password
|
||||
from rest_framework import serializers
|
||||
|
||||
from apps.rsform.models import Subscription
|
||||
from apps.rsform.models import Editor, Subscription
|
||||
|
||||
from . import messages as msg
|
||||
from . import models
|
||||
|
@ -69,14 +69,16 @@ class AuthSerializer(serializers.Serializer):
|
|||
'id': None,
|
||||
'username': '',
|
||||
'is_staff': False,
|
||||
'subscriptions': []
|
||||
'subscriptions': [],
|
||||
'editor': []
|
||||
}
|
||||
else:
|
||||
return {
|
||||
'id': instance.pk,
|
||||
'username': instance.username,
|
||||
'is_staff': instance.is_staff,
|
||||
'subscriptions': [sub.item.pk for sub in Subscription.objects.filter(user=instance)]
|
||||
'subscriptions': [sub.item.pk for sub in Subscription.objects.filter(user=instance)],
|
||||
'editor': [edit.item.pk for edit in Editor.objects.filter(editor=instance)]
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ class TestUserAPIViews(EndpointTester):
|
|||
self.assertEqual(response.data['username'], self.user.username)
|
||||
self.assertEqual(response.data['is_staff'], self.user.is_staff)
|
||||
self.assertEqual(response.data['subscriptions'], [])
|
||||
self.assertEqual(response.data['editor'], [])
|
||||
|
||||
self.logout()
|
||||
response = self.executeOK()
|
||||
|
@ -51,6 +52,7 @@ class TestUserAPIViews(EndpointTester):
|
|||
self.assertEqual(response.data['username'], '')
|
||||
self.assertEqual(response.data['is_staff'], False)
|
||||
self.assertEqual(response.data['subscriptions'], [])
|
||||
self.assertEqual(response.data['editor'], [])
|
||||
|
||||
|
||||
class TestUserUserProfileAPIView(EndpointTester):
|
||||
|
|
|
@ -112,8 +112,10 @@ class UpdatePassword(views.APIView):
|
|||
if serializer.is_valid():
|
||||
old_password = serializer.data.get("old_password")
|
||||
if not self.object.check_password(old_password):
|
||||
return Response({"old_password": ["Wrong password."]},
|
||||
status=c.HTTP_400_BAD_REQUEST)
|
||||
return Response(
|
||||
{"old_password": ["Wrong password."]},
|
||||
status=c.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
# Note: set_password also hashes the password that the user will get
|
||||
self.object.set_password(serializer.data.get("new_password"))
|
||||
self.object.save()
|
||||
|
|
|
@ -172,7 +172,7 @@ DATABASES = {
|
|||
SPECTACULAR_SETTINGS = {
|
||||
'TITLE': 'ConceptPortal API',
|
||||
'DESCRIPTION': 'Портал для работы с экспликациями концептуальных схем',
|
||||
'VERSION': '0.1.1',
|
||||
'VERSION': '0.1.2',
|
||||
'SERVE_INCLUDE_SCHEMA': False,
|
||||
|
||||
'COMPONENT_SPLIT_PATCH': True,
|
||||
|
|
|
@ -81,7 +81,7 @@ export const LibraryState = ({ children }: LibraryStateProps) => {
|
|||
result = result.filter(item => filter.isSubscribed == user?.subscriptions.includes(item.id));
|
||||
}
|
||||
if (filter.isEditor !== undefined) {
|
||||
// TODO: load editors from backend
|
||||
result = result.filter(item => filter.isEditor == user?.editor.includes(item.id));
|
||||
}
|
||||
if (filter.query) {
|
||||
result = result.filter(item => matchLibraryItem(item, filter.query!));
|
||||
|
|
|
@ -27,6 +27,7 @@ export interface IUser {
|
|||
*/
|
||||
export interface ICurrentUser extends Pick<IUser, 'id' | 'username' | 'is_staff'> {
|
||||
subscriptions: LibraryItemID[];
|
||||
editor: LibraryItemID[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -262,7 +262,7 @@ export function labelLocationHead(head: LocationHead): string {
|
|||
switch (head) {
|
||||
case LocationHead.USER: return 'личные (/U)';
|
||||
case LocationHead.COMMON: return 'общие (/S)';
|
||||
case LocationHead.LIBRARY: return 'неизменные (/L)';
|
||||
case LocationHead.LIBRARY: return 'примеры (/L)';
|
||||
case LocationHead.PROJECTS: return 'проекты (/P)';
|
||||
}
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ export function describeLocationHead(head: LocationHead): string {
|
|||
switch (head) {
|
||||
case LocationHead.USER: return 'Личные схемы пользователя';
|
||||
case LocationHead.COMMON: return 'Рабочий каталог публичных схем';
|
||||
case LocationHead.LIBRARY: return 'Каталог неизменных схем';
|
||||
case LocationHead.LIBRARY: return 'Каталог неизменных схем-примеров';
|
||||
case LocationHead.PROJECTS: return 'Рабочий каталог проектных схем';
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user