From adfc494ec17ee43847d7c0c833dad9c178f29358 Mon Sep 17 00:00:00 2001
From: Matthias Runge <mrunge@redhat.com>
Date: Thu, 26 Mar 2015 14:04:18 +0100
Subject: [PATCH] Replace AnonymousUser with AbstractBaseUser

Django-1.8 added _meta classes for User models,
which aren't supported by AnonymousUsers.
AbstractBaseUser honors admin users, thus changes in permissions required

SimpleTest has been deprecated since Django-1.6 and
was now removed.

Partially Implements: blueprint django18

Change-Id: Ie243fd2304421694023f579f49f8fa201e761ba3
---
 openstack_auth/tests/run_tests.py | 10 ++++++++--
 openstack_auth/tests/settings.py  |  1 +
 openstack_auth/user.py            | 35 +++++++++++++++++++++++++++++++++--
 tox.ini                           |  7 ++++---
 4 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/openstack_auth/tests/run_tests.py b/openstack_auth/tests/run_tests.py
index 32ec848..0245262 100644
--- a/openstack_auth/tests/run_tests.py
+++ b/openstack_auth/tests/run_tests.py
@@ -20,7 +20,10 @@ import sys
 os.environ['DJANGO_SETTINGS_MODULE'] = 'openstack_auth.tests.settings'
 
 import django
-from django.test import simple as test_simple
+if django.VERSION < (1, 8, 0):
+    from django.test import simple as test_simple
+else:
+    from django.test import runner
 
 if hasattr(django, 'setup'):
     django.setup()
@@ -35,7 +38,10 @@ def run(*test_args):
         "..",
     )
     sys.path.insert(0, parent)
-    failures = test_simple.DjangoTestSuiteRunner().run_tests(test_args)
+    if django.VERSION < (1, 8, 0):
+        failures = test_simple.DjangoTestSuiteRunner().run_tests(test_args)
+    else:
+        failures = runner.DiscoverRunner().run_tests(test_args)
     sys.exit(failures)
 
 
diff --git a/openstack_auth/tests/settings.py b/openstack_auth/tests/settings.py
index 44ee1ff..355b75f 100644
--- a/openstack_auth/tests/settings.py
+++ b/openstack_auth/tests/settings.py
@@ -32,6 +32,7 @@ MIDDLEWARE_CLASSES = [
 ]
 
 AUTHENTICATION_BACKENDS = ['openstack_auth.backend.KeystoneBackend']
+AUTH_USER_MODEL = 'openstack_auth.User'
 
 OPENSTACK_KEYSTONE_URL = "http://localhost:5000/v3"
 
diff --git a/openstack_auth/user.py b/openstack_auth/user.py
index 132e37b..dcd2c3c 100644
--- a/openstack_auth/user.py
+++ b/openstack_auth/user.py
@@ -16,6 +16,7 @@ import logging
 
 from django.conf import settings
 from django.contrib.auth import models
+from django.db import models as dbmodels
 from keystoneclient.common import cms as keystone_cms
 from keystoneclient import exceptions as keystone_exceptions
 
@@ -117,7 +118,7 @@ class Token(object):
         self.serviceCatalog = auth_ref.service_catalog.get_data()
 
 
-class User(models.AnonymousUser):
+class User(models.AbstractBaseUser, models.PermissionsMixin):
     """A User class with some extra special sauce for Keystone.
 
     In addition to the standard Django user attributes, this class also has
@@ -185,13 +186,17 @@ class User(models.AnonymousUser):
         Unscoped Keystone token.
 
     """
+
+    USERNAME_FIELD = 'id'
+    id = dbmodels.CharField(max_length=240, primary_key=True)
+
     def __init__(self, id=None, token=None, user=None, tenant_id=None,
                  service_catalog=None, tenant_name=None, roles=None,
                  authorized_tenants=None, endpoint=None, enabled=False,
                  services_region=None, user_domain_id=None,
                  user_domain_name=None, domain_id=None, domain_name=None,
                  project_id=None, project_name=None,
-                 is_federated=False, unscoped_token=None):
+                 is_federated=False, unscoped_token=None, password=None):
         self.id = id
         self.pk = id
         self.token = token
@@ -216,11 +221,14 @@ class User(models.AnonymousUser):
         # Unscoped token is used for listing user's project that works
         # for both federated and keystone user.
         self.unscoped_token = unscoped_token
+        self.password = None
 
         # List of variables to be deprecated.
         self.tenant_id = self.project_id
         self.tenant_name = self.project_name
 
+        self.USERNAME_FIELD = self.username
+
     def __unicode__(self):
         return self.username
 
@@ -382,6 +390,23 @@ class User(models.AnonymousUser):
         the user has a permissions matching one of the elements of
         that tuple
         """
+
+        def check_service_enabled(perm):
+            """Permission check for enabled services.
+
+            Check should return false, if service disabled
+            """
+            enabled_service = perm.split("openstack.services.")[1:]
+            if enabled_service:
+                if isinstance(enabled_service, list):
+                    enabled_service = enabled_service[0]
+                for service in self.service_catalog:
+                    service_type = service.get('type', '')
+                    if service_type == enabled_service:
+                        return True
+                return False
+            return True
+
         # If there are no permissions to check, just return true
         if not perm_list:
             return True
@@ -394,4 +419,10 @@ class User(models.AnonymousUser):
                 # check that a permission in the tuple matches
                 if not self.has_a_matching_perm(perm, obj):
                     return False
+            # check if service disabled
+            if isinstance(perm, basestring):
+                return check_service_enabled(perm)
+            else:
+                for p in perm:
+                    return check_service_enabled(p)
         return True
diff --git a/tox.ini b/tox.ini
index 6e4e30c..a4909ee 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
 [tox]
-minversion = 1.6
+minversion = 1.8
 skipsdist = True
 envlist = py27,py27dj14,py27dj15,py27dj16,pep8,py33,py34
 
@@ -24,14 +24,15 @@ commands = pip install django>=1.6,<1.7
 commands = pip install django>=1.5,<1.6
            python openstack_auth/tests/run_tests.py {posargs}
 
-[testenv:py27dj14]
-commands = pip install django>=1.4,<1.5
+[testenv:py27dj17]
+commands = pip install django<1.8
            python openstack_auth/tests/run_tests.py {posargs}
 
 [testenv:pep8]
 setenv = DJANGO_SETTINGS_MODULE=openstack_auth.tests.settings
 commands = flake8
 
+
 [testenv:venv]
 commands = {posargs}
 
-- 
1.9.1

