def login(self): username, password = self['username'], self['password'] salt_hash = yield db.row( """ select id, salt, hash from users where username = %(username)s""", {'username': username}) if not salt_hash: raise Stink("no user named %s" % username) user_id, salt, hash = tuple( (salt_hash[key] for key in ('id', 'salt', 'hash'))) if hashlib.sha256(password + salt).hexdigest() == hash: token = os.urandom(16).encode('hex') yield db.query( """ insert into tokens (user_id, token) values (%(user_id)s, %(token)s)""", { 'user_id': user_id, 'token': token }) self.set_cookie('token', token) else: raise Stink("bad password") self.request.user = yield db.value( """select user_id from tokens where token = %(token)s""", {'token': token}) defer.returnValue({ 'message': 'logged in', 'token': token, 'user': { 'id': self.request.user } })
def is_owner(self): user_id = yield db.value( """ select users.id from users, avatars where avatars.user_id = users.id and avatars.id = %(avatar)s""", {'avatar': self['avatar']}) if not user_id: raise Stink("no avatar set %s" % self['avatar']) if user_id != self.request.user: raise Stink("you don't own avatar %s" % self['avatar']) defer.returnValue(True)
def is_owner(self): user_id, page = (self.request.user, self['page']) data = yield db.row( """ select users.id as user_id, pages.published from users, pages where pages.user_id = users.id and pages.id = %(page)s""", {'page': page}) if not data: raise Stink("no page set %s" % page) if data['user_id'] != user_id: raise Stink("you don't own page %s" % page) defer.returnValue(data['published'])
def add(self): self.verify() published = yield self.is_owner() if published: raise Stink("can't add an image to a published page") yield files.save(self.request.files['file'][0]['body'], 'page', set_id=self['page'])
def select(self): published = yield self.is_owner() if not published: raise Stink("can't select an unpublished page") user_id, page = (self.request.user, self['page']) yield db.query( "update users set page = %(page)s where id = %(user_id)s", { 'page': page, 'user_id': user_id })
def post_message(self): forum, thread, content, avatar = (self['forum'], self['thread'], self['content'], self['avatar']) if not self.request.user: raise Stink('must be logged in/token must be valid') if not avatar: raise Stink('must specify avatar id') if not (forum or thread): raise Stink('must specify forum id or thread') if forum and thread: raise Stink('pick one, a forum or a thread to post to') if forum: page = yield db.value( "select page from users where id = %(forum)s", {'forum': forum}) if not page: raise Stink("can't post a thread to a forum with no page") yield db.query( """ insert into ops (user_id, content, forum_id, avatar_id, dt, page_id) values (%(user_id)s, %(content)s, %(forum)s, %(avatar)s, now(), %(page)s)""", { 'user_id': self.request.user, 'content': content, 'forum': forum, 'avatar': avatar, 'page': page }) else: yield db.query( """ insert into posts (user_id, content, thread_id, avatar_id, dt) values (%(user_id)s, %(content)s, (select id from ops where content = %(thread)s), %(avatar)s, now())""", { 'user_id': self.request.user, 'content': content, 'avatar': avatar, 'thread': thread }) defer.returnValue({'success': True})
def thread(self, path): content = urllib.unquote(path) comparator = '<' if self['comparator'] == 'gt': comparator = '>' posts = yield db.query( """ select ops.page_id, posts.thread_id, posts.content, posts.dt, posts.user_id, files.url as avatar_url from posts, ops, files, users where posts.thread_id = ops.id and ops.content = %%(content)s and posts.user_id = users.id and files.id = posts.avatar_id and posts.dt %(comparator)s %%(dt)s order by posts.dt desc limit 10 """ % {'comparator': comparator}, { 'content': content, 'dt': self.arg('dt', '3000-01-01T01:01:01') }) if not posts: raise Stink('no thread named %s' % path) page = yield db.query( """ select files.id, files.url from files, pages where files.set_id = %(page)s and pages.id = %(page)s""", {'page': posts[0]['page_id']}) user = yield self.user() defer.returnValue({ 'user': user, 'thread': content, 'page': page, 'posts': list( reversed([{ 'content': post['content'], 'dt': post['dt'], 'user': { 'avatar': post['avatar_url'], 'id': post['user_id'] } } for post in posts])) })
def verify(self): if not self['name']: raise Stink("images need a name") if not 'file' in self.request.files: raise Stink("you have to upload a file") files.verify(self.request.files['file'][0]['body'], self.reqs)
def publish(self): published = yield self.is_owner() if published: raise Stink("this page is already published") yield db.query("update pages set published = true where id = %(page)s", {'page': self['page']}) yield self.select()
def verify(self): if not 'file' in self.request.files: raise Stink("you must upload an image") files.verify(self.request.files['file'][0]['body'], self.reqs)