mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-21 05:45:37 +08:00
initial commit of email activation feature
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
If you want to disable registration for users that are using disposable email address
|
||||
rename this file to disposable_email_blacklist.conf and fill it with the disposable domains
|
||||
that you want to have blacklisted. Each on its own line without the '@' character as shown below.
|
||||
Users using emails from these domains will get an error during the registration.
|
||||
|
||||
mailinator.com
|
||||
sogetthis.com
|
||||
spamgourmet.com
|
||||
trashmail.net
|
||||
@@ -132,6 +132,14 @@ class Configuration( object ):
|
||||
self.admin_users = kwargs.get( "admin_users", "" )
|
||||
self.mailing_join_addr = kwargs.get('mailing_join_addr',"galaxy-announce-join@bx.psu.edu")
|
||||
self.error_email_to = kwargs.get( 'error_email_to', None )
|
||||
self.admin_email = kwargs.get( 'admin_email', None )
|
||||
self.user_activation_on = kwargs.get( 'user_activation_on', None )
|
||||
self.activation_grace_period = kwargs.get( 'activation_grace_period', None )
|
||||
self.inactivity_box_visible = kwargs.get( 'inactivity_box_visible', None )
|
||||
self.inactivity_box_content = kwargs.get( 'inactivity_box_content', None )
|
||||
self.inactivity_box_class = kwargs.get( 'inactivity_box_class', None )
|
||||
# Get the disposable email domains blacklist file
|
||||
self.blacklist_file = resolve_path( kwargs.get( 'blacklist_file', None ), self.root )
|
||||
self.smtp_server = kwargs.get( 'smtp_server', None )
|
||||
self.smtp_username = kwargs.get( 'smtp_username', None )
|
||||
self.smtp_password = kwargs.get( 'smtp_password', None )
|
||||
|
||||
@@ -84,12 +84,25 @@ class JobHandlerQueue( object ):
|
||||
Checks all jobs that are in the 'new', 'queued' or 'running' state in
|
||||
the database and requeues or cleans up as necessary. Only run as the
|
||||
job handler starts.
|
||||
In case the activation is enforced it will filter out the jobs of inactive users.
|
||||
"""
|
||||
for job in self.sa_session.query( model.Job ).enable_eagerloads( False ) \
|
||||
jobs_at_startup = []
|
||||
if self.app.config.user_activation_on:
|
||||
jobs_at_startup = self.sa_session.query( model.Job ).enable_eagerloads( False ) \
|
||||
.outerjoin( model.User ) \
|
||||
.filter( ( ( model.Job.state == model.Job.states.NEW ) \
|
||||
| ( model.Job.state == model.Job.states.RUNNING ) \
|
||||
| ( model.Job.state == model.Job.states.QUEUED ) ) \
|
||||
& ( model.Job.handler == self.app.config.server_name ) ):
|
||||
& ( model.Job.handler == self.app.config.server_name ) \
|
||||
& or_( ( model.Job.user_id == None ),( model.User.active == True ) ) ).all()
|
||||
else:
|
||||
jobs_at_startup = self.sa_session.query( model.Job ).enable_eagerloads( False ) \
|
||||
.filter( ( ( model.Job.state == model.Job.states.NEW ) \
|
||||
| ( model.Job.state == model.Job.states.RUNNING ) \
|
||||
| ( model.Job.state == model.Job.states.QUEUED ) ) \
|
||||
& ( model.Job.handler == self.app.config.server_name ) ).all()
|
||||
|
||||
for job in jobs_at_startup:
|
||||
if job.tool_id not in self.app.toolbox.tools_by_id:
|
||||
log.warning( "(%s) Tool '%s' removed from tool config, unable to recover job" % ( job.id, job.tool_id ) )
|
||||
JobWrapper( job, self ).fail( 'This tool was disabled before the job completed. Please contact your Galaxy administrator.' )
|
||||
@@ -146,8 +159,9 @@ class JobHandlerQueue( object ):
|
||||
over all new and waiting jobs to check the state of the jobs each
|
||||
depends on. If the job has dependencies that have not finished, it
|
||||
it goes to the waiting queue. If the job has dependencies with errors,
|
||||
it is marked as having errors and removed from the queue. Otherwise,
|
||||
the job is dispatched.
|
||||
it is marked as having errors and removed from the queue. If the job
|
||||
belongs to an inactive user it is ignored.
|
||||
Otherwise, the job is dispatched.
|
||||
"""
|
||||
# Pull all new jobs from the queue at once
|
||||
jobs_to_check = []
|
||||
@@ -173,7 +187,17 @@ class JobHandlerQueue( object ):
|
||||
(model.LibraryDatasetDatasetAssociation.deleted == True),
|
||||
(model.Dataset.state != model.Dataset.states.OK),
|
||||
(model.Dataset.deleted == True)))).subquery()
|
||||
jobs_to_check = self.sa_session.query(model.Job).enable_eagerloads(False) \
|
||||
if self.app.config.user_activation_on:
|
||||
jobs_to_check = self.sa_session.query(model.Job).enable_eagerloads(False) \
|
||||
.outerjoin( model.User ) \
|
||||
.filter(and_((model.Job.state == model.Job.states.NEW),
|
||||
or_((model.Job.user_id == None),(model.User.active == True)),
|
||||
(model.Job.handler == self.app.config.server_name),
|
||||
~model.Job.table.c.id.in_(hda_not_ready),
|
||||
~model.Job.table.c.id.in_(ldda_not_ready))) \
|
||||
.order_by(model.Job.id).all()
|
||||
else:
|
||||
jobs_to_check = self.sa_session.query(model.Job).enable_eagerloads(False) \
|
||||
.filter(and_((model.Job.state == model.Job.states.NEW),
|
||||
(model.Job.handler == self.app.config.server_name),
|
||||
~model.Job.table.c.id.in_(hda_not_ready),
|
||||
|
||||
@@ -78,6 +78,8 @@ class User( object, Dictifiable ):
|
||||
self.external = False
|
||||
self.deleted = False
|
||||
self.purged = False
|
||||
self.active = False
|
||||
self.activation_token = None
|
||||
self.username = None
|
||||
# Relationships
|
||||
self.histories = []
|
||||
|
||||
@@ -52,7 +52,9 @@ model.User.table = Table( "galaxy_user", metadata,
|
||||
Column( "form_values_id", Integer, ForeignKey( "form_values.id" ), index=True ),
|
||||
Column( "deleted", Boolean, index=True, default=False ),
|
||||
Column( "purged", Boolean, index=True, default=False ),
|
||||
Column( "disk_usage", Numeric( 15, 0 ), index=True ) )
|
||||
Column( "disk_usage", Numeric( 15, 0 ), index=True ) ,
|
||||
Column( "active", Boolean, index=True, default=True, nullable=False ),
|
||||
Column( "activation_token", TrimmedString( 64 ), nullable=True, index=True ) )
|
||||
|
||||
model.UserAddress.table = Table( "user_address", metadata,
|
||||
Column( "id", Integer, primary_key=True),
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
'''
|
||||
Created on Sep 10, 2013
|
||||
|
||||
@author: marten
|
||||
|
||||
Adds 'active' and 'activation_token' columns to the galaxy_user table.
|
||||
'''
|
||||
|
||||
from sqlalchemy import *
|
||||
from sqlalchemy.orm import *
|
||||
from migrate import *
|
||||
from migrate.changeset import *
|
||||
from galaxy.model.custom_types import TrimmedString
|
||||
|
||||
import logging
|
||||
log = logging.getLogger( __name__ )
|
||||
|
||||
user_active_column = Column( "active", Boolean, default=True, nullable=True )
|
||||
user_activation_token_column = Column( "activation_token", TrimmedString( 64 ), nullable=True )
|
||||
|
||||
|
||||
def display_migration_details():
|
||||
print ""
|
||||
print "This migration script adds active and activation_token columns to the user table"
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
print __doc__
|
||||
metadata = MetaData()
|
||||
metadata.bind = migrate_engine
|
||||
metadata.reflect()
|
||||
|
||||
# Add the active and activation_token columns to the user table in one try because the depend on each other.
|
||||
try:
|
||||
user_table = Table( "galaxy_user", metadata, autoload=True )
|
||||
user_active_column.create( table = user_table , populate_default = True)
|
||||
user_activation_token_column.create( table = user_table )
|
||||
assert user_active_column is user_table.c.active
|
||||
assert user_activation_token_column is user_table.c.activation_token
|
||||
except Exception, e:
|
||||
print str(e)
|
||||
log.error( "Adding columns 'active' and 'activation_token' to galaxy_user table failed: %s" % str( e ) )
|
||||
return
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
metadata = MetaData()
|
||||
metadata.bind = migrate_engine
|
||||
metadata.reflect()
|
||||
|
||||
# Drop the user table's active and activation_token columns in one try because the depend on each other.
|
||||
try:
|
||||
user_table = Table( "galaxy_user", metadata, autoload=True )
|
||||
user_active = user_table.c.active
|
||||
user_activation_token = user_table.c.activation_token
|
||||
user_active.drop()
|
||||
user_activation_token.drop()
|
||||
except Exception, e:
|
||||
log.debug( "Dropping 'active' and 'activation_token' columns from galaxy_user table failed: %s" % ( str( e ) ) )
|
||||
@@ -2,18 +2,31 @@ import re
|
||||
|
||||
VALID_PUBLICNAME_RE = re.compile( "^[a-z0-9\-]+$" )
|
||||
VALID_PUBLICNAME_SUB = re.compile( "[^a-z0-9\-]" )
|
||||
# Basic regular expression to check email validity.
|
||||
VALID_EMAIL_RE = re.compile( "[^@]+@[^@]+\.[^@]+" )
|
||||
FILL_CHAR = '-'
|
||||
|
||||
def validate_email( trans, email, user=None, check_dup=True ):
|
||||
"""
|
||||
Validates the email format, also checks whether the domain is blacklisted in the disposable domains configuration.
|
||||
"""
|
||||
message = ''
|
||||
# Load the blacklist file location from the configuration file.
|
||||
blacklist_file = trans.app.config.blacklist_file
|
||||
if blacklist_file is not None:
|
||||
email_blacklist = [ line.rstrip() for line in file( blacklist_file ).readlines() ]
|
||||
if user and user.email == email:
|
||||
return message
|
||||
if len( email ) == 0 or "@" not in email or "." not in email:
|
||||
message = "Enter a real email address"
|
||||
if not( VALID_EMAIL_RE.match( email ) ):
|
||||
message = "Please enter your real email address."
|
||||
elif len( email ) > 255:
|
||||
message = "Email address exceeds maximum allowable length"
|
||||
message = "Email address exceeds maximum allowable length."
|
||||
elif check_dup and trans.sa_session.query( trans.app.model.User ).filter_by( email=email ).first():
|
||||
message = "User with that email already exists"
|
||||
message = "User with that email already exists."
|
||||
# If the blacklist is not empty filter out the disposable domains.
|
||||
elif email_blacklist is not None:
|
||||
if email.split('@')[1] in email_blacklist:
|
||||
message = "Please enter your permanent email address."
|
||||
return message
|
||||
|
||||
def validate_publicname( trans, publicname, user=None ):
|
||||
|
||||
@@ -51,6 +51,8 @@ def app_factory( global_conf, **kwargs ):
|
||||
webapp.add_ui_controllers( 'galaxy.webapps.galaxy.controllers', app )
|
||||
# Force /history to go to /root/history -- needed since the tests assume this
|
||||
webapp.add_route( '/history', controller='root', action='history' )
|
||||
# Force /activate to go to the controller
|
||||
webapp.add_route( '/activate', controller='user', action='activate' )
|
||||
# These two routes handle our simple needs at the moment
|
||||
webapp.add_route( '/async/:tool_id/:data_id/:data_secret', controller='async', action='index', tool_id=None, data_id=None, data_secret=None )
|
||||
webapp.add_route( '/:controller/:action', action='index' )
|
||||
|
||||
@@ -8,6 +8,7 @@ import os
|
||||
import socket
|
||||
import string
|
||||
import random
|
||||
import urllib
|
||||
from galaxy import web
|
||||
from galaxy import util, model
|
||||
from galaxy.model.orm import and_
|
||||
@@ -17,6 +18,8 @@ from galaxy.web import url_for
|
||||
from galaxy.web.base.controller import BaseUIController, UsesFormDefinitionsMixin
|
||||
from galaxy.web.form_builder import CheckboxField, build_select_field
|
||||
from galaxy.web.framework.helpers import time_ago, grids
|
||||
from datetime import datetime, timedelta
|
||||
from galaxy.util import hash_util
|
||||
|
||||
log = logging.getLogger( __name__ )
|
||||
|
||||
@@ -147,7 +150,14 @@ class User( BaseUIController, UsesFormDefinitionsMixin ):
|
||||
if trans.user:
|
||||
if user_openid.user and user_openid.user.id != trans.user.id:
|
||||
message = "The OpenID <strong>%s</strong> is already associated with another Galaxy account, <strong>%s</strong>. Please disassociate it from that account before attempting to associate it with a new account." % ( display_identifier, user_openid.user.email )
|
||||
status = "error"
|
||||
if not trans.user.active and trans.app.config.user_activation_on: # Account activation is ON and the user is INACTIVE.
|
||||
if ( trans.app.config.activation_grace_period != 0 ): # grace period is ON
|
||||
if self.is_outside_grace_period( trans, trans.user.create_time ): # User is outside the grace period. Login is disabled and he will have the activation email resent.
|
||||
message = self.resend_verification_email( trans, trans.user.email )
|
||||
else: # User is within the grace period, let him log in.
|
||||
pass
|
||||
else: # Grace period is off. Login is disabled and user will have the activation email resent.
|
||||
message = self.resend_verification_email( trans, trans.user.email )
|
||||
elif not user_openid.user or user_openid.user == trans.user:
|
||||
if openid_provider_obj.id:
|
||||
user_openid.provider = openid_provider_obj.id
|
||||
@@ -282,7 +292,7 @@ class User( BaseUIController, UsesFormDefinitionsMixin ):
|
||||
subscribe_checked = CheckboxField.is_checked( subscribe )
|
||||
error = ''
|
||||
if not trans.app.config.allow_user_creation and not trans.user_is_admin():
|
||||
error = 'User registration is disabled. Please contact your Galaxy administrator for an account.'
|
||||
error = 'User registration is disabled. Please contact your local Galaxy administrator for an account.'
|
||||
else:
|
||||
# Check email and password validity
|
||||
error = self.__validate( trans, params, email, password, confirm, username )
|
||||
@@ -465,9 +475,13 @@ class User( BaseUIController, UsesFormDefinitionsMixin ):
|
||||
openid_providers=trans.app.openid_providers,
|
||||
form_input_auto_focus=True,
|
||||
active_view="user" )
|
||||
|
||||
def __validate_login( self, trans, **kwd ):
|
||||
"""
|
||||
Function validates numerous cases that might happen during the login time.
|
||||
"""
|
||||
message = kwd.get( 'message', '' )
|
||||
status = kwd.get( 'status', 'done' )
|
||||
status = kwd.get( 'status', 'error' )
|
||||
email = kwd.get( 'email', '' )
|
||||
password = kwd.get( 'password', '' )
|
||||
redirect = kwd.get( 'redirect', trans.request.referer ).strip()
|
||||
@@ -475,27 +489,69 @@ class User( BaseUIController, UsesFormDefinitionsMixin ):
|
||||
user = trans.sa_session.query( trans.app.model.User ).filter( trans.app.model.User.table.c.email==email ).first()
|
||||
if not user:
|
||||
message = "No such user (please note that login is case sensitive)"
|
||||
status = 'error'
|
||||
elif user.deleted:
|
||||
message = "This account has been marked deleted, contact your Galaxy administrator to restore the account."
|
||||
status = 'error'
|
||||
message = "This account has been marked deleted, contact your local Galaxy administrator to restore the account."
|
||||
if trans.app.config.admin_email is not None:
|
||||
message += 'Contact: %s' % trans.app.config.admin_email
|
||||
elif user.external:
|
||||
message = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it."
|
||||
status = 'error'
|
||||
if trans.app.config.admin_email is not None:
|
||||
message += 'Contact: %s' % trans.app.config.admin_email
|
||||
elif not user.check_password( password ):
|
||||
message = "Invalid password"
|
||||
status = 'error'
|
||||
else:
|
||||
trans.handle_user_login( user )
|
||||
if trans.webapp.name == 'galaxy':
|
||||
trans.log_event( "User logged in" )
|
||||
message = 'You are now logged in as %s.<br>You can <a target="_top" href="%s">go back to the page you were visiting</a> or <a target="_top" href="%s">go to the home page</a>.' % \
|
||||
( user.email, redirect, url_for( '/' ) )
|
||||
if trans.app.config.require_login:
|
||||
message += ' <a target="_top" href="%s">Click here</a> to continue to the home page.' % web.url_for( controller="root", action="welcome" )
|
||||
success = True
|
||||
elif trans.app.config.user_activation_on and not user.active: # activation is ON and the user is INACTIVE
|
||||
if ( trans.app.config.activation_grace_period != 0 ): # grace period is ON
|
||||
if self.is_outside_grace_period( trans, user.create_time ): # User is outside the grace period. Login is disabled and he will have the activation email resent.
|
||||
message = self.resend_verification_email( trans, email )
|
||||
else: # User is within the grace period, let him log in.
|
||||
message, success, status = self.proceed_login( trans, user, redirect )
|
||||
else: # Grace period is off. Login is disabled and user will have the activation email resent.
|
||||
message = self.resend_verification_email( trans, email )
|
||||
else: # activation is OFF
|
||||
message, success, status = self.proceed_login( trans, user, redirect )
|
||||
return ( message, status, user, success )
|
||||
|
||||
def proceed_login ( self, trans, user, redirect ):
|
||||
"""
|
||||
Function processes user login. It is called in case all the login requirements are valid.
|
||||
"""
|
||||
trans.handle_user_login( user )
|
||||
if trans.webapp.name == 'galaxy':
|
||||
trans.log_event( "User logged in" )
|
||||
message = 'You are now logged in as %s.<br>You can <a target="_top" href="%s">go back to the page you were visiting</a> or <a target="_top" href="%s">go to the home page</a>.' % \
|
||||
( user.email, redirect, url_for( '/' ) )
|
||||
if trans.app.config.require_login:
|
||||
message += ' <a target="_top" href="%s">Click here</a> to continue to the home page.' % web.url_for( controller="root", action="welcome" )
|
||||
success = True
|
||||
status = 'done'
|
||||
return message, success, status
|
||||
|
||||
def resend_verification_email( self, trans, email ):
|
||||
"""
|
||||
Function resends the verification email in case user wants to log in with an inactive account.
|
||||
"""
|
||||
is_activation_sent = self.send_verification_email( trans, email )
|
||||
if is_activation_sent:
|
||||
message = 'This account has not been activated yet. The activation link has been sent again. Please check your email address %s.<br>' % email
|
||||
else:
|
||||
message = 'This account has not been activated yet but we are unable to send the activation link. Please contact your local Galaxy administrator.'
|
||||
if trans.app.config.admin_email is not None:
|
||||
message += 'Contact: %s' % trans.app.config.admin_email
|
||||
return message
|
||||
|
||||
def is_outside_grace_period ( self, trans, create_time ):
|
||||
"""
|
||||
Function checks whether the user is outside the config-defined grace period for inactive accounts.
|
||||
"""
|
||||
# Activation is forced and the user is not active yet. Check the grace period.
|
||||
activation_grace_period = trans.app.config.activation_grace_period
|
||||
# Default value is 3 hours.
|
||||
if activation_grace_period == None:
|
||||
activation_grace_period = 3
|
||||
delta = timedelta( hours = int( activation_grace_period ) )
|
||||
time_difference = datetime.utcnow() - create_time
|
||||
return ( time_difference > delta or activation_grace_period == 0 )
|
||||
|
||||
@web.expose
|
||||
def logout( self, trans, logout_all=False ):
|
||||
if trans.webapp.name == 'galaxy':
|
||||
@@ -533,7 +589,9 @@ class User( BaseUIController, UsesFormDefinitionsMixin ):
|
||||
redirect = kwd.get( 'redirect', trans.request.referer ).strip()
|
||||
is_admin = cntrller == 'admin' and trans.user_is_admin
|
||||
if not trans.app.config.allow_user_creation and not trans.user_is_admin():
|
||||
message = 'User registration is disabled. Please contact your Galaxy administrator for an account.'
|
||||
message = 'User registration is disabled. Please contact your local Galaxy administrator for an account.'
|
||||
if trans.app.config.admin_email is not None:
|
||||
message += 'Contact: %s' % trans.app.config.admin_email
|
||||
status = 'error'
|
||||
else:
|
||||
if not refresh_frames:
|
||||
@@ -606,6 +664,8 @@ class User( BaseUIController, UsesFormDefinitionsMixin ):
|
||||
user = trans.app.model.User( email=email )
|
||||
user.set_password_cleartext( password )
|
||||
user.username = username
|
||||
if trans.app.config.user_activation_on: # Do not set the active flag in case activation is OFF.
|
||||
user.active = False
|
||||
trans.sa_session.add( user )
|
||||
trans.sa_session.flush()
|
||||
trans.app.security_agent.create_private_user_role( user )
|
||||
@@ -633,7 +693,7 @@ class User( BaseUIController, UsesFormDefinitionsMixin ):
|
||||
if subscribe_checked:
|
||||
# subscribe user to email list
|
||||
if trans.app.config.smtp_server is None:
|
||||
error = "Now logged in as " + user.email + ". However, subscribing to the mailing list has failed because mail is not configured for this Galaxy instance."
|
||||
error = "Now logged in as " + user.email + ". However, subscribing to the mailing list has failed because mail is not configured for this Galaxy instance. <br>Please contact your local Galaxy administrator."
|
||||
else:
|
||||
body = 'Join Mailing list.\n'
|
||||
to = trans.app.config.mailing_join_addr
|
||||
@@ -659,9 +719,86 @@ class User( BaseUIController, UsesFormDefinitionsMixin ):
|
||||
status = 'error'
|
||||
success = False
|
||||
else:
|
||||
message = 'Now logged in as %s.<br><a target="_top" href="%s">Return to the home page.</a>' % ( user.email, url_for( '/' ) )
|
||||
success = True
|
||||
is_activation_sent = self.send_verification_email( trans, email )
|
||||
if is_activation_sent:
|
||||
message = 'Now logged in as %s.<br>Verification email has been sent to your email address. Please verify it by clicking the activation link in the email.<br><a target="_top" href="%s">Return to the home page.</a>' % ( user.email, url_for( '/' ) )
|
||||
success = True
|
||||
else:
|
||||
message = 'Unable to send activation email, please contact your local Galaxy administrator.'
|
||||
if trans.app.config.admin_email is not None:
|
||||
message += 'Contact: %s' % trans.app.config.admin_email
|
||||
success = False
|
||||
return ( message, status, user, success )
|
||||
|
||||
def send_verification_email( self, trans, email ):
|
||||
"""
|
||||
Send the verification email containing the activation link to the user's email.
|
||||
"""
|
||||
activation_link = self.prepare_activation_link( trans, email )
|
||||
|
||||
body = ("Hi %s,\n\n"
|
||||
"Please click the activation link below in order to activate your account.\n\n"
|
||||
"Activation link: %s \n\n"
|
||||
"Your Galaxy Team" % ( email, activation_link ))
|
||||
to = email
|
||||
frm = trans.app.config.admin_email
|
||||
subject = 'How to activate your Galaxy account'
|
||||
try:
|
||||
util.send_mail( frm, to, subject, body, trans.app.config )
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
def prepare_activation_link( self, trans, email ):
|
||||
"""
|
||||
Prepares the account activation link for the user.
|
||||
"""
|
||||
activation_token = self.get_activation_token( trans, email )
|
||||
host = trans.request.host.split( ':' )[ 0 ]
|
||||
if host == 'localhost':
|
||||
host = socket.getfqdn()
|
||||
activation_link = str( trans.request.host ) + url_for( controller='user', action='activate' ) + "?activation_token=" + str( activation_token ) + "&email=" + urllib.quote( email )
|
||||
return activation_link
|
||||
|
||||
def get_activation_token ( self, trans, email ):
|
||||
"""
|
||||
Checks for the activation token. Creates new activation token and stores it in the database if none found.
|
||||
"""
|
||||
user = trans.sa_session.query( trans.app.model.User ).filter( trans.app.model.User.table.c.email == email ).first()
|
||||
activation_token = user.activation_token
|
||||
if activation_token == None:
|
||||
activation_token = hash_util.new_secure_hash( str( random.getrandbits( 256 ) ) )
|
||||
user.activation_token = activation_token
|
||||
trans.sa_session.add( user )
|
||||
trans.sa_session.flush()
|
||||
return activation_token
|
||||
|
||||
@web.expose
|
||||
def activate( self, trans, **kwd ):
|
||||
"""
|
||||
Function checks whether token fits the user and then activates the user's account.
|
||||
"""
|
||||
params = util.Params( kwd, sanitize=False )
|
||||
email = urllib.unquote( params.get( 'email', None ) )
|
||||
activation_token = params.get( 'activation_token', None )
|
||||
|
||||
if email == None or activation_token == None:
|
||||
# We don't have the email or activation_token, show error.
|
||||
return trans.show_error_message( "You are using wrong activation link. Try to log-in and we will send you a new activation email.<br><a href='%s'>Go to login page.</a>" ) % web.url_for( controller="root", action="index" )
|
||||
else:
|
||||
# Find the user
|
||||
user = trans.sa_session.query( trans.app.model.User ).filter( trans.app.model.User.table.c.email==email ).first()
|
||||
if user.activation_token == activation_token:
|
||||
user.activation_token = None
|
||||
user.active = True
|
||||
trans.sa_session.add(user)
|
||||
trans.sa_session.flush()
|
||||
return trans.show_ok_message( "Your account has been successfully activated!<br><a href='%s'>Go to login page.</a>" ) % web.url_for( controller='root', action='index' )
|
||||
else:
|
||||
# Tokens don't match. Activation is denied.
|
||||
return trans.show_error_message( "You are using wrong activation link. Try to log in and we will send you a new activation email.<br><a href='%s'>Go to login page.</a>" ) % web.url_for( controller='root', action='index' )
|
||||
return
|
||||
|
||||
def __get_user_type_form_definition( self, trans, user=None, **kwd ):
|
||||
params = util.Params( kwd )
|
||||
if user and user.values:
|
||||
@@ -885,7 +1022,7 @@ class User( BaseUIController, UsesFormDefinitionsMixin ):
|
||||
@web.expose
|
||||
def reset_password( self, trans, email=None, **kwd ):
|
||||
if trans.app.config.smtp_server is None:
|
||||
return trans.show_error_message( "Mail is not configured for this Galaxy instance. Please contact an administrator." )
|
||||
return trans.show_error_message( "Mail is not configured for this Galaxy instance. Please contact your local Galaxy administrator." )
|
||||
message = util.restore_text( kwd.get( 'message', '' ) )
|
||||
status = 'done'
|
||||
if kwd.get( 'reset_password_button', False ):
|
||||
@@ -1042,7 +1179,7 @@ class User( BaseUIController, UsesFormDefinitionsMixin ):
|
||||
phone = util.restore_text( params.get( 'phone', '' ) )
|
||||
ok = True
|
||||
if not trans.app.config.allow_user_creation and not is_admin:
|
||||
return trans.show_error_message( 'User registration is disabled. Please contact your Galaxy administrator for an account.' )
|
||||
return trans.show_error_message( 'User registration is disabled. Please contact your local Galaxy administrator for an account.' )
|
||||
if params.get( 'new_address_button', False ):
|
||||
if not short_desc:
|
||||
ok = False
|
||||
|
||||
@@ -1140,6 +1140,7 @@ ul.icons{list-style-type:none;text-indent:-0.75em}ul.icons li [class^="fa-icon-"
|
||||
body{background:#fff;color:#000;margin:10px}body.full-content{overflow:hidden;margin:0;padding:0;width:100%;height:100%}
|
||||
#background{position:absolute;background:#fff;z-index:-1;top:0;left:0;margin:0;padding:0;width:100%;height:100%}
|
||||
#messagebox{position:absolute;top:34px;left:0;width:100%;height:30px !important;overflow:hidden;border-bottom:solid #999 1px;font-size:90%}
|
||||
#inactivebox{position:absolute;top:34px;left:0;width:100%;height:30px !important;overflow:hidden;border-bottom:solid #999 1px;font-size:90%}
|
||||
#left,#left-border,#center,#right-border,#right{position:absolute;top:34px;bottom:0px;overflow:hidden;background:#fff}
|
||||
#left{left:0px;width:250px;z-index:200;border-right:solid #999 1px}
|
||||
#left-border{left:250px}
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
self.has_left_panel = hasattr( self, 'left_panel' )
|
||||
self.has_right_panel = hasattr( self, 'right_panel' )
|
||||
self.message_box_visible = app.config.message_box_visible
|
||||
self.show_inactivity_warning = False
|
||||
if trans.user:
|
||||
self.show_inactivity_warning = ( ( trans.user.active is False ) and ( app.config.user_activation_on is True) and ( app.config.inactivity_box_content is not None ) )
|
||||
self.overlay_visible=False
|
||||
self.active_view=None
|
||||
self.body_class=""
|
||||
@@ -26,12 +29,20 @@
|
||||
right: 0 !important;
|
||||
%endif
|
||||
}
|
||||
%if self.message_box_visible:
|
||||
## This is some dirty hack happening
|
||||
%if self.message_box_visible or self.show_inactivity_warning:
|
||||
#left, #left-border, #center, #right-border, #right
|
||||
{
|
||||
top: 64px;
|
||||
}
|
||||
%endif
|
||||
%if self.message_box_visible and self.show_inactivity_warning:
|
||||
#left, #left-border, #center, #right-border, #right
|
||||
{
|
||||
top: 94px;
|
||||
}
|
||||
#inactivebox{top:64px;}
|
||||
%endif
|
||||
</style>
|
||||
</%def>
|
||||
|
||||
@@ -300,11 +311,16 @@
|
||||
<div id="masthead" class="navbar navbar-fixed-top navbar-inverse">
|
||||
${self.masthead()}
|
||||
</div>
|
||||
<div id="messagebox" class="panel-${app.config.message_box_class}-message">
|
||||
%if self.message_box_visible and app.config.message_box_content:
|
||||
<div id="messagebox" class="panel-${app.config.message_box_class}-message">
|
||||
${app.config.message_box_content}
|
||||
%endif
|
||||
</div>
|
||||
%endif
|
||||
%if self.show_inactivity_warning:
|
||||
<div id="inactivebox" class="panel-warning-message">
|
||||
${app.config.inactivity_box_content}
|
||||
</div>
|
||||
%endif
|
||||
${self.overlay(visible=self.overlay_visible)}
|
||||
%if self.has_left_panel:
|
||||
<div id="left">
|
||||
|
||||
@@ -242,8 +242,8 @@ paste.app_factory = galaxy.web.buildapp:app_factory
|
||||
|
||||
# Galaxy sends mail for various things: Subscribing users to the mailing list
|
||||
# if they request it, emailing password resets, notification from the Galaxy
|
||||
# Sample Tracking system, and reporting dataset errors. To do this, it needs
|
||||
# to send mail through an SMTP server, which you may define here (host:port).
|
||||
# Sample Tracking system, reporting dataset errors, and sending activation emails.
|
||||
# To do this, it needs to send mail through an SMTP server, which you may define here (host:port).
|
||||
# Galaxy will automatically try STARTTLS but will continue upon failure.
|
||||
#smtp_server = None
|
||||
|
||||
@@ -261,6 +261,33 @@ paste.app_factory = galaxy.web.buildapp:app_factory
|
||||
# will be sent to this address. Error reports are disabled if no address is set.
|
||||
#error_email_to = None
|
||||
|
||||
# Administrator's email is shown to user in case of Galaxy misconfiguration or a generic error.
|
||||
# It is also used as a sender for the account activation mail.
|
||||
#admin_email = None
|
||||
|
||||
# E-mail domains blacklist is used for filtering out users that are using disposable email address
|
||||
# during the registration. If their address domain matches any domain in the BL they are refused the registration.
|
||||
#blacklist_file = config/disposable_email_blacklist.conf
|
||||
|
||||
|
||||
# -- Account activation
|
||||
|
||||
# This is user account activation feature global flag. If set to "False" the rest of the Account
|
||||
# activation configuration is ignored and user activation is disabled (a.k.a. accounts are active since registration).
|
||||
# Note the activation is also not working in case the smtp server is not defined.
|
||||
#user_activation_on = False
|
||||
|
||||
# Activation grace period. Activation is not forced (login is not disabled) until
|
||||
# grace period has passed. Users under grace period can't run jobs (see inactivity_box_content).
|
||||
# In hours. Default is 3. Enter 0 to disable grace period.
|
||||
# Users with OpenID logins have grace period forever.
|
||||
#activation_grace_period = 0
|
||||
|
||||
# Used for warning box for inactive accounts (unable to run jobs).
|
||||
# In use only if activation_grace_period is set.
|
||||
#inactivity_box_content = Your account has not been activated yet. Please activate your account by verifying your email address. For now you can access everything at Galaxy but your jobs won't run.
|
||||
|
||||
|
||||
# -- Display sites
|
||||
|
||||
# Galaxy can display data at various external browsers. These options specify
|
||||
|
||||
Reference in New Issue
Block a user