Skip to content

Commit

Permalink
Add UI for Changing and Clearing Password. Closes #30
Browse files Browse the repository at this point in the history
  • Loading branch information
leupibr committed Jun 7, 2019
1 parent de0084f commit e714c16
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 2 deletions.
7 changes: 7 additions & 0 deletions tracker/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,10 @@ class SettingsForm(forms.ModelForm):
class Meta:
model = Setting
fields = ('timezone', 'locale', 'duration_format', 'timestamp_rounding', 'allow_parallel_tracking')


class ChangePasswordForm(forms.Form):
password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'form-control'}),
help_text='Password must be at least 8 characters long and must contain'
' at least one letter and one number')
confirm_password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'form-control'}))
54 changes: 54 additions & 0 deletions tracker/templates/tracker/user/account.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{% extends "tracker/base.html" %}

{% load django_bootstrap_breadcrumbs %}

{% block breadcrumbs %}
{% breadcrumb_raw "Home" "tracker:index" %}
{% breadcrumb_raw user.get_full_name "/user/profile" %}
{% breadcrumb_raw "Account" "tracker:/user/account" %}
{% endblock %}

{% block content %}
<div class="container">
<div class="row justify-content-md-center mb-2">
<div class="card p-3 col-md-6 shadow">
<form class="form" method="post" action="{% url 'tracker:user/account/change_password' %}">
{% csrf_token %}

{% for field in change_password_form %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}{% if field.field.required %}*{% endif %}</label>
{{ field }}
{% if field.help_text %}
<small class="form-text text-muted">{{ field.help_text|safe }}</small>
{% endif %}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
</div>

<div class="row justify-content-md-center">
<div class="card p-3 col-md-6 shadow">
<div class="alert alert-light" role="alert">
<h4 class="alert-heading">Warning</h4>
<p>
Please use a password only as a last resort. Even if <em>trrrakk</em> hashes and salts your password,
stores it in an encrypted database and only uses secure communication channels (https), it is
still more save not storing a password at all.
</p>
<p>
The login mechanism with Google-OAuth2 or Github-OAuth2 doesn't require to store any
password on <em>trrrakk</em>. Instead it delegates the responsibility to the big players
and trusts their security standards.
</p>
</div>
<form class="form" method="post" action="{% url 'tracker:user/account/clear_password' %}">
{% csrf_token %}
<button type="submit" class="btn btn-danger">Clear Password</button>
</form>
</div>
</div>
</div>
{% endblock %}
4 changes: 4 additions & 0 deletions tracker/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,9 @@
path(f'{reports_base}monthly_distribution', views.user.monthly_distribution, name='user/reports/monthly_distribution'),
path(f'{reports_base}weekly_time', views.user.weekly_time, name='user/reports/weekly_time'),
path(f'{reports_base}weekly_worktime', views.user.weekly_worktime_report, name='user/reports/weekly_worktime'),

path('settings', views.user.settings, name='user/settings'),
path('account', views.user.account, name='user/account'),
path('account/change_password', views.user.change_password, name='user/account/change_password'),
path('account/clear_password', views.user.clear_password, name='user/account/clear_password'),
]
57 changes: 55 additions & 2 deletions tracker/views/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
import pytz
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from django.shortcuts import render, redirect
from django.utils import formats
from django.utils.translation import activate as tl_activate

from tracker.forms import SettingsForm
from tracker.forms import SettingsForm, ChangePasswordForm
from tracker.models import TimeRecord, Project, Setting


Expand Down Expand Up @@ -222,6 +222,59 @@ def settings(request):
return render(request, 'tracker/user/settings.html', context={'form': form})


@login_required
def account(request):
return render(request, 'tracker/user/account.html', context={
'change_password_form': ChangePasswordForm()
})


@login_required
def change_password(request):
if request.method != 'POST':
messages.error(request, 'Invalid request method')
return redirect('tracker:user/account')

password = request.POST['password']
confirmation = request.POST['confirm_password']

if password != confirmation:
messages.error(request, 'Passwords do not match')
return redirect('tracker:user/account')

min_len = 8
if len(password) < min_len:
messages.error(request, f'Passwords must be at least {min_len} characters long')
return redirect('tracker:user/account')

if not any(char.isdigit() for char in password):
messages.error(request, 'Password must contain at least 1 digit.')
return redirect('tracker:user/account')

if not any(char.isalpha() for char in password):
messages.error(request, 'Password must contain at least 1 letter.')
return redirect('tracker:user/account')

request.user.set_password(password)
request.user.save()

messages.success(request, 'Password successfully changed')
return redirect('tracker:user/account')


@login_required
def clear_password(request):
if request.method != 'POST':
messages.error(request, 'Invalid request method')
return redirect('tracker:user/account')

request.user.set_unusable_password()
request.user.save()

messages.success(request, 'Password successfully cleared')
return redirect('tracker:user/account')


def build_sum_for_dates(setting, dates, matrix):
init = 0 if setting.duration_format == Setting.DURATION_FORMAT_DECIMAL else timedelta()
return [sum([p['duration'][i] for p in matrix], init) for i in range(len(dates))]
Expand Down
3 changes: 3 additions & 0 deletions trrrakk/templates/trrrakk/navigation.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
<i class="fa fa-wrench"></i> Settings
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="{% url 'tracker:user/account' %}">
<i class="fas fa-user"></i> Account
</a>
<a class="dropdown-item" href="{% url 'logout' %}">
<i class="fa fa-sign-out-alt"></i> Sign out
</a>
Expand Down

0 comments on commit e714c16

Please sign in to comment.