Browse Source

Store the one time login token in profile so user.password can be used for regular passwords.

pull/27/head
Pēteris Caune 9 years ago
parent
commit
dd188064fa
5 changed files with 72 additions and 30 deletions
  1. +24
    -0
      hc/accounts/backends.py
  2. +20
    -0
      hc/accounts/migrations/0003_profile_token.py
  3. +11
    -0
      hc/accounts/models.py
  4. +12
    -30
      hc/accounts/views.py
  5. +5
    -0
      hc/settings.py

+ 24
- 0
hc/accounts/backends.py View File

@ -0,0 +1,24 @@
from django.contrib.auth.hashers import check_password
from django.contrib.auth.models import User
from hc.accounts.models import Profile
# Authenticate against the token in user's profile.
class ProfileBackend(object):
def authenticate(self, username=None, token=None):
try:
profile = Profile.objects.get(user__username=username)
except Profile.DoesNotExist:
return None
if not check_password(token, profile.token):
return None
return profile.user
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None

+ 20
- 0
hc/accounts/migrations/0003_profile_token.py View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2016-01-04 20:26
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0002_profile_ping_log_limit'),
]
operations = [
migrations.AddField(
model_name='profile',
name='token',
field=models.CharField(blank=True, max_length=128),
),
]

+ 11
- 0
hc/accounts/models.py View File

@ -1,5 +1,6 @@
from datetime import timedelta
from django.conf import settings
from django.contrib.auth.hashers import make_password
from django.contrib.auth.models import User
from django.core import signing
from django.core.urlresolvers import reverse
@ -26,9 +27,19 @@ class Profile(models.Model):
next_report_date = models.DateTimeField(null=True, blank=True)
reports_allowed = models.BooleanField(default=True)
ping_log_limit = models.IntegerField(default=100)
token = models.CharField(max_length=128, blank=True)
objects = ProfileManager()
def send_instant_login_link(self):
token = str(uuid.uuid4())
self.token = make_password(token)
self.save()
path = reverse("hc-check-token", args=[self.user.username, token])
ctx = {"login_link": settings.SITE_ROOT + path}
emails.login(self.user.email, ctx)
def send_report(self):
# reset next report date first:
now = timezone.now()


+ 12
- 30
hc/accounts/views.py View File

@ -1,6 +1,5 @@
import uuid
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import login as auth_login
from django.contrib.auth import logout as auth_logout
@ -8,18 +7,17 @@ from django.contrib.auth import authenticate
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.core import signing
from django.core.urlresolvers import reverse
from django.http import HttpResponseBadRequest
from django.shortcuts import redirect, render
from hc.accounts.forms import EmailForm, ReportSettingsForm
from hc.accounts.models import Profile
from hc.api.models import Channel, Check
from hc.lib import emails
def _make_user(email):
username = str(uuid.uuid4())[:30]
user = User(username=username, email=email)
user.set_unusable_password()
user.save()
channel = Channel()
@ -46,18 +44,6 @@ def _associate_demo_check(request, user):
del request.session["welcome_code"]
def _send_login_link(user):
token = str(uuid.uuid4())
user.set_password(token)
user.save()
login_link = reverse("hc-check-token", args=[user.username, token])
login_link = settings.SITE_ROOT + login_link
ctx = {"login_link": login_link}
emails.login(user.email, ctx)
def login(request):
if request.method == 'POST':
form = EmailForm(request.POST)
@ -69,12 +55,8 @@ def login(request):
user = _make_user(email)
_associate_demo_check(request, user)
# We don't want to reset passwords of staff users :-)
if user.is_staff:
return HttpResponseBadRequest()
_send_login_link(user)
profile = Profile.objects.for_user(user)
profile.send_instant_login_link()
return redirect("hc-login-link-sent")
else:
@ -99,17 +81,17 @@ def check_token(request, username, token):
# User is already logged in
return redirect("hc-checks")
user = authenticate(username=username, password=token)
if user is not None:
if user.is_active:
# This should get rid of "welcome_code" in session
request.session.flush()
user = authenticate(username=username, token=token)
if user is not None and user.is_active:
# This should get rid of "welcome_code" in session
request.session.flush()
user.set_unusable_password()
user.save()
auth_login(request, user)
profile = Profile.objects.for_user(user)
profile.token = ""
profile.save()
auth_login(request, user)
return redirect("hc-checks")
return redirect("hc-checks")
request.session["bad_link"] = True
return redirect("hc-login")


+ 5
- 0
hc/settings.py View File

@ -51,6 +51,11 @@ MIDDLEWARE_CLASSES = (
'django.middleware.security.SecurityMiddleware',
)
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'hc.accounts.backends.ProfileBackend'
)
ROOT_URLCONF = 'hc.urls'
TEMPLATES = [


Loading…
Cancel
Save