improve blacklist, secure routes, add more routes...

This commit is contained in:
mystie 2024-09-28 00:31:54 +03:00
parent 82c6a8b67b
commit 0a98041a23

63
app.py
View file

@ -3,6 +3,7 @@ from flask_compress import Compress
from dotenv import load_dotenv from dotenv import load_dotenv
from mysql.connector import errorcode from mysql.connector import errorcode
from functools import wraps from functools import wraps
from werkzeug.utils import secure_filename
import mysql.connector import mysql.connector
import urllib import urllib
import functions as func import functions as func
@ -79,7 +80,7 @@ def loginRequired(f):
@wraps(f) @wraps(f)
def login_required(*args, **kwargs): def login_required(*args, **kwargs):
if not logged_in: if not logged_in:
return abort(403) return abort(404)
return f(*args, **kwargs) return f(*args, **kwargs)
return login_required return login_required
@ -95,6 +96,8 @@ def before_request():
@app.context_processor @app.context_processor
def inject_stuff(): def inject_stuff():
cfg = func.loadJSON(const.configFile) cfg = func.loadJSON(const.configFile)
# for 1.6.0 or later
# questionCount = getQuestionCount()
return dict(metadata=func.generateMetadata(), len=len, str=str, const=const, cfg=cfg, logged_in=logged_in, version_id=const.version_id, version=const.version, appName=const.appName) return dict(metadata=func.generateMetadata(), len=len, str=str, const=const, cfg=cfg, logged_in=logged_in, version_id=const.version_id, version=const.version, appName=const.appName)
# -- template filters -- # -- template filters --
@ -256,7 +259,9 @@ def addQuestion():
return {'error': 'An error has occurred'}, 500 return {'error': 'An error has occurred'}, 500
blacklist = func.readPlainFile(const.blacklistFile, split=True) blacklist = func.readPlainFile(const.blacklistFile, split=True)
if (question in blacklist) or (from_who in blacklist):
for bad_word in blacklist:
if bad_word in question or bad_word in from_who:
# return a generic error message so bad actors wouldn't figure out the blacklist # return a generic error message so bad actors wouldn't figure out the blacklist
return {'error': 'An error has occurred'}, 500 return {'error': 'An error has occurred'}, 500
@ -309,6 +314,7 @@ def returnToInbox():
return {'message': 'Successfully returned question to inbox.'}, 200 return {'message': 'Successfully returned question to inbox.'}, 200
@api_bp.route('/pin_question/', methods=['POST']) @api_bp.route('/pin_question/', methods=['POST'])
@loginRequired
def pinQuestion(): def pinQuestion():
question_id = request.args.get('question_id', '') question_id = request.args.get('question_id', '')
if not question_id: if not question_id:
@ -323,6 +329,7 @@ def pinQuestion():
return {'message': 'Successfully pinned question.'}, 200 return {'message': 'Successfully pinned question.'}, 200
@api_bp.route('/unpin_question/', methods=['POST']) @api_bp.route('/unpin_question/', methods=['POST'])
@loginRequired
def unpinQuestion(): def unpinQuestion():
question_id = request.args.get('question_id', '') question_id = request.args.get('question_id', '')
if not question_id: if not question_id:
@ -363,45 +370,39 @@ def addAnswer():
return jsonify({'message': 'Answer added successfully!'}), 201 return jsonify({'message': 'Answer added successfully!'}), 201
# reserved for 1.6.0 or later @api_bp.route('/upload_favicon/', methods=['POST'])
""" @loginRequired
@api_bp.route('/question_count/', methods=['GET']) def uploadFavicon():
def questionCount(): favicon = request.files.get('favicon')
if favicon and func.allowedFile(favicon.filename):
filename = secure_filename(favicon.filename)
favicon_path = const.faviconDir / filename
favicon.save(favicon_path)
func.generateFavicon(filename)
return {'message': 'Successfully updated favicon!'}, 201
elif favicon and not func.allowedFile(favicon.filename):
return {'error': 'File type is not supported'}, 400
elif not favicon:
return {'error': "favicon is not specified"}, 400
@api_bp.route('/get_question_count/', methods=['GET'])
def getQuestionCount():
conn = func.connectToDb() conn = func.connectToDb()
cursor = conn.cursor() cursor = conn.cursor()
cursor.execute("SELECT COUNT(*) FROM questions WHERE answered=%s", (False,)) cursor.execute("SELECT COUNT(id) FROM questions WHERE answered=%s", (False,))
question_count = cursor.fetchone() question_count = cursor.fetchone()
cursor.close() cursor.close()
conn.close() conn.close()
return str(question_count[0]) return str(question_count[0])
"""
# unused # unused
""" """
@api_bp.route('/all_questions/', methods=['GET'])
def listQuestions():
answered = request.args.get('answered', False)
conn = func.connectToDb()
cursor = conn.cursor(dictionary=True)
cursor.execute("SELECT id, from_who, creation_date, content, answered, answer_id FROM questions WHERE answered=%s", (answered,))
questions = cursor.fetchall()
cursor.close()
conn.close()
return jsonify(questions)
@api_bp.route('/all_answers/', methods=['GET'])
def listAnswers():
conn = func.connectToDb()
cursor = conn.cursor(dictionary=True)
cursor.execute("SELECT id, question_id, creation_date, content FROM answers")
answers = cursor.fetchall()
cursor.close()
conn.close()
return jsonify(answers)
"""
@api_bp.route('/view_question/', methods=['GET']) @api_bp.route('/view_question/', methods=['GET'])
@loginRequired
def viewQuestion(): def viewQuestion():
question_id = request.args.get('question_id', '') question_id = request.args.get('question_id', '')
if not question_id: if not question_id:
@ -416,6 +417,7 @@ def viewQuestion():
return jsonify(question) return jsonify(question)
@api_bp.route('/view_answer/', methods=['GET']) @api_bp.route('/view_answer/', methods=['GET'])
@loginRequired
def viewAnswer(): def viewAnswer():
answer_id = request.args.get('answer_id', '') answer_id = request.args.get('answer_id', '')
if not answer_id: if not answer_id:
@ -428,6 +430,7 @@ def viewAnswer():
cursor.close() cursor.close()
conn.close() conn.close()
return jsonify(answer) return jsonify(answer)
"""
@api_bp.route('/update_config/', methods=['POST']) @api_bp.route('/update_config/', methods=['POST'])
@loginRequired @loginRequired