From ab7f64ea5d81efecb56bc7e3b4efeb3578db2d79 Mon Sep 17 00:00:00 2001 From: Jannis Leidel Date: Wed, 14 Sep 2016 11:03:35 +0200 Subject: [PATCH 1/3] Move Debian build script next to other scripts. --- README.md | 4 +++- build.sh => bin/build-deb.sh | 7 ++++--- 2 files changed, 7 insertions(+), 4 deletions(-) rename build.sh => bin/build-deb.sh (76%) diff --git a/README.md b/README.md index cb69b57c..c11f4495 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,9 @@ Development Setup This application is packaged with Docker, which manages and maintains a consistent application environment. -On a Debian-derived Linux distributions, run `./build.sh` in the project root directory to perform all the installation steps automatically. On other OSs, [install Docker](https://docs.docker.com/mac/) and [Docker Compose](https://docs.docker.com/compose/install/) manually. +On a Debian-derived Linux distributions, run `./bin/build-deb.sh` to perform all +the installation steps automatically. On other OSs, [install Docker](https://docs.docker.com/mac/) and +[Docker Compose](https://docs.docker.com/compose/install/) manually. To start the application, run `docker-compose up`. diff --git a/build.sh b/bin/build-deb.sh similarity index 76% rename from build.sh rename to bin/build-deb.sh index 668f1ca1..a1101971 100755 --- a/build.sh +++ b/bin/build-deb.sh @@ -1,7 +1,8 @@ #!/usr/bin/env bash - set -e +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + # the Docker and Docker Compose packages in the repositories are too old to work with this project - install the latest versions instead sudo apt-get install --yes -qq curl sudo apt-get purge --yes -qq lxc-docker docker.io docker-compose # remove old packages that can cause conflicts @@ -11,5 +12,5 @@ sudo chmod +x /usr/local/bin/docker-compose # install Docker Compose sudo usermod -aG docker ${USER} # add the current user to the Docker group (required in order to run the Docker daemon without sudo) # we still need sudo even though we've been added to the Docker group here, since the group change only takes effect after logging out and logging in again -sudo docker-compose run web ./manage.py collectstatic # collect all the static files to /app/static, required by the tests -sudo docker-compose run web ./manage.py test # run the test suite real quick +sudo docker-compose run web ${DIR}/../manage.py collectstatic # collect all the static files to /app/static, required by the tests +sudo docker-compose run web ${DIR}/../manage.py test # run the test suite real quick From ac1cc24fb0f123a9665d1276970678990269d68d Mon Sep 17 00:00:00 2001 From: Jannis Leidel Date: Fri, 16 Sep 2016 12:32:08 +0200 Subject: [PATCH 2/3] Add custom allauth provider for Google OpenIDConnect Also: - Rename some classes to just Atmo - Remove unused django-browserid backend --- Makefile | 5 + README.md | 13 + atmo/__init__.py | 2 +- atmo/apps.py | 2 +- atmo/settings.py | 58 +++-- atmo/templates/account/base.html | 1 + atmo/templates/account/login.html | 40 +++ atmo/templates/atmo/base.html | 43 +++- atmo/templates/atmo/dashboard.html | 233 ++++++++---------- atmo/templates/atmo/login.html | 40 --- atmo/templates/atmo/new-cluster.html | 2 +- atmo/urls.py | 5 +- atmo/users/__init__.py | 0 atmo/users/adapters.py | 33 +++ atmo/users/management/__init__.py | 0 atmo/users/management/commands/__init__.py | 0 .../commands/add_google_credentials.py | 33 +++ atmo/users/migrations/0001_initial_site.py | 32 +++ atmo/users/migrations/__init__.py | 0 atmo/users/provider.py | 42 ++++ atmo/users/urls.py | 5 + atmo/users/views.py | 93 +++++++ atmo/utils/auth.py | 6 - atmo/utils/tests.py | 18 -- atmo/views.py | 11 +- requirements.txt | 19 +- 26 files changed, 497 insertions(+), 239 deletions(-) create mode 100644 Makefile create mode 100644 atmo/templates/account/base.html create mode 100644 atmo/templates/account/login.html delete mode 100644 atmo/templates/atmo/login.html create mode 100644 atmo/users/__init__.py create mode 100644 atmo/users/adapters.py create mode 100644 atmo/users/management/__init__.py create mode 100644 atmo/users/management/commands/__init__.py create mode 100644 atmo/users/management/commands/add_google_credentials.py create mode 100644 atmo/users/migrations/0001_initial_site.py create mode 100644 atmo/users/migrations/__init__.py create mode 100644 atmo/users/provider.py create mode 100644 atmo/users/urls.py create mode 100644 atmo/users/views.py delete mode 100644 atmo/utils/auth.py delete mode 100644 atmo/utils/tests.py diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..b7fb4c14 --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +.PHONY: creds + +creds: + @docker-compose run web ./manage.py add_google_credentials \ + --client-id="$(CLIENT_ID)" --client-secret="$(CLIENT_SECRET)" diff --git a/README.md b/README.md index c11f4495..ecb49a70 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,19 @@ Quick troubleshooting guide: * The AWS credentials on the current machine are likely not correctly set. * Set them in your **ENVIRONMENT VARIABLES** (these environment variables are transferred to the docker container, from definitions in `docker-compose.yml`). * See the [relevant section of the Boto3 docs](https://boto3.readthedocs.org/en/latest/guide/configuration.html#environment-variables) for more details. +* Django raises a 404 when trying to login + * Google Developer credentials are needed to get the Google authentication + workflow running. + * Go to https://console.developers.google.com/, create a new project + * Click on "credentials" and create a new "OAuth client ID" + * Application type: "Web application" + * Name: "ATMO" (e.g. append "dev" or similar for local development) + * Authorized redirect URIs: + * ://[:]/accounts/google/login/callback/ e.g.: + * http://localhost:8000/accounts/google/login/callback/ for local development + * With the client ID and client secret given run the following to add them + to the django-allauth config system: + * CLIENT_ID= CLIENT_SECRET= make creds Production Setup ---------------- diff --git a/atmo/__init__.py b/atmo/__init__.py index 4e35cb3e..5aa0232a 100644 --- a/atmo/__init__.py +++ b/atmo/__init__.py @@ -1 +1 @@ -default_app_config = 'atmo.apps.AnalysisServiceAppConfig' +default_app_config = 'atmo.apps.AtmoAppConfig' diff --git a/atmo/apps.py b/atmo/apps.py index a791b0f5..3c728ba9 100644 --- a/atmo/apps.py +++ b/atmo/apps.py @@ -3,7 +3,7 @@ import session_csrf -class AnalysisServiceAppConfig(AppConfig): +class AtmoAppConfig(AppConfig): name = 'atmo' def ready(self): diff --git a/atmo/settings.py b/atmo/settings.py index 569c2a4a..cfea9b09 100644 --- a/atmo/settings.py +++ b/atmo/settings.py @@ -16,9 +16,9 @@ from urllib import parse import dj_database_url +from django.core.urlresolvers import reverse_lazy from decouple import Csv, config - # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(__file__)) ROOT = os.path.dirname(os.path.join(BASE_DIR, '..')) @@ -41,26 +41,26 @@ 'atmo', 'atmo.clusters', 'atmo.jobs', + 'atmo.users', 'atmo.workers', # Third party apps 'whitenoise.runserver_nostatic', 'django_rq', + 'allauth', + 'allauth.account', + 'allauth.socialaccount', # Django apps + 'django.contrib.sites', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', - 'django_browserid', ] -for app in config('EXTRA_APPS', default='', cast=Csv()): - INSTALLED_APPS.append(app) - - MIDDLEWARE_CLASSES = ( 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', @@ -133,12 +133,40 @@ } } -# Add the django_browserid authentication backend. +# Add the django-allauth authentication backend. AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend', - 'atmo.utils.auth.AllowMozillaEmailsBackend', + 'allauth.account.auth_backends.AuthenticationBackend', ) -LOGIN_URL = "/login/" + +LOGIN_URL = reverse_lazy('account_login') +LOGOUT_URL = reverse_lazy('account_logout') +LOGIN_REDIRECT_URL = reverse_lazy('dashboard') + +# django-allauth configuration +ACCOUNT_LOGOUT_REDIRECT_URL = LOGIN_REDIRECT_URL +if not DEBUG: + ACCOUNT_DEFAULT_HTTP_PROTOCOL = 'https' +ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 7 +ACCOUNT_EMAIL_SUBJECT_PREFIX = "[ATMO] " +ACCOUNT_EMAIL_REQUIRED = True +ACCOUNT_EMAIL_VERIFICATION = 'optional' +ACCOUNT_LOGOUT_ON_GET = True +ACCOUNT_ADAPTER = 'atmo.users.adapters.AtmoAccountAdapter' +ACCOUNT_USERNAME_REQUIRED = False + +SOCIALACCOUNT_ADAPTER = 'atmo.users.adapters.AtmoSocialAccountAdapter' +SOCIALACCOUNT_EMAIL_VERIFICATION = 'none' # no extra verification needed +SOCIALACCOUNT_QUERY_EMAIL = True # needed by the Google provider + +SOCIALACCOUNT_PROVIDERS = { + 'google': { + 'HOSTED_DOMAIN': 'mozilla.com', + 'AUTH_PARAMS': { + 'prompt': 'select_account', + } + } +} # Internationalization # https://docs.djangoproject.com/en/1.9/topics/i18n/ @@ -170,6 +198,7 @@ 'django.template.context_processors.media', 'django.template.context_processors.static', 'django.template.context_processors.tz', + 'django.template.context_processors.request', 'django.contrib.messages.context_processors.messages', 'session_csrf.context_processor', 'atmo.utils.context_processors.settings', @@ -181,15 +210,10 @@ } }, ] -if not DEBUG: - TEMPLATES[0]['OPTIONS']['loaders'] = [ - ('django.template.loaders.cached.Loader', TEMPLATES[0]['OPTIONS']['loaders']), - ] # Django-CSP CSP_DEFAULT_SRC = ( "'self'", - 'https://login.persona.org', ) CSP_FONT_SRC = ( "'self'", @@ -198,7 +222,6 @@ 'https://*.mozilla.net', 'http://*.mozilla.org', 'https://*.mozilla.org', - 'https://login.persona.org', ) CSP_IMG_SRC = ( "'self'", @@ -207,7 +230,6 @@ 'https://*.mozilla.net', 'http://*.mozilla.org', 'https://*.mozilla.org', - 'https://login.persona.org', ) CSP_SCRIPT_SRC = ( "'self'", @@ -216,7 +238,6 @@ 'https://*.mozilla.org', 'http://*.mozilla.net', 'https://*.mozilla.net', - 'https://login.persona.org', ) CSP_STYLE_SRC = ( "'self'", @@ -225,8 +246,9 @@ 'https://*.mozilla.org', 'http://*.mozilla.net', 'https://*.mozilla.net', - 'https://login.persona.org', ) # This is needed to get a CRSF token in /admin ANON_ALWAYS = True + +SITE_ID = 1 diff --git a/atmo/templates/account/base.html b/atmo/templates/account/base.html new file mode 100644 index 00000000..a16b6e98 --- /dev/null +++ b/atmo/templates/account/base.html @@ -0,0 +1 @@ +{% extends "atmo/base.html" %} diff --git a/atmo/templates/account/login.html b/atmo/templates/account/login.html new file mode 100644 index 00000000..3c87092f --- /dev/null +++ b/atmo/templates/account/login.html @@ -0,0 +1,40 @@ +{% extends "account/base.html" %} +{% load socialaccount static %} + +{% block head_title %}Login{% endblock %} + +{% block head_extra %} + +{% endblock %} + +{% block content %} +
+
+
+

Telemetry Data Analysis

+

To get started, log in with an @mozilla.com email!

+ +
+
+
+
+
+

What is this?

+

The Telemetry Data Analysis service gives direct access to Mozilla Telemetry data:

+ +
+
+

Links & resources

+ +
+
+{% endblock %} diff --git a/atmo/templates/atmo/base.html b/atmo/templates/atmo/base.html index 0d0f5b16..e06cbd4f 100644 --- a/atmo/templates/atmo/base.html +++ b/atmo/templates/atmo/base.html @@ -1,4 +1,4 @@ -{% load browserid staticfiles %} +{% load staticfiles %} {% block head_basic %} @@ -17,19 +17,50 @@ - Telemetry Self-Serve Data Analysis - {% browserid_css %} - {% browserid_js %} + Telemetry Self-Serve Data Analysis - {% block head_title %}Welcome{% endblock %} {% endblock %} {% block head_extra %} {% endblock %} - {% browserid_info %} - + +
{% block content %} {% endblock %} +
{% csrf_token %}