Esempio n. 1
0
    def __init__(self, db_settings, testing=False):
        self.testing = testing

        self.engine = create_engine(
            URL(**db_settings),
            isolation_level="SERIALIZABLE",  # As we don't have a lot of IO, we can afford the highest isolation.
            echo=False,  # Echo the SQL queries if testing. NOTE: removed, this breaks the tests
            pool_pre_ping=True,  # Make sure the connection is OK before using it.
        )

        # noinspection PyArgumentEqualDefault
        self.session_maker = sessionmaker(
            bind=self.engine,
            autoflush=True,  # Flush at each query so that we can see our changes in the current session.
            autocommit=False,  # Never auto-commit, we want proper transactions!
        )

        if testing:
            self.session_maker = scoped_session(self.session_maker)

            # If testing, drop all tables & recreate them
            Base.metadata.drop_all(self.engine)
            Base.metadata.create_all(self.engine)

        else:
            # Create NainA table if not exists. (The other tables should already exist.)
            for retries in range(Database.RETRY_COUNT):
                try:
                    LOG.info("connecting_to_database")
                    Base.metadata.create_all(
                        self.engine,
                        tables=[NainA.__table__]
                    )
                    LOG.info("connection_established")
                    LOG.info("table_created")
                except OperationalError as e:
                    LOG.warning("could_not_connect_to_database", extra={'exception': e})
                    if retries + 1 == Database.RETRY_COUNT:
                        raise
                    time.sleep(Database.RETRY_INTERVAL)
Esempio n. 2
0
    def get_logs(self, ctx, username) -> List[str]:
        """
        User story: As an admin, I can retrieve the logs of a member, so I can help him troubleshoot their connection
        issues.

        :raise MemberNotFound
        """
        # Fetch all the devices of the member to put them in the request
        # all_devices = get_all_devices(s)
        # q = s.query(all_devices, Adherent.login.label("login"))
        # q = q.join(Adherent, Adherent.id == all_devices.columns.adherent_id)
        # q = q.filter(Adherent.login == username)
        # mac_tbl = list(map(lambda x: x.mac, q.all()))

        # Check that the user exists in the system.
        result, _ = self.member_repository.search_member_by(ctx,
                                                            username=username)
        if not result:
            raise MemberNotFoundError(username)

        # Do the actual log fetching.
        try:
            # TODO: Fetch all the devices and put them into this request.
            logs = self.logs_repository.get_logs(ctx, username, [])

            LOG.info('member_get_logs',
                     extra=log_extra(
                         ctx,
                         username=username,
                     ))

            return logs

        except LogFetchError:
            LOG.warning("log_fetch_failed",
                        extra=log_extra(ctx, username=username))
            return []  # We fail open here.
Esempio n. 3
0
    def new_membership(self,
                       ctx,
                       username,
                       duration,
                       payment_method,
                       start_str=None) -> None:
        """
        Core use case of ADH. Registers a membership.

        User story: As an admin, I can create a new membership record, so that a member can have internet access.
        :param payment_method:
        :param ctx: context
        :param username: username
        :param duration: duration of the membership in days
        :param start_str: optional start date of the membership

        :raise IntMustBePositiveException
        :raise NoPriceAssignedToThatDurationException
        :raise MemberNotFound
        :raise InvalidAdmin
        :raise UnknownPaymentMethod
        """
        if start_str is None:
            return self.new_membership(
                ctx,
                username,
                duration,
                payment_method,
                start_str=datetime.datetime.now().isoformat())

        if duration < 0:
            raise IntMustBePositive('duration')

        if duration not in self.config.PRICES:
            LOG.warning("create_membership_record_no_price_defined",
                        extra=log_extra(ctx, duration=duration))
            raise NoPriceAssignedToThatDuration(duration)

        start = string_to_date(start_str)
        end = start + datetime.timedelta(days=duration)

        # TODO check price.
        try:
            price = self.config.PRICES[duration]  # Expresed in EUR.
            price_in_cents = price * 100  # Expressed in cents of EUR.
            duration_str = self.config.DURATION_STRING.get(duration, '')
            title = f'Internet - {duration_str}'

            self.money_repository.add_member_payment_record(
                ctx, price_in_cents, title, username, payment_method)
            self.membership_repository.create_membership(
                ctx, username, start, end)
            self.member_repository.update_member(
                ctx, username, departure_date=end.isoformat())

        except InvalidAdmin:
            LOG.warning("create_membership_record_admin_not_found",
                        extra=log_extra(ctx))
            raise

        except UnknownPaymentMethod:
            LOG.warning("create_membership_record_unknown_payment_method",
                        extra=log_extra(ctx, payment_method=payment_method))
            raise

        LOG.info("create_membership_record",
                 extra=log_extra(ctx,
                                 username=username,
                                 duration_in_days=duration,
                                 start_date=start.isoformat()))