123 lines
3.9 KiB
Python
123 lines
3.9 KiB
Python
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
# implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
from six.moves.urllib import parse as urlparse
|
|
|
|
from django.conf import settings
|
|
from django.contrib import auth
|
|
from django.contrib.auth import middleware
|
|
from django.contrib.auth import models
|
|
from django.utils import timezone
|
|
|
|
from keystoneclient.v2_0 import client as client_v2
|
|
from keystoneclient.v3 import client as client_v3
|
|
|
|
|
|
"""
|
|
We need the request object to get the user, so we'll slightly modify the
|
|
existing django.contrib.auth.get_user method. To do so we update the
|
|
auth middleware to point to our overridden method.
|
|
|
|
Calling the "patch_middleware_get_user" method somewhere like our urls.py
|
|
file takes care of hooking it in appropriately.
|
|
"""
|
|
|
|
|
|
def middleware_get_user(request):
|
|
if not hasattr(request, '_cached_user'):
|
|
request._cached_user = get_user(request)
|
|
return request._cached_user
|
|
|
|
|
|
def get_user(request):
|
|
try:
|
|
user_id = request.session[auth.SESSION_KEY]
|
|
backend_path = request.session[auth.BACKEND_SESSION_KEY]
|
|
backend = auth.load_backend(backend_path)
|
|
backend.request = request
|
|
user = backend.get_user(user_id) or models.AnonymousUser()
|
|
except KeyError:
|
|
user = models.AnonymousUser()
|
|
return user
|
|
|
|
|
|
def patch_middleware_get_user():
|
|
middleware.get_user = middleware_get_user
|
|
auth.get_user = get_user
|
|
|
|
|
|
""" End Monkey-Patching. """
|
|
|
|
|
|
def check_token_expiration(token):
|
|
""" Timezone-aware checking of the auth token's expiration timestamp.
|
|
|
|
Returns ``True`` if the token has not yet expired, otherwise ``False``.
|
|
"""
|
|
expiration = token.expires
|
|
if settings.USE_TZ and timezone.is_naive(expiration):
|
|
# Presumes that the Keystone is using UTC.
|
|
expiration = timezone.make_aware(expiration, timezone.utc)
|
|
# In case we get an unparseable expiration timestamp, return False
|
|
# so you can't have a "forever" token just by breaking the expires param.
|
|
if expiration:
|
|
return expiration > timezone.now()
|
|
else:
|
|
return False
|
|
|
|
|
|
# From django.contrib.auth.views
|
|
# Added in Django 1.4.3, 1.5b2
|
|
# Vendored here for compatibility with old Django versions.
|
|
def is_safe_url(url, host=None):
|
|
"""
|
|
Return ``True`` if the url is a safe redirection (i.e. it doesn't point to
|
|
a different host).
|
|
|
|
Always returns ``False`` on an empty url.
|
|
"""
|
|
if not url:
|
|
return False
|
|
netloc = urlparse.urlparse(url)[1]
|
|
return not netloc or netloc == host
|
|
|
|
|
|
# Helper for figuring out keystone version
|
|
# Implementation will change when API version discovery is available
|
|
def get_keystone_version():
|
|
return getattr(settings, 'OPENSTACK_API_VERSIONS', {}).get('identity', 2.0)
|
|
|
|
|
|
def get_keystone_client():
|
|
if get_keystone_version() < 3:
|
|
return client_v2
|
|
else:
|
|
return client_v3
|
|
|
|
|
|
def get_project_list(*args, **kwargs):
|
|
if get_keystone_version() < 3:
|
|
auth_url = kwargs.get('auth_url', '').replace('v3', 'v2.0')
|
|
kwargs['auth_url'] = auth_url
|
|
client = get_keystone_client().Client(*args, **kwargs)
|
|
projects = client.tenants.list()
|
|
else:
|
|
auth_url = kwargs.get('auth_url', '').replace('v2.0', 'v3')
|
|
kwargs['auth_url'] = auth_url
|
|
client = get_keystone_client().Client(*args, **kwargs)
|
|
client.management_url = auth_url
|
|
projects = client.projects.list(user=kwargs.get('user_id'))
|
|
|
|
projects.sort(key=lambda project: project.name.lower())
|
|
return projects
|