diff options
author | B. Stack <bgstack15@gmail.com> | 2022-02-11 20:56:59 -0500 |
---|---|---|
committer | B. Stack <bgstack15@gmail.com> | 2022-02-11 20:56:59 -0500 |
commit | 99f6fb15a5aaa326a729e73974006d1064a5582f (patch) | |
tree | 41795c1a447bb88c7521c286840c7d290c0afb8c | |
parent | add support for title, and ensure no js (diff) | |
download | stackbin-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.md | 1 | ||||
-rw-r--r-- | pastebin.py | 68 | ||||
-rw-r--r-- | static/pastebin.js | 47 | ||||
-rw-r--r-- | templates/layout.html | 5 | ||||
-rw-r--r-- | templates/new_paste.html | 2 | ||||
-rw-r--r-- | templates/show_paste.html | 21 |
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 %} |