2019-07-10 15:54:17 +02:00
|
|
|
import hashlib
|
|
|
|
import logging
|
2019-01-20 10:05:50 +01:00
|
|
|
import os
|
2018-11-15 15:15:07 +01:00
|
|
|
import sys
|
2018-01-20 15:58:36 +01:00
|
|
|
from collections import OrderedDict
|
|
|
|
from operator import attrgetter
|
2019-03-26 15:42:43 +01:00
|
|
|
from typing import Any, Dict, List
|
2018-01-20 15:58:36 +01:00
|
|
|
|
2014-11-13 22:23:16 +01:00
|
|
|
from django.apps import AppConfig
|
2017-01-20 10:23:14 +01:00
|
|
|
from django.conf import settings
|
2019-04-15 13:30:18 +02:00
|
|
|
from django.db.models import Max
|
2019-01-20 13:06:38 +01:00
|
|
|
from django.db.models.signals import post_migrate, pre_delete
|
2014-11-13 22:23:16 +01:00
|
|
|
|
|
|
|
|
2019-07-10 15:54:17 +02:00
|
|
|
logger = logging.getLogger("openslides.core")
|
|
|
|
|
|
|
|
|
2014-11-13 22:23:16 +01:00
|
|
|
class CoreAppConfig(AppConfig):
|
2019-01-06 16:22:33 +01:00
|
|
|
name = "openslides.core"
|
|
|
|
verbose_name = "OpenSlides Core"
|
2014-11-13 22:23:16 +01:00
|
|
|
|
|
|
|
def ready(self):
|
|
|
|
# Import all required stuff.
|
2017-01-14 12:29:42 +01:00
|
|
|
from .config import config
|
2019-01-27 13:17:17 +01:00
|
|
|
from .projector import register_projector_slides
|
2018-11-05 09:04:41 +01:00
|
|
|
from . import serializers # noqa
|
2017-02-21 09:34:24 +01:00
|
|
|
from .signals import (
|
2019-01-20 13:06:38 +01:00
|
|
|
autoupdate_for_many_to_many_relations,
|
2017-02-21 09:34:24 +01:00
|
|
|
delete_django_app_permissions,
|
|
|
|
get_permission_change_data,
|
2017-04-10 16:28:38 +02:00
|
|
|
permission_change,
|
2018-02-02 13:51:19 +01:00
|
|
|
post_permission_creation,
|
|
|
|
)
|
2015-06-29 12:08:15 +02:00
|
|
|
from .views import (
|
|
|
|
ConfigViewSet,
|
2016-10-21 11:05:24 +02:00
|
|
|
CountdownViewSet,
|
|
|
|
ProjectorMessageViewSet,
|
2015-06-29 12:08:15 +02:00
|
|
|
ProjectorViewSet,
|
2019-03-26 14:57:04 +01:00
|
|
|
ProjectionDefaultViewSet,
|
2015-06-29 12:08:15 +02:00
|
|
|
TagViewSet,
|
|
|
|
)
|
2018-10-26 15:37:29 +02:00
|
|
|
from .websocket import (
|
|
|
|
NotifyWebsocketClientMessage,
|
|
|
|
ConstantsWebsocketClientMessage,
|
|
|
|
GetElementsWebsocketClientMessage,
|
|
|
|
AutoupdateWebsocketClientMessage,
|
2018-12-23 11:05:38 +01:00
|
|
|
ListenToProjectors,
|
2019-04-15 14:19:40 +02:00
|
|
|
PingPong,
|
2018-10-26 15:37:29 +02:00
|
|
|
)
|
2018-12-23 11:05:38 +01:00
|
|
|
from ..utils.rest_api import router
|
|
|
|
from ..utils.websocket import register_client_message
|
2018-08-30 09:07:06 +02:00
|
|
|
|
2018-09-10 08:15:31 +02:00
|
|
|
# Collect all config variables before getting the constants.
|
|
|
|
config.collect_config_variables_from_apps()
|
|
|
|
|
|
|
|
# Define projector elements.
|
2019-01-27 13:17:17 +01:00
|
|
|
register_projector_slides()
|
2016-06-02 12:47:01 +02:00
|
|
|
|
2014-11-13 22:23:16 +01:00
|
|
|
# Connect signals.
|
2016-01-25 14:48:00 +01:00
|
|
|
post_permission_creation.connect(
|
2019-01-06 16:22:33 +01:00
|
|
|
delete_django_app_permissions, dispatch_uid="delete_django_app_permissions"
|
|
|
|
)
|
2017-02-21 09:34:24 +01:00
|
|
|
permission_change.connect(
|
2019-01-06 16:22:33 +01:00
|
|
|
get_permission_change_data, dispatch_uid="core_get_permission_change_data"
|
|
|
|
)
|
2014-11-13 22:23:16 +01:00
|
|
|
|
2019-01-06 16:22:33 +01:00
|
|
|
post_migrate.connect(
|
2019-07-10 15:54:17 +02:00
|
|
|
manage_config, sender=self, dispatch_uid="core_manage_config"
|
2019-01-06 16:22:33 +01:00
|
|
|
)
|
2019-01-20 13:06:38 +01:00
|
|
|
pre_delete.connect(
|
|
|
|
autoupdate_for_many_to_many_relations,
|
|
|
|
dispatch_uid="core_autoupdate_for_many_to_many_relations",
|
|
|
|
)
|
2017-08-22 14:17:20 +02:00
|
|
|
|
2015-01-17 14:25:05 +01:00
|
|
|
# Register viewsets.
|
2019-01-06 16:22:33 +01:00
|
|
|
router.register(
|
|
|
|
self.get_model("Projector").get_collection_string(), ProjectorViewSet
|
|
|
|
)
|
2019-03-26 14:57:04 +01:00
|
|
|
router.register(
|
|
|
|
self.get_model("Projectiondefault").get_collection_string(),
|
|
|
|
ProjectionDefaultViewSet,
|
|
|
|
)
|
2019-01-06 16:22:33 +01:00
|
|
|
router.register(self.get_model("Tag").get_collection_string(), TagViewSet)
|
|
|
|
router.register(
|
|
|
|
self.get_model("ConfigStore").get_collection_string(),
|
|
|
|
ConfigViewSet,
|
|
|
|
"config",
|
|
|
|
)
|
|
|
|
router.register(
|
|
|
|
self.get_model("ProjectorMessage").get_collection_string(),
|
|
|
|
ProjectorMessageViewSet,
|
|
|
|
)
|
|
|
|
router.register(
|
|
|
|
self.get_model("Countdown").get_collection_string(), CountdownViewSet
|
|
|
|
)
|
2015-01-17 14:01:44 +01:00
|
|
|
|
2019-03-19 20:26:12 +01:00
|
|
|
if "runserver" in sys.argv or "changeconfig" in sys.argv:
|
2019-01-20 10:05:50 +01:00
|
|
|
startup()
|
2018-09-01 08:00:00 +02:00
|
|
|
|
2018-10-26 15:37:29 +02:00
|
|
|
# Register client messages
|
|
|
|
register_client_message(NotifyWebsocketClientMessage())
|
|
|
|
register_client_message(ConstantsWebsocketClientMessage())
|
|
|
|
register_client_message(GetElementsWebsocketClientMessage())
|
|
|
|
register_client_message(AutoupdateWebsocketClientMessage())
|
2018-12-23 11:05:38 +01:00
|
|
|
register_client_message(ListenToProjectors())
|
2019-04-15 14:19:40 +02:00
|
|
|
register_client_message(PingPong())
|
2018-10-26 15:37:29 +02:00
|
|
|
|
2018-09-10 08:15:31 +02:00
|
|
|
def get_config_variables(self):
|
|
|
|
from .config_variables import get_config_variables
|
2019-01-06 16:22:33 +01:00
|
|
|
|
2018-09-10 08:15:31 +02:00
|
|
|
return get_config_variables()
|
|
|
|
|
2017-01-14 12:29:42 +01:00
|
|
|
def get_startup_elements(self):
|
2017-03-06 16:34:20 +01:00
|
|
|
"""
|
2018-07-09 23:22:26 +02:00
|
|
|
Yields all Cachables required on startup i. e. opening the websocket
|
2017-03-06 16:34:20 +01:00
|
|
|
connection.
|
|
|
|
"""
|
2019-01-06 16:22:33 +01:00
|
|
|
for model_name in (
|
|
|
|
"Projector",
|
2019-03-26 14:57:04 +01:00
|
|
|
"ProjectionDefault",
|
2019-01-06 16:22:33 +01:00
|
|
|
"Tag",
|
|
|
|
"ProjectorMessage",
|
|
|
|
"Countdown",
|
|
|
|
"ConfigStore",
|
|
|
|
):
|
2018-07-09 23:22:26 +02:00
|
|
|
yield self.get_model(model_name)
|
2017-01-20 10:23:14 +01:00
|
|
|
|
|
|
|
def get_angular_constants(self):
|
2018-01-20 15:58:36 +01:00
|
|
|
from .config import config
|
|
|
|
|
2018-08-29 15:49:44 +02:00
|
|
|
constants: Dict[str, Any] = {}
|
|
|
|
|
2017-01-20 10:23:14 +01:00
|
|
|
# Client settings
|
|
|
|
client_settings_keys = [
|
2019-01-06 16:22:33 +01:00
|
|
|
"MOTION_IDENTIFIER_MIN_DIGITS",
|
|
|
|
"MOTION_IDENTIFIER_WITHOUT_BLANKS",
|
|
|
|
"MOTIONS_ALLOW_AMENDMENTS_OF_AMENDMENTS",
|
2019-04-15 14:19:40 +02:00
|
|
|
"PRIORITIZED_GROUP_IDS",
|
|
|
|
"PING_INTERVAL",
|
|
|
|
"PING_TIMEOUT",
|
2017-01-20 10:23:14 +01:00
|
|
|
]
|
|
|
|
client_settings_dict = {}
|
|
|
|
for key in client_settings_keys:
|
|
|
|
try:
|
|
|
|
client_settings_dict[key] = getattr(settings, key)
|
|
|
|
except AttributeError:
|
|
|
|
# Settings key does not exist. Do nothing. The client will
|
|
|
|
# treat this as undefined.
|
|
|
|
pass
|
2019-04-15 13:30:18 +02:00
|
|
|
constants["Settings"] = client_settings_dict
|
2018-01-20 15:58:36 +01:00
|
|
|
|
|
|
|
# Config variables
|
2018-08-22 22:00:08 +02:00
|
|
|
config_groups: List[Any] = []
|
2019-01-06 16:22:33 +01:00
|
|
|
for config_variable in sorted(
|
|
|
|
config.config_variables.values(), key=attrgetter("weight")
|
|
|
|
):
|
2018-01-20 15:58:36 +01:00
|
|
|
if config_variable.is_hidden():
|
|
|
|
# Skip hidden config variables. Do not even check groups and subgroups.
|
|
|
|
continue
|
2019-01-06 16:22:33 +01:00
|
|
|
if not config_groups or config_groups[-1]["name"] != config_variable.group:
|
2018-01-20 15:58:36 +01:00
|
|
|
# Add new group.
|
2019-01-06 16:22:33 +01:00
|
|
|
config_groups.append(
|
|
|
|
OrderedDict(name=config_variable.group, subgroups=[])
|
|
|
|
)
|
|
|
|
if (
|
|
|
|
not config_groups[-1]["subgroups"]
|
|
|
|
or config_groups[-1]["subgroups"][-1]["name"]
|
|
|
|
!= config_variable.subgroup
|
|
|
|
):
|
2018-01-20 15:58:36 +01:00
|
|
|
# Add new subgroup.
|
2019-01-06 16:22:33 +01:00
|
|
|
config_groups[-1]["subgroups"].append(
|
|
|
|
OrderedDict(name=config_variable.subgroup, items=[])
|
|
|
|
)
|
2018-01-20 15:58:36 +01:00
|
|
|
# Add the config variable to the current group and subgroup.
|
2019-01-06 16:22:33 +01:00
|
|
|
config_groups[-1]["subgroups"][-1]["items"].append(config_variable.data)
|
2019-04-15 13:30:18 +02:00
|
|
|
constants["ConfigVariables"] = config_groups
|
|
|
|
|
|
|
|
# get max migration id -> the "version" of the DB
|
|
|
|
from django.db.migrations.recorder import MigrationRecorder
|
|
|
|
|
2019-07-10 15:54:17 +02:00
|
|
|
migration_version = MigrationRecorder.Migration.objects.aggregate(Max("id"))[
|
|
|
|
"id__max"
|
|
|
|
]
|
|
|
|
config_version = config["config_version"]
|
|
|
|
hash = hashlib.sha1(
|
|
|
|
f"{migration_version}#{config_version}".encode()
|
|
|
|
).hexdigest()
|
|
|
|
constants["DbSchemaVersion"] = hash
|
|
|
|
logger.info(f"DbSchemaVersion={hash}")
|
2018-01-20 15:58:36 +01:00
|
|
|
|
2018-08-29 15:49:44 +02:00
|
|
|
return constants
|
2017-08-22 14:17:20 +02:00
|
|
|
|
|
|
|
|
2019-07-10 15:54:17 +02:00
|
|
|
def manage_config(**kwargs):
|
|
|
|
"""
|
|
|
|
Should be run after every migration. Saves default values
|
|
|
|
of all non db-existing config objects into the db. Deletes all
|
|
|
|
unnecessary old config values, e.g. all db entries, that does
|
|
|
|
not have a config_variable anymore. Increments the config version,
|
|
|
|
if at least one of the operations altered some data.
|
|
|
|
"""
|
2017-08-22 14:17:20 +02:00
|
|
|
from .config import config
|
2019-01-06 16:22:33 +01:00
|
|
|
|
2019-07-10 15:54:17 +02:00
|
|
|
altered = config.save_default_values()
|
|
|
|
altered = config.cleanup_old_config_values() or altered
|
|
|
|
if altered:
|
|
|
|
config.increment_version()
|
2018-11-01 17:30:18 +01:00
|
|
|
|
|
|
|
|
2019-01-20 10:05:50 +01:00
|
|
|
def startup():
|
|
|
|
"""
|
|
|
|
Runs commands that are needed at startup.
|
|
|
|
|
|
|
|
Sets the cache, constants and startup history
|
|
|
|
"""
|
|
|
|
if os.environ.get("NO_STARTUP"):
|
|
|
|
return
|
|
|
|
|
|
|
|
from openslides.utils.constants import set_constants, get_constants_from_apps
|
|
|
|
from openslides.utils.cache import element_cache
|
|
|
|
from openslides.core.models import History
|
|
|
|
|
|
|
|
element_cache.ensure_cache()
|
2019-07-10 15:54:17 +02:00
|
|
|
set_constants(get_constants_from_apps())
|
2019-01-20 10:05:50 +01:00
|
|
|
History.objects.build_history()
|