diff --git a/decide/base/helpers.py b/decide/base/helpers.py new file mode 100644 index 000000000..a96fd92fc --- /dev/null +++ b/decide/base/helpers.py @@ -0,0 +1,22 @@ +from django.apps import apps +from django.conf import settings +from django.db import router + + +def is_valid_app(app_label: str) -> bool: + return apps.is_installed(app_label) and app_label in settings.APIS + + +def is_same_api(app_label_1: str, app_label_2: str) -> bool: + return settings.APIS.get(app_label_1) == settings.APIS.get(app_label_2) + + +def is_same_database(model_1, model_2) -> bool: + return router.db_for_read(model_1) == router.db_for_read(model_2) + + +def is_possible_connect_apps(app_label_1: str, app_label_2: str) -> bool: + if not is_valid_app(app_label_1) or not is_valid_app(app_label_2): + return False + + return is_same_api(app_label_1, app_label_2) diff --git a/decide/voting/admin.py b/decide/voting/admin.py index dff206a94..d4533d256 100644 --- a/decide/voting/admin.py +++ b/decide/voting/admin.py @@ -1,13 +1,28 @@ +from django.conf import settings from django.contrib import admin from django.utils import timezone +from base.helpers import is_possible_connect_apps, is_same_database from .models import QuestionOption from .models import Question -from .models import Voting +from .models import CensusLocal, Voting, VotingLocal from .filters import StartedFilter +try: + from census.models import Census +except ImportError: + CENSUS_LOCAL_AVAILABLE = False +else: + CENSUS_LOCAL_AVAILABLE = ( + is_possible_connect_apps('voting', 'census') + and is_same_database(Census, Voting) + and is_possible_connect_apps('voting', 'authentication') + and is_same_database(Census, settings.AUTH_USER_MODEL) + ) + + def start(modeladmin, request, queryset): for v in queryset.all(): v.create_pubkey() @@ -46,5 +61,28 @@ class VotingAdmin(admin.ModelAdmin): actions = [ start, stop, tally ] +class CensusInline(admin.TabularInline): + model = CensusLocal + fk_name = 'voting' + extra = 1 + autocomplete_fields = ('voter',) + + +class VotingCensusAdmin(admin.ModelAdmin): + list_display = ('name',) + + def get_inlines(self, request, obj): + return [CensusInline] + + def has_add_permission(self, request): + return False + + def has_delete_permission(self, request, obj=None): + return False + + +if CENSUS_LOCAL_AVAILABLE: + admin.site.register(VotingLocal, VotingCensusAdmin) + admin.site.register(Voting, VotingAdmin) admin.site.register(Question, QuestionAdmin) diff --git a/decide/voting/models.py b/decide/voting/models.py index 802c8a375..c2dd53202 100644 --- a/decide/voting/models.py +++ b/decide/voting/models.py @@ -1,7 +1,6 @@ +from django.conf import settings from django.db import models from django.db.models import JSONField -from django.db.models.signals import post_save -from django.dispatch import receiver from base import mods from base.models import Auth, Key @@ -131,3 +130,39 @@ def do_postproc(self): def __str__(self): return self.name + + +class CensusLocal(models.Model): + voting = models.ForeignKey( + 'voting.VotingLocal', + on_delete=models.CASCADE, + db_column='voting_id', + db_constraint=False, + related_name='+', + ) + voter = models.ForeignKey( + settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + db_column='voter_id', + db_constraint=False, + related_name='+', + ) + + class Meta: + managed = False # create to managed local census easier + db_table = 'census_census' + unique_together = (('voting', 'voter'),) + + +class VotingLocal(models.Model): + name = models.CharField(max_length=200) + voters = models.ManyToManyField( + settings.AUTH_USER_MODEL, + through='voting.CensusLocal', + blank=True, + ) + + class Meta: + managed = False # create to managed local census easier + db_table = 'voting_voting' + verbose_name_plural = 'Census local votings'