Autoupdate on user permission change.
This commit is contained in:
parent
f1c0821dd0
commit
bcc85f9cad
@ -14,13 +14,20 @@ class AssignmentsAppConfig(AppConfig):
|
|||||||
|
|
||||||
# Import all required stuff.
|
# Import all required stuff.
|
||||||
from openslides.core.config import config
|
from openslides.core.config import config
|
||||||
|
from openslides.core.signals import permission_change
|
||||||
from openslides.utils.rest_api import router
|
from openslides.utils.rest_api import router
|
||||||
from .config_variables import get_config_variables
|
from .config_variables import get_config_variables
|
||||||
|
from .signals import get_permission_change_data
|
||||||
from .views import AssignmentViewSet, AssignmentPollViewSet
|
from .views import AssignmentViewSet, AssignmentPollViewSet
|
||||||
|
|
||||||
# Define config variables
|
# Define config variables
|
||||||
config.update_config_variables(get_config_variables())
|
config.update_config_variables(get_config_variables())
|
||||||
|
|
||||||
|
# Connect signals.
|
||||||
|
permission_change.connect(
|
||||||
|
get_permission_change_data,
|
||||||
|
dispatch_uid='assignment_get_permission_change_data')
|
||||||
|
|
||||||
# Register viewsets.
|
# Register viewsets.
|
||||||
router.register(self.get_model('Assignment').get_collection_string(), AssignmentViewSet)
|
router.register(self.get_model('Assignment').get_collection_string(), AssignmentViewSet)
|
||||||
router.register('assignments/poll', AssignmentPollViewSet)
|
router.register('assignments/poll', AssignmentPollViewSet)
|
||||||
|
13
openslides/assignments/signals.py
Normal file
13
openslides/assignments/signals.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
from django.apps import apps
|
||||||
|
|
||||||
|
|
||||||
|
def get_permission_change_data(sender, permissions=None, **kwargs):
|
||||||
|
"""
|
||||||
|
Returns all necessary collections if a 'can_see' permission changes.
|
||||||
|
"""
|
||||||
|
assignments_app = apps.get_app_config(app_label='assignments')
|
||||||
|
for permission in permissions:
|
||||||
|
# There could be only one 'assignment.can_see' and then we want to return data.
|
||||||
|
if permission.content_type.app_label == assignment_app.label and permission.codename == 'can_see':
|
||||||
|
return assignment_app.get_startup_elements()
|
||||||
|
return None
|
@ -18,7 +18,10 @@ class CoreAppConfig(AppConfig):
|
|||||||
from .signals import post_permission_creation
|
from .signals import post_permission_creation
|
||||||
from ..utils.rest_api import router
|
from ..utils.rest_api import router
|
||||||
from .config_variables import get_config_variables
|
from .config_variables import get_config_variables
|
||||||
from .signals import delete_django_app_permissions
|
from .signals import (
|
||||||
|
delete_django_app_permissions,
|
||||||
|
get_permission_change_data,
|
||||||
|
permission_change)
|
||||||
from .views import (
|
from .views import (
|
||||||
ChatMessageViewSet,
|
ChatMessageViewSet,
|
||||||
ConfigViewSet,
|
ConfigViewSet,
|
||||||
@ -35,6 +38,9 @@ class CoreAppConfig(AppConfig):
|
|||||||
post_permission_creation.connect(
|
post_permission_creation.connect(
|
||||||
delete_django_app_permissions,
|
delete_django_app_permissions,
|
||||||
dispatch_uid='delete_django_app_permissions')
|
dispatch_uid='delete_django_app_permissions')
|
||||||
|
permission_change.connect(
|
||||||
|
get_permission_change_data,
|
||||||
|
dispatch_uid='core_get_permission_change_data')
|
||||||
|
|
||||||
# Register viewsets.
|
# Register viewsets.
|
||||||
router.register(self.get_model('Projector').get_collection_string(), ProjectorViewSet)
|
router.register(self.get_model('Projector').get_collection_string(), ProjectorViewSet)
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
|
from django.apps import apps
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.dispatch import Signal
|
from django.dispatch import Signal
|
||||||
|
|
||||||
# This signal is sent when the migrate command is done. That means it is sent
|
# This signal is send when the migrate command is done. That means it is sent
|
||||||
# after post_migrate sending and creating all Permission objects. Don't use it
|
# after post_migrate sending and creating all Permission objects. Don't use it
|
||||||
# for other things than dealing with Permission objects.
|
# for other things than dealing with Permission objects.
|
||||||
post_permission_creation = Signal()
|
post_permission_creation = Signal()
|
||||||
|
|
||||||
|
# This signal is send, if a permission is changed.
|
||||||
|
permission_change = Signal()
|
||||||
|
|
||||||
|
|
||||||
def delete_django_app_permissions(sender, **kwargs):
|
def delete_django_app_permissions(sender, **kwargs):
|
||||||
"""
|
"""
|
||||||
@ -19,3 +23,21 @@ def delete_django_app_permissions(sender, **kwargs):
|
|||||||
Q(app_label='contenttypes') |
|
Q(app_label='contenttypes') |
|
||||||
Q(app_label='sessions'))
|
Q(app_label='sessions'))
|
||||||
Permission.objects.filter(content_type__in=contenttypes).delete()
|
Permission.objects.filter(content_type__in=contenttypes).delete()
|
||||||
|
|
||||||
|
|
||||||
|
def get_permission_change_data(sender, permissions=None, **kwargs):
|
||||||
|
"""
|
||||||
|
Returns all necessary collections if the coupled permission changes.
|
||||||
|
"""
|
||||||
|
from ..utils.collection import Collection
|
||||||
|
core_app = apps.get_app_config(app_label='core')
|
||||||
|
for permission in permissions:
|
||||||
|
# There could be only one 'users.can_see' and then we want to return data.
|
||||||
|
if permission.content_type.app_label == core_app.label:
|
||||||
|
if permission.codename == 'can_see_projector':
|
||||||
|
yield Collection(core_app.get_model('Projector').get_collection_string())
|
||||||
|
elif permission.codename == 'can_manage_projector':
|
||||||
|
yield Collection(core_app.get_model('ProjectorMessage').get_collection_string())
|
||||||
|
yield Collection(core_app.get_model('Countdown').get_collection_string())
|
||||||
|
elif permission.codename == 'can_use_chat':
|
||||||
|
yield Collection(core_app.get_model('ChatMessage').get_collection_string())
|
||||||
|
@ -13,9 +13,16 @@ class MediafilesAppConfig(AppConfig):
|
|||||||
from . import projector # noqa
|
from . import projector # noqa
|
||||||
|
|
||||||
# Import all required stuff.
|
# Import all required stuff.
|
||||||
|
from openslides.core.signals import permission_change
|
||||||
from openslides.utils.rest_api import router
|
from openslides.utils.rest_api import router
|
||||||
|
from .signals import get_permission_change_data
|
||||||
from .views import MediafileViewSet
|
from .views import MediafileViewSet
|
||||||
|
|
||||||
|
# Connect signals.
|
||||||
|
permission_change.connect(
|
||||||
|
get_permission_change_data,
|
||||||
|
dispatch_uid='mediafile_get_permission_change_data')
|
||||||
|
|
||||||
# Register viewsets.
|
# Register viewsets.
|
||||||
router.register(self.get_model('Mediafile').get_collection_string(), MediafileViewSet)
|
router.register(self.get_model('Mediafile').get_collection_string(), MediafileViewSet)
|
||||||
|
|
||||||
|
13
openslides/mediafiles/signals.py
Normal file
13
openslides/mediafiles/signals.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
from django.apps import apps
|
||||||
|
|
||||||
|
|
||||||
|
def get_permission_change_data(sender, permissions=None, **kwargs):
|
||||||
|
"""
|
||||||
|
Returns all necessary collections if a 'can_see' permission changes.
|
||||||
|
"""
|
||||||
|
mediafile_app = apps.get_app_config(app_label='mediafiles')
|
||||||
|
for permission in permissions:
|
||||||
|
# There could be only one 'mediafiles.can_see' and then we want to return data.
|
||||||
|
if permission.content_type.app_label == mediafile_app.label and permission.codename == 'can_see':
|
||||||
|
return mediafile_app.get_startup_elements()
|
||||||
|
return None
|
@ -15,9 +15,10 @@ class MotionsAppConfig(AppConfig):
|
|||||||
|
|
||||||
# Import all required stuff.
|
# Import all required stuff.
|
||||||
from openslides.core.config import config
|
from openslides.core.config import config
|
||||||
|
from openslides.core.signals import permission_change
|
||||||
from openslides.utils.rest_api import router
|
from openslides.utils.rest_api import router
|
||||||
from .config_variables import get_config_variables
|
from .config_variables import get_config_variables
|
||||||
from .signals import create_builtin_workflows
|
from .signals import create_builtin_workflows, get_permission_change_data
|
||||||
from .views import CategoryViewSet, MotionViewSet, MotionBlockViewSet, MotionPollViewSet, MotionChangeRecommendationViewSet, WorkflowViewSet
|
from .views import CategoryViewSet, MotionViewSet, MotionBlockViewSet, MotionPollViewSet, MotionChangeRecommendationViewSet, WorkflowViewSet
|
||||||
|
|
||||||
# Define config variables
|
# Define config variables
|
||||||
@ -25,6 +26,9 @@ class MotionsAppConfig(AppConfig):
|
|||||||
|
|
||||||
# Connect signals.
|
# Connect signals.
|
||||||
post_migrate.connect(create_builtin_workflows, dispatch_uid='motion_create_builtin_workflows')
|
post_migrate.connect(create_builtin_workflows, dispatch_uid='motion_create_builtin_workflows')
|
||||||
|
permission_change.connect(
|
||||||
|
get_permission_change_data,
|
||||||
|
dispatch_uid='motion_get_permission_change_data')
|
||||||
|
|
||||||
# Register viewsets.
|
# Register viewsets.
|
||||||
router.register(self.get_model('Category').get_collection_string(), CategoryViewSet)
|
router.register(self.get_model('Category').get_collection_string(), CategoryViewSet)
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
from django.apps import apps
|
||||||
from django.utils.translation import ugettext_noop
|
from django.utils.translation import ugettext_noop
|
||||||
|
|
||||||
from .models import State, Workflow
|
from .models import State, Workflow
|
||||||
@ -102,3 +103,15 @@ def create_builtin_workflows(sender, **kwargs):
|
|||||||
state_2_2.next_states.add(state_2_3, state_2_4, state_2_5, state_2_6, state_2_7, state_2_8, state_2_9)
|
state_2_2.next_states.add(state_2_3, state_2_4, state_2_5, state_2_6, state_2_7, state_2_8, state_2_9)
|
||||||
workflow_2.first_state = state_2_1
|
workflow_2.first_state = state_2_1
|
||||||
workflow_2.save()
|
workflow_2.save()
|
||||||
|
|
||||||
|
|
||||||
|
def get_permission_change_data(sender, permissions=None, **kwargs):
|
||||||
|
"""
|
||||||
|
Returns all necessary collections if a 'can_see' permission changes.
|
||||||
|
"""
|
||||||
|
motion_app = apps.get_app_config(app_label='motions')
|
||||||
|
for permission in permissions:
|
||||||
|
# There could be only one 'motion.can_see' and then we want to return data.
|
||||||
|
if permission.content_type.app_label == motion_app.label and permission.codename == 'can_see':
|
||||||
|
return motion_app.get_startup_elements()
|
||||||
|
return None
|
||||||
|
@ -14,10 +14,10 @@ class UsersAppConfig(AppConfig):
|
|||||||
|
|
||||||
# Import all required stuff.
|
# Import all required stuff.
|
||||||
from ..core.config import config
|
from ..core.config import config
|
||||||
from ..core.signals import post_permission_creation
|
from ..core.signals import post_permission_creation, permission_change
|
||||||
from ..utils.rest_api import router
|
from ..utils.rest_api import router
|
||||||
from .config_variables import get_config_variables
|
from .config_variables import get_config_variables
|
||||||
from .signals import create_builtin_groups_and_admin
|
from .signals import create_builtin_groups_and_admin, get_permission_change_data
|
||||||
from .views import GroupViewSet, UserViewSet
|
from .views import GroupViewSet, UserViewSet
|
||||||
|
|
||||||
# Define config variables
|
# Define config variables
|
||||||
@ -27,6 +27,9 @@ class UsersAppConfig(AppConfig):
|
|||||||
post_permission_creation.connect(
|
post_permission_creation.connect(
|
||||||
create_builtin_groups_and_admin,
|
create_builtin_groups_and_admin,
|
||||||
dispatch_uid='create_builtin_groups_and_admin')
|
dispatch_uid='create_builtin_groups_and_admin')
|
||||||
|
permission_change.connect(
|
||||||
|
get_permission_change_data,
|
||||||
|
dispatch_uid='user_get_permission_change_data')
|
||||||
|
|
||||||
# Register viewsets.
|
# Register viewsets.
|
||||||
router.register(self.get_model('User').get_collection_string(), UserViewSet)
|
router.register(self.get_model('User').get_collection_string(), UserViewSet)
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
from django.apps import apps
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
|
||||||
@ -5,6 +6,18 @@ from ..utils.autoupdate import inform_changed_data
|
|||||||
from .models import Group, User
|
from .models import Group, User
|
||||||
|
|
||||||
|
|
||||||
|
def get_permission_change_data(sender, permissions=None, **kwargs):
|
||||||
|
"""
|
||||||
|
Returns all necessary collections if a 'can_see' permission changes.
|
||||||
|
"""
|
||||||
|
user_app = apps.get_app_config(app_label='users')
|
||||||
|
for permission in permissions:
|
||||||
|
# There could be only one 'users.can_see' and then we want to return data.
|
||||||
|
if permission.content_type.app_label == user_app.label and permission.codename == 'can_see':
|
||||||
|
return user_app.get_startup_elements()
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def create_builtin_groups_and_admin(**kwargs):
|
def create_builtin_groups_and_admin(**kwargs):
|
||||||
"""
|
"""
|
||||||
Creates the builtin groups: Default, Delegates, Staff and Committees.
|
Creates the builtin groups: Default, Delegates, Staff and Committees.
|
||||||
|
@ -6,7 +6,9 @@ from django.utils.encoding import force_text
|
|||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from ..core.config import config
|
from ..core.config import config
|
||||||
|
from ..core.signals import permission_change
|
||||||
from ..utils.auth import anonymous_is_enabled, has_perm
|
from ..utils.auth import anonymous_is_enabled, has_perm
|
||||||
|
from ..utils.autoupdate import send_collections_to_users, inform_changed_data
|
||||||
from ..utils.collection import CollectionElement
|
from ..utils.collection import CollectionElement
|
||||||
from ..utils.rest_api import (
|
from ..utils.rest_api import (
|
||||||
ModelViewSet,
|
ModelViewSet,
|
||||||
@ -19,7 +21,7 @@ from ..utils.rest_api import (
|
|||||||
from ..utils.views import APIView
|
from ..utils.views import APIView
|
||||||
from .access_permissions import GroupAccessPermissions, UserAccessPermissions
|
from .access_permissions import GroupAccessPermissions, UserAccessPermissions
|
||||||
from .models import Group, User
|
from .models import Group, User
|
||||||
from .serializers import GroupSerializer
|
from .serializers import GroupSerializer, PermissionRelatedField
|
||||||
|
|
||||||
|
|
||||||
# Viewsets for the REST API
|
# Viewsets for the REST API
|
||||||
@ -169,6 +171,42 @@ class GroupViewSet(ModelViewSet):
|
|||||||
self.perform_destroy(instance)
|
self.perform_destroy(instance)
|
||||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||||
|
|
||||||
|
def update(self, request, *args, **kwargs):
|
||||||
|
# Collect old and new permissions to get the difference.
|
||||||
|
permission_names = request.data['permissions']
|
||||||
|
if isinstance(permission_names, str):
|
||||||
|
permission_names = [permission_names]
|
||||||
|
|
||||||
|
permissionSerializer = PermissionRelatedField(read_only=True)
|
||||||
|
given_permissions = [
|
||||||
|
permissionSerializer.to_internal_value(data=perm) for perm in permission_names]
|
||||||
|
group = Group.objects.get(pk=int(kwargs['pk']))
|
||||||
|
old_permissions = list(group.permissions.all()) # Force evaluation so the perms doesn't change.
|
||||||
|
|
||||||
|
response = super().update(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def diff(first, second):
|
||||||
|
"""
|
||||||
|
This helper function calculates the difference of two lists: first-second.
|
||||||
|
"""
|
||||||
|
second = set(second)
|
||||||
|
return [item for item in first if item not in second]
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
new_permissions = diff(given_permissions, old_permissions)
|
||||||
|
|
||||||
|
# some permissions are added
|
||||||
|
if(len(new_permissions) > 0):
|
||||||
|
signal_results = permission_change.send(None, action='added', permissions=new_permissions)
|
||||||
|
collections_to_send = []
|
||||||
|
for (receiver, signal_collections) in signal_results:
|
||||||
|
if signal_collections:
|
||||||
|
collections_to_send.extend(signal_collections)
|
||||||
|
#send_collections_to_users(collections_to_send, [user.id for user in group.user_set.all()])
|
||||||
|
# inform_changed_data(what?)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
# Special API views
|
# Special API views
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ def send_data(message):
|
|||||||
user = None
|
user = None
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
user = CollectionElement.from_values('users/user', user_id)
|
user = user_to_collection_user(user_id)
|
||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
# The user does not exist. Skip him/her.
|
# The user does not exist. Skip him/her.
|
||||||
continue
|
continue
|
||||||
@ -187,6 +187,21 @@ def send_data(message):
|
|||||||
{'text': json.dumps(output)})
|
{'text': json.dumps(output)})
|
||||||
|
|
||||||
|
|
||||||
|
def send_collections_to_users(collections, users_ids):
|
||||||
|
for user_id, channel_names in websocket_user_cache.get_all().items():
|
||||||
|
if user_id in users_ids:
|
||||||
|
try:
|
||||||
|
user = user_to_collection_user(user_id)
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
# The user does not exist. Skip him/her.
|
||||||
|
continue
|
||||||
|
output = []
|
||||||
|
for collection in collections:
|
||||||
|
output.extend(collection.as_autoupdate_for_user(user))
|
||||||
|
for channel_name in channel_names:
|
||||||
|
send_or_wait(Channel(channel_name).send, {'text': json.dumps(output)})
|
||||||
|
|
||||||
|
|
||||||
def inform_changed_data(instances, information=None):
|
def inform_changed_data(instances, information=None):
|
||||||
"""
|
"""
|
||||||
Informs the autoupdate system and the caching system about the creation or
|
Informs the autoupdate system and the caching system about the creation or
|
||||||
|
Loading…
Reference in New Issue
Block a user