123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- # GNU MediaGoblin -- federated, autonomous media hosting
- # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
- #
- # This program is free software: you can redistribute it and/or modify
- # it under the terms of the GNU Affero General Public License as published by
- # the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU Affero General Public License for more details.
- #
- # You should have received a copy of the GNU Affero General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
- import logging
- import six
- import wtforms
- from sqlalchemy import or_
- from mediagoblin import mg_globals
- from mediagoblin.tools.crypto import get_timed_signer_url
- from mediagoblin.db.models import User, Privilege
- from mediagoblin.tools.mail import (normalize_email, send_email,
- email_debug_message)
- from mediagoblin.tools.template import render_template
- from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
- from mediagoblin.tools.pluginapi import hook_handle
- from mediagoblin import auth
- _log = logging.getLogger(__name__)
- def normalize_user_or_email_field(allow_email=True, allow_user=True):
- """
- Check if we were passed a field that matches a username and/or email
- pattern.
- This is useful for fields that can take either a username or email
- address. Use the parameters if you want to only allow a username for
- instance"""
- message = _(u'Invalid User name or email address.')
- nomail_msg = _(u"This field does not take email addresses.")
- nouser_msg = _(u"This field requires an email address.")
- def _normalize_field(form, field):
- email = u'@' in field.data
- if email: # normalize email address casing
- if not allow_email:
- raise wtforms.ValidationError(nomail_msg)
- wtforms.validators.Email()(form, field)
- field.data = normalize_email(field.data)
- else: # lower case user names
- if not allow_user:
- raise wtforms.ValidationError(nouser_msg)
- wtforms.validators.Length(min=3, max=30)(form, field)
- wtforms.validators.Regexp(r'^\w+$')(form, field)
- field.data = field.data.lower()
- if field.data is None: # should not happen, but be cautious anyway
- raise wtforms.ValidationError(message)
- return _normalize_field
- EMAIL_VERIFICATION_TEMPLATE = (
- u"{uri}?"
- u"token={verification_key}")
- def send_verification_email(user, request, email=None,
- rendered_email=None):
- """
- Send the verification email to users to activate their accounts.
- Args:
- - user: a user object
- - request: the request
- """
- if not email:
- email = user.email
- if not rendered_email:
- verification_key = get_timed_signer_url('mail_verification_token') \
- .dumps(user.id)
- rendered_email = render_template(
- request, 'mediagoblin/auth/verification_email.txt',
- {'username': user.username,
- 'verification_url': EMAIL_VERIFICATION_TEMPLATE.format(
- uri=request.urlgen('mediagoblin.auth.verify_email',
- qualified=True),
- verification_key=verification_key)})
- # TODO: There is no error handling in place
- send_email(
- mg_globals.app_config['email_sender_address'],
- [email],
- # TODO
- # Due to the distributed nature of GNU MediaGoblin, we should
- # find a way to send some additional information about the
- # specific GNU MediaGoblin instance in the subject line. For
- # example "GNU MediaGoblin @ Wandborg - [...]".
- 'GNU MediaGoblin - Verify your email!',
- rendered_email)
- def basic_extra_validation(register_form, *args):
- users_with_username = User.query.filter_by(
- username=register_form.username.data).count()
- users_with_email = User.query.filter_by(
- email=register_form.email.data).count()
- extra_validation_passes = True
- if users_with_username:
- register_form.username.errors.append(
- _(u'Sorry, a user with that name already exists.'))
- extra_validation_passes = False
- if users_with_email:
- register_form.email.errors.append(
- _(u'Sorry, a user with that email address already exists.'))
- extra_validation_passes = False
- return extra_validation_passes
- def register_user(request, register_form):
- """ Handle user registration """
- extra_validation_passes = auth.extra_validation(register_form)
- if extra_validation_passes:
- # Create the user
- user = auth.create_user(register_form)
- # give the user the default privileges
- user.all_privileges += get_default_privileges(user)
- user.save()
- # log the user in
- request.session['user_id'] = six.text_type(user.id)
- request.session.save()
- # send verification email
- email_debug_message(request)
- send_verification_email(user, request)
- return user
- return None
- def get_default_privileges(user):
- instance_privilege_scheme = mg_globals.app_config['user_privilege_scheme']
- default_privileges = [Privilege.query.filter(
- Privilege.privilege_name==privilege_name).first()
- for privilege_name in instance_privilege_scheme.split(',')]
- default_privileges = [privilege for privilege in default_privileges if not privilege == None]
- return default_privileges
- def check_login_simple(username, password):
- user = auth.get_user(username=username)
- if not user:
- _log.info("User %r not found", username)
- hook_handle("auth_fake_login_attempt")
- return None
- if not auth.check_password(password, user.pw_hash):
- _log.warn("Wrong password for %r", username)
- return None
- _log.info("Logging %r in", username)
- return user
- def check_auth_enabled():
- if not hook_handle('authentication'):
- _log.warning('No authentication is enabled')
- return False
- else:
- return True
- def no_auth_logout(request):
- """
- Log out the user if no authentication is enabled, but don't delete
- the messages
- """
- if not request.app.auth and 'user_id' in request.session:
- del request.session['user_id']
- request.session.save()
- def create_basic_user(form):
- user = User()
- user.username = form.username.data
- user.email = form.email.data
- user.save()
- return user
|