aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsudan <sudan@douban.com>2016-02-22 17:20:20 +0800
committersudan <sudan@douban.com>2016-02-22 17:20:20 +0800
commitf0a9e8a874d216deb73e87b8b08f73b6a00151ff (patch)
treec3f10d9746aac51bb7f784a5ee04f4ca6b065125
parentremove gunicorn (diff)
downloadstackbin-f0a9e8a874d216deb73e87b8b08f73b6a00151ff.tar.gz
stackbin-f0a9e8a874d216deb73e87b8b08f73b6a00151ff.tar.bz2
stackbin-f0a9e8a874d216deb73e87b8b08f73b6a00151ff.zip
add private paste
-rw-r--r--pastebin.py23
-rw-r--r--static/style.css5
-rw-r--r--templates/new_paste.html19
-rw-r--r--templates/show_paste.html4
4 files changed, 34 insertions, 17 deletions
diff --git a/pastebin.py b/pastebin.py
index 03ab9b8..4d4309d 100644
--- a/pastebin.py
+++ b/pastebin.py
@@ -1,6 +1,7 @@
from datetime import datetime
+from itsdangerous import Signer
from flask import (Flask, request, url_for, redirect, g,
- render_template, session)
+ render_template, session, abort)
from flask.ext.sqlalchemy import SQLAlchemy
@@ -28,13 +29,15 @@ class Paste(db.Model):
code = 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 = db.relationship('Paste', lazy=True, backref='children',
uselist=False, remote_side=[id])
- def __init__(self, user, code, parent=None):
+ def __init__(self, user, code, parent=None, is_private=False):
self.user = user
self.code = code
+ self.is_private = is_private
self.pub_date = datetime.utcnow()
self.parent = parent
@@ -53,10 +56,14 @@ def new_paste():
if reply_to is not None:
parent = Paste.query.get(reply_to)
if request.method == 'POST' and request.form['code']:
- paste = Paste(g.user, request.form['code'], parent=parent)
+ is_private = bool(request.form.get('is_private'))
+ paste = Paste(g.user, request.form['code'], parent=parent,
+ is_private=is_private)
db.session.add(paste)
db.session.commit()
- return redirect(url_for('show_paste', paste_id=paste.id))
+ sign = Signer(app.secret_key, salt='jackson').sign(str(paste.id)) \
+ 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)
@@ -64,5 +71,11 @@ def new_paste():
@app.route('/<int:paste_id>')
def show_paste(paste_id):
paste = Paste.query.options(db.eagerload('children')).get_or_404(paste_id)
+ if paste.is_private:
+ try:
+ sign = request.args.get('s', '')
+ assert str(paste.id) == \
+ Signer(app.secret_key, salt='jackson').unsign(sign)
+ except:
+ abort(403)
return render_template('show_paste.html', paste=paste)
-
diff --git a/static/style.css b/static/style.css
index a8fc27c..8a7a7c0 100644
--- a/static/style.css
+++ b/static/style.css
@@ -7,7 +7,8 @@ a:hover { color: #c00; }
.nav { margin: 0 0 15px 0; font-size: 14px; list-style: none; padding: 0 10px; }
.nav li { display: inline; }
.nav li + li:before { content: " // "; }
-h2 { font-weight: normal; color: #999; margin-bottom: 10px; padding: 0 10px}
+h2 { font-weight: normal; color: #999; margin-bottom: 10px; padding-left: 10px}
+.chk-private { float: right; font-size: 12px; margin-top: 12px}
dl { overflow: auto; font-size: 14px; padding: 0 10px}
dl dt { font-weight: bold; min-width: 70px; float: left; padding-right: 15px;
clear: left; }
@@ -15,7 +16,7 @@ dl dd { float: left; margin: 0; padding: 0; }
pre, textarea { font-family: 'Consolas', monospace; font-size: 14px;
background: #f4f4f4; padding: 10px; margin: 0; line-height: 1.4em;
word-break: break-word; white-space: pre-wrap;}
-textarea { border: none; width: 100%; }
+textarea { border: none; width: 780px; }
.code, .flash { background: #f4f4f4; padding: 0; }
.pagination strong,
.pagination span.ellipsis,
diff --git a/templates/new_paste.html b/templates/new_paste.html
index c7c623d..5f1760a 100644
--- a/templates/new_paste.html
+++ b/templates/new_paste.html
@@ -1,13 +1,14 @@
{% extends "layout.html" %}
{% block title %}New Paste{% endblock %}
{% block body %}
-<h2>New Paste
- {%- if parent %}
- - Reply to #{{ parent.id }}
- {%- endif %}
-</h2>
- <form action="" method=post>
- <div class=code><textarea name=code cols=60 rows=12>{{ parent.code }}</textarea></div>
- <p><input type=submit value="New Paste">
- </form>
+<form action="" method=post>
+ <h2>New Paste
+ {%- if parent %}
+ - Reply to #{{ parent.id }}
+ {%- endif %}
+ <span class="chk-private"><input name="is_private" type="checkbox"/>Private</span>
+ </h2>
+ <div class=code><textarea name=code cols=60 rows=12>{{ parent.code }}</textarea></div>
+ <p><input type=submit value="New Paste">
+</form>
{% endblock %}
diff --git a/templates/show_paste.html b/templates/show_paste.html
index 89ad18e..9628402 100644
--- a/templates/show_paste.html
+++ b/templates/show_paste.html
@@ -11,7 +11,9 @@
<dd>{{ paste.pub_date.strftime('%Y-%m-%d @ %H:%M') }}
<dt>Actions
<dd>
- <a href="{{ url_for('new_paste', reply_to=paste.id) }}">Reply</a>
+ {% if not paste.is_private %}
+ <a href="{{ url_for('new_paste', reply_to=paste.id) }}">Reply</a>
+ {% endif %}
{%- if g.user and paste.user == g.user -%}
, <a href="{{ url_for('delete_paste', paste_id=paste.id) }}">Delete</a>
{% endif %}
bgstack15