import time
from urllib import quote
-from urlparse import urlsplit, urlunsplit
-from functools import wraps
+from urlparse import urlsplit, urlunsplit, urlparse
from datetime import tzinfo, timedelta
-from django.http import HttpResponse, urlencode
+from django.http import HttpResponse, HttpResponseBadRequest, urlencode
from django.template import RequestContext
-from django.contrib.sites.models import Site
from django.utils.translation import ugettext as _
-from django.contrib.auth import login, authenticate
+from django.contrib.auth import authenticate
from django.core.urlresolvers import reverse
+from django.core.exceptions import ValidationError
from astakos.im.models import AstakosUser, Invitation, ApprovalTerms
-from astakos.im.settings import INVITATIONS_PER_LEVEL, COOKIE_NAME, COOKIE_DOMAIN, COOKIE_SECURE, FORCE_PROFILE_UPDATE
+from astakos.im.settings import (
+ INVITATIONS_PER_LEVEL, COOKIE_NAME, COOKIE_DOMAIN, COOKIE_SECURE,
+ FORCE_PROFILE_UPDATE, LOGGING_LEVEL
+)
+from astakos.im.functions import login
logger = logging.getLogger(__name__)
def epoch(datetime):
return int(time.mktime(datetime.timetuple())*1000)
-def get_or_create_user(email, realname='', first_name='', last_name='', affiliation='', level=0, provider='local', password=''):
- """Find or register a user into the internal database
- and issue a token for subsequent requests.
- """
- user, created = AstakosUser.objects.get_or_create(email=email,
- defaults={
- 'password':password,
- 'affiliation':affiliation,
- 'level':level,
- 'invitations':INVITATIONS_PER_LEVEL.get(level, 0),
- 'provider':provider,
- 'realname':realname,
- 'first_name':first_name,
- 'last_name':last_name
- })
- if created:
- user.renew_token()
- user.save()
- logger.info('Created user %s', user)
-
- return user
-
def get_context(request, extra_context={}, **kwargs):
if not extra_context:
extra_context = {}
raise ValueError(_('Email: %s is reserved' % invitation.username))
return invitation
+def restrict_next(url, domain=None, allowed_schemes=()):
+ """
+ Return url if having the supplied ``domain`` (if present) or one of the ``allowed_schemes``.
+ Otherwise return None.
+
+ >>> print restrict_next('/im/feedback', '.okeanos.grnet.gr')
+ /im/feedback
+ >>> print restrict_next('pithos.okeanos.grnet.gr/im/feedback', '.okeanos.grnet.gr')
+ pithos.okeanos.grnet.gr/im/feedback
+ >>> print restrict_next('https://pithos.okeanos.grnet.gr/im/feedback', '.okeanos.grnet.gr')
+ https://pithos.okeanos.grnet.gr/im/feedback
+ >>> print restrict_next('pithos://127.0.0,1', '.okeanos.grnet.gr')
+ None
+ >>> print restrict_next('pithos://127.0.0,1', '.okeanos.grnet.gr', allowed_schemes=('pithos'))
+ pithos://127.0.0,1
+ >>> print restrict_next('node1.example.com', '.okeanos.grnet.gr')
+ None
+ >>> print restrict_next('//node1.example.com', '.okeanos.grnet.gr')
+ None
+ >>> print restrict_next('https://node1.example.com', '.okeanos.grnet.gr')
+ None
+ >>> print restrict_next('https://node1.example.com')
+ https://node1.example.com
+ >>> print restrict_next('//node1.example.com')
+ //node1.example.com
+ >>> print restrict_next('node1.example.com')
+ node1.example.com
+ """
+ if not url:
+ return
+ parts = urlparse(url, scheme='http')
+ if not parts.netloc:
+ # fix url if does not conforms RFC 1808
+ url = '//%s' % url
+ parts = urlparse(url, scheme='http')
+ # TODO more scientific checks?
+ if not parts.netloc: # internal url
+ return url
+ elif not domain:
+ return url
+ elif parts.netloc.endswith(domain):
+ return url
+ elif parts.scheme in allowed_schemes:
+ return url
+
def prepare_response(request, user, next='', renew=False):
"""Return the unique username and the token
as 'X-Auth-User' and 'X-Auth-Token' headers,
renew = renew or (user.auth_token_expires and user.auth_token_expires < datetime.datetime.now())
if renew:
user.renew_token()
- user.save()
+ try:
+ user.save()
+ except ValidationError, e:
+ return HttpResponseBadRequest(e)
+
+ next = restrict_next(next, domain=COOKIE_DOMAIN)
if FORCE_PROFILE_UPDATE and not user.is_verified and not user.is_superuser:
params = ''
user = authenticate(email=user.email, auth_token=user.auth_token)
login(request, user)
set_cookie(response, user)
+ request.session.set_expiry(user.auth_token_expires)
if not next:
next = reverse('astakos.im.views.index')
response.set_cookie(COOKIE_NAME, value=cookie_value,
expires=expire_fmt, path='/',
domain=COOKIE_DOMAIN, secure=COOKIE_SECURE)
+ msg = 'Cookie [expiring %s] set for %s' % (user.auth_token_expires, user.email)
+ logger._log(LOGGING_LEVEL, msg, [])
class lazy_string(object):
def __init__(self, function, *args, **kwargs):
return AstakosUser.objects.filter(email = email).count() != 0
def get_query(request):
- return request.__getattribute__(request.method)
\ No newline at end of file
+ try:
+ return request.__getattribute__(request.method)
+ except AttributeError:
+ return {}
\ No newline at end of file