Ejemplo n.º 1
0
    def test_single_transactions(self):
        user1 = self.session.query(models.User).get(1)
        user4 = self.session.query(models.User).get(4)
        user1_balance = user1.balance
        user4_balance = user4.balance

        # Negative or zero amount is forbidden
        for v in [0, -1, -2, -52, 0.3, 0.9, -1e7]:
            with self.assertRaises(ValueError):
                transactions.create_transaction(user1, user4, v, "", self.session, logging.getLogger())
        self.assertEqual(user1_balance, user1.balance)
        self.assertEqual(user4_balance, user4.balance)

        # Don't allow transactions of unknown users
        with self.assertRaises(ValueError):
            transactions.create_transaction(models.User(), user1, 42, "", self.session, logging.getLogger())

        total = 0
        for i, v in enumerate([3, 41, 51, 9, 3]):
            t = transactions.create_transaction(user4, user1, v, "", self.session, logging.getLogger())
            total += v
            self.assertEqual(t.id, i+1)
            self.assertEqual(t.amount, v)
            self.assertEqual(t.multi_transaction, None)
            self.assertEqual(user1.balance, user1_balance + total)
            self.assertEqual(user4.balance, user4_balance - total)
            self.assertEqual(i+1, len(self.session.query(models.Transaction).all()))
Ejemplo n.º 2
0
 def get_sample_users() -> List[models.User]:
     return [
         models.User(name="user1", balance=-42, external=True),
         models.User(name="user2", balance=51, external=False),
         models.User(name="user3", external=True),
         models.User(name="user4", balance=2, external=False),
         models.User(name="user5",
                     permission=False,
                     active=False,
                     external=False,
                     voucher_id=2),
         models.User(external=False),
         models.User(name="community",
                     external=False,
                     special=True,
                     balance=2,
                     permission=True)
     ]
Ejemplo n.º 3
0
    def make_special_user(self, community_name: str = "Community"):
        opts = {"echo": conf.SQLALCHEMY_ECHOING}
        if self.database_url.startswith("sqlite:"):
            opts = {"connect_args": {"check_same_thread": False}}
        engine = sqlalchemy.create_engine(self.database_url, **opts)
        session = sqlalchemy.orm.sessionmaker(autocommit=False,
                                              autoflush=False,
                                              bind=engine)()

        specials = session.query(models.User).filter_by(special=True).all()
        if len(specials) > 1:
            self.fail("CRITICAL ERROR. Please drop a bug report.")
        if len(specials) == 0:
            session.add(
                models.User(active=True,
                            special=True,
                            external=False,
                            permission=False,
                            name=community_name))
            session.commit()
        session.close()
Ejemplo n.º 4
0
    def test_multi_transactions(self):
        self.session.add_all(self.get_sample_users())
        self.session.commit()

        # Three people donate their money to one
        m1 = models.MultiTransaction(base_amount=4)
        self.session.add(m1)
        self.session.commit()
        self.session.add_all([
            models.Transaction(sender_id=2,
                               receiver_id=1,
                               amount=4,
                               multi_transaction_id=1),
            models.Transaction(sender_id=3,
                               receiver_id=1,
                               amount=4,
                               multi_transaction_id=1),
            models.Transaction(sender_id=4,
                               receiver_id=1,
                               amount=4,
                               multi_transaction_id=1)
        ])
        self.session.commit()
        self.assertEqual(m1.base_amount, 4)
        self.assertEqual(m1.schema.total_amount, 12)

        # Four people get paid by one equally
        m2 = models.MultiTransaction(base_amount=3)
        self.session.add(m2)
        self.session.commit()
        self.session.add_all([
            models.Transaction(sender_id=2,
                               receiver_id=1,
                               amount=2,
                               multi_transaction_id=2),
            models.Transaction(sender_id=2,
                               receiver_id=3,
                               amount=2,
                               multi_transaction_id=2),
            models.Transaction(sender_id=2,
                               receiver_id=5,
                               amount=2,
                               multi_transaction_id=2),
            models.Transaction(sender_id=2,
                               receiver_id=6,
                               amount=2,
                               multi_transaction_id=2)
        ])
        self.session.commit()
        self.assertEqual(m2.schema.total_amount, 8)

        # Six people pay to two guys unequally (6th person payer pays twice)
        self.session.add(models.User(balance=-132, external=False))
        self.session.add(models.User(balance=3, external=False))
        m3 = models.MultiTransaction(base_amount=10)
        self.session.add(m3)
        self.session.commit()
        self.session.add_all([
            models.Transaction(sender_id=1,
                               receiver_id=8,
                               amount=10,
                               multi_transaction_id=3),
            models.Transaction(sender_id=1,
                               receiver_id=9,
                               amount=10,
                               multi_transaction_id=3),
            models.Transaction(sender_id=2,
                               receiver_id=8,
                               amount=10,
                               multi_transaction_id=3),
            models.Transaction(sender_id=2,
                               receiver_id=9,
                               amount=10,
                               multi_transaction_id=3),
            models.Transaction(sender_id=3,
                               receiver_id=8,
                               amount=10,
                               multi_transaction_id=3),
            models.Transaction(sender_id=3,
                               receiver_id=9,
                               amount=10,
                               multi_transaction_id=3),
            models.Transaction(sender_id=4,
                               receiver_id=8,
                               amount=10,
                               multi_transaction_id=3),
            models.Transaction(sender_id=4,
                               receiver_id=9,
                               amount=10,
                               multi_transaction_id=3),
            models.Transaction(sender_id=5,
                               receiver_id=8,
                               amount=10,
                               multi_transaction_id=3),
            models.Transaction(sender_id=5,
                               receiver_id=9,
                               amount=10,
                               multi_transaction_id=3),
            models.Transaction(sender_id=6,
                               receiver_id=8,
                               amount=20,
                               multi_transaction_id=3),
            models.Transaction(sender_id=6,
                               receiver_id=9,
                               amount=20,
                               multi_transaction_id=3)
        ])
        self.session.commit()
        self.assertEqual(len(m3.transactions), 12)
        self.assertEqual(m3.schema.total_amount, 140)
Ejemplo n.º 5
0
def init_project(args: argparse.Namespace) -> int:
    settings = _settings.read_settings_from_json_source(False)
    if not settings:
        print(
            "No settings file found. A basic config will be created now interactively."
        )
        settings = _settings.get_default_config()

        if args.database:
            settings["database"]["connection"] = args.database
        else:
            print(
                "\nEnter the full database connection string below. It's required to make the "
                "project persistent. It uses an in-memory sqlite3 database by default (press "
                "Enter to use that default). Note that the in-memory database does not work "
                "properly in all environments. A persistent database is highly recommended."
            )
            settings["database"]["connection"] = input(
                "> ") or settings["database"]["connection"]

        with open(_settings.CONFIG_PATHS[0], "w") as f:
            json.dump(settings, f, indent=4)

    else:
        print(
            "A config file has been found. Consider removing it before continuing to avoid inconsistencies."
        )

    config = _settings.config.CoreConfig(
        **_settings.read_settings_from_json_source(False))
    database.init(config.database.connection, config.database.echo)
    session = database.get_new_session()

    if not args.no_community:
        specials = session.query(models.User).filter_by(special=True).all()
        if len(specials) > 1:
            raise RuntimeError("CRITICAL ERROR. Please drop a bug report.")
        if len(specials) == 0:
            session.add(
                models.User(active=True,
                            special=True,
                            external=False,
                            permission=False,
                            name=args.community))
            session.commit()

    if len(session.query(models.Application).all()) == 0 or args.application:
        name = args.application
        if not name:
            print(
                "\nThere's no registered application yet. Nobody can use the API "
                "without an application account. Skip this step by pressing Enter. "
                "Otherwise type in the name of the new application account below."
            )
            name = input("> ")

        if len(session.query(
                models.Application).filter_by(name=name).all()) > 0:
            print(
                f"An application with the given name {name!r} already "
                f"exists. Therefore, it can't be created. Exiting.",
                file=sys.stderr)
            session.flush()
            session.close()
            return 1

        passwd = args.password
        if not passwd and name:
            print(
                f"\nThe new application {name!r} needs a password to properly authenticate "
                "against the API in production later on. Enter the password below. "
                "Make sure that the password meets good length & strength standards. "
                "Note that pressing Enter will not create the new application!"
            )
            passwd = input("> ")

        if name and not passwd:
            print("No new application account created!")
        elif name and passwd:
            salt = secrets.token_urlsafe(16)
            password = models.Password(salt=salt,
                                       passwd=auth.hash_password(passwd, salt))
            session.add(models.Application(name=name, password=password))
            session.commit()

    session.flush()
    session.close()

    print("Done.")
    return 0