# HG changeset patch # User ymh # Date 1395415521 -3600 # Node ID 4e7178ce568814b6f2136b6aaf7f8a54f91fe9ec # Parent a76a79affb4a6c5296fa121e1b2e438b3175d6f3 Implement single sign on with egonomy - mobenfact diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/__init__.py --- a/src/egonomy/__init__.py Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/__init__.py Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -VERSION = (0, 8, 9, "final", 1) +VERSION = (0, 9, 0, "final", 0) VERSION_STR = unicode(".".join(map(lambda i:"%02d" % (i,), VERSION[:2]))) diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/auth/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/egonomy/auth/__init__.py Fri Mar 21 16:25:21 2014 +0100 @@ -0,0 +1,31 @@ +from django.conf import settings +from django.utils.crypto import get_random_string + +from egonomy.utils import unix_time, encodeAES, decodeAES + + +def get_egonomy_token(request): + + if request.user.is_authenticated(): + sessionid = request.session.session_key + salt = get_random_string(length=getattr(settings, 'EGONOMY_SALT_LENGTH', 12)) + + return encodeAES("|".join([sessionid,salt])) + else: + return None + +#TODO : check +def parse_egonomy_token(token): + + #retore padding if needed + token += "=" * ((4 - len(token) % 4) % 4) + decoded_token = decodeAES(str(token)) + sessionid, salt = decoded_token.split("|") + + return {'sessionid': sessionid, 'salt': salt} + + +def clean_egonomy_username(username, is_internal): + prefix = settings.EGONOMY_USER_PREFIX + return (prefix if ( prefix not in username and not is_internal) else "") + username + diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/auth/backends.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/egonomy/auth/backends.py Fri Mar 21 16:25:21 2014 +0100 @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +''' +Created on Mar 19, 2014 + +@author: ymh +''' + +import logging + +from django.conf import settings +from django.contrib.auth import get_user_model +import requests + +from egonomy.auth import clean_egonomy_username + + +logger = logging.getLogger(__name__) + +class EgonomyBackend(object): + """ + Authenticate against egonomy. + """ + + def authenticate(self, username=None, password=None): + + + User = get_user_model() + login_url = getattr(settings, "EGONOMY_LOGIN_URL", None) + + if not login_url: + return None + + logger.debug("EgonomyBackend.authenticate Calling %s" % login_url) + res_login = requests.post(login_url, data={'user_name': username, 'user_password': password, 'login':'true'}) + + logger.debug("EgonomyBackend.authenticate Response received %s" % res_login.text) + + try: + res_json = res_login.json() + except: + return None + + if res_json.get("success", False): + username = clean_egonomy_username(username, False) + user, _ = User.objects.get_or_create(**{ + User.USERNAME_FIELD: username + }) + return user + return None + + def get_user(self, user_id): + User = get_user_model() + try: + return User.objects.get(pk=user_id) + except User.DoesNotExist: + return None \ No newline at end of file diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/auth/middleware.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/egonomy/auth/middleware.py Fri Mar 21 16:25:21 2014 +0100 @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +''' +Created on Mar 19, 2014 + +@author: ymh +''' +import logging + +from django.conf import settings +from django.contrib import auth +from django.contrib.auth import get_user_model +from django.core.exceptions import ImproperlyConfigured +import requests + +from egonomy.auth import clean_egonomy_username +from django.http.response import HttpResponseBadRequest + + +logger = logging.getLogger(__name__) + +class EgonomyUserTokenMiddleware(object): + + parameter = (getattr(settings, "EGONOMY_TOKEN_NAME", None) or "egonomytoken") + + def process_request(self, request): + if not hasattr(request, 'user'): + raise ImproperlyConfigured( + "The Egonomy user token auth middleware requires the" + " authentication middleware to be installed. Edit your" + " MIDDLEWARE_CLASSES setting to insert" + " 'django.contrib.auth.middleware.AuthenticationMiddleware'" + " before the EgonomyUserTokenMiddleware class.") + + logger.debug("EgonomyUserTokenMiddleware called") + token = request.POST.get(self.parameter,request.GET.get(self.parameter,None)) + if not token: + return + + logger.debug("EgonomyUserTokenMiddleware token found %s" % token) + + token_check_url = getattr(settings, "EGONOMY_TOKEN_CHECK_URL", None) + if not token_check_url: + return + + res_check = requests.get(token_check_url, params={self.parameter:token}) + logger.debug("EgonomyUserTokenMiddleware json raw %s" % res_check.text) + res_json = res_check.json() + + logger.debug("EgonomyUserTokenMiddleware json %s" % res_json ) + if not res_json.get('success', False): + return + + username = res_json.get('username', None) + if not username : + return HttpResponseBadRequest("Empty username") + + #"namespace" username + username = clean_egonomy_username(username, res_json.get('external', True)) + # If the user is already authenticated and that user is the user we are + # getting passed in the headers, then the correct user is already + # persisted in the session and we don't need to continue. + if request.user.is_authenticated() and request.user.get_username() == username: + return + else: + auth.logout(request) + + # create user if not known + # login user + UserModel = get_user_model() + + # Note that this could be accomplished in one try-except clause, but + # instead we use get_or_create when creating unknown users since it has + # built-in safeguards for multiple threads. + user, _ = UserModel.objects.get_or_create(**{ + UserModel.USERNAME_FIELD: username + }) + + if user: + user.backend = 'django.contrib.auth.backends.ModelBackend' + # User is valid. Set request.user and persist user in the session + # by logging the user in. + request.user = user + + auth.login(request, user) diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/config.py.tmpl --- a/src/egonomy/config.py.tmpl Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/config.py.tmpl Fri Mar 21 16:25:21 2014 +0100 @@ -151,4 +151,11 @@ EMAIL_HOST = '%(email_host)s' EMAIL_HOST_USER = '%(email_host_user)s' EMAIL_HOST_PASSWORD = '%(email_host_password)s' -EMAIL_PORT = %(email_port)d +EMAIL_PORT = %(email_port)d + +EGONOMY_URL = '#' +EGONOMY_LOGIN_URL ='' +EGONOMY_SALT_LENGTH = 12 +EGONOMY_TOKEN_NAME = 'egonomytoken' +EGONOMY_TOKEN_CHECK_URL = '' + diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/settings.py --- a/src/egonomy/settings.py Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/settings.py Fri Mar 21 16:25:21 2014 +0100 @@ -102,6 +102,7 @@ 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', + 'egonomy.auth.middleware.EgonomyUserTokenMiddleware' # Uncomment the next line for simple clickjacking protection: # 'django.middleware.clickjacking.XFrameOptionsMiddleware', ) @@ -182,11 +183,24 @@ } } +AUTHENTICATION_BACKENDS = ( + 'django.contrib.auth.backends.ModelBackend', + 'egonomy.auth.backends.EgonomyBackend', +) + HAYSTACK_SIGNAL_PROCESSOR = 'egonomy.search_indexes.EgonomySignalProcessor' ACCOUNT_ACTIVATION_DAYS = 7 TASTYPIE_DEFAULT_FORMATS = ['json'] +EGONOMY_URL = '#' +EGONOMY_LOGIN_URL ='' +EGONOMY_SALT_LENGTH = 12 +EGONOMY_TOKEN_NAME = 'egonomytoken' +EGONOMY_TOKEN_CHECK_URL = '' + +EGONOMY_USER_PREFIX = 'egonomy:' + from .config import * #@UnusedWildImport if not "SRC_BASE_URL" in locals(): diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/egonomy_all_collections.html --- a/src/egonomy/templates/egonomy_all_collections.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/egonomy_all_collections.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -{% extends "egonomy_newbase.html" %} +{% extends "egonomy_base.html" %} {% load static %} {% load i18n %} {% load thumbnail %} diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/egonomy_all_fragments.html --- a/src/egonomy/templates/egonomy_all_fragments.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/egonomy_all_fragments.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -{% extends "egonomy_newbase.html" %} +{% extends "egonomy_base.html" %} {% load static %} {% load i18n %} {% load thumbnail %} diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/egonomy_all_pictures.html --- a/src/egonomy/templates/egonomy_all_pictures.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/egonomy_all_pictures.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -{% extends "egonomy_newbase.html" %} +{% extends "egonomy_base.html" %} {% load static %} {% load i18n %} {% load thumbnail %} diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/egonomy_annotate_picture.html --- a/src/egonomy/templates/egonomy_annotate_picture.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/egonomy_annotate_picture.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -{% extends "egonomy_newbase.html" %} +{% extends "egonomy_base.html" %} {% load static %} {% load absstatic %} {% load i18n %} diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/egonomy_base.html --- a/src/egonomy/templates/egonomy_base.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/egonomy_base.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,68 +1,150 @@ {% load static %} {% load i18n %} -{#% load analytics %#} - - {% block head %} - - - - TagItAll by eGonomy » {% block title %}Base{% endblock %} - {% block css_declaration %}{% endblock %} - {% block css_import %} - - {% endblock %} - {% block css_page %}{% endblock %} - {% block js_import %} - - {% endblock %} - {% block js_inline %} - - {% endblock %} - + + + + +{% block head %} + + + + + TagItAll by eGonomy » {% block title %}Base{% endblock %} + {% block css_declaration %}{% endblock %} + {% block css_import %} + + + {% endblock %} - -
+ {% block css_page %}{% endblock %} + +{% endblock %} + +
+ {% if current_user_collection_list %} +
-

TagItAll {% trans "by" %} eGonomy

-
- - - -
- +

{% trans "Add to the collection" %}

+
+
+
+

+ + +

+

+ + +

+ + + {% csrf_token %} +
+
-
-
- {% block content %} - {% endblock %} -
-
+
+
+

egonomy

+
+ +
-
- {#% analytics %#} - - + +
+ {% block content %} + {% endblock %} +
+
+ +

© IRI 2013 - v{{ VERSION }}

+
+
+ {% block js_common %} + + + + {% endblock %} + + {% block js_page %} + {% endblock %} + + + \ No newline at end of file diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/egonomy_create_fragment.html --- a/src/egonomy/templates/egonomy_create_fragment.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/egonomy_create_fragment.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -{% extends "egonomy_newbase.html" %} +{% extends "egonomy_base.html" %} {% load static %} {% load i18n %} {% load thumbnail %} diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/egonomy_home.html --- a/src/egonomy/templates/egonomy_home.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/egonomy_home.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -{% extends "egonomy_newbase.html" %} +{% extends "egonomy_base.html" %} {% load static %} {% load i18n %} {% load thumbnail %} diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/egonomy_newbase.html --- a/src/egonomy/templates/egonomy_newbase.html Mon Mar 17 16:18:45 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,150 +0,0 @@ -{% load static %} -{% load i18n %} - - - - - -{% block head %} - - - - - TagItAll by eGonomy » {% block title %}Base{% endblock %} - {% block css_declaration %}{% endblock %} - {% block css_import %} - - - - {% endblock %} - {% block css_page %}{% endblock %} - -{% endblock %} - -
- {% if current_user_collection_list %} -
-
-

{% trans "Add to the collection" %}

- -
-
-
-

- - -

-

- - -

- - - {% csrf_token %} -
-
-
-
-

{% trans "The item was successfully added to the collection" %}

-

{% trans "See the collection" %}

-
-
-

{% trans "An error occurred while adding the item to the collection" %}

-
- {% endif %} - {% block popins %}{% endblock %} -
-
-
-

egonomy

-
- - -
-
-
- {% block content %} - {% endblock %} -
-
- -

© IRI 2013 - v{{ VERSION }}

-
-
- {% block js_common %} - - - - {% endblock %} - - {% block js_page %} - {% endblock %} - - - \ No newline at end of file diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/egonomy_view_collection.html --- a/src/egonomy/templates/egonomy_view_collection.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/egonomy_view_collection.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -{% extends "egonomy_newbase.html" %} +{% extends "egonomy_base.html" %} {% load static %} {% load i18n %} diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/egonomy_view_fragment.html --- a/src/egonomy/templates/egonomy_view_fragment.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/egonomy_view_fragment.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -{% extends "egonomy_newbase.html" %} +{% extends "egonomy_base.html" %} {% load static %} {% load i18n %} {% load thumbnail %} diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/registration/activate.html --- a/src/egonomy/templates/registration/activate.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/registration/activate.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -{% extends "egonomy_newbase.html" %} +{% extends "egonomy_base.html" %} {% load i18n %} {% block content %} diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/registration/activation_complete.html --- a/src/egonomy/templates/registration/activation_complete.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/registration/activation_complete.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -{% extends "egonomy_newbase.html" %} +{% extends "egonomy_base.html" %} {% load i18n %} {% block content %} diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/registration/login.html --- a/src/egonomy/templates/registration/login.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/registration/login.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -{% extends "egonomy_newbase.html" %} +{% extends "egonomy_base.html" %} {% load static %} {% load i18n %} diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/registration/password_change_done.html --- a/src/egonomy/templates/registration/password_change_done.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/registration/password_change_done.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -{% extends "egonomy_newbase.html" %} +{% extends "egonomy_base.html" %} {% load i18n %} {% block content %} diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/registration/password_change_form.html --- a/src/egonomy/templates/registration/password_change_form.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/registration/password_change_form.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -{% extends "egonomy_newbase.html" %} +{% extends "egonomy_base.html" %} {% load i18n %} {% block content %} diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/registration/password_reset_complete.html --- a/src/egonomy/templates/registration/password_reset_complete.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/registration/password_reset_complete.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -{% extends "egonomy_newbase.html" %} +{% extends "egonomy_base.html" %} {% load i18n %} {% block content %} diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/registration/password_reset_confirm.html --- a/src/egonomy/templates/registration/password_reset_confirm.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/registration/password_reset_confirm.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -{% extends "egonomy_newbase.html" %} +{% extends "egonomy_base.html" %} {% load i18n %} {% block content %} diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/registration/password_reset_done.html --- a/src/egonomy/templates/registration/password_reset_done.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/registration/password_reset_done.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -{% extends "egonomy_newbase.html" %} +{% extends "egonomy_base.html" %} {% load i18n %} {% block content %} diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/registration/password_reset_form.html --- a/src/egonomy/templates/registration/password_reset_form.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/registration/password_reset_form.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -{% extends "egonomy_newbase.html" %} +{% extends "egonomy_base.html" %} {% load i18n %} {% block content %} diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/registration/registration_complete.html --- a/src/egonomy/templates/registration/registration_complete.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/registration/registration_complete.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -{% extends "egonomy_newbase.html" %} +{% extends "egonomy_base.html" %} {% load i18n %} {% block content %} diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/templates/registration/registration_form.html --- a/src/egonomy/templates/registration/registration_form.html Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/templates/registration/registration_form.html Fri Mar 21 16:25:21 2014 +0100 @@ -1,4 +1,4 @@ -{% extends "egonomy_newbase.html" %} +{% extends "egonomy_base.html" %} {% load i18n %} {% block content %} diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/urls.py --- a/src/egonomy/urls.py Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/urls.py Fri Mar 21 16:25:21 2014 +0100 @@ -39,6 +39,8 @@ # login logout view url(r'^login/', 'django.contrib.auth.views.login', name='login'), url(r'^logout/', 'django.contrib.auth.views.logout', name='logout'), + url(r'^ajax-login/', 'egonomy.views.ajax_login', name='ajax_login'), + url(r'^check-egonomy-token/(?P[\w\d\-_=]*)$', 'egonomy.views.check_egonomy_token', name='check_egonomy_token'), (r'^api/', include('egonomy.api.urls')), (r'^accounts/', include('registration.backends.default.urls')), ) diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/utils/__init__.py --- a/src/egonomy/utils/__init__.py Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/utils/__init__.py Fri Mar 21 16:25:21 2014 +0100 @@ -0,0 +1,30 @@ +import base64 +import datetime +import hashlib + +from Crypto.Cipher import AES # encryption library +from django.conf import settings +import pytz + + +def unix_time(dt): + epoch = datetime.datetime.utcfromtimestamp(0).replace(tzinfo=pytz.UTC) + delta = dt - epoch + return delta.total_seconds() + +BLOCK_SIZE = 32 +# the character used for padding--with a block cipher such as AES, the value +# you encrypt must be a multiple of BLOCK_SIZE in length. This character is +# used to ensure that your value is always a multiple of BLOCK_SIZE +PADDING = '{' + +# one-liner to sufficiently pad the text to be encrypted +pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING + +# create a cipher object using the random secret +cipher = AES.new(hashlib.md5(settings.SECRET_KEY).hexdigest()) + +# one-liners to encrypt/encode and decrypt/decode a string +# encrypt with AES, encode with base64 +encodeAES = lambda s: base64.urlsafe_b64encode(cipher.encrypt(pad(s))) +decodeAES = lambda e: cipher.decrypt(base64.urlsafe_b64decode(e)).rstrip(PADDING) diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/utils/context_processors.py --- a/src/egonomy/utils/context_processors.py Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/utils/context_processors.py Fri Mar 21 16:25:21 2014 +0100 @@ -1,5 +1,13 @@ +from django.conf import settings + import egonomy +from egonomy.auth import get_egonomy_token + def egonomy_context(request): - return {'VERSION': egonomy.get_version() } + egonomy_url = getattr(settings, 'EGONOMY_URL', '#') + egonomy_token = get_egonomy_token(request) + egonomy_token_name = ( getattr(settings, 'EGONOMY_TOKEN_NAME', 'egonomytoken') or 'egonomytoken') + return {'VERSION': egonomy.get_version(), 'EGONOMY_URL': "%s?%s=%s" % (egonomy_url, egonomy_token_name, egonomy_token) if egonomy_token else egonomy_url } + diff -r a76a79affb4a -r 4e7178ce5688 src/egonomy/views.py --- a/src/egonomy/views.py Mon Mar 17 16:18:45 2014 +0100 +++ b/src/egonomy/views.py Fri Mar 21 16:25:21 2014 +0100 @@ -1,34 +1,42 @@ from datetime import datetime +import json +import logging +import os +import subprocess +from unicodedata import normalize +import uuid + from django.conf import settings +from django.contrib.auth import authenticate, login, get_user_model, SESSION_KEY, \ + load_backend, BACKEND_SESSION_KEY from django.contrib.auth.decorators import login_required -from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType from django.core.paginator import Paginator, InvalidPage, EmptyPage from django.core.urlresolvers import reverse from django.db.models.aggregates import Max -from django.http.response import HttpResponseForbidden, HttpResponse +from django.http.response import HttpResponseForbidden, HttpResponse, \ + HttpResponseBadRequest from django.shortcuts import get_object_or_404, render_to_response, redirect from django.template import RequestContext +from django.utils.importlib import import_module from django.utils.translation import ugettext as _ -from egonomy.models import ImageMetadata, Image, Fragment, ImageInfo, Collection,\ +from django.views.decorators.csrf import csrf_exempt +from haystack.query import RelatedSearchQuerySet +import requests +from sorl.thumbnail import default, get_thumbnail +from sorl.thumbnail.images import ImageFile + +from egonomy.auth import parse_egonomy_token +from egonomy.models import ImageMetadata, Image, Fragment, ImageInfo, Collection, \ CollectionItem from egonomy.search_indexes import QueryParser from egonomy.search_indexes.paginator import SearchPaginator from egonomy.search_indexes.query import ModelRelatedSearchQuerySet from egonomy.utils.queries import cache_generics -from haystack.query import RelatedSearchQuerySet -from sorl.thumbnail import default, get_thumbnail -from sorl.thumbnail.images import ImageFile -from unicodedata import normalize -import json -import os -import requests -import subprocess -import uuid + -import logging logger = logging.getLogger(__name__) - +User = get_user_model() def home(request): @@ -366,7 +374,7 @@ frg.image = img frg.coordinates = frg_path # We build the svg xml - file_path = os.path.join(settings.MEDIA_ROOT, str(img.info.image_file)) + filepath = os.path.join(settings.MEDIA_ROOT, str(img.info.image_file)) image_file = default.kvstore.get_or_set(ImageFile(img.info.image_file)) ratio = int(100 * frg.ratio * image_file.ratio) svg = '\n\ @@ -375,10 +383,10 @@ \n\ \n\ \n\ - \n\ - \n\ + \n\ + \n\ ' - # We save the svg file + # We save the svg filepath uid = str(uuid.uuid1()) svg_file_path = os.path.join(settings.BATIK_RASTERIZER_TEMP_FOLDER, uid + '.svg') svg_file = open(svg_file_path,'w') @@ -675,7 +683,7 @@ try: col_pk = int(col_pk) except: - return HttpResponse("Collection number invalid.", status=400) + return HttpResponse("Collection number invalid.", status_code=400) col = get_object_or_404(Collection.objects.select_related('author'), pk=col_pk) # We check if the current user is the collection's author if col.author != request.user: @@ -692,10 +700,10 @@ try: item_id = int(item_id) except: - return HttpResponse("Fragment number invalid.", status=400) + return HttpResponse("Fragment number invalid.", status_code=400) item = get_object_or_404(Fragment, pk=item_id) else: - return HttpResponse("item-type must be 'image' or 'fragment'.", status=400) + return HttpResponse("item-type must be 'image' or 'fragment'.", status_code=400) col_item = CollectionItem() col_item.collection = col @@ -729,7 +737,7 @@ try: col_pk = int(col_pk) except: - return HttpResponse("Collection number invalid.", status=400) + return HttpResponse("Collection number invalid.", status_code=400) col = get_object_or_404(Collection.objects.select_related('author'), pk=col_pk) # We check if the current user is the collection's author if col.author != request.user: @@ -740,7 +748,7 @@ # Test item's pk if not item_pk: - return HttpResponse("item_pk must be set.", status=400) + return HttpResponse("item_pk must be set.", status_code=400) # Get item item = get_object_or_404(CollectionItem, pk=item_pk) # Everything has been checked, we can delete the item @@ -764,7 +772,7 @@ try: col_pk = int(col_pk) except: - return HttpResponse("Collection number invalid.", status=400) + return HttpResponse("Collection number invalid.", status_code=400) col = get_object_or_404(Collection.objects.select_related('author'), pk=col_pk) # We check if the current user is the collection's author if col.author != request.user: @@ -775,11 +783,11 @@ # Test item's pk if not item_pk: - return HttpResponse("item_pk must be set.", status=400) + return HttpResponse("item_pk must be set.", status_code=400) # Get item item = get_object_or_404(CollectionItem, pk=item_pk) if item.collection != col: - return HttpResponse("Item and collection are not related.", status=400) + return HttpResponse("Item and collection are not related.", status_code=400) # Everything has been checked, we can modify and save the item item.description = description item.save() @@ -787,8 +795,6 @@ # It is an ajax call, we juste return "ok" return HttpResponse("modifyok") - - @login_required def import_collection(request): @@ -855,3 +861,91 @@ +@csrf_exempt +def ajax_login(request): + if request.method == 'POST': + username = request.POST.get('username', '').strip() + password = request.POST.get('password', '').strip() + if username and password: + # Test username/password combination + user = authenticate(username=username, password=password) + # Found a match + if user is not None: + # User is active + if user.is_active: + # Officially log the user in + login(request, user) + data = {'success': True} + else: + data = {'success': False, 'error': 'User is not active'} + else: + data = {'success': False, 'error': 'Wrong username and/or password'} + + return HttpResponse(json.dumps(data), mimetype='application/json') + + # Request method is not POST or one of username or password is missing + return HttpResponseBadRequest() + + + +def check_egonomy_token(request, token): + + logger.debug("TOKEN : " + token) + if not token: + return HttpResponseBadRequest("token must be provided") + + token_items = parse_egonomy_token(token) + + session_key = token_items.get('sessionid', None) + salt = token_items.get('salt', None) + + error_msg = None + + if len(token_items) != 2: + error_msg = "Bad token size" + elif not session_key: + error_msg = 'No session id in token' + elif not salt or len(salt) != getattr(settings, 'EGONOMY_SALT_LENGTH', 12): + error_msg = 'Bad token format' + + if error_msg: + return HttpResponseBadRequest("Bad token format : %s" % error_msg) + + res_msg = {} + + #get session + engine = import_module(settings.SESSION_ENGINE) + session = engine.SessionStore(session_key) + + user_id = session.get(SESSION_KEY) + auth_backend = load_backend(session.get(BACKEND_SESSION_KEY)) + + if session.get_expiry_age() < 0: + res_msg['success'] = False + res_msg['message'] = "Token expired" + elif not user_id or not auth_backend: + res_msg['success'] = False + res_msg['message'] = "no user" + else: + user = None + try: + user = auth_backend.get_user(user_id) + except: + pass + + if not user: + res_msg['success'] = False + res_msg['message'] = "user unknown" + else: + username = getattr(user,User.USERNAME_FIELD) + res_msg['success'] = True + res_msg['message'] = "" + res_msg['username'] = username.replace(settings.EGONOMY_USER_PREFIX,"") + res_msg['external'] = username.startswith(settings.EGONOMY_USER_PREFIX) + + return HttpResponse(json.dumps(res_msg), mimetype='application/json') + + + + + diff -r a76a79affb4a -r 4e7178ce5688 virtualenv/res/lib/lib_create_env.py --- a/virtualenv/res/lib/lib_create_env.py Mon Mar 17 16:18:45 2014 +0100 +++ b/virtualenv/res/lib/lib_create_env.py Fri Mar 21 16:25:21 2014 +0100 @@ -17,8 +17,8 @@ URLS = { #'': {'setup': '', 'url':'', 'local':''}, 'DISTRIBUTE': {'setup': 'distribute', 'url':'http://pypi.python.org/packages/source/d/distribute/distribute-0.6.31.tar.gz', 'local':"distribute-0.6.31.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, - 'DJANGO': {'setup': 'django', 'url': 'https://www.djangoproject.com/download/1.5/tarball/', 'local':"Django-1.5.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, - 'DJANGO-EXTENSIONS': { 'setup': 'django-extensions', 'url':'https://github.com/django-extensions/django-extensions/archive/1.0.2.tar.gz', 'local':"django-extensions-1.0.2.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, + 'DJANGO': {'setup': 'django', 'url': 'https://www.djangoproject.com/download/1.6.2/tarball/', 'local':"Django-1.6.2.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, + 'DJANGO-EXTENSIONS': { 'setup': 'django-extensions', 'url':'https://github.com/django-extensions/django-extensions/archive/1.3.3.tar.gz', 'local':"django-extensions-1.3.3.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, 'DJANGO-REGISTRATION': { 'setup': 'django-registration', 'url':'https://bitbucket.org/ubernostrum/django-registration/downloads/django-registration-1.0.tar.gz', 'local':"django-registration-1.0.tar.gz", 'install': {'method': 'easy_install', 'option_str': '-Z', 'dict_extra_env': None}}, 'SOUTH': { 'setup': 'South', 'url':'http://www.aeracode.org/releases/south/south-0.7.5.tar.gz', 'local':"south-0.7.5.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, 'SORL_THUMBNAIL' : { 'setup': 'sorl-thumbnail', 'url':'https://github.com/sorl/sorl-thumbnail/archive/master.tar.gz', 'local':"sorl-thumbnail-v11.12.tar.gz", 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, @@ -38,7 +38,7 @@ 'PYTZ' : {'setup': 'pytz', 'url':'http://pypi.python.org/packages/source/p/pytz/pytz-2012j.tar.gz', 'local' : 'pytz-2012j.tar.gz', 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, # dependencies for Tastypie : mimeparse>=0.1.3, python-dateutil>=2.1, lxml, PyYAML (not necessary but we never know), python-digest 'MIMEPARSE' : {'setup':'mimeparse', 'url':'http://pypi.python.org/packages/source/m/mimeparse/mimeparse-0.1.3.tar.gz', 'local': 'mimeparse-0.1.3.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, - 'SIX' : {'setup':'six', 'url':'http://pypi.python.org/packages/source/s/six/six-1.2.0.tar.gz', 'local': 'six-1.2.0.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, + 'SIX' : {'setup':'six', 'url':'https://pypi.python.org/packages/source/s/six/six-1.6.1.tar.gz', 'local': 'six-1.6.1.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, 'PYTHON-DATEUTIL' : {'setup':'python-dateutil', 'url':'http://pypi.python.org/packages/source/p/python-dateutil/python-dateutil-2.1.tar.gz', 'local': 'python-dateutil-2.1.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, 'PYYAML' : {'setup':'pyyaml', 'url':'http://pypi.python.org/packages/source/P/PyYAML/PyYAML-3.10.tar.gz', 'local': 'PyYAML-3.10.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, 'PYTHON-DIGEST' : {'setup':'python-digest', 'url':'http://pypi.python.org/packages/source/p/python-digest/python-digest-1.7.tar.gz', 'local': 'python-digest-1.7.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, @@ -46,6 +46,7 @@ 'ISODATE' : {'setup': 'isodate', 'url': 'https://github.com/gweis/isodate/archive/0.4.9.tar.gz', 'local': 'isodate-0.4.9.tar.gz', 'install': {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, 'HTML5LIB' : {'setup': 'html5lib', 'url': 'https://html5lib.googlecode.com/files/html5lib-0.95.tar.gz', 'local': 'html5lib-0.95.tar.gz', 'install': {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, 'RDFLIB' : {'setup': 'rdflib', 'url': 'https://nodeload.github.com/RDFLib/rdflib/tar.gz/master', 'local': 'rdflib-2.4.0.tar.gz', 'install': {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, + 'PYCRYPTO' : {'setup': 'pycrypto', 'url': 'http://ftp.dlitz.net/pub/dlitz/crypto/pycrypto/pycrypto-2.6.1.tar.gz', 'local': 'pycrypto-2.6.1.tar.gz', 'install': {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, } if system_str == 'Windows': @@ -300,7 +301,12 @@ extra_env = {} if 'TMPDIR' not in extra_env: - extra_env['TMPDIR'] = os.path.abspath(tmp_dir) + extra_env['TMPDIR'] = os.path.abspath(tmp_dir) + if system_str == 'Darwin': + archflags = extra_env.get('ARCHFLAGS', '') + if '-Wno-error=unused-command-line-argument-hard-error-in-future' not in archflags: + archflags += " -Wno-error=unused-command-line-argument-hard-error-in-future" + extra_env['ARCHFLAGS'] = archflags.strip() #isinstance(lst, (list, tuple)) if key not in ignore_packages: logger.notify("install %s with method %s" % (key, repr(method))) diff -r a76a79affb4a -r 4e7178ce5688 virtualenv/res/src/Django-1.5.tar.gz Binary file virtualenv/res/src/Django-1.5.tar.gz has changed diff -r a76a79affb4a -r 4e7178ce5688 virtualenv/res/src/Django-1.6.2.tar.gz Binary file virtualenv/res/src/Django-1.6.2.tar.gz has changed diff -r a76a79affb4a -r 4e7178ce5688 virtualenv/res/src/django-extensions-1.0.2.tar.gz Binary file virtualenv/res/src/django-extensions-1.0.2.tar.gz has changed diff -r a76a79affb4a -r 4e7178ce5688 virtualenv/res/src/django-extensions-1.3.3.tar.gz Binary file virtualenv/res/src/django-extensions-1.3.3.tar.gz has changed diff -r a76a79affb4a -r 4e7178ce5688 virtualenv/res/src/pycrypto-2.6.1.tar.gz Binary file virtualenv/res/src/pycrypto-2.6.1.tar.gz has changed diff -r a76a79affb4a -r 4e7178ce5688 virtualenv/res/src/six-1.2.0.tar.gz Binary file virtualenv/res/src/six-1.2.0.tar.gz has changed diff -r a76a79affb4a -r 4e7178ce5688 virtualenv/res/src/six-1.6.1.tar.gz Binary file virtualenv/res/src/six-1.6.1.tar.gz has changed diff -r a76a79affb4a -r 4e7178ce5688 virtualenv/web/res/res_create_env.py --- a/virtualenv/web/res/res_create_env.py Mon Mar 17 16:18:45 2014 +0100 +++ b/virtualenv/web/res/res_create_env.py Fri Mar 21 16:25:21 2014 +0100 @@ -28,6 +28,7 @@ 'ISODATE', 'HTML5LIB', 'RDFLIB', + 'PYCRYPTO', ] #if system_str == "Linux" and 'PIL' in INSTALLS: