Skip to content

Commit

Permalink
added ability to upload images
Browse files Browse the repository at this point in the history
  • Loading branch information
Mole1424 committed Jan 15, 2024
1 parent 64707fb commit b8bae0a
Show file tree
Hide file tree
Showing 22 changed files with 200 additions and 94 deletions.
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ flask-sqlalchemy = "*"
markdown = "*"
werkzeug = "*"
flask-limiter = "*"
pillow = "*"

[dev-packages]

Expand Down
76 changes: 75 additions & 1 deletion Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 45 additions & 1 deletion app.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from functools import wraps
from logging import INFO, basicConfig, info, warning
from os import environ, getenv
from os import environ, getenv, path, getcwd, remove

from flask import Flask, redirect, render_template, request, session
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from markdown import markdown
from markupsafe import escape
from PIL import Image
from werkzeug.security import check_password_hash
from werkzeug.utils import secure_filename

from db_schema import Projects, db

Expand All @@ -29,6 +31,9 @@

app.secret_key = getenv("SECRET_KEY")

app.config["UPLOAD_FOLDER"] = getenv("PHOTO_LOC")
app.config["MAX_CONTENT_LENGTH"] = 16 * 1024 * 1024 # 16MB max upload size


def login_required(func): # decorator to restrict access to certain pages
@wraps(func)
Expand Down Expand Up @@ -255,6 +260,7 @@ def log_blog_change(ip: str, action: str, project_id: int, success: bool):

LOGIN_URL = "/" + getenv("LOGIN_URL")
LOGGINGIN_URL = "/" + getenv("LOGGINGIN_URL")
PHOTO_URL = "/" + getenv("PHOTO_URL")


@app.route(LOGIN_URL)
Expand All @@ -278,3 +284,41 @@ def logging_in():
f"{request.remote_addr} failed to log in with password {request.form['password']}"
)
return redirect(LOGIN_URL)


@app.route(PHOTO_URL, methods=["GET", "POST"])
@login_required
def upload_photo():
if (
request.method == "POST"
and check_password_hash(password, request.form["password"])
and "photo" in request.files
and request.files["photo"].filename != ""
):
photo = request.files["photo"]

if not photo.filename.endswith((".png", ".jpg", ".jpeg")): # checks file type
return "<h1>Invalid file type</h1>"

filename = secure_filename(photo.filename)
filepath = path.join(getcwd(), app.config["UPLOAD_FOLDER"][1:], filename)
# update filename if already exists
i = 1
while path.exists(filepath):
filename = f"{i}{filename}"
filepath = path.join(getcwd(), app.config["UPLOAD_FOLDER"][1:], filename)
i += 1
photo.save(filepath)

# check if image is valid
# done after save because some weird reason `Image.open(photo)` corrupts the image and I have no clue why
try:
Image.open(filepath).verify()
except Exception as e:
remove(filepath)
warning(f"{request.remote_addr} uploaded invalid image: {e}")
return "<h1>Invalid image</h1>"

info(f"{request.remote_addr} uploaded photo {filename}")
return f"<h1>Photo uploaded successfully to {filepath}</h1><img src='{app.config['UPLOAD_FOLDER']}{filename}' alt='uploaded photo'>"
return render_template("uploadphoto.html", action=PHOTO_URL)
2 changes: 2 additions & 0 deletions config_example.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
DB_URI;sqlite:///test.db
PHOTO_LOC;/path/to/img/
DB_PASSWORD;hashed-db-password
LOGGINGIN_URL;loggingin
LOGIN_URL;login
PHOTO_URL;photo
SECRET_KEY;secret-key
Binary file removed static/img/ApolloLogo.png
Binary file not shown.
Binary file removed static/img/WebDev.png
Binary file not shown.
Binary file removed static/img/XSSOhNo.jpg
Binary file not shown.
Binary file removed static/img/broken_embed_discord.png
Binary file not shown.
Binary file removed static/img/hairy_men.png
Binary file not shown.
Binary file removed static/img/logo.png
Binary file not shown.
Binary file removed static/img/migration_error_log.png
Binary file not shown.
Binary file removed static/img/warwick.png
Binary file not shown.
2 changes: 1 addition & 1 deletion templates/aboutme.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div class="aboutmecontainer">
<div class="aboutme{{'full' if not homepage}}">
<div class="aboutmelogocontainer">
<img src="../static/img/logo.png" alt="logo" class="aboutmelogo">
<img src="{{config['UPLOAD_FOLDER']}}logo.png" alt="logo" class="aboutmelogo">
</div>
<div class="aboutmetext">
{% if homepage %}
Expand Down
4 changes: 2 additions & 2 deletions templates/aboutmepage.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
{% block title %} About Joel {% endblock %}
{% block description %} About Joel Coulon {% endblock %}
{% block head %}
<link rel="stylesheet" href="../static/css/aboutme.css">
<meta property="og:image" content="https://joelcoulon.co.uk/static/images/logo.png">
<link rel="stylesheet" href="/static/css/aboutme.css">
<meta property="og:image" content="{{config['UPLOAD_FOLDER']}}logo.png">
<meta property="og:url" content="https://joelcoulon.com/aboutme">
{% endblock %}

Expand Down
8 changes: 4 additions & 4 deletions templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}{% endblock %}</title>
<meta property="og:title" content="{{self.title()}}">
<link rel="icon" href="/static/img/logo.png" type="image/icon type">
<link rel="icon" href="{{config['UPLOAD_FOLDER']}}logo.png" type="image/icon type">
<meta name="keywords" content="Joel, Coulon, Joel Coulon, Programming, University of Warwick">
<meta name="description" content="{% block description %}{% endblock%}">
<meta property="og:description" content="{{self.description()}}">
<link rel="stylesheet" href="../static/css/main.css">
<link rel="stylesheet" href="../static/css/navbar.css">
<link rel="stylesheet" href="/static/css/main.css">
<link rel="stylesheet" href="/static/css/navbar.css">
{% block head %}{% endblock %}
<meta property="og:type" content="{{ 'article' if 'projects' in request.url else 'website' }}" />
<meta property="og:locale" content="en_GB">
</head>

<body>
<nav class="navbar">
<a href="/" class="logo"><img src="../static/img/logo.png" alt="logo"></a>
<a href="/" class="logo"><img src="{{config['UPLOAD_FOLDER']}}logo.png" alt="logo"></a>
<ul class="navlinksleft">
<li class="navlink"><a href="/aboutme">About Me</a></li>
<li class="navlink"><a href="/projects">Projects</a></li>
Expand Down
109 changes: 35 additions & 74 deletions templates/editproject.html
Original file line number Diff line number Diff line change
@@ -1,74 +1,35 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title }} - Edit</title>
<link rel="icon" href="/static/img/logo.png" type="image/icon type">
<meta name="description" content="Website for Joel Coulon">
<meta name="keywords" content="Joel, Coulon, Joel Coulon, Mole1424, Programming, University of Warwick">
<link rel="stylesheet" href="../../static/css/main.css">
<link rel="stylesheet" href="../../static/css/navbar.css">
<link rel="stylesheet" href="../../static/css/editproject.css">
</head>

<body>
<nav class="navbar">
<a href="/" class="logo"><img src="../../static/img/logo.png" alt="logo"></a>
<ul class="navlinksleft">
<li class="navlink"><a href="/aboutme">About Me</a></li>
<li class="navlink"><a href="/projects">Projects</a></li>
</ul>
<ul class="navlinksright">
<li class="navlink">
<a href="https://github.com/Mole1424">
<svg xmlns="http://www.w3.org/2000/svg" class="navsvg" viewBox="0 0 100 100">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z"
fill="#fff" />
</svg>
</a>
</li>
<li class="navlink" id="lastnavlink">
<a href="mailto: joel@joelcoulon.com">
<svg xmlns="http://www.w3.org/2000/svg" class="navsvg" viewBox="10 12 100 100">
<path
d="M 0,27.283 V 24 a 8,8 0 0 1 8,-8 h 112 a 8,8 0 0 1 8,8 v 3.283 l -64,40 z m 66.12,48.11 a 4.004,4.004 0 0 1 -4.24,0 L 0,36.717 V 104 a 8,8 0 0 0 8,8 h 112 a 8,8 0 0 0 8,-8 V 36.717 Z"
fill="#fff" />
</svg>
</a>
</li>
</ul>
</nav>
<form action="{{ action }}" method="post" class="projectform">
{% if delete %}
<p>WARNING!!!! This cannot be undone</p>
{% else %}
<div class="field">
<label for="title">Title</label><br>
<input type="text" id="title" name="title" value="{{ title }}">
</div>
<div class="field">
<label for="description">Description</label><br>
<textarea id="description" name="description">{{ description }}</textarea>
</div>
<div class="field">
<label for="image">Image</label><br>
<input type="text" id="image" name="image" value="{{ image }}">
</div>
<div class="field">
<label for="blog">Blog</label><br>
<textarea id="blog" name="blog">{{ blog }}</textarea>
</div>
{% endif %}
<div class="field">
<label for="password">Password</label><br>
<input type="password" id="password" name="password">
</div>
<input type="submit" value="Submit" class="projectbutton">
</form>
</body>

</html>
{% extends "base.html" %}
{% block title %} {{title}} - Edit {% endblock %}
{% block description %} Edit a project {% endblock %}
{% block head %}
<link rel="stylesheet" href="/static/css/editproject.css">
{% endblock %}
{% block content %}
<form action="{{ action }}" method="post" class="projectform">
{% if delete %}
<p>WARNING!!!! This cannot be undone</p>
{% else %}
<div class="field">
<label for="title">Title</label><br>
<input type="text" id="title" name="title" value="{{ title }}">
</div>
<div class="field">
<label for="description">Description</label><br>
<textarea id="description" name="description">{{ description }}</textarea>
</div>
<div class="field">
<label for="image">Image</label><br>
<input type="text" id="image" name="image" value="{{ image }}">
</div>
<div class="field">
<label for="blog">Blog</label><br>
<textarea id="blog" name="blog">{{ blog }}</textarea>
</div>
{% endif %}
<div class="field">
<label for="password">Password</label><br>
<input type="password" id="password" name="password">
</div>
<input type="submit" value="Submit" class="projectbutton">
</form>
{% endblock %}
6 changes: 3 additions & 3 deletions templates/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
{% block title %} Joel Coulon {% endblock %}
{% block description %} Website for Joel Coulon {% endblock %}
{% block head %}
<link rel="stylesheet" href="../static/css/aboutme.css">
<link rel="stylesheet" href="../static/css/projects.css">
<meta property="og:image" content="https://joelcoulon.com/static/images/logo.png">
<link rel="stylesheet" href="/static/css/aboutme.css">
<link rel="stylesheet" href="/static/css/projects.css">
<meta property="og:image" content="{{config['UPLOAD_FOLDER']}}/logo.png">
<meta property="og:url" content="https://joelcoulon.com/">
{% endblock %}
{% block content %}
Expand Down
7 changes: 4 additions & 3 deletions templates/projectpage.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
{% block title %} {{ project.title }} {% endblock %}
{% block description %} {{ project.description }} {% endblock %}
{% block head %}
<link rel="stylesheet" href="../static/css/projectpage.css">
<link rel="stylesheet" href="/static/css/projectpage.css">
<meta property="og:image"
content="{{'https://joelcoulon.com' if not project.image.startswith('https://')}}{{ project.image }}">
content="{{config['UPLOAD_FOLDER'] if not project.image.startswith('https://')}}{{ project.image }}">
<meta property="og:url" content="https://joelcoulon.com/projects/{{ project.id }}">
{% endblock %}
{% block content %}
<article class="projectarticle">
<div class="imgtitle">
<img src="{{ project.image }}" alt="{{ project.title }}">
<img src="{{config['UPLOAD_FOLDER'] if not project.image.startswith('https://')}}{{ project.image }}"
alt="{{ project.title }}">
<div class="description">
<h1>{{ project.title }}</h1>
<p>{{ project.description }}</p>
Expand Down
Loading

0 comments on commit b8bae0a

Please sign in to comment.