diff --git a/Dockerfile b/Dockerfile index 91ec5dd..94788f9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,6 @@ -FROM python:3.6 +FROM python:3.8 ENV PYTHONUNBUFFERED 1 -RUN wget -O /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64 && chmod +x /usr/local/bin/dumb-init - RUN mkdir /code WORKDIR /code diff --git a/ac_mediator/celery.py b/ac_mediator/celery.py index f8003cf..8cad35f 100644 --- a/ac_mediator/celery.py +++ b/ac_mediator/celery.py @@ -18,7 +18,7 @@ # Load task modules from all registered Django app configs. app.autodiscover_tasks() -app.autodiscover_tasks('api', related_name='requests_distributor') +app.autodiscover_tasks(['api'], related_name='requests_distributor') @app.task(bind=True) diff --git a/ac_mediator/settings.py b/ac_mediator/settings.py index 05a3bc1..3357b04 100644 --- a/ac_mediator/settings.py +++ b/ac_mediator/settings.py @@ -133,7 +133,7 @@ REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES': ('rest_framework.renderers.JSONRenderer',), 'DEFAULT_AUTHENTICATION_CLASSES': ( - 'oauth2_provider.ext.rest_framework.OAuth2Authentication', + 'oauth2_provider.contrib.rest_framework.OAuth2Authentication', ), 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated' if not DEBUG or not ALLOW_UNAUTHENTICATED_API_REQUESTS_ON_DEBUG diff --git a/ac_mediator/urls.py b/ac_mediator/urls.py index 21369f6..8842984 100644 --- a/ac_mediator/urls.py +++ b/ac_mediator/urls.py @@ -1,5 +1,5 @@ from django.conf import settings -from django.conf.urls import include, url +from django.urls import re_path, include from django.contrib import admin from django.contrib.auth import views as auth_views from accounts.views import registration, activate_account, resend_activation_emmil @@ -13,43 +13,43 @@ domainPrefix = "" urlpatterns = [ - url(r'^%scrash/$' % domainPrefix, crash_me, name='crash_me'), - url(r'^%sregister/$' % domainPrefix, registration, name='registration'), - url(r'^%sactivate/(?P[^\/]+)/(?P[^\/]+)/.*$' % domainPrefix, activate_account, name="accounts-activate"), - url(r'^%sreactivate/$' % domainPrefix, resend_activation_emmil, name="accounts-resend-activation"), - url(r'^%slogin/$' % domainPrefix, auth_views.login, {'template_name': 'accounts/login.html'}, name='login'), - url(r'^%slogout/$' % domainPrefix, auth_views.logout, {'next_page': settings.LOGOUT_URL}, name='logout'), - url(r'^%spassword_reset/$' % domainPrefix, auth_views.password_reset, dict( + re_path(r'^%scrash/$' % domainPrefix, crash_me, name='crash_me'), + re_path(r'^%sregister/$' % domainPrefix, registration, name='registration'), + re_path(r'^%sactivate/(?P[^\/]+)/(?P[^\/]+)/.*$' % domainPrefix, activate_account, name="accounts-activate"), + re_path(r'^%sreactivate/$' % domainPrefix, resend_activation_emmil, name="accounts-resend-activation"), + re_path(r'^%slogin/$' % domainPrefix, auth_views.LoginView.as_view(template_name='accounts/login.html'), name='login'), + re_path(r'^%slogout/$' % domainPrefix, auth_views.LogoutView.as_view(next_page=settings.LOGOUT_URL), name='logout'), + re_path(r'^%spassword_reset/$' % domainPrefix, auth_views.PasswordResetView.as_view( template_name='accounts/password_reset_form.html', subject_template_name='emails/password_reset_subject.txt', email_template_name='emails/password_reset.txt', ), name='password_reset'), - url(r'^%spassword_reset/done/$' % domainPrefix, auth_views.password_reset_done, dict( + re_path(r'^%spassword_reset/done/$' % domainPrefix, auth_views.PasswordResetDoneView.as_view( template_name='accounts/password_reset_done.html' ), name='password_reset_done'), - url(r'^%sreset/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$' % domainPrefix, - auth_views.password_reset_confirm, dict( + re_path(r'^%sreset/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$' % domainPrefix, + auth_views.PasswordResetConfirmView.as_view( template_name='accounts/password_reset_confirm.html' ), name='password_reset_confirm'), - url(r'^%sreset/done/$' % domainPrefix, auth_views.password_reset_complete, dict( + re_path(r'^%sreset/done/$' % domainPrefix, auth_views.PasswordResetCompleteView.as_view( template_name='accounts/password_reset_complete.html' ), name='password_reset_complete'), # Accounts - url(r'^%s' % domainPrefix, include('accounts.urls')), + re_path(r'^%s' % domainPrefix, include('accounts.urls')), # Developers - url(r'^developers/', include('developers.urls')), + re_path(r'^developers/', include('developers.urls')), # Api - url(r'^%sapi/' % domainPrefix, include('api.urls')), + re_path(r'^%sapi/' % domainPrefix, include('api.urls')), # Admin - url(r'^admin/monitor/$', monitor, name="admin-monitor"), - url(r'^admin/', admin.site.urls), + re_path(r'^admin/monitor/$', monitor, name="admin-monitor"), + re_path(r'^admin/', admin.site.urls), # Documentation - url(r'^docs/', include('docs.urls')), + re_path(r'^docs/', include('docs.urls')), ] if settings.DEBUG: diff --git a/accounts/migrations/0010_auto_20200206_1610.py b/accounts/migrations/0010_auto_20200206_1610.py new file mode 100644 index 0000000..89ced71 --- /dev/null +++ b/accounts/migrations/0010_auto_20200206_1610.py @@ -0,0 +1,24 @@ +# Generated by Django 2.2.10 on 2020-02-06 15:10 + +import django.contrib.postgres.fields.jsonb +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('accounts', '0009_auto_20161027_1651'), + ] + + operations = [ + migrations.AlterField( + model_name='account', + name='last_name', + field=models.CharField(blank=True, max_length=150, verbose_name='last name'), + ), + migrations.AlterField( + model_name='servicecredentials', + name='credentials', + field=django.contrib.postgres.fields.jsonb.JSONField(default=dict), + ), + ] diff --git a/accounts/models.py b/accounts/models.py index 06f6d63..ebf7b3e 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -38,9 +38,9 @@ class ServiceCredentials(models.Model): interpreting the contests of the 'credentials' field. """ - account = models.ForeignKey(Account, related_name='service_credentials') + account = models.ForeignKey(Account, related_name='service_credentials', on_delete=models.deletion.CASCADE) service_id = models.CharField(max_length=64) - credentials = JSONField(null=False, default={}) + credentials = JSONField(null=False, default=dict) created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) diff --git a/accounts/tests.py b/accounts/tests.py index 539a1bf..4e96378 100644 --- a/accounts/tests.py +++ b/accounts/tests.py @@ -1,6 +1,6 @@ from django.test import TestCase, override_settings from accounts.models import Account -from django.core.urlresolvers import reverse +from django.urls import reverse from django.core import mail from django.conf import settings diff --git a/accounts/urls.py b/accounts/urls.py index 9999472..7bfe9b6 100644 --- a/accounts/urls.py +++ b/accounts/urls.py @@ -1,5 +1,5 @@ -from django.conf.urls import url -from django.core.urlresolvers import reverse_lazy +from django.urls import re_path +from django.urls import reverse_lazy from accounts import views from oauth2_provider.views.token import AuthorizedTokenDeleteView, AuthorizedTokensListView from accounts.views import home @@ -9,23 +9,24 @@ # https://stackoverflow.com/questions/6930982/how-to-use-a-variable-inside-a-regular-expression # domainPrefix = "authenticate/" domainPrefix = "" +app_name = 'accounts' urlpatterns = [ # Home - url(r'^%s$' % domainPrefix, home, name='home'), - url(r'^%sabout/$' % domainPrefix, views.about, name='about'), + re_path(r'^%s$' % domainPrefix, home, name='home'), + re_path(r'^%sabout/$' % domainPrefix, views.about, name='about'), # Link services - url(r'^%slink_services/$' % domainPrefix, views.link_services, name='link_services'), - url(r'^%slink_service/(?P[^\/]+)/$' % domainPrefix, views.link_service_callback, name='link_service_callback'), - url(r'^%slink_service_get_token/(?P[^\/]+)/$' % domainPrefix, views.link_service_get_token, name='link_service_get_token'), - url(r'^%sunlink_service/(?P[^\/]+)/$' % domainPrefix, views.unlink_service, name='unlink_service'), + re_path(r'^%slink_services/$' % domainPrefix, views.link_services, name='link_services'), + re_path(r'^%slink_service/(?P[^\/]+)/$' % domainPrefix, views.link_service_callback, name='link_service_callback'), + re_path(r'^%slink_service_get_token/(?P[^\/]+)/$' % domainPrefix, views.link_service_get_token, name='link_service_get_token'), + re_path(r'^%sunlink_service/(?P[^\/]+)/$' % domainPrefix, views.unlink_service, name='unlink_service'), # Manage given api credentials - url(r'^%sauthorized_clients/$' % domainPrefix, AuthorizedTokensListView.as_view( + re_path(r'^%sauthorized_clients/$' % domainPrefix, AuthorizedTokensListView.as_view( template_name='accounts/authorized-tokens.html', ), name="authorized-token-list"), - url(r'^%sauthorized_clients/(?P\d+)/delete/$' % domainPrefix, AuthorizedTokenDeleteView.as_view( + re_path(r'^%sauthorized_clients/(?P\d+)/delete/$' % domainPrefix, AuthorizedTokenDeleteView.as_view( template_name='accounts/authorized-token-delete.html', - success_url=reverse_lazy('authorized-token-list'), + success_url=reverse_lazy('accounts:authorized-token-list'), ), name="authorized-token-delete"), ] diff --git a/accounts/views.py b/accounts/views.py index 0041443..ad65d35 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -1,6 +1,6 @@ from django.shortcuts import render from django.contrib.auth.decorators import login_required -from django.core.urlresolvers import reverse +from django.urls import reverse from django.http import HttpResponseRedirect from accounts.forms import RegistrationForm, ReactivationForm from accounts.models import ServiceCredentials, Account @@ -11,8 +11,8 @@ def registration(request): - if request.user.is_authenticated(): - return HttpResponseRedirect(reverse('home')) + if request.user.is_authenticated: + return HttpResponseRedirect(reverse('accounts:home')) if request.method == 'POST': form = RegistrationForm(request.POST) if form.is_valid(): @@ -28,7 +28,7 @@ def registration(request): def activate_account(request, username, uid_hash): if request.user.is_authenticated: - return HttpResponseRedirect(reverse('home')) + return HttpResponseRedirect(reverse('accounts:home')) try: account = Account.objects.get(username__iexact=username) @@ -46,7 +46,7 @@ def activate_account(request, username, uid_hash): def resend_activation_emmil(request): if request.user.is_authenticated: - return HttpResponseRedirect(reverse('home')) + return HttpResponseRedirect(reverse('accounts:home')) if request.method == 'POST': form = ReactivationForm(request.POST) @@ -138,4 +138,4 @@ def link_service_get_token(request, service_id): @login_required def unlink_service(request, service_id): ServiceCredentials.objects.filter(account=request.user, service_id=service_id).delete() - return HttpResponseRedirect(reverse('link_services')) + return HttpResponseRedirect(reverse('accounts:link_services')) diff --git a/api/forms.py b/api/forms.py index 0676b9a..0d58d74 100644 --- a/api/forms.py +++ b/api/forms.py @@ -1,7 +1,7 @@ from django import forms from django.forms import ModelForm from django.forms.fields import Field -from django.utils.text import mark_safe +from django.utils.safestring import mark_safe from django.forms.widgets import HiddenInput from api.models import ApiClient setattr(Field, 'is_checkbox', lambda self: isinstance(self.widget, forms.CheckboxInput)) # Used in the template diff --git a/api/migrations/0005_auto_20200206_1610.py b/api/migrations/0005_auto_20200206_1610.py new file mode 100644 index 0000000..24db255 --- /dev/null +++ b/api/migrations/0005_auto_20200206_1610.py @@ -0,0 +1,30 @@ +# Generated by Django 2.2.10 on 2020-02-06 15:10 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0004_apiclient_password_grant_is_allowed'), + ] + + operations = [ + migrations.AddField( + model_name='apiclient', + name='updated', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='apiclient', + name='id', + field=models.BigAutoField(primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='apiclient', + name='user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='api_apiclient', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/api/models.py b/api/models.py index a9dd184..841c07a 100644 --- a/api/models.py +++ b/api/models.py @@ -1,5 +1,5 @@ from django.db import models -from django.core.urlresolvers import reverse +from django.urls import reverse from oauth2_provider.models import AbstractApplication @@ -14,7 +14,7 @@ class ApiClient(AbstractApplication): # Add more custom fields here like description, logo, preferred services... def get_absolute_url(self): - return reverse('developers-app-detail', args=[self.id]) + return reverse('developers:app-detail', args=[self.id]) def clean(self): """ diff --git a/api/oauth2_urls.py b/api/oauth2_urls.py index e57b8fd..82e429d 100644 --- a/api/oauth2_urls.py +++ b/api/oauth2_urls.py @@ -1,10 +1,11 @@ -from django.conf.urls import url +from django.urls import re_path from oauth2_provider import views -urlpatterns = ( - url(r'^authorize/?$', views.AuthorizationView.as_view( +app_name = 'oauth2_provider' +urlpatterns = [ + re_path(r'^authorize/?$', views.AuthorizationView.as_view( template_name='accounts/authorize_client.html', ), name="authorize"), - url(r'^token/?$', views.TokenView.as_view(), name="token"), - url(r'^revoke_token/?$', views.RevokeTokenView.as_view(), name="revoke-token"), -) + re_path(r'^token/?$', views.TokenView.as_view(), name="token"), + re_path(r'^revoke_token/?$', views.RevokeTokenView.as_view(), name="revoke-token"), +] diff --git a/api/request_distributor.py b/api/request_distributor.py index 37d9187..29e535e 100644 --- a/api/request_distributor.py +++ b/api/request_distributor.py @@ -35,7 +35,7 @@ def process_request(request, wait_until_complete=False, include=None, exclude=No return a response right after all requests have been sent. This response will mainly include a response_id parameter that can be later used to pull the actual responses from the 3rd party services (see ResponseAggregator.collect_response). - If wait_until_complete is set to False, then this method will wait untill a response is + If wait_until_complete is set to False, then this method will wait until a response is received for all requests and only then will return an aggregated response including the contents of all 3rd party services individual responses. @@ -83,7 +83,7 @@ def process_request(request, wait_until_complete=False, include=None, exclude=No # Wait until all responses are received (only if wait_until_complete == True) if wait_until_complete: # We wait until we get a response for all the requests we sent - # We do that by continuously iterating over all async_response_objetcs in a while + # We do that by continuously iterating over all async_response_objects in a while # loop and only exit when all of them have been flagged as ready # TODO: we should add some control over timeouts, etc as this operation is blocking while True: diff --git a/api/response_aggregator.py b/api/response_aggregator.py index bd25d12..d0ef324 100644 --- a/api/response_aggregator.py +++ b/api/response_aggregator.py @@ -123,7 +123,7 @@ def collect_response(self, response_id, format='json'): to_return = response.copy() to_return['meta']['response_id'] = response_id # Add response_id to returned dictionary to_return['meta']['collect_url'] = \ - settings.BASE_URL + '{0}?rid={1}'.format(reverse('api-collect'), + settings.BASE_URL + '{0}?rid={1}'.format(reverse('api:api-collect'), response_id) # Add collect url for convenience to_return['meta']['current_timestamp'] = str(datetime.datetime.now()) if response['meta']['status'] == RESPONSE_STATUS_FINISHED and settings.DELETE_RESPONSES_AFTER_CONSUMED: diff --git a/api/tests.py b/api/tests.py index 35cca9f..4a592b4 100644 --- a/api/tests.py +++ b/api/tests.py @@ -1,7 +1,7 @@ from django.test import TestCase, override_settings from api.models import ApiClient from accounts.models import Account -from django.core.urlresolvers import reverse +from django.urls import reverse from services import management from django.conf import settings import oauth2_provider @@ -399,7 +399,7 @@ def get_download_url(self, acid): def test_get_download_link(self): # Make unauthenticated request and assert it returns 401 - resp = self.client.get(reverse('api-download'), { + resp = self.client.get(reverse('api:download'), { 'acid': 'DownloadService:123', }) self.assertEqual(resp.status_code, 401) @@ -414,19 +414,19 @@ def test_get_download_link(self): ) # Make API request authenticated and assert it returns 200 - resp = self.client.get(reverse('api-download'), { + resp = self.client.get(reverse('api:download'), { 'acid': 'DownloadService:123', }, HTTP_AUTHORIZATION='Bearer {0}'.format(access_token)) self.assertEqual(resp.status_code, 200) # Ensure request for non existing service returns 404 - resp = self.client.get(reverse('api-download'), { + resp = self.client.get(reverse('api:download'), { 'acid': 'DownloadService2:123', }, HTTP_AUTHORIZATION='Bearer {0}'.format(access_token)) self.assertEqual(resp.status_code, 404) # Ensure request with no acid parameter returns 400 - resp = self.client.get(reverse('api-download'), { + resp = self.client.get(reverse('api:download'), { 'acid2': 'DownloadService:123', }, HTTP_AUTHORIZATION='Bearer {0}'.format(access_token)) self.assertEqual(resp.status_code, 400) diff --git a/api/urls.py b/api/urls.py index f1ebfd2..3521e1f 100644 --- a/api/urls.py +++ b/api/urls.py @@ -1,17 +1,18 @@ -from django.conf.urls import include, url +from django.urls import re_path, include from api import views +app_name = 'api' urlpatterns = [ - url(r'^v1/services/$', views.services, name='api-services'), - url(r'^v1/collect/$', views.collect_response, name='api-collect'), - url(r'^v1/search/text/$', views.text_search, name='api-text-search'), - url(r'^v1/license/$', views.licensing, name='api-licensing'), - url(r'^v1/download/$', views.download, name='api-download'), - url(r'^v1/me/$', views.me, name='api-me'), + re_path(r'^v1/services/$', views.services, name='services'), + re_path(r'^v1/collect/$', views.collect_response, name='collect'), + re_path(r'^v1/search/text/$', views.text_search, name='text-search'), + re_path(r'^v1/license/$', views.licensing, name='licensing'), + re_path(r'^v1/download/$', views.download, name='download'), + re_path(r'^v1/me/$', views.me, name='me'), # Oauth2 urls - url(r'^o/', include('api.oauth2_urls', namespace='oauth2_provider')), + re_path(r'^o/', include('api.oauth2_urls')), # Invalid url - url(r'$', views.invalid_url), + re_path(r'$', views.invalid_url), ] diff --git a/api/utils.py b/api/utils.py index 4b5eb90..8e26ddf 100644 --- a/api/utils.py +++ b/api/utils.py @@ -1,7 +1,6 @@ from oauth2_provider.oauth2_validators import OAuth2Validator from oauth2_provider.models import AbstractApplication -from rest_framework.views import exception_handler -from rest_framework.compat import set_rollback +from rest_framework.views import exception_handler, set_rollback from rest_framework.response import Response from rest_framework import status diff --git a/api/views.py b/api/views.py index 9c21614..ef8b0a8 100644 --- a/api/views.py +++ b/api/views.py @@ -24,7 +24,7 @@ def get_request_context(request): else: # In integration tests or local development it can happen that successful_authenticator does not exist # In that case we provide 'fake' context so tests can be carried out correctly - if request.user.is_authenticated(): + if request.user.is_authenticated: user_account_id = request.user.id dev_account_id = user_account_id else: @@ -108,7 +108,7 @@ def me(request): the access token used to authenticate. This information is useful for a third party application to uniquely identify an Audio Commons user account and be able to store extra information associated to the account or display user information on screen. - + This endpoint takes no query parameters. :statuscode 200: no error diff --git a/developers/urls.py b/developers/urls.py index 6563562..ceb9ea3 100644 --- a/developers/urls.py +++ b/developers/urls.py @@ -1,19 +1,20 @@ -from django.conf.urls import url +from django.urls import re_path from developers import views as dev_views +app_name = 'developers' urlpatterns = [ - url(r'^clients/$', dev_views.ApplicationList.as_view(), - name="developers-app-list"), - url(r'^clients/register/$', dev_views.ApplicationRegistration.as_view(), - name="developers-app-register"), - url(r'^clients/(?P\d+)/$', dev_views.ApplicationDetail.as_view(), - name="developers-app-detail"), - url(r'^clients/(?P\d+)/delete/$', dev_views.ApplicationDelete.as_view(), - name="developers-app-delete"), - url(r'^clients/(?P\d+)/update/$', dev_views.ApplicationUpdate.as_view(), - name="developers-app-update"), - url(r'^clients/(?P\d+)/monitor/$', dev_views.application_monitor, - name="developers-app-monitor"), - url(r'^clients/(?P\d+)/monitor/data/$', dev_views.get_application_monitor_data, - name="developers-app-monitor-data"), + re_path(r'^clients/$', dev_views.ApplicationList.as_view(), + name="app-list"), + re_path(r'^clients/register/$', dev_views.ApplicationRegistration.as_view(), + name="app-register"), + re_path(r'^clients/(?P\d+)/$', dev_views.ApplicationDetail.as_view(), + name="app-detail"), + re_path(r'^clients/(?P\d+)/delete/$', dev_views.ApplicationDelete.as_view(), + name="app-delete"), + re_path(r'^clients/(?P\d+)/update/$', dev_views.ApplicationUpdate.as_view(), + name="app-update"), + re_path(r'^clients/(?P\d+)/monitor/$', dev_views.application_monitor, + name="app-monitor"), + re_path(r'^clients/(?P\d+)/monitor/data/$', dev_views.get_application_monitor_data, + name="app-monitor-data"), ] diff --git a/developers/views.py b/developers/views.py index ade4869..8b34203 100644 --- a/developers/views.py +++ b/developers/views.py @@ -3,7 +3,7 @@ from oauth2_provider.views.application import ApplicationList as ProviderApplicationList from oauth2_provider.views.application import ApplicationDelete as ProviderApplicationDelete from oauth2_provider.views.application import ApplicationUpdate as ProviderApplicationUpdate -from django.core.urlresolvers import reverse_lazy +from django.urls import reverse_lazy from django.shortcuts import render, get_object_or_404 from django.contrib.auth.decorators import login_required from django.http import JsonResponse @@ -15,7 +15,7 @@ class ApplicationRegistration(ProviderApplicationRegistration): template_name = "developers/application_registration_form.html" - success_url = reverse_lazy('developers-app-list') + success_url = reverse_lazy('developers:app-list') def get_form_class(self): return ApiClientForm @@ -30,7 +30,7 @@ class ApplicationList(ProviderApplicationList): class ApplicationDelete(ProviderApplicationDelete): - success_url = reverse_lazy('developers-app-list') + success_url = reverse_lazy('developers:app-list') template_name = "developers/application_confirm_delete.html" diff --git a/docker-compose.yml b/docker-compose.yml index 5978e54..5818c59 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,15 +1,15 @@ -version: '2' +version: '3.7' volumes: dbvolume: services: db: - image: postgres:9.6 + image: postgres:12.1 env_file: - .env volumes: - dbvolume:/var/lib/postgresql/data/ nginx: - image: nginx + image: nginx:1.17.8 ports: - "80:80" - "443:443" @@ -19,9 +19,8 @@ services: depends_on: - web - flower - #- redmon redis: - image: redis + image: redis:5.0.7 web: build: . env_file: @@ -38,8 +37,10 @@ services: build: . env_file: - .env - volumes_from: - - web + volumes: + - .:/code + - /static/ + - ./services/services_conf.cfg:/code/services/services_conf.cfg command: celery worker -A ac_mediator --concurrency=${CELERY_CONCURRENCY} depends_on: - redis @@ -47,8 +48,10 @@ services: build: . env_file: - .env - volumes_from: - - web + volumes: + - .:/code + - /static/ + - ./services/services_conf.cfg:/code/services/services_conf.cfg command: celery beat -A ac_mediator depends_on: - redis @@ -59,8 +62,3 @@ services: command: flower --address=0.0.0.0 --port=5555 --broker=redis://redis --url_prefix=flower depends_on: - celery - #redmon: # Redis monitoring - # build: ./docker/redmon/ - # command: redmon --port=4567 --redis=redis://redis --base-path=/redmon --secure=${REDMON_BASIC_AUTH} - # depends_on: - # - redis diff --git a/docker/flower/Dockerfile b/docker/flower/Dockerfile index 571444b..8eebd7f 100644 --- a/docker/flower/Dockerfile +++ b/docker/flower/Dockerfile @@ -1,8 +1,6 @@ -FROM python:3.6 +FROM python:3.8 ENV PYTHONUNBUFFERED 1 -RUN wget -O /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64 && chmod +x /usr/local/bin/dumb-init - RUN mkdir /code WORKDIR /code ADD requirements.txt /code/ diff --git a/docker/flower/requirements.txt b/docker/flower/requirements.txt index e2dfaff..1316830 100644 --- a/docker/flower/requirements.txt +++ b/docker/flower/requirements.txt @@ -1,2 +1,2 @@ -redis -flower \ No newline at end of file +redis==3.4.1 +flower==0.9.3 \ No newline at end of file diff --git a/docker/redmon/Dockerfile b/docker/redmon/Dockerfile deleted file mode 100644 index 9ed063f..0000000 --- a/docker/redmon/Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -FROM ruby:2.3 - -RUN wget -O /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64 && chmod +x /usr/local/bin/dumb-init - -RUN mkdir /code -WORKDIR /code -RUN gem install redmon diff --git a/requirements.txt b/requirements.txt index d2f6ffe..c4c5bb1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,19 +1,19 @@ -Django==1.11.20 -docutils==0.12 -djangorestframework==3.5.1 -django-oauth-toolkit==0.10.0 -django-extensions==1.7.4 -django-docs==0.2.1 -dj-database-url==0.4.1 -psycopg2==2.6.2 -requests==2.21.0 -Sphinx==1.4 -Pygments==2.1.3 -sphinxcontrib-httpdomain==1.4.0 -redis==2.10.5 -kombu==4.0.2 # Needed to avoid problems with celery -celery==4.0.2 -uwsgi==2.0.17.1 -raven==5.32.0 -graypy==0.2.14 -pyparsing==2.2.0 +Django==2.2.10 +docutils==0.16 +djangorestframework==3.11.0 +django-oauth-toolkit==1.0.0 +django-extensions==2.2.6 +django-docs==0.3.1 +dj-database-url==0.5.0 +psycopg2-binary==2.8.4 +requests==2.22.0 +Sphinx==2.3.1 +Pygments==2.5.2 +sphinxcontrib-httpdomain==1.7.0 +redis==3.4.1 +kombu==4.6.7 +celery==4.4.0 +pyuwsgi==2.0.18 +raven==6.10.0 +graypy==2.1.0 +pyparsing==2.4.6 diff --git a/services/acservice/auth.py b/services/acservice/auth.py index 468c835..dcfb895 100644 --- a/services/acservice/auth.py +++ b/services/acservice/auth.py @@ -1,6 +1,6 @@ from accounts.models import ServiceCredentials from ac_mediator.exceptions import * -from django.core.urlresolvers import reverse +from django.urls import reverse from django.conf import settings import requests from services.acservice.constants import * @@ -37,7 +37,7 @@ def get_authorize_url(self): return self.BASE_AUTHORIZE_URL.format(self.service_client_id) def get_redirect_uri(self): - return settings.BASE_URL + reverse('link_service_callback', args=[self.id]) + return settings.BASE_URL + reverse('accounts:link_service_callback', args=[self.id]) def access_token_request_data(self, authorization_code=None, refresh_token=None): data = {'client_id': self.service_client_id, 'client_secret': self.service_client_secret} @@ -133,7 +133,7 @@ def check_credentials_should_be_renewed_background(self, credentials): For OAuth2 based services, this should be True when refresh token is about to expire but can be still set to False if only access token has expired (as the access token can be automatically renewed at request time if the refresh token is still valid). - This method should be overwritten by each individual service or it will return the opposite + This method should be overwritten by each individual service or it will return the opposite value of `check_credentials_are_valid`. :param credentials: credentials object as stored in ServiceCredentials entry """ diff --git a/templates/accounts/about.html b/templates/accounts/about.html index d26d1cb..a728e45 100644 --- a/templates/accounts/about.html +++ b/templates/accounts/about.html @@ -4,11 +4,11 @@ {% block content %}

- Audio Commons Logo + Audio Commons Logo | About

diff --git a/templates/accounts/authorized-tokens.html b/templates/accounts/authorized-tokens.html index 29d18ab..1649b34 100644 --- a/templates/accounts/authorized-tokens.html +++ b/templates/accounts/authorized-tokens.html @@ -1,12 +1,11 @@ {% extends "base.html" %} {% load staticfiles %} {% load i18n %} -{% load url from compat %} {% block title %}{% trans "Authorized applications" %}{% endblock title %} {% block content %}

- Audio Commons Logo + Audio Commons Logo | Authorized applications

@@ -14,7 +13,7 @@

{% for authorized_token in authorized_tokens %}
  • {{ authorized_token.application }} - +
    • {% for scope_name, scope_description in authorized_token.scopes.items %} @@ -26,5 +25,5 @@

      {% endfor %}



    -

    Back

    +

    Back

    {% endblock %} diff --git a/templates/accounts/home.html b/templates/accounts/home.html index 32c9f93..f43c226 100644 --- a/templates/accounts/home.html +++ b/templates/accounts/home.html @@ -6,7 +6,7 @@

    Audio Commons Logo Welcome!


    {% endblock %} diff --git a/templates/accounts/link_service_callback.html b/templates/accounts/link_service_callback.html index a47f42e..cdf3968 100644 --- a/templates/accounts/link_service_callback.html +++ b/templates/accounts/link_service_callback.html @@ -59,7 +59,7 @@ {% endif %} {% endif %} {% if not errors and not complete %} - window.location='{% url "link_service_get_token" service_id %}?code={{ code }}'; + window.location='{% url "accounts:link_service_get_token" service_id %}?code={{ code }}'; {% endif %}">
    diff --git a/templates/accounts/link_services.html b/templates/accounts/link_services.html index c2fac39..de946e3 100644 --- a/templates/accounts/link_services.html +++ b/templates/accounts/link_services.html @@ -16,7 +16,7 @@

    - Audio Commons Logo + Audio Commons Logo | Link service accounts

    @@ -28,7 +28,7 @@

    Linkable services

    {% if user_credentials %} unlink {% else %}
    diff --git a/templates/developers/application_confirm_delete.html b/templates/developers/application_confirm_delete.html index 9accebc..b9297cd 100644 --- a/templates/developers/application_confirm_delete.html +++ b/templates/developers/application_confirm_delete.html @@ -1,18 +1,17 @@ {% extends "base.html" %} {% block title %}Delete {{ application.name }}{% endblock title %} {% load i18n %} -{% load url from compat %} {% block content %}

    {% trans "Are you sure to delete the Api Client" %} {{ application.name }}?

    -
    + {% csrf_token %}
    diff --git a/templates/developers/application_detail.html b/templates/developers/application_detail.html index 7469446..922d76f 100644 --- a/templates/developers/application_detail.html +++ b/templates/developers/application_detail.html @@ -2,10 +2,9 @@ {% block title %}{{ application.name }}{% endblock title %} {% load staticfiles %} {% load i18n %} -{% load url from compat %} {% block content %}

    - Audio Commons Logo + Audio Commons Logo | API Client Details

    @@ -71,8 +70,8 @@

    - Back + Back {% endblock content %} \ No newline at end of file diff --git a/templates/developers/application_form.html b/templates/developers/application_form.html index 96c4529..2cc1985 100644 --- a/templates/developers/application_form.html +++ b/templates/developers/application_form.html @@ -1,7 +1,6 @@ {% extends "base.html" %} {% load staticfiles %} {% load i18n %} -{% load url from compat %} {% block content %} -
    +

    - Audio Commons Logo + Audio Commons Logo | {% block app-form-title %} {% trans "Edit application" %} {{ application.name }} @@ -90,7 +89,7 @@

    -   Back +   Back
    diff --git a/templates/developers/application_list.html b/templates/developers/application_list.html index 798e5be..2c75a81 100644 --- a/templates/developers/application_list.html +++ b/templates/developers/application_list.html @@ -5,7 +5,7 @@ {% block content %}

    - Audio Commons Logo + Audio Commons Logo | Developers

    @@ -15,16 +15,16 @@

    Manage API Clients

    {% for application in applications %}
  • {{ application.name }}
    - - {% comment %} - {% endcomment %} + + {% comment %} + {% endcomment %}
  • {% endfor %} {% endif %}
    - New API Client + New API Client

    Documentation

    diff --git a/templates/developers/application_monitor.html b/templates/developers/application_monitor.html index 5bb1b19..6a72c9f 100644 --- a/templates/developers/application_monitor.html +++ b/templates/developers/application_monitor.html @@ -9,7 +9,7 @@ }, false); function loadApplicationMonitorData() { - getJSON('{% url "developers-app-monitor-data" application.id %}').then( + getJSON('{% url "developers:app-monitor-data" application.id %}').then( function(xhr) { // Success (status = 200) // Sort data by date var sortedData = xhr.response.data.sort(function(a,b){ @@ -197,6 +197,6 @@

    Monitor {{ application.name }}

    - Back + Back
    {% endblock content %} \ No newline at end of file diff --git a/templates/developers/application_registration_form.html b/templates/developers/application_registration_form.html index 651d568..ebcf4ab 100644 --- a/templates/developers/application_registration_form.html +++ b/templates/developers/application_registration_form.html @@ -1,10 +1,9 @@ {% extends "developers/application_form.html" %} {% block title %}Register a new Api Client{% endblock title %} {% load i18n %} -{% load url from compat %} {% block app-form-title %}{% trans "Register a new Api Client" %}{% endblock app-form-title %} -{% block app-form-action-url %}{% url 'developers-app-register' %}{% endblock app-form-action-url %} +{% block app-form-action-url %}{% url 'developers:app-register' %}{% endblock app-form-action-url %} -{% block app-form-back-url %}{% url "developers-app-list" %}"{% endblock app-form-back-url %} \ No newline at end of file +{% block app-form-back-url %}{% url "developers:app-list" %}"{% endblock app-form-back-url %} \ No newline at end of file