aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheo Chatzimichos <tampakrap@gmail.com>2013-09-04 11:03:41 -0700
committerTheo Chatzimichos <tampakrap@gmail.com>2013-09-04 11:03:41 -0700
commit6ca78c04886ca3050c952ff0a36098c510b911c9 (patch)
treef5c4885442d87d5e43b9601b793854c7bc863e4f
parentMerge pull request #81 from tampakrap/test_ldapuser (diff)
parentadd integration tests for settings (diff)
downloadidentity.gentoo.org-6ca78c04886ca3050c952ff0a36098c510b911c9.tar.gz
identity.gentoo.org-6ca78c04886ca3050c952ff0a36098c510b911c9.tar.bz2
identity.gentoo.org-6ca78c04886ca3050c952ff0a36098c510b911c9.zip
Merge pull request #82 from dastergon/settings
add support for user settings
-rw-r--r--okupy/accounts/forms.py64
-rw-r--r--okupy/accounts/urls.py14
-rw-r--r--okupy/accounts/views.py248
-rw-r--r--okupy/templates/base.html6
-rw-r--r--okupy/templates/settings-contact.html52
-rw-r--r--okupy/templates/settings-email.html45
-rw-r--r--okupy/templates/settings-gentoo.html42
-rw-r--r--okupy/templates/settings-password.html35
-rw-r--r--okupy/templates/settings-profile.html54
-rw-r--r--okupy/tests/integration/test_settings.py77
-rw-r--r--requirements.txt1
-rwxr-xr-xsetup.py1
12 files changed, 630 insertions, 9 deletions
diff --git a/okupy/accounts/forms.py b/okupy/accounts/forms.py
index 8997e1c..01a342a 100644
--- a/okupy/accounts/forms.py
+++ b/okupy/accounts/forms.py
@@ -5,6 +5,8 @@ from django import forms
from okupy.accounts.models import OpenID_Attributes
from okupy.crypto.ciphers import sessionrefcipher
+import pytz
+
class LoginForm(forms.Form):
username = forms.CharField(max_length=100, label='Username:')
@@ -59,8 +61,70 @@ class SignupForm(forms.Form):
return password_verify
+#Settings
+
+class ProfileSettingsForm(forms.Form):
+ first_name = forms.CharField(
+ max_length=100, label='First Name', required=False)
+ last_name = forms.CharField(
+ max_length=100, label='Last Name', required=False)
+ birthday = forms.DateField(
+ input_formats='%m/%d/%Y', label='Birthday (format: month/day/year)', required=False)
+ timezone = forms.ChoiceField(
+ choices=[(x, x) for x in pytz.common_timezones])
+
+
+class PasswordSettingsForm(forms.Form):
+ old_password = forms.CharField(max_length=30, widget=forms.PasswordInput(
+ ), label='Old Password', required=False)
+ new_password = forms.CharField(max_length=30, widget=forms.PasswordInput(
+ ), label='New Password', required=False)
+ new_password_verify = forms.CharField(max_length=30, widget=forms.PasswordInput(), label='Repeat New Password', required=False)
+
+ def clean(self):
+ cleaned_data = super(PasswordSettingsForm, self).clean()
+ new_password = cleaned_data.get('new_password')
+ new_password_verify = cleaned_data.get('new_password_verify')
+ old_password = cleaned_data.get('old_password')
+ if (new_password or new_password_verify) and (not old_password):
+ raise forms.ValidationError(
+ 'Please enter your current password to change the password.')
+ elif new_password != new_password_verify:
+ raise forms.ValidationError('Passsword verification failed. Please re-enter the new password.')
+ elif (old_password and new_password) and (not new_password_verify):
+ raise forms.ValidationError('Password verification failed. Please repeat your new password.')
+ return cleaned_data
+
+
+class EmailSettingsForm(forms.Form):
+ email = forms.EmailField(max_length=254, label='Add Email', help_text='A valid email address, please.', required=False)
+
+
+class ContactSettingsForm(forms.Form):
+ website = forms.URLField(label='Website', required=False)
+ im = forms.CharField(max_length=100, label='IM', required=False)
+ location = forms.CharField(label='Location', required=False)
+ longitude = forms.FloatField(label='Longitude', required=False)
+ latitude = forms.FloatField(label='Latitude', required=False)
+ phone = forms.CharField(label='Home Phone', required=False)
+ gpg_fingerprint = forms.CharField(label='GPG Fingerprint', required=False)
+
+
+class GentooAccountSettingsForm(forms.Form):
+ gentoo_join_date = forms.CharField(
+ label='Gentoo Join Date', required=False)
+ gentoo_retire_date = forms.CharField(
+ label='Gentoo Retire Date', required=False)
+ developer_bug = forms.CharField(
+ label='Developer Bugs (Bug Number)', required=False)
+ mentor = forms.CharField(max_length=100, label='Mentor', required=False)
+ ssh_key = forms.CharField(widget=forms.Textarea(
+ attrs={'cols': 50, 'rows': 8}), label='SSH Key', required=False)
+
+
# OpenID forms.
+
class SiteAuthForm(forms.ModelForm):
class Meta:
model = OpenID_Attributes
diff --git a/okupy/accounts/urls.py b/okupy/accounts/urls.py
index 86b158b..9212089 100644
--- a/okupy/accounts/urls.py
+++ b/okupy/accounts/urls.py
@@ -9,12 +9,14 @@ accounts_urlpatterns = patterns(
url(r'^login/$', v.login),
url(r'^ssl-auth/$', v.ssl_auth),
url(r'^logout/$', v.logout, name="logout"),
- url(r'^devlist/$', v.lists, {'acc_list': 'devlist'},
- name="active_developers"),
- url(r'^former-devlist/$', v.lists, {'acc_list': 'former-devlist'},
- name="former_developers"),
- url(r'^foundation-members/$', v.lists, {'acc_list': 'foundation-members'},
- name="foundation_members"),
+ url(r'^devlist/$', v.lists, {'acc_list': 'devlist'}, name="active_developers"),
+ url(r'^former-devlist/$', v.lists, {'acc_list': 'former-devlist'}, name="former_developers"),
+ url(r'^foundation-members/$', v.lists, {'acc_list': 'foundation-members'}, name="foundation_members"),
+ url(r'^contact-settings/$', v.contact_settings, name="contact-settings"),
+ url(r'^gentoo-dev-settings/$', v.gentoo_dev_settings, name="gentoo-dev-settings"),
+ url(r'^profile-settings/$', v.profile_settings, name="profile-settings"),
+ url(r'^password-settings/$', v.password_settings, name="password-settings"),
+ url(r'^email-settings/$', v.email_settings, name="email-settings"),
url(r'^signup/$', v.signup),
url(r'^activate/(?P<token>[a-zA-Z0-9-_]+)/$', v.activate),
url(r'^otp-setup/$', v.otp_setup),
diff --git a/okupy/accounts/views.py b/okupy/accounts/views.py
index fc96f55..2db9981 100644
--- a/okupy/accounts/views.py
+++ b/okupy/accounts/views.py
@@ -28,7 +28,9 @@ from urlparse import urljoin
from okupy import OkupyError
from okupy.accounts.forms import (LoginForm, OpenIDLoginForm, SSLCertLoginForm,
OTPForm, SignupForm, SiteAuthForm,
- StrongAuthForm)
+ StrongAuthForm, ProfileSettingsForm,
+ ContactSettingsForm, EmailSettingsForm,
+ GentooAccountSettingsForm, PasswordSettingsForm)
from okupy.accounts.models import LDAPUser, OpenID_Attributes, Queue
from okupy.accounts.openid_store import DjangoDBOpenIDStore
from okupy.common.ldap_helpers import (get_bound_ldapuser,
@@ -47,6 +49,7 @@ import openid.yadis.discover
import openid.fetchers
import django_otp
import io
+import ldap
import logging
import qrcode
@@ -70,7 +73,7 @@ def lists(request, acc_list):
def index(request):
ldb_user = LDAPUser.objects.filter(username=request.user.username)
return render(request, 'index.html', {
- 'ldb_user': ldb_user
+ 'ldb_user': ldb_user,
})
@@ -366,6 +369,247 @@ def activate(request, token):
return redirect(login)
+# Settings
+
+@strong_auth_required
+@otp_required
+def profile_settings(request):
+ """ Primary account settings, """
+ user_profile_info = get_bound_ldapuser(request)
+ profile_settings = None
+ if request.method == "POST":
+ profile_settings = ProfileSettingsForm(request.POST)
+ if profile_settings.is_valid():
+ try:
+ #birthday = profile_settings.cleaned_data['birthday']
+ first_name = profile_settings.cleaned_data['first_name']
+ last_name = profile_settings.cleaned_data['last_name']
+
+ if user_profile_info.first_name != first_name:
+ user_profile_info.first_name = first_name
+
+ if user_profile_info.last_name != last_name:
+ user_profile_info.last_name = last_name
+
+ user_profile_info.full_name = '%s %s' % (first_name, last_name)
+ user_profile_info.gecos = '%s %s' % (first_name, last_name)
+
+ """
+ if user_profile_info.birthday != birthday:
+ user_profile_info.birthday = birthday
+ """
+ try:
+ user_profile_info.save()
+ except IntegrityError:
+ pass
+ except ldap.TYPE_OR_VALUE_EXISTS:
+ pass
+ except Exception as error:
+ logger.critical(error, extra=log_extra_data(request))
+ logger_mail.exception(error)
+ raise OkupyError("Can't contact LDAP server")
+ else:
+ profile_settings = ProfileSettingsForm()
+
+ return render(request, 'settings-profile.html', {
+ 'profile_settings': profile_settings,
+ 'user_profile_info': user_profile_info,
+ })
+
+
+@strong_auth_required
+@otp_required
+def password_settings(request):
+ """ Password settings """
+ user_profile_info = get_bound_ldapuser(request)
+ password_settings = None
+ if request.method == "POST":
+ password_settings = PasswordSettingsForm(request.POST)
+ if password_settings.is_valid():
+ try:
+ new_password = password_settings.cleaned_data['new_password']
+ new_password_verify = password_settings.cleaned_data['new_password_verify']
+ old_password = password_settings.cleaned_data['old_password']
+
+ if old_password and (new_password == new_password_verify):
+ for hash in list(user_profile_info.password):
+ print hash
+ try:
+ if ldap_md5_crypt.verify(old_password, hash):
+ user_profile_info.password.append(ldap_md5_crypt.encrypt(new_password_verify))
+ user_profile_info.password.remove(hash)
+ break
+ except ValueError:
+ # ignore unknown hashes
+ pass
+ try:
+ user_profile_info.save()
+ except IntegrityError:
+ pass
+ except ldap.TYPE_OR_VALUE_EXISTS:
+ pass
+ except Exception as error:
+ logger.critical(error, extra=log_extra_data(request))
+ logger_mail.exception(error)
+ raise OkupyError("Can't contact LDAP server")
+ else:
+ password_settings = PasswordSettingsForm()
+
+ return render(request, 'settings-password.html', {
+ 'password_settings': password_settings,
+ 'user_profile_info': user_profile_info,
+ })
+
+
+@strong_auth_required
+@otp_required
+def email_settings(request):
+ """ Email Settings """
+ user_profile_info = get_bound_ldapuser(request)
+ email_settings = None
+ if request.method == "POST":
+ email_settings = EmailSettingsForm(request.POST)
+ if email_settings.is_valid():
+ try:
+ email = email_settings.cleaned_data['email']
+
+ if request.POST.get('delete'):
+ user_profile_info.email.remove(email)
+ else:
+ user_profile_info.email.append(email)
+
+ try:
+ user_profile_info.save()
+ except IntegrityError:
+ pass
+ except ldap.TYPE_OR_VALUE_EXISTS:
+ pass
+ except Exception as error:
+ logger.critical(error, extra=log_extra_data(request))
+ logger_mail.exception(error)
+ raise OkupyError("Can't contact LDAP server")
+ else:
+ email_settings = EmailSettingsForm()
+
+ return render(request, 'settings-email.html', {
+ 'email_settings': email_settings,
+ 'user_profile_info': user_profile_info,
+ })
+
+
+@strong_auth_required
+@otp_required
+def contact_settings(request):
+ """ Contact details """
+ user_profile_info = get_bound_ldapuser(request)
+ contact_settings = None
+ if request.method == "POST":
+ contact_settings = ContactSettingsForm(request.POST)
+ if contact_settings.is_valid():
+ try:
+ gpg_fingerprint = contact_settings.cleaned_data['gpg_fingerprint']
+ im = contact_settings.cleaned_data['im']
+ latitude = contact_settings.cleaned_data['latitude']
+ location = contact_settings.cleaned_data['location']
+ longitude = contact_settings.cleaned_data['longitude']
+ phone = contact_settings.cleaned_data['phone']
+ website = contact_settings.cleaned_data['website']
+
+ if user_profile_info.location != location:
+ user_profile_info.location = location
+
+ if user_profile_info.phone != phone:
+ user_profile_info.phone = phone
+
+ if user_profile_info.website != website:
+ user_profile_info.website.pop()
+ user_profile_info.website.append(website)
+
+ if user_profile_info.im != im:
+ user_profile_info.im.pop()
+ user_profile_info.im.append(im)
+
+ if user_profile_info.longitude != longitude:
+ user_profile_info.longitude = longitude
+
+ if user_profile_info.latitude != latitude:
+ user_profile_info.latitude = latitude
+
+ if user_profile_info.gpg_fingerprint != gpg_fingerprint:
+ user_profile_info.gpg_fingerprint.pop()
+ user_profile_info.gpg_fingerprint.append(gpg_fingerprint)
+
+ try:
+ user_profile_info.save()
+ except IntegrityError:
+ pass
+ except ldap.TYPE_OR_VALUE_EXISTS:
+ pass
+ except Exception as error:
+ logger.critical(error, extra=log_extra_data(request))
+ logger_mail.exception(error)
+ raise OkupyError("Can't contact LDAP server")
+ else:
+ contact_settings = ContactSettingsForm()
+
+ return render(request, 'settings-contact.html', {
+ 'contact_settings': contact_settings,
+ 'user_profile_info': user_profile_info,
+ })
+
+
+@strong_auth_required
+@otp_required
+def gentoo_dev_settings(request):
+ """ Gentoo related information """
+ user_profile_info = get_bound_ldapuser(request)
+ gentoo_account_settings = None
+ if request.method == "POST":
+ gentoo_account_settings = GentooAccountSettingsForm(request.POST)
+ if gentoo_account_settings.is_valid():
+ try:
+ devbug = gentoo_account_settings.cleaned_data['developer_bug']
+ gentoo_join_date = gentoo_account_settings.cleaned_data['gentoo_join_date']
+ gentoo_mentor = gentoo_account_settings.cleaned_data['mentor']
+ ssh_pubkey = gentoo_account_settings.cleaned_data['ssh_key']
+
+ if user_profile_info.developer_bug != devbug:
+ user_profile_info.developer_bug.append(devbug)
+
+ if user_profile_info.gentoo_join_date != gentoo_join_date:
+ user_profile_info.gentoo_join_date.append(gentoo_join_date)
+
+ if user_profile_info.mentor != gentoo_mentor:
+ user_profile_info.mentor.append(gentoo_mentor)
+
+ if ssh_pubkey:
+ user_profile_info.ssh_key.append(ssh_pubkey)
+
+ if user_profile_info.is_retired or user_profile_info.gentoo_retire_date:
+ gentoo_retire_date = gentoo_account_settings.cleaned_data['gentoo_retire_date']
+ if user_profile_info.gentoo_retire_date != gentoo_retire_date:
+ user_profile_info.gentoo_retire_date.append(
+ gentoo_retire_date)
+
+ try:
+ user_profile_info.save()
+ except IntegrityError:
+ pass
+ except ldap.TYPE_OR_VALUE_EXISTS:
+ pass
+ except Exception as error:
+ logger.critical(error, extra=log_extra_data(request))
+ logger_mail.exception(error)
+ raise OkupyError("Can't contact LDAP server")
+ else:
+ gentoo_account_settings = GentooAccountSettingsForm()
+
+ return render(request, 'settings-gentoo.html', {
+ 'gentoo_account_settings': gentoo_account_settings,
+ 'user_profile_info': user_profile_info,
+ })
+
+
@strong_auth_required
@otp_required
def otp_setup(request):
diff --git a/okupy/templates/base.html b/okupy/templates/base.html
index 3e886a0..d8f1b1e 100644
--- a/okupy/templates/base.html
+++ b/okupy/templates/base.html
@@ -65,7 +65,11 @@
<a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ user.username }}<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="{% url 'index' %}" title="View Profile">View Profile</a></li>
- <li><a href="#" title="Edit Profile">Edit Profile</a></li>
+ <li><a href="{% url 'profile-settings' %}" title="Edit Profile">Edit Profile</a></li>
+ <li><a href="{% url 'contact-settings' %}" title="Contact Settings">Contact Settings</a></li>
+ <li><a href="{% url 'password-settings' %}" title="Change Password">Change Password</a></li>
+ <li><a href="{% url 'email-settings' %}" title="Email Settings">Email Settings</a></li>
+ <li><a href="{% url 'gentoo-dev-settings' %}" title="Gentoo Account Settings">Gentoo Account Settings</a></li>
<li><a href="#" title="Invite others">Invite</a></li>
<li><a href="{% url 'logout' %}" title="Logout">Logout</a></li>
</ul>
diff --git a/okupy/templates/settings-contact.html b/okupy/templates/settings-contact.html
new file mode 100644
index 0000000..502e056
--- /dev/null
+++ b/okupy/templates/settings-contact.html
@@ -0,0 +1,52 @@
+{% extends "base.html" %}
+
+{% block content %}
+<div id="pageRow" class="container">
+ <div class="row">
+ <div id="page" class="span10">
+ <div>
+ <h1>Contact Settings</h1>
+ <h3>Change your contact to details.</h3>
+ <div class="form well">
+ <form action="." method="POST">{% csrf_token %}
+ {{ contact_settings.errors }}
+ {{ contact_settings.non_field_errors }}
+ <div class="row-fluid">
+ {{ contact_settings.website.label_tag }}
+ <input name="website" type="text" value="{{ user_profile_info.website.0 }}" /> {{ contact_settings.website.errors|striptags }}
+ </div>
+ <div class="row-fluid">
+ {{ contact_settings.im.label_tag }}
+ <input name="im" type="text" value="{{ user_profile_info.im.0 }}" /> {{ contact_settings.im.errors|striptags }}
+ </div>
+ <div class="row-fluid">
+ {{ contact_settings.location.label_tag }}
+ <input name="location" type="text" value="{{ user_profile_info.location }}" /> {{ contact_settings.location.errors|striptags }}
+ </div>
+ <div class="row-fluid">
+ {{ contact_settings.longitude.label_tag }}
+ <input name="longitude" type="text" value="{{ user_profile_info.longitude }}" /> {{ contact_settings.longitude.errors|striptags }}
+ </div>
+ <div class="row-fluid">
+ {{ contact_settings.latitude.label_tag }}
+ <input name="latitude" type="text" value="{{ user_profile_info.latitude }}" /> {{ contact_settings.latitude.errors|striptags }}
+ </div>
+ <div class="row-fluid">
+ {{ contact_settings.phone.label_tag }}
+ <input name="phone" type="text" value="{{ user_profile_info.phone }}" /> {{ contact_settings.phone.errors|striptags }}
+ </div>
+ <div class="row-fluid">
+ {{ contact_settings.gpg_fingerprint.label_tag }}
+ <input name="gpg_fingerprint" type="text" value="{{ user_profile_info.gpg_fingerprint.0 }}" /> {{ contact_settings.gpg_fingerprint.errors|striptags }}
+
+ </div>
+ <div class="row-fluid buttons">
+ <input class="btn btn-primary" type="submit" value="Save" />
+ </div>
+ </form>
+ </div>
+ </div>
+ </div>
+{% endblock %}
+
+{# vim:se fileencoding=utf8 et ts=4 sts=4 sw=4 ft=htmldjango : #}
diff --git a/okupy/templates/settings-email.html b/okupy/templates/settings-email.html
new file mode 100644
index 0000000..7f0af1d
--- /dev/null
+++ b/okupy/templates/settings-email.html
@@ -0,0 +1,45 @@
+{% extends "base.html" %}
+
+{% block content %}
+<div id="pageRow" class="container">
+ <div class="row">
+ <div id="page" class="span10">
+ <div>
+ <h1>Email Settings</h1>
+ <h3>Manage your emails.</h3>
+ <div class="form well">
+ {{ email_settings.errors }}
+ {{ email_settings.non_field_errors }}
+ <div class="row-fluid ">
+ <table class="table">
+ <thead>
+ <tr>
+ <th>Email</th>
+ <th> </th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for mail in user_profile_info.email%}
+ <form action="." method="POST">{% csrf_token %}
+ <tr>
+ <td><input type="hidden" name="email" value="{{ mail }}" />{{mail}}</td>
+ <td><input class="btn" type="submit" name="delete" value="Delete" /></td>
+ </tr>
+ </form>
+ {% endfor %}
+ </tbody>
+ </table>
+ <form action="." method="POST">{% csrf_token %}
+ {{ email_settings.email.label_tag }}
+ <input name="email" type="text" /> {{ email_settings.email.errors|striptags }}
+ <div class="row-fluid buttons">
+ <input class="btn btn-primary" type="submit" value="Add email" />
+ </div>
+ </form>
+ </div>
+ </div>
+ </div>
+ </div>
+{% endblock %}
+
+{# vim:se fileencoding=utf8 et ts=4 sts=4 sw=4 ft=htmldjango : #}
diff --git a/okupy/templates/settings-gentoo.html b/okupy/templates/settings-gentoo.html
new file mode 100644
index 0000000..224c838
--- /dev/null
+++ b/okupy/templates/settings-gentoo.html
@@ -0,0 +1,42 @@
+{% extends "base.html" %}
+
+{% block content %}
+<div id="pageRow" class="container">
+ <div class="row">
+ <div id="page" class="span10">
+ <div>
+ <h1>Gentoo Developer Information</h1>
+ <h3>Change your Gentoo related details</h3>
+ {% if user_profile_info.is_developer %}
+ <div class="form well">
+ <form action="." method="POST">{% csrf_token %}
+ <div class="row-fluid">
+ {{ gentoo_account_settings.developer_bug.label_tag }}
+ <input name="developer_bug" type="text" value="{{ user_profile_info.developer_bug.0 }}" /> {{ gentoo_account_settings.developer_bug.errors|striptags }}
+ </div>
+ <div class="row-fluid">
+ {{ gentoo_account_settings.mentor.label_tag }}
+ <input name="mentor" type="text" value="{{ user_profile_info.mentor.0 }}" /> {{ gentoo_account_settings.mentor.errors|striptags }}
+ </div>
+ <div class="row-fluid">
+ {{ gentoo_account_settings.gentoo_join_date.label_tag }}
+ <input name="gentoo_join_date" type="text" value="{{ user_profile_info.gentoo_join_date.0 }}" /> {{ gentoo_account_settings.gentoo_join_date.errors|striptags }}
+ </div>
+ <div class="row-fluid">
+ {{ gentoo_account_settings.gentoo_retire_date.label_tag }}
+ <input name="gentoo_retire_date" type="text" value="{{ user_profile_info.gentoo_retire_date.0 }}" /> {{ gentoo_account_settings.gentoo_retire_date.errors|striptags }}
+ </div>
+ <div class="row-fluid">
+ {{ gentoo_account_settings.ssh_key.label_tag }} {{ gentoo_account_settings.ssh_key.errors|striptags }}
+ {{ gentoo_account_settings.ssh_key }}
+ </div>
+ <div class="row-fluid buttons">
+ <input class="btn btn-primary" type="submit" value="Update" />
+ </div>
+ </form>
+ </div>{% endif %}
+ </div>
+ </div>
+{% endblock %}
+
+{# vim:se fileencoding=utf8 et ts=4 sts=4 sw=4 ft=htmldjango : #}
diff --git a/okupy/templates/settings-password.html b/okupy/templates/settings-password.html
new file mode 100644
index 0000000..3e427b9
--- /dev/null
+++ b/okupy/templates/settings-password.html
@@ -0,0 +1,35 @@
+{% extends "base.html" %}
+
+{% block content %}
+<div id="pageRow" class="container">
+ <div class="row">
+ <div id="page" class="span10">
+ <div>
+ <h1>Change Password</h1>
+ <h3>Change your password.</h3>
+ <div class="form well">
+ <form action="." method="POST">{% csrf_token %}
+ {{ password_settings.errors }}
+ {{ password_settings.non_field_errors }}
+ <div class="row-fluid">
+ {{ password_settings.old_password.label_tag }}
+ {{ password_settings.old_password }} {{ password_settings.old_password.non_field_errors|striptags }}
+ </div>
+ <div class="row-fluid">
+ {{ password_settings.new_password.label_tag }}
+ {{ password_settings.new_password }} {{ password_settings.new_password.errors|striptags }}
+ </div>
+ <div class="row-fluid">
+ {{ password_settings.new_password_verify.label_tag }}
+ {{ password_settings.new_password_verify }} {{ password_settings.new_password_verify.errors|striptags }}
+ </div>
+ <div class="row-fluid buttons">
+ <input class="btn btn-primary" type="submit" value="Update Password" />
+ </div>
+ </form>
+ </div>
+ </div>
+ </div>
+{% endblock %}
+
+{# vim:se fileencoding=utf8 et ts=4 sts=4 sw=4 ft=htmldjango : #}
diff --git a/okupy/templates/settings-profile.html b/okupy/templates/settings-profile.html
new file mode 100644
index 0000000..05cd57c
--- /dev/null
+++ b/okupy/templates/settings-profile.html
@@ -0,0 +1,54 @@
+{% extends "base.html" %}
+
+{% block content %}
+<div id="pageRow" class="container">
+ <div class="row">
+ <div id="page" class="span10">
+ <div>
+ <h1>Profile Information</h1>
+ <h3>Change your basic account information</h3>
+ <div class="form well">
+ <form action="." method="POST">{% csrf_token %}
+ {{ profile_settings.errors }}
+ {{ profile_settings.non_field_errors }}
+ <div class="row-fluid">
+ {{ profile_settings.first_name.label_tag }}
+ <input name="first_name" type="text" value="{{ user_profile_info.first_name }}" /> {{ profile_settings.first_name.errors|striptags }}
+ </div>
+ <div class="row-fluid">
+ {{ profile_settings.last_name.label_tag }}
+ <input name="last_name" type="text" value="{{ user_profile_info.last_name }}" /> {{ profile_settings.last_name.errors|striptags }}
+ </div>
+ <div class="row-fluid">
+ {{ profile_settings.email.label_tag }}
+ <input name="email" type="text" value="{{ user_profile_info.email.0 }}" /> {{ profile_settings.email.errors|striptags }}
+ </div>
+ <!-- <div class="row-fluid">
+ {{ profile_settings.birthday.label_tag }}
+ <input name="birthday" type="text" value="{{ user_profile_info.birthday }}" /> {{ profile_settings.birthday.errors|striptags }}
+ </div> -->
+ <div class="row-fluid">
+ {{ profile_settings.timezone.label_tag }}
+ {{ profile_settings.timezone }}
+ <div class="row-fluid">
+ {{ profile_settings.old_password.label_tag }}
+ {{ profile_settings.old_password }} {{ profile_settings.old_password.non_field_errors|striptags }}
+ </div>
+ <div class="row-fluid">
+ {{ profile_settings.new_password.label_tag }}
+ {{ profile_settings.new_password }} {{ profile_settings.new_password.errors|striptags }}
+ </div>
+ <div class="row-fluid">
+ {{ profile_settings.new_password_verify.label_tag }}
+ {{ profile_settings.new_password_verify }} {{ profile_settings.new_password_verify.errors|striptags }}
+ </div>
+ <div class="row-fluid buttons">
+ <input class="btn btn-primary" type="submit" value="Update Profile" />
+ </div>
+ </form>
+ </div>
+ </div>
+ </div>
+{% endblock %}
+
+{# vim:se fileencoding=utf8 et ts=4 sts=4 sw=4 ft=htmldjango : #}
diff --git a/okupy/tests/integration/test_settings.py b/okupy/tests/integration/test_settings.py
new file mode 100644
index 0000000..f22e926
--- /dev/null
+++ b/okupy/tests/integration/test_settings.py
@@ -0,0 +1,77 @@
+# vim:fileencoding=utf8:et:ts=4:sts=4:sw=4:ft=python
+
+from django.conf import settings
+from django.test import TestCase
+from django.test.client import Client
+from mockldap import MockLdap
+
+from okupy.tests import vars
+
+
+class SettingsIntegrationTests(TestCase):
+ @classmethod
+ def setUpClass(cls):
+ cls.mockldap = MockLdap(vars.DIRECTORY)
+
+ def setUp(self):
+ self.client = Client()
+ self.mockldap.start()
+ self.ldapobject = self.mockldap[settings.AUTH_LDAP_SERVER_URI]
+
+ def tearDown(self):
+ self.mockldap.stop()
+
+ def test_profile_settings_page_uses_correct_template(self):
+ response = self.client.post('/login/', vars.LOGIN_ALICE)
+ response = self.client.get('/')
+ response = self.client.get('/profile-settings/')
+ self.assertTemplateUsed(response, 'base.html')
+ self.assertTemplateUsed(response, 'settings-profile.html')
+
+ def test_password_settings_page_uses_correct_template(self):
+ response = self.client.post('/login/', vars.LOGIN_ALICE)
+ response = self.client.get('/')
+ response = self.client.get('/password-settings/')
+ self.assertTemplateUsed(response, 'base.html')
+ self.assertTemplateUsed(response, 'settings-password.html')
+
+ def test_email_settings_page_uses_correct_template(self):
+ response = self.client.post('/login/', vars.LOGIN_ALICE)
+ response = self.client.get('/')
+ response = self.client.get('/email-settings/')
+ self.assertTemplateUsed(response, 'base.html')
+ self.assertTemplateUsed(response, 'settings-email.html')
+
+ def test_contact_settings_page_uses_correct_template(self):
+ response = self.client.post('/login/', vars.LOGIN_ALICE)
+ response = self.client.get('/')
+ response = self.client.get('/contact-settings/')
+ self.assertTemplateUsed(response, 'base.html')
+ self.assertTemplateUsed(response, 'settings-contact.html')
+
+ def test_gentoo_account_settings_page_uses_correct_template(self):
+ response = self.client.post('/login/', vars.LOGIN_ALICE)
+ response = self.client.get('/')
+ response = self.client.get('/gentoo-dev-settings/')
+ self.assertTemplateUsed(response, 'base.html')
+ self.assertTemplateUsed(response, 'settings-gentoo.html')
+
+ def test_profile_settings_page_returns_404_for_non_authenticated_users(self):
+ response = self.client.get('/profile-settings/')
+ self.assertTrue(response.status_code, 404)
+
+ def test_password_settings_page_returns_404_for_non_authenticated_users(self):
+ response = self.client.get('/password-settings/')
+ self.assertTrue(response.status_code, 404)
+
+ def test_email_settings_page_returns_404_for_non_authenticated_users(self):
+ response = self.client.get('/email-settings/')
+ self.assertTrue(response.status_code, 404)
+
+ def test_contact_setttings_page_returns_404_for_non_authenticated_users(self):
+ response = self.client.get('/contact-settings/')
+ self.assertTrue(response.status_code, 404)
+
+ def test_gentoo_account_settings_page_returns_404_for_non_authenticated_users(self):
+ response = self.client.get('/gentoo-dev-settings/')
+ self.assertTrue(response.status_code, 404)
diff --git a/requirements.txt b/requirements.txt
index 710459a..067e449 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -13,4 +13,5 @@ pyopenssl>=0.13
python-ldap>=2.4.10
python-memcached>=1.53
python-openid>=2.2.5
+pytz>=2012j
qrcode>=3.0
diff --git a/setup.py b/setup.py
index 92adfe0..306ee40 100755
--- a/setup.py
+++ b/setup.py
@@ -46,6 +46,7 @@ setup(
'python-ldap>=2.4.10',
'python-memcached>=1.53',
'python-openid>=2.2.5',
+ 'pytz>=2012j',
'qrcode>=3.0',
],
setup_requires=[