
The code base had many references to User.username and other specific to LocalUser attributes as that was the way it use to exist. This updates those to query on the generic User model but filtering by attributes on the LocalUser.
198 lines
6.7 KiB
Python
198 lines
6.7 KiB
Python
# 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 LocalUser, 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 = LocalUser.query.filter_by(
|
|
username=register_form.username.data).count()
|
|
users_with_email = LocalUser.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 = LocalUser()
|
|
user.username = form.username.data
|
|
user.email = form.email.data
|
|
user.save()
|
|
return user
|