mirror of
https://github.com/Adam-Ant/QuotesDB
synced 2024-12-20 11:34:35 +00:00
Add barebones files from previous work
This commit is contained in:
commit
fd8e17926e
16
default.sql
Normal file
16
default.sql
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
CREATE TABLE Users (
|
||||||
|
uid int NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
user varchar(255) NOT NULL,
|
||||||
|
realname varchar(255) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE Quotes (
|
||||||
|
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
quote VARCHAR(2048) NOT NULL,
|
||||||
|
date VARCHAR(255) NOT NULL,
|
||||||
|
user INT NOT NULL,
|
||||||
|
context VARCHAR(8000),
|
||||||
|
FOREIGN KEY (user) REFERENCES Users(uid)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
112
main.py
Normal file
112
main.py
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
from os import urandom as rand
|
||||||
|
from flaskext.mysql import MySQL
|
||||||
|
import pymysql
|
||||||
|
from flask import Flask, render_template, session, redirect, url_for, request, flash
|
||||||
|
import pprint
|
||||||
|
|
||||||
|
pp = pprint.PrettyPrinter(indent=4)
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
app.secret_key = rand(24)
|
||||||
|
|
||||||
|
# Thank you based StackOverflow
|
||||||
|
def cleanup_string(text):
|
||||||
|
text = text.encode("ascii", "replace").decode()
|
||||||
|
return text.strip()
|
||||||
|
|
||||||
|
# Load User Table into variable
|
||||||
|
def mysql_do(query):
|
||||||
|
db = pymysql.connect(host='dockerdev', port=3306, user='root', passwd='development', db='QuoteDB')
|
||||||
|
cur = db.cursor()
|
||||||
|
cur.execute(query)
|
||||||
|
data = cur.fetchall()
|
||||||
|
cur.close()
|
||||||
|
db.commit()
|
||||||
|
db.close()
|
||||||
|
return data
|
||||||
|
|
||||||
|
userdb = mysql_do("SELECT * FROM Users")
|
||||||
|
|
||||||
|
@app.route("/")
|
||||||
|
def index():
|
||||||
|
if 'username' in session:
|
||||||
|
return render_template("index.html", user=session["username"])
|
||||||
|
return render_template("index.html")
|
||||||
|
|
||||||
|
@app.route("/quotes")
|
||||||
|
def quoutepage():
|
||||||
|
retdata = mysql_do("SELECT * FROM Quotes ORDER BY ID DESC")
|
||||||
|
return render_template("quote_view.html", data=retdata)
|
||||||
|
|
||||||
|
@app.route("/addquote", methods=['GET','POST'])
|
||||||
|
def addquote():
|
||||||
|
if request.method == "POST":
|
||||||
|
|
||||||
|
quotein = pymysql.escape_string(request.form['quote'])
|
||||||
|
contextin = pymysql.escape_string(request.form['context'])
|
||||||
|
userin = pymysql.escape_string(request.form['user'])
|
||||||
|
|
||||||
|
|
||||||
|
#Remove Trailing and leading whitespace, strip unicode
|
||||||
|
quotein = cleanup_string(quotein)
|
||||||
|
contextin = cleanup_string(contextin)
|
||||||
|
|
||||||
|
if not quotein or quotein.isspace():
|
||||||
|
flash("Error: You must enter a quote!","danger")
|
||||||
|
return redirect(url_for("addquote"))
|
||||||
|
|
||||||
|
# Check if the <textarea> has been tampered with...
|
||||||
|
if (len(quotein) > 500) or (len(contextin) > 500):
|
||||||
|
flash("Error: Quote too long. Stop fucking with the code :P","danger")
|
||||||
|
return redirect(url_for("addquote"))
|
||||||
|
|
||||||
|
# This checks if the user value has been changed to a non integer
|
||||||
|
try:
|
||||||
|
userin = int(userin)
|
||||||
|
except:
|
||||||
|
flash("Error: Invalid userID. Stop fucking with the code :P","danger")
|
||||||
|
return redirect(url_for("addquote"))
|
||||||
|
|
||||||
|
# Check if the value is out of range of the valid uid's
|
||||||
|
if (userin > int(userdb[-1][0]) or (userin <= 0)):
|
||||||
|
flash("Error: Invalid userID. Stop fucking with the code :P","danger")
|
||||||
|
return redirect(url_for("addquote"))
|
||||||
|
|
||||||
|
|
||||||
|
if not contextin:
|
||||||
|
contextin = "NULL"
|
||||||
|
else:
|
||||||
|
contextin = "\'" + contextin + "\'"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
sql = "INSERT INTO `Quotes` (`id`, `quote`, `date`, `user`, `context`) VALUES (NULL, '%s', CURRENT_TIMESTAMP, %d, %s);" % (quotein, userin, contextin)
|
||||||
|
print(sql)
|
||||||
|
mysql_do(sql)
|
||||||
|
flash("Success! The entry was added to the database.","success")
|
||||||
|
return redirect(url_for('index'))
|
||||||
|
return render_template("add_quote.html", users=userdb)
|
||||||
|
|
||||||
|
@app.route("/login", methods=['GET', 'POST'])
|
||||||
|
def login():
|
||||||
|
if request.method == 'POST':
|
||||||
|
session['username'] = request.form['username']
|
||||||
|
return redirect(url_for('index'))
|
||||||
|
return render_template("login.html")
|
||||||
|
|
||||||
|
@app.route("/logout")
|
||||||
|
def logout():
|
||||||
|
session.pop('username',None)
|
||||||
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
|
@app.context_processor
|
||||||
|
def utility_processor():
|
||||||
|
def uid_to_user(uid):
|
||||||
|
for user in userdb:
|
||||||
|
if user[0] == uid:
|
||||||
|
return user[1]
|
||||||
|
return dict(uid_to_user=uid_to_user)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run(host="0.0.0.0", debug=True)
|
28
templates/add_quote.html
Normal file
28
templates/add_quote.html
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
{% block body %}
|
||||||
|
<h1> Add new Quote </h1>
|
||||||
|
<form method="post">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="quote">Quote:</label>
|
||||||
|
<textarea rows="3" maxlength="500" class="form-control" id="quote" name="quote" ></textarea>
|
||||||
|
<span class="help-block">Required</span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="context">Context:</label>
|
||||||
|
<textarea rows="3" maxlength="500" class="form-control" id="context" name="context" ></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="user">User:</label>
|
||||||
|
<select class="form-control" id="user" name="user">
|
||||||
|
{% for user in users %}
|
||||||
|
<option value="{{ user[0] }}">{{ user[1] }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
<span class="help-block">User not listed? Add one <a href="https://www.youtube.com/watch?v=woySeSNBL3o">here</a></span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="submit" class="btn btn-primary">Submit</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
8
templates/index.html
Normal file
8
templates/index.html
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
{% block body %}
|
||||||
|
<div class="jumbotron">
|
||||||
|
<h1>Clockwork Quotes Database</h1>
|
||||||
|
<p><a class="btn btn-lg btn-success" href="/quotes" role="button">View Quotes</a></p>
|
||||||
|
<p><a class="btn btn-lg btn-info" href="/addquote" role="button">Add a Quote</a></p>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
65
templates/layout.html
Normal file
65
templates/layout.html
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Clockwork Quote DB</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
|
||||||
|
|
||||||
|
<!-- Bootstrap core JavaScript
|
||||||
|
================================================== -->
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
|
||||||
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
|
||||||
|
|
||||||
|
{% block head %}{% endblock %}
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-inverse" style="border-radius: 0">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="navbar-header">
|
||||||
|
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#mainNavbar">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</button>
|
||||||
|
<a href="/" class="navbar-brand"><span class="glyphicon glyphicon-cog"></span> Clockwork Quotes</a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="collapse navbar-collapse" id="mainNavbar">
|
||||||
|
{% if user %}
|
||||||
|
<a href="logout" class="btn btn-primary navbar-btn navbar-right "role="button" ><span class="glyphicon glyphicon-log-out"></span> Sign Out</a>
|
||||||
|
<ul class="nav navbar-nav navbar-right">
|
||||||
|
<li class="navbar-text">Hello <b> {{ user }}!</b></li>
|
||||||
|
</ul>
|
||||||
|
{% else %}
|
||||||
|
<a href="login" class="btn btn-primary navbar-btn navbar-right "role="button"><span class="glyphicon glyphicon-log-in"></span> Login</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||||
|
{% if messages %}
|
||||||
|
{% for category, message in messages %}
|
||||||
|
{% set splitmessage = message.split(" ", 1) %}
|
||||||
|
<div class="alert alert-{{ category }} alert-dismissable">
|
||||||
|
<a href="#" class="close" data-dismiss="alert" aria-label="close"> <span class="glyphicon glyphicon-remove"></span></a>
|
||||||
|
<strong>{{ splitmessage[0] }}</strong> {{ splitmessage[1] }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
|
{% block body %}{% endblock %}
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<p>© Adam Dodman 2017</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
26
templates/login.html
Normal file
26
templates/login.html
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
{% block body %}
|
||||||
|
<form method="post" role="form" data-toggle="validator">
|
||||||
|
<div class="form-group has-feedback">
|
||||||
|
<label class="control-label col-sm-4" for="username">Username:</label>
|
||||||
|
<div class="col-xs-4 input-group">
|
||||||
|
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
|
||||||
|
<input type="text" class="form-control" placeholder="Enter username" id="username" name="username" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-sm-4" for="pw">Password:</label>
|
||||||
|
<div class="col-xs-4 input-group">
|
||||||
|
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
|
||||||
|
<input type="password" class="form-control" placeholder="Enter password" id="pw" name="pw">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-4">
|
||||||
|
<button type="submit" class="btn btn-primary">Submit</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
42
templates/quote_view.html
Normal file
42
templates/quote_view.html
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.13/css/dataTables.bootstrap.min.css">
|
||||||
|
<script src="https://cdn.datatables.net/1.10.13/js/jquery.dataTables.min.js"></script>
|
||||||
|
<script src="https://cdn.datatables.net/1.10.13/js/dataTables.bootstrap.min.js"></script>
|
||||||
|
<script type="text/javascript" class="init">
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#QuoteTable').DataTable( {
|
||||||
|
"order": [[ 0,"desc" ]],
|
||||||
|
"lengthMenu": [[ 10, 25, 50, 100, -1 ], [ 10, 25, 50, 100, "All" ]],
|
||||||
|
"pagingType": "full_numbers",
|
||||||
|
"stateSave": true
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover table-bordered" id="QuoteTable">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Date Added</th>
|
||||||
|
<th>User</th>
|
||||||
|
<th>Quote</th>
|
||||||
|
<th>Context</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for entry in data %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ "{:%Y/%m/%d %H:%M:%S}".format(entry[2]) }}</td>
|
||||||
|
<td>{{ uid_to_user(entry[3]) }}</td>
|
||||||
|
<td>{{ entry[1] }}</td>
|
||||||
|
<td>{{ entry[4] }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
Loading…
Reference in New Issue
Block a user