Undid last commit

- Legacy-Id: 12792
This commit is contained in:
Henrik Levkowetz 2017-02-08 18:03:29 +00:00
parent 15628c698f
commit db1cc15f1f
14 changed files with 80 additions and 341 deletions

View file

@ -15,8 +15,7 @@
"respond": "~1",
"select2": "~3",
"select2-bootstrap-css": "~1",
"spin.js": "~2",
"zxcvbn": "~4"
"spin.js": "~2"
},
"devDependencies": {},
"overrides": {

View file

@ -1,5 +1,4 @@
import re
from unidecode import unidecode
from django import forms
from django.conf import settings
@ -9,7 +8,7 @@ from django.contrib.auth.models import User
from django.utils.html import mark_safe
from django.core.urlresolvers import reverse as urlreverse
from django_password_strength.widgets import PasswordStrengthInput, PasswordConfirmationInput
from unidecode import unidecode
import debug # pyflakes:ignore
@ -32,8 +31,8 @@ class RegistrationForm(forms.Form):
class PasswordForm(forms.Form):
password = forms.CharField(widget=PasswordStrengthInput)
password_confirmation = forms.CharField(widget=PasswordConfirmationInput,
password = forms.CharField(widget=forms.PasswordInput)
password_confirmation = forms.CharField(widget=forms.PasswordInput,
help_text="Enter the same password as above, for verification.")
def clean_password_confirmation(self):
@ -167,28 +166,3 @@ class WhitelistForm(forms.ModelForm):
exclude = ['by', 'time' ]
from django import forms
class ChangePasswordForm(forms.Form):
current_password = forms.CharField(widget=forms.PasswordInput)
new_password = forms.CharField(widget=PasswordStrengthInput)
new_password_confirmation = forms.CharField(widget=PasswordConfirmationInput)
def __init__(self, user, data=None):
self.user = user
super(ChangePasswordForm, self).__init__(data)
def clean_current_password(self):
password = self.cleaned_data.get('current_password', None)
if not self.user.check_password(password):
raise ValidationError('Invalid password')
def clean(self):
new_password = self.cleaned_data.get('new_password', None)
conf_password = self.cleaned_data.get('new_password_confirmation', None)
if not new_password == conf_password:
raise ValidationError("The password confirmation is different than the new password")

View file

@ -3,20 +3,23 @@
from django.conf.urls import url
from django.contrib.auth.views import login, logout
from ietf.ietfauth import views
from ietf.ietfauth.views import add_account_whitelist
urlpatterns = [
url(r'^$', views.index),
url(r'^confirmnewemail/(?P<auth>[^/]+)/$', views.confirm_new_email),
url(r'^create/$', views.create_account),
url(r'^create/confirm/(?P<auth>[^/]+)/$', views.confirm_account),
url(r'^$', 'ietf.ietfauth.views.index'),
# url(r'^login/$', 'ietf.ietfauth.views.ietf_login'),
url(r'^login/$', login),
url(r'^logout/$', logout),
url(r'^password/$', views.change_password),
url(r'^profile/$', views.profile),
url(r'^reset/$', views.password_reset),
url(r'^reset/confirm/(?P<auth>[^/]+)/$', views.confirm_password_reset),
url(r'^review/$', views.review_overview),
url(r'^testemail/$', views.test_email),
url(r'whitelist/add/?$', views.add_account_whitelist),
# url(r'^loggedin/$', 'ietf.ietfauth.views.ietf_loggedin'),
# url(r'^loggedout/$', 'ietf.ietfauth.views.logged_out'),
url(r'^profile/$', 'ietf.ietfauth.views.profile'),
# (r'^login/(?P<user>[a-z0-9.@]+)/(?P<passwd>.+)$', 'ietf.ietfauth.views.url_login'),
url(r'^testemail/$', 'ietf.ietfauth.views.test_email'),
url(r'^create/$', 'ietf.ietfauth.views.create_account'),
url(r'^create/confirm/(?P<auth>[^/]+)/$', 'ietf.ietfauth.views.confirm_account'),
url(r'^reset/$', 'ietf.ietfauth.views.password_reset'),
url(r'^reset/confirm/(?P<auth>[^/]+)/$', 'ietf.ietfauth.views.confirm_password_reset'),
url(r'^confirmnewemail/(?P<auth>[^/]+)/$', 'ietf.ietfauth.views.confirm_new_email'),
url(r'whitelist/add/?$', add_account_whitelist),
url(r'^review/$', 'ietf.ietfauth.views.review_overview'),
]

View file

@ -32,27 +32,24 @@
# Copyright The IETF Trust 2007, All Rights Reserved
import importlib
from datetime import datetime as DateTime, timedelta as TimeDelta, date as Date
from collections import defaultdict
import django.core.signing
from django import forms
from django.contrib import messages
from django.conf import settings
from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse as urlreverse
from django.http import Http404, HttpResponseRedirect #, HttpResponse,
from django.http import Http404 #, HttpResponse, HttpResponseRedirect
from django.shortcuts import render, redirect, get_object_or_404
#from django.contrib.auth import REDIRECT_FIELD_NAME, authenticate, login
from django.contrib.auth.decorators import login_required
#from django.utils.http import urlquote
import django.core.signing
from django.contrib.sites.models import Site
from django.contrib.auth.models import User
from django import forms
import debug # pyflakes:ignore
from ietf.group.models import Role, Group
from ietf.ietfauth.forms import RegistrationForm, PasswordForm, ResetPasswordForm, TestEmailForm, WhitelistForm, ChangePasswordForm
from ietf.ietfauth.forms import RegistrationForm, PasswordForm, ResetPasswordForm, TestEmailForm, WhitelistForm
from ietf.ietfauth.forms import get_person_form, RoleEmailForm, NewEmailForm
from ietf.ietfauth.htpasswd import update_htpasswd_file
from ietf.ietfauth.utils import role_required
@ -468,46 +465,3 @@ def review_overview(request):
'review_wishes': review_wishes,
'review_wish_form': review_wish_form,
})
@login_required
def change_password(request):
success = False
person = None
try:
person = request.user.person
except Person.DoesNotExist:
return render(request, 'registration/missing_person.html')
emails = Email.objects.filter(person=person, active=True).order_by('-primary','-time').first
if request.method == 'POST':
user = request.user
form = ChangePasswordForm(user, request.POST)
if form.is_valid():
new_password = form.cleaned_data["new_password"]
user.set_password(new_password)
user.save()
# password is also stored in htpasswd file
update_htpasswd_file(user.username, new_password)
# keep the session
update_session_auth_hash(request, user)
messages.success(request, "Your password was successfully changed")
return HttpResponseRedirect(urlreverse('ietf.ietfauth.views.profile'))
else:
form = ChangePasswordForm(request.user)
hlibname, hashername = settings.PASSWORD_HASHERS[0].rsplit('.',1)
hlib = importlib.import_module(hlibname)
hasher = getattr(hlib, hashername)
return render(request, 'registration/change_password.html', {
'form': form,
'success': success,
'hasher': hasher,
})

View file

@ -32,7 +32,6 @@ from ietf.ipr.utils import (get_genitive, get_ipr_summary,
iprs_from_docs, related_docs)
from ietf.message.models import Message
from ietf.message.utils import infer_message
from ietf.name.models import IprLicenseTypeName
from ietf.person.models import Person
from ietf.secr.utils.document import get_rfc_num, is_draft
from ietf.utils.draft_search import normalize_draftname
@ -704,7 +703,6 @@ def get_details_tabs(ipr, selected):
('History', urlreverse('ipr_history', kwargs={ 'id': ipr.pk }))
]]
@debug.trace
def show(request, id):
"""View of individual declaration"""
ipr = get_object_or_404(IprDisclosureBase, id=id).get_child()
@ -719,7 +717,6 @@ def show(request, id):
return render(request, "ipr/details_view.html", {
'ipr': ipr,
'tabs': get_details_tabs(ipr, 'Disclosure'),
'choices_abc': [ i.desc for i in IprLicenseTypeName.objects.filter(slug__in=['no-license', 'royalty-free', 'reasonable', ]) ],
'updates_iprs': ipr.relatedipr_source_set.all(),
'updated_by_iprs': ipr.relatedipr_target_set.filter(source__state="posted")
})

View file

@ -54,13 +54,6 @@ ADMINS = (
('Ryan Cross', 'rcross@amsl.com'),
)
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.SHA1PasswordHasher',
'django.contrib.auth.hashers.CryptPasswordHasher',
]
ALLOWED_HOSTS = [".ietf.org", ".ietf.org.", "209.208.19.216", "4.31.198.44", ]
@ -303,12 +296,11 @@ INSTALLED_APPS = (
'django.contrib.staticfiles',
# External apps
'bootstrap3',
'django_markup',
'django_password_strength',
'djangobwr',
'form_utils',
'tastypie',
'widget_tweaks',
'django_markup',
# IETF apps
'ietf.api',
'ietf.community',
@ -790,6 +782,7 @@ SILENCED_SYSTEM_CHECKS = [
"fields.W342", # Setting unique=True on a ForeignKey has the same effect as using a OneToOneField.
]
# Put the production SECRET_KEY in settings_local.py, and also any other
# sensitive or site-specific changes. DO NOT commit settings_local.py to svn.
from settings_local import * # pyflakes:ignore pylint: disable=wildcard-import

View file

@ -1,130 +0,0 @@
// Taken from django-password-strength, with changes to use the bower-managed zxcvbn.js The
// bower-managed zxcvbn.js is kept up-to-date to a larger extent than the copy packaged with
// the django-password-strength component.
(function($, window, document, undefined){
window.djangoPasswordStrength = {
config: {
passwordClass: 'password_strength',
confirmationClass: 'password_confirmation'
},
init: function (config) {
var self = this;
// Setup configuration
if ($.isPlainObject(config)) {
$.extend(self.config, config);
}
self.initListeners();
},
initListeners: function() {
var self = this;
var body = $('body');
$('.' + self.config.passwordClass).on('keyup', function() {
var password_strength_bar = $(this).parent().find('.password_strength_bar');
var password_strength_info = $(this).parent().find('.password_strength_info');
if( $(this).val() ) {
var result = zxcvbn( $(this).val() );
if( result.score < 3 ) {
password_strength_bar.removeClass('progress-bar-success').addClass('progress-bar-warning');
password_strength_info.find('.label').removeClass('hidden');
} else {
password_strength_bar.removeClass('progress-bar-warning').addClass('progress-bar-success');
password_strength_info.find('.label').addClass('hidden');
}
password_strength_bar.width( ((result.score+1)/5)*100 + '%' ).attr('aria-valuenow', result.score + 1);
// henrik@levkowetz.com -- this is the only changed line:
password_strength_info.find('.password_strength_time').html(result.crack_times_display.online_no_throttling_10_per_second);
password_strength_info.removeClass('hidden');
} else {
password_strength_bar.removeClass('progress-bar-success').addClass('progress-bar-warning');
password_strength_bar.width( '0%' ).attr('aria-valuenow', 0);
password_strength_info.addClass('hidden');
}
self.match_passwords($(this));
});
var timer = null;
$('.' + self.config.confirmationClass).on('keyup', function() {
var password_field;
var confirm_with = $(this).data('confirm-with');
if( confirm_with ) {
password_field = $('#' + confirm_with);
} else {
password_field = $('.' + self.config.passwordClass);
}
if (timer !== null) clearTimeout(timer);
timer = setTimeout(function(){
self.match_passwords(password_field);
}, 400);
});
},
display_time: function(seconds) {
var minute = 60;
var hour = minute * 60;
var day = hour * 24;
var month = day * 31;
var year = month * 12;
var century = year * 100;
// Provide fake gettext for when it is not available
if( typeof gettext !== 'function' ) { gettext = function(text) { return text; }; };
if( seconds < minute ) return gettext('only an instant');
if( seconds < hour) return (1 + Math.ceil(seconds / minute)) + ' ' + gettext('minutes');
if( seconds < day) return (1 + Math.ceil(seconds / hour)) + ' ' + gettext('hours');
if( seconds < month) return (1 + Math.ceil(seconds / day)) + ' ' + gettext('days');
if( seconds < year) return (1 + Math.ceil(seconds / month)) + ' ' + gettext('months');
if( seconds < century) return (1 + Math.ceil(seconds / year)) + ' ' + gettext('years');
return gettext('centuries');
},
match_passwords: function(password_field, confirmation_fields) {
var self = this;
// Optional parameter: if no specific confirmation field is given, check all
if( confirmation_fields === undefined ) { confirmation_fields = $('.' + self.config.confirmationClass) }
if( confirmation_fields === undefined ) { return; }
var password = password_field.val();
confirmation_fields.each(function(index, confirm_field) {
var confirm_value = $(confirm_field).val();
var confirm_with = $(confirm_field).data('confirm-with');
if( confirm_with && confirm_with == password_field.attr('id')) {
if( confirm_value && password ) {
if (confirm_value === password) {
$(confirm_field).parent().find('.password_strength_info').addClass('hidden');
} else {
$(confirm_field).parent().find('.password_strength_info').removeClass('hidden');
}
} else {
$(confirm_field).parent().find('.password_strength_info').addClass('hidden');
}
}
});
// If a password field other than our own has been used, add the listener here
if( !password_field.hasClass(self.config.passwordClass) && !password_field.data('password-listener') ) {
password_field.on('keyup', function() {
self.match_passwords($(this));
});
password_field.data('password-listener', true);
}
}
};
// Call the init for backwards compatibility
djangoPasswordStrength.init();
})(jQuery, window, document);

View file

@ -16,16 +16,14 @@
{% else %}
{% if user.is_authenticated %}
<li><a rel="nofollow" href="/accounts/logout/" >Sign out</a></li>
<li><a rel="nofollow" href="/accounts/profile/">Account info</a></li>
<li><a rel="nofollow" href="/accounts/profile/">Edit profile</a></li>
{% else %}
<li><a rel="nofollow" href="/accounts/login/?next={{request.get_full_path|urlencode}}">Sign in</a></li>
<li><a rel="nofollow" href="/accounts/reset/">Password reset</a></li>
{% endif %}
{% endif %}
{% if not request.user.is_authenticated %}
<li><a href="{% url "ietf.ietfauth.views.create_account" %}">New account</a></li>
{% endif %}
<li><a href="{% url "ietf.ietfauth.views.create_account" %}">{% if request.user.is_authenticated %}Manage account{% else %}New account{% endif %}</a></li>
<li><a href="{%url "ietf.cookies.views.preferences" %}" rel="nofollow">Preferences</a></li>
{% if user|has_role:"Reviewer" %}

View file

@ -200,19 +200,9 @@
specification, is as follows(select one licensing declaration option only):
</p>
{% if ipr.licensing.slug == "provided-later" %}
<div>
Possible licencing choices a), b), and c) when Licencing Declaration to be Provided Later:
<ul style="list-style: none">
{% for desc in choices_abc %}
<li>{{ desc}}</li>
{% endfor %}
</ul>
</p>
{% endif %}
<dl class="dl-horizontal">
<dt>Licensing</dt>
<dd>{% if ipr.licensing.slug == "provided-later" %}{{ ipr.licensing.desc|slice:"2:"|slice:":117" }}){% else %}{{ ipr.licensing.desc|slice:"2:" }}{% endif %}</dd>
<dd>{% if ipr.licensing.slug == "later" %}{{ ipr.licensing.desc|slice:"2:"|slice:":43" }}{% else %}{{ ipr.licensing.desc|slice:"2:" }}{% endif %}</dd>
<dt>Licensing information, comments, notes, or URL for further information</dt>
<dd>{{ ipr.licensing_comments|default:"(No information submitted)"|linebreaks }}</dd>

View file

@ -3,56 +3,30 @@
{% load origin %}
{% load bootstrap3 %}
{% load staticfiles %}
{% block title %}Account creation{% endblock %}
{% block js %}
{{ block.super }}
<script type="text/javascript" src="{% static 'zxcvbn/zxcvbn.js' %}"></script>
<script type="text/javascript" src="{% static 'ietf/js/password_strength.js' %}"></script>
{% endblock %}
{% block title %}Change password{% endblock %}
{% block content %}
{% origin %}
{% if success %}
<h1>Your password was successfully changed.</h1>
<h1>Password change successful</h1>
<p>Your password has been updated.</p>
<a type="a" class="btn btn-primary" href="/accounts/login/" rel="nofollow">Sign in</a>
{% else %}
<div class="row">
<div class="col-md-2 col-sm-0"></div>
<div class="col-md-8 col-sm-12">
<h1>Change password</h1>
<h1>Change password</h1>
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
<p>You can change the password below for your user {{ username }} below.</p>
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button type="submit" class="btn btn-primary">Change password</button>
{% endbuttons %}
</form>
<div class="help-block">
This password change form uses the
<a href="https://blogs.dropbox.com/tech/2012/04/zxcvbn-realistic-password-strength-estimation/">zxcvbn</a>
password strength estimator to give an indication of password strength.
The crack times given assume online attack without rate limiting,
at a rate of 10 attempts per second.
</div>
<div class="help-block">
The datatracker currently uses a <b>{{ hasher.algorithm }}</b>-based
password hasher with
<b>{% if hasher.iterations %}{{ hasher.iterations }} iterations{% else %}{{ hasher.rounds }} rounds{% endif %}</b>.
Calculating offline attack time if password hashes wouldleak is left
as an excercise for the reader.
</div>
</div>
<div class="col-md-2 col-sm-0"></div>
</div>
{% buttons %}
<button type="submit" class="btn btn-primary">Change password</button>
{% endbuttons %}
</form>
{% endif %}
{% endblock %}

View file

@ -18,9 +18,22 @@
{% else %}
<div class="row">
<div class="col-md-2 col-sm-0"></div>
<div class="col-md-8 col-sm-12">
<div class="col-md-6">
<h1>Account creation</h1>
<p>Please enter your email address in order to create a new datatracker account.</p>
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button type="submit" class="btn btn-primary">Create account</button>
{% endbuttons %}
</form>
</div>
<div class="col-md-6">
<h1>Other options</h1>
<p>
<b>If you already have an account and want to use a new email address,</b>
please go to your account profile page and
@ -36,20 +49,7 @@
<p>
<a class="btn btn-warning" href="{% url "ietf.ietfauth.views.password_reset" %}">Reset your password</a>
</p>
<hr>
<p>Please enter your email address in order to create your datatracker account.</p>
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button type="submit" class="btn btn-primary">Create account</button>
{% endbuttons %}
</form>
</div>
<div class="col-md-2 col-sm-0"></div>
</div>
{% endif %}
{% endblock %}

View file

@ -22,13 +22,6 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Password</label>
<div class="col-sm-10">
<p class="form-control-static"><a href="{% url 'ietf.ietfauth.views.change_password' %}">Password change form</a></p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Email addresses</label>
<div class="col-sm-10">

View file

@ -8,27 +8,24 @@
{% block content %}
{% origin %}
<div class="col-md-2 col-sm-0"></div>
<div class="col-md-8 col-sm-12">
<h1>Sign in</h1>
<h1>Sign in</h1>
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<table class="col-md-12">
<tr>
<td >
<button type="submit" class="btn btn-primary">Sign in</button>
</td>
<td >
Forgot your password? <a href="{% url 'ietf.ietfauth.views.password_reset' %}">Request a reset</a>.
</td>
</tr>
</table>
{% endbuttons %}
</form>
{% buttons %}
<table class="col-md-12">
<tr>
<td >
<button type="submit" class="btn btn-primary">Sign in</button>
</td>
<td >
Forgot your password? <a href="{% url 'ietf.ietfauth.views.password_reset' %}">Request a reset</a>.
</td>
</tr>
</table>
{% endbuttons %}
</form>
</div>
<div class="col-md-2 col-sm-0"></div>
{% endblock %}

View file

@ -8,11 +8,9 @@ coverage>=4.0.1,!=4.0.2
decorator>=3.4.0
defusedxml>=0.4.1 # for TastyPie when ussing xml; not a declared dependency
Django>=1.9,<1.10
django-bcrypt>=0.9.2
django-bootstrap3>=7.0
django-formtools>=1.0 # instead of django.contrib.formtools in 1.8
django-markup>=1.1
django-password-strength>=1.2.1
django-tastypie>=0.13.1
django-widget-tweaks>=1.3
docutils>=0.12
@ -45,4 +43,3 @@ Unidecode>=0.4.18
#wsgiref>=0.1.2
xml2rfc>=2.5.
xym>=0.1.2,!=0.3
zxcvbn-python>=4.4.14