diff --git a/.github/workflows/django.yml b/.github/workflows/django.yml
new file mode 100644
index 0000000000..8675b06b04
--- /dev/null
+++ b/.github/workflows/django.yml
@@ -0,0 +1,54 @@
+name: Python application
+
+on: [push]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ strategy:
+ matrix:
+ pyversion: ['3.8', '3.5']
+ pgversion: ['10.8', '12']
+
+ services:
+ postgres:
+ image: postgres:${{matrix.pgversion}}
+ env:
+ POSTGRES_USER: decide
+ POSTGRES_PASSWORD: decide
+ POSTGRES_DB: decide
+ ports:
+ - 5432:5432
+ # needed because the postgres container does not provide a healthcheck
+ options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up Python ${{matrix.pyversion}}
+ uses: actions/setup-python@v2
+ with:
+ python-version: ${{matrix.pyversion}}
+ - name: psycopg2 prerequisites
+ run: sudo apt-get install libpq-dev
+ - name: Install dependencies and config
+ run: |
+ python -m pip install --upgrade pip
+ pip install -r requirements.txt
+ pip install codacy-coverage
+ cp decide/local_settings.gactions.py decide/local_settings.py
+ - name: Run migrations (unnecessary)
+ run: |
+ cd decide
+ python manage.py migrate
+ - name: Run tests
+ run: |
+ cd decide
+ coverage run --branch --source=. ./manage.py test --keepdb
+ coverage xml
+ - name: Codacy Coverage Reporter
+ uses: codacy/codacy-coverage-reporter-action@v1
+ with:
+ project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
+ coverage-reports: decide/coverage.xml
diff --git a/.github/workflows/simpleWF.yml b/.github/workflows/simpleWF.yml
new file mode 100644
index 0000000000..f045431d14
--- /dev/null
+++ b/.github/workflows/simpleWF.yml
@@ -0,0 +1,19 @@
+name: GitHub Actions Demo
+on: [push]
+jobs:
+ Explore-GitHub-Actions:
+ runs-on: ubuntu-latest
+ steps:
+ - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
+ - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
+ - run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
+ - name: Check out repository code
+ uses: actions/checkout@v1
+ - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
+ - run: echo "🖥️ The workflow is now ready to test your code on the runner."
+ - name: List files in the repository
+ run: |
+ ls ${{ github.workspace }}
+ - run: echo "🍏 This job's status is ${{ job.status }}."
+ - name: Contains expresion in a step
+ run: echo "Is this branch master or develop? ${{ contains('refs/heads/master refs/heads/develop',github.ref)}}"
diff --git a/decide/authentication/tests_auth.py b/decide/authentication/tests_auth.py
new file mode 100644
index 0000000000..b92f7f7f09
--- /dev/null
+++ b/decide/authentication/tests_auth.py
@@ -0,0 +1,65 @@
+from pyexpat import model
+from django.test import TestCase
+from django.contrib.staticfiles.testing import StaticLiveServerTestCase
+
+from selenium import webdriver
+from selenium.webdriver.support.ui import WebDriverWait
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support import expected_conditions as EC
+from selenium.webdriver.common.keys import Keys
+
+from base.tests import BaseTestCase
+from voting.models import Question, Voting
+
+class AdminTestCase(StaticLiveServerTestCase):
+
+
+ def setUp(self):
+ #Load base test functionality for decide
+ self.base = BaseTestCase()
+ self.base.setUp()
+
+ options = webdriver.ChromeOptions()
+ options.headless = False
+ self.driver = webdriver.Chrome(options=options)
+
+ super().setUp()
+
+ def tearDown(self):
+ super().tearDown()
+ self.driver.quit()
+
+ self.base.tearDown()
+
+ def test_simpleVisualizer(self):
+ q = Question(desc='test question')
+ q.save()
+ v = Voting(name='test voting', question=q)
+ v.save()
+ response =self.driver.get(f'{self.live_server_url}/visualizer/{v.pk}/')
+ vState= self.driver.find_element(By.TAG_NAME,"h2").text
+ self.assertTrue(vState, "Votación no comenzada")
+
+ def test_simpleCorrectLogin(self):
+ self.driver.get(f'{self.live_server_url}/admin/')
+ self.driver.find_element(By.ID,'id_username').send_keys("admin")
+ self.driver.find_element(By.ID,'id_password').send_keys("qwerty",Keys.ENTER)
+
+ print(self.driver.current_url)
+ #In case of a correct loging, a element with id 'user-tools' is shown in the upper right part
+ self.assertTrue(len(self.driver.find_elements(By.ID,'user-tools'))==1)
+
+ def test_Admin_Login_fail(self):
+ self.driver.get(f'{self.live_server_url}/admin/')
+ data = {'id_username': 'voter1', 'id_password': '321'}
+ response = self.client.post('/authentication/login/', data, format='json')
+
+ self.assertEqual(response.status_code, 400)
+
+
+class SimpleTest(TestCase):
+ def test_basic_addition(self):
+ self.assertEqual(1 + 1, 2)
+
+
+
\ No newline at end of file
diff --git a/decide/booth/templates/booth/booth.html b/decide/booth/templates/booth/booth.html
index 164f547a31..27a80e51c6 100644
--- a/decide/booth/templates/booth/booth.html
+++ b/decide/booth/templates/booth/booth.html
@@ -81,7 +81,7 @@
[[ voting.question.desc ]]
-
+
diff --git a/decide/census/admin.py b/decide/census/admin.py
index 8fa7f6762b..90d69bdbe5 100644
--- a/decide/census/admin.py
+++ b/decide/census/admin.py
@@ -4,9 +4,11 @@
class CensusAdmin(admin.ModelAdmin):
+ #list_display = ('voting_id', 'voter_id','adscripcion_id')
list_display = ('voting_id', 'voter_id')
list_filter = ('voting_id', )
+ #search_fields = ('voter_id','adscripcion_id', )
search_fields = ('voter_id', )
diff --git a/decide/census/models.py b/decide/census/models.py
index e51a5b44e4..409c9f2b32 100644
--- a/decide/census/models.py
+++ b/decide/census/models.py
@@ -4,6 +4,7 @@
class Census(models.Model):
voting_id = models.PositiveIntegerField()
voter_id = models.PositiveIntegerField()
-
+ #adscripcion_id = models.PositiveIntegerField()
class Meta:
+ #unique_together = (('voting_id', 'voter_id','adscripcion_id'),)
unique_together = (('voting_id', 'voter_id'),)
diff --git a/decide/census/views.py b/decide/census/views.py
index 26dcf92f19..fb775e87e8 100644
--- a/decide/census/views.py
+++ b/decide/census/views.py
@@ -20,8 +20,10 @@ class CensusCreate(generics.ListCreateAPIView):
def create(self, request, *args, **kwargs):
voting_id = request.data.get('voting_id')
voters = request.data.get('voters')
+ #adscripcion_id = request.data.get('adscripcion_id')
try:
for voter in voters:
+ #census = Census(voting_id=voting_id, voter_id=voter, adscripcion_id=adscripcion_id)
census = Census(voting_id=voting_id, voter_id=voter)
census.save()
except IntegrityError:
@@ -30,6 +32,7 @@ def create(self, request, *args, **kwargs):
def list(self, request, *args, **kwargs):
voting_id = request.GET.get('voting_id')
+ #adscripcion_id = request.GET.get('adscripcion_id')
voters = Census.objects.filter(voting_id=voting_id).values_list('voter_id', flat=True)
return Response({'voters': voters})
diff --git a/decide/decide/settings.py b/decide/decide/settings.py
index 1d22b67324..3611fc6916 100644
--- a/decide/decide/settings.py
+++ b/decide/decide/settings.py
@@ -75,6 +75,7 @@
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
@@ -151,6 +152,9 @@
USE_TZ = True
+
+
+
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
# Static files (CSS, JavaScript, Images)
@@ -180,3 +184,12 @@
INSTALLED_APPS = INSTALLED_APPS + MODULES
+from django.utils.translation import ugettext_lazy as _
+LANGUAGES = [
+ ('es', _('Español')),
+ ('en-us', _('English')),
+ ('de', _('German'))
+]
+LOCALE_PATHS = [
+ os.path.join(BASE_DIR, 'locale')
+]
\ No newline at end of file
diff --git a/decide/local_settings.py b/decide/local_settings.py
new file mode 100644
index 0000000000..becbb60fca
--- /dev/null
+++ b/decide/local_settings.py
@@ -0,0 +1,42 @@
+ALLOWED_HOSTS = ["*"]
+
+# Modules in use, commented modules that you won't use
+MODULES = [
+ 'authentication',
+ 'base',
+ 'booth',
+ 'census',
+ 'mixnet',
+ 'postproc',
+ 'store',
+ 'visualizer',
+ 'voting',
+]
+
+APIS = {
+ 'authentication': 'http://localhost:8000',
+ 'base': 'http://localhost:8000',
+ 'booth': 'http://localhost:8000',
+ 'census': 'http://localhost:8000',
+ 'mixnet': 'http://localhost:8000',
+ 'postproc': 'http://localhost:8000',
+ 'store': 'http://localhost:8000',
+ 'visualizer': 'http://localhost:8000',
+ 'voting': 'http://localhost:8000',
+}
+
+BASEURL = 'http://localhost:8000'
+
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.postgresql',
+ 'NAME': 'postgres',
+ 'USER': 'decide',
+ 'PASSWORD': 'complexpassword',
+ 'HOST': 'localhost',
+ 'PORT': '5432',
+ }
+}
+
+# number of bits for the key, all auths should use the same number of bits
+KEYBITS = 256
diff --git a/decide/locale/es/LC_MESSAGES/django.po b/decide/locale/es/LC_MESSAGES/django.po
new file mode 100644
index 0000000000..167cd0fbd0
--- /dev/null
+++ b/decide/locale/es/LC_MESSAGES/django.po
@@ -0,0 +1,64 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR , YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2022-11-17 19:27+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: booth/templates/booth/booth.html:19
+msgid "logout"
+msgstr ""
+
+#: booth/templates/booth/booth.html:33
+msgid "Username"
+msgstr "Que"
+
+#: booth/templates/booth/booth.html:41
+msgid "Password"
+msgstr "Pasa"
+
+#: booth/templates/booth/booth.html:49
+msgid "Login"
+msgstr "Perro"
+
+#: booth/templates/booth/booth.html:64
+msgid "Vote"
+msgstr ""
+
+#: booth/templates/booth/booth.html:160 booth/templates/booth/booth.html:170
+#: booth/templates/booth/booth.html:201
+msgid "Error: "
+msgstr ""
+
+#: booth/templates/booth/booth.html:198
+msgid "Conglatulations. Your vote has been sent"
+msgstr ""
+
+#: decide/settings.py:189
+msgid "Español"
+msgstr ""
+
+#: decide/settings.py:190
+msgid "English"
+msgstr ""
+
+#: decide/settings.py:191
+msgid "German"
+msgstr ""
+
+#: visualizer/templates/visualizer/visualizer.html:25
+msgid "result"
+msgstr "Resultado de la votación"
diff --git a/decide/visualizer/templates/visualizer/visualizer.html b/decide/visualizer/templates/visualizer/visualizer.html
index 0faed6bac3..89a761b747 100644
--- a/decide/visualizer/templates/visualizer/visualizer.html
+++ b/decide/visualizer/templates/visualizer/visualizer.html
@@ -22,7 +22,7 @@ [[ voting.id ]] - [[ voting.name ]]
Votación no comenzada
Votación en curso
-
Resultados:
+
{% trans "result" %}
@@ -48,7 +48,7 @@ Resultados:
{% block extrabody %}
-
+
diff --git a/decide/voting/models.py b/decide/voting/models.py
index a10ab2bcb6..156d5a8a5c 100644
--- a/decide/voting/models.py
+++ b/decide/voting/models.py
@@ -121,3 +121,5 @@ def do_postproc(self):
def __str__(self):
return self.name
+
+
diff --git a/decide/voting/tests.py b/decide/voting/tests.py
index 063c52e1cc..2e0263fdb8 100644
--- a/decide/voting/tests.py
+++ b/decide/voting/tests.py
@@ -106,6 +106,21 @@ def test_complete_voting(self):
for q in v.postproc:
self.assertEqual(tally.get(q["number"], 0), q["votes"])
+ def testCreateVotinAPI(self):
+ self.login()
+ data = {
+ 'name': 'Example',
+ 'desc': 'Description example',
+ 'question': 'I want a ',
+ 'question_opt': ['cat', 'dog', 'horse']
+ }
+
+ response = self.client.post('/voting/', data, format='json')
+ self.assertEqual(response.status_code, 201)
+
+ voting = Voting.objects.get(name='Example')
+ self.assertEqual(voting.desc, 'Description example')
+
def test_create_voting_from_api(self):
data = {'name': 'Example'}
response = self.client.post('/voting/', data, format='json')
@@ -208,3 +223,26 @@ def test_update_voting(self):
response = self.client.put('/voting/{}/'.format(voting.pk), data, format='json')
self.assertEqual(response.status_code, 400)
self.assertEqual(response.json(), 'Voting already tallied')
+
+class VotingModelTestCase(BaseTestCase):
+ def setUp(self):
+
+ q = Question(desc='Descripcion')
+ q.save()
+
+ opt1 = QuestionOption(question=q, option='opcion 1')
+ opt1.save()
+ opt1 = QuestionOption(question=q, option='opcion 2')
+ opt1.save()
+
+ self.v = Voting(name='Votacion', question=q)
+ self.v.save()
+ super().setUp()
+
+ def tearDown(self):
+ super().tearDown()
+ self.v = None
+
+ def testExist(self):
+ v=Voting.objects.get(name='Votacion')
+ self.assertEquals(v.question.options.all()[0].option, "opcion 1")
\ No newline at end of file
diff --git a/decide/voting/tests_admin.py b/decide/voting/tests_admin.py
new file mode 100644
index 0000000000..89cbf57bfa
--- /dev/null
+++ b/decide/voting/tests_admin.py
@@ -0,0 +1,50 @@
+from pyexpat import model
+from django.test import TestCase
+from django.contrib.staticfiles.testing import StaticLiveServerTestCase
+
+from selenium import webdriver
+from selenium.webdriver.support.ui import WebDriverWait
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support import expected_conditions as EC
+from selenium.webdriver.common.keys import Keys
+
+from base.tests import BaseTestCase
+from voting.models import Question, Voting
+
+class AdminTestCase(StaticLiveServerTestCase):
+
+
+ def setUp(self):
+ #Load base test functionality for decide
+ self.base = BaseTestCase()
+ self.base.setUp()
+
+ options = webdriver.ChromeOptions()
+ options.headless = False
+ self.driver = webdriver.Chrome(options=options)
+
+ super().setUp()
+
+ def tearDown(self):
+ super().tearDown()
+ self.driver.quit()
+
+ self.base.tearDown()
+
+ def test_simpleVisualizer(self):
+ q = Question(desc='test question')
+ q.save()
+ v = Voting(name='test voting', question=q)
+ v.save()
+ response =self.driver.get(f'{self.live_server_url}/visualizer/{v.pk}/')
+ vState= self.driver.find_element(By.TAG_NAME,"h2").text
+ self.assertTrue(vState, "Votación no comenzada")
+
+ def test_simpleCorrectLogin(self):
+ self.driver.get(f'{self.live_server_url}/admin/')
+ self.driver.find_element(By.ID,'id_username').send_keys("admin")
+ self.driver.find_element(By.ID,'id_password').send_keys("qwerty",Keys.ENTER)
+
+ print(self.driver.current_url)
+ #In case of a correct loging, a element with id 'user-tools' is shown in the upper right part
+ self.assertTrue(len(self.driver.find_elements(By.ID,'user-tools'))==1)
\ No newline at end of file
diff --git a/loadtest/gen_census.py b/loadtest/gen_census.py
index 64f5705604..b30c92b95d 100644
--- a/loadtest/gen_census.py
+++ b/loadtest/gen_census.py
@@ -4,7 +4,7 @@
HOST = "http://localhost:8000"
USER = "admin"
-PASS = "admin"
+PASS = "MisPapis55"
VOTING = 1
diff --git a/requirements.txt b/requirements.txt
index d5860a1eb4..73e5855f29 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,7 +4,7 @@ djangorestframework==3.7.7
django-cors-headers==2.1.0
requests==2.18.4
django-filter==1.1.0
-psycopg2==2.7.4
+psycopg2==2.8.4
django-rest-swagger==2.2.0
coverage==4.5.2
django-nose==1.4.6