From 762a9692314cb9d75e4b753948171ff7b25f91f8 Mon Sep 17 00:00:00 2001 From: Kuiyu CHANG Date: Thu, 24 Mar 2016 15:12:30 +0800 Subject: [PATCH 01/10] added logic to show an error page/msg if email cannot be sent as reported by email smtp server. Also added optional captcha in reset page if django-simple-captcha==0.5.1 is installed --- docs/quickstart.rst | 2 + password_reset/__init__.py | 2 +- password_reset/forms.py | 10 ++ .../locale/zh-hans/LC_MESSAGES/django.mo | Bin 0 -> 3212 bytes .../locale/zh-hans/LC_MESSAGES/django.po | 160 ++++++++++++++++++ .../zh-hans/LC_MESSAGES/django.po.original | 122 +++++++++++++ password_reset/locale/zh_Hans | 1 + .../password_reset/recovery_email.txt | 4 + .../password_reset/recovery_form.html | 46 ++++- .../templates/password_reset/reset_sent.html | 6 + .../password_reset/reset_sent_failed.html | 11 ++ password_reset/urls.py | 2 + password_reset/views.py | 32 +++- setup.py | 1 + 14 files changed, 387 insertions(+), 12 deletions(-) create mode 100644 password_reset/locale/zh-hans/LC_MESSAGES/django.mo create mode 100644 password_reset/locale/zh-hans/LC_MESSAGES/django.po create mode 100644 password_reset/locale/zh-hans/LC_MESSAGES/django.po.original create mode 120000 password_reset/locale/zh_Hans create mode 100644 password_reset/templates/password_reset/reset_sent_failed.html diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 2776bd50..42482bf4 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -32,6 +32,8 @@ What you get * Password reset links that expire in two days (configurable). +* Optionally invoke a captcha in the password reset page if django-simple-captcha (0.5.1 or higher) is installed and configured. + What you can do --------------- diff --git a/password_reset/__init__.py b/password_reset/__init__.py index ef72cc0f..4ca39e7c 100644 --- a/password_reset/__init__.py +++ b/password_reset/__init__.py @@ -1 +1 @@ -__version__ = '0.8.1' +__version__ = '0.8.2' diff --git a/password_reset/forms.py b/password_reset/forms.py index 4f8b4ec5..1c8f16b9 100644 --- a/password_reset/forms.py +++ b/password_reset/forms.py @@ -4,11 +4,21 @@ from django.utils.translation import ugettext_lazy as _ from django.conf import settings + +try: + from captcha.fields import CaptchaField # uses django-simple-captcha==0.5.1 +except ImportError: + pass + from .utils import get_user_model class PasswordRecoveryForm(forms.Form): username_or_email = forms.CharField() + try: + captcha = CaptchaField(label=_('Captcha')) # Optional Captcha + except: + pass error_messages = { 'not_found': _("Sorry, this user doesn't exist."), diff --git a/password_reset/locale/zh-hans/LC_MESSAGES/django.mo b/password_reset/locale/zh-hans/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..eb97a3849505d7ac3deda98f3749d92d32ec2515 GIT binary patch literal 3212 zcmai#TWlQF8OINoLTm1nYfIrMQot6TjguA>7UO1XFTui>$X*A9R;AfeQ0-PcM(z^dEtToH)rmIkW$H^zIpk<2jtq;C$>3#u~u;@5BYi3itrH3J!pq;Jx7UcQN)T7y^F* zM!;5ZFZfsRICww!4fq839r!T#;N6Tp0zLh5 zufcc0d*Phc+u$+qOz`~dJ%|O*E#NP~UXc9$1$+xM!I!{)f&0Pl!TZ2o1h)q{cnACy zp69UmF!&ir&pU8=3Va2`64nDozyn|t_$i1V`wExG!GD7ff!~6ZukQmsRHy8018MwK zkn+_P@XsKovO$p6OOWCo1OEnI1%CrR3DIwZyTE6`Ns#)aH>d`P$L zVM``LtW_U!;)6PC6S{DWSt*e9*Fhtd)`f z=cIjrMtQz%9!h1oku)tyAsBX$1>HO%Au9}FpJn;IsWeylJ-LQ2Sj@iB-1zd`_bx_Fc?IXOaJI3uyJT7c|Ad~u$36_bR zB`hS$Y_NaiJ=Kl%Cuah=i{gh6FDWW{c%yv9#uInS6(xmVp`!`?wXWh6rU0Ez@_NHC?jS?7aN47|2& zdwn@a?_^}E!QR#)#d{fHm%GU_Me`25WvegJhKdWD#EJLO*C7@|ORAnnusIl@`bdACkfm zX2LL&WCcoT3t-A1_H&Rw1g%#T1W|5jsSvA_q`X&Z8-n*|5m+i^4f|ebw@^*Pw5r+z zzQ<}CV|(=rVJdgknj=EmVA4nqqU)?-4k7+0#7d$chtQ9{81!3AW>VNK()zoIJ6d}} z+m9|pQNny*r1j0n-YDN6?dfgr?yBn%LzZ;3PCIENv_EB%widI(yl!82Oly_GucX$d zJ0i??HSK&^YucqXy~KCE9R9=Z7n^oBHDRLGBMus5JeYSN8tKtGyS26mf1^9x+5Y0& z-CfbT4&8RNnAA->Mc>Xaf4#4xgLg$bqr5rV8ENm>6KQMfiT3ukV5*tSAQ&ws^mLea zM7s9&k>uu%jy)+OWXWW84y1OrcSfu6?F=>5wW7tatF>5m2)Z5dzO!Q}g)RFkzJI#J zwtB5E_PVyaI*()x2&qNQxJBI%=DYh1r;ZhJ^M$D+#gPw~d+i^E^;7QIrQjQ$Ute@5 zCf%vi-q=!M_Hbz|SIDi_e1vcN_PeJ}mqteO*Ni* zEL<-go%B9jDdsi`H*?A~9^K_5g}KoXE9Mr8%cHnuwf_Pzg_-W+&09BSnG(Xv11GBg zMzlTD-$u>f0yGpi&bS{e-tO!8Vt#GXJ9Gt#AV*1nEBDkg#lCs7Ftg}gUQpWqH!{X5 zI;(fLZj2Y^b5MQj#stLsF_oiXwUH|8Oy#K7Ajc zuHxKzcWuo(w(4D;Ky;;Z=e^I@i`NbnrkA|&Yu-n5-jx}cLN%0KKhnzVGaKH?#h^77 zR=t_=pcX1eXP18J`%L9u9m}tc8nbnlAPb1_ePf?*}HVHxOuWTI$gN3?v0<$uU|sXy19$q*~!wO zrP4=B6jpw1!MilC+JRpCO$XPISUmbU^CmV($M}kO;;5UORVr9TWA)A({}4N-+K71e zE==XGUq=A7g)B^8K@PAZY9;&mMK}8yERD<-H;<51Yy4C;y literal 0 HcmV?d00001 diff --git a/password_reset/locale/zh-hans/LC_MESSAGES/django.po b/password_reset/locale/zh-hans/LC_MESSAGES/django.po new file mode 100644 index 00000000..6fdbb8df --- /dev/null +++ b/password_reset/locale/zh-hans/LC_MESSAGES/django.po @@ -0,0 +1,160 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-02-05 16:48+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: forms.py:14 +msgid "Captcha" +msgstr "认证码" + +#: forms.py:17 +msgid "Sorry, this user doesn't exist." +msgstr "抱歉,用户名不存在." + +#: forms.py:34 +msgid "Username" +msgstr "用户名" + +#: forms.py:35 +msgid "Email" +msgstr "邮箱" + +#: forms.py:36 +msgid "Username or Email" +msgstr "用户名或者邮箱" + +#: forms.py:58 +msgid "Sorry, inactive users can't recover their password." +msgstr "非常抱歉,非活跃用户无法重置密码。" + +#: forms.py:96 +msgid "Unable to find user." +msgstr "找不到指定用户" + +#: forms.py:103 +msgid "New password" +msgstr "新密码" + +#: forms.py:107 +msgid "New password (confirm)" +msgstr "新密码(确认)" + +#: forms.py:112 +msgid "The two passwords didn't match." +msgstr "两次输入的密码不一致" + +#: templates/password_reset/recovery_done.html:3 +msgid "New password set" +msgstr "设置新密码" + +#: templates/password_reset/recovery_done.html:6 +msgid "" +"Your password has successfully been reset. You can use it right now on the " +"login page." +msgstr "您的密码已经重设成功,现在可以登录了。" + +#: templates/password_reset/recovery_email.txt:1 +#, python-format +msgid "Dear %(username)s," +msgstr "%(username)s,您好:" + +#: templates/password_reset/recovery_email.txt:3 +#, python-format +msgid "" +"You -- or someone pretending to be you -- has requested a password reset on " +"%(domain)s." +msgstr "您或某人在 %(domain)s 申请了密码重置。" + +#: templates/password_reset/recovery_email.txt:5 +msgid "You can set your new password by following this link:" +msgstr "您可以通过以下链接重置密码:" + +#: templates/password_reset/recovery_email.txt:9 +msgid "" +"If you don't want to reset your password, simply ignore this email and it " +"will stay unchanged." +msgstr "若不想重设密码,可以忽略此邮件。" + +#: templates/password_reset/recovery_email.txt:11 +msgid "Yours Truly" +msgstr "感谢您的惠顾" + +#: templates/password_reset/recovery_email.txt:12 +msgid "Administrator" +msgstr "管理者" + +#: templates/password_reset/recovery_email_subject.txt:1 +#, python-format +msgid "Password recovery on %(domain)s" +msgstr "重设 %(domain)s 密码" + +#: templates/password_reset/recovery_form.html:5 +msgid "Password recovery" +msgstr "重新设置密码" + +#: templates/password_reset/recovery_form.html:8 +msgid "Recover Password" +msgstr "重设密码" + +#: templates/password_reset/recovery_form.html:60 +msgid "Recover my password" +msgstr "重设密码" + +#: templates/password_reset/reset.html:5 +#, python-format +msgid "" +"Sorry, this password reset link is invalid. You can still request a new one." +msgstr "" +"抱歉,链接已经失效,您可以在 请求一个新链接." + +#: templates/password_reset/reset.html:7 +#, python-format +msgid "Hi, %(username)s. Please choose your new password." +msgstr "您好,%(username)s. 请输入您的新密码." + +#: templates/password_reset/reset.html:11 +msgid "Set new password" +msgstr "设置新密码" + +#: templates/password_reset/reset_sent.html:4 +msgid "Password recovery sent" +msgstr "发送重设密码" + +#: templates/password_reset/reset_sent.html:8 +#, python-format +msgid "" +"An email was sent to %(email)s %(ago)s ago. Use the link in " +"it to set a new password." +msgstr "" +"已经在%(ago)s以前向您的邮箱 %(email)s 发送了邮件,请根据邮件" +"提示重新设置您的新密码." + +#: templates/password_reset/reset_sent.html:11 +#: templates/password_reset/reset_sent_failed.html:9 +msgid "Return to Main Page" +msgstr "回主页" + +#: templates/password_reset/reset_sent_failed.html:4 +msgid "Password recovery NOT successful" +msgstr "发送重设密码" + +#: templates/password_reset/reset_sent_failed.html:7 +msgid "" +"The email for this registered user is invalid, password reset information " +"cannot be sent. Please contact our administrator for assistance." +msgstr "此用户电邮地址无法接收密码重置信息。欢迎联系我们的客服部门。" diff --git a/password_reset/locale/zh-hans/LC_MESSAGES/django.po.original b/password_reset/locale/zh-hans/LC_MESSAGES/django.po.original new file mode 100644 index 00000000..12fa1c0a --- /dev/null +++ b/password_reset/locale/zh-hans/LC_MESSAGES/django.po.original @@ -0,0 +1,122 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-01-23 10:01+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: forms.py:26 +msgid "Username" +msgstr "用户名" + +#: forms.py:27 +msgid "Email" +msgstr "邮箱" + +#: forms.py:28 +msgid "Username or Email" +msgstr "用户名或者邮箱" + +#: forms.py:48 forms.py:58 forms.py:70 +msgid "Sorry, this user doesn't exist." +msgstr "抱歉,用户名不存在." + +#: forms.py:72 +msgid "Unable to find user." +msgstr "找不到指定用户" + +#: forms.py:78 +msgid "New password" +msgstr "新密码" + +#: forms.py:82 +msgid "New password (confirm)" +msgstr "新密码(确认)" + +#: forms.py:94 +msgid "The two passwords didn't match." +msgstr "两次输入的密码不一致" + +#: templates/password_reset/recovery_done.html:3 +msgid "New password set" +msgstr "设置新密码" + +#: templates/password_reset/recovery_done.html:6 +msgid "" +"Your password has successfully been reset. You can use it right now on the " +"login page." +msgstr "您的密码已经重设成功,现在可以登录了." + +#: templates/password_reset/recovery_email.txt:1 +#, python-format +msgid "Dear %(username)s," +msgstr "您好 %(username)s," + +#: templates/password_reset/recovery_email.txt:3 +#, python-format +msgid "" +"You -- or someone pretending to be you -- has requested a password reset on " +"%(domain)s." +msgstr "您或者其它的人在 %(domain)s 申请了密码重置." + +#: templates/password_reset/recovery_email.txt:5 +msgid "You can set your new password by following this link:" +msgstr "您可以通过以下链接重置密码:" + +#: templates/password_reset/recovery_email.txt:9 +msgid "" +"If you don't want to reset your password, simply ignore this email and it " +"will stay unchanged." +msgstr "如果您不想重设密码,可以忽略此邮箱." + +#: templates/password_reset/recovery_email_subject.txt:1 +#, python-format +msgid "Password recovery on %(domain)s" +msgstr "在 %(domain)s 上重设密码" + +#: templates/password_reset/recovery_form.html:5 +msgid "Password recovery" +msgstr "重新设置密码" + +#: templates/password_reset/recovery_form.html:11 +msgid "Recover my password" +msgstr "重设密码" + +#: templates/password_reset/reset.html:5 +#, python-format +msgid "" +"Sorry, this password reset link is invalid. You can still request a new one." +msgstr "抱歉,链接已经失效,您可以在 请求一个新链接." + +#: templates/password_reset/reset.html:7 +#, python-format +msgid "Hi, %(username)s. Please choose your new password." +msgstr "您好,%(username)s. 请输入您的新密码." + +#: templates/password_reset/reset.html:11 +msgid "Set new password" +msgstr "设置新密码" + +#: templates/password_reset/reset_sent.html:4 +msgid "Password recovery sent" +msgstr "发送重设密码" + +#: templates/password_reset/reset_sent.html:7 +#, python-format +msgid "" +"An email was sent to %(email)s %(ago)s ago. Use the link in " +"it to set a new password." +msgstr "已经在%(ago)s以前向您的邮箱 %(email)s发送了邮件,根据邮件提示重新设置您的新密码." diff --git a/password_reset/locale/zh_Hans b/password_reset/locale/zh_Hans new file mode 120000 index 00000000..80d1c227 --- /dev/null +++ b/password_reset/locale/zh_Hans @@ -0,0 +1 @@ +zh-hans \ No newline at end of file diff --git a/password_reset/templates/password_reset/recovery_email.txt b/password_reset/templates/password_reset/recovery_email.txt index 9c4af9cc..70b1af2a 100644 --- a/password_reset/templates/password_reset/recovery_email.txt +++ b/password_reset/templates/password_reset/recovery_email.txt @@ -7,3 +7,7 @@ http{% if secure %}s{% endif %}://{{ site.domain }}{% url "password_reset_reset" token %} {% trans "If you don't want to reset your password, simply ignore this email and it will stay unchanged." %} + +{% trans "Yours Truly" %}, +{% trans "Administrator" %} +{{ site.domain }} diff --git a/password_reset/templates/password_reset/recovery_form.html b/password_reset/templates/password_reset/recovery_form.html index e0aff0ca..defaca11 100644 --- a/password_reset/templates/password_reset/recovery_form.html +++ b/password_reset/templates/password_reset/recovery_form.html @@ -1,12 +1,46 @@ {% extends "password_reset/base.html" %} {% load i18n %} +{% load sekizai_tags %} {% block title %}{% trans "Password recovery" %}{% endblock %} {% block content %} -
- {% csrf_token %} - {{ form.as_p }} -

-
-{% endblock %} +

{% trans "Recover Password" %}

+
+{% csrf_token %} +{% for field in form %} +{% if field.name != "captcha" %} +
+ {{ field.label_tag }} + +
+{% else %} +

+

+ + + +   {{ field }} +
+{% endif %} +
+ {{ field.errors }} +
+{% endfor %} + +
+
+ +
+
+ +
+{% endblock content %} diff --git a/password_reset/templates/password_reset/reset_sent.html b/password_reset/templates/password_reset/reset_sent.html index bc56b7c2..f5362f78 100644 --- a/password_reset/templates/password_reset/reset_sent.html +++ b/password_reset/templates/password_reset/reset_sent.html @@ -4,5 +4,11 @@ {% block title %}{% trans "Password recovery sent" %}{% endblock %} {% block content %} + + +{% trans "Return to Main Page" %} + + {% endblock %} diff --git a/password_reset/templates/password_reset/reset_sent_failed.html b/password_reset/templates/password_reset/reset_sent_failed.html new file mode 100644 index 00000000..77f3f6c3 --- /dev/null +++ b/password_reset/templates/password_reset/reset_sent_failed.html @@ -0,0 +1,11 @@ +{% extends "password_reset/base.html" %} +{% load i18n %} + +{% block title %}{% trans "Password recovery NOT successful" %}{% endblock %} + +{% block content %} +

{% trans "The email for this registered user is invalid, password reset information cannot be sent. Please contact our administrator for assistance." %}

+ +{% trans "Return to Main Page" %} + +{% endblock %} diff --git a/password_reset/urls.py b/password_reset/urls.py index eedad198..7b4817d9 100644 --- a/password_reset/urls.py +++ b/password_reset/urls.py @@ -6,6 +6,8 @@ urlpatterns = [ url(r'^recover/(?P.+)/$', views.recover_done, name='password_reset_sent'), + url(r'^recover/(?P.+)/$', views.recover_failed, + name='password_reset_sent_failed'), url(r'^recover/$', views.recover, name='password_reset_recover'), url(r'^reset/done/$', views.reset_done, name='password_reset_done'), url(r'^reset/(?P[\w:-]+)/$', views.reset, diff --git a/password_reset/views.py b/password_reset/views.py index 6be66ee0..6cb35a17 100644 --- a/password_reset/views.py +++ b/password_reset/views.py @@ -31,7 +31,7 @@ def loads_with_timestamp(value, salt): """Returns the unsigned value along with its timestamp, the time when it got dumped.""" try: - signing.loads(value, salt=salt, max_age=-1) + signing.loads(value, salt=salt, max_age=-999999) except signing.SignatureExpired as e: age = float(str(e).split('Signature age ')[1].split(' >')[0]) timestamp = timezone.now() - datetime.timedelta(seconds=age) @@ -52,18 +52,39 @@ def get_context_data(self, **kwargs): return ctx recover_done = RecoverDone.as_view() +class RecoverFailed(SaltMixin, generic.TemplateView): + template_name = 'password_reset/reset_sent_failed.html' + + def get_context_data(self, **kwargs): + ctx = super(RecoverFailed, self).get_context_data(**kwargs) + try: + ctx['timestamp'], ctx['email'] = loads_with_timestamp( + self.kwargs['signature'], salt=self.url_salt, + ) + except signing.BadSignature: + raise Http404 + return ctx +recover_failed = RecoverFailed.as_view() + + class Recover(SaltMixin, generic.FormView): case_sensitive = True form_class = PasswordRecoveryForm template_name = 'password_reset/recovery_form.html' success_url_name = 'password_reset_sent' + failure_url_name = 'password_reset_sent_failed' email_template_name = 'password_reset/recovery_email.txt' email_subject_template_name = 'password_reset/recovery_email_subject.txt' search_fields = ['username', 'email'] + sent_success = 0 def get_success_url(self): - return reverse(self.success_url_name, args=[self.mail_signature]) + if self.sent_success: + return reverse(self.success_url_name, args=[self.mail_signature]) + else: + return reverse(self.failure_url_name, args=[self.mail_signature]) + def get_context_data(self, **kwargs): kwargs['url'] = self.request.get_full_path() @@ -92,12 +113,13 @@ def send_notification(self): context).strip() subject = loader.render_to_string(self.email_subject_template_name, context).strip() - send_mail(subject, body, settings.DEFAULT_FROM_EMAIL, - [self.user.email]) + result = send_mail(subject, body, settings.DEFAULT_FROM_EMAIL, + [self.user.email], fail_silently=True) + return result def form_valid(self, form): self.user = form.cleaned_data['user'] - self.send_notification() + self.sent_success = self.send_notification() if ( len(self.search_fields) == 1 and self.search_fields[0] == 'username' diff --git a/setup.py b/setup.py index df82b271..b657ef5f 100644 --- a/setup.py +++ b/setup.py @@ -20,6 +20,7 @@ long_description=open('README.rst').read(), install_requires=[ 'Django>=1.4', + #'django-simple-captcha>=0.5.1', # will use captcha if installed ], classifiers=[ 'Development Status :: 4 - Beta', From ad9b1fec09eddd8252fba4a64ad898fa9fa8c5af Mon Sep 17 00:00:00 2001 From: Kuiyu CHANG Date: Thu, 24 Mar 2016 15:35:55 +0800 Subject: [PATCH 02/10] removed/cleaned django.po.original --- .../zh-hans/LC_MESSAGES/django.po.original | 122 ------------------ 1 file changed, 122 deletions(-) delete mode 100644 password_reset/locale/zh-hans/LC_MESSAGES/django.po.original diff --git a/password_reset/locale/zh-hans/LC_MESSAGES/django.po.original b/password_reset/locale/zh-hans/LC_MESSAGES/django.po.original deleted file mode 100644 index 12fa1c0a..00000000 --- a/password_reset/locale/zh-hans/LC_MESSAGES/django.po.original +++ /dev/null @@ -1,122 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-23 10:01+0800\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: forms.py:26 -msgid "Username" -msgstr "用户名" - -#: forms.py:27 -msgid "Email" -msgstr "邮箱" - -#: forms.py:28 -msgid "Username or Email" -msgstr "用户名或者邮箱" - -#: forms.py:48 forms.py:58 forms.py:70 -msgid "Sorry, this user doesn't exist." -msgstr "抱歉,用户名不存在." - -#: forms.py:72 -msgid "Unable to find user." -msgstr "找不到指定用户" - -#: forms.py:78 -msgid "New password" -msgstr "新密码" - -#: forms.py:82 -msgid "New password (confirm)" -msgstr "新密码(确认)" - -#: forms.py:94 -msgid "The two passwords didn't match." -msgstr "两次输入的密码不一致" - -#: templates/password_reset/recovery_done.html:3 -msgid "New password set" -msgstr "设置新密码" - -#: templates/password_reset/recovery_done.html:6 -msgid "" -"Your password has successfully been reset. You can use it right now on the " -"login page." -msgstr "您的密码已经重设成功,现在可以登录了." - -#: templates/password_reset/recovery_email.txt:1 -#, python-format -msgid "Dear %(username)s," -msgstr "您好 %(username)s," - -#: templates/password_reset/recovery_email.txt:3 -#, python-format -msgid "" -"You -- or someone pretending to be you -- has requested a password reset on " -"%(domain)s." -msgstr "您或者其它的人在 %(domain)s 申请了密码重置." - -#: templates/password_reset/recovery_email.txt:5 -msgid "You can set your new password by following this link:" -msgstr "您可以通过以下链接重置密码:" - -#: templates/password_reset/recovery_email.txt:9 -msgid "" -"If you don't want to reset your password, simply ignore this email and it " -"will stay unchanged." -msgstr "如果您不想重设密码,可以忽略此邮箱." - -#: templates/password_reset/recovery_email_subject.txt:1 -#, python-format -msgid "Password recovery on %(domain)s" -msgstr "在 %(domain)s 上重设密码" - -#: templates/password_reset/recovery_form.html:5 -msgid "Password recovery" -msgstr "重新设置密码" - -#: templates/password_reset/recovery_form.html:11 -msgid "Recover my password" -msgstr "重设密码" - -#: templates/password_reset/reset.html:5 -#, python-format -msgid "" -"Sorry, this password reset link is invalid. You can still request a new one." -msgstr "抱歉,链接已经失效,您可以在 请求一个新链接." - -#: templates/password_reset/reset.html:7 -#, python-format -msgid "Hi, %(username)s. Please choose your new password." -msgstr "您好,%(username)s. 请输入您的新密码." - -#: templates/password_reset/reset.html:11 -msgid "Set new password" -msgstr "设置新密码" - -#: templates/password_reset/reset_sent.html:4 -msgid "Password recovery sent" -msgstr "发送重设密码" - -#: templates/password_reset/reset_sent.html:7 -#, python-format -msgid "" -"An email was sent to %(email)s %(ago)s ago. Use the link in " -"it to set a new password." -msgstr "已经在%(ago)s以前向您的邮箱 %(email)s发送了邮件,根据邮件提示重新设置您的新密码." From 15eb17f830d45b6db9ce754195cfc88f04928e5a Mon Sep 17 00:00:00 2001 From: Kuiyu CHANG Date: Mon, 28 Mar 2016 09:44:36 +0800 Subject: [PATCH 03/10] removed sekizai_tags from include, which broke the travis build --- password_reset/templates/password_reset/recovery_form.html | 1 - 1 file changed, 1 deletion(-) diff --git a/password_reset/templates/password_reset/recovery_form.html b/password_reset/templates/password_reset/recovery_form.html index defaca11..4e152c0f 100644 --- a/password_reset/templates/password_reset/recovery_form.html +++ b/password_reset/templates/password_reset/recovery_form.html @@ -1,6 +1,5 @@ {% extends "password_reset/base.html" %} {% load i18n %} -{% load sekizai_tags %} {% block title %}{% trans "Password recovery" %}{% endblock %} From 22567e8e3d479421766699ce9a7cd2685e5d18d5 Mon Sep 17 00:00:00 2001 From: Kuiyu CHANG Date: Mon, 28 Mar 2016 17:09:35 +0800 Subject: [PATCH 04/10] fixed test cases to work with optional captchas, also unified error messages in forms --- password_reset/forms.py | 25 +++++++++++-------------- password_reset/tests/settings.py | 14 ++++++++++++-- password_reset/tests/tests.py | 23 +++++++++++++++++------ password_reset/tests/urls.py | 12 +++++++++++- 4 files changed, 51 insertions(+), 23 deletions(-) diff --git a/password_reset/forms.py b/password_reset/forms.py index 1c8f16b9..1eb9a5ec 100644 --- a/password_reset/forms.py +++ b/password_reset/forms.py @@ -8,22 +8,23 @@ try: from captcha.fields import CaptchaField # uses django-simple-captcha==0.5.1 except ImportError: + CaptchaField = None pass from .utils import get_user_model +error_messages = { + 'not_found': _("Sorry, this user doesn't exist."), + 'password_mismatch':_("The two passwords didn't match."), +} class PasswordRecoveryForm(forms.Form): username_or_email = forms.CharField() try: - captcha = CaptchaField(label=_('Captcha')) # Optional Captcha + if CaptchaField and settings.CAPTCHA_CHALLENGE_FUNCT: # defined + captcha = CaptchaField(label=_('Captcha')) # Optional Captcha except: pass - - error_messages = { - 'not_found': _("Sorry, this user doesn't exist."), - } - def __init__(self, *args, **kwargs): self.case_sensitive = kwargs.pop('case_sensitive', True) search_fields = kwargs.pop('search_fields', ('username', 'email')) @@ -73,7 +74,7 @@ def get_user_by_username(self, username): try: user = User._default_manager.get(**{key: username}) except User.DoesNotExist: - raise forms.ValidationError(self.error_messages['not_found'], + raise forms.ValidationError(error_messages['not_found'], code='not_found') return user @@ -84,7 +85,7 @@ def get_user_by_email(self, email): try: user = User._default_manager.get(**{key: email}) except User.DoesNotExist: - raise forms.ValidationError(self.error_messages['not_found'], + raise forms.ValidationError(error_messages['not_found'], code='not_found') return user @@ -97,7 +98,7 @@ def get_user_by_both(self, username): try: user = User._default_manager.get(filters) except User.DoesNotExist: - raise forms.ValidationError(self.error_messages['not_found'], + raise forms.ValidationError(error_messages['not_found'], code='not_found') except User.MultipleObjectsReturned: raise forms.ValidationError(_("Unable to find user.")) @@ -115,10 +116,6 @@ class PasswordResetForm(forms.Form): widget=forms.PasswordInput, ) - error_messages = { - 'password_mismatch': _("The two passwords didn't match."), - } - def __init__(self, *args, **kwargs): self.user = kwargs.pop('user') super(PasswordResetForm, self).__init__(*args, **kwargs) @@ -128,7 +125,7 @@ def clean_password2(self): password2 = self.cleaned_data['password2'] if not password1 == password2: raise forms.ValidationError( - self.error_messages['password_mismatch'], + error_messages['password_mismatch'], code='password_mismatch') return password2 diff --git a/password_reset/tests/settings.py b/password_reset/tests/settings.py index f7c1479b..f9c72830 100644 --- a/password_reset/tests/settings.py +++ b/password_reset/tests/settings.py @@ -9,12 +9,19 @@ }, } -INSTALLED_APPS = ( +INSTALLED_APPS = [ 'django.contrib.auth', 'django.contrib.contenttypes', 'password_reset', 'password_reset.tests', -) +] + +try: + INSTALLED_APPS += [ + #'captcha' # include captcha if available + ] +except: + pass MIGRATION_MODULES = { 'auth': 'django.contrib.auth.tests.migrations', @@ -28,3 +35,6 @@ ), }, }] + +#AUTH_USER_MODEL = None +DISABLE_CAPTCHA=True diff --git a/password_reset/tests/tests.py b/password_reset/tests/tests.py index b80b1dcd..51228c89 100644 --- a/password_reset/tests/tests.py +++ b/password_reset/tests/tests.py @@ -11,20 +11,30 @@ except ImportError: from unittest import SkipTest -from ..forms import PasswordRecoveryForm, PasswordResetForm +from ..forms import PasswordRecoveryForm, PasswordResetForm, error_messages from ..utils import get_user_model +#import settings +""" +Commented out this part due to incompatibilities with Django 1.8.4 +See http://stackoverflow.com/questions/27433228/django-1-7-django-db-utils-operationalerror-no-such-table-auth-customuser if django.VERSION >= (1, 5): from django.contrib.auth.tests.custom_user import ( # noqa CustomUser, ExtensionUser) else: CustomUser = None # noqa ExtensionUser = None # noqa +""" +CustomUser = None +ExtensionUser = None +# Test manually via +# ./manage.py test --settings password_reset.tests.settings password_reset.tests class CustomUserVariants(type): def __new__(cls, name, bases, dct): - if django.VERSION >= (1, 5): + #if django.VERSION >= (1, 5) and settings.AUTH_USER_MODEL: + if 1>2: for custom_user in ['auth.CustomUser', 'auth.ExtensionUser']: suffix = custom_user.lower().replace('.', '_') for key, fn in list(dct.items()): @@ -61,7 +71,7 @@ def test_username_input(self): form = PasswordRecoveryForm(data={'username_or_email': 'inexisting'}) self.assertFalse(form.is_valid()) self.assertEqual(form.errors['username_or_email'], - ["Sorry, this user doesn't exist."]) + [error_messages['not_found']]) create_user() @@ -133,7 +143,7 @@ def test_form_custom_search(self): }, search_fields=['email']) self.assertFalse(form.is_valid()) self.assertEqual(form.errors['username_or_email'], - ["Sorry, this user doesn't exist."]) + [error_messages['not_found']]) user = create_user() @@ -142,7 +152,7 @@ def test_form_custom_search(self): }, search_fields=['email']) self.assertFalse(form.is_valid()) self.assertEqual(form.errors['username_or_email'], - ["Sorry, this user doesn't exist."]) + [error_messages['not_found']]) # Search by actual email works form = PasswordRecoveryForm(data={ @@ -162,7 +172,7 @@ def test_form_custom_search(self): }, search_fields=['username']) self.assertFalse(form.is_valid()) self.assertEqual(form.errors['username_or_email'], - ["Sorry, this user doesn't exist."]) + [error_messages['not_found']]) form = PasswordRecoveryForm(data={ 'username_or_email': 'username', @@ -280,6 +290,7 @@ def test_email_recover(self): self.user = create_user() url = reverse('email_recover') response = self.client.get(url) + print "----------- guiyu: response=%s" % response self.assertNotContains(response, "Username or Email") self.assertContains(response, "Email:") diff --git a/password_reset/tests/urls.py b/password_reset/tests/urls.py index 25832f3d..edc07682 100644 --- a/password_reset/tests/urls.py +++ b/password_reset/tests/urls.py @@ -1,8 +1,13 @@ -from django.conf.urls import url +from django.conf.urls import url, include from ..urls import urlpatterns from . import views +try: + import captcha as captcha_installed +except: + captcha_installed = None + urlpatterns += [ url(r'^email_recover/$', views.email_recover, name='email_recover'), url(r'^username_recover/$', views.username_recover, @@ -10,3 +15,8 @@ url(r'^insensitive_recover/$', views.insensitive_recover, name='insensitive_recover'), ] + +if captcha_installed: + urlpatterns += [ + url(r'^captcha/', include('captcha.urls')), + ] From c1b9563dbf39e79853ddf79578fa7deccd9e8ed3 Mon Sep 17 00:00:00 2001 From: Kuiyu CHANG Date: Mon, 28 Mar 2016 17:33:27 +0800 Subject: [PATCH 05/10] added blank models.py to work with Django 1.5 or lower; Added COLON_SUFFIX for django 1.5 tests to pass --- password_reset/models.py | 0 password_reset/tests/tests.py | 11 ++++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 password_reset/models.py diff --git a/password_reset/models.py b/password_reset/models.py new file mode 100644 index 00000000..e69de29b diff --git a/password_reset/tests/tests.py b/password_reset/tests/tests.py index 51228c89..b27956d5 100644 --- a/password_reset/tests/tests.py +++ b/password_reset/tests/tests.py @@ -28,6 +28,11 @@ CustomUser = None ExtensionUser = None + +if django.VERSION < (1, 6): + COLON_SUFFIX = '' # Django 1.5 or lower do NOT auto add colon suffix +else: + COLON_SUFFIX = ':' # Django 1.6 or higher auto add colon suffix # Test manually via # ./manage.py test --settings password_reset.tests.settings password_reset.tests @@ -290,9 +295,9 @@ def test_email_recover(self): self.user = create_user() url = reverse('email_recover') response = self.client.get(url) - print "----------- guiyu: response=%s" % response self.assertNotContains(response, "Username or Email") - self.assertContains(response, "Email:") + + self.assertContains(response, "Email%s" % COLON_SUFFIX) response = self.client.post(url, {'username_or_email': 'foo'}) try: @@ -319,7 +324,7 @@ def test_username_recover(self): response = self.client.get(url) self.assertNotContains(response, "Username or Email") - self.assertContains(response, "Username:") + self.assertContains(response, "Username%s" % COLON_SUFFIX) response = self.client.post(url, {'username_or_email': 'bar@example.com'}) From 074a35db1a8627397053531734f26b331696e1ee Mon Sep 17 00:00:00 2001 From: Kuiyu CHANG Date: Mon, 28 Mar 2016 17:59:31 +0800 Subject: [PATCH 06/10] fixed some lint errors --- password_reset/forms.py | 14 +++++++++----- password_reset/tests/settings.py | 10 ---------- password_reset/tests/tests.py | 1 - password_reset/utils.py | 6 ++++-- password_reset/views.py | 5 ++--- 5 files changed, 15 insertions(+), 21 deletions(-) diff --git a/password_reset/forms.py b/password_reset/forms.py index 1eb9a5ec..5ff771d1 100644 --- a/password_reset/forms.py +++ b/password_reset/forms.py @@ -6,7 +6,7 @@ try: - from captcha.fields import CaptchaField # uses django-simple-captcha==0.5.1 + from captcha.fields import CaptchaField # uses django-simple-captcha==0.5.1 except ImportError: CaptchaField = None pass @@ -14,17 +14,19 @@ from .utils import get_user_model error_messages = { - 'not_found': _("Sorry, this user doesn't exist."), - 'password_mismatch':_("The two passwords didn't match."), + 'not_found': _("Sorry, this user doesn't exist."), + 'password_mismatch': _("The two passwords didn't match."), } + class PasswordRecoveryForm(forms.Form): username_or_email = forms.CharField() try: - if CaptchaField and settings.CAPTCHA_CHALLENGE_FUNCT: # defined + if CaptchaField and settings.CAPTCHA_CHALLENGE_FUNCT: # defined captcha = CaptchaField(label=_('Captcha')) # Optional Captcha except: pass + def __init__(self, *args, **kwargs): self.case_sensitive = kwargs.pop('case_sensitive', True) search_fields = kwargs.pop('search_fields', ('username', 'email')) @@ -92,7 +94,9 @@ def get_user_by_email(self, email): def get_user_by_both(self, username): key = '__%sexact' key = key % '' if self.case_sensitive else key % 'i' - f = lambda field: Q(**{field + key: username}) + #f = lambda field: Q(**{field + key: username}) + def f(field): # to satisfy lint in Travis auto build on Github + return Q(**{field + key: username}) filters = f('username') | f('email') User = get_user_model() try: diff --git a/password_reset/tests/settings.py b/password_reset/tests/settings.py index f9c72830..22c1f6db 100644 --- a/password_reset/tests/settings.py +++ b/password_reset/tests/settings.py @@ -16,13 +16,6 @@ 'password_reset.tests', ] -try: - INSTALLED_APPS += [ - #'captcha' # include captcha if available - ] -except: - pass - MIGRATION_MODULES = { 'auth': 'django.contrib.auth.tests.migrations', } @@ -35,6 +28,3 @@ ), }, }] - -#AUTH_USER_MODEL = None -DISABLE_CAPTCHA=True diff --git a/password_reset/tests/tests.py b/password_reset/tests/tests.py index b27956d5..f07550c4 100644 --- a/password_reset/tests/tests.py +++ b/password_reset/tests/tests.py @@ -13,7 +13,6 @@ from ..forms import PasswordRecoveryForm, PasswordResetForm, error_messages from ..utils import get_user_model -#import settings """ Commented out this part due to incompatibilities with Django 1.8.4 diff --git a/password_reset/utils.py b/password_reset/utils.py index 6200970f..9721f5fe 100644 --- a/password_reset/utils.py +++ b/password_reset/utils.py @@ -2,8 +2,10 @@ from django.contrib.auth import get_user_model except ImportError: from django.contrib.auth.models import User - get_user_model = lambda: User # noqa - + #get_user_model = lambda: User # noqa + def my_user(): # to satisfy lint in Travis auto build on Github + return User # noqa + get_user_model = my_user def get_username(user): username_field = getattr(user, 'USERNAME_FIELD', 'username') diff --git a/password_reset/views.py b/password_reset/views.py index 6cb35a17..18ec50eb 100644 --- a/password_reset/views.py +++ b/password_reset/views.py @@ -52,6 +52,7 @@ def get_context_data(self, **kwargs): return ctx recover_done = RecoverDone.as_view() + class RecoverFailed(SaltMixin, generic.TemplateView): template_name = 'password_reset/reset_sent_failed.html' @@ -67,7 +68,6 @@ def get_context_data(self, **kwargs): recover_failed = RecoverFailed.as_view() - class Recover(SaltMixin, generic.FormView): case_sensitive = True form_class = PasswordRecoveryForm @@ -85,7 +85,6 @@ def get_success_url(self): else: return reverse(self.failure_url_name, args=[self.mail_signature]) - def get_context_data(self, **kwargs): kwargs['url'] = self.request.get_full_path() return super(Recover, self).get_context_data(**kwargs) @@ -114,7 +113,7 @@ def send_notification(self): subject = loader.render_to_string(self.email_subject_template_name, context).strip() result = send_mail(subject, body, settings.DEFAULT_FROM_EMAIL, - [self.user.email], fail_silently=True) + [self.user.email], fail_silently=True) return result def form_valid(self, form): From 395f5a14e5a4f468a91a925df94be203db6a4dfc Mon Sep 17 00:00:00 2001 From: Kuiyu CHANG Date: Mon, 28 Mar 2016 18:19:00 +0800 Subject: [PATCH 07/10] restored custom user --- password_reset/forms.py | 7 +++++-- password_reset/tests/tests.py | 16 ++++++++-------- password_reset/utils.py | 6 ++++-- password_reset/views.py | 6 +++--- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/password_reset/forms.py b/password_reset/forms.py index 5ff771d1..4d7e5d7f 100644 --- a/password_reset/forms.py +++ b/password_reset/forms.py @@ -6,7 +6,8 @@ try: - from captcha.fields import CaptchaField # uses django-simple-captcha==0.5.1 + if 'captcha' in settings.INSTALLED_APPS: + from captcha.fields import CaptchaField # uses django-simple-captcha except ImportError: CaptchaField = None pass @@ -94,9 +95,11 @@ def get_user_by_email(self, email): def get_user_by_both(self, username): key = '__%sexact' key = key % '' if self.case_sensitive else key % 'i' - #f = lambda field: Q(**{field + key: username}) + # f = lambda field: Q(**{field + key: username}) + def f(field): # to satisfy lint in Travis auto build on Github return Q(**{field + key: username}) + filters = f('username') | f('email') User = get_user_model() try: diff --git a/password_reset/tests/tests.py b/password_reset/tests/tests.py index f07550c4..2d28b22f 100644 --- a/password_reset/tests/tests.py +++ b/password_reset/tests/tests.py @@ -15,30 +15,31 @@ from ..utils import get_user_model """ +CustomUser = None +ExtensionUser = None Commented out this part due to incompatibilities with Django 1.8.4 See http://stackoverflow.com/questions/27433228/django-1-7-django-db-utils-operationalerror-no-such-table-auth-customuser +""" if django.VERSION >= (1, 5): from django.contrib.auth.tests.custom_user import ( # noqa CustomUser, ExtensionUser) else: CustomUser = None # noqa ExtensionUser = None # noqa -""" -CustomUser = None -ExtensionUser = None - if django.VERSION < (1, 6): COLON_SUFFIX = '' # Django 1.5 or lower do NOT auto add colon suffix else: COLON_SUFFIX = ':' # Django 1.6 or higher auto add colon suffix + # Test manually via -# ./manage.py test --settings password_reset.tests.settings password_reset.tests +# ./manage.py test --settings password_reset.tests.settings +# password_test.tests + class CustomUserVariants(type): def __new__(cls, name, bases, dct): - #if django.VERSION >= (1, 5) and settings.AUTH_USER_MODEL: - if 1>2: + if django.VERSION >= (1, 5): for custom_user in ['auth.CustomUser', 'auth.ExtensionUser']: suffix = custom_user.lower().replace('.', '_') for key, fn in list(dct.items()): @@ -48,7 +49,6 @@ def __new__(cls, name, bases, dct): AUTH_USER_MODEL=custom_user)(fn) return super(CustomUserVariants, cls).__new__(cls, name, bases, dct) - def create_user(): email = 'bar@example.com' password = 'pass' diff --git a/password_reset/utils.py b/password_reset/utils.py index 9721f5fe..bd45d3b9 100644 --- a/password_reset/utils.py +++ b/password_reset/utils.py @@ -2,9 +2,11 @@ from django.contrib.auth import get_user_model except ImportError: from django.contrib.auth.models import User - #get_user_model = lambda: User # noqa + # get_user_model = lambda: User # noqa + def my_user(): # to satisfy lint in Travis auto build on Github - return User # noqa + return User # noqa + get_user_model = my_user def get_username(user): diff --git a/password_reset/views.py b/password_reset/views.py index 18ec50eb..85cfefa9 100644 --- a/password_reset/views.py +++ b/password_reset/views.py @@ -113,15 +113,15 @@ def send_notification(self): subject = loader.render_to_string(self.email_subject_template_name, context).strip() result = send_mail(subject, body, settings.DEFAULT_FROM_EMAIL, - [self.user.email], fail_silently=True) + [ self.user.email ], fail_silently=True) return result def form_valid(self, form): self.user = form.cleaned_data['user'] self.sent_success = self.send_notification() if ( - len(self.search_fields) == 1 and - self.search_fields[0] == 'username' + len(self.search_fields) == 1 and + self.search_fields[0] == 'username' ): # if we only search by username, don't disclose the user email # since it may now be public information. From bae7e50cf379a036ca5b13992a9fdf442d3697c3 Mon Sep 17 00:00:00 2001 From: Kuiyu CHANG Date: Mon, 28 Mar 2016 18:27:16 +0800 Subject: [PATCH 08/10] fixed lint errors --- password_reset/tests/tests.py | 7 +------ password_reset/utils.py | 1 + password_reset/views.py | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/password_reset/tests/tests.py b/password_reset/tests/tests.py index 2d28b22f..fef47201 100644 --- a/password_reset/tests/tests.py +++ b/password_reset/tests/tests.py @@ -14,12 +14,6 @@ from ..forms import PasswordRecoveryForm, PasswordResetForm, error_messages from ..utils import get_user_model -""" -CustomUser = None -ExtensionUser = None -Commented out this part due to incompatibilities with Django 1.8.4 -See http://stackoverflow.com/questions/27433228/django-1-7-django-db-utils-operationalerror-no-such-table-auth-customuser -""" if django.VERSION >= (1, 5): from django.contrib.auth.tests.custom_user import ( # noqa CustomUser, ExtensionUser) @@ -49,6 +43,7 @@ def __new__(cls, name, bases, dct): AUTH_USER_MODEL=custom_user)(fn) return super(CustomUserVariants, cls).__new__(cls, name, bases, dct) + def create_user(): email = 'bar@example.com' password = 'pass' diff --git a/password_reset/utils.py b/password_reset/utils.py index bd45d3b9..dc82fa82 100644 --- a/password_reset/utils.py +++ b/password_reset/utils.py @@ -9,6 +9,7 @@ def my_user(): # to satisfy lint in Travis auto build on Github get_user_model = my_user + def get_username(user): username_field = getattr(user, 'USERNAME_FIELD', 'username') return getattr(user, username_field) diff --git a/password_reset/views.py b/password_reset/views.py index 85cfefa9..e620822a 100644 --- a/password_reset/views.py +++ b/password_reset/views.py @@ -113,7 +113,7 @@ def send_notification(self): subject = loader.render_to_string(self.email_subject_template_name, context).strip() result = send_mail(subject, body, settings.DEFAULT_FROM_EMAIL, - [ self.user.email ], fail_silently=True) + [self.user.email], fail_silently=True) return result def form_valid(self, form): From 95e735771534673f00eea5963d62afdf0b1a84a0 Mon Sep 17 00:00:00 2001 From: Kuiyu CHANG Date: Mon, 28 Mar 2016 23:11:51 +0800 Subject: [PATCH 09/10] dummy changes to invoke lint, which was not run due to travis server issues --- password_reset/tests/tests.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/password_reset/tests/tests.py b/password_reset/tests/tests.py index fef47201..31f579a4 100644 --- a/password_reset/tests/tests.py +++ b/password_reset/tests/tests.py @@ -26,8 +26,7 @@ else: COLON_SUFFIX = ':' # Django 1.6 or higher auto add colon suffix -# Test manually via -# ./manage.py test --settings password_reset.tests.settings +# Test manually via ./manage.py test --settings password_reset.tests.settings # password_test.tests From fe8370210f4d52684aca39171b6700dba3c5bf58 Mon Sep 17 00:00:00 2001 From: Kuiyu CHANG Date: Tue, 29 Mar 2016 10:44:32 +0800 Subject: [PATCH 10/10] locale: removed old zh/, create link zh to zh-hans. --- password_reset/locale/zh | 1 + .../locale/zh/LC_MESSAGES/django.mo | Bin 2524 -> 0 bytes .../locale/zh/LC_MESSAGES/django.po | 122 ------------------ 3 files changed, 1 insertion(+), 122 deletions(-) create mode 120000 password_reset/locale/zh delete mode 100644 password_reset/locale/zh/LC_MESSAGES/django.mo delete mode 100644 password_reset/locale/zh/LC_MESSAGES/django.po diff --git a/password_reset/locale/zh b/password_reset/locale/zh new file mode 120000 index 00000000..80d1c227 --- /dev/null +++ b/password_reset/locale/zh @@ -0,0 +1 @@ +zh-hans \ No newline at end of file diff --git a/password_reset/locale/zh/LC_MESSAGES/django.mo b/password_reset/locale/zh/LC_MESSAGES/django.mo deleted file mode 100644 index f1f11c350efc46072a3314f8a06d3f5ebd8cce99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2524 zcmaKs{cjXS7{^CJg^Hs1mKdXxCd4+}9#_N!j?!?n2Q>EO(iaSxsN1`_yOq72V`qwe?DO)S zXXno?>n8}V*Kogq`w!f2;Xd~S9=J9;8Wl!uo)ZyKLURNH-Wx&guDvw z244Up;ESLRO24ACei3{L<6EG#TLh1Szk@O|(*@Lg~n zk~$3T2KOQNaqtU_e|uVeA9;olyb=b6Koi^v=D>~MU!e5+2;2<*1Il_gBj}r8Ehxt! zP}bQ4N;@6=1Uv@54*m{G`$ym_;3hbi{%i4&V;>j<_k(rd=b+6023V4uK+2*f&w}!j zI-$(s1-He$Dh-P{J%<54FV+Y7igD!n^SEWMQa@Rnyiitgf8@K|#~R$S4id5`OX-G5 z`*lGDvmEMh+9({GTZyKvb;Y%M(YU=dL$}uH30^NKo_^XZ79& zE5VR^M^z=O2DC29t+-*Q>Q_%AFo~2(r#6f7Bkw{tQWOSHanJKVr4J6#TvKkP5xD}I}BGZu_9KBV5y_3rFj*bxWAK!|fnF z(A(BVJ3{SY+8AyRwYKdGwX}4FyStlUY9%r#K48b<(Uo*xa!T%L6C# zb7x?gpTF<(uKnbV=G4F&8!t@FEf0-)m+vm+77GhGYciWOpt~O4Y%&t9a-(e zg~G(NcY8`jMM^8#Ro?0f*KI*E=`l<|dT~Qg&2%^M)@k z4V{qH5WunZ3 jvUAG$D#et>-tf44_FG@!{9Oc8!WFK}y9*Nt, YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-01-23 10:01+0800\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: forms.py:26 -msgid "Username" -msgstr "用户名" - -#: forms.py:27 -msgid "Email" -msgstr "邮箱" - -#: forms.py:28 -msgid "Username or Email" -msgstr "用户名或者邮箱" - -#: forms.py:48 forms.py:58 forms.py:70 -msgid "Sorry, this user doesn't exist." -msgstr "抱歉,用户名不存在." - -#: forms.py:72 -msgid "Unable to find user." -msgstr "找不到指定用户" - -#: forms.py:78 -msgid "New password" -msgstr "新密码" - -#: forms.py:82 -msgid "New password (confirm)" -msgstr "新密码(确认)" - -#: forms.py:94 -msgid "The two passwords didn't match." -msgstr "两次输入的密码不一致" - -#: templates/password_reset/recovery_done.html:3 -msgid "New password set" -msgstr "设置新密码" - -#: templates/password_reset/recovery_done.html:6 -msgid "" -"Your password has successfully been reset. You can use it right now on the " -"login page." -msgstr "您的密码已经重设成功,现在可以登录了." - -#: templates/password_reset/recovery_email.txt:1 -#, python-format -msgid "Dear %(username)s," -msgstr "您好 %(username)s," - -#: templates/password_reset/recovery_email.txt:3 -#, python-format -msgid "" -"You -- or someone pretending to be you -- has requested a password reset on " -"%(domain)s." -msgstr "您或者其它的人在 %(domain)s 申请了密码重置." - -#: templates/password_reset/recovery_email.txt:5 -msgid "You can set your new password by following this link:" -msgstr "您可以通过以下链接重置密码:" - -#: templates/password_reset/recovery_email.txt:9 -msgid "" -"If you don't want to reset your password, simply ignore this email and it " -"will stay unchanged." -msgstr "如果您不想重设密码,可以忽略此邮箱." - -#: templates/password_reset/recovery_email_subject.txt:1 -#, python-format -msgid "Password recovery on %(domain)s" -msgstr "在 %(domain)s 上重设密码" - -#: templates/password_reset/recovery_form.html:5 -msgid "Password recovery" -msgstr "重新设置密码" - -#: templates/password_reset/recovery_form.html:11 -msgid "Recover my password" -msgstr "重设密码" - -#: templates/password_reset/reset.html:5 -#, python-format -msgid "" -"Sorry, this password reset link is invalid. You can still request a new one." -msgstr "抱歉,链接已经失效,您可以在 请求一个新链接." - -#: templates/password_reset/reset.html:7 -#, python-format -msgid "Hi, %(username)s. Please choose your new password." -msgstr "您好,%(username)s. 请输入您的新密码." - -#: templates/password_reset/reset.html:11 -msgid "Set new password" -msgstr "设置新密码" - -#: templates/password_reset/reset_sent.html:4 -msgid "Password recovery sent" -msgstr "发送重设密码" - -#: templates/password_reset/reset_sent.html:7 -#, python-format -msgid "" -"An email was sent to %(email)s %(ago)s ago. Use the link in " -"it to set a new password." -msgstr "已经在%(ago)s以前向您的邮箱 %(email)s发送了邮件,根据邮件提示重新设置您的新密码."