db.py 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import hashlib
  2. import hmac
  3. import binascii
  4. import os
  5. import tornado.gen
  6. import psycopg2
  7. import momoko
  8. import config
  9. def hash_pw(password, salt=None):
  10. if salt is None:
  11. salt = os.urandom(16)
  12. h = hmac.new(salt, password.encode('utf-8'), hashlib.sha256)
  13. hashed = h.hexdigest()
  14. salt_hex = binascii.hexlify(salt).decode()
  15. return hashed, salt_hex
  16. class MomokoDB:
  17. db = momoko.Pool(dsn='dbname=%s user=%s' % (config.db.database, config.db.user), size=2)
  18. @tornado.gen.coroutine
  19. def execute(self, query, *args):
  20. result = yield momoko.Op(self.db.execute, query, args, cursor_factory=psycopg2.extras.DictCursor)
  21. return result
  22. @tornado.gen.coroutine
  23. def create_user(self, username, password):
  24. hashed_password, salt = hash_pw(password)
  25. query = 'INSERT INTO users (username, password, salt) VALUES (%s, %s, %s) RETURNING id;'
  26. cursor = yield self.execute(query, username, hashed_password, salt)
  27. return cursor.fetchone()['id']
  28. @tornado.gen.coroutine
  29. def check_user(self, username, password):
  30. query = 'SELECT id, username, password, salt FROM users WHERE username=%s;'
  31. cursor = yield self.execute(query, username)
  32. user = cursor.fetchone()
  33. if not user:
  34. return
  35. salt = binascii.unhexlify(bytes(user['salt'], 'ascii'))
  36. hashed, _ = hash_pw(password, salt)
  37. if hashed == user['password']:
  38. return user
  39. @tornado.gen.coroutine
  40. def create_group(self, user_id, group_name):
  41. cursor = yield self.execute('INSERT INTO groups (name) VALUES(%s) RETURNING id;', group_name)
  42. group_id = cursor.fetchone()['id']
  43. yield self.execute('INSERT INTO user_groups (user_id, group_id) VALUES(%s, %s);', user_id, group_id)
  44. return group_id
  45. @tornado.gen.coroutine
  46. def get_groups(self, user_id):
  47. cursor = yield self.execute('''
  48. SELECT groups.id, groups.name FROM users
  49. JOIN user_groups ON users.id = user_groups.user_id
  50. JOIN groups ON user_groups.group_id = groups.id
  51. WHERE users.id = %s;
  52. ''', user_id)
  53. return cursor.fetchall()