aboutsummaryrefslogtreecommitdiff
path: root/pastebin.py
blob: 37fda533e7996bdc46eaf11ca9e124b25ff2972a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
from datetime import datetime
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)

def url_for_other_page(page):
   args = request.view_args.copy()
   args['page'] = page
   return url_for(request.endpoint, **args)
app.jinja_env.globals['url_for_other_page'] = url_for_other_page

@app.before_request
def check_user_status():
   g.user = None
   if 'user_id' in session:
      g.user = User.query.get(session['user_id'])

class Paste(db.Model):
   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(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):
      self.user = user
      self.code = code
      self.title = title
      self.is_private = is_private
      self.pub_date = datetime.utcnow()
      self.parent = parent

class User(db.Model):
   id = db.Column(db.Integer, primary_key=True)
   display_name = db.Column(db.String(120))
   fb_id = db.Column(db.String(30), unique=True)
   pastes = db.relationship(Paste, lazy='dynamic', backref='user')

@app.route('/', methods=['GET', 'POST'])
def new_paste():
   parent = None
   reply_to = request.args.get('reply_to')
   if reply_to is not None:
      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"
      if request.form['pastetitle'] and request.form['pastetitle'] != "Enter title here":
         title = request.form['pastetitle']
      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)) \
         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)

@app.route('/<paste_id>/')
@app.route('/<paste_id>')
def show_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))
   if paste.is_private:
      try:
         sign = request.args.get('s', '')
         assert str(paste.id) == \
            Signer(app.secret_key, salt=app.config['SALT']).unsign(sign).decode("utf-8")
      except:
         abort(403)
   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)
bgstack15