Send a confirmation email when an account is created. Links don't do anything yet.

This commit is contained in:
yackob03 2013-09-27 19:29:01 -04:00
parent 87dc3b6344
commit 99341f7d53
8 changed files with 73 additions and 7 deletions

10
app.py
View file

@ -3,15 +3,19 @@ import logging
from flask import Flask from flask import Flask
from flask.ext.principal import Principal from flask.ext.principal import Principal
from flask.ext.login import LoginManager from flask.ext.login import LoginManager
from flask.ext.mail import Mail
from config import ProductionConfig
app = Flask(__name__) app = Flask(__name__)
app.config.from_object(ProductionConfig())
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
Principal(app, use_sessions=True) Principal(app, use_sessions=True)
app.secret_key = '1cb18882-6d12-440d-a4cc-b7430fb5f884'
login_manager = LoginManager() login_manager = LoginManager()
login_manager.init_app(app) login_manager.init_app(app)
login_manager.login_view = 'signin' login_manager.login_view = 'signin'
mail = Mail()
mail.init_app(app)

15
config.py Normal file
View file

@ -0,0 +1,15 @@
class FlaskConfig(object):
SECRET_KEY = '1cb18882-6d12-440d-a4cc-b7430fb5f884'
class MailConfig(object):
MAIL_SERVER = 'email-smtp.us-east-1.amazonaws.com'
MAIL_USE_TLS = True
MAIL_PORT = 587
MAIL_USERNAME = 'AKIAIXV5SDGCPVMU3N4Q'
MAIL_PASSWORD = 'AhmX/vWE91uQ2RtcEKTkfNrzZehEjPNXOXeOXgQNfLao'
DEFAULT_MAIL_SENDER = 'support@fluxmonkey.io'
MAIL_FAIL_SILENTLY = False
TESTING = False
class ProductionConfig(FlaskConfig, MailConfig):
pass

View file

@ -66,6 +66,14 @@ class AccessToken(BaseModel):
created = DateTimeField(default=datetime.now) created = DateTimeField(default=datetime.now)
class EmailConfirmation(BaseModel):
code = CharField(default=random_string_generator())
user = ForeignKeyField(User)
pw_reset = BooleanField(default=False)
email_confirm = BooleanField(default=False)
created = DateTimeField(default=datetime.now)
class Image(BaseModel): class Image(BaseModel):
# This class is intentionally denormalized. Even though images are supposed # This class is intentionally denormalized. Even though images are supposed
# to be globally unique we can't treat them as such for permissions and # to be globally unique we can't treat them as such for permissions and

View file

@ -28,9 +28,14 @@ def create_user(username, password, email):
try: try:
new_user = User.create(username=username, password_hash=pw_hash, new_user = User.create(username=username, password_hash=pw_hash,
email=email) email=email)
return new_user
except Exception as ex: except Exception as ex:
raise DataModelException(ex.message) raise DataModelException(ex.message)
return new_user
def create_confirm_email_code(user):
code = EmailConfirmation(user=user, email_confirm=True)
return code
def get_user(username): def get_user(username):

View file

@ -11,6 +11,7 @@ from app import app
from auth.auth import (process_auth, get_authenticated_user, from auth.auth import (process_auth, get_authenticated_user,
get_validated_token) get_validated_token)
from util.names import parse_namespace_repository, parse_repository_name from util.names import parse_namespace_repository, parse_repository_name
from util.email import send_confirmation_email
from auth.permissions import (ModifyRepositoryPermission, from auth.permissions import (ModifyRepositoryPermission,
ReadRepositoryPermission, UserPermission) ReadRepositoryPermission, UserPermission)
@ -46,8 +47,10 @@ def generate_headers(f):
@app.route('/v1/users/', methods=['POST']) @app.route('/v1/users/', methods=['POST'])
def create_user(): def create_user():
user_data = request.get_json() user_data = request.get_json()
model.create_user(user_data['username'], user_data['password'], new_user = model.create_user(user_data['username'], user_data['password'],
user_data['email']) user_data['email'])
code = model.create_confirm_email_code(new_user)
send_confirmation_email(new_user.username, new_user.email, code.code)
return make_response('Created', 201) return make_response('Created', 201)

View file

@ -56,6 +56,16 @@ def signin():
abort(403) abort(403)
@app.route('/confirm', methods=['GET'])
def confirm_email():
pass
@app.route('/reset', methods=['GET'])
def password_reset():
pass
@app.route('/signin', methods=['GET']) @app.route('/signin', methods=['GET'])
def render_signin_page(): def render_signin_page():
return send_file('templates/signin.html') return send_file('templates/signin.html')

View file

@ -3,3 +3,4 @@ flask
py-bcrypt py-bcrypt
Flask-Principal Flask-Principal
Flask-Login Flask-Login
Flask-Mail

20
util/email.py Normal file
View file

@ -0,0 +1,20 @@
from flask.ext.mail import Message
from app import mail, app
CONFIRM_MESSAGE = """
This email address was recently used to register the username '%s'
at <a href="http://quay.io">Quay.io</a>.<br>
<br>
To confirm this email address, please click the following link:<br>
<a href="http://quay.io/confirm?token=%s">http://quay.io/confirm?token=%s</a>
"""
def send_confirmation_email(username, email, token):
msg = Message('Welcome to Quay! Please confirm your email.',
sender='support@fluxmonkey.io', # Why do I need this?
recipients=[email])
msg.html = CONFIRM_MESSAGE % (username, token, token)
mail.send(msg)