Skip to content
Permalink
Browse files

add comments

  • Loading branch information...
JeffVandrewJr committed Jan 23, 2019
1 parent 3ff8895 commit 054fc3826a807ace2504419fdd97e08a8f114c2d
@@ -12,9 +12,15 @@
from flask_sqlalchemy import SQLAlchemy
import os

'''
Unfortunately Flask App factories cant's conform to PEP
Codex beauty standards!
'''


VERSION = '0.6.69'

# extensions
# register extensions
bootstrap = Bootstrap()
db = SQLAlchemy()
migrate = Migrate()
@@ -26,7 +32,7 @@
scheduler = APScheduler()


# admin
# register Flask-Admin
class AdminHomeView(AdminIndexView):
@expose('/')
def index(self):
@@ -47,7 +53,7 @@ def inaccessible_callback(self, name, **kwargs):
)


# global
# this will be needed in the create_app fn later
global temp_bp

# permissions - flask_principal objects created by BloggingEngine
@@ -8,6 +8,7 @@

@bp.route('/deletesquare')
def delete_square():
# deactivates square and converts all subs to Bitcoin billing
square = Square.query.first()
if square is not None:
db.session.delete(square)
@@ -22,6 +23,7 @@ def delete_square():

@bp.route('/deletega')
def delete_ga():
# deactivates Google Analytics
ga = ThirdPartyServices.query.filter_by(
name='ga').first()
if ga is not None:
@@ -34,6 +36,9 @@ def delete_ga():

@bp.route('/deactivateisso')
def deactivate_isso():
# deactivates isso comments
# does not delete the comments.db, so can be reactivated later
# comment moderation password can be rest by deactivate/reactivate
isso = ThirdPartyServices.query.filter_by(
name='isso').first()
if isso is not None:
@@ -49,6 +54,7 @@ def deactivate_isso():

@bp.route('/testemail')
def test_email():
# sends a test email to ensure SMTP settings are correct
email = Email.query.first()
send_email(
subject='Test Email',
@@ -4,6 +4,9 @@


def isso_config():
# isso requires a config file
# this function writes a config file in isso format
# file is saved in a Docker volume shared between lp and isso
file = '/var/lib/config/isso.cfg'
isso_pass = ThirdPartyServices.query.filter_by(
name='isso').first().code
@@ -10,8 +10,16 @@
from flask import flash, redirect, url_for, current_app
from flask_login import current_user

'''
Flask-Admin creates views in the admin panel using classes.
These classes are loaded using the load_admin function.
This __init__ file is loaded in the app factory to register
the necessary classes to Flask-Admin.
'''


class LibrePatronBaseView(BaseView):
# protects admin panel from regular users
def is_accessible(self):
return current_user.is_authenticated and \
current_user.role == 'admin'
@@ -23,6 +31,7 @@ def inaccessible_callback(self, name, **kwargs):
class BTCPayView(LibrePatronBaseView):
@expose('/', methods=['GET', 'POST'])
def btcpay(self):
# custom view to pair BTCPay
form = BTCCodeForm()
btcpay = BTCPayClientStore.query.first()
if form.validate_on_submit():
@@ -43,6 +52,7 @@ def btcpay(self):
class GAView(LibrePatronBaseView):
@expose('/', methods=['GET', 'POST'])
def ga(self):
# custom view to input Google Analytics UA code
form = GAForm()
ga = ThirdPartyServices.query.filter_by(name='ga').first()
if form.validate_on_submit():
@@ -68,6 +78,7 @@ def ga(self):
class IssoView(LibrePatronBaseView):
@expose('/', methods=['GET', 'POST'])
def isso(self):
# custom view to activate isso comments
if Email.query.first() is None:
flash('You must set up email first.')
return redirect(url_for('email.email'))
@@ -99,6 +110,7 @@ def isso(self):
class SquareView(LibrePatronBaseView):
@expose('/', methods=['GET', 'POST'])
def square(self):
# custom view to activate Square credit card pmts
form = SquareSetupForm()
square = Square.query.first()
if form.validate_on_submit():
@@ -125,6 +137,7 @@ def square(self):
class EmailView(LibrePatronBaseView):
@expose('/', methods=['GET', 'POST'])
def email(self):
# custom view to set SMTP settings
form = EmailSetupForm()
email = Email.query.first()
if form.validate_on_submit():
@@ -154,6 +167,11 @@ def email(self):


class LibrePatronModelView(ModelView):
'''
Inherits from the Flask-Admin ModelView, which is used for
manually editing info in the database. This customizes the look
for LibrePatron and also protects it from non-admins.
'''
can_export = True
create_modal = True
edit_modal = True
@@ -167,11 +185,21 @@ def inaccessible_callback(self, name, **kwargs):


class UserView(LibrePatronModelView):
'''
Allows admins to search for users by username or email. Also
excludes password hashes from the table of users for aesthetic
reasons.
'''
column_exclude_list = ['password_hash', 'renew']
column_searchable_list = ['username', 'email']


class PriceView(LibrePatronModelView):
'''
This is a special version of ModelView for editing price levels
stored in the database. The custom template warns the admin about
the consequences of changing price levels.
'''
list_template = 'admin/custom_list.html'


@@ -65,6 +65,12 @@ def update_sub():
@bp.route('/v1/square/<int:price>', methods=['GET', 'POST'])
@login_required
def process_square(price):
'''
Receives a nonce from Square, and uses the nonce to
charge the card. Upon successful charge, it updates the
user's subscription and stores the Square Customer ID and
Card ID for future charges.
'''
if not request.form or 'nonce' not in request.form:
return "Bad Request", 422
square = Square.query.first()
@@ -14,6 +14,7 @@

@bp.route('/login', methods=['GET', 'POST'])
def login():
# login page
if current_user.is_authenticated:
return redirect(url_for('auth.account'))
form = LoginForm()
@@ -39,13 +40,15 @@ def login():
@bp.route('/logout')
@login_required
def logout():
# logs user out
logout_user()
flash('You are logged out.', 'info')
return redirect(url_for('main.index'))


@bp.route('/register', methods=['GET', 'POST'])
def register():
# registers a new user
if current_user.is_authenticated:
flash('You are already registered.')
return redirect(url_for('main.index'))
@@ -70,6 +73,7 @@ def register():

@bp.route('/adminsetup', methods=['GET', 'POST'])
def adminsetup():
# registers an admin user
if User.query.filter_by(role='admin').first() is not None:
flash('Administrator is already set.')
return redirect(url_for('main.index'))
@@ -97,6 +101,7 @@ def adminsetup():
@bp.route('/account')
@login_required
def account():
# displays user's account expiration and status
if hasattr(current_user, 'role'):
if current_user.role == 'admin':
return redirect(url_for('admin.index'))
@@ -123,6 +128,7 @@ def account():
@bp.route('/cancelcc')
@login_required
def cancel_square():
# allows user to cancel credit card auto-billing
if hasattr(current_user, 'role'):
if current_user.role == 'admin':
return redirect(url_for('admin.index'))
@@ -137,6 +143,7 @@ def cancel_square():
@bp.route('/mailopt')
@login_required
def mail_opt():
# opts the user out of email notifications for new updates
if hasattr(current_user, 'role'):
if current_user.role == 'admin':
return redirect(url_for('admin.index'))
@@ -152,6 +159,7 @@ def mail_opt():

@bp.route('/resetrequest', methods=['GET', 'POST'])
def reset_password_request():
# request a password reset
form = ResetPasswordRequestForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
@@ -172,6 +180,7 @@ def reset_password_request():

@bp.route('/reset_password/<token>', methods=['GET', 'POST'])
def reset_password(token):
# accepts incoming password reset request from emailed link
if current_user.is_authenticated:
flash(
'You must log out before resetting your password.',
@@ -1,3 +1,6 @@
'''
This overrides the blueprint auto-generated by Flask-Blogging.
'''
from app import temp_bp

bp = temp_bp
@@ -6,6 +6,10 @@

@bp.before_request
def protect():
'''
Registers new function to Flask-Blogging Blueprint that protects
updates to make them only viewable by paid subscribers.
'''
if current_user.is_authenticated:
if datetime.today() <= current_user.expiration:
return None
@@ -9,12 +9,14 @@


def send_async_email(app, msg):
# sends a single email asyncronously
with app.app_context():
mail = Email.query.first()
mail.send(msg)


def send_async_bulkmail(app, msg, users):
# accepts user list and message, sending msg to all paid users
with app.app_context():
mail = Email.query.first()
try:
@@ -30,6 +32,7 @@ def send_async_bulkmail(app, msg, users):


def send_email(subject, sender, recipients, text_body, html_body):
# composes a single email and passes it to send_async_email fn
msg = Message(subject, sender=sender, recipients=recipients)
msg.body = text_body
msg.html = html_body
@@ -39,6 +42,10 @@ def send_email(subject, sender, recipients, text_body, html_body):


def send_reminder_emails(app, reminder_list):
'''
Takes a list of users about to expire, and emails them fresh
payment links that direct to BTCPay.
'''
with app.app_context():
mail = Email.query.first()
try:
@@ -71,6 +78,10 @@ def send_reminder_emails(app, reminder_list):


def send_failed_emails(app, failed_list, declined_list):
'''
Takes a list of users whose credit card renewals failed via
Square, and emails them asking to update their credit card.
'''
with app.app_context():
mail = Email.query.first()
site = app.config['BLOGGING_SITENAME']
@@ -111,6 +122,7 @@ def send_failed_emails(app, failed_list, declined_list):


def send_bulkmail(subject, sender, users, text_body, html_body):
# composes an email message and sends ti to send_async_bulkmail
msg = Message(subject, sender=sender)
msg.body = text_body
msg.html = html_body
@@ -120,6 +132,7 @@ def send_bulkmail(subject, sender, users, text_body, html_body):


def send_password_reset_email(user):
# emails user a token to reset password
token = user.get_reset_password_token()
mail = Email.query.first()
send_email(
@@ -133,6 +146,11 @@ def send_password_reset_email(user):


def email_post(post):
'''
Takes a blog post, uses the Markdown engine to render it to HTML,
then creates an email message from the HTML. The msg is then passed
to send_bulkmail function.
'''
mail = Email.query.first()
try:
markdown = Markdown()
@@ -13,6 +13,12 @@
@bp.route('/')
@bp.route('/index')
def index():
'''
Displays the main homepage. The homepage text is stored in the db
as a 'post' (just like an update for paid subscribers), but it has a
special "PUBLIC" tag to designate that it's the homepage. This page
is viewable by all visitiors.
'''
try:
posts = blog_engine.storage.get_posts(
count=1,
@@ -74,7 +80,8 @@ def index():

@bp.route('/support')
def support():
# set default pricing if none exists
# displays priving page
# also sets default pricing if none exists
if PriceLevel.query.all() == []:
level_1 = PriceLevel(
name='Patron',
@@ -108,6 +115,7 @@ def support():
@bp.route('/creditcard')
@login_required
def credit_card():
# directs user to sqpaymentform.js
price = request.args.get('price')
if price is None:
flash('There was an error. Try again.')
@@ -127,6 +135,7 @@ def credit_card():
@bp.route('/createinvoice')
@login_required
def create_invoice():
# creates a BTCPay invoice when a user chooses a price level
user_arg = request.args.get('username')
if user_arg is not None:
if user_arg != current_user.username:

0 comments on commit 054fc38

Please sign in to comment.
You can’t perform that action at this time.