aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Stack <bgstack15@gmail.com>2022-02-11 20:56:59 -0500
committerB. Stack <bgstack15@gmail.com>2022-02-11 20:56:59 -0500
commit99f6fb15a5aaa326a729e73974006d1064a5582f (patch)
tree41795c1a447bb88c7521c286840c7d290c0afb8c
parentadd support for title, and ensure no js (diff)
downloadstackbin-99f6fb15a5aaa326a729e73974006d1064a5582f.tar.gz
stackbin-99f6fb15a5aaa326a729e73974006d1064a5582f.tar.bz2
stackbin-99f6fb15a5aaa326a729e73974006d1064a5582f.zip
use UUID for paste id, and more js removal
Using uuids means that titles need to be used for displaying "replies," "in response to," and so on.
-rw-r--r--README-bgstack15.md1
-rw-r--r--pastebin.py68
-rw-r--r--static/pastebin.js47
-rw-r--r--templates/layout.html5
-rw-r--r--templates/new_paste.html2
-rw-r--r--templates/show_paste.html21
6 files changed, 67 insertions, 77 deletions
diff --git a/README-bgstack15.md b/README-bgstack15.md
index 34137f5..199b254 100644
--- a/README-bgstack15.md
+++ b/README-bgstack15.md
@@ -11,7 +11,6 @@ Run server.
# Improvements
I still need to practice these:
-* Support editing the title?
* Fix the private bins problem: they always return 403
* Support deleting somehow: from an admin panel, or a link on the page?
* use UUIDs for link instead of sequential integers?
diff --git a/pastebin.py b/pastebin.py
index 4d5c231..cd67265 100644
--- a/pastebin.py
+++ b/pastebin.py
@@ -3,6 +3,35 @@ from itsdangerous import Signer
from flask import (Flask, request, url_for, redirect, g, render_template, session, abort)
from flask_sqlalchemy import SQLAlchemy
+## ripped from https://stackoverflow.com/questions/183042/how-can-i-use-uuids-in-sqlalchemy/812363#812363
+from sqlalchemy import types
+from sqlalchemy.dialects.mysql.base import MSBinary
+from sqlalchemy.schema import Column
+import uuid
+class UUID(types.TypeDecorator):
+ impl = MSBinary
+ def __init__(self):
+ self.impl.length = 16
+ types.TypeDecorator.__init__(self,length=self.impl.length)
+ def process_bind_param(self,value,dialect=None):
+ if value and isinstance(value,uuid.UUID):
+ return value.bytes
+ elif value and not isinstance(value,uuid.UUID):
+ raise ValueError('value %s is not a valid uuid.UUID' % value)
+ else:
+ return None
+ def process_result_value(self,value,dialect=None):
+ if value:
+ return uuid.UUID(bytes=value)
+ else:
+ return None
+ def is_mutable(self):
+ return False
+id_column_name = "id"
+def id_column():
+ #import uuid
+ return Column(id_column_name,UUID(),primary_key=True,default=uuid.uuid4)
+
app = Flask(__name__)
app.config.from_pyfile('config.cfg')
db = SQLAlchemy(app)
@@ -20,13 +49,13 @@ def check_user_status():
g.user = User.query.get(session['user_id'])
class Paste(db.Model):
- id = db.Column(db.Integer, primary_key=True)
+ id = id_column()
code = db.Column(db.Text)
title = db.Column(db.Text)
pub_date = db.Column(db.DateTime)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
is_private = db.Column(db.Boolean)
- parent_id = db.Column(db.Integer, db.ForeignKey('paste.id'))
+ parent_id = db.Column(UUID(), db.ForeignKey('paste.id'))
parent = db.relationship('Paste', lazy=True, backref='children', uselist=False, remote_side=[id])
def __init__(self, user, code, title, parent=None, is_private=False):
@@ -46,9 +75,12 @@ class User(db.Model):
@app.route('/', methods=['GET', 'POST'])
def new_paste():
parent = None
- reply_to = request.args.get('reply_to', type=int)
+ reply_to = request.args.get('reply_to')
if reply_to is not None:
- parent = Paste.query.get(reply_to)
+ try:
+ parent = Paste.query.get(uuid.UUID(reply_to))
+ except:
+ parent = Paste.query.get(reply_to)
if request.method == 'POST' and request.form['code']:
is_private = bool(request.form.get('is_private'))
title = "Untitled paste"
@@ -62,10 +94,13 @@ def new_paste():
return redirect(url_for('show_paste', paste_id=paste.id, s=sign))
return render_template('new_paste.html', parent=parent)
-@app.route('/<int:paste_id>/')
-@app.route('/<int:paste_id>')
+@app.route('/<paste_id>/')
+@app.route('/<paste_id>')
def show_paste(paste_id):
- paste = Paste.query.options(db.eagerload('children')).get_or_404(paste_id)
+ try:
+ paste = Paste.query.options(db.eagerload('children')).get_or_404(paste_id)
+ except:
+ paste = Paste.query.options(db.eagerload('children')).get_or_404(uuid.UUID(paste_id))
if paste.is_private:
try:
sign = request.args.get('s', '')
@@ -73,4 +108,21 @@ def show_paste(paste_id):
Signer(app.secret_key, salt='jackson').unsign(sign).decode("utf-8")
except:
abort(403)
- return render_template('show_paste.html', paste=paste)
+ parent = None
+ if paste.parent_id:
+ try:
+ parent = Paste.query.get(uuid.UUID(paste.parent_id))
+ except:
+ parent = Paste.query.get(paste.parent_id)
+ children = []
+ if paste.children:
+ for i in paste.children:
+ j = None
+ try:
+ j = Paste.query.get(uuid.UUID(i.id))
+ except:
+ j = Paste.query.get(i.id)
+ if j:
+ k = j.id, j.title
+ children.append(k)
+ return render_template('show_paste.html', paste=paste, parent=parent, children=children)
diff --git a/static/pastebin.js b/static/pastebin.js
deleted file mode 100644
index 4412595..0000000
--- a/static/pastebin.js
+++ /dev/null
@@ -1,47 +0,0 @@
-(function() {
- var global = this;
-
- var lib = global.pastebin = {
- urlRoot : '/',
-
- autoHideFlashes : function() {
- var flashes = $('p.flash:visible').hide();
- if (flashes.length) {
- flashes.slideDown('fast');
- window.setTimeout(function() {
- flashes.slideUp('slow');
- }, 5000);
- }
- },
-
- flash : function(message) {
- $('<p class=flash></p>')
- .append(message)
- .hide()
- .insertAfter('ul.nav')
- .slideDown('fast');
- },
-
- onNewReply : function(reply, type) {
- var pasteDescription = '';
- if (type == 'user') {
- pasteDescription = 'your paste <a href="' +
- pastebin.urlRoot + reply.paste_id + '">#' + reply.paste_id + '</a>';
- } else {
- pasteDescription = 'this paste';
- }
- var msg = $('<span>New reply to ' + pasteDescription + ': <a href="' +
- pastebin.urlRoot + reply.reply_id + '">#' + reply.reply_id + '</a></span>');
- if (reply.author)
- msg.append($('<span></span>').text(' ' + reply.author))
- lib.flash(msg);
- }
-
- };
-
-
- $(function() {
- /* animate the server side flashes a bit */
- lib.autoHideFlashes();
- });
-})();
diff --git a/templates/layout.html b/templates/layout.html
index 6b53bb3..bfe8b05 100644
--- a/templates/layout.html
+++ b/templates/layout.html
@@ -6,11 +6,6 @@
<meta name="format-detection" content="telephone=no">
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}">
<link rel="stylesheet" media="screen and (max-width: 800px)" href="{{ url_for('static', filename='small.css') }}" />
-{#
-<script type=text/javascript src="{{ url_for('static', filename='jquery.js') }}"></script>
-<script type=text/javascript src="{{ url_for('static', filename='pastebin.js') }}"></script>
-<script type=text/javascript>pastebin.urlRoot = {{ request.url_root|tojson|safe }};</script>
-#}
<div class=page>
<ul class=nav>
<li><a href="{{ url_for('new_paste') }}">New Paste</a>
diff --git a/templates/new_paste.html b/templates/new_paste.html
index 4d658c6..977ef22 100644
--- a/templates/new_paste.html
+++ b/templates/new_paste.html
@@ -4,7 +4,7 @@
<form action="" method=post>
<h2><div class="pastetitle"><textarea rows="1" name="pastetitle">Enter title here</textarea></div>
{%- if parent %}
- - Reply to #{{ parent.id }}
+ - Reply to {{ parent.title }}
{%- endif %}
<span class="chk-private"><input name="is_private" type="checkbox"/>Private</span>
</h2>
diff --git a/templates/show_paste.html b/templates/show_paste.html
index 26273bf..03d57b1 100644
--- a/templates/show_paste.html
+++ b/templates/show_paste.html
@@ -9,7 +9,7 @@
<dd>{{ paste.user.display_name }}
{% endif %}
<dt>Date
- <dd>{{ paste.pub_date.strftime('%Y-%m-%d @ %H:%M') }}
+ <dd>{{ paste.pub_date.strftime('%Y-%m-%dT%H:%M:%SZ') }}
<dt>Actions
<dd>
{% if not paste.is_private %}
@@ -18,27 +18,18 @@
{%- if g.user and paste.user == g.user -%}
, <a href="{{ url_for('delete_paste', paste_id=paste.id) }}">Delete</a>
{% endif %}
- {% if paste.parent_id %}
+ {% if parent %}
<dt>In reply to
- <dd><a href="{{ url_for('show_paste', paste_id=paste.parent_id) }}">#{{ paste.parent_id }}</a>
+ <dd><a href="{{ url_for('show_paste', paste_id=paste.parent_id) }}">{{ parent.title }}</a>
{% endif %}
- {% if paste.children %}
+ {% if children %}
<dt>Replies
<dd>
- {% for child in paste.children -%}
+ {% for childid,childtitle in children -%}
{%- if not loop.first %},{% endif %}
- <a href="{{ url_for('show_paste', paste_id=child.id) }}">#{{ child.id }}</a>
+ <a href="{{ url_for('show_paste', paste_id=childid) }}">{{ childtitle }}</a>
{%- endfor %}
{% endif %}
</dl>
<div class=code><pre>{{ paste.code }}</pre></div>
- <link rel="stylesheet" href="//cdn.jsdelivr.net/highlight.js/9.1.0/styles/default.min.css">
- <script src="//cdn.jsdelivr.net/highlight.js/9.1.0/highlight.min.js"></script>
- <script>
- $(document).ready(function() {
- $('pre').each(function(i, block) {
- hljs.highlightBlock(block);
- });
- });
- </script>
{% endblock %}
bgstack15