async def api_get_session(request): logger.debug('get_session') session = await get_session(request) data = await request.json() await set_csrf_token_session(session) success = False token = session['csrf_token'] user = None uid = session.get('uid') if uid: user = get_user_from_session(session, request.db_session) session['tz'] = data.get('user_timezone') if user.enable: context = { 'user': user, 'db_session': request.db_session, 'ws_session': session, 'method': 'read', 'queue': request.app.queue } user = await user.serialize(context) success = True else: user.logout(session) user = None resp_data = {'success': success, 'user': user, 'token': token} return web.json_response(resp_data)
async def api_check_email_disponibility(request): logger.debug('check_email_disponibility') try: data = await request.json() email = data['email'] except: raise exceptions.InvalidRequestException('Missing json data') available = not request.db_session.query(User)\ .filter(User.email == email).count() resp_data = {'success': True, 'available': available} return web.json_response(resp_data)
async def api_admin(request): logger.debug('admin') session = await get_session(request) user = get_user_from_session(session, request.db_session) context = { 'user': user, 'ws_session': session, 'db_session': request.db_session, 'method': 'read', 'queue': request.app.queue } resp_data = {'success': True, 'user': await user.serialize(context)} return web.json_response(resp_data)
async def get_json_data(self): try: req_data = await self.request.json() actions = req_data['actions'] # Convert actions to list if necessary if not type(actions) == list: actions = [actions] logger.debug('actions = {actions}'.format(actions=actions)) return actions except: raise exceptions.InvalidRequestException( 'No json send or missing actions parameters')
async def wrapped(*args): logger.debug('require: {permission}'.format(permission=permission)) # Supports class based views see web.View if isinstance(args[0], AbstractView): request = args[0].request params = args[0] # self else: request = args[-1] params = request # request session = await get_session(request) has_perm = permits(request, session, permission) if not has_perm: raise exceptions.NotAuthorizedException(permission) return (await func(params))
async def api_send_reset_password_token(request): logger.debug('send_reset_password_token') session = await get_session(request) try: data = await request.json() email = data['email'] except: raise exceptions.InvalidRequestException('Missing json data') user_query = request.db_session.query(User)\ .filter(User.email == email) if user_query.count(): user = user_query.one() # NOTE disable user cannot reset their password if not user.enable: raise exceptions.EmailNotFound( '{email} belong to a disabled user'.format(email=email)) context = { 'user': user, 'db_session': request.db_session, 'ws_session': session, 'method': 'create', 'data': { 'user_uid': user.get_uid() }, 'queue': request.app.queue } reset_password_token = Resetpasswordtoken() await reset_password_token.validate_and_save(context) resp_data = {'success': True} # TEST if config.get('env', 'production') in ['development', 'test']: resp_data['reset_password_token'] = reset_password_token.token return web.json_response(resp_data) # EMAIL NOT FOUND else: raise exceptions.EmailNotFound(email)
async def api_confirm_email(request): logger.debug('confirm_email') try: data = await request.json() email_confirmation_token = data['token'] except: raise exceptions.InvalidRequestException('Missing json data') session = await get_session(request) user = get_user_from_session(session, request.db_session) context = { 'user': user, 'db_session': request.db_session, 'ws_session': session, 'method': 'update', 'queue': request.app.queue } token_query = request.db_session.query(Emailconfirmationtoken)\ .filter(Emailconfirmationtoken.token == email_confirmation_token) if token_query.count(): email_confirmation_token = token_query.one() context['target'] = email_confirmation_token ret = email_confirmation_token.use(context) if ret: context['data'] = {'email_confirmed': True} del context['target'] await user.validate_and_save(context) context['method'] = 'read' resp_data = { 'success': True, 'user': await user.serialize(context) } return web.json_response(resp_data) # TOKEN NOT FOUND else: raise exceptions.TokenInvalidException('token not found')
async def api_validate_reset_password_token(request): logger.debug('validate_reset_password_token') session = await get_session(request) try: data = await request.json() reset_password_token = data['reset_password_token'] except: raise exceptions.InvalidRequestException('Missing json data') session['tz'] = data.get('user_timezone') token_query = request.db_session.query(Resetpasswordtoken)\ .filter(Resetpasswordtoken.token == reset_password_token) if token_query.count(): reset_password_token = token_query.one() user = request.db_session.query(User)\ .filter(User.mongo_id == reset_password_token.user_uid).one() context = { 'user': user, 'db_session': request.db_session, 'ws_session': session, 'method': 'update', 'target': reset_password_token, 'queue': request.app.queue } ret = reset_password_token.use(context) if ret: await set_session(user, request) context['method'] = 'read' resp_data = { 'success': True, 'user': await user.serialize(context) } return web.json_response(resp_data) # TOKEN NOT FOUND else: raise exceptions.TokenInvalidException('Token not found')
async def wrapped(*args): logger.debug('csrf_protected') # Supports class based views see web.View if isinstance(args[0], AbstractView): request = args[0].request params = args[0] # self else: request = args[-1] params = request # request session = await get_session(request) try: data = await request.json() except: raise exceptions.InvalidRequestException('No json send') csrf_token_session = session.get('csrf_token') csrf_token_request = data.get('token') if csrf_token_request != csrf_token_session: raise exceptions.CSRFMismatch() return (await func(params))
serv_generator = loop.create_server(handler, config.get('server_host'), config.get('server_port')) return serv_generator, handler, app if __name__ == '__main__': """ loop = uvloop.new_event_loop() asyncio.set_event_loop(loop) """ loop = asyncio.get_event_loop() serv_generator, handler, app = loop.run_until_complete(init(loop)) serv = loop.run_until_complete(serv_generator) logger.info('Server listening at %s' % str(serv.sockets[0].getsockname())) try: loop.run_forever() except KeyboardInterrupt: logger.debug('Server stopping...') finally: loop.run_until_complete(shutdown(serv, app, handler)) loop.close() logger.debug('Server stopped')
async def init(loop, config_args=None): # CONFIG config.configure(config_args) logger.debug('Env: {env}'.format(env=config.get('env'))) # SESSION redis_pool = await aioredis.create_pool(('localhost', 6379), db=config.get('redis_database', 0)) storage = redis_storage.RedisStorage(redis_pool) app = web.Application( loop=loop, middlewares=[session_middleware(storage), db_handler]) app.redis_pool = redis_pool # QUEUE app.queue = Queue(connection=Redis()) # WEBSOCKET """ app['websockets'] = [] """ handler = app.make_handler() # ROUTES for route in routes: app.router.add_route(route[0], route[1], route[2], name=route[3]) if config.get('env', 'production') == 'development': static_path = os.path.join(ROOT, 'dist-dev') else: if config.get('release', 'latest') == 'latest': latest_version_path = os.path.join(ROOT, 'releases', 'latest.txt') if os.path.exists(latest_version_path): with open(latest_version_path, 'r') as fd: release_version = fd.read() else: raise Exception("The latest.txt file doesn't exists") else: release_version = config.get('release') static_path = os.path.join(ROOT, 'releases', release_version) app.router.add_static('/', static_path, name='static') logger.info( "Serving static: {static_path}".format(static_path=static_path)) aiohttp_jinja2.setup(app, loader=jinja2.FileSystemLoader(static_path)) # PREPARE HOOK async def after_request(request, response): if hasattr(request, 'db_session'): request.db_session.end() request.db_session.db.client.close() db_session_gauge.dec() app.on_response_prepare.append(after_request) # SHUTDOWN app.on_shutdown.append(on_shutdown) serv_generator = loop.create_server(handler, config.get('server_host'), config.get('server_port')) # PROMETHEUS CLIENT if not config.get('env', 'production') == 'test': start_http_server(8001) return serv_generator, handler, app
if not config.get('env', 'production') == 'test': start_http_server(8001) return serv_generator, handler, app if __name__ == '__main__': """ loop = uvloop.new_event_loop() asyncio.set_event_loop(loop) """ loop = asyncio.get_event_loop() serv_generator, handler, app = loop.run_until_complete(init(loop)) serv = loop.run_until_complete(serv_generator) logger.debug('Server listening at %s' % str(serv.sockets[0].getsockname())) try: loop.run_forever() except KeyboardInterrupt: logger.debug('Server stopping...') finally: loop.run_until_complete(shutdown(serv, app, handler)) loop.close() logger.debug('Server stopped')
async def post(self): actions = await self.get_json_data() session = await get_session(self.request) author = get_user_from_session(session, self.request.db_session) read_context = { 'author': author, 'db_session': self.request.db_session, 'ws_session': session, 'method': 'read', 'queue': self.request.app.queue, } action_context = { 'author': author, 'db_session': self.request.db_session, 'ws_session': session, 'queue': self.request.app.queue } success = True response_data = [] error = [] for index, action in enumerate(actions): try: # RESPONSE response_data.append(dict()) response_data[index]['success'] = True response_data[index]['results'] = [] # ACTION action_name = action.get('action') if not action_name: raise exceptions.InvalidRequestException( 'Missing action in actions[{index}]'.format( index=index)) elif action_name not in self.action_list: raise exceptions.InvalidRequestException( 'Invalid action name: "{action_name}"'.format( action_name=action_name)) action_context['method'] = action_name # IMPORT MODEL model_name = action.get('model') if not model_name: raise exceptions.InvalidRequestException( 'Missing model in action') model_class = self.import_model(model_name) # CREATE if action_name == 'create': results = [model_class()] response_data[index]['total'] = 1 # QUERY else: # READ SPECIFIC RECORD uid = action.get('uid') if uid: base_query = self.request.db_session\ .query(model_class)\ .filter(model_class.mongo_id == uid) # BATCH elif action.get('uids'): uids = action.get('uids') base_query = self.request.db_session.query(model_class) response_data[index]['total'] = len(uids) base_query = base_query.in_('mongo_id', *uids) results = base_query.all() else: filters = action.get('filters') filters_wildcard = action.get('filters_wildcard') limit = action.get('limit') skip = action.get('skip') descending = action.get('descending') ascending = action.get('ascending') base_query = self.request.db_session.query(model_class) if limit: base_query = base_query.limit(limit) if skip: base_query = base_query.skip(skip) if descending: base_query = base_query.descending(descending) if ascending: base_query = base_query.ascending(ascending) if filters: if 'uid' in filters: filters['mongo_id'] = filters['uid'] del filters['uid'] base_query = base_query.filter_by(**filters) if filters_wildcard: wildcard = [] for key, value in iter(filters_wildcard.items()): wildcard.append( getattr(model_class, key).regex('.*%s.*' % value, ignore_case=True)) base_query = base_query.or_(*wildcard) response_data[index]['total'] = base_query.count() results = base_query.all() # PROCESSING RESULTS for result in results: # AUTHORIZATION CHECK logger.debug('action_context = {action_context}'.format( action_context=action_context)) if not await result.method_autorized(action_context): raise exceptions.NotAuthorizedException( '{author} not authorized to {action_name} {result}' .format(author=author, action_name=action_name, result=result)) # APPLY ACTION # CREATE & UPDATE if action_name in ['create', 'update']: data = action.get('data') if not data: raise exceptions.InvalidRequestException( 'Missing data in action') action_context['data'] = data sane_data = await result.sanitize_data(action_context) action_context['data'] = sane_data # BEFORE HOOK await getattr( result, 'before_{action_name}'.format( action_name=action_name))(action_context) await result.validate_and_save(action_context) # AFTER HOOK await getattr( result, 'after_{action_name}'.format( action_name=action_name))(action_context) # DELETE elif action_name == 'delete': await result.before_delete(action_context) self.request.db_session.remove(result, safe=True) await result.after_delete(action_context) if not action.get('total_only', False) \ and not action_name == 'delete': # READ # NOTE the authorization check has already # been performed for the read if not action_name == 'read': logger.debug( 'read_context = {read_context}'.format( read_context=read_context)) if not await result.method_autorized(read_context): raise exceptions.NotAuthorizedException( '{author} not authorized to {action_name} {result}' # noqa .format( author=author, action_name=read_context.get('method'), result=result)) response_data[index]['results'].append( await result.serialize(read_context)) except Exception as e: success = False tb = traceback.format_exc() logger.error('Request HandledException<{exception}>'.format( exception=str(tb))) if isinstance(e, exceptions.ServerBaseException): error_msg = e.get_name() else: serverside_unhandled_exception_counter.inc() error_msg = 'ServerSideError' response_data[index] = {'success': False, 'error': error_msg} error.append(error_msg) # RESPONSE trimmed_response_data = self.trim_response_data( success, response_data, error) return web.json_response(trimmed_response_data)
config.get('server_host'), config.get('server_port') ) return serv_generator, handler, app if __name__ == '__main__': """ loop = uvloop.new_event_loop() asyncio.set_event_loop(loop) """ loop = asyncio.get_event_loop() serv_generator, handler, app = loop.run_until_complete(init(loop)) serv = loop.run_until_complete(serv_generator) logger.info('Server listening at %s' % str(serv.sockets[0].getsockname())) try: loop.run_forever() except KeyboardInterrupt: logger.debug('Server stopping...') finally: loop.run_until_complete(shutdown(serv, app, handler)) loop.close() logger.debug('Server stopped')
async def index(request): logger.debug('index') return {}