From 9c7db563b3969e69ff7740a927a6b3e3c8107125 Mon Sep 17 00:00:00 2001 From: Matheus Fernandes Date: Wed, 24 Jan 2018 10:41:03 -0200 Subject: [PATCH 1/6] :whale: Wait for database on start.sh Signed-off-by: Matheus Fernandes --- wikilegis/start.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/wikilegis/start.sh b/wikilegis/start.sh index d4a32e15..ac67d514 100755 --- a/wikilegis/start.sh +++ b/wikilegis/start.sh @@ -1,5 +1,15 @@ #!/bin/bash +while true; do + PG_STATUS=`PGPASSWORD=$DATABASE_PASSWORD psql -U $DATABASE_USER -w -h $DATABASE_HOST -c '\l \q' | grep postgres | wc -l` + if ! [ "$PG_STATUS" -eq "0" ]; then + break + fi + + echo "Waiting Database Setup" + sleep 10 +done + PGPASSWORD=$DATABASE_PASSWORD psql -U $DATABASE_USER -w -h $DATABASE_HOST -c "CREATE DATABASE ${DATABASE_NAME} OWNER ${DATABASE_USER}" python3 manage.py migrate From c80197dd7ce8501e4a0fb58ef31ebd21a538529c Mon Sep 17 00:00:00 2001 From: Matheus Fernandes Date: Wed, 24 Jan 2018 11:29:11 -0200 Subject: [PATCH 2/6] :sparkles: New e-Democracia Compatibility (#101) * Change remoteuserbackend to persistentremoteuserbackend Signed-off-by: Matheus Fernandes * Add staticfiles when remote_user and debug is enabled Signed-off-by: Matheus Fernandes * Update resource to allow update and delete users Signed-off-by: Matheus Fernandes * Allow delete user resource Signed-off-by: Matheus Fernandes * Remove never executed code Signed-off-by: Matheus Fernandes * Add translations Signed-off-by: Matheus Fernandes --- wikilegis/accounts/middlewares.py | 12 --------- wikilegis/api/authorization.py | 26 ++++++++++++++++++ wikilegis/api/resources.py | 25 ++++++++++++----- wikilegis/locale/en/LC_MESSAGES/django.po | 28 +++++++++++++------- wikilegis/locale/es/LC_MESSAGES/django.po | 28 +++++++++++++------- wikilegis/locale/pt_BR/LC_MESSAGES/django.po | 28 +++++++++++++------- wikilegis/wikilegis/urls.py | 5 ++++ 7 files changed, 104 insertions(+), 48 deletions(-) create mode 100644 wikilegis/api/authorization.py diff --git a/wikilegis/accounts/middlewares.py b/wikilegis/accounts/middlewares.py index dd88a0af..06eaa71c 100644 --- a/wikilegis/accounts/middlewares.py +++ b/wikilegis/accounts/middlewares.py @@ -24,18 +24,6 @@ def process_request(self, request): try: username = request.META[self.header] except KeyError: - # If specified header doesn't exist then remove any existing - # authenticated remote-user, or return (leaving request.user set to - # AnonymousUser by the AuthenticationMiddleware). - if request.user.is_authenticated(): - try: - stored_backend = load_backend(request.session.get( - auth.BACKEND_SESSION_KEY, '')) - if isinstance(stored_backend, RemoteUserBackend): - auth.logout(request) - except ImproperlyConfigured: - # backend failed to load - auth.logout(request) return # If the user is already authenticated and that user is the user we are # getting passed in the headers, then the correct user is already diff --git a/wikilegis/api/authorization.py b/wikilegis/api/authorization.py new file mode 100644 index 00000000..d22e214d --- /dev/null +++ b/wikilegis/api/authorization.py @@ -0,0 +1,26 @@ +from tastypie.authorization import Authorization +from tastypie.exceptions import Unauthorized +from django.conf import settings +from django.utils.translation import ugettext_lazy as _ + + +class UpdateUserAuthorization(Authorization): + + def api_key_is_valid(self, bundle): + api_key = bundle.request.GET.get('api_key', None) + if api_key and api_key == settings.API_KEY: + return True + else: + raise Unauthorized(_('Missing api key')) + + def update_list(self, object_list, bundle): + raise Unauthorized(_('You cannot perform this action')) + + def update_detail(self, object_list, bundle): + return self.api_key_is_valid(bundle) + + def delete_list(self, object_list, bundle): + raise Unauthorized(_('You cannot perform this action')) + + def delete_detail(self, object_list, bundle): + return self.api_key_is_valid(bundle) diff --git a/wikilegis/api/resources.py b/wikilegis/api/resources.py index a39f6648..a3d6b436 100644 --- a/wikilegis/api/resources.py +++ b/wikilegis/api/resources.py @@ -1,6 +1,8 @@ from django.conf import settings +from django.conf.urls import url from django.contrib.auth import get_user_model from django.contrib.contenttypes.models import ContentType +from api.authorization import UpdateUserAuthorization from tastypie.resources import ModelResource, ALL_WITH_RELATIONS, ALL from tastypie import fields @@ -10,23 +12,34 @@ class UserResource(ModelResource): def dehydrate(self, bundle): + bundle.data.pop('is_active', None) + bundle.data.pop('is_staff', None) + bundle.data.pop('is_superuser', None) + key = bundle.request.GET.get('api_key', None) if key != settings.API_KEY: del bundle.data['email'] return bundle - def dehydrate_username(self, bundle): - return bundle.obj.__str__() + def prepend_urls(self): + re_url = r"^(?P%s)/(?P[\w\d_.-]+)/$".format( + self._meta.resource_name + ) + return [ + url(re_url, self.wrap_view('dispatch_detail'), + name="api_dispatch_detail"), + ] class Meta: queryset = get_user_model().objects.all() - allowed_methods = ['get'] - excludes = ['is_active', 'is_staff', 'is_superuser', 'last_login', - 'password', 'date_joined'] + allowed_methods = ['get', 'put', 'delete'] + excludes = ['last_login', 'password', 'date_joined'] + authorization = UpdateUserAuthorization() + detail_uri_name = 'username' filtering = { 'first_name': ALL, 'last_name': ALL, - 'username': ALL + 'username': ALL, } diff --git a/wikilegis/locale/en/LC_MESSAGES/django.po b/wikilegis/locale/en/LC_MESSAGES/django.po index ae0998a9..5f88e70e 100644 --- a/wikilegis/locale/en/LC_MESSAGES/django.po +++ b/wikilegis/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-06-07 13:18-0300\n" +"POT-Creation-Date: 2018-01-24 11:17-0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -66,6 +66,14 @@ msgstr "" msgid "Users" msgstr "" +#: api/authorization.py:14 +msgid "Missing api key" +msgstr "" + +#: api/authorization.py:17 api/authorization.py:23 +msgid "You cannot perform this action" +msgstr "" + #: core/admin.py:23 core/models.py:160 msgid "reference" msgstr "" @@ -368,8 +376,8 @@ msgid "New" msgstr "" #: core/templates/base.html:34 core/templates/base.html:36 -#: core/templates/base.html:38 core/views.py:213 core/views.py:233 -#: core/views.py:255 core/views.py:298 +#: core/templates/base.html:38 core/views.py:214 core/views.py:234 +#: core/views.py:256 core/views.py:299 msgid "Oops" msgstr "" @@ -569,33 +577,33 @@ msgstr "" msgid "Access control. Please log in and try again." msgstr "" -#: core/views.py:74 +#: core/views.py:75 msgid "Access denied. Please contact the project author." msgstr "" -#: core/views.py:97 core/views.py:116 +#: core/views.py:98 core/views.py:117 msgid "" "The following URL has returned no known bill:
{}/bill/{}" msgstr "" -#: core/views.py:135 +#: core/views.py:136 msgid "The following URL has returned no known segment." msgstr "" -#: core/views.py:214 +#: core/views.py:215 msgid "This bill is closed for participation :(" msgstr "" -#: core/views.py:234 +#: core/views.py:235 msgid "You must be logged to comment :(" msgstr "" -#: core/views.py:256 +#: core/views.py:257 msgid "You must be logged to vote :(" msgstr "" -#: core/views.py:299 +#: core/views.py:300 msgid "You must be logged to suggest new amendment :(" msgstr "" diff --git a/wikilegis/locale/es/LC_MESSAGES/django.po b/wikilegis/locale/es/LC_MESSAGES/django.po index 26361a6b..78b22b0e 100644 --- a/wikilegis/locale/es/LC_MESSAGES/django.po +++ b/wikilegis/locale/es/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-06-07 13:18-0300\n" +"POT-Creation-Date: 2018-01-24 11:17-0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -67,6 +67,14 @@ msgstr "" msgid "Users" msgstr "" +#: api/authorization.py:14 +msgid "Missing api key" +msgstr "" + +#: api/authorization.py:17 api/authorization.py:23 +msgid "You cannot perform this action" +msgstr "" + #: core/admin.py:23 core/models.py:160 msgid "reference" msgstr "" @@ -369,8 +377,8 @@ msgid "New" msgstr "" #: core/templates/base.html:34 core/templates/base.html:36 -#: core/templates/base.html:38 core/views.py:213 core/views.py:233 -#: core/views.py:255 core/views.py:298 +#: core/templates/base.html:38 core/views.py:214 core/views.py:234 +#: core/views.py:256 core/views.py:299 msgid "Oops" msgstr "" @@ -570,33 +578,33 @@ msgstr "" msgid "Access control. Please log in and try again." msgstr "" -#: core/views.py:74 +#: core/views.py:75 msgid "Access denied. Please contact the project author." msgstr "" -#: core/views.py:97 core/views.py:116 +#: core/views.py:98 core/views.py:117 msgid "" "The following URL has returned no known bill:
{}/bill/{}" msgstr "" -#: core/views.py:135 +#: core/views.py:136 msgid "The following URL has returned no known segment." msgstr "" -#: core/views.py:214 +#: core/views.py:215 msgid "This bill is closed for participation :(" msgstr "" -#: core/views.py:234 +#: core/views.py:235 msgid "You must be logged to comment :(" msgstr "" -#: core/views.py:256 +#: core/views.py:257 msgid "You must be logged to vote :(" msgstr "" -#: core/views.py:299 +#: core/views.py:300 msgid "You must be logged to suggest new amendment :(" msgstr "" diff --git a/wikilegis/locale/pt_BR/LC_MESSAGES/django.po b/wikilegis/locale/pt_BR/LC_MESSAGES/django.po index d9110a7b..e0577661 100644 --- a/wikilegis/locale/pt_BR/LC_MESSAGES/django.po +++ b/wikilegis/locale/pt_BR/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-06-07 13:18-0300\n" +"POT-Creation-Date: 2018-01-24 11:17-0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -68,6 +68,14 @@ msgstr "Usuário" msgid "Users" msgstr "Usuários" +#: api/authorization.py:14 +msgid "Missing api key" +msgstr "Chave da api não encontrada" + +#: api/authorization.py:17 api/authorization.py:23 +msgid "You cannot perform this action" +msgstr "Você não pode realizar essa ação" + #: core/admin.py:23 core/models.py:160 msgid "reference" msgstr "referência" @@ -370,8 +378,8 @@ msgid "New" msgstr "Novo" #: core/templates/base.html:34 core/templates/base.html:36 -#: core/templates/base.html:38 core/views.py:213 core/views.py:233 -#: core/views.py:255 core/views.py:298 +#: core/templates/base.html:38 core/views.py:214 core/views.py:234 +#: core/views.py:256 core/views.py:299 msgid "Oops" msgstr "Oops" @@ -577,11 +585,11 @@ msgstr "Erro 403" msgid "Access control. Please log in and try again." msgstr "Acesso controlado. Faça o login e tente novamente." -#: core/views.py:74 +#: core/views.py:75 msgid "Access denied. Please contact the project author." msgstr "Acesso negado. Favor contatar o autor do projeto." -#: core/views.py:97 core/views.py:116 +#: core/views.py:98 core/views.py:117 msgid "" "The following URL has returned no known bill:
{}/bill/{}" @@ -589,23 +597,23 @@ msgstr "" "A seguinte URL não retornou um projeto de lei conhecido:
{}/" "bill/{}" -#: core/views.py:135 +#: core/views.py:136 msgid "The following URL has returned no known segment." msgstr "A seguinte URL não retornou um trecho conhecido." -#: core/views.py:214 +#: core/views.py:215 msgid "This bill is closed for participation :(" msgstr "Este projeto de lei está fechado para participação :(" -#: core/views.py:234 +#: core/views.py:235 msgid "You must be logged to comment :(" msgstr "Você deve estar logado para comentar :(" -#: core/views.py:256 +#: core/views.py:257 msgid "You must be logged to vote :(" msgstr "Você deve estar logado para votar :(" -#: core/views.py:299 +#: core/views.py:300 msgid "You must be logged to suggest new amendment :(" msgstr "Você deve estar logado para sugerir uma nova proposta :(" diff --git a/wikilegis/wikilegis/urls.py b/wikilegis/wikilegis/urls.py index 49efa182..d903f585 100644 --- a/wikilegis/wikilegis/urls.py +++ b/wikilegis/wikilegis/urls.py @@ -13,7 +13,9 @@ 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ +from django.conf import settings from django.conf.urls import url, include +from django.conf.urls.static import static from django.contrib import admin urlpatterns = [ @@ -23,3 +25,6 @@ url(r'^', include('api.urls')), url(r'^', include('accounts.urls')), ] + +if settings.FORCE_SCRIPT_NAME and settings.DEBUG: + urlpatterns += static('/static/', document_root=settings.STATIC_ROOT) From 2188e30034deacff38781f99472fb5675c724f02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eriv=C3=A2nio=20Vasconcelos?= Date: Mon, 29 Jan 2018 14:39:11 -0200 Subject: [PATCH 3/6] :sparkles: add order_by in bill api (#102) --- wikilegis/api/resources.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wikilegis/api/resources.py b/wikilegis/api/resources.py index a3d6b436..81d0ecf5 100644 --- a/wikilegis/api/resources.py +++ b/wikilegis/api/resources.py @@ -90,7 +90,9 @@ class Meta: 'title': ALL, 'status': ALL, 'id': ALL, + 'closing_date': ALL, } + ordering = ['closing_date'] class SegmentTypeResource(ModelResource): From 3582f65e84ce4a6d7d35b47776072af73a4f79ee Mon Sep 17 00:00:00 2001 From: Mike Linksvayer Date: Wed, 31 Jan 2018 10:51:39 -0800 Subject: [PATCH 4/6] Description and example at top of README (#104) Came across this via a [blog post](https://hackernoon.com/brazil-open-sources-legislative-texts-687513fb8c40) and had to search for a bit to find how it is used/looks. Just an idle suggestion! --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index dc388547..c98e6f14 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +# wikilegis + +Collaborative editing of legislative texts. See https://edemocracia.camara.leg.br/wikilegis/ for a live instance used by Brazil's Chamber of Deputies. + # Requirements * Python 3.x From 9938e3680708eeb4706d99ed65722569cc417c18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eriv=C3=A2nio=20Vasconcelos?= Date: Tue, 20 Feb 2018 11:57:26 -0300 Subject: [PATCH 5/6] :construction: order api queryset (#105) --- wikilegis/api/resources.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wikilegis/api/resources.py b/wikilegis/api/resources.py index 81d0ecf5..6447baab 100644 --- a/wikilegis/api/resources.py +++ b/wikilegis/api/resources.py @@ -81,7 +81,8 @@ class BillResource(ModelResource): class Meta: queryset = core_models.Bill.objects.filter( allowed_users__isnull=True, - is_visible=True).exclude(status='draft') + is_visible=True).exclude(status='draft').order_by( + '-status', '-modified') resource_name = 'bill' excludes = ['is_visible'] allowed_methods = ['get'] @@ -92,7 +93,7 @@ class Meta: 'id': ALL, 'closing_date': ALL, } - ordering = ['closing_date'] + ordering = ['closing_date', 'status', 'modified'] class SegmentTypeResource(ModelResource): From 13380748da4947c5e384fd6b77794fb2c96110e6 Mon Sep 17 00:00:00 2001 From: Matheus Fernandes Date: Mon, 9 Apr 2018 16:42:43 -0300 Subject: [PATCH 6/6] Activate plugin on dokcerfile Signed-off-by: Matheus Fernandes --- Dockerfile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2878f698..7e4e3c9b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,13 +12,15 @@ RUN chmod 0644 /etc/cron.d/wikilegis ADD . /var/labhacker/wikilegis WORKDIR /var/labhacker/wikilegis -RUN pip3 install -r requirements.txt psycopg2 gunicorn && \ +RUN pip3 install -U pip && \ + pip3 install -r requirements.txt psycopg2 gunicorn && \ rm -r /root/.cache RUN npm install WORKDIR /var/labhacker/wikilegis/wikilegis -RUN python3 manage.py bower_install --allow-root && \ +RUN python3 manage.py activate_plugin camara_deputados && \ + python3 manage.py bower_install --allow-root && \ python3 manage.py compress --force && \ python3 manage.py collectstatic --no-input && \ python3 manage.py compilemessages