1
0
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:
Adam Dodman 2017-10-03 02:18:13 +01:00
commit fd8e17926e
7 changed files with 297 additions and 0 deletions

16
default.sql Normal file
View 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
View 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
View 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
View 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
View 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>&copy; Adam Dodman 2017</p>
</footer>
</div>
</body>
</html>

26
templates/login.html Normal file
View 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
View 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 %}