Send a confirmation email when an account is created. Links don't do anything yet.
This commit is contained in:
parent
87dc3b6344
commit
99341f7d53
8 changed files with 73 additions and 7 deletions
10
app.py
10
app.py
|
@ -3,15 +3,19 @@ import logging
|
|||
from flask import Flask
|
||||
from flask.ext.principal import Principal
|
||||
from flask.ext.login import LoginManager
|
||||
|
||||
from flask.ext.mail import Mail
|
||||
from config import ProductionConfig
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config.from_object(ProductionConfig())
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
Principal(app, use_sessions=True)
|
||||
|
||||
app.secret_key = '1cb18882-6d12-440d-a4cc-b7430fb5f884'
|
||||
|
||||
login_manager = LoginManager()
|
||||
login_manager.init_app(app)
|
||||
login_manager.login_view = 'signin'
|
||||
|
||||
mail = Mail()
|
||||
mail.init_app(app)
|
||||
|
|
15
config.py
Normal file
15
config.py
Normal 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
|
|
@ -66,6 +66,14 @@ class AccessToken(BaseModel):
|
|||
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):
|
||||
# This class is intentionally denormalized. Even though images are supposed
|
||||
# to be globally unique we can't treat them as such for permissions and
|
||||
|
|
|
@ -28,9 +28,14 @@ def create_user(username, password, email):
|
|||
try:
|
||||
new_user = User.create(username=username, password_hash=pw_hash,
|
||||
email=email)
|
||||
return new_user
|
||||
except Exception as ex:
|
||||
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):
|
||||
|
|
|
@ -11,6 +11,7 @@ from app import app
|
|||
from auth.auth import (process_auth, get_authenticated_user,
|
||||
get_validated_token)
|
||||
from util.names import parse_namespace_repository, parse_repository_name
|
||||
from util.email import send_confirmation_email
|
||||
from auth.permissions import (ModifyRepositoryPermission,
|
||||
ReadRepositoryPermission, UserPermission)
|
||||
|
||||
|
@ -46,8 +47,10 @@ def generate_headers(f):
|
|||
@app.route('/v1/users/', methods=['POST'])
|
||||
def create_user():
|
||||
user_data = request.get_json()
|
||||
model.create_user(user_data['username'], user_data['password'],
|
||||
user_data['email'])
|
||||
new_user = model.create_user(user_data['username'], user_data['password'],
|
||||
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)
|
||||
|
||||
|
||||
|
|
|
@ -56,6 +56,16 @@ def signin():
|
|||
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'])
|
||||
def render_signin_page():
|
||||
return send_file('templates/signin.html')
|
||||
|
|
|
@ -2,4 +2,5 @@ peewee
|
|||
flask
|
||||
py-bcrypt
|
||||
Flask-Principal
|
||||
Flask-Login
|
||||
Flask-Login
|
||||
Flask-Mail
|
20
util/email.py
Normal file
20
util/email.py
Normal 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)
|
Reference in a new issue