finished up the comments/user system
This commit is contained in:
parent
ce9c995a50
commit
9cd68f4048
2
.gitignore
vendored
2
.gitignore
vendored
@ -15,6 +15,8 @@ docker-compose.yaml
|
|||||||
# Flask Data & Config
|
# Flask Data & Config
|
||||||
*.ini
|
*.ini
|
||||||
data
|
data
|
||||||
|
.flask_session
|
||||||
|
*.json
|
||||||
*.gif
|
*.gif
|
||||||
|
|
||||||
# Writing
|
# Writing
|
||||||
|
|||||||
27
app/app.py
27
app/app.py
@ -116,12 +116,21 @@ def index():
|
|||||||
# Get posts
|
# Get posts
|
||||||
posts = get_posts()
|
posts = get_posts()
|
||||||
|
|
||||||
# Get Comments
|
if 'username' in flask.session:
|
||||||
comments = []
|
user = flask.session['username']
|
||||||
|
else:
|
||||||
|
user = 'Anon'
|
||||||
|
|
||||||
|
# Get Comments
|
||||||
posts_and_comments = []
|
posts_and_comments = []
|
||||||
for post in posts:
|
for post in posts:
|
||||||
posts_and_comments.append((post.body, comments))
|
|
||||||
|
comments = comment.get_comments(post.title)
|
||||||
|
posts_and_comments.append(({
|
||||||
|
"body" : post.body,
|
||||||
|
"title" : post.title
|
||||||
|
},
|
||||||
|
comments))
|
||||||
|
|
||||||
# Get status
|
# Get status
|
||||||
status = get_status()
|
status = get_status()
|
||||||
@ -129,17 +138,7 @@ def index():
|
|||||||
# Setup Comment Form
|
# Setup Comment Form
|
||||||
form = comment.CommentForm()
|
form = comment.CommentForm()
|
||||||
|
|
||||||
return flask.render_template('index.html', posts=posts_and_comments, status=status, form=form, user="yes")
|
return flask.render_template('index.html', posts=posts_and_comments, status=status, form=form, user=user)
|
||||||
|
|
||||||
# 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())
|
|
||||||
|
|
||||||
flask.abort(404)
|
|
||||||
|
|
||||||
# Posts
|
# Posts
|
||||||
@app.route('/post/<string:post_name>')
|
@app.route('/post/<string:post_name>')
|
||||||
|
|||||||
@ -1,22 +1,56 @@
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
import flask_session
|
|
||||||
import flask_wtf.csrf
|
import flask_wtf.csrf
|
||||||
import wtforms
|
import wtforms
|
||||||
|
|
||||||
|
COMMENTS_PATH = "./data/comments.json"
|
||||||
comments = flask.Blueprint('comment', __name__, template_folder='./templates')
|
comments = flask.Blueprint('comment', __name__, template_folder='./templates')
|
||||||
|
|
||||||
class CommentForm(flask_wtf.FlaskForm):
|
class CommentForm(flask_wtf.FlaskForm):
|
||||||
textbox = wtforms.TextAreaField('Input')
|
textbox = wtforms.TextAreaField('Input')
|
||||||
|
|
||||||
@comments.route('/comment/', methods=['POST'])
|
@comments.route('/comment/<string:post_title>', methods=['POST'])
|
||||||
def comment():
|
def comment(post_title: str):
|
||||||
form = CommentForm(csrf_enabled=True)
|
form = CommentForm(csrf_enabled=True)
|
||||||
|
|
||||||
|
save_comment(form.textbox.data, post_title)
|
||||||
|
|
||||||
return flask.redirect('/')
|
return flask.redirect('/')
|
||||||
|
|
||||||
|
def save_comment(content: str, post_title: str):
|
||||||
|
with open(COMMENTS_PATH, 'r') as file:
|
||||||
|
comment_data = json.loads(file.read())
|
||||||
|
|
||||||
def get_comments(post_id : int) -> list[dict]:
|
# 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 []
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"2" : [
|
|
||||||
{
|
|
||||||
"username" : "0x01FE",
|
|
||||||
"content" : "Hello, this is an example comment!"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"users" : {
|
|
||||||
"0x01FE" : "cGFzc3dvcmQ="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -8,7 +8,6 @@ class Post:
|
|||||||
date : datetime.datetime
|
date : datetime.datetime
|
||||||
body : str
|
body : str
|
||||||
file : str
|
file : str
|
||||||
id : int
|
|
||||||
title : str
|
title : str
|
||||||
url : str
|
url : str
|
||||||
|
|
||||||
@ -20,13 +19,11 @@ class Post:
|
|||||||
|
|
||||||
self.category = lines[1].split(":")[1].strip()
|
self.category = lines[1].split(":")[1].strip()
|
||||||
self.author = lines[2].split(":")[1].strip()
|
self.author = lines[2].split(":")[1].strip()
|
||||||
self.title = lines[6][2:-1]
|
self.title = lines[6].replace('#', '').strip()
|
||||||
self.url = '/post/' + self.title.replace(' ', '-')
|
self.url = '/post/' + self.title.replace(' ', '-')
|
||||||
|
|
||||||
date = lines[3].split(":")[1].strip()
|
date = lines[3].split(":")[1].strip()
|
||||||
self.date = datetime.datetime.strptime(date, "%d-%m-%Y")
|
self.date = datetime.datetime.strptime(date, "%d-%m-%Y")
|
||||||
|
|
||||||
self.id = int(lines[4].split(":")[1].strip())
|
|
||||||
|
|
||||||
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:]))
|
||||||
|
|
||||||
|
|||||||
@ -216,13 +216,12 @@ a:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.comment-editor textarea {
|
.comment-editor textarea {
|
||||||
width: 100%;
|
width: 80%;
|
||||||
height: 6em;
|
height: 6em;
|
||||||
padding: 0.75em;
|
padding: 0.75em;
|
||||||
|
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-color: var(--secondary50);
|
border-color: var(--secondary50);
|
||||||
border-radius: var(--border-radius);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment-editor textarea:focus {
|
.comment-editor textarea:focus {
|
||||||
|
|||||||
@ -19,7 +19,8 @@
|
|||||||
<a href="../motion-pictures/">Motion Picture</a><br>
|
<a href="../motion-pictures/">Motion Picture</a><br>
|
||||||
<a href="../programming/">Programming</a><br>
|
<a href="../programming/">Programming</a><br>
|
||||||
<a href="/writing/">Writing</a><br>
|
<a href="/writing/">Writing</a><br>
|
||||||
<a href="."><u>About</u></a>
|
<a href="."><u>About</u></a><br>
|
||||||
|
<a href="/login/">Login</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Main Page -->
|
<!-- Main Page -->
|
||||||
|
|||||||
@ -19,7 +19,8 @@
|
|||||||
<a href="../motion-pictures/">Motion Picture</a><br>
|
<a href="../motion-pictures/">Motion Picture</a><br>
|
||||||
<a href="../programming/">Programming</a><br>
|
<a href="../programming/">Programming</a><br>
|
||||||
<a href="/writing/">Writing</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>
|
</div>
|
||||||
|
|
||||||
<!-- Main Page -->
|
<!-- Main Page -->
|
||||||
|
|||||||
@ -19,7 +19,8 @@
|
|||||||
<a href="/motion-pictures/">Motion Picture</a><br>
|
<a href="/motion-pictures/">Motion Picture</a><br>
|
||||||
<a href="/programming/">Programming</a><br>
|
<a href="/programming/">Programming</a><br>
|
||||||
<a href="/writing/">Writing</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>
|
</div>
|
||||||
|
|
||||||
<!-- Main Page -->
|
<!-- Main Page -->
|
||||||
@ -27,15 +28,19 @@
|
|||||||
<div class="dlog">
|
<div class="dlog">
|
||||||
{% for post in posts %}
|
{% for post in posts %}
|
||||||
<div class="post">
|
<div class="post">
|
||||||
{{ post[0]|safe }}
|
{{ post[0].body|safe }}
|
||||||
<div class="comment-container">
|
<div class="comment-container">
|
||||||
{% for comment in post[1] %}
|
{% for comment in post[1] %}
|
||||||
<div class="comment">{{ comment|safe }}</div>
|
<div class="comment">
|
||||||
|
<h4>{{ comment.username }}</h4>
|
||||||
|
<p>{{ comment.content }}</p>
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% if user %}
|
{% if user %}
|
||||||
<div class="comment-editor">
|
<div class="comment-editor">
|
||||||
<h3>{{ user }}</h3>
|
<h3>{{ user }}</h3>
|
||||||
<form method="post" action="/comment/">
|
<form method="post" action="/comment/{{ post[0].title }}">
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
{{ form.textbox }}
|
{{ form.textbox }}
|
||||||
<input type="submit" value="Save">
|
<input type="submit" value="Save">
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@ -19,7 +19,8 @@
|
|||||||
<a href="."><u>Motion Picture</u></a><br>
|
<a href="."><u>Motion Picture</u></a><br>
|
||||||
<a href="../programming/">Programming</a><br>
|
<a href="../programming/">Programming</a><br>
|
||||||
<a href="/writing/">Writing</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>
|
</div>
|
||||||
|
|
||||||
<!-- Main Page -->
|
<!-- Main Page -->
|
||||||
|
|||||||
@ -19,7 +19,8 @@
|
|||||||
<a href="../motion-pictures/">Motion Picture</a><br>
|
<a href="../motion-pictures/">Motion Picture</a><br>
|
||||||
<a href="../programming/">Programming</a><br>
|
<a href="../programming/">Programming</a><br>
|
||||||
<a href="/writing/">Writing</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>
|
</div>
|
||||||
|
|
||||||
<!-- Main Page -->
|
<!-- Main Page -->
|
||||||
|
|||||||
@ -19,7 +19,8 @@
|
|||||||
<a href="../motion-pictures/">Motion Picture</a><br>
|
<a href="../motion-pictures/">Motion Picture</a><br>
|
||||||
<a href="."><u>Programming</u></a><br>
|
<a href="."><u>Programming</u></a><br>
|
||||||
<a href="/writing/">Writing</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>
|
</div>
|
||||||
|
|
||||||
<!-- Main Page -->
|
<!-- Main Page -->
|
||||||
|
|||||||
40
app/templates/user/login.html
Normal file
40
app/templates/user/login.html
Normal 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>
|
||||||
@ -13,22 +13,22 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<a href="."><u>Home</u></a><br>
|
<a href="/"><u>Home</u></a><br>
|
||||||
<a href="./games/">Games</a><br>
|
<a href="/games/">Games</a><br>
|
||||||
<a href="./music/">Music</a><br>
|
<a href="/music/">Music</a><br>
|
||||||
<a href="./motion-pictures/">Motion Picture</a><br>
|
<a href="/motion-pictures/">Motion Picture</a><br>
|
||||||
<a href="./programming/">Programming</a><br>
|
<a href="/programming/">Programming</a><br>
|
||||||
<a href="./about/">About</a>
|
<a href="/about/">About</a><br>
|
||||||
|
<a href="/login/">Login</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Main Page -->
|
|
||||||
<!-- Get it? D-Log? Like digital log? -->
|
|
||||||
<div class="dlog">
|
<div class="dlog">
|
||||||
<h1>Register</h1>
|
<h1>Register</h1>
|
||||||
<form method="post" action="/user/register/">
|
<form method="post" action="/user/add/">
|
||||||
{{ form.username }}
|
{{ form.hidden_tag() }}
|
||||||
{{ form.password }}
|
Username: {{ form.username }} <br>
|
||||||
<input type="submit" value="Register">
|
Password: {{ form.password }} <br>
|
||||||
|
<input type="submit" value="Register">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
77
app/user.py
77
app/user.py
@ -1,9 +1,12 @@
|
|||||||
|
import base64
|
||||||
|
import json
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
import flask_wtf.csrf
|
import flask_wtf.csrf
|
||||||
import wtforms
|
import wtforms
|
||||||
|
|
||||||
user = flask.Blueprint('user', __name__, template_folder='./templates/user')
|
user = flask.Blueprint('user', __name__, template_folder='./templates/user')
|
||||||
|
USERS_PATH = "./data/users.json"
|
||||||
class RegisterUserForm(flask_wtf.FlaskForm):
|
class RegisterUserForm(flask_wtf.FlaskForm):
|
||||||
username = wtforms.StringField("Username", [
|
username = wtforms.StringField("Username", [
|
||||||
wtforms.validators.Length(min=4, max=32),
|
wtforms.validators.Length(min=4, max=32),
|
||||||
@ -14,12 +17,80 @@ class RegisterUserForm(flask_wtf.FlaskForm):
|
|||||||
wtforms.validators.DataRequired()
|
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"])
|
@user.route('/user/add/', methods=["POST"])
|
||||||
def add_user():
|
def add_user():
|
||||||
pass
|
|
||||||
|
# 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:
|
||||||
|
flask.abort(400)
|
||||||
|
|
||||||
|
# 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))
|
||||||
|
|
||||||
|
flask.redirect('/')
|
||||||
|
|
||||||
@user.route('/user/register/')
|
@user.route('/user/register/')
|
||||||
def register_user():
|
def register_page():
|
||||||
form = RegisterUserForm()
|
form = RegisterUserForm()
|
||||||
|
|
||||||
return flask.render_template('register.html', form=form)
|
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:
|
||||||
|
flask.abort(400)
|
||||||
|
|
||||||
|
# Does password match?
|
||||||
|
if user_data[username] != password:
|
||||||
|
flask.abort(400)
|
||||||
|
|
||||||
|
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('/')
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user