Compare commits

..

12 Commits

Author SHA1 Message Date
Ferdinand Thiessen 1201505586 docs(migrations): Some documentation ++
continuous-integration/woodpecker the build failed Details
2021-12-22 00:57:00 +01:00
Ferdinand Thiessen 40424f9fd3 feat(docs): Add documentation on how to install tables 2021-12-22 00:57:00 +01:00
Ferdinand Thiessen e657241b42 fix(db): Remove print statement for debugging 2021-12-22 00:57:00 +01:00
Ferdinand Thiessen 88fc3b1ac8 feat(db): Add initial migrations for core Flaschengeist + balance and pricelist plugins 2021-12-22 00:57:00 +01:00
Ferdinand Thiessen 77be01b8cf feat(db): Add migrations support to plugins 2021-12-22 00:57:00 +01:00
Ferdinand Thiessen e5b4150ce3 fix(db): Add __repr__ to custom column types, same as done by SQLAlchemy 2021-12-22 00:57:00 +01:00
Ferdinand Thiessen 0698f3ea94 feat(db): Add database migration support, implements #19
Migrations allow us to keep track of database changes and upgrading databases if needed.
2021-12-22 00:56:49 +01:00
Ferdinand Thiessen 9bcba9c7f9 fix(users): Fix import error inside `set_roles`
continuous-integration/woodpecker the build failed Details
2021-12-22 00:37:52 +01:00
Ferdinand Thiessen 016ed7739a fix(db): Fix Serial column type for SQLite
continuous-integration/woodpecker the build failed Details
2021-12-22 00:36:41 +01:00
Ferdinand Thiessen 702b894f75 feat(tests): Added first unit test for the user controller
continuous-integration/woodpecker the build failed Details
2021-12-22 00:34:32 +01:00
Ferdinand Thiessen 519eac8f25 feat(ci): Added pipeline for tests
continuous-integration/woodpecker the build failed Details
Add all supported, meaning by flaschengeist, python versions.
Use slim image of python instead of alpine, because Pillow does not
provide any wheels for musllibc
2021-12-22 00:29:33 +01:00
Ferdinand Thiessen aaec6b43ae tests: Fix tests for current backend 2021-12-21 22:56:03 +01:00
10 changed files with 94 additions and 32 deletions

View File

@ -1,6 +1,6 @@
pipeline:
lint:
image: python:alpine
image: python:slim
commands:
- pip install black
- black --check --line-length 120 --target-version=py37 .

21
.woodpecker/test.yml Normal file
View File

@ -0,0 +1,21 @@
pipeline:
install:
image: python:${PYTHON}-slim
commands:
- python -m venv --clear venv
- export PATH=venv/bin:$PATH
- python -m pip install --upgrade pip
- pip install -v ".[tests]"
test:
image: python:${PYTHON}-slim
commands:
- export PATH=venv/bin:$PATH
- python -m pytest
matrix:
PYTHON:
- 3.10
- 3.9
- 3.8
- 3.7

View File

@ -101,7 +101,7 @@ def set_roles(user: User, roles: list[str], create=False):
Raises:
BadRequest if invalid arguments given or not all roles found while *create* is set to false
"""
from roleController import create_role
from .roleController import create_role
if not isinstance(roles, list) and any([not isinstance(r, str) for r in roles]):
raise BadRequest("Invalid role name")
@ -149,7 +149,7 @@ def get_user_by_role(role: Role):
return User.query.join(User.roles_).filter_by(role_id=role.id).all()
def get_user(uid, deleted=False):
def get_user(uid, deleted=False) -> User:
"""Get an user by userid from database
Args:
uid: Userid to search for

View File

@ -48,7 +48,7 @@ class Serial(TypeDecorator):
"""Same as MariaDB Serial used for IDs"""
cache_ok = True
impl = BigInteger().with_variant(mysql.BIGINT(unsigned=True), "mysql").with_variant(sqlite.INTEGER, "sqlite")
impl = BigInteger().with_variant(mysql.BIGINT(unsigned=True), "mysql").with_variant(sqlite.INTEGER(), "sqlite")
# https://alembic.sqlalchemy.org/en/latest/autogenerate.html?highlight=custom%20column#affecting-the-rendering-of-types-themselves
def __repr__(self) -> str:

View File

@ -30,13 +30,14 @@ install_requires =
SQLAlchemy >= 1.4.28
toml
werkzeug >= 2.0
PyMySQL;platform_system=='Windows'
mysqlclient;platform_system!='Windows'
[options.extras_require]
argon = argon2-cffi
ldap = flask_ldapconn; ldap3
test = pytest; coverage
tests = pytest; pytest-depends; coverage
mysql =
PyMySQL;platform_system=='Windows'
mysqlclient;platform_system!='Windows'
[options.package_data]
* = *.toml

View File

@ -3,8 +3,7 @@ import tempfile
import pytest
from flaschengeist import database
from flaschengeist.app import create_app, install_all
from flaschengeist.app import create_app
# read in SQL for populating test data
with open(os.path.join(os.path.dirname(__file__), "data.sql"), "r") as f:
@ -25,12 +24,14 @@ def app():
app = create_app(
{
"TESTING": True,
"DATABASE": {"file_path": f"/{db_path}"},
"DATABASE": {"engine": "sqlite", "database": f"/{db_path}"},
"LOGGING": {"level": "DEBUG"},
}
)
with app.app_context():
install_all()
database.db.create_all()
database.db.session.commit()
engine = database.db.engine
with engine.connect() as connection:
for statement in _data_sql:

View File

@ -1,4 +1,8 @@
INSERT INTO user ('userid', 'firstname', 'lastname', 'mail', 'id') VALUES ('user', 'Max', 'Mustermann', 'abc@def.gh', 1);
INSERT INTO "user" ('userid', 'firstname', 'lastname', 'mail', 'deleted', 'id') VALUES ('user', 'Max', 'Mustermann', 'abc@def.gh', 0, 1);
INSERT INTO "user" ('userid', 'firstname', 'lastname', 'mail', 'deleted', 'id') VALUES ('deleted_user', 'John', 'Doe', 'doe@example.com', 1, 2);
-- Password = 1234
INSERT INTO user_attribute VALUES(1,1,'password',X'800495c4000000000000008cc0373731346161336536623932613830366664353038656631323932623134393936393561386463353536623037363761323037623238346264623833313265323333373066376233663462643332666332653766303537333564366335393133366463366234356539633865613835643661643435343931376636626663343163653333643635646530386634396231323061316236386162613164373663663333306564306463303737303733336136353363393538396536343266393865942e');
INSERT INTO session ('expires', 'token', 'lifetime', 'id', 'user_id') VALUES ('2999-01-01 00:00:00', 'f4ecbe14be3527ca998143a49200e294', 600, 1, 1);
INSERT INTO session ('expires', 'token', 'lifetime', 'id', 'user_id') VALUES ('2999-01-01 00:00:00', 'f4ecbe14be3527ca998143a49200e294', 600, 1, 1);
-- ROLES
INSERT INTO role ('name', 'id') VALUES ('role_1', 1);
INSERT INTO permission ('name', 'id') VALUES ('permission_1', 1);

View File

@ -15,9 +15,9 @@ def test_login(client):
# Login successful
assert result.status_code == 201
# User set correctly
assert json["user"]["userid"] == USERID
assert json["userid"] == USERID
# Token works
assert client.get("/auth", headers={"Authorization": f"Bearer {json['session']['token']}"}).status_code == 200
assert client.get("/auth", headers={"Authorization": f"Bearer {json['token']}"}).status_code == 200
def test_login_decorator(client):

View File

@ -1,17 +0,0 @@
import pytest
from werkzeug.exceptions import BadRequest
import flaschengeist.plugins.events.event_controller as event_controller
from flaschengeist.plugins.events.models import EventType
VALID_TOKEN = "f4ecbe14be3527ca998143a49200e294"
EVENT_TYPE_NAME = "Test Type"
def test_create_event_type(app):
with app.app_context():
type = event_controller.create_event_type(EVENT_TYPE_NAME)
assert isinstance(type, EventType)
with pytest.raises(BadRequest):
event_controller.create_event_type(EVENT_TYPE_NAME)

52
tests/test_users.py Normal file
View File

@ -0,0 +1,52 @@
import pytest
from werkzeug.exceptions import BadRequest, NotFound
from flaschengeist.controller import roleController, userController
from flaschengeist.models.user import User
VALID_TOKEN = "f4ecbe14be3527ca998143a49200e294"
def test_get_user(app):
with app.app_context():
user = userController.get_user("user")
assert user is not None and isinstance(user, User)
assert user.userid == "user"
user = userController.get_user("deleted_user", deleted=True)
assert user is not None and isinstance(user, User)
assert user.userid == "deleted_user"
with pytest.raises(NotFound):
user = userController.get_user("__does_not_exist__")
with pytest.raises(NotFound):
user = userController.get_user("__does_not_exist__", deleted=True)
with pytest.raises(NotFound):
user = userController.get_user("deleted_user")
def test_set_roles(app):
with app.app_context():
user = userController.get_user("user")
userController.set_roles(user, [])
assert user.roles_ == []
userController.set_roles(user, ["role_1"])
assert len(user.roles_) == 1 and user.roles_[0].id == 1
# Test unknown role + no create flag -> raise no changes
with pytest.raises(BadRequest):
userController.set_roles(user, ["__custom__"])
assert len(user.roles_) == 1
userController.set_roles(user, ["__custom__"], create=True)
assert len(user.roles_) == 1 and user.roles_[0].name == "__custom__"
assert roleController.get("__custom__").id == user.roles_[0].id
userController.set_roles(user, ["__custom__"], create=True)
assert len(user.roles_) == 1
userController.set_roles(user, ["__custom__", "role_1"])
assert len(user.roles_) == 2
userController.set_roles(user, [])
assert len(user.roles_) == 0