Compare commits

..

14 Commits

Author SHA1 Message Date
0x01fe
c3f7cd5ac7 forgot to remove the endpoint 2024-07-11 15:35:23 -05:00
0x01fe
9cdd5f3da4 removed writing page 2024-07-11 15:34:59 -05:00
0x01fe
abc4574988 refactored how comments are handled to fit in with the posts class 2024-07-01 10:30:42 -05:00
0x01fe
8712b8734e fixed most endpoints 2024-07-01 09:52:38 -05:00
0x01fe
2542b6862c added some checks for user/comments files 2024-07-01 09:41:30 -05:00
0x01fe
724e0ac3d9 consolidated some pages 2024-07-01 09:35:53 -05:00
0x01fe
8d49357074 various changes making the website look better 2024-06-28 15:40:53 -05:00
0x01FE
022f41a883 fixed some bugs that i found when deploying 2024-06-26 18:03:12 -05:00
0x01fe
e69ec565f7 fixed post links and added comment stuff to posts page 2024-06-26 16:03:47 -05:00
0x01fe
caf3a7ac32 menu pathing changes 2024-06-26 15:58:05 -05:00
0x01fe
9cd68f4048 finished up the comments/user system 2024-06-26 15:53:17 -05:00
0x01fe
ce9c995a50 Merge branch 'main' into comments 2024-06-26 14:10:02 -05:00
0x01fe
76688b2d2c started working on the comments feature 2024-04-03 13:13:48 -05:00
0x01fe
f569620fce started adding the comment thing 2024-03-27 14:50:43 -05:00
19 changed files with 610 additions and 332 deletions

6
.gitignore vendored
View File

@ -11,6 +11,12 @@ docker-compose.yaml
# Ignore images in posts
*.jpg
*.png
# Flask Data & Config
*.ini
data
.flask_session
*.json
*.gif
# Writing

View File

@ -4,8 +4,6 @@ FROM python:3.12.2-slim-bookworm
RUN apt-get update && apt-get upgrade -y
RUN groupadd -r app && useradd -r -g app app
COPY . .
RUN python3 -m pip install --upgrade pip
@ -13,6 +11,4 @@ RUN python3 -m pip install -r requirements.txt
WORKDIR ./app
USER app
CMD ["python3", "-u", "app.py"]

View File

@ -2,17 +2,25 @@ import os
import glob
import configparser
import random
import base64
import datetime
import requests
import flask
import flask_wtf.csrf
import flask_session
import waitress
import markdown
from post import Post
import comment
import user
app = flask.Flask(__name__, static_url_path='', static_folder='static')
app.register_blueprint(comment.comments)
app.register_blueprint(user.user)
# CONFIG
CONFIG_PATH = "./config.ini"
config = configparser.ConfigParser()
config.read(CONFIG_PATH)
@ -23,11 +31,22 @@ STATUS_FILE = config['STATUS']['STATUS_FILE']
PORT = int(config['NETWORK']['PORT'])
DEV = int(config['NETWORK']['DEV'])
# CSRF Protect
app.config['SECRET_KEY'] = base64.b64decode(config["FLASK"]["SECRET"])
csrf = flask_wtf.csrf.CSRFProtect()
csrf.init_app(app)
# Session Setup
app.config['SESSION_TYPE'] = 'filesystem'
app.config['SESSION_FILE_DIR'] = './data/.flask_session/'
flask_session.Session(app)
MUSIC_API_TOKEN = config['AUTH']['MUSIC_API_TOKEN']
MUSIC_API_URL = config['NETWORK']['MUSIC_API_URL']
statuses = {}
def get_posts(category_filter : str | None = None) -> list[Post]:
def get_posts(category_filter : str | None = None) -> list[tuple[dict, list]]:
post_files = glob.glob(f'{POSTS_FOLDER}/*')
try:
post_files.remove(f'{POSTS_FOLDER}/POST_TEMPLATE.md')
@ -57,7 +76,12 @@ def get_posts(category_filter : str | None = None) -> list[Post]:
ordered_posts.append(most_recent)
posts.remove(most_recent)
return reversed(ordered_posts)
# Convert to dict
posts = []
for post in reversed(ordered_posts):
posts.append(post.__dict__)
return posts
def read_status_file() -> dict:
with open(STATUS_FILE, 'r', encoding='utf-8') as file:
@ -97,40 +121,57 @@ def index():
# Get posts
posts = get_posts()
post_bodies = []
for post in posts:
post_bodies.append(post.body)
if 'username' in flask.session:
user = flask.session['username']
else:
user = 'Anon'
# Get status
status = get_status()
return flask.render_template('index.html', posts=post_bodies, status=status)
# Setup Comment Form
form = comment.CommentForm()
return flask.render_template('index.html', posts=posts, status=status, form=form, user=user, title='0x01fe.net')
# Posts
@app.route('/post/<string:post_name>')
def post(post_name: str):
for post in get_posts():
if post.title.replace(' ', '-') == post_name:
return flask.render_template('index.html', posts=[post.body], status=get_status())
if post['title'] == post_name:
if 'username' in flask.session:
user = flask.session['username']
else:
user = 'Anon'
# Setup Comment Form
form = comment.CommentForm()
return flask.render_template('index.html', posts=[post], status=get_status(), form=form, user=user, title='0x01fe.net')
flask.abort(404)
# Games Page
@app.route('/games/')
def games():
# Category's Endpoint
@app.route('/category/<string:category>/')
def category_filter(category: str):
# Get posts
posts = get_posts(category_filter="games")
posts = get_posts(category_filter=category)
post_bodies = []
for post in posts:
post_bodies.append(post.body)
if 'username' in flask.session:
user = flask.session['username']
else:
user = 'Anon'
# Get status
status = get_status()
return flask.render_template('games.html', posts=post_bodies, status=status)
# Setup Comment Form
form = comment.CommentForm()
return flask.render_template('index.html', posts=posts, status=status, form=form, user=user, title=category.replace('-', ' '))
# Music Page
@app.route('/music/')
@ -139,9 +180,10 @@ def music():
# Get posts
posts = get_posts(category_filter="music")
post_bodies = []
for post in posts:
post_bodies.append(post.body)
if 'username' in flask.session:
user = flask.session['username']
else:
user = 'Anon'
# Get status
status = get_status()
@ -164,64 +206,30 @@ def music():
top_albums[album_index]['listen_time'] = hours
return flask.render_template('music.html', posts=post_bodies, status=status, top_albums=top_albums)
# Setup Comment Form
form = comment.CommentForm()
# Motion Pictures Page
@app.route('/motion-pictures/')
def motion_pictures():
# Get posts
posts = get_posts(category_filter="motion-pictures")
post_bodies = []
for post in posts:
post_bodies.append(post.body)
# Get status
status = get_status()
return flask.render_template('motion-pictures.html', posts=post_bodies, status=status)
return flask.render_template('music.html', posts=posts, status=status, top_albums=top_albums, form=form, user=user)
# Programming Page
@app.route('/programming/')
def programming():
# Get posts
posts = get_posts(category_filter="programming")
posts_and_comments = get_posts(category_filter="programming")
post_bodies = []
for post in posts:
post_bodies.append(post.body)
if 'username' in flask.session:
user = flask.session['username']
else:
user = 'Anon'
# Get status
status = get_status()
return flask.render_template('programming.html', posts=post_bodies, status=status)
@app.route('/writing/')
def writing():
works = []
# Get all works in writing folder
files = glob.glob(WRITING_FOLDER + '*')
for path in files:
date: str = datetime.datetime.fromtimestamp(os.path.getctime(path)).strftime("%B %d, %Y")
name: str = path.split('/')[-1]
works.append({
'date' : date,
'name' : name,
'path' : path
})
return flask.render_template('writing.html', works=works)
# Setup Comment Form
form = comment.CommentForm()
return flask.render_template('programming.html', posts=posts_and_comments, form=form, user=user, status=status)
# About Page
@app.route('/about/')

61
app/comment.py Normal file
View File

@ -0,0 +1,61 @@
import json
import os
import flask
import flask_wtf.csrf
import wtforms
COMMENTS_PATH = "./data/comments.json"
comments = flask.Blueprint('comment', __name__, template_folder='./templates')
class CommentForm(flask_wtf.FlaskForm):
textbox = wtforms.TextAreaField('Input')
@comments.route('/comment/<string:post_title>', methods=['POST'])
def comment(post_title: str):
form = CommentForm(csrf_enabled=True)
save_comment(form.textbox.data, post_title)
return flask.redirect('/')
def save_comment(content: str, post_title: str):
with open(COMMENTS_PATH, 'r') as file:
comment_data = json.loads(file.read())
# See if user is logged in, otherwise setup as anon
if 'username' in flask.session:
username = flask.session['username']
else:
username = 'Anon'
comment = {
"username" : username,
"content" : content
}
# Add comment to JSON data
if post_title in comment_data:
comment_data[post_title].append(comment)
else:
comment_data[post_title] = [comment]
# Save JSON data
with open(COMMENTS_PATH, 'w') as file:
file.write(json.dumps(comment_data))
def get_comments(post_title : int) -> list[dict]:
with open(COMMENTS_PATH, 'r') as file:
comment_data = json.loads(file.read())
if post_title in comment_data:
return comment_data[post_title]
else:
return []
# Check Comments file exists
if not os.path.exists(COMMENTS_PATH):
with open(COMMENTS_PATH, 'w+') as file:
file.write('{}')

View File

@ -1,15 +1,19 @@
import markdown
import datetime
import comment
class Post:
category : str
author : str
date : datetime.datetime
date_str : str
body : str
file : str
title : str
url : str
comments : list[dict]
def __init__(self, file_path):
self.file = file_path
@ -19,11 +23,12 @@ class Post:
self.category = lines[1].split(":")[1].strip()
self.author = lines[2].split(":")[1].strip()
self.title = lines[6][2:-1]
self.url = '/post/' + self.title.replace(' ', '-')
self.title = lines[6].replace('#', '').strip()
self.url = '/post/' + self.title
date = lines[3].split(":")[1].strip()
self.date = datetime.datetime.strptime(date, "%d-%m-%Y")
self.date_str = self.date.strftime("%B %d, %Y")
self.body = markdown.markdown(f'# [{self.title}]({self.url})\n' + ''.join(lines[7:]))
self.body = markdown.markdown(f'# [{self.title}]({self.url})\n' + ''.join(lines[7:]), extensions=['footnotes'])
self.comments = comment.get_comments(self.title)

View File

@ -4,6 +4,6 @@ author: author
date: date
# POST
## TITLE
# TITLE
### DATE OR SUBTITLE
POST TEXT

View File

@ -101,6 +101,7 @@ Buildings that you know // People come and go // Are a certain way
And then you get the news that obliterates your view // Amputate your truths // The signifiance has changed
Hospital inane // Meaningless and grey // But lie within the walls and the signifiance will change
What would it take for us to change the game? // Maybe our existence is signifiance in vain
Is that what we consider changing? // Ah, save me
# Candles by King Gizzard & The Lizard Wizard
This little man is too hot to handle // Set the funeral on fire with the candles
@ -110,37 +111,3 @@ My little heart, as cold as a morgue // Let the weight of it drop like an iceber
# Presumptuous by King Gizzard & The Lizard Wizard
Eggshell, landmine, stepping stones // Kindred spirits at a crossroads
The world we built is on a tilt // Bottled up inside and filled with guilt
# Mountians Made of Steam by Silver Mt. Zion
The angels in your palm // Sing gentle worried songs
The sweetness of our dreams // Like mountains made of steam
# God Bless our Dead Marines by Silver Mt. Zion
They put angels in the electric chair, The electric chair, the electric chair
Straight up angels in the electric chair, The electric chair, the electric chair
And no one knew or no one cared // But burning stars lit up their hair
Someone had an accident above the burning trees // While somewhere distant, peacefully // Our vulgar leaders sleep
There's fresh meat in the club tonight // God bless our dead marines
When the world is sick // Can't no one be well? // But I dreamt we was all beautiful and strong
# Cam Girl / Cage Girl by Jane Remover
I peel my eyes open, everyone knows, and nobody cares
You're biting chunks out of my face, say it's the same
# Unbirthing by Cynthoni
The sonic recreation of its death // echoing through the artificial abyss
It must be liquidated in content // for a dying population addicted to its own descrution
it is blood that greases the gears of our beloved death machines // and you will be its gasoline
# You don't even know who I am by underscores
Everybody has bad days! Don't worry! It's not the end of the world! There's always tomorrow!
Today is the worst day of my life // I think I'm in love with the cards // You're were dealt
Today is the best day of my life // I invited myself in and wore your clothes // Took your pills // Cried your makeup off
And for once, I felt just like you
# Experimental Skin by Jane Remover
Allez, allez
Come touch it, see no evil // Come touch it, see no evil
Bitches don't know what to call it, I'm like 3 and 0
I can't hear you over the band // I wanna sin, blow the city up // I wanna sin, blow the city up // I wanna sin, blow the city up
Think I became a part of you // Who care? I'm just a robot to you

View File

@ -19,6 +19,10 @@ html {
--primary20: hsla(209, 61%, 71%, 20%);
--primary40: hsla(209, 61%, 71%, 40%);
--secondary: hsl(277, 81%, 33%);
--secondary10: hsla(277, 81%, 33%, 10%);
--secondary20: hsla(277, 81%, 33%, 20%);
--secondary30: hsla(277, 81%, 33%, 30%);
--secondary40: hsla(277, 81%, 33%, 40%);
--secondary50: hsla(277, 81%, 33%, 50%);
--accent: hsl(291, 81%, 60%);
--accent75: hsla(291, 81%, 60%, 75%);
@ -43,7 +47,24 @@ a:hover {
color: var(--accent);
}
blockquote {
background-color: var(--secondary10);
border-style: var(--borders-style);
border-radius: 7.5px;
padding: 0.25em;
}
.post blockquote p {
text-indent: 1.5em;
}
.post blockquote li p {
text-indent: 0;
}
li {
margin-left: 4em;
}
/* Other */
@ -206,6 +227,50 @@ a:hover {
text-indent: 3em;
}
.post-date {
float: right;
}
.comment-container {
background-color: var(--primary40);
border-style: var(--borders-style);
border-radius: var(--border-radius);
padding: 1em;
margin: 1em;
}
.comment {
background-color: var(--primary40);
border-style: var(--borders-style);
border-radius: 5px;
margin: 0.25em;
padding: 0.25em;
}
.comment h4 {
margin: 0.25em;
}
.comment p {
margin: 0.25em;
text-indent: 1em;
}
.comment-editor textarea {
width: 80%;
height: 6em;
padding: 0.75em;
border-style: solid;
border-color: var(--secondary50);
}
.comment-editor textarea:focus {
border: 3px solid var(--accent);
}
/* MUSIC */
.albums {
height: fit-content;

View File

@ -13,13 +13,13 @@
<div class="container">
<!-- Sidebar -->
<div class="sidebar">
<a href="..">Home</a><br>
<a href="../games/">Games</a><br>
<a href="../music/">Music</a><br>
<a href="../motion-pictures/">Motion Picture</a><br>
<a href="../programming/">Programming</a><br>
<a href="/writing/">Writing</a><br>
<a href="."><u>About</u></a>
<a href="/"><u>Home</u></a><br>
<a href="/category/games/">Games</a><br>
<a href="/music/">Music</a><br>
<a href="/category/motion-pictures/">Motion Picture</a><br>
<a href="/programming/">Programming</a><br>
<a href="/about/">About</a><br>
<a href="/login/">Login</a>
</div>
<!-- Main Page -->

View File

@ -1,34 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<header>
<link rel="shortcut icon" href="index_favicon.ico">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<title>0x01fe.net - Games</title>
</header>
<body>
<div class="header">
<h1>Games</h1>
{{ status|safe }}
</div>
<div class="container">
<!-- Sidebar -->
<div class="sidebar">
<a href="..">Home</a><br>
<a href="."><u>Games</u></a><br>
<a href="../music/">Music</a><br>
<a href="../motion-pictures/">Motion Picture</a><br>
<a href="../programming/">Programming</a><br>
<a href="/writing/">Writing</a><br>
<a href="../about/">About</a>
</div>
<!-- Main Page -->
<!-- Get it? D-Log? Like digital log? -->
<div class="dlog">
{% for post in posts %}
<div class="post">{{ post|safe }}</div>
{% endfor %}
</div>
</div>
</body>
</html>

View File

@ -3,30 +3,54 @@
<header>
<link rel="shortcut icon" href="index_favicon.ico">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<title>0x01fe.net</title>
<title>0x01fe.net - {{ title }}</title>
</header>
<body>
<div class="header">
<h1>0x01fe.net</h1>
<h1>{{ title }}</h1>
{{ status|safe }}
</div>
<div class="container">
<!-- Sidebar -->
<div class="sidebar">
<a href="."><u>Home</u></a><br>
<a href="/games/">Games</a><br>
<a href="/"><u>Home</u></a><br>
<a href="/category/games/">Games</a><br>
<a href="/music/">Music</a><br>
<a href="/motion-pictures/">Motion Picture</a><br>
<a href="/category/motion-pictures/">Motion Picture</a><br>
<a href="/programming/">Programming</a><br>
<a href="/writing/">Writing</a><br>
<a href="/about/">About</a>
<a href="/about/">About</a><br>
<a href="/login/">Login</a>
</div>
<!-- Main Page -->
<!-- Get it? D-Log? Like digital log? -->
<div class="dlog">
{% for post in posts %}
<div class="post">{{ post|safe }}</div>
<div class="post">
<div class="post-date">
{{ post.date_str }}
</div>
{{ post.body|safe }}
<div class="comment-container">
<h2>Comments</h2>
{% for comment in post.comments %}
<div class="comment">
<h4>{{ comment.username }}</h4>
<p>{{ comment.content }}</p>
</div>
{% endfor %}
{% if user %}
<div class="comment-editor">
<h4>{{ user }}</h4>
<form method="post" action="/comment/{{ post.title }}">
{{ form.hidden_tag() }}
{{ form.textbox }}
<input type="submit" value="Save">
</form>
</div>
{% endif %}
</div>
</div>
{% endfor %}
</div>
</div>

View File

@ -1,34 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<header>
<link rel="shortcut icon" href="index_favicon.ico">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<title>0x01fe.net - Motion Pictures</title>
</header>
<body>
<div class="header">
<h1>Motion Pictures</h1>
{{ status|safe }}
</div>
<div class="container">
<!-- Sidebar -->
<div class="sidebar">
<a href="..">Home</a><br>
<a href="../games/">Games</a><br>
<a href="../music/">Music</a><br>
<a href="."><u>Motion Picture</u></a><br>
<a href="../programming/">Programming</a><br>
<a href="/writing/">Writing</a><br>
<a href="../about/">About</a>
</div>
<!-- Main Page -->
<!-- Get it? D-Log? Like digital log? -->
<div class="dlog">
{% for post in posts %}
<div class="post">{{ post|safe }}</div>
{% endfor %}
</div>
</div>
</body>
</html>

View File

@ -13,20 +13,44 @@
<div class="container">
<!-- Sidebar -->
<div class="sidebar">
<a href="..">Home</a><br>
<a href="../games/">Games</a><br>
<a href="."><u>Music</u></a><br>
<a href="../motion-pictures/">Motion Picture</a><br>
<a href="../programming/">Programming</a><br>
<a href="/writing/">Writing</a><br>
<a href="../about/">About</a>
<a href="/"><u>Home</u></a><br>
<a href="/category/games/">Games</a><br>
<a href="/music/">Music</a><br>
<a href="/category/motion-pictures/">Motion Picture</a><br>
<a href="/programming/">Programming</a><br>
<a href="/about/">About</a><br>
<a href="/login/">Login</a>
</div>
<!-- Main Page -->
<!-- Get it? D-Log? Like digital log? -->
<div class="dlog">
{% for post in posts %}
<div class="post">{{ post|safe }}</div>
<div class="post">
<div class="post-date">
{{ post.date_str }}
</div>
{{ post.body|safe }}
<div class="comment-container">
<h2>Comments</h2>
{% for comment in post.comments %}
<div class="comment">
<h4>{{ comment.username }}</h4>
<p>{{ comment.content }}</p>
</div>
{% endfor %}
{% if user %}
<div class="comment-editor">
<h4>{{ user }}</h4>
<form method="post" action="/comment/{{ post.title }}">
{{ form.hidden_tag() }}
{{ form.textbox }}
<input type="submit" value="Save">
</form>
</div>
{% endif %}
</div>
</div>
{% endfor %}
</div>

View File

@ -13,20 +13,44 @@
<div class="container">
<!-- Sidebar -->
<div class="sidebar">
<a href="..">Home</a><br>
<a href="../games/">Games</a><br>
<a href="../music/">Music</a><br>
<a href="../motion-pictures/">Motion Picture</a><br>
<a href="."><u>Programming</u></a><br>
<a href="/writing/">Writing</a><br>
<a href="../about/">About</a>
<a href="/"><u>Home</u></a><br>
<a href="/category/games/">Games</a><br>
<a href="/music/">Music</a><br>
<a href="/category/motion-pictures/">Motion Picture</a><br>
<a href="/programming/">Programming</a><br>
<a href="/about/">About</a><br>
<a href="/login/">Login</a>
</div>
<!-- Main Page -->
<!-- Get it? D-Log? Like digital log? -->
<div class="dlog">
{% for post in posts %}
<div class="post">{{ post|safe }}</div>
<div class="post">
<div class="post-date">
{{ post.date_str }}
</div>
{{ post.body|safe }}
<div class="comment-container">
<h2>Comments</h2>
{% for comment in post.comments %}
<div class="comment">
<h4>{{ comment.username }}</h4>
<p>{{ comment.content }}</p>
</div>
{% endfor %}
{% if user %}
<div class="comment-editor">
<h4>{{ user }}</h4>
<form method="post" action="/comment/{{ post.title }}">
{{ form.hidden_tag() }}
{{ form.textbox }}
<input type="submit" value="Save">
</form>
</div>
{% endif %}
</div>
</div>
{% endfor %}
</div>

View File

@ -0,0 +1,40 @@
<!DOCTYPE html>
<html lang="en">
<header>
<link rel="shortcut icon" href="index_favicon.ico">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<title>0x01fe.net - Login</title>
</header>
<body>
<div class="header">
<h1>0x01fe.net</h1>
{{ status|safe }}
</div>
<div class="container">
<!-- Sidebar -->
<div class="sidebar">
<a href="/"><u>Home</u></a><br>
<a href="/games/">Games</a><br>
<a href="/music/">Music</a><br>
<a href="/motion-pictures/">Motion Picture</a><br>
<a href="/programming/">Programming</a><br>
<a href="/about/">About</a><br>
<a href="/login/">Login</a>
</div>
<div class="dlog">
<h1>Login</h1>
<form method="post" action="/user/login/">
{{ form.hidden_tag() }}
Username: {{ form.username }} <br>
Password: {{ form.password }} <br>
<input type="submit" value="Login">
</form>
<br>
<h1>Need to Register?</h1>
<a href="/user/register/">Register</a>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="en">
<header>
<link rel="shortcut icon" href="index_favicon.ico">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<title>0x01fe.net - Register</title>
</header>
<body>
<div class="header">
<h1>0x01fe.net</h1>
{{ status|safe }}
</div>
<div class="container">
<!-- Sidebar -->
<div class="sidebar">
<a href="/"><u>Home</u></a><br>
<a href="/games/">Games</a><br>
<a href="/music/">Music</a><br>
<a href="/motion-pictures/">Motion Picture</a><br>
<a href="/programming/">Programming</a><br>
<a href="/about/">About</a><br>
<a href="/login/">Login</a>
</div>
<div class="dlog">
<h1>Register</h1>
<form method="post" action="/user/add/">
{{ form.hidden_tag() }}
Username: {{ form.username }} <br>
Password: {{ form.password }} <br>
<input type="submit" value="Register">
</form>
</div>
</div>
</body>
</html>

View File

@ -1,14 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<body>
<a href="/">home</a>
<p>
This is just a little page where I post stuff I write. I was kind of unsure if I wanted this stuff out here but I think to those who know me it could serve as an interesting view into some thoughts that I don't often express elsewhere.
</p>
<br>
<br>
{% for work in works %}
<a href="/{{ work.path }}">{{ work.name }}</a> {{ work.date }}
{% endfor %}
</body>
</html>

102
app/user.py Normal file
View File

@ -0,0 +1,102 @@
import base64
import json
import os
import flask
import flask_wtf.csrf
import wtforms
user = flask.Blueprint('user', __name__, template_folder='./templates/user')
USERS_PATH = "./data/users.json"
class RegisterUserForm(flask_wtf.FlaskForm):
username = wtforms.StringField("Username", [
wtforms.validators.Length(min=4, max=32),
wtforms.validators.DataRequired()
])
password = wtforms.PasswordField("Password", [
wtforms.validators.Length(min=8, max=64),
wtforms.validators.DataRequired()
])
class LoginUserForm(flask_wtf.FlaskForm):
username = wtforms.StringField("Username", [
wtforms.validators.DataRequired()
])
password = wtforms.PasswordField("Password", [
wtforms.validators.DataRequired()
])
@user.route('/user/add/', methods=["POST"])
def add_user():
# Get form data
form = RegisterUserForm(csrf_enabled=True)
username = form.username.data
password = form.password.data
# Read existing user data
with open(USERS_PATH, 'r') as file:
user_data = json.loads(file.read())
# check if user exists
if username in user_data:
return 'ERROR PROCESSING REQUEST - That user already exists'
# Store password / server side cookie
user_data[username] = base64.b64encode(password.encode()).decode()
flask.session['username'] = username
# Write user data
with open(USERS_PATH, 'w') as file:
file.write(json.dumps(user_data))
return flask.redirect('/')
@user.route('/user/register/')
def register_page():
form = RegisterUserForm()
return flask.render_template('register.html', form=form)
@user.route('/user/login/', methods=["POST"])
def login_user():
form = LoginUserForm(csrf_enabled=True)
username = form.username.data
password = base64.b64encode(form.password.data.encode()).decode()
# Read existing user data
with open(USERS_PATH, 'r') as file:
user_data = json.loads(file.read())
# check if user exists
if username not in user_data:
return 'ERROR PROCESSING REQUEST - Bad username OR password'
# Does password match?
if user_data[username] != password:
return 'ERROR PROCESSING REQUEST - Bad username OR password'
flask.session['username'] = username
return flask.redirect('/')
@user.route('/login/')
def login_page():
form = LoginUserForm()
return flask.render_template('login.html', form=form)
@user.route('/logout/')
def logout_user():
if 'username' in flask.session:
flask.session.pop('username')
return flask.redirect('/')
# Check User file exists
if not os.path.exists(USERS_PATH):
with open(USERS_PATH, 'w+') as file:
file.write('{}')

View File

@ -2,4 +2,6 @@ Markdown==3.5.2
Flask==2.2.3
waitress==2.1.2
Werkzeug==2.2.3
Flask-Session==0.5.0
Flask-WTF==1.1.1
requests==2.31.0