From 617e60be3c7d2e0f17639f3487a721d4efdc02c0 Mon Sep 17 00:00:00 2001 From: hernani Date: Thu, 24 Jun 2010 00:57:31 +0000 Subject: [PATCH] Closes OSQA 175 and OSQA 318. Added a bunch of options to configure the email validation process, and what a user is not allowed to do without validating the email. git-svn-id: http://svn.osqa.net/svnroot/osqa/trunk@443 0cfe37f9-358a-4d5e-be75-b63607b5c754 --- forum/actions/user.py | 2 +- forum/badges/base.py | 2 +- forum/models/user.py | 22 +++- forum/settings/users.py | 18 +++ forum/skins/default/templates/ask.html | 22 ++-- .../templates/auth/mail_validation.html | 30 +++++ ...ail_validation.html => welcome_email.html} | 0 forum/skins/default/templates/question.html | 10 +- forum/skins/default/templates/users/info.html | 12 +- forum/urls.py | 6 +- forum/views/auth.py | 84 +++++++------ forum/views/users.py | 12 +- forum/views/writers.py | 111 +++++++++++++----- settings_local.py.dist | 2 - 14 files changed, 226 insertions(+), 107 deletions(-) create mode 100644 forum/skins/default/templates/auth/mail_validation.html rename forum/skins/default/templates/auth/{email_validation.html => welcome_email.html} (100%) diff --git a/forum/actions/user.py b/forum/actions/user.py index e8f1035..8f225d2 100644 --- a/forum/actions/user.py +++ b/forum/actions/user.py @@ -13,7 +13,7 @@ class UserJoinsAction(ActionProxy): def process_action(self): hash = ValidationHash.objects.create_new(self.user, 'email', [self.user.email]) - send_template_email([self.user], "auth/email_validation.html", {'validation_code': hash}) + send_template_email([self.user], "auth/welcome_email.html", {'validation_code': hash}) def describe(self, viewer=None): return _("%(user)s %(have_has)s joined the %(app_name)s Q&A community") % { diff --git a/forum/badges/base.py b/forum/badges/base.py index 1900119..79fcb52 100644 --- a/forum/badges/base.py +++ b/forum/badges/base.py @@ -69,7 +69,7 @@ class AbstractBadge(object): trigger = isinstance(action, Action) and action or None if not awarded: - AwardAction(user=user, node=node, ip=action.ip).save(data=dict(badge=cls.ondb, trigger=trigger)) + AwardAction(user=user, node=node).save(data=dict(badge=cls.ondb, trigger=trigger)) except MultipleObjectsReturned: if node: logging.error('Found multiple %s badges awarded for user %s (%s)' % (self.name, user.username, user.id)) diff --git a/forum/models/user.py b/forum/models/user.py index 89bea28..f5eb9a6 100644 --- a/forum/models/user.py +++ b/forum/models/user.py @@ -90,6 +90,16 @@ def true_if_is_super_or_staff(fn): return decorated +def false_if_validation_required_to(item): + def decorator(fn): + def decorated(self, *args, **kwargs): + if item in settings.REQUIRE_EMAIL_VALIDATION_TO and not self.email_isvalid: + return False + else: + return fn(self, *args, **kwargs) + return decorated + return decorator + class User(BaseModel, DjangoUser): is_approved = models.BooleanField(default=False) email_isvalid = models.BooleanField(default=False) @@ -116,7 +126,7 @@ class User(BaseModel, DjangoUser): @property def is_siteowner(self): - #temporary thing, for now lets just assume that the site owner will always be the first user of the application + #todo: temporary thing, for now lets just assume that the site owner will always be the first user of the application return self.id == 1 @property @@ -191,6 +201,7 @@ class User(BaseModel, DjangoUser): def can_vote_down(self): return self.reputation >= int(settings.REP_TO_VOTE_DOWN) + @false_if_validation_required_to('flag') def can_flag_offensive(self, post=None): if post is not None and post.author == self: return False @@ -203,9 +214,10 @@ class User(BaseModel, DjangoUser): return self.reputation >= int(settings.REP_TO_VIEW_FLAGS) @true_if_is_super_or_staff + @false_if_validation_required_to('comment') def can_comment(self, post): return self == post.author or self.reputation >= int(settings.REP_TO_COMMENT - ) or (post.__class__.__name__ == "Answer" and self == post.question.author) + ) or (post.__class__.__name__ == "Answer" and self == post.question.author) @true_if_is_super_or_staff def can_like_comment(self, comment): @@ -271,6 +283,12 @@ class User(BaseModel, DjangoUser): def can_upload_files(self): return self.reputation >= int(settings.REP_TO_UPLOAD) + def email_valid_and_can_ask(self): + return 'ask' not in settings.REQUIRE_EMAIL_VALIDATION_TO or self.email_isvalid + + def email_valid_and_can_answer(self): + return 'answer' not in settings.REQUIRE_EMAIL_VALIDATION_TO or self.email_isvalid + def check_password(self, old_passwd): self.__dict__.update(self.__class__.objects.filter(id=self.id).values('password')[0]) return DjangoUser.check_password(self, old_passwd) diff --git a/forum/settings/users.py b/forum/settings/users.py index 01377d7..07f47b6 100644 --- a/forum/settings/users.py +++ b/forum/settings/users.py @@ -1,4 +1,5 @@ from forms import CommaStringListWidget +from django.forms import CheckboxSelectMultiple from base import Setting, SettingSet from django.utils.translation import ugettext as _ @@ -24,3 +25,20 @@ EMAIL_UNIQUE = Setting('EMAIL_UNIQUE', True, USERS_SET, dict( label = _("Force unique email"), help_text = _("Should each user have an unique email."))) +REQUIRE_EMAIL_VALIDATION_TO = Setting('REQUIRE_EMAIL_VALIDATION_TO', [], USERS_SET, dict( +label = _("Require email validation to..."), +help_text = _("Which actions in this site, users without a valid email will be prevented from doing."), +widget=CheckboxSelectMultiple, +choices=(("ask", _("ask questions")), ("answer", _("provide answers")), ("comment", _("make comments")), ("flag", _("report posts"))), +required=False, +)) + +HOLD_PENDING_POSTS_MINUTES = Setting('HOLD_PENDING_POSTS_MINUTES', 120, USERS_SET, dict( +label=_("Hold pending posts for X minutes"), +help_text=_("How much time in minutes a post should be kept in session until the user logs in or validates the email.") +)) + +WARN_PENDING_POSTS_MINUTES = Setting('WARN_PENDING_POSTS_MINUTES', 15, USERS_SET, dict( +label=_("Warn about pending posts afer X minutes"), +help_text=_("How much time in minutes a user that just logged in or validated his email should be warned about a pending post instead of publishing it automatically.") +)) \ No newline at end of file diff --git a/forum/skins/default/templates/ask.html b/forum/skins/default/templates/ask.html index 4eb806b..2f2b92e 100644 --- a/forum/skins/default/templates/ask.html +++ b/forum/skins/default/templates/ask.html @@ -71,18 +71,20 @@
{% if not request.user.is_authenticated %}
-

{% trans "login to post question info" %}

+ {% trans "You are welcome to start submitting your question anonymously." %} +

{% blocktrans %} + After submiting your question, you will be redirected to the login/signup page. + Your question will be saved in the current session and will be published after you login with your existing account, + or signup for a new account{% endblocktrans %}{% if "ask" in settings.REQUIRE_EMAIL_VALIDATION_TO %} + {% trans "and validate your email." %}{% else %}.{% endif %}

{% else %} - {% ifequal settings.EMAIL_VALIDATION 'on' %} - {% if not request.user.email_isvalid %} -
- {% blocktrans with request.user.email as email %}must have valid {{email}} to post, - see {{email_validation_faq_url}} - {% endblocktrans %} -
- {% endif %} - {% endifequal %} + {% if not request.user.email_valid_and_can_ask %} +
+ {% blocktrans %}Remember, your question will not be published until you validate your email.{% endblocktrans %} + {% trans "Send me a validation link." %} +
+ {% endif %} {% endif %}

diff --git a/forum/skins/default/templates/auth/mail_validation.html b/forum/skins/default/templates/auth/mail_validation.html new file mode 100644 index 0000000..d73a428 --- /dev/null +++ b/forum/skins/default/templates/auth/mail_validation.html @@ -0,0 +1,30 @@ +{% load i18n extra_tags email_tags %} + +{% declare %} + prefix = settings.EMAIL_SUBJECT_PREFIX + app_name = settings.APP_SHORT_NAME + + exclude_finetune = True +{% enddeclare %} + +{% email %} + {% subject %}{% blocktrans %}{{ prefix }} Your email validation link {{ app_name }}{% endblocktrans %}{% endsubject %} + + {% htmlcontent notifications/base.html %} +

{% trans "Please use the following link to help us verify your email address:" %}

+ + {% trans "Validate my email address" %} + +

{% trans "If the above link is not clickable, copy and paste this url into your web browser's address bar:" %}

+ +

{% fullurl auth_validate_email user=recipient.id,code=validation_code %}

+ {% endhtmlcontent %} + +{% textcontent notifications/base_text.html %} +{% trans "Copy and paste this url into your web browser's address bar to help us verify your email address:" %} + +{% fullurl auth_validate_email user=recipient.id,code=validation_code %} +{% endtextcontent %} + +{% endemail %} + diff --git a/forum/skins/default/templates/auth/email_validation.html b/forum/skins/default/templates/auth/welcome_email.html similarity index 100% rename from forum/skins/default/templates/auth/email_validation.html rename to forum/skins/default/templates/auth/welcome_email.html diff --git a/forum/skins/default/templates/question.html b/forum/skins/default/templates/question.html index 81711e0..694ab71 100644 --- a/forum/skins/default/templates/question.html +++ b/forum/skins/default/templates/question.html @@ -179,14 +179,18 @@ {% endspaceless %}
{% if not request.user.is_authenticated %} -
{% trans "you can answer anonymously and then login" %}
+
{% trans "You can answer anonymously and then login." %}
{% else %}

{% ifequal request.user question.author %} - {% trans "answer your own question only to give an answer" %} + {% trans "Answer your own question only to give an answer." %} {% else %} - {% trans "please only give an answer, no discussions" %} + {% trans "Please only give an answer, no discussions." %} {% endifequal %} + {% if not request.user.email_valid_and_can_answer %} + {% blocktrans %}Remember, your answer will not be published until you validate your email.{% endblocktrans %} + {% trans "Send me a validation link." %} + {% endif %}

{% endif %} diff --git a/forum/skins/default/templates/users/info.html b/forum/skins/default/templates/users/info.html index b533f00..8ffc7fa 100644 --- a/forum/skins/default/templates/users/info.html +++ b/forum/skins/default/templates/users/info.html @@ -75,10 +75,18 @@ {% endif %} {% endif %} - {% if request.user.is_superuser %} + {% if can_view_private %} {% trans "email" %} - {{ view_user.email }} + + {{ view_user.email }} + {% if not view_user.email_isvalid %} + ({% trans "not validated" %}) + {% ifequal request.user view_user %} + {% trans "Send me a validation link." %} + {% endifequal %} + {% endif %} + {% endif %}