Пример #1
0
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)
Пример #2
0
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)
Пример #3
0
def desimpersonate(access_token: str = Cookie(None),
                   session: Session = Depends(get_session)):
    if not access_token:
        raise HTTPException(status_code=401,
                            detail="Missing authorization header")

    data = helpers.validate_jwt(access_token)
    if data is None or "impersonator_id" not in data:
        raise HTTPException(status_code=401)

    impersonator = (session.query(Users).options(joinedload(
        Users.permissions)).get(data["impersonator_id"]))
    if impersonator is None:
        logger.warning("Could not find impersonator. This is odd")
        raise HTTPException(status_code=400)

    logger.info(
        f"Desimpersonating from {impersonator.email}",
        impersonator_id=str(impersonator.id),
    )

    data = {
        "username": data["impersonator_username"],
        "email": data["impersonator_email"],
        "admin": impersonator.permissions is not None,
    }
    return {
        "access_token":
        helpers.generate_jwt(user_id=impersonator.id, extra_data=data)
    }
Пример #4
0
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)
Пример #5
0
def reset_user_password_request(
        data: PasswordResetRequestModel,
        session: Session = Depends(get_session),
        language: str = Cookie(None),
):
    user_credentials = (session.query(Credentials).join(Users).options(
        joinedload(Credentials.user)).filter(
            (Credentials.username == data.username)
            | (Users.email == data.username)).one_or_none())

    if user_credentials is None:
        raise HTTPException(status_code=404)

    reset_id = uuid.uuid4()
    if not helpers.send_event_user_password_reset(
            user=user_credentials.user, reset_id=reset_id, language=language):
        raise HTTPException(
            status_code=409,
            detail="Password reset requests cannot be handled at the moment",
        )

    user_credentials.reset_id = reset_id
    session.commit()

    logger.info(
        f"User password reset request successful: {user_credentials.user.email}",
        user_id=user_credentials.user.id,
        user_email=user_credentials.user.email,
    )

    return {"reset_id": str(reset_id)}
Пример #6
0
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
Пример #7
0
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)
Пример #8
0
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
Пример #9
0
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)
Пример #10
0
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
Пример #11
0
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
Пример #12
0
    def send(self, message):
        sender = message.email[SENDER]
        if sender not in self.open_connections:
            self.login(sender)

        client = self.open_connections[sender]
        client.send_message(message.email)

        logger.info(f"Email sent to {message.email[TO]}", email=message.email)
Пример #13
0
async def get_swarms(access_token: str = Cookie(None),
                     session: Session = Depends(get_session)):
    """
    Get a list of swarms
    """
    user_id = await get_logged_in_user(access_token)
    swarms = (session.query(Swarms).filter(Swarms.user_id == user_id,
                                           Swarms.deleted_at.is_(None)).all())
    logger.info("Get list of swarms successfull",
                user_id=user_id,
                nb_swarms=len(swarms))
    return swarms
Пример #14
0
async def get_hives(access_token: str = Cookie(None),
                    session: Session = Depends(get_session)):
    """
    Get a list of hives
    """
    user_id = await get_logged_in_user(access_token)
    hives = (session.query(Hives).filter(Hives.user_id == user_id,
                                         Hives.deleted_at.is_(None)).all())

    logger.info("Get list of hives successfull",
                user_id=user_id,
                nb_hives=len(hives))
    return hives
Пример #15
0
def initialize_user(properties, body):
    body = json.loads(body)
    user_id = body.get("user", {}).get("id")
    language = body.get("language")

    if user_id is None:
        logger.error(
            "Incorrect message received: missing 'user.id' key",
            body=body,
            properties=properties,
        )
        return False

    if language is None:
        logger.error(
            "Incorrect message received: missing 'language' key",
            body=body,
            properties=properties,
        )
        return False

    if language not in LANGUAGES:
        logger.error(f"Incorrect language: {body['languages']}")
        return False

    objects = [
        HiveConditions(name=item[language], user_id=user_id)
        for item in DEFAULT_HIVE_CONDITIONS
    ]
    objects.extend(
        HoneyTypes(name=item[language], user_id=user_id)
        for item in DEFAULT_HONEY_TYPES)
    objects.extend(
        SwarmHealthStatuses(name=item[language], user_id=user_id)
        for item in DEFAULT_SWARM_HEALTH_STATUSES)
    objects.extend(
        EventTypes(name=item[language], user_id=user_id)
        for item in DEFAULT_EVENT_TYPES)
    objects.extend(
        EventStatuses(name=item[language], user_id=user_id)
        for item in DEFAULT_EVENT_STATUSES)

    db_client = db()
    with db_client as session:
        session.bulk_save_objects(objects)
        session.commit()

    logger.info("Default data created for user", user_id=user_id)
    return True
Пример #16
0
    def close(self, emails=None):
        if emails is None:
            emails = list(self.open_connections.keys())
        elif isinstance(emails, str):
            emails = [emails]

        for email in emails:
            connection = self.open_connections.get(email)
            if connection is None:
                logger.info(f"No opened connection for {email}")
                continue

            connection.close()
            logger.info(f"Closed connection for {email}")
            del self.open_connections[email]
Пример #17
0
async def get_apiaries(
        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)
    apiaries = (session.query(Apiaries).filter(
        Apiaries.user_id == user_id, Apiaries.deleted_at.is_(None)).all())

    logger.info("Get list of apiaries sucessfull",
                user_id=user_id,
                nb_apiaries=len(apiaries))
    return apiaries
Пример #18
0
async def get_hive(
        hive_id: uuid.UUID,
        access_token: str = Cookie(None),
        session: Session = Depends(get_session),
):
    """
    Get a single hive
    """
    user_id = await get_logged_in_user(access_token)
    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)

    logger.info("Get hive successfull", hive_id=hive_id)
    return hive
Пример #19
0
def send_email(payload, template, **kwargs):
    language = payload["language"]
    receiver = payload["user"]["email"]
    sender = CONFIG.NOREPLY_EMAIL

    subject = template[language]["subject"]
    body = template[language]["body"].format(**kwargs)

    email = Email(sender=sender, receiver=receiver, subject=subject, body=body)

    client = EmailEngine()
    client.send(email)
    logger.info(f"Email '{subject}' sent to {receiver} !",
                payload=payload,
                subject=subject)
    client.close()
Пример #20
0
async def get_swarm(
        swarm_id: uuid.UUID,
        access_token: str = Cookie(None),
        session: Session = Depends(get_session),
):
    """
    Get a swarm
    """
    user_id = await get_logged_in_user(access_token)

    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")

    logger.info("Get swarm successfull", user_id=user_id, swarm_id=swarm_id)
    return swarm
Пример #21
0
    def login(self, email_address):
        if email_address in self.open_connections:
            return

        password_var_name = "{name}_EMAIL_PASSWORD".format(
            name=email_address.split("@")[0].upper())

        password = CONFIG.get(password_var_name)
        if password is None:
            logger.error(
                f"Trying to connect to an unknown email: {email_address}")
            raise ValueError(f"{email_address} is unknown")

        client = self.get_email_client()
        client.login(email_address, password)
        logger.info(f"Connected to {email_address}")

        self.open_connections[email_address] = client
Пример #22
0
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
Пример #23
0
def impersonate_user(
        user_id: uuid.UUID,
        access_token: str = Cookie(None),
        session: Session = Depends(get_session),
):
    user = session.query(Users).get(user_id)
    if user is None:
        raise HTTPException(status_code=404)

    if not access_token:
        raise HTTPException(status_code=401,
                            detail="Missing authorization header")

    data = helpers.validate_jwt(access_token)
    if data is None:
        raise HTTPException(status_code=401)

    impersonator = (session.query(Users).options(joinedload(
        Users.permissions)).get(data["user_id"]))
    if impersonator is None:
        raise HTTPException(status_code=401)

    if impersonator.permissions is None or not impersonator.permissions.impersonate:
        raise HTTPException(status_code=403)

    logger.info(
        f"Impersonating user: {user.email} (by {impersonator.email})",
        user_id=str(user.id),
        impersonator_id=str(impersonator.id),
    )

    data = {
        "username": f"{user.email} ({data['username']})",
        "email": user.email,
        "admin": user.permissions is not None,
        "impersonator_id": str(impersonator.id),
        "impersonator_email": data["email"],
        "impersonator_username": data["username"],
    }

    return {
        "access_token": helpers.generate_jwt(user_id=user_id, extra_data=data)
    }
Пример #24
0
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,
    )
Пример #25
0
async def get_setup_data(
        data_type: SetupDataType,
        access_token: str = Cookie(None),
        session: Session = Depends(get_session),
):
    """
    Get a setup object and return it as json
    """
    user_id = await get_logged_in_user(access_token)
    model = MAPPING[data_type]

    objects = (session.query(model).filter(model.user_id == user_id,
                                           model.deleted_at.is_(None)).all())

    logger.info(
        "Get setup object successfull",
        user_id=user_id,
        nb_object=len(objects),
        data_type=data_type,
    )
    return objects
Пример #26
0
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
Пример #27
0
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,
    )
Пример #28
0
 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
Пример #29
0
def authenticate_user(authorization: str = Header(None),
                      session: Session = Depends(get_session)):
    if not authorization:
        raise HTTPException(status_code=401,
                            detail="Missing authorization header")

    credentials = helpers.parse_authorization_header(authorization)
    if credentials is None:
        raise HTTPException(status_code=401,
                            detail="Could not parse access_token")

    user_credentials = (session.query(Credentials).join(Users).filter(
        or_(
            Credentials.username == credentials.username,
            Users.email == credentials.username,
        )).one_or_none())
    if user_credentials is None or user_credentials.password != credentials.password:
        raise HTTPException(status_code=401, detail="Wrong credentials")

    user_id = str(user_credentials.user_id)

    user_credentials.last_seen = datetime.datetime.utcnow()
    session.commit()

    logger.info(
        f"User logged in: {credentials.username}",
        user_id=user_id,
        username=user_credentials.username,
    )

    data = {
        "username": user_credentials.username,
        "email": user_credentials.user.email,
        "admin": user_credentials.user.permissions is not None,
    }

    return {
        "access_token": helpers.generate_jwt(user_id=user_id, extra_data=data)
    }
Пример #30
0
def activate_user(
        data: ActivateModel,
        session: Session = Depends(get_session),
):
    user = session.query(Users).get(data.user_id)

    if user is None:
        raise HTTPException(status_code=404)

    if user.activated:
        return JSONResponse(content="Already activated", status_code=200)

    if user.activation_id != data.activation_id:
        raise HTTPException(status_code=400)

    user.activation_id = None
    user.activated = True
    session.commit()

    logger.info(f"User activated: {user.email}",
                user_id=user.id,
                user_email=user.email)