Cleaning up

Separated out commands into it's own file, so more can be added if needed.
Pulled email templates into app template folder for easy access.
Added Argon2 settings to .... settings
This commit is contained in:
Aaron Kimbrell
2019-04-20 18:44:49 -05:00
parent 7283a86753
commit 22ba2a7e0a
26 changed files with 264 additions and 96 deletions

View File

@@ -10,11 +10,7 @@ from flask_wtf.csrf import CSRFProtect
from app.models import User, Role, UsersRoles
from flask_user import user_registered
import click
from flask.cli import with_appcontext
import datetime
from flask_user import current_app
from app.commands import init_db
# Instantiate Flask extensions
@@ -120,7 +116,8 @@ def init_email_error_handler(app):
Initialize a logger to send emails on error-level messages.
Unhandled exceptions will now send an email message to app.config.ADMINS.
"""
if app.debug: return # Do not send error emails while developing
if app.debug:
return # Do not send error emails while developing
# Retrieve email settings from app.config
host = app.config['MAIL_SERVER']
@@ -150,82 +147,3 @@ def init_email_error_handler(app):
app.logger.addHandler(mail_handler)
# Log errors using: app.logger.error('Some error message')
# TODO: separate out into a commands file
@click.command("init_db")
@with_appcontext
def init_db():
""" Initialize the database."""
print('Initializing Database.')
print('Dropping all tables.')
db.drop_all()
print('Creating all tables.')
db.create_all()
create_users()
print('Database has been initialized.')
def create_users():
""" Create users """
# Create all tables
db.create_all()
# Adding roles
print('Creating Roles.')
admin_role = find_or_create_role('admin', u'Admin') # 1
user_role = find_or_create_role('user', u'User') # 2
reviewer = find_or_create_role('reviewer', u'Reviewer') # 3
viewer = find_or_create_role('viewer', u'Viewer') # 4
helper = find_or_create_role('helper', u'Helper') # 5
# Add users
print('Creating Admin User.')
admin_user = find_or_create_user(u'Admin', u'Admin', u'Admin', u'admin@library.msstate.edu', 'Password1', u'CSE', u'net001', u'000-000-000', 1970, 1, 1, u'16623257668', u'US', u'Mississippi', u'Mississippi State', u'39762', u'395 Hardy Rd', None, admin_role)
# Save to DB
db.session.commit()
def find_or_create_role(name, label):
""" Find existing role or create new role """
role = Role.query.filter(Role.name == name).first()
if not role:
role = Role(name=name, label=label)
db.session.add(role)
return role
def find_or_create_user(first_name, middle_name, last_name, email, password, department, net_id, msu_id, b_year, b_month, b_day, prim_phone, country=u'US', administrative_area=u'Mississippi', locality=u'Mississippi State', postal_code=u'39762', thoroughfare=u'395 Hardy Rd', premise=None, role=None):
""" Find existing user or create new user """
user = User.query.filter(User.email == email).first()
if not user:
b_time = datetime.datetime(b_year, b_month, b_day)
user = User(email=email,
first_name=first_name,
middle_name=middle_name,
last_name=last_name,
department=department,
net_id=net_id,
msu_id=msu_id,
birth_date=b_time.strftime('%B %d, %Y'),
prim_phone=prim_phone,
country=country,
administrative_area=administrative_area,
locality=locality,
postal_code=postal_code,
thoroughfare=thoroughfare,
premise=premise,
password=current_app.user_manager.password_manager.hash_password(password),
active=True,
email_confirmed_at=datetime.datetime.utcnow())
if role:
user.roles.append(role)
db.session.add(user)
return user

81
app/commands.py Normal file
View File

@@ -0,0 +1,81 @@
import click
from flask.cli import with_appcontext
import datetime
from flask_user import current_app
from app import db
from app.models import Role, User
@click.command("init_db")
@with_appcontext
def init_db():
""" Initialize the database."""
print('Initializing Database.')
print('Dropping all tables.')
db.drop_all()
print('Creating all tables.')
db.create_all()
create_users()
print('Database has been initialized.')
def create_users():
""" Create users """
# Create all tables
db.create_all()
# Adding roles
print('Creating Roles.')
admin_role = find_or_create_role('admin', u'Admin') # 1
user_role = find_or_create_role('user', u'User') # 2
reviewer = find_or_create_role('reviewer', u'Reviewer') # 3
viewer = find_or_create_role('viewer', u'Viewer') # 4
helper = find_or_create_role('helper', u'Helper') # 5
# Add users
print('Creating Admin User.')
admin_user = find_or_create_user(u'Admin', u'Admin', u'Admin', u'admin@library.msstate.edu', 'Password1', u'CSE', u'net001', u'000-000-000', 1970, 1, 1, u'16623257668', u'US', u'Mississippi', u'Mississippi State', u'39762', u'395 Hardy Rd', None, admin_role)
# Save to DB
db.session.commit()
def find_or_create_role(name, label):
""" Find existing role or create new role """
role = Role.query.filter(Role.name == name).first()
if not role:
role = Role(name=name, label=label)
db.session.add(role)
return role
def find_or_create_user(first_name, middle_name, last_name, email, password, department, net_id, msu_id, b_year, b_month, b_day, prim_phone, country=u'US', administrative_area=u'Mississippi', locality=u'Mississippi State', postal_code=u'39762', thoroughfare=u'395 Hardy Rd', premise=None, role=None):
""" Find existing user or create new user """
user = User.query.filter(User.email == email).first()
if not user:
b_time = datetime.datetime(b_year, b_month, b_day)
user = User(email=email,
first_name=first_name,
middle_name=middle_name,
last_name=last_name,
department=department,
net_id=net_id,
msu_id=msu_id,
birth_date=b_time.strftime('%B %d, %Y'),
prim_phone=prim_phone,
country=country,
administrative_area=administrative_area,
locality=locality,
postal_code=postal_code,
thoroughfare=thoroughfare,
premise=premise,
password=current_app.user_manager.password_manager.hash_password(password),
active=True,
email_confirmed_at=datetime.datetime.utcnow())
if role:
user.roles.append(role)
db.session.add(user)
return user

View File

@@ -1,4 +1,3 @@
import os
# *****************************
@@ -10,9 +9,10 @@ DEBUG = True
# Folders for uploading and supporting documents
# THESE FOLDER MUST EXIST ON THE FILE SYSTEM
SIGNATURE_FOLDER = '/path/to/instance/signatures'
SUBMISSION_FOLDER = '/path/to/instance/submissions'
DOCUMENTS_FOLDER = '/path/to/instance/documents'
SIGNATURE_FOLDER = '/data/signatures'
SUBMISSION_FOLDER = '/data/submissions'
DOCUMENTS_FOLDER = '/data/documents'
# DO NOT use Unsecure Secrets in production environments
# Generate a safe one with:
# python -c "import os; print repr(os.urandom(24));"
@@ -20,7 +20,7 @@ SECRET_KEY = 'This is an UNSECURE Secret. CHANGE THIS for production environment
# SQLAlchemy settings
SQLALCHEMY_DATABASE_URI = 'postgresql://user:password@host:port/database'
SQLALCHEMY_TRACK_MODIFICATIONS = False # Avoids a SQLAlchemy Warning
SQLALCHEMY_TRACK_MODIFICATIONS = False # Avoids a SQLAlchemy Warning
# Flask-Mail settings
# For smtp.gmail.com to work, you MUST set "Allow less secure apps" to ON in Google Accounts.
@@ -33,7 +33,7 @@ MAIL_USERNAME = 'yourname@gmail.com'
MAIL_PASSWORD = 'password'
# Sendgrid settings
SENDGRID_API_KEY='place-your-sendgrid-api-key-here'
SENDGRID_API_KEY = 'place-your-sendgrid-api-key-here'
# Flask-User settings
USER_APP_NAME = 'Flask-User starter app'
@@ -42,4 +42,4 @@ USER_EMAIL_SENDER_EMAIL = 'yourname@gmail.com'
ADMINS = [
'"Admin One" <admin1@gmail.com>',
]
]

View File

@@ -1,5 +1,4 @@
from flask_marshmallow.sqla import ModelSchema
from app import ma
from .models import User, Notification, Submission, Revision, Review

View File

@@ -1,6 +1,4 @@
# Settings common to all environments (development|staging|production)
# Place environment specific settings in env_settings.py
# An example file (env_settings_example.py) can be used as a starting point
# Application settings
APP_NAME = "MSState Library ETD System"
@@ -22,8 +20,16 @@ USER_ENABLE_EMAIL = True # Register with Email
USER_ENABLE_REGISTRATION = True # Allow new users to register
USER_REQUIRE_RETYPE_PASSWORD = True # Prompt for `retype password` in:
USER_ENABLE_USERNAME = False # Register and Login with username
USER_PASSLIB_CRYPTCONTEXT_SCHEMES = ['argon2'] # argon2 for hashing
# Password hashing settings
USER_PASSLIB_CRYPTCONTEXT_SCHEMES = ['argon2'] # argon2 for password hashing
# I would suggest settings these to the maximum that you can.
USER_PASSLIB_CRYPTCONTEXT_KEYWORDS = dict(argon2__rounds=5, argon2__memory_cost=8192, argon2__max_threads=-1)
# rounds - This corresponds linearly to the amount of time hashing will take.
# memory_cost - Defines the memory usage in kibibytes. This corresponds linearly to the amount of memory hashing will take.
# max_threads - Maximum number of threads that will be used. -1 means unlimited; otherwise hashing will use `min(parallelism, max_threads)` threads.
# Flask-User routing settings
USER_AFTER_LOGIN_ENDPOINT = "main.index"
USER_AFTER_LOGOUT_ENDPOINT = "main.signed_out"
USER_AFTER_EDIT_USER_PROFILE_ENDPOINT = 'main.profile'

View File

@@ -0,0 +1,8 @@
<p>Dear {{ user.email }},</p>
{% block message %}
{% endblock %}
<p>Sincerely,<br/>
{{ app_name }}
</p>

View File

@@ -0,0 +1,7 @@
Dear User,
{% block message %}
{% endblock %}
Sincerely,
{{ app_name }}

View File

@@ -0,0 +1 @@
{{ app_name }} - {% block subject %}{% endblock %}

View File

@@ -0,0 +1,11 @@
{% extends 'flask_user/emails/base_message.html' %}
{% block message %}
<p>You will need to confirm your email to start using {{ app_name }}.</p>
<p>If you initiated this confirmation, please click on the link below:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="{{ confirm_email_link }}">Confirm your email</a>.</p>
<p>If you did not initiate this confirmation, you may safely ignore this email.</p>
{% endblock %}

View File

@@ -0,0 +1,10 @@
{% extends 'flask_user/emails/base_message.txt' %}
{% block message %}
You will need to confirm your email to start using {{ app_name }}.
If you initiated this registration, please visit the link below:
{{ confirm_email_link }}
If you did not initiate this registration, you may safely ignore this email.
{% endblock %}

View File

@@ -0,0 +1,3 @@
{% extends 'flask_user/emails/base_subject.txt' %}
{% block subject %}Email Confirmation{% endblock %}

View File

@@ -0,0 +1,10 @@
{% extends 'flask_user/emails/base_message.html' %}
{% block message %}
<p>You have been invited to join {{ app_name }}!</p>
<p>To register an account, please click on the link below:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="{{ accept_invitation_link }}">Join {{ app_name }}</a>.</p>
{% endblock %}

View File

@@ -0,0 +1,9 @@
{% extends 'flask_user/emails/base_message.txt' %}
{% block message %}
You have been invited to join {{ app_name }}.
To register an account, please click on the link below:
{{ accept_invitation_link }}
{% endblock %}

View File

@@ -0,0 +1,3 @@
{% extends 'flask_user/emails/base_subject.txt' %}
{% block subject %}Invitation{% endblock %}

View File

@@ -0,0 +1,8 @@
{% extends 'flask_user/emails/base_message.html' %}
{% block message %}
<p>Your password has been changed.</p>
{% if user_manager.USER_ENABLE_FORGOT_PASSWORD %}
<p>If you did not initiate this password change, <a href="{{ url_for('user.forgot_password', _external=True) }}">click here to reset it</a>.</p>
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,12 @@
{% extends 'flask_user/emails/base_message.txt' %}
{% block message %}
Your password has been changed.
{% if user_manager.enable_forgot_password -%}
If you did not initiate this password change, click the link below to reset it.
{{ url_for('user.forgot_password', _external=True) }}
{% endif -%}
{% endblock %}

View File

@@ -0,0 +1,3 @@
{% extends 'flask_user/emails/base_subject.txt' %}
{% block subject %}Your password has been changed{% endblock %}

View File

@@ -0,0 +1,16 @@
{% extends 'flask_user/emails/base_message.html' %}
{% block message %}
<p>Thank you for registering with {{ app_name }}.</p>
{% if confirm_email_link -%}
<p>You will need to confirm your email next.</p>
<p>If you initiated this registration, please click on the link below:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="{{ confirm_email_link }}">Confirm your email</a>.</p>
<p>If you did not initiate this registration, you may safely ignore this email.</p>
{%- endif %}
{% endblock %}

View File

@@ -0,0 +1,15 @@
{% extends 'flask_user/emails/base_message.txt' %}
{% block message %}
Thank you for registering with {{ app_name }}.
{% if confirm_email_link -%}
You will need to confirm your email next.
If you initiated this registration, please visit the link below:
{{ confirm_email_link }}
If you did not initiate this registration, you may safely ignore this email.
{%- endif %}
{% endblock %}

View File

@@ -0,0 +1,3 @@
{% extends 'flask_user/emails/base_subject.txt' %}
{% block subject %}{% if user_manager.enable_confirm_email and not user.confirmed_at %}Confirm your email{% else %}Thank you for registering{% endif %}{% endblock %}

View File

@@ -0,0 +1,12 @@
{% extends 'flask_user/emails/base_message.html' %}
{% block message %}
<p>We have received your password reset request.</p>
<p>If you initiated this request, please click on the link below:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="{{ reset_password_link }}">Reset password</a>.</p>
<p>If you did not initiate this password reset, you may safely ignore this email.</p>
{% endblock %}

View File

@@ -0,0 +1,11 @@
{% extends 'flask_user/emails/base_message.txt' %}
{% block message %}
We have received your password reset request.
If you initiated this request, please click on the link below:
{{ reset_password_link }}
If you did not initiate this password reset, you may safely ignore this email.
{% endblock %}

View File

@@ -0,0 +1,3 @@
{% extends 'flask_user/emails/base_subject.txt' %}
{% block subject %}Reset password{% endblock %}

View File

@@ -0,0 +1,6 @@
{% extends 'flask_user/emails/base_message.html' %}
{% block message %}
<p>Your username has been changed.</p>
<p>If you did not initiate this username change, please <a href="{{ url_for('user.login', _external=True) }}">sign in</a> (using your email address) and change your password.</p>
{% endblock %}

View File

@@ -0,0 +1,10 @@
{% extends 'flask_user/emails/base_message.txt' %}
{% block message %}
Your username has been changed.
If you did not initiate this username change, please sign in (using your email address) and change your password.
{{ url_for('user.login', _external=True) }}
{% endblock %}

View File

@@ -0,0 +1,3 @@
{% extends 'flask_user/emails/base_subject.txt' %}
{% block subject %}Your username has been changed{% endblock %}