From 418066f4eda3c774426fb16aa710f75348d325e9 Mon Sep 17 00:00:00 2001
From: janmax <mail-github@jmx.io>
Date: Fri, 7 Apr 2017 23:47:51 +0200
Subject: [PATCH] Separated auth_db and implemented default database router

---
 .gitignore                                 | 13 ++++--
 core/templates/core/student_startpage.html | 41 +++++++++----------
 grady/database_router.py                   | 42 ++++++++++++++++++++
 grady/settings/default.py                  | 10 ++++-
 populatedb.py                              | 46 ++++++++++++++--------
 requirements.txt                           |  1 +
 6 files changed, 112 insertions(+), 41 deletions(-)
 create mode 100644 grady/database_router.py

diff --git a/.gitignore b/.gitignore
index c613aeb3..a5c4f26b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,12 +2,15 @@
 # $GIT_DIR/info/exclude or the core.excludesFile configuration variable as
 # described in https://git-scm.com/docs/gitignore
 
+# python specific
 *.egg-info
 *.pot
 *.py[co]
 .tox/
 __pycache__
 MANIFEST
+
+# Django specific
 dist/
 docs/_build/
 docs/locale/
@@ -16,12 +19,16 @@ tests/coverage_html/
 tests/.coverage
 build/
 tests/report/
-db.sqlite3
+*.sqlite3
+
+# project specific
 env-grady/
-.DS_Store
 reinit.sh
 data/
 raw/
 testing_facility/
-login_data.csv
 klausur_*
+*.csv
+
+# operation system
+.DS_Store
diff --git a/core/templates/core/student_startpage.html b/core/templates/core/student_startpage.html
index 14709577..e874fb40 100644
--- a/core/templates/core/student_startpage.html
+++ b/core/templates/core/student_startpage.html
@@ -8,7 +8,7 @@
 
 <div class="row justify-content-center">
   <div class="col-6">
-  <div class="row my-3">
+    <div class="row my-3">
       <h2>Hello {{ student.student }}</h2>
     </div>
 
@@ -26,27 +26,28 @@
           <tr class="align-middle">
             <td class="align-middle">
               {% if submission.seen %}
-                <span class="badge badge-success">Seen</span>
-              {% endif %}</td>
-              <td class="align-middle">{{ submission.type }}</td>
-              <td class="align-middle">
-                {% with submission.feedback_list.all|first as feedback %}
-                {% if feedback.final %}
-                <code> {{ feedback.score }} / {{submission.type.full_score}} </code>
-                {% else %}
-                <span class="badge badge-danger">No Feedback</span>
-                {% endif %}
-                {% endwith %}
-              </td>
-              <td class="align-middle"><a class="btn btn-primary" href="{% url 'SubmissionView' submission.slug %}">View</a></td>
-            </tr>
-            {% endfor %}
-          </tbody>
-        </table>
-      </div>
+              <span class="badge badge-success">Seen</span>
+              {% endif %}
+            </td>
+            <td class="align-middle">{{ submission.type }}</td>
+            <td class="align-middle">
+              {% with submission.feedback_list.all|first as feedback %}
+              {% if feedback.final %}
+              <code> {{ feedback.score }} / {{submission.type.full_score}} </code>
+              {% else %}
+              <span class="badge badge-danger">No Feedback</span>
+              {% endif %}
+              {% endwith %}
+            </td>
+            <td class="align-middle"><a class="btn btn-primary" href="{% url 'SubmissionView' submission.slug %}">View</a></td>
+          </tr>
+          {% endfor %}
+        </tbody>
+      </table>
     </div>
   </div>
+</div>
 
 
 
-  {% endblock body_block %}
+{% endblock body_block %}
diff --git a/grady/database_router.py b/grady/database_router.py
new file mode 100644
index 00000000..0ad5f6b2
--- /dev/null
+++ b/grady/database_router.py
@@ -0,0 +1,42 @@
+import random
+
+
+class AuthRouter(object):
+    """
+    A router to control all database operations on models in the
+    auth application.
+    """
+    def db_for_read(self, model, **hints):
+        """
+        Attempts to read auth models go to auth_db.
+        """
+        if model._meta.app_label == 'auth':
+            return 'auth_db'
+        return None
+
+    def db_for_write(self, model, **hints):
+        """
+        Attempts to write auth models go to auth_db.
+        """
+        if model._meta.app_label == 'auth':
+            return 'auth_db'
+        return None
+
+    def allow_relation(self, obj1, obj2, **hints):
+        """
+        Allow relations if a model in the auth app is involved.
+        """
+        if obj1._meta.app_label == 'auth' or \
+           obj2._meta.app_label == 'auth':
+           return True
+        return None
+
+    def allow_migrate(self, db, app_label, model_name=None, **hints):
+        """
+        Make sure the auth app only appears in the 'auth_db'
+        database.
+        """
+        if app_label == 'auth':
+            return db == 'auth_db'
+        return None
+
diff --git a/grady/settings/default.py b/grady/settings/default.py
index 8643455c..6284427b 100644
--- a/grady/settings/default.py
+++ b/grady/settings/default.py
@@ -78,10 +78,18 @@ WSGI_APPLICATION = 'grady.wsgi.application'
 DATABASES = {
     'default': {
         'ENGINE': 'django.db.backends.sqlite3',
-        'NAME': os.path.join(BASE_DIR, '../db.sqlite3'),
+        'NAME': os.path.join(BASE_DIR, 'default_db.sqlite3'),
+    },
+    'auth_db': {
+        'ENGINE': 'django.db.backends.sqlite3',
+        'NAME': os.path.join(BASE_DIR, 'auth_db.sqlite3'),
     }
 }
 
+DATABASE_ROUTERS = [
+    'grady.database_router.AuthRouter',
+]
+
 
 # Password validation
 # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
diff --git a/populatedb.py b/populatedb.py
index 7b1cdbba..c731261f 100644
--- a/populatedb.py
+++ b/populatedb.py
@@ -4,7 +4,6 @@ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'grady.settings')
 
 import django
 import xkcdpass.xkcd_password as xp
-import getpass
 import json
 import argparse
 from collections import namedtuple
@@ -26,13 +25,14 @@ from core.models import Student, Submission, SubmissionType, Feedback
 if INFO:
     info = print
 else:
-    info = lambda _: 0
+    info = lambda _: None
+
 
 def parseme():
     parser = argparse.ArgumentParser()
     parser.add_argument(
-        '--superuser',
-        help='Superuser will be created users be created',
+        '--create-users',
+        help='Will just populate auth_db',
         action='store_true')
     parser.add_argument(
         '--compiler-output-only',
@@ -87,7 +87,7 @@ def add_submission_type(name,
     if created:
         info(f"- Created Task {task.name}")
     else:
-        info(f"- Got Task {task.name}")
+        info(f"- Task {task.name} was already created")
     return task
 
 
@@ -110,6 +110,7 @@ def add_submission(type, text, student, compiler_output):
     info(f"- Created Submission of Type {sub.type}")
     return sub
 
+
 def add_compiler_output_only(type, text, student, compiler_output):
 
     sub = Submission.objects.get(type=type, student=student)
@@ -132,10 +133,7 @@ def add_auto_feedback(submission, compiler_output):
             return Feedback.DID_NOT_COMPILE, Feedback.NEEDS_REVIEW
         elif compiler_output.endswith('COULD NOT LINK'):
             return Feedback.COULD_NOT_LINK, Feedback.NEEDS_REVIEW
-        elif compiler_output.endswith('WARNINGS'):
-            return None, None
-        else:
-            return None, None
+        return None, None
 
     auto_correct, _ = User.objects.get_or_create(username='auto_correct')
     feedback = Feedback()
@@ -190,8 +188,11 @@ def add_group(group_name):
 
 def create_superuser():
     try:
+        username = 'doncamillo'
+        password = xp.generate_xkcdpassword(wordlist, numwords=2)
+        login_writer.writerow(username, password)
         User.objects.create_superuser(
-            username='doncamillo', password=getpass.getpass(), email='a@b.com')
+            username=username, password=password, email='mail-gardy@jmx.io')
     except Exception as e:
         info("- Superuser was already created.")
         return
@@ -211,10 +212,12 @@ class PopulateDatabase:
 
     def __init__(self, args):
         self.args = args
-        self.create_groups()
-        self.create_user_accounts()
-        self.create_submission_types()
-        self.populate_submissions()
+        if self.args.create_users:
+            self.create_groups()
+            self.create_user_accounts()
+        else: # dirty
+            self.create_submission_types()
+            self.populate_submissions()
 
     def create_groups(self):
         self.student_group  = add_group('Students')
@@ -272,14 +275,23 @@ class PopulateDatabase:
 if __name__ == '__main__':
     args = parseme()
     print("Starting population script...")
+
+    if args.create_users:
+        LOGIN_FILE = 'login_data.csv'
+    else:
+        LOGIN_FILE = '/dev/null'
+
     try:
-        login_data_f = open('login_data.csv', 'a')
-        if os.stat('login_data.csv').st_size == 0:
+        login_data_f = open(LOGIN_FILE, 'a')
+        if os.stat(LOGIN_FILE).st_size == 0:
             login_writer = csv.writer(login_data_f)
             login_writer.writerow(['username', 'password'])
         else:
             login_writer = csv.writer(login_data_f)
+
+        # start the actual population
+        create_superuser()
         PopulateDatabase(args)
+
     finally:
         login_data_f.close()
-    create_superuser()
diff --git a/requirements.txt b/requirements.txt
index e670a894..b5000e3b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,3 +3,4 @@ django-extensions~=1.7.7
 gunicorn~=19.7.0
 psycopg2~=2.7.1
 xkcdpass~=1.9.5
+xlrd~=1.0.0
-- 
GitLab