yurt
This commit is contained in:
1
app/utils/__init__.py
Normal file
1
app/utils/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# Utils package
|
||||
38
app/utils/auth.py
Normal file
38
app/utils/auth.py
Normal file
@@ -0,0 +1,38 @@
|
||||
"""
|
||||
Authentication utilities and decorators
|
||||
"""
|
||||
|
||||
from functools import wraps
|
||||
from flask import session, flash, redirect, url_for, current_app
|
||||
|
||||
|
||||
def login_required(f):
|
||||
"""Decorator to require login for route access"""
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
if 'logged_in' not in session:
|
||||
flash('Please log in to access this page.')
|
||||
return redirect(url_for('auth.login'))
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
||||
|
||||
def check_credentials(username, password):
|
||||
"""Check if provided credentials are valid"""
|
||||
return (username == current_app.config['ADMIN_USERNAME'] and
|
||||
password == current_app.config['ADMIN_PASSWORD'])
|
||||
|
||||
|
||||
def login_user():
|
||||
"""Log in the user by setting session"""
|
||||
session['logged_in'] = True
|
||||
|
||||
|
||||
def logout_user():
|
||||
"""Log out the user by clearing session"""
|
||||
session.pop('logged_in', None)
|
||||
|
||||
|
||||
def is_authenticated():
|
||||
"""Check if current user is authenticated"""
|
||||
return 'logged_in' in session
|
||||
24
app/utils/error_handlers.py
Normal file
24
app/utils/error_handlers.py
Normal file
@@ -0,0 +1,24 @@
|
||||
"""
|
||||
Error handlers for the application
|
||||
"""
|
||||
|
||||
from flask import render_template, current_app
|
||||
|
||||
|
||||
def register_error_handlers(app):
|
||||
"""Register error handlers with the app"""
|
||||
|
||||
@app.errorhandler(404)
|
||||
def not_found_error(error):
|
||||
current_app.logger.error(f'404 error: {error}')
|
||||
return render_template('errors/404.html'), 404
|
||||
|
||||
@app.errorhandler(500)
|
||||
def internal_error(error):
|
||||
current_app.logger.error(f'500 error: {error}')
|
||||
return render_template('errors/500.html'), 500
|
||||
|
||||
@app.errorhandler(413)
|
||||
def too_large(error):
|
||||
current_app.logger.error(f'413 error - File too large: {error}')
|
||||
return render_template('errors/413.html'), 413
|
||||
60
app/utils/helpers.py
Normal file
60
app/utils/helpers.py
Normal file
@@ -0,0 +1,60 @@
|
||||
"""
|
||||
Utility helper functions
|
||||
"""
|
||||
|
||||
from flask import current_app, make_response, jsonify
|
||||
from app.models.database import PetPicture
|
||||
|
||||
|
||||
def allowed_file(filename):
|
||||
"""Check if file extension is allowed"""
|
||||
return ('.' in filename and
|
||||
filename.rsplit('.', 1)[1].lower() in current_app.config['ALLOWED_EXTENSIONS'])
|
||||
|
||||
|
||||
def get_liked_pictures_from_cookie(request):
|
||||
"""Extract liked picture IDs from cookie"""
|
||||
liked_pictures = request.cookies.get('liked_pictures', '')
|
||||
return liked_pictures.split(',') if liked_pictures else []
|
||||
|
||||
|
||||
def add_liked_status_to_pictures(pictures, liked_list):
|
||||
"""Add user_liked status to picture records"""
|
||||
pictures_with_likes = []
|
||||
for picture in pictures:
|
||||
picture_dict = dict(picture)
|
||||
picture_dict['user_liked'] = str(picture['id']) in liked_list
|
||||
pictures_with_likes.append(picture_dict)
|
||||
return pictures_with_likes
|
||||
|
||||
|
||||
def handle_like_action(picture_id, request):
|
||||
"""Handle like/unlike action and return JSON response"""
|
||||
# Get existing likes from cookie
|
||||
liked_list = get_liked_pictures_from_cookie(request)
|
||||
picture_id_str = str(picture_id)
|
||||
|
||||
if picture_id_str in liked_list:
|
||||
# Unlike: remove from cookie and decrement count
|
||||
liked_list.remove(picture_id_str)
|
||||
PetPicture.update_likes(picture_id, increment=False)
|
||||
liked = False
|
||||
else:
|
||||
# Like: add to cookie and increment count
|
||||
liked_list.append(picture_id_str)
|
||||
PetPicture.update_likes(picture_id, increment=True)
|
||||
liked = True
|
||||
|
||||
# Get updated like count
|
||||
like_count = PetPicture.get_like_count(picture_id)
|
||||
|
||||
# Create response with updated cookie
|
||||
response = make_response(jsonify({
|
||||
'liked': liked,
|
||||
'like_count': like_count
|
||||
}))
|
||||
|
||||
# Update cookie (expires in 1 year)
|
||||
response.set_cookie('liked_pictures', ','.join(liked_list), max_age=365*24*60*60)
|
||||
|
||||
return response
|
||||
32
app/utils/logging_config.py
Normal file
32
app/utils/logging_config.py
Normal file
@@ -0,0 +1,32 @@
|
||||
"""
|
||||
Logging configuration
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
from logging.handlers import RotatingFileHandler
|
||||
|
||||
|
||||
def setup_logging(app):
|
||||
"""Setup application logging"""
|
||||
if not app.debug and not app.testing:
|
||||
# Production logging setup
|
||||
if not os.path.exists('logs'):
|
||||
os.mkdir('logs')
|
||||
|
||||
file_handler = RotatingFileHandler(
|
||||
'logs/pets_powerwashing.log',
|
||||
maxBytes=10240,
|
||||
backupCount=10
|
||||
)
|
||||
file_handler.setFormatter(logging.Formatter(
|
||||
'%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
|
||||
))
|
||||
file_handler.setLevel(logging.INFO)
|
||||
app.logger.addHandler(file_handler)
|
||||
|
||||
app.logger.setLevel(logging.INFO)
|
||||
app.logger.info('Pets of Powerwashing startup')
|
||||
else:
|
||||
# Development logging
|
||||
app.logger.setLevel(logging.DEBUG)
|
||||
Reference in New Issue
Block a user