Rename routes to gallery

Move methods to api.py
Remove old db manager as its unused
Remove old db tables as theres a new schema file
Rename onlylegsSass to sassy, unused for now
Update example.env to reflect new layout
This commit is contained in:
Michał 2023-01-10 14:40:43 +00:00
parent a499e6c840
commit e395139656
13 changed files with 146 additions and 326 deletions

View file

@ -13,19 +13,12 @@ import time
import sys
import os
# Import required OnlyLegs packages
#from packages import onlylegsDB
#onlylegsDB = onlylegsDB.DBmanager()
#onlylegsDB.initialize()
#from packages import onlylegsSass
#onlylegsSass = onlylegsSass.Sassy('default')
# Import flask
from flask import *
from werkzeug.utils import secure_filename
def create_app(test_config=None):
# Get environment variables
from dotenv import load_dotenv
load_dotenv(os.path.join('./gallery', 'user', '.env'))
@ -49,6 +42,16 @@ def create_app(test_config=None):
os.makedirs(app.instance_path)
except OSError:
pass
# Load database
from . import db
db.init_app(app)
# Load theme
#from . import sassy
#sassy.compile('default')
@app.errorhandler(405)
def method_not_allowed(e):
@ -80,47 +83,19 @@ def create_app(test_config=None):
msg = 'Server died inside :c'
return render_template('error.html', error=error, msg=msg), 500
from . import auth
app.register_blueprint(auth.bp)
from . import routes
app.register_blueprint(routes.bp)
# Load login, registration and logout manager
from . import auth
app.register_blueprint(auth.blueprint)
# Load apis
from . import api
app.register_blueprint(api.blueprint)
# Load routes for home and images
from . import gallery
app.register_blueprint(gallery.blueprint)
app.add_url_rule('/', endpoint='index')
#
# METHODS
#
@app.route('/fileList/<item_type>', methods=['GET'])
def image_list(item_type):
if request.method != 'GET':
abort(405)
cursor = onlylegsDB.database.cursor()
cursor.execute("SELECT * FROM posts ORDER BY id DESC")
item_list = cursor.fetchall()
return jsonify(item_list)
@app.route('/uploads/<quality>/<request_file>', methods=['GET'])
def uploads(quality, request_file):
if request.method != 'GET':
abort(405)
quality = secure_filename(quality)
quality_dir = os.path.join(app.config['UPLOAD_FOLDER'], quality)
if not os.path.isdir(quality_dir):
abort(404)
request_file = secure_filename(request_file)
if not os.path.isfile(os.path.join(quality_dir, request_file)):
abort(404)
return send_from_directory(quality_dir, request_file)
from . import db
db.init_app(app)
return app

28
gallery/api.py Normal file
View file

@ -0,0 +1,28 @@
import functools
from flask import (
Blueprint, flash, g, redirect, render_template, request, session, url_for, abort, jsonify, send_from_directory
)
from werkzeug.security import check_password_hash, generate_password_hash
from werkzeug.utils import secure_filename
from gallery.db import get_db
blueprint = Blueprint('api', __name__, url_prefix='/api')
@blueprint.route('/uploads/<quality>/<request_file>', methods=['POST'])
def uploads(quality, request_file):
if request.method != 'POST':
abort(405)
#quality = secure_filename(quality)
#quality_dir = os.path.join(app.config['UPLOAD_FOLDER'], quality)
#if not os.path.isdir(quality_dir):
# abort(404)
#request_file = secure_filename(request_file)
#if not os.path.isfile(os.path.join(quality_dir, request_file)):
# abort(404)
#return send_from_directory(quality_dir, request_file)
abort(404)

View file

@ -5,10 +5,10 @@ from flask import (
from werkzeug.security import check_password_hash, generate_password_hash
from gallery.db import get_db
bp = Blueprint('auth', __name__, url_prefix='/auth')
blueprint = Blueprint('auth', __name__, url_prefix='/auth')
@bp.before_app_request
@blueprint.before_app_request
def load_logged_in_user():
user_id = session.get('user_id')
@ -20,7 +20,7 @@ def load_logged_in_user():
).fetchone()
@bp.route('/register', methods=('GET', 'POST'))
@blueprint.route('/register', methods=('GET', 'POST'))
def register():
if request.method == 'POST':
username = request.form['username']
@ -50,7 +50,7 @@ def register():
return render_template('auth/register.html')
@bp.route('/login', methods=('GET', 'POST'))
@blueprint.route('/login', methods=('GET', 'POST'))
def login():
if request.method == 'POST':
username = request.form['username']
@ -76,7 +76,7 @@ def login():
return render_template('auth/login.html')
@bp.route('/logout')
@blueprint.route('/logout')
def logout():
session.clear()
return redirect(url_for('index'))

64
gallery/gallery.py Normal file
View file

@ -0,0 +1,64 @@
from flask import (
Blueprint, flash, g, redirect, render_template, request, url_for, jsonify
)
from werkzeug.exceptions import abort
from werkzeug.utils import secure_filename
from gallery.auth import login_required
from gallery.db import get_db
blueprint = Blueprint('gallery', __name__)
@blueprint.route('/')
def index():
return render_template('index.html')
@blueprint.route('/image/<request_id>')
def image(request_id):
# Check if request_id is valid
try:
request_id = int(request_id)
except ValueError:
abort(404)
result = onlylegsDB.getImage(request_id)
return render_template('image.html', fileName=result[1], id=request_id)
@blueprint.route('/group')
def groups():
return render_template('groups/group.html', group_id='gwa gwa')
@blueprint.route('/group/<int:id>')
def group(id):
return render_template('groups/group.html', group_id=id)
@blueprint.route('/upload', methods=('GET', 'POST'))
@login_required
def upload():
if request.method == 'POST':
file = request.files['file']
form = request.form
if secure_filename(file.filename) == '':
flash('No selected file')
return redirect('gallery.upload')
return render_template('upload.html')
@blueprint.route('/profile')
def profile():
return render_template('profile.html', user_id='gwa gwa')
@blueprint.route('/profile/<int:id>')
def profile_id(id):
return render_template('profile.html', user_id=id)
@blueprint.route('/settings')
@login_required
def settings():
return render_template('settings.html')

View file

@ -1,91 +0,0 @@
import datetime
now = datetime.datetime.now()
import sys
import os
class DBmanager():
def __init__(self):
try:
import mysql.connector
from mysql.connector import Error
from dotenv import load_dotenv
except ImportError:
print("Error: could not import required packages")
sys.exit(1)
env_path = os.path.join('usr', '.env')
if not os.path.exists(env_path):
print("Error: could not find .env file")
sys.exit(1)
load_dotenv(env_path)
print(f"{now.hour}:{now.minute}:{now.second} - Connecting to database...")
try:
database = mysql.connector.connect(host=os.environ.get('DB_HOST'),
port=os.environ.get('DB_PORT'),
database=os.environ.get('DB_NAME'),
user=os.environ.get('DB_USER'),
password=os.environ.get('DB_PASS')
)
if database.is_connected():
db_Info = database.get_server_info()
print("Connected to MySQL Server version:", db_Info)
cursor = database.cursor()
cursor.execute("select database();")
record = cursor.fetchone()
print("Connected to database:", record[0])
print(f"{now.hour}:{now.minute}:{now.second} - Done!\n")
except Error as e:
print("Error while connecting to Database!\nFull error:", e)
sys.exit(1)
self.database = database
def initialize(self):
if not os.path.exists(os.path.join('packages', 'tables', 'generate.sql')):
print("Error: could not find tables directory")
sys.exit(1)
else:
print(f"{now.hour}:{now.minute}:{now.second} - Initializing tables...")
with open(os.path.join('packages', 'tables', 'generate.sql'), 'r') as sql:
cursor = self.database.cursor()
query = cursor.execute(sql.read(), multi=True)
i = 0
for res in query:
print(f"Query {i+1}: Affected {res.rowcount} rows")
i += 1
if not os.path.exists(os.path.join('packages', 'tables', 'junctions.sql')):
print("Error: could not find junctions directory")
sys.exit(1)
else:
print(f"{now.hour}:{now.minute}:{now.second} - Initializing junctions...")
with open(os.path.join('packages', 'tables', 'junctions.sql'), 'r') as sql:
cursor = self.database.cursor()
query = cursor.execute(sql.read(), multi=True)
i = 0
for res in query:
print(f"Query {i+1}: Affected {res.rowcount} rows")
i += 1
self.database.commit()
print(f"{now.hour}:{now.minute}:{now.second} - Done!\n")
def getImage(self, id):
sql = "SELECT * FROM posts WHERE id = %s"
img = (id,)
cursor = self.database.cursor()
cursor.execute(sql, img)
return cursor.fetchone()

View file

@ -1,67 +0,0 @@
CREATE TABLE IF NOT EXISTS users (
id INT(69) NOT NULL PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(255) NOT NULL UNIQUE,
email VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS posts (
id INT(69) PRIMARY KEY AUTO_INCREMENT,
file_name VARCHAR(255) NOT NULL UNIQUE,
author_id INT(69) NOT NULL,
description TEXT NOT NULL,
alt TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS groups (
id INT(69) PRIMARY KEY AUTO_INCREMENT,
author_id INT(69) NOT NULL,
name VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS permissions (
id INT(69) PRIMARY KEY AUTO_INCREMENT,
user_id INT(69) NOT NULL,
admin BOOLEAN NOT NULL DEFAULT FALSE,
create_posts BOOLEAN NOT NULL DEFAULT TRUE,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS devices (
id INT(69) PRIMARY KEY AUTO_INCREMENT,
user_id INT(69) NOT NULL,
device_id VARCHAR(255) NOT NULL,
cookie VARCHAR(255) NOT NULL,
ip VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS tokens (
id INT(69) PRIMARY KEY AUTO_INCREMENT,
token VARCHAR(255) NOT NULL UNIQUE,
is_used BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS logs (
id INT(69) PRIMARY KEY AUTO_INCREMENT,
ip VARCHAR(255) NOT NULL,
user_id INT(69) DEFAULT NULL,
code INT(69) NOT NULL,
note TEXT DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS bans (
id INT(69) PRIMARY KEY AUTO_INCREMENT,
ip VARCHAR(255) NOT NULL,
code INT(69) NOT NULL,
note TEXT DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

View file

@ -1,5 +0,0 @@
CREATE TABLE IF NOT EXISTS group_junction (
id INT(69) PRIMARY KEY AUTO_INCREMENT,
group_id INT(69) NOT NULL,
image_id INT(69) NOT NULL
);

View file

@ -1,69 +0,0 @@
from flask import (
Blueprint, flash, g, redirect, render_template, request, url_for
)
from werkzeug.exceptions import abort
from gallery.auth import login_required
from gallery.db import get_db
bp = Blueprint('routes', __name__)
#
# ROUTES
#
@bp.route('/')
def index():
return render_template('index.html')
@bp.route('/group')
def group():
return render_template('group.html', group_id='gwa gwa')
@bp.route('/group/<group_id>')
def group_id(group_id):
try:
group_id = int(group_id)
except ValueError:
abort(404)
return render_template('group.html', group_id=group_id)
@bp.route('/upload')
def upload():
return render_template('upload.html')
@bp.route('/upload/form', methods=['POST'])
def upload_form():
if request.method != 'POST':
abort(405)
return 'balls'
@bp.route('/profile')
def profile():
return render_template('profile.html', user_id='gwa gwa')
@bp.route('/profile/<user_id>')
def profile_id(user_id):
try:
user_id = int(user_id)
except ValueError:
abort(404)
return render_template('profile.html', user_id=user_id)
@bp.route('/settings')
def settings():
return render_template('settings.html')
@bp.route('/image/<request_id>')
def image(request_id):
# Check if request_id is valid
try:
request_id = int(request_id)
except ValueError:
abort(404)
result = onlylegsDB.getImage(request_id)
return render_template('image.html', fileName=result[1], id=request_id)

View file

@ -3,35 +3,25 @@ now = datetime.datetime.now()
import sys
import shutil
import os
import sass
class Sassy():
class compile():
def __init__(self, theme):
print("### OnlyLegs Theme Manager ###")
print(f"{now.hour}:{now.minute}:{now.second} - Loading theme...")
print(f"Loading '{theme}' theme...")
try:
import sass
except ImportError:
print("Could not find libsass!")
sys.exit(1)
theme_path = os.path.join('./user', 'themes', theme, 'style.scss')
font_path = os.path.join('./user', 'themes', theme, 'fonts')
theme_path = os.path.join('usr', 'themes', theme, 'style.scss')
print(f"Theme path: {theme_path}")
if os.path.exists(theme_path):
print(f"Theme '{theme}' found at:", theme_path)
self.sass = sass
self.loadTheme(theme_path)
self.loadFonts(font_path)
else:
print("No theme found!")
sys.exit(1)
font_path = os.path.join('usr', 'themes', theme, 'fonts')
if os.path.exists(font_path):
print("Fonts found at:", font_path)
self.loadFonts(font_path)
else:
print("No fonts found!")
print(f"{now.hour}:{now.minute}:{now.second} - Done!\n")
@ -41,24 +31,23 @@ class Sassy():
f.write(self.sass.compile(filename=theme, output_style='compressed'))
print("Compiled successfully to:", f.name)
except self.sass.CompileError as e:
print("Failed to compile!\nFull error:", e)
print("Failed to compile!\n", e)
sys.exit(1)
def loadFonts (self, font_path):
dest = os.path.join('static', 'theme', 'fonts')
dest = os.path.join('./static', 'theme', 'fonts')
if os.path.exists(dest):
print("Removing old fonts...")
try:
shutil.rmtree(dest)
print("Removed old fonts!")
except Exception as e:
print("Failed to remove old fonts!\nFull error:", e)
print("Failed to remove old fonts!\n", e)
sys.exit(1)
try:
shutil.copytree(font_path, dest)
print("Copied fonts to:", dest)
except Exception as e:
print("Failed to copy fonts!\nFull error:", e)
print("Failed to copy fonts!\n", e)
sys.exit(1)

View file

@ -14,21 +14,21 @@
<body>
<nav id="navRoot">
<div>
<a href="{{url_for('index')}}">
<a href="{{url_for('gallery.index')}}">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 -2 24 24" width="24" fill="currentColor">
<path d="M2 8v10h12V8H2zm2-2V2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-2v4a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h2zm2 0h8a2 2 0 0 1 2 2v4h2V2H6v4zm0 9a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"></path><path d="M7 6a3 3 0 1 1 6 0h-2a1 1 0 0 0-2 0H7zm1.864 13.518l2.725-4.672a1 1 0 0 1 1.6-.174l1.087 1.184 1.473-1.354-1.088-1.183a3 3 0 0 0-4.8.52L7.136 18.51l1.728 1.007zm6.512-12.969a2.994 2.994 0 0 1 3.285.77l1.088 1.183-1.473 1.354-1.087-1.184A1 1 0 0 0 16 8.457V8c0-.571-.24-1.087-.624-1.451z"></path>
</svg>
<span>Home</span>
</a>
<a href="{{url_for('group')}}">
<a href="{{url_for('gallery.groups')}}">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 -4 24 24" width="24" fill="currentColor">
<path d="M17 4H9.415l-.471-1.334A1.001 1.001 0 0 0 8 2H3a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1zm-6.17-2H17a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h5c1.306 0 2.417.835 2.83 2z"></path>
</svg>
<span>Groups</span>
</a>
<a href="{{url_for('upload')}}">
<a href="{{url_for('gallery.upload')}}">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -5 24 24" width="24" fill="currentColor">
<path d="M8 3.414v5.642a1 1 0 1 1-2 0V3.414L4.879 4.536A1 1 0 0 1 3.464 3.12L6.293.293a1 1 0 0 1 1.414 0l2.829 2.828A1 1 0 1 1 9.12 4.536L8 3.414zM1 12h12a1 1 0 0 1 0 2H1a1 1 0 0 1 0-2z"></path>
</svg>
@ -36,14 +36,14 @@
</a>
</div>
<div>
<a href="{{url_for('profile')}}">
<a href="{{url_for('gallery.profile')}}">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 -2 24 24" width="24" fill="currentColor">
<path d="M10 20C4.477 20 0 15.523 0 10S4.477 0 10 0s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm0-14a4 4 0 0 1 4 4v2a4 4 0 1 1-8 0V8a4 4 0 0 1 4-4zm0 2a2 2 0 0 0-2 2v2a2 2 0 1 0 4 0V8a2 2 0 0 0-2-2zM5.91 16.876a8.033 8.033 0 0 1-1.58-1.232 5.57 5.57 0 0 1 2.204-1.574 1 1 0 1 1 .733 1.86c-.532.21-.993.538-1.358.946zm8.144.022a3.652 3.652 0 0 0-1.41-.964 1 1 0 1 1 .712-1.868 5.65 5.65 0 0 1 2.284 1.607 8.032 8.032 0 0 1-1.586 1.225z"></path>
</svg>
<span>Profile</span>
</a>
<a href="{{url_for('settings')}}">
<a href="{{url_for('gallery.settings')}}">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-1 -2 24 24" width="24" fill="currentColor">
<path d="M9.815 3.094a3.467 3.467 0 0 1-2.78-1.09l-.084-.001a3.467 3.467 0 0 1-2.781 1.09 3.477 3.477 0 0 1-1.727 2.51 3.471 3.471 0 0 1 0 2.794 3.477 3.477 0 0 1 1.727 2.51 3.467 3.467 0 0 1 2.78 1.09h.084a3.467 3.467 0 0 1 2.78-1.09 3.477 3.477 0 0 1 1.727-2.51 3.471 3.471 0 0 1 0-2.794 3.477 3.477 0 0 1-1.726-2.51zM14 5.714a1.474 1.474 0 0 0 0 2.572l-.502 1.684a1.473 1.473 0 0 0-1.553 2.14l-1.443 1.122A1.473 1.473 0 0 0 8.143 14l-2.304-.006a1.473 1.473 0 0 0-2.352-.765l-1.442-1.131A1.473 1.473 0 0 0 .5 9.968L0 8.278a1.474 1.474 0 0 0 0-2.555l.5-1.69a1.473 1.473 0 0 0 1.545-2.13L3.487.77A1.473 1.473 0 0 0 5.84.005L8.143 0a1.473 1.473 0 0 0 2.358.768l1.444 1.122a1.473 1.473 0 0 0 1.553 2.14L14 5.714zm-5.812 9.198a7.943 7.943 0 0 0 2.342-.73 3.468 3.468 0 0 1-.087.215 3.477 3.477 0 0 1 1.727 2.51 3.467 3.467 0 0 1 2.78 1.09h.084a3.467 3.467 0 0 1 2.78-1.09 3.477 3.477 0 0 1 1.727-2.51 3.471 3.471 0 0 1 0-2.794 3.477 3.477 0 0 1-1.726-2.51 3.467 3.467 0 0 1-2.78-1.09h-.084l-.015.016a8.077 8.077 0 0 0 .002-2.016L16.144 6a1.473 1.473 0 0 0 2.358.768l1.444 1.122a1.473 1.473 0 0 0 1.553 2.14L22 11.714a1.474 1.474 0 0 0 0 2.572l-.502 1.684a1.473 1.473 0 0 0-1.553 2.14l-1.443 1.122a1.473 1.473 0 0 0-2.359.768l-2.304-.006a1.473 1.473 0 0 0-2.352-.765l-1.442-1.131a1.473 1.473 0 0 0-1.545-2.13l-.312-1.056zM7 10a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm8 8a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"></path>
</svg>

View file

@ -78,7 +78,7 @@
// Upload the information
$.ajax({
url: '/upload/form',
url: '/upload',
type: 'post',
data: formData,
contentType: false,
@ -89,7 +89,7 @@
});
// Empty values
$("#image").val("");
$("#file").val("");
$("#alt").val("");
$("#description").val("");
$("#tags").val("");

View file

@ -1,13 +1,9 @@
# DATABASE CONFIGURATION
DB_NAME = onlylegs
DB_USER = root
DB_PASS =
DB_HOST = localhost
DB_PORT =
# EMAIL CONFIGURATION
EMAIL_HOST = smtp.example.com
EMAIL_PORT = 465
EMAIL_HOST_USER = noreply@example.com
EMAIL_HOST_PASSWORD = supersecurepassword
EMAIL_USE_TLS = True
EMAIL_HOST = #smtp.gmail.com
EMAIL_PORT = #465
EMAIL_HOST_USER = #your email
EMAIL_HOST_PASSWORD = #your password
EMAIL_USE_TLS = #True
# FLASK SECRETE KEY, DONT LOOSE IT!!!!!!!
FLASK_SECRET = #your secret key