From c18fbf9a2fbba964a8344e63eb2ee919bcf29f1a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Bedna=C5=99=C3=ADk?= <jan.bednarik@gmail.com>
Date: Sun, 17 Dec 2017 22:56:06 +0100
Subject: [PATCH] Add Django project files and core app.

---
 Makefile                                 |   5 +-
 README.md                                |   9 +-
 manage.py                                |  22 ++++
 openlobby/core/__init__.py               |   0
 openlobby/core/admin.py                  |   3 +
 openlobby/core/apps.py                   |   5 +
 openlobby/core/migrations/__init__.py    |   0
 openlobby/core/models.py                 |   3 +
 openlobby/core/templates/core/index.html |   6 +
 openlobby/core/tests.py                  |   3 +
 openlobby/core/views.py                  |   5 +
 openlobby/settings.py                    | 135 ++++++++++++++++++++++-
 openlobby/urls.py                        |   6 +
 openlobby/wsgi.py                        |  16 +++
 requirements.txt                         |   6 +-
 15 files changed, 214 insertions(+), 10 deletions(-)
 create mode 100755 manage.py
 create mode 100644 openlobby/core/__init__.py
 create mode 100644 openlobby/core/admin.py
 create mode 100644 openlobby/core/apps.py
 create mode 100644 openlobby/core/migrations/__init__.py
 create mode 100644 openlobby/core/models.py
 create mode 100644 openlobby/core/templates/core/index.html
 create mode 100644 openlobby/core/tests.py
 create mode 100644 openlobby/core/views.py
 create mode 100644 openlobby/urls.py
 create mode 100644 openlobby/wsgi.py

diff --git a/Makefile b/Makefile
index 9c9fdd5..7898120 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,10 @@ install:
 	pip install -e .
 
 run:
-	SECRET_KEY=local FLASK_DEBUG=1 FLASK_APP=./openlobby/server.py flask run -p 8010
+	DEBUG=1 python manage.py runserver 8010
+
+migrate:
+	DEBUG=1 python manage.py migrate
 
 build:
 	docker build -t openlobby/openlobby-server:latest .
diff --git a/README.md b/README.md
index 7bd58cf..cd0bddf 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,9 @@ prepared Elasticsearch Docker container with Czech support at
 ## Configuration
 
 Configuration is done by environment variables:
- - `SECRET_KEY` - long random secret string (required)
+ - `DEBUG` - Set to any value to turn on debug mode. Don't use in production!
+ - `SECRET_KEY` - long random secret string (required if not in debug mode)
+ - `DATABASE_DSN` - DSN of PostgreSQL database (default: `postgresql://db:db@localhost:5432/openlobby`)
  - `ELASTICSEARCH_DSN` - DSN of Elasticsearch cluster (default: `http://localhost:9200`)
  - `SITE_NAME` - site name for OpenID authentication (default: `Open Lobby`)
  - `ES_INDEX` - Elasticsearch index (default: `openlobby`)
@@ -44,12 +46,13 @@ You need to have Python 3 installed. Clone this repository and run:
 1. `make init-env` - prepares Python virtualenv in dir `.env`
 2. `source .env/bin/activate` - activates virtualenv
 3. `make install` - installs requirements and server in development mode
-4. `make run` - runs development server on port `8010`
+4. `make migrate` - runs database migrations
+5. `make run` - runs development server on port `8010`
 
 Now you can use GraphQL API endpoint and GraphiQL web interface at
 `http://localhost:8010/graphql`
 
-Next time you can just do steps 2 and 4.
+Next time you can just do steps 2 and 5.
 
 Development server assumes that you have
 [openlobby/openlobby-es-czech](https://github.com/openlobby/openlobby-es-czech).
diff --git a/manage.py b/manage.py
new file mode 100755
index 0000000..de2d50d
--- /dev/null
+++ b/manage.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+import os
+import sys
+
+if __name__ == "__main__":
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "openlobby.settings")
+    try:
+        from django.core.management import execute_from_command_line
+    except ImportError:
+        # The above import may fail for some other reason. Ensure that the
+        # issue is really that Django is missing to avoid masking other
+        # exceptions on Python 2.
+        try:
+            import django
+        except ImportError:
+            raise ImportError(
+                "Couldn't import Django. Are you sure it's installed and "
+                "available on your PYTHONPATH environment variable? Did you "
+                "forget to activate a virtual environment?"
+            )
+        raise
+    execute_from_command_line(sys.argv)
diff --git a/openlobby/core/__init__.py b/openlobby/core/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/openlobby/core/admin.py b/openlobby/core/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/openlobby/core/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/openlobby/core/apps.py b/openlobby/core/apps.py
new file mode 100644
index 0000000..26f78a8
--- /dev/null
+++ b/openlobby/core/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class CoreConfig(AppConfig):
+    name = 'core'
diff --git a/openlobby/core/migrations/__init__.py b/openlobby/core/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/openlobby/core/models.py b/openlobby/core/models.py
new file mode 100644
index 0000000..71a8362
--- /dev/null
+++ b/openlobby/core/models.py
@@ -0,0 +1,3 @@
+from django.db import models
+
+# Create your models here.
diff --git a/openlobby/core/templates/core/index.html b/openlobby/core/templates/core/index.html
new file mode 100644
index 0000000..25a2631
--- /dev/null
+++ b/openlobby/core/templates/core/index.html
@@ -0,0 +1,6 @@
+<html>
+  <body>
+    <h1>Open Lobby Server</h1>
+    <p>GraphQL API endpoint and GraphiQL is at: <a href="/graphql">/graphql</a></p>
+  </body>
+</html>
diff --git a/openlobby/core/tests.py b/openlobby/core/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/openlobby/core/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/openlobby/core/views.py b/openlobby/core/views.py
new file mode 100644
index 0000000..da70d49
--- /dev/null
+++ b/openlobby/core/views.py
@@ -0,0 +1,5 @@
+from django.views.generic.base import TemplateView
+
+
+class IndexView(TemplateView):
+    template_name = 'core/index.html'
diff --git a/openlobby/settings.py b/openlobby/settings.py
index c1a8b8b..3aef4d9 100644
--- a/openlobby/settings.py
+++ b/openlobby/settings.py
@@ -1,4 +1,134 @@
 import os
+import dsnparse
+
+# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = 'DEBUG' in os.environ
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = os.environ.get('SECRET_KEY')
+if not SECRET_KEY:
+    if DEBUG:
+        SECRET_KEY = 'not-secret-at-all'
+    else:
+        raise RuntimeError('Missing SECRET_KEY environment variable.')
+
+ALLOWED_HOSTS = ['*']
+
+
+# Application definition
+
+INSTALLED_APPS = [
+    'django.contrib.admin',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.staticfiles',
+    'openlobby.core',
+]
+
+MIDDLEWARE = [
+    'django.middleware.security.SecurityMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    'django.middleware.csrf.CsrfViewMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
+
+ROOT_URLCONF = 'openlobby.urls'
+
+TEMPLATES = [
+    {
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
+        'DIRS': [],
+        'APP_DIRS': True,
+        'OPTIONS': {
+            'context_processors': [
+                'django.template.context_processors.debug',
+                'django.template.context_processors.request',
+                'django.contrib.auth.context_processors.auth',
+                'django.contrib.messages.context_processors.messages',
+            ],
+        },
+    },
+]
+
+WSGI_APPLICATION = 'openlobby.wsgi.application'
+
+DATABASE_DSN = os.environ.get('DATABASE_DSN', 'postgresql://db:db@localhost:5432/openlobby')
+db = dsnparse.parse(DATABASE_DSN)
+assert db.scheme == 'postgresql'
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.postgresql',
+        'NAME': db.paths[0],
+        'USER': db.username,
+        'PASSWORD': db.password,
+        'HOST': db.host,
+        'PORT': db.port,
+    }
+}
+
+
+# Password validation
+
+AUTH_PASSWORD_VALIDATORS = [
+    {
+        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+    },
+]
+
+
+# Internationalization
+
+LANGUAGE_CODE = 'cs'
+
+TIME_ZONE = 'Europe/Prague'
+
+USE_I18N = True
+
+USE_L10N = True
+
+USE_TZ = True
+
+
+# Static files (CSS, JavaScript, Images)
+
+STATIC_URL = '/static/'
+
+
+LOGGING = {
+    'version': 1,
+    'disable_existing_loggers': False,
+    'handlers': {
+        'console': {
+            'class': 'logging.StreamHandler',
+        },
+    },
+    'loggers': {
+        'django': {
+            'handlers': ['console'],
+            'level': 'INFO' if DEBUG else 'WARNING',
+        },
+    },
+}
+
+
+###############################################################################
+# Custom settings
 
 # Elasticsearch index
 ES_INDEX = os.environ.get('ES_INDEX', 'openlobby')
@@ -6,11 +136,6 @@ ES_INDEX = os.environ.get('ES_INDEX', 'openlobby')
 # default analyzer for text fields
 ES_TEXT_ANALYZER = os.environ.get('ES_TEXT_ANALYZER', 'czech')
 
-# secret key for signing tokens
-SECRET_KEY = os.environ.get('SECRET_KEY')
-if not SECRET_KEY:
-    raise RuntimeError('Missing SECRET_KEY environment variable.')
-
 # signature algorithm JSON Web Tokens
 JWT_ALGORITHM = 'HS512'
 
diff --git a/openlobby/urls.py b/openlobby/urls.py
new file mode 100644
index 0000000..eff7f1a
--- /dev/null
+++ b/openlobby/urls.py
@@ -0,0 +1,6 @@
+from django.urls import path
+from openlobby.core.views import IndexView
+
+urlpatterns = [
+    path('', IndexView.as_view(), name='index'),
+]
diff --git a/openlobby/wsgi.py b/openlobby/wsgi.py
new file mode 100644
index 0000000..5f399cc
--- /dev/null
+++ b/openlobby/wsgi.py
@@ -0,0 +1,16 @@
+"""
+WSGI config for openlobby project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "openlobby.settings")
+
+application = get_wsgi_application()
diff --git a/requirements.txt b/requirements.txt
index 13ed9ee..1503bd6 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,12 +1,16 @@
+Django>=2,<2.1
 graphene>=2.0,<3.0
 flask>=0.12,<0.13
 flask_graphQL>=1.4,<1.5
 elasticsearch-dsl>=5.3.0,<6.0.0
 pytest>=3.2.3,<3.3.0
+pytest-django>=3.1.2,<3.2
 pytest-env>=0.6.2,<0.7
 oic>=0.12.0,<0.13
 pyjwt>=1.5.3,<1.6
 iso8601>=0.1.12,<0.2
-arrow>=0.10.0,<0.11
+arrow>=0.12.0,<0.13
 bleach>=2.1.1,<2.2
 snapshottest>=0.5.0,<0.6
+psycopg2>=2.7,<2.8
+dsnparse>=0.1.11,<0.2
-- 
GitLab