async def create_setup_data( body: SetupDataPostModel, data_type: SetupDataType, access_token: str = Cookie(None), session: Session = Depends(get_session), ): """ Create a setup object and return it as json """ user_id = await get_logged_in_user(access_token) logger.info("Create setup data received", user_id=user_id, data_type=data_type, payload=body) model = MAPPING[data_type] obj = model(name=body.value, user_id=user_id) session.add(obj) try: session.commit() except Exception as exc: logger.exception("Something went wrong when saving the object") raise HTTPException(status_code=400, detail="Database error") from exc session.refresh(obj) logger.info( "Create setup data successfull", user_id=user_id, data_type=data_type, obj_id=obj.id, ) return obj
async def delete_swarm( swarm_id: uuid.UUID, access_token: str = Cookie(None), session: Session = Depends(get_session), ): """ Delete a swarm """ user_id = await get_logged_in_user(access_token) logger.info("Delete swarm received", user_id=user_id, swarm_id=swarm_id) swarm = session.query(Swarms).get(swarm_id) if swarm is None or swarm.deleted_at: raise HTTPException(status_code=404, detail="Swarm not found") if swarm.user_id != user_id: raise HTTPException(status_code=403) try: swarm.deleted_at = datetime.datetime.now() swarm.hive = None session.commit() except Exception as exc: logger.exception("Database error", swarm=swarm) raise HTTPException( status_code=400, detail="Couldn't delete the swarm in database") from exc logger.info("Delete swarm successfull", user_id=user_id, swarm_id=swarm_id)
async def post_swarm( data: SwarmPostModel, access_token: str = Cookie(None), session: Session = Depends(get_session), ): """ Create an Swarm object and return it as json """ user_id = await get_logged_in_user(access_token) logger.info("Post swarm received", user_id=user_id, payload=data) swarm = Swarms( health_status_id=data.health_status_id, queen_year=data.queen_year, user_id=user_id, ) session.add(swarm) try: session.commit() except Exception as exc: logger.exception("Database error", swarm=swarm) raise HTTPException( status_code=400, detail="Couldn't save the swarm in database") from exc logger.info("Post swarm successfull", user_id=user_id, swarm_id=swarm.id) return swarm
async def delete_hive( hive_id: uuid.UUID, access_token: str = Cookie(None), session: Session = Depends(get_session), ): """ Delete hive """ user_id = await get_logged_in_user(access_token) logger.info("Delete hive received", user_id=user_id, hive_id=hive_id) hive = session.query(Hives).get(hive_id) if hive is None or hive.deleted_at or hive.user_id != user_id: raise HTTPException(status_code=404) try: now = datetime.datetime.now() hive.deleted_at = now hive.apiary_id = None # TODO: how to manage swarm when hive is being deleted # if hive.swarm: # hive.swarm.deleted_at = now session.commit() except Exception as exc: logger.exception("Something went wrong when deleting the hive", hive=hive) raise HTTPException(status_code=400, detail="Database error") from exc logger.info("Delete hive successfull", user_id=user_id, hive_id=hive_id)
async def post_hive_comments( hive_id: uuid.UUID, data: PostCommentModel, access_token: str = Cookie(None), session: Session = Depends(get_session), ): """ Post a comment """ user_id = await get_logged_in_user(access_token) hive = session.query(Hives).get(hive_id) if not hive or hive.user_id != user_id or hive.deleted_at: raise HTTPException(status_code=404) comment = Comments( user_id=user_id, hive_id=hive.id, swarm_id=hive.swarm_id, comment=data.comment, type="user", date=data.date, event_id=data.event_id, ) session.add(comment) try: session.commit() except Exception as exc: logger.exception("Database error", comment=comment) raise HTTPException( status_code=400, detail="Couldn't save the comment in database") from exc return comment
async def put_swarm( data: SwarmPutModel, swarm_id: uuid.UUID, access_token: str = Cookie(None), session: Session = Depends(get_session), ): """ Modify a swarm """ user_id = await get_logged_in_user(access_token) logger.info("Put swarm received", user_id=user_id, swarm_id=swarm_id) swarm = session.query(Swarms).get(swarm_id) if swarm is None or swarm.deleted_at or swarm.user_id != user_id: raise HTTPException(status_code=404, detail="Swarm not found") if not (data.health_status_id or data.queen_year): raise HTTPException(status_code=400, detail="No data provided") swarm.health_status_id = data.health_status_id or swarm.health_status_id swarm.queen_year = data.queen_year or swarm.queen_year try: session.commit() except Exception as exc: logger.exception("Database error", swarm=swarm) raise HTTPException( status_code=400, detail="Couldn't update the swarm in database") from exc logger.info("Put swarm successfull", user_id=user_id, swarm_id=swarm_id)
async def delete_apiary( apiary_id: uuid.UUID, access_token: str = Cookie(None), session: Session = Depends(get_session), ): """ Delete apiary """ user_id = await get_logged_in_user(access_token) logger.info("Delete apiary received", user_id=user_id, apiary_id=apiary_id) apiary = session.query(Apiaries).get(apiary_id) if apiary is None or apiary.deleted_at or apiary.user_id != user_id: raise HTTPException(status_code=404) if apiary.nb_hives > 0: raise HTTPException(status_code=400, detail="Hives are linked to this apiary") try: apiary.deleted_at = datetime.datetime.utcnow() session.commit() except Exception as exc: logger.exception("Something went wrong when deleting the apiary", apiary=apiary) raise HTTPException(status_code=400, detail="Database error") from exc logger.info("Delete apiary successful", apiary_id=apiary_id, user_id=user_id)
async def put_comment( comment_id: uuid.UUID, data: PutCommentModel, access_token: str = Cookie(None), session: Session = Depends(get_session), ): """ Modify a comment """ user_id = await get_logged_in_user(access_token) comment = session.query(Comments).get(comment_id) if not comment or comment.user_id != user_id or comment.deleted_at: raise HTTPException(status_code=404) for key, value in data.dict().items(): if value is not None: setattr(comment, key, value) try: session.commit() except Exception as exc: logger.exception("Database error", comment=comment) raise HTTPException( status_code=400, detail="Couldn't update the comment in database") from exc
async def post_apiary( data: ApiaryPostModel, access_token: str = Cookie(None), session: Session = Depends(get_session), ): """ Create an Apiary object and return it as json """ user_id = await get_logged_in_user(access_token) logger.info("Post apiary received", user_id=user_id, payload=data) apiary = Apiaries( name=data.name, location=data.location, honey_type_id=data.honey_type, user_id=user_id, ) session.add(apiary) try: session.commit() except Exception as exc: logger.exception("Database error", apiary=apiary) raise HTTPException( status_code=400, detail="Couldn't save the apiary in database") from exc logger.info("Post apiary successfull", apiary_id=apiary.id, user_id=user_id) return apiary
async def update_apiary( body: ApiaryPutModel, apiary_id: uuid.UUID, access_token: str = Cookie(None), session: Session = Depends(get_session), ): """ Update an Apiary object """ user_id = await get_logged_in_user(access_token) logger.info("Put apiary received", user_id=user_id, payload=body, apiary_id=apiary_id) if all(v is None for v in body.dict().values()): raise HTTPException(400, detail="No argument provided") apiary = session.query(Apiaries).get(apiary_id) if apiary is None or apiary.deleted_at or apiary.user_id != user_id: raise HTTPException(status_code=404) for key, value in body.dict().items(): if value is not None: setattr(apiary, key, value) try: session.commit() except Exception as exc: logger.exception("Something went wrong when updating the apiary", apiary=apiary) raise HTTPException(status_code=400, detail="Database error") from exc logger.info("Put apiary successfull", apiary_id=apiary_id, user_id=user_id)
async def post_hive( data: HivePostModel, access_token: str = Cookie(None), session: Session = Depends(get_session), ): """ Create an Hive object and return it as json """ user_id = await get_logged_in_user(access_token) logger.info("Post hive received", user_id=user_id, payload=data) hive = Hives( name=data.name, condition_id=data.condition_id, owner_id=data.owner_id, swarm_id=data.swarm_id, apiary_id=data.apiary_id, user_id=user_id, ) session.add(hive) try: session.commit() except Exception as exc: logger.exception("Database error", hive=hive) raise HTTPException( status_code=400, detail="Couldn't save the hive in database") from exc logger.info("Post hive successfull", user_id=user_id, hive_id=hive.id) return hive
def send_rbmq_message(routing_key, content): rbmq_client = RBMQPublisher() try: rbmq_client.publish(routing_key=routing_key, content=content) except: logger.exception( "Could not publish rabbitmq message", routing_key=routing_key, content=content, ) return False finally: rbmq_client.close() return True
def create_user( user_data: UserModel, session: Session = Depends(get_session), language: str = Cookie(None), ): # validate data if language not in ("fr", "en"): language = "fr" if not helpers.validate_email(user_data.email): raise HTTPException(400, "Invalid email address") if not helpers.validate_password(user_data.password): raise HTTPException(400, "Invalid password") if session.query(exists().where(Users.email == user_data.email)).scalar(): raise HTTPException(400, "Email already exists") if session.query(exists().where( Credentials.username == user_data.username)).scalar(): raise HTTPException(400, "Username already exists") # create all objects user = Users(email=user_data.email) credentials = Credentials( user=user, username=user_data.username, password=helpers.get_password_hash(user_data.password), ) owner = Owners(user=user, name=user_data.username) try: session.add_all((user, credentials, owner)) session.commit() logger.info(f"User created: {user.email}", user_id=user.id, user_email=user.email) except Exception as exc: logger.exception(f"Could not create user {user_data.email}") raise HTTPException(400, "Database error when creating the user") from exc if not helpers.send_event_user_created(user=user, language=language): logger.error("User created but could not publish the rabbitmq message", user_id=user.id) return user
async def move_hive( hive_id: uuid.UUID, apiary_id: uuid.UUID, access_token: str = Cookie(None), session: Session = Depends(get_session), ): """ Move hive to a new apiary """ user_id = await get_logged_in_user(access_token) logger.info("Move hive received", user_id=user_id, hive_id=hive_id, new_apiary_id=apiary_id) hive = session.query(Hives).get(hive_id) if hive is None or hive.user_id != user_id or hive.deleted_at: raise HTTPException(status_code=404, detail="Hive not found") apiary = session.query(Apiaries).get(apiary_id) if apiary is None or apiary.user_id != user_id or apiary.deleted_at: raise HTTPException(status_code=404, detail="Apiary not found") try: hive.apiary = apiary session.commit() except Exception as exc: logger.exception( "Something went wrong while moving a hive to a new apiary", hive=hive, apiary=apiary, ) raise HTTPException(status_code=400, detail="Database error") from exc logger.info( "Apiary successfully moved", user_id=user_id, new_apiary_id=apiary_id, hive_id=hive_id, )
async def delete_setup_data( data_type: SetupDataType, obj_id: uuid.UUID, access_token: str = Cookie(None), session: Session = Depends(get_session), ): """ Update a setup object and return it as json """ user_id = await get_logged_in_user(access_token) logger.info( "Delete setup data received", user_id=user_id, data_type=data_type, obj_id=obj_id, ) model = MAPPING[data_type] obj = session.query(model).get(obj_id) if obj is None: raise HTTPException(status_code=404) if obj.user_id != user_id: raise HTTPException(status_code=403) try: obj.deleted_at = datetime.datetime.utcnow() session.commit() except Exception as exc: logger.exception("Something went wrong when saving the object") raise HTTPException(status_code=400, detail="Database error") from exc logger.info( "Delete setup data successfull", user_id=user_id, data_type=data_type, obj_id=obj_id, )
def consume(self): while True: logger.info("Starting consuming...", queue=self.queue) try: with self.connection_manager as channel: self.setup(channel) channel.basic_consume(queue=self.queue, on_message_callback=self.process) channel.start_consuming() except KeyboardInterrupt: logger.info("Goodbye") self.connection_manager.close() return except pika.exceptions.StreamLostError: logger.warning( "RBMQ connection stream has been lost. Trying to reconnect" ) continue except: logger.exception("Critical error on consumer") self.connection_manager.close() raise
async def del_comment( comment_id: uuid.UUID, access_token: str = Cookie(None), session: Session = Depends(get_session), ): """ Delete a comment """ user_id = await get_logged_in_user(access_token) comment = session.query(Comments).get(comment_id) if not comment or comment.user_id != user_id or comment.deleted_at: raise HTTPException(status_code=404) comment.deleted_at = datetime.datetime.now() try: session.commit() except Exception as exc: logger.exception("Database error", comment=comment) raise HTTPException( status_code=400, detail="Couldn't mark a comment as deleted in database") from exc
def reset_user_password(properties, payload): logger.info( "Received message to reset a user password !", properties=properties, payload=payload, ) try: payload = json.loads(payload) except: logger.exception("Message is not in JSON format") return False required_keys = ("user", "language", "reset_link") if any(key not in payload for key in required_keys): logger.error("Incorrect message received - some keys are missing", payload=payload) return False send_email(payload, RESET_PASSWORD_EMAIL, reset_link=payload["reset_link"]) return True
def process(self, channel, method, properties, body): log_details = dict(properties=properties, body=body, routing_key=method.routing_key) logger.info(f"New message received {method.routing_key}", **log_details) handler = self.handlers.get(method.routing_key) if handler is None: logger.warning("Unknown routing key", **log_details) channel.basic_nack(method.delivery_tag, requeue=False) return try: success = handler(properties, body) if success: channel.basic_ack(method.delivery_tag) else: channel.basic_nack(method.delivery_tag, requeue=False) except: # pylint: disable=bare-except logger.exception("Critical error when handling rbmq message", **log_details) channel.basic_nack(method.delivery_tag, requeue=False)
def publish(self, routing_key, content, headers=None): if headers is None: headers = {} headers.update(self._get_default_headers()) properties = pika.BasicProperties(headers=headers) body = json.dumps(content, default=str) try: with self.connection_manager as channel: channel.basic_publish( exchange=self.exchange, routing_key=routing_key, body=body, properties=properties, ) except: logger.exception( "Fail to publish message in rbmq", body=body, properties=properties, routing_key=routing_key, ) raise
async def post_event( data: PostEventModel, access_token: str = Cookie(None), session: Session = Depends(get_session), ): """ Post an event """ user_id = await get_logged_in_user(access_token) if data.hive_id: hive = session.query(Hives).get(data.hive_id) if not hive or hive.user_id != user_id or hive.deleted_at: raise HTTPException(status_code=404) event = Events( user_id=user_id, hive_id=data.hive_id, due_date=data.due_date, type_id=data.type_id, status_id=data.status_id, title=data.title, description=data.description, ) session.add(event) try: session.commit() except Exception as exc: logger.exception("Database error", event=event) raise HTTPException( status_code=400, detail="Couldn't save the comment in database") from exc return event
async def put_hive( data: HivePutModel, hive_id: uuid.UUID, access_token: str = Cookie(None), session: Session = Depends(get_session), ): """ Update an Hive object """ user_id = await get_logged_in_user(access_token) logger.info("Put hive received", user_id=user_id, payload=data, hive_id=hive_id) if all(v is None for v in data.dict().values()): raise HTTPException(400, detail="No argument provided") hive = session.query(Hives).get(hive_id) if hive is None or hive.deleted_at or hive.user_id != user_id: raise HTTPException(status_code=404) for key, value in data.dict().items(): if value is not None: setattr(hive, key, value) try: session.commit() except Exception as exc: logger.exception("Database error", hive=hive) raise HTTPException( status_code=400, detail="Couldn't update the hive in database") from exc logger.info("Put hive successfull", user_id=user_id, hive_id=hive_id)
async def __call__(self, request: fastapi.Request, call_next): await self.before_request() if self.db: session = self.db.get_session() request.state.session = session try: response = await call_next(request) except: await self.exception_handler() logger.exception("Unexpected exception happened") response = fastapi.Response(status_code=500, content="Unexpected error happened") finally: if self.db: session.close() await self.after_request() return response
def welcome_new_user(properties, payload): logger.info( "Received message to welcome a new user !", properties=properties, payload=payload, ) try: payload = json.loads(payload) except: logger.exception("Message is not in JSON format") return False required_keys = ("user", "language", "activation_link") if any(key not in payload for key in required_keys): logger.error("Incorrect message received - some keys are missing", payload=payload) return False send_email(payload, WELCOME_EMAIL, activation_link=payload["activation_link"]) return True