193 lines
6.9 KiB
Python
193 lines
6.9 KiB
Python
# mandayejs - saml reverse proxy
|
|
# Copyright (C) 2015 Entr'ouvert
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify it
|
|
# under the terms of the GNU Affero General Public License as published
|
|
# by the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
from __future__ import absolute_import
|
|
|
|
import logging
|
|
import urlparse
|
|
|
|
from django.contrib.auth.models import User
|
|
from django.contrib.auth.decorators import login_required
|
|
from django.contrib.auth.signals import user_logged_out
|
|
from django.contrib import messages
|
|
from django.dispatch import receiver
|
|
from django.http import HttpResponseRedirect, HttpResponse
|
|
from django.shortcuts import render, resolve_url
|
|
from django.template import RequestContext
|
|
from django.views.generic.base import TemplateView
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
from django.utils.translation import ugettext_lazy as _
|
|
from django.template import Template
|
|
|
|
from .models import UserCredentials
|
|
from mandayejs.mandaye.forms import FormFactory
|
|
from mandayejs.mandaye.utils import exec_phantom, cookie_builder,\
|
|
get_login_info, get_logout_info
|
|
from mandayejs.applications import get_app_settings
|
|
|
|
from mellon.views import logout as mellon_logout
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def home(request):
|
|
return HttpResponseRedirect('/')
|
|
|
|
|
|
def logout(request, *args, **kwargs):
|
|
logger.debug("running slo")
|
|
response = mellon_logout(request, *args, **kwargs)
|
|
logger.debug("deleting cookies")
|
|
app_settings = get_app_settings()
|
|
for cookie in app_settings.SITE_AUTH_COOKIE_KEYS:
|
|
response.delete_cookie(cookie)
|
|
if getattr(app_settings, 'SITE_LOGIN_PATH_PREFIX', None):
|
|
response.delete_cookie(cookie, path=app_settings.SITE_LOGIN_PATH_PREFIX)
|
|
return response
|
|
|
|
|
|
@receiver(user_logged_out)
|
|
def local_logout(sender, request, user, **kwargs):
|
|
data = get_logout_info(request)
|
|
logger.debug(data)
|
|
result = exec_phantom(data, script='do_logout.js')
|
|
logger.debug(result)
|
|
|
|
|
|
class Panel(TemplateView):
|
|
template_name = 'mandaye/panel.html'
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(Panel, self).get_context_data(**kwargs)
|
|
app_settings = get_app_settings()
|
|
scripts = getattr(app_settings, 'SITE_APP_SCRIPTS', None)
|
|
context['site_scripts'] = scripts
|
|
context['force_redirect_url'] = getattr(app_settings, 'SITE_FORCE_REDIRECT_URL', '')
|
|
context['force_redirect_locator'] = getattr(app_settings, 'SITE_FORCE_REDIRECT_LOCATOR', '')
|
|
context['logout_locator'] = getattr(app_settings, 'SITE_LOGOUT_LOCATOR', '')
|
|
context['is_linked'] = self.is_account_linked()
|
|
return context
|
|
|
|
def is_account_linked(self):
|
|
"""Check if user account is associated
|
|
"""
|
|
try:
|
|
user = User.objects.get(username=self.request.user.username)
|
|
return user.usercredentials_set.get().linked
|
|
except (User.DoesNotExist, UserCredentials.DoesNotExist) as e:
|
|
return False
|
|
|
|
|
|
panel = Panel.as_view()
|
|
|
|
|
|
@login_required
|
|
def post_login(request, *args, **kwargs):
|
|
try:
|
|
user = User.objects.get(username=request.user.username)
|
|
logger.debug(user)
|
|
credentials = UserCredentials.objects.get(user=user)
|
|
logger.debug(credentials)
|
|
except (UserCredentials.DoesNotExist,):
|
|
return HttpResponseRedirect(resolve_url('associate'))
|
|
next_url = request.GET.get('next_url')
|
|
return render(request, 'mandaye/post-login.html', {'next_url': next_url})
|
|
|
|
|
|
@login_required
|
|
@csrf_exempt
|
|
def associate(request, *args, **kwargs):
|
|
if request.method == 'POST':
|
|
|
|
form = FormFactory(request.POST)
|
|
if form.is_valid():
|
|
credentials, created = UserCredentials.objects.get_or_create(user=request.user)
|
|
credentials.locators = form.cleaned_data
|
|
credentials.linked = False
|
|
credentials.save()
|
|
|
|
return HttpResponseRedirect(resolve_url('post-login'))
|
|
else:
|
|
form = FormFactory()
|
|
app_settings = get_app_settings()
|
|
response = render(request, 'mandaye/associate.html', {
|
|
'form': form, 'app': {
|
|
'name': app_settings.get_name(), 'slug': app_settings.get_slug()}})
|
|
return response
|
|
|
|
|
|
@login_required
|
|
def dissociate(request, *args, **kwargs):
|
|
try:
|
|
c_user = UserCredentials.objects.get(user__username=request.user.username)
|
|
c_user.delete()
|
|
logger.debug("{} dissacioted".format(c_user.user.username))
|
|
return HttpResponseRedirect(
|
|
request.META.get(
|
|
'HTTP_REFERER', app_settings.SITE_LOGIN_PATH)
|
|
)
|
|
except (UserCredentials.DoesNotExist,):
|
|
return HttpResponseRedirect(resolve_url('associate'))
|
|
|
|
|
|
@login_required
|
|
def post_login_do(request, *args, **kwargs):
|
|
user = User.objects.get(username=request.user.username)
|
|
try:
|
|
credentials = user.usercredentials_set.get()
|
|
except (UserCredentials.DoesNotExist,):
|
|
return HttpResponseRedirect(resolve_url('associate'))
|
|
|
|
login_info = get_login_info(request, credentials)
|
|
|
|
logger.debug(login_info)
|
|
login_info['locators'] = [credentials.to_login_info(decrypt=True)]
|
|
result = exec_phantom(login_info)
|
|
logger.debug(result)
|
|
|
|
if result.get('result') == 'failure':
|
|
logger.debug('authentication failed')
|
|
logger.debug("redirecting to {}".format(resolve_url('associate')))
|
|
credentials.delete()
|
|
messages.error(request, _('wrong user credentials'))
|
|
url = resolve_url('associate')
|
|
elif result.get('result') == 'timeout':
|
|
messages.error(request, _('server took too long to respond'))
|
|
url = resolve_url('associate')
|
|
elif result.get('result') == 'json_error':
|
|
messages.error(request, _('invalid response from server'))
|
|
url = resolve_url('associate')
|
|
elif result.get('result') == 'redirect':
|
|
url = urlparse.urlsplit(result.get('url', '/'))
|
|
url = urlparse.urlunsplit((None, None, url.path, url.query, url.fragment))
|
|
else:
|
|
credentials.linked = True
|
|
credentials.save()
|
|
url = result.get('url', '/')
|
|
|
|
# redirect user only if SSO successful
|
|
if request.GET.get('next_url') and result['result'] == 'ok':
|
|
url = request.GET['next_url']
|
|
template = Template('<script type="text/javascript">\
|
|
window.top.location = "{{url}}";</script>')
|
|
context = RequestContext(request, {'url': url})
|
|
response = HttpResponse(template.render(context))
|
|
if result.get('headers', None):
|
|
response.cookies = cookie_builder(result.get('headers'))
|
|
|
|
return response
|