mirror of
https://github.com/aronwk-aaron/MSState-Library-ETD.git
synced 2025-12-30 09:19:49 -06:00
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:
@@ -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
81
app/commands.py
Normal 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
|
||||
@@ -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>',
|
||||
]
|
||||
]
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from flask_marshmallow.sqla import ModelSchema
|
||||
from app import ma
|
||||
from .models import User, Notification, Submission, Revision, Review
|
||||
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
8
app/templates/flask_user/emails/base_message.html
Normal file
8
app/templates/flask_user/emails/base_message.html
Normal file
@@ -0,0 +1,8 @@
|
||||
<p>Dear {{ user.email }},</p>
|
||||
|
||||
{% block message %}
|
||||
{% endblock %}
|
||||
|
||||
<p>Sincerely,<br/>
|
||||
{{ app_name }}
|
||||
</p>
|
||||
7
app/templates/flask_user/emails/base_message.txt
Normal file
7
app/templates/flask_user/emails/base_message.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
Dear User,
|
||||
|
||||
{% block message %}
|
||||
{% endblock %}
|
||||
|
||||
Sincerely,
|
||||
{{ app_name }}
|
||||
1
app/templates/flask_user/emails/base_subject.txt
Normal file
1
app/templates/flask_user/emails/base_subject.txt
Normal file
@@ -0,0 +1 @@
|
||||
{{ app_name }} - {% block subject %}{% endblock %}
|
||||
11
app/templates/flask_user/emails/confirm_email_message.html
Normal file
11
app/templates/flask_user/emails/confirm_email_message.html
Normal 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/>
|
||||
<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 %}
|
||||
10
app/templates/flask_user/emails/confirm_email_message.txt
Normal file
10
app/templates/flask_user/emails/confirm_email_message.txt
Normal 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 %}
|
||||
@@ -0,0 +1,3 @@
|
||||
{% extends 'flask_user/emails/base_subject.txt' %}
|
||||
|
||||
{% block subject %}Email Confirmation{% endblock %}
|
||||
10
app/templates/flask_user/emails/invite_user_message.html
Normal file
10
app/templates/flask_user/emails/invite_user_message.html
Normal 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/>
|
||||
<a href="{{ accept_invitation_link }}">Join {{ app_name }}</a>.</p>
|
||||
|
||||
{% endblock %}
|
||||
9
app/templates/flask_user/emails/invite_user_message.txt
Normal file
9
app/templates/flask_user/emails/invite_user_message.txt
Normal 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 %}
|
||||
3
app/templates/flask_user/emails/invite_user_subject.txt
Normal file
3
app/templates/flask_user/emails/invite_user_subject.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
{% extends 'flask_user/emails/base_subject.txt' %}
|
||||
|
||||
{% block subject %}Invitation{% endblock %}
|
||||
@@ -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 %}
|
||||
12
app/templates/flask_user/emails/password_changed_message.txt
Normal file
12
app/templates/flask_user/emails/password_changed_message.txt
Normal 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 %}
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{% extends 'flask_user/emails/base_subject.txt' %}
|
||||
|
||||
{% block subject %}Your password has been changed{% endblock %}
|
||||
16
app/templates/flask_user/emails/registered_message.html
Normal file
16
app/templates/flask_user/emails/registered_message.html
Normal 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/>
|
||||
<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 %}
|
||||
15
app/templates/flask_user/emails/registered_message.txt
Normal file
15
app/templates/flask_user/emails/registered_message.txt
Normal 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 %}
|
||||
3
app/templates/flask_user/emails/registered_subject.txt
Normal file
3
app/templates/flask_user/emails/registered_subject.txt
Normal 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 %}
|
||||
12
app/templates/flask_user/emails/reset_password_message.html
Normal file
12
app/templates/flask_user/emails/reset_password_message.html
Normal 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/>
|
||||
<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 %}
|
||||
11
app/templates/flask_user/emails/reset_password_message.txt
Normal file
11
app/templates/flask_user/emails/reset_password_message.txt
Normal 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 %}
|
||||
@@ -0,0 +1,3 @@
|
||||
{% extends 'flask_user/emails/base_subject.txt' %}
|
||||
|
||||
{% block subject %}Reset password{% endblock %}
|
||||
@@ -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 %}
|
||||
10
app/templates/flask_user/emails/username_changed_message.txt
Normal file
10
app/templates/flask_user/emails/username_changed_message.txt
Normal 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 %}
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{% extends 'flask_user/emails/base_subject.txt' %}
|
||||
|
||||
{% block subject %}Your username has been changed{% endblock %}
|
||||
Reference in New Issue
Block a user