From bd134ed333278f33c9b5596ef5df2501ee648bb1 Mon Sep 17 00:00:00 2001 From: "B. Stack" Date: Sat, 12 Feb 2022 12:07:05 -0500 Subject: add admin page, delete function, and APPNAME var The admin can view the links to private pastes, and can delete pastes from the web console. For now, the admin page is not protected, so this is not production-ready. --- pastebin.py | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 3 deletions(-) (limited to 'pastebin.py') diff --git a/pastebin.py b/pastebin.py index 37fda53..4c529f9 100644 --- a/pastebin.py +++ b/pastebin.py @@ -29,9 +29,14 @@ class UUID(types.TypeDecorator): return False id_column_name = "id" def id_column(): - #import uuid return Column(id_column_name,UUID(),primary_key=True,default=uuid.uuid4) +def get_signed(string, salt="blank"): + return Signer(app.secret_key, salt=salt).sign(str(string)) + +def get_unsigned(string, salt="blank"): + return Signer(app.secret_key, salt=salt).unsign(str(string)).decode("utf-8") + app = Flask(__name__) app.config.from_pyfile('config.cfg') db = SQLAlchemy(app) @@ -41,6 +46,7 @@ def url_for_other_page(page): args['page'] = page return url_for(request.endpoint, **args) app.jinja_env.globals['url_for_other_page'] = url_for_other_page +app.jinja_env.globals['appname'] = app.config['APPNAME'] @app.before_request def check_user_status(): @@ -89,7 +95,7 @@ def new_paste(): paste = Paste(g.user, request.form['code'], title, parent=parent, is_private=is_private) db.session.add(paste) db.session.commit() - sign = Signer(app.secret_key, salt=app.config['SALT']).sign(str(paste.id)) \ + sign = get_signed(paste.id, salt=app.config['SALT']) \ if is_private else None return redirect(url_for('show_paste', paste_id=paste.id, s=sign)) return render_template('new_paste.html', parent=parent) @@ -105,7 +111,7 @@ def show_paste(paste_id): try: sign = request.args.get('s', '') assert str(paste.id) == \ - Signer(app.secret_key, salt=app.config['SALT']).unsign(sign).decode("utf-8") + get_unsigned(sign, salt=app.config['SALT']) except: abort(403) parent = None @@ -126,3 +132,66 @@ def show_paste(paste_id): k = j.id, j.title children.append(k) return render_template('show_paste.html', paste=paste, parent=parent, children=children) + +@app.route('//delete/', methods=['POST']) +@app.route('//delete', methods=['POST']) +def delete_paste(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)) + sign = str(request.form['s']) + try: + assert str(paste.id) == get_unsigned(sign, salt=app.config['DELETESALT']) + except: + abort(403) + try: + Paste.query.filter(Paste.id == paste.id).delete() + db.session.commit() + return "OK",200 # WORKHERE: make this and the 500 redirect to admin/ + except: + return "failure to delete object.",500 + +def get_all_pastes(): + """ + Get custom arrangement of pastes for Admin view + """ + all1 = Paste.query.all() + all2 = [] + for p1 in all1: + parent_id = None + parent_title = None + children = [] + if p1.parent_id: + parent_id = p1.parent_id + try: + parent_title = Paste.query.get(p1.parent_id).title + except: + parent_title = "" # works better than None for the parent column of the generated html + if p1.children: + for c1 in p1.children: + child = Paste.query.get(c1.id) + child_title = child.title + c2 = c1.id, child_title + children.append(c2) + private = None + if p1.is_private: + private = get_signed(p1.id, salt=app.config['SALT']) + p2 = { + "id": p1.id, + "title": p1.title, + "private": private, + "user_id": p1.user_id, + "is_private": p1.is_private, + "parent": (parent_id, parent_title), + "children": children, + "delete": get_signed(p1.id, salt=app.config['DELETESALT']).decode("utf-8") + } + all2.append(p2) + return all2 + +@app.route('/admin/') +@app.route('/admin') +def admin(): + all_pastes = get_all_pastes() + return render_template('admin.html', pastes = all_pastes) -- cgit