async def mutate(_, info: ResolveInfo, new_title: str): """ Mutation handler Args: info: Resolve information new_title: Title of the new to remove like Returns: mutation """ user_id: int = info.context['request'].user['id'] new_service: NewService = container.get('new_service') user_service: UserService = container.get('user_service') with container.get('session_provider')(read_only=False): new: NewModel = await new_service.read_one(title=new_title) if new: user: UserModel = await user_service.read_one(id=user_id) if new in user.new_likes: user.new_likes.remove(new) await user_service.update(user) return DeleteNewLike(ok=True) else: raise ValueError(f'New {new_title} not liked yet') else: raise ValueError(f'New {new_title} not found')
def init_uaa(app: Application) -> Application: """ Initialize the web application Args: app: configuration profile to use Returns: web application initialized """ load() setup_event_bus() ElasticAPM(app, container.get('apm')) storage_engine: Engine = container.get('storage_engine') init_sql_db(BASE, storage_engine, alembic_ini_path=ALEMBIC_INI_PATH) if not sql_health_check(storage_engine): sys.exit(1) HealthCheck(app, health_check) users_view.setup_routes(app) auth_view.setup_routes(app) app.middlewares.append(error_middleware) app.middlewares.append(auth_middleware) app.middlewares.append(validation_middleware) return app
async def mutate(_, info, new_title: str): """ Mutation handler which likes the new specified Args: info: mutation resolving info new_title: associated new title Returns: create mutation """ user_id: int = info.context['request'].user['id'] new_service: NewService = container.get('new_service') user_service: UserService = container.get('user_service') with container.get('session_provider')(read_only=False): new: NewModel = await new_service.read_one(title=new_title) if new: user: UserModel = await user_service.read_one(id=user_id) user.new_likes.append(new) await user_service.update(user) return LikeNew(ok=True) else: raise ValueError(f'New {new_title} not found')
async def mutate(_, info: ResolveInfo, source_name: str): """ Mutation handler Args: info: Resolve information source_name: Name of the source to unfollow Returns: mutation """ user_id: int = info.context['request'].user['id'] source_service: SourceService = container.get('source_service') user_service: UserService = container.get('user_service') with container.get('session_provider')(read_only=False): source: SourceModel = await source_service.read_one( name=source_name) if source: user: UserModel = await user_service.read_one(id=user_id) if source in user.source_follows: user.source_follows.remove(source) await user_service.update(user) return UnfollowSource(ok=True) else: raise ValueError('Source not followed yet') else: raise ValueError(f'Source {source_name} not found')
async def mutate(_, info, source_name: str): """ Mutation handler which creates the association of the current user with the named source Args: info: mutation resolving info source_name: name of the source to follow Returns: create mutation """ user_id: int = info.context['request'].user['id'] source_service: SourceService = container.get('source_service') user_service: UserService = container.get('user_service') with container.get('session_provider')(read_only=False): source: SourceModel = await source_service.read_one( name=source_name) if source: user: UserModel = await user_service.read_one(id=user_id) user.source_follows.append(source) await user_service.update(user) return FollowSource(ok=True) else: raise ValueError(f'Source {source_name} not found')
async def mutate(_, info: ResolveInfo, newspaper_name: str): """ Mutation handler Args: info: Resolve information newspaper_name: Name of the newspaper to unfollow Returns: mutation """ user_id: int = info.context['request'].user['id'] newspaper_service: NewspaperService = container.get( 'newspaper_service') user_service: UserService = container.get('user_service') with container.get('session_provider')(read_only=False): newspaper: NewspaperModel = await newspaper_service.read_one( name=newspaper_name) if newspaper: user: UserModel = await user_service.read_one(id=user_id) if newspaper in user.newspaper_follows: user.newspaper_follows.remove(newspaper) await user_service.update(user) return UnfollowNewspaper(ok=True) else: raise ValueError('Newspaper not followed yet') else: raise ValueError(f'Newspaper {newspaper_name} not found')
async def mutate(_, info, newspaper_name: str): """ Mutation handler which creates the named newspaper follow with the current user Args: info: mutation resolving info newspaper_name: name of the newspaper to follow Returns: create mutation """ user_id: int = info.context['request'].user['id'] newspaper_service: NewspaperService = container.get( 'newspaper_service') user_service: UserService = container.get('user_service') with container.get('session_provider')(read_only=False): newspaper: NewspaperModel = await newspaper_service.read_one( name=newspaper_name) if newspaper: user: UserModel = await user_service.read_one(id=user_id) if newspaper.user_id != user_id: user.newspaper_follows.append(newspaper) await user_service.update(user) return FollowNewspaper(ok=True) else: raise ValueError( f'Impossible to follow your own newspaper') else: raise ValueError(f'Newspaper {newspaper_name} not found')
async def authenticate(self, request: Request) -> Response: """ Request to authenticate an user Args: request: input REST request Returns: json REST response with the authentication token """ LOGGER.info('REST request to authenticate an user') try: username = request['data']['username'] password = request['data']['password'] except Exception as ex: raise HTTPBadRequest(text=str(ex)) from ex auth_service: AuthService = container.get('auth_service') token_json = await auth_service.authenticate(username, password) token_response = json_response(token_json, status=200) token_response.set_cookie(name='JWT_TOKEN', value=token_json['token'], httponly=True) return token_response
async def post_create_user(self, request: Request) -> Response: """ Request to create an user Args: request: input REST request Returns: json REST response with the created user """ LOGGER.info('REST request to create user') try: username = request['data']['username'] password = request['data']['password'] first_name = request['data']['first_name'] last_name = request['data']['last_name'] email = request['data']['email'] except Exception as ex: raise HTTPBadRequest(text=str(ex)) from ex user_service: UserService = container.get('user_service') user_created = await user_service.create_user(username, password, first_name, last_name, email) return json_response(dict(user_created), status=200)
async def resolve_news(self, _, source: str = None, hydration: bool = None, sentiment: float = None, higher: bool = True, from_date: datetime = None, to_date: datetime = None) -> List[dict]: """ News list graphql query Args: source: news source filter hydration: news hydration flag filter sentiment: news sentiment threshold filter higher: True if the sentiment filter searches for higher values, False otherwise from_date: news date start filter to_date: news date end filter Returns: list of queried news """ LOGGER.info('Resolving multiple news') news_service: NewsService = container.get('news_service') return [ new.dto(CustomDateTime.DATE_FORMAT) for new in await news_service.get_news_filtered( source=source, hydration=hydration, sentiment=(sentiment, higher), from_date=from_date.timestamp() if from_date else None, to_date=to_date.timestamp() if to_date else None) ]
async def health_check() -> bool: """ Check the health status of the application checking the connection with the database Returns: True if the status is OK, False otherwise """ return mongo_health_check(container.get('storage_client')._mongo_client)
async def health_check() -> bool: """ Check the health status of the application Returns: True if the status is OK, False otherwise """ return sql_health_check(container.get('storage_engine'))
async def request_executor(inner_request): LOGGER.info('REST request to delete user') authenticated_user_username = inner_request.user['username'] user_service: UserService = container.get('user_service') await user_service.delete_user(authenticated_user_username) response = HTTPNoContent() response.del_cookie('JWT_TOKEN') return response
async def request_executor(inner_request): LOGGER.info('REST request to index new') try: new_data = from_dict(New, inner_request['data']) except Exception as ex: raise HTTPBadRequest(text=str(ex)) from ex index_service = container.get('index_service') indexed_new: NewModel = index_service.index_new(new_data) return json_response(dict(indexed_new), status=200)
def init_news_manager(app: Application) -> Application: """ Initialize the web application Args: app: configuration profile to use Returns: web application initialized """ load() container.get('locker').reset() container.get('news_consume_service') container.get('news_publish_service') HealthCheck(app, health_check) news_view.setup_routes(app) setup_graphql_routes(app, schema, get_logger()) app.middlewares.append(error_middleware) app.middlewares.append(uaa_auth_middleware) app.middlewares.append(validation_middleware) app.on_shutdown.append(shutdown) return app
def init_search_engine(app: Application) -> Application: """ Initialize the web application Args: app: configuration profile to use Returns: web application initialized """ load() ElasticAPM(app, container.get('apm')) storage_engine = container.get('storage_engine') if not sql_health_check(storage_engine): sys.exit(1) init_sql_db(BASE, storage_engine, alembic_ini_path=ALEMBIC_INI_PATH) session_provider = container.get('session_provider') BASE.query = session_provider.query_property HealthCheck(app, health_check) container.get('index_service') setup_event_bus() setup_graphql_routes(app, schema, get_logger(), middlewares=[SQLMiddleware(session_provider)]) index_views.setup_routes(app) app.middlewares.append(error_middleware) app.middlewares.append(uaa_auth_middleware) app.middlewares.append(validation_middleware) app.on_shutdown.append(shutdown) return app
async def resolve_new(self, _, title: str) -> dict: """ Single new graphql query Args: title: title to get new Returns: queried new """ LOGGER.info('Resolving new %s', title) news_service: NewsService = container.get('news_service') return asdict(await news_service.get_new_by_title(title))
async def resolve_detail(root, _) -> dict: """ New schema detail field resolver Args: root: root new schema instance Returns: root new detail """ LOGGER.info('Resolving new detail') news_manager_service: NewsManagerService = container.get( 'news_manager_service') return await news_manager_service.get_new_by_title(root.title)
async def middleware(request: Request) -> Response: apm = container.get('apm') try: apm.begin_transaction('request') response = await handler(request) apm.end_transaction(f'{request.method}{request.rel_url}', response.status) return response except HTTPException as ex: LOGGER.error('Request %s has failed with exception: %s', request, repr(ex)) apm.end_transaction(f'{request.method}{request.rel_url}', ex.status) apm.capture_exception() return json_error(ex.status, ex) except Exception as ex: LOGGER.error('Request %s has failed with exception: %s', request, repr(ex), exc_info=True) apm.end_transaction(f'{request.method}{request.rel_url}', 500) apm.capture_exception() return json_error(500, ex)
async def middleware(request: Request): request.user = None jwt_token = request.headers.getone('X-API-Key', None) if not jwt_token: jwt_token = request.cookies.get('JWT_TOKEN', None) if jwt_token: jwt_token = 'Bearer ' + jwt_token if jwt_token: payload = decode_token(jwt_token) try: user_service: UserService = container.get('user_service') user = await user_service.get_user_by_id(payload['user_id']) request.user = dict(user) if user else None except KeyError: raise HTTPUnauthorized(reason='Wrong authorization token') return await handler(request)
def handle_new(self, _, __, ___, body: str): """ Handle a new with the received data Args: body: message body with the new to handle """ LOGGER.info('Handling new') apm = container.get('apm') apm.begin_transaction('consume') try: body = json.loads(body) new = from_dict(New, body) asyncio.run(self._handle_new(new)) apm.end_transaction('New handle', 'OK') except Exception as ex: LOGGER.error('Error while updating new %s', str(ex), exc_info=True) apm.end_transaction('New handle', 'FAIL') apm.capture_exception()
def index_message(self, _, __, ___, body: str): """ Index the information from the received message Args: body: message body with the new data """ apm = container.get('apm') apm.begin_transaction('consume') try: body = json.loads(body) LOGGER.info('Indexing new %s', body['title']) new = from_dict(New, body) asyncio.run(self.index_new(new)) apm.end_transaction('New index', 'OK') except Exception as ex: LOGGER.error('Error while indexing new %s', str(ex), exc_info=True) apm.end_transaction('New index', 'FAIL') apm.capture_exception()
async def validate_token(self, request: Request) -> Response: """ Request to validate a JWT token Args: request: input REST request Returns: json REST response with the authenticated user data """ LOGGER.info('REST request to validate JWT token') try: token = request['data']['token'] except Exception as ex: raise HTTPBadRequest(text=str(ex)) from ex auth_service: AuthService = container.get('auth_service') user = await auth_service.validate_token(token) return json_response(dict(user), status=200)
async def request_executor(inner_request): LOGGER.info('REST request to get all news') try: start_date = mktime( strptime(inner_request.rel_url.query['start_date'], self.DATE_FORMAT) ) if 'start_date' in inner_request.rel_url.query else None end_date = mktime( strptime(inner_request.rel_url.query['end_date'], self.DATE_FORMAT) ) if 'end_date' in inner_request.rel_url.query else None except Exception as ex: raise HTTPBadRequest(text=str(ex)) news_service: NewsService = container.get('news_service') news = list( map( lambda new: new.dto(self.DATE_FORMAT), await news_service.get_news_filtered(from_date=start_date, to_date=end_date))) return json_response(news, status=200)