Advertisement
Guest User

Untitled

a guest
May 31st, 2017
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.86 KB | None | 0 0
  1. import logging
  2. import hashlib
  3. import tornado.web
  4. import json
  5. import datetime
  6. import time
  7. import base64
  8. import random
  9. import string
  10.  
  11. import settings
  12.  
  13. from tornado.web import authenticated
  14.  
  15. from db.base import AsyncDB, SyncDB
  16. from core.utils import DummyObject
  17.  
  18. async_db, async_fs = AsyncDB()()
  19. sync_db, sync_fs = SyncDB()()
  20. logger = logging.getLogger(__name__)
  21.  
  22.  
  23. # TODO: should be placed in utils module
  24. def get_token(context):
  25.     # check for token as param
  26.     token = context.get_argument('access_token', None)
  27.  
  28.     if not token:
  29.         # or as Authorization bearer header
  30.         auth_header = context.request.headers.get('Authorization', None)
  31.         if not auth_header:
  32.             raise Exception('This resource need a authorization token')
  33.         token = auth_header[7:]
  34.  
  35.     return token
  36.  
  37.  
  38. # TODO: should be placed in utils module
  39. async def create_token(data, user):
  40.     access_raw = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(15))
  41.     access_token = base64.b64encode( access_raw.encode("utf-8") ).decode("utf-8")
  42.  
  43.     refresh_raw = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(15))
  44.     refresh_token = base64.b64encode( refresh_raw.encode("utf-8") ).decode("utf-8")
  45.  
  46.     expires_in = int(datetime.datetime.now(datetime.timezone.utc).timestamp() + settings.TOKEN_TTL)
  47.     refresh_expires_in = int(datetime.datetime.now(datetime.timezone.utc).timestamp() + settings.REFRESH_TOKEN_TTL)
  48.  
  49.     result = await async_db.access_tokens.insert({
  50.         "grant_type": data.get('grant_type'),
  51.         "access_token": access_token,
  52.         "data": data,
  53.         "expires_in": expires_in,
  54.         "refresh_token": refresh_token,
  55.         "refresh_expires_in": refresh_expires_in,
  56.         "user_id": user.get('_id')
  57.     })
  58.     return access_token, refresh_token
  59.  
  60.  
  61. class Base(tornado.web.RequestHandler):
  62.    
  63.      def get_current_user(self):
  64.         try:
  65.             token = get_token(self)
  66.  
  67.             access = sync_db.access_tokens.find_one({'access_token':token})
  68.             if not access:
  69.                 raise Exception('Invalid token')
  70.  
  71.             if int(access.get('expires_in')) <= int(time.time()):
  72.                 raise Exception('Expired token')
  73.  
  74.             _user = sync_db.admin_users.find_one({'_id':access.get('user_id')})
  75.             if not _user is None:
  76.                 user = DummyObject()
  77.                 user.__dict__ = _user
  78.                 return user
  79.  
  80.         except Exception as e:
  81.             self.set_header('Content-Type', 'application/json')
  82.             self.set_status(401)
  83.             raise tornado.web.Finish()
  84.  
  85.  
  86. class Logout(Base):
  87.    
  88.     async def get(self):
  89.         try:
  90.             token = get_token(self)
  91.             access = await async_db.access_tokens.remove({'access_token':token})
  92.         except Exception as e:
  93.             self.set_header('Content-Type', 'application/json')
  94.             self.set_status(401)
  95.             self.write({ 'error': str(e)})
  96.  
  97.  
  98. class Login(Base):
  99.  
  100.     async def post(self):
  101.  
  102.         try:
  103.             data = json.loads(self.request.body.decode('utf-8'))
  104.         except Exception as e:
  105.             self.set_status(400)
  106.             self.write({ 'error':'Bad request'})
  107.             return
  108.  
  109.         # check grant_type
  110.         if data.get('grant_type') == 'password':
  111.             hashpassword = hashlib.md5(str.encode(settings.SALT + data.get('password'))).hexdigest()
  112.  
  113.             user = await async_db.admin_users.find_one({
  114.                 "email":data.get('username'),
  115.                 "password":hashpassword
  116.             })
  117.  
  118.             if user is None:
  119.                 self.set_status(401)
  120.                 self.write({ 'error':'Wrong username or password'})
  121.                 return
  122.  
  123.             try:
  124.                 access_token, refresh_token = await create_token(data=data, user=user)
  125.             except Exception as e:
  126.                 logger.debug('login error: %r' % e)
  127.                 self.set_status(400)
  128.                 self.write({ 'error':'Could not log in. Please try again later'})
  129.                 return
  130.  
  131.             self.write({
  132.                 'access_token':access_token,
  133.                 'token_type':settings.TOKEN_TYPE,
  134.                 'user_id': str(user.get('_id')),
  135.                 'refresh_token':refresh_token,
  136.                 'expires_in':settings.TOKEN_TTL
  137.             })
  138.             return
  139.  
  140.         if data.get('grant_type') == 'refresh_token':
  141.             try:
  142.                 access = await async_db.access_tokens.find_one({'refresh_token':data.get('refresh_token')})
  143.                 if access is None:
  144.                     raise Exception('Invalid refresh token')
  145.  
  146.                 if int(access.get('refresh_expires_in')) <= int(time.time()):
  147.                     raise Exception('expired token')
  148.  
  149.                 user = await async_db.admin_users.find_one({'_id':access.get('user_id')})
  150.                 if user is None:
  151.                     raise Exception('Invalid refresh token')
  152.  
  153.             except Exception as e:
  154.                 self.set_header('Content-Type', 'application/json')
  155.                 self.set_status(401)
  156.                 self.write({ 'error': str(e)})
  157.                 return
  158.  
  159.             try:
  160.                 access_token, refresh_token = await create_token(data=data, user=user)
  161.             except Exception as e:
  162.                 logger.debug('login error: %r' % e)
  163.                 self.set_status(400)
  164.                 self.write({ 'error':'Could not log in. Please try again later'})
  165.                 return
  166.  
  167.             _ = await async_db.access_tokens.remove({'refresh_token':data.get('refresh_token')})
  168.  
  169.             self.write({
  170.                 'access_token':access_token,
  171.                 'user_id': str(user.get('_id')),
  172.                 'refresh_token':refresh_token,
  173.                 'expires_in':settings.TOKEN_TTL
  174.             })
  175.             return
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement