Skip to content

Commit

Permalink
reset password
Browse files Browse the repository at this point in the history
  • Loading branch information
Nodraak committed Nov 2, 2014
1 parent 493b0c4 commit 9e31264
Show file tree
Hide file tree
Showing 18 changed files with 507 additions and 18 deletions.
5 changes: 4 additions & 1 deletion cdc.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ todo long run
- button radius
- flake8 compliant (pep8 + other stuff)
- `git tag -a v1.4 -m 'my version 1.4'` + `git push origin --tags`
- migrations
* ./manage.py schemamigration app_name --initial
* ./manage.py schemamigration app_name --auto

#########################################################
# #
Expand All @@ -20,11 +23,11 @@ todo long run
to do now
- https://docs.djangoproject.com/en/dev/ref/contrib/sitemaps/
- syndication (rss + atom) : https://docs.djangoproject.com/en/dev/ref/contrib/syndication/
- media sociaux (syncro fb, twitter, google) -> https://github.com/foxmask/django-th
- news / tuto / articles : export pdf (pandoc)

to do maybe
- noscript : menu, (logout ok)
- media sociaux (syncro fb, twitter, google) -> https://github.com/foxmask/django-th
- calendar : list (prochain, passés, ...)
- publications : tags, multi-page
- better member (mail, citation, bio, ... osef ?)
Expand Down
10 changes: 8 additions & 2 deletions iTeam/member/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# @Author: Adrien Chardon
# @Date: 2014-07-13 18:51:48
# @Last Modified by: Adrien Chardon
# @Last Modified time: 2014-08-22 17:02:41
# @Last Modified time: 2014-11-02 17:54:01

# This file is part of iTeam.org.
# Copyright (C) 2014 Adrien Chardon (Nodraak).
Expand All @@ -24,10 +24,16 @@

from django.contrib import admin

from iTeam.member.models import Profile
from iTeam.member.models import Profile, ForgotPasswordToken


class ProfileAdmin(admin.ModelAdmin):
search_fields = ['user__username']

admin.site.register(Profile, ProfileAdmin)


class ForgotPasswordTokenAdmin(admin.ModelAdmin):
search_fields = ['user__username']

admin.site.register(ForgotPasswordToken, ForgotPasswordTokenAdmin)
27 changes: 26 additions & 1 deletion iTeam/member/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# @Author: Adrien Chardon
# @Date: 2014-08-20 19:01:30
# @Last Modified by: Adrien Chardon
# @Last Modified time: 2014-09-02 14:02:30
# @Last Modified time: 2014-11-02 17:48:30

# This file is part of iTeam.org.
# Copyright (C) 2014 Adrien Chardon (Nodraak).
Expand Down Expand Up @@ -200,3 +200,28 @@ def clean(self):
del cleaned_data['password_confirm']

return cleaned_data


class LostPasswordForm(forms.Form):

username = forms.CharField(
label='Identifiant',
widget=forms.TextInput(
attrs={
'autofocus': '',
'placeholder': 'Identifiant'
}
)
)

def clean(self):
cleaned_data = super(LostPasswordForm, self).clean()

username = cleaned_data.get('username')

# Check if the user exist
if User.objects.filter(username=username).count() == 0:
msg = u"L'utilisateur %s n'a pas été trouvé." % username
self._errors['username'] = self.error_class([msg])

return cleaned_data
76 changes: 76 additions & 0 deletions iTeam/member/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):
# Adding model 'Profile'
db.create_table(u'member_profile', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('user', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['auth.User'], unique=True)),
('promo', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
('avatar_url', self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True)),
('is_publisher', self.gf('django.db.models.fields.BooleanField')(default=False)),
('is_admin', self.gf('django.db.models.fields.BooleanField')(default=False)),
))
db.send_create_signal(u'member', ['Profile'])


def backwards(self, orm):
# Deleting model 'Profile'
db.delete_table(u'member_profile')


models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'member.profile': {
'Meta': {'object_name': 'Profile'},
'avatar_url': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_admin': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_publisher': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'promo': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True'})
}
}

complete_apps = ['member']
81 changes: 81 additions & 0 deletions iTeam/member/migrations/0002_auto__add_forgotpasswordtoken.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):
# Adding model 'ForgotPasswordToken'
db.create_table(u'member_forgotpasswordtoken', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
('token', self.gf('django.db.models.fields.CharField')(max_length=100)),
('expires', self.gf('django.db.models.fields.DateTimeField')()),
))
db.send_create_signal(u'member', ['ForgotPasswordToken'])


def backwards(self, orm):
# Deleting model 'ForgotPasswordToken'
db.delete_table(u'member_forgotpasswordtoken')


models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'member.forgotpasswordtoken': {
'Meta': {'object_name': 'ForgotPasswordToken'},
'expires': ('django.db.models.fields.DateTimeField', [], {}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'token': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
},
u'member.profile': {
'Meta': {'object_name': 'Profile'},
'avatar_url': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_admin': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_publisher': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'promo': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True'})
}
}

complete_apps = ['member']
Empty file.
45 changes: 44 additions & 1 deletion iTeam/member/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# @Author: Adrien Chardon
# @Date: 2014-08-20 14:35:58
# @Last Modified by: Adrien Chardon
# @Last Modified time: 2014-11-01 14:33:28
# @Last Modified time: 2014-11-02 22:35:10

# This file is part of iTeam.org.
# Copyright (C) 2014 Adrien Chardon (Nodraak).
Expand All @@ -26,6 +26,9 @@

from django.db import models
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.core.mail import send_mail
from django.template.loader import render_to_string


class Profile(models.Model):
Expand All @@ -43,3 +46,43 @@ def get_avatar_url(self):
username_hash = md5(self.user.username).hexdigest()
size = 100
return 'https://secure.gravatar.com/avatar/{0}?d=identicon&s={1}'.format(username_hash, size)


class ForgotPasswordToken(models.Model):
class Meta:
verbose_name = 'Token réinitialisation mot de passe'
verbose_name_plural = 'Tokens réinitialisation mot de passe'

user = models.ForeignKey(User, verbose_name='Utilisateur')
token = models.CharField(max_length=100)
expires = models.DateTimeField('Expiration')

def __str__(self):
return '<ForgotPasswordToken User={}>'.format(self.user)

def get_absolute_url(self):
return reverse('member:password_reset_confirm', args=[self.token])


def send_templated_mail(subject, template, context, recipients):
"""Send an email based on a template.
Args:
subject: (string) Subject of the email
template: (string) Name of the template used for the message
context: (dictionary) Dictionary used for the message
recipients: (list) List of the recipients
Returns:
Number of successfully delivered messages (0 or 1)
"""

message = render_to_string(template, context)

return send_mail(
recipient_list = recipients,
subject = subject,
message = message,
from_email = None, # use default one from settings_prod.py
)
5 changes: 4 additions & 1 deletion iTeam/member/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# @Author: Adrien Chardon
# @Date: 2014-08-19 17:38:33
# @Last Modified by: Adrien Chardon
# @Last Modified time: 2014-10-30 22:55:17
# @Last Modified time: 2014-11-02 18:08:40

# This file is part of iTeam.org.
# Copyright (C) 2014 Adrien Chardon (Nodraak).
Expand Down Expand Up @@ -36,6 +36,9 @@
url(r'^inscription/$', views.register_view, name='register_view'),
url(r'^connexion/$', views.login_view, name='login_view'),
url(r'^deconnexion/$', views.logout_view, name='logout_view'),

url(r'^oubli/$', views.password_reset_ask, name='password_reset_ask'),
url(r'^oubli/(?P<token>.+)/$', views.password_reset_confirm, name='password_reset_confirm'),
)

# Note : '_view' because of weird recursive function call ...
Loading

0 comments on commit 9e31264

Please sign in to comment.