import logging
import socket
-from random import randint
from smtplib import SMTPException
from urllib import quote
from functools import wraps
-from django.conf import settings
from django.core.mail import send_mail
from django.http import HttpResponse
from django.shortcuts import redirect
from astakos.im.models import AstakosUser, Invitation
from astakos.im.backends import get_backend
-from astakos.im.util import get_context, get_current_site, prepare_response
+from astakos.im.util import get_context, prepare_response, set_cookie
from astakos.im.forms import *
+from astakos.im.settings import DEFAULT_CONTACT_EMAIL, DEFAULT_FROM_EMAIL, COOKIE_NAME, COOKIE_DOMAIN, IM_MODULES, SITENAME, BASEURL
+from astakos.im.functions import invite as invite_func
-def render_response(template, tab=None, status=200, context_instance=None, **kwargs):
+logger = logging.getLogger(__name__)
+
+def render_response(template, tab=None, status=200, reset_cookie=False, context_instance=None, **kwargs):
"""
Calls ``django.template.loader.render_to_string`` with an additional ``tab``
keyword argument and returns an ``django.http.HttpResponse`` with the
tab = template.partition('_')[0].partition('.html')[0]
kwargs.setdefault('tab', tab)
html = render_to_string(template, kwargs, context_instance=context_instance)
- return HttpResponse(html, status=status)
+ response = HttpResponse(html, status=status)
+ if reset_cookie:
+ set_cookie(response, context_instance['request'].user)
+ return response
def requires_anonymous(func):
return func(request, *args)
return wrapper
-def index(request, login_template_name='login.html', profile_template_name='profile.html', extra_context={}):
+def index(request, login_template_name='im/login.html', profile_template_name='im/profile.html', extra_context={}):
"""
If there is logged on user renders the profile page otherwise renders login page.
``login_template_name``
A custom login template to use. This is optional; if not specified,
- this will default to ``login.html``.
+ this will default to ``im/login.html``.
``profile_template_name``
A custom profile template to use. This is optional; if not specified,
- this will default to ``profile.html``.
+ this will default to ``im/profile.html``.
``extra_context``
An dictionary of variables to add to the template context.
**Template:**
- profile.html or login.html or ``template_name`` keyword argument.
+ im/profile.html or im/login.html or ``template_name`` keyword argument.
"""
template_name = login_template_name
form = globals()[formclass](**kwargs),
context_instance = get_context(request, extra_context))
-def _generate_invitation_code():
- while True:
- code = randint(1, 2L**63 - 1)
- try:
- Invitation.objects.get(code=code)
- # An invitation with this code already exists, try again
- except Invitation.DoesNotExist:
- return code
-
-def _send_invitation(request, baseurl, inv):
- sitename, sitedomain = get_current_site(request, use_https=request.is_secure())
- subject = _('Invitation to %s' % sitename)
- baseurl = request.build_absolute_uri('/').rstrip('/')
- url = '%s%s?code=%d' % (baseurl, reverse('astakos.im.views.signup'), inv.code)
- message = render_to_string('invitation.txt', {
- 'invitation': inv,
- 'url': url,
- 'baseurl': baseurl,
- 'service': sitename,
- 'support': settings.DEFAULT_CONTACT_EMAIL % sitename.lower()})
- sender = settings.DEFAULT_FROM_EMAIL % sitename
- send_mail(subject, message, sender, [inv.username])
- logging.info('Sent invitation %s', inv)
-
@login_required
@transaction.commit_manually
-def invite(request, template_name='invitations.html', extra_context={}):
+def invite(request, template_name='im/invitations.html', extra_context={}):
"""
Allows a user to invite somebody else.
``template_name``
A custom template to use. This is optional; if not specified,
- this will default to ``invitations.html``.
+ this will default to ``im/invitations.html``.
``extra_context``
An dictionary of variables to add to the template context.
**Template:**
- invitations.html or ``template_name`` keyword argument.
+ im/invitations.html or ``template_name`` keyword argument.
**Settings:**
The view expectes the following settings are defined:
* LOGIN_URL: login uri
- * SIGNUP_TARGET: Where users should signup with their invitation code
- * DEFAULT_CONTACT_EMAIL: service support email
- * DEFAULT_FROM_EMAIL: from email
+ * ASTAKOS_DEFAULT_CONTACT_EMAIL: service support email
+ * ASTAKOS_DEFAULT_FROM_EMAIL: from email
"""
status = None
message = None
realname = request.POST.get('realname')
if inviter.invitations > 0:
- code = _generate_invitation_code()
- invitation = Invitation(inviter=inviter,
- username=username,
- code=code,
- realname=realname)
- invitation.save()
-
try:
- baseurl = request.build_absolute_uri('/').rstrip('/')
- _send_invitation(request, baseurl, invitation)
- inviter.invitations = max(0, inviter.invitations - 1)
- inviter.save()
+ invite_func(inviter, username, realname)
status = messages.SUCCESS
message = _('Invitation sent to %s' % username)
transaction.commit()
context_instance = context)
@login_required
-def edit_profile(request, template_name='profile.html', extra_context={}):
+def edit_profile(request, template_name='im/profile.html', extra_context={}):
"""
Allows a user to edit his/her profile.
In case of POST updates the user informantion and redirects to ``next``
url parameter if exists.
- If the user isn't logged in, redirects to settings.LOGIN_URL.
+ If the user isn't logged in, redirects to settings.LOGIN_URL.
**Arguments**
``template_name``
A custom template to use. This is optional; if not specified,
- this will default to ``profile.html``.
+ this will default to ``im/profile.html``.
``extra_context``
An dictionary of variables to add to the template context.
**Template:**
- profile.html or ``template_name`` keyword argument.
+ im/profile.html or ``template_name`` keyword argument.
+
+ **Settings:**
+
+ The view expectes the following settings are defined:
+
+ * LOGIN_URL: login uri
"""
form = ProfileForm(instance=request.user)
extra_context['next'] = request.GET.get('next')
+ reset_cookie = False
if request.method == 'POST':
form = ProfileForm(request.POST, instance=request.user)
if form.is_valid():
try:
- form.save()
+ prev_token = request.user.auth_token
+ user = form.save()
+ reset_cookie = user.auth_token != prev_token
+ form = ProfileForm(instance=user)
+ next = request.POST.get('next')
+ if next:
+ return redirect(next)
msg = _('Profile has been updated successfully')
messages.add_message(request, messages.SUCCESS, msg)
except ValueError, ve:
messages.add_message(request, messages.ERROR, ve)
- next = request.POST.get('next')
- if next:
- return redirect(next)
return render_response(template_name,
+ reset_cookie = reset_cookie,
form = form,
context_instance = get_context(request,
- extra_context,
- user=request.user))
+ extra_context))
-def signup(request, on_failure='signup.html', on_success='signup_complete.html', extra_context={}, backend=None):
+@requires_anonymous
+def signup(request, on_failure='im/signup.html', on_success='im/signup_complete.html', extra_context={}, backend=None):
"""
Allows a user to create a local account.
The user activation will be delegated to the backend specified by the ``backend`` keyword argument
if present, otherwise to the ``astakos.im.backends.InvitationBackend``
- if settings.INVITATIONS_ENABLED is True or ``astakos.im.backends.SimpleBackend`` if not
+ if settings.ASTAKOS_INVITATIONS_ENABLED is True or ``astakos.im.backends.SimpleBackend`` if not
(see backends);
Upon successful user creation if ``next`` url parameter is present the user is redirected there
``on_failure``
A custom template to render in case of failure. This is optional;
- if not specified, this will default to ``signup.html``.
+ if not specified, this will default to ``im/signup.html``.
``on_success``
A custom template to render in case of success. This is optional;
- if not specified, this will default to ``signup_complete.html``.
+ if not specified, this will default to ``im/signup_complete.html``.
``extra_context``
An dictionary of variables to add to the template context.
**Template:**
- signup.html or ``on_failure`` keyword argument.
- signup_complete.html or ``on_success`` keyword argument.
+ im/signup.html or ``on_failure`` keyword argument.
+ im/signup_complete.html or ``on_success`` keyword argument.
"""
try:
if not backend:
backend = get_backend(request)
- for provider in settings.IM_MODULES:
+ for provider in IM_MODULES:
extra_context['%s_form' % provider] = backend.get_signup_form(provider)
if request.method == 'POST':
provider = request.POST.get('provider')
context_instance=get_context(request, extra_context))
except (Invitation.DoesNotExist, ValueError), e:
messages.add_message(request, messages.ERROR, e)
- for provider in settings.IM_MODULES:
+ for provider in IM_MODULES:
main = provider.capitalize() if provider == 'local' else 'ThirdParty'
formclass = '%sUserCreationForm' % main
extra_context['%s_form' % provider] = globals()[formclass]()
context_instance=get_context(request, extra_context))
@login_required
-def send_feedback(request, template_name='feedback.html', email_template_name='feedback_mail.txt', extra_context={}):
+def send_feedback(request, template_name='im/feedback.html', email_template_name='im/feedback_mail.txt', extra_context={}):
"""
Allows a user to send feedback.
In case of GET request renders a form for providing the feedback information.
In case of POST sends an email to support team.
- If the user isn't logged in, redirects to settings.LOGIN_URL.
+ If the user isn't logged in, redirects to settings.LOGIN_URL.
**Arguments**
``template_name``
A custom template to use. This is optional; if not specified,
- this will default to ``feedback.html``.
+ this will default to ``im/feedback.html``.
``extra_context``
An dictionary of variables to add to the template context.
**Template:**
- signup.html or ``template_name`` keyword argument.
+ im/signup.html or ``template_name`` keyword argument.
**Settings:**
- * DEFAULT_CONTACT_EMAIL: List of feedback recipients
+ * LOGIN_URL: login uri
+ * ASTAKOS_DEFAULT_CONTACT_EMAIL: List of feedback recipients
"""
if request.method == 'GET':
form = FeedbackForm()
form = FeedbackForm(request.POST)
if form.is_valid():
- sitename, sitedomain = get_current_site(request, use_https=request.is_secure())
- subject = _("Feedback from %s" % sitename)
+ subject = _("Feedback from %s" % SITENAME)
from_email = request.user.email
- recipient_list = [settings.DEFAULT_CONTACT_EMAIL % sitename.lower()]
+ recipient_list = [DEFAULT_CONTACT_EMAIL]
content = render_to_string(email_template_name, {
'message': form.cleaned_data['feedback_msg'],
'data': form.cleaned_data['feedback_data'],
"""
auth_logout(request)
response = HttpResponse()
- response.delete_cookie(settings.COOKIE_NAME)
+ response.delete_cookie(COOKIE_NAME, path='/', domain=COOKIE_DOMAIN)
next = request.GET.get('next')
if next:
response['Location'] = next
response.status_code = 302
return response
- html = render_to_string(template, context_instance=get_context(request, extra_context))
- return HttpResponse(html)
+ context = get_context(request, extra_context)
+ response.write(render_to_string(template, context_instance=context))
+ return response
def activate(request):
"""
user.is_active = True
user.save()
- return prepare_response(request, user, next, renew=True)
\ No newline at end of file
+ return prepare_response(request, user, next, renew=True)