Added auth & improved database
All checks were successful
Build on push / prepare (push) Successful in 9s
Build on push / query (push) Successful in 18s
Build on push / core (push) Successful in 24s
Build on push / dependency (push) Successful in 17s
Build on push / database (push) Successful in 15s
Build on push / translation (push) Successful in 15s
Build on push / mail (push) Successful in 18s
Build on push / application (push) Successful in 19s
Build on push / auth (push) Successful in 16s

This commit is contained in:
2025-09-17 12:21:32 +02:00
parent 4625b626e6
commit 504dc5e188
76 changed files with 1849 additions and 302 deletions

View File

@@ -1,13 +1,15 @@
from typing import Optional
from cpl.application import ApplicationABC
from cpl.auth import KeycloakAdmin
from cpl.core.console import Console
from cpl.core.environment import Environment
from cpl.core.log import LoggerABC
from cpl.dependency import ServiceProviderABC
from model.city import City
from model.city_dao import CityDao
from model.user import User
from model.user_dao import UserDao
from model.user_repo import UserRepo
from model.user_repo_abc import UserRepoABC
class Application(ApplicationABC):
@@ -16,21 +18,16 @@ class Application(ApplicationABC):
self._logger: Optional[LoggerABC] = None
async def test_repos(self):
user_repo: UserRepo = self._services.get_service(UserRepoABC)
if len(await user_repo.get_users()) == 0:
user_repo.add_test_user()
Console.write_line("Users:")
for user in await user_repo.get_users():
Console.write_line(user.UserId, user.Name, user.City)
Console.write_line("Cities:")
for city in await user_repo.get_cities():
Console.write_line(city.CityId, city.Name, city.ZIP)
async def test_daos(self):
userDao: UserDao = self._services.get_service(UserDao)
cityDao: CityDao = self._services.get_service(CityDao)
Console.write_line(await userDao.get_all())
if len(await cityDao.get_all()) == 0:
city_id = await cityDao.create(City(0, "Haren", "49733"))
await userDao.create(User(0, "NewUser", city_id))
Console.write_line(await userDao.get_all())
async def configure(self):
@@ -41,3 +38,7 @@ class Application(ApplicationABC):
self._logger.debug(f"Environment: {Environment.get_environment()}")
await self.test_daos()
kc_admin: KeycloakAdmin = self._services.get_service(KeycloakAdmin)
x = kc_admin.get_users()
Console.write_line(x)

View File

@@ -0,0 +1,5 @@
from enum import Enum
class CustomPermissions(Enum):
test = "test"

View File

@@ -13,4 +13,5 @@ async def main():
if __name__ == "__main__":
import asyncio
asyncio.run(main())
loop = asyncio.get_event_loop()
loop.run_until_complete(main())

View File

@@ -0,0 +1,29 @@
from datetime import datetime
from typing import Optional
from cpl.core.typing import SerialId
from cpl.database.abc.db_model_abc import DbModelABC
class City(DbModelABC):
def __init__(
self,
id: int,
name: str,
zip: str,
deleted: bool = False,
editor_id: Optional[SerialId] = None,
created: Optional[datetime] = None,
updated: Optional[datetime] = None,
):
DbModelABC.__init__(self, id, deleted, editor_id, created, updated)
self._name = name
self._zip = zip
@property
def name(self) -> str:
return self._name
@property
def zip(self) -> str:
return self._zip

View File

@@ -0,0 +1,11 @@
from cpl.database.abc import DbModelDaoABC
from model.city import City
class CityDao(DbModelDaoABC[City]):
def __init__(self):
DbModelDaoABC.__init__(self, __name__, City, "city")
self.attribute(City.name, str)
self.attribute(City.zip, int)

View File

@@ -1,54 +0,0 @@
from cpl.database.abc.table_abc import TableABC
class CityModel(TableABC):
def __init__(self, name: str, zip_code: str, id=0):
self.CityId = id
self.Name = name
self.ZIP = zip_code
@staticmethod
def get_create_string() -> str:
return str(
f"""
CREATE TABLE IF NOT EXISTS `City` (
`CityId` INT(30) NOT NULL AUTO_INCREMENT,
`Name` VARCHAR(64) NOT NULL,
`ZIP` VARCHAR(5) NOT NULL,
PRIMARY KEY(`CityId`)
);
"""
)
@property
def insert_string(self) -> str:
return str(
f"""
INSERT INTO `City` (
`Name`, `ZIP`
) VALUES (
'{self.Name}',
'{self.ZIP}'
);
"""
)
@property
def udpate_string(self) -> str:
return str(
f"""
UPDATE `City`
SET `Name` = '{self.Name}',
`ZIP` = '{self.ZIP}',
WHERE `CityId` = {self.Id};
"""
)
@property
def delete_string(self) -> str:
return str(
f"""
DELETE FROM `City`
WHERE `CityId` = {self.Id};
"""
)

View File

@@ -1,9 +1,23 @@
from datetime import datetime
from typing import Optional
from cpl.core.typing import SerialId
from cpl.database.abc.db_model_abc import DbModelABC
class User(DbModelABC):
def __init__(self, id: int, name: str, city_id: int = 0):
DbModelABC.__init__(self, id)
def __init__(
self,
id: int,
name: str,
city_id: int = 0,
deleted: bool = False,
editor_id: Optional[SerialId] = None,
created: Optional[datetime] = None,
updated: Optional[datetime] = None,
):
DbModelABC.__init__(self, id, deleted, editor_id, created, updated)
self._name = name
self._city_id = city_id
@@ -13,4 +27,4 @@ class User(DbModelABC):
@property
def city_id(self) -> int:
return self._city_id
return self._city_id

View File

@@ -1,4 +1,3 @@
from cpl.database import InternalTables
from cpl.database.abc import DbModelDaoABC
from model.user import User
@@ -6,7 +5,7 @@ from model.user import User
class UserDao(DbModelDaoABC[User]):
def __init__(self):
DbModelDaoABC.__init__(self, __name__, User, InternalTables.users)
DbModelDaoABC.__init__(self, __name__, User, "users")
self.attribute(User.name, str)
self.attribute(User.city_id, int, db_name="CityId")

View File

@@ -1,56 +0,0 @@
from cpl.database.abc.table_abc import TableABC
from .city_model import CityModel
class UserModel(TableABC):
def __init__(self, name: str, city: CityModel, id=0):
self.UserId = id
self.Name = name
self.CityId = city.CityId if city is not None else 0
self.City = city
@staticmethod
def get_create_string() -> str:
return str(
f"""
CREATE TABLE IF NOT EXISTS `User` (
`UserId` INT(30) NOT NULL AUTO_INCREMENT,
`Name` VARCHAR(64) NOT NULL,
`CityId` INT(30),
FOREIGN KEY (`UserId`) REFERENCES City(`CityId`),
PRIMARY KEY(`UserId`)
);
"""
)
@property
def insert_string(self) -> str:
return str(
f"""
INSERT INTO `User` (
`Name`
) VALUES (
'{self.Name}'
);
"""
)
@property
def udpate_string(self) -> str:
return str(
f"""
UPDATE `User`
SET `Name` = '{self.Name}',
`CityId` = {self.CityId},
WHERE `UserId` = {self.UserId};
"""
)
@property
def delete_string(self) -> str:
return str(
f"""
DELETE FROM `User`
WHERE `UserId` = {self.UserId};
"""
)

View File

@@ -1,38 +0,0 @@
from cpl.database.abc.db_context_abc import DBContextABC
from .city_model import CityModel
from .user_model import UserModel
from .user_repo_abc import UserRepoABC
class UserRepo(UserRepoABC):
def __init__(self, db_context: DBContextABC):
UserRepoABC.__init__(self)
self._db_context: DBContextABC = db_context
def add_test_user(self):
city = CityModel("Haren", "49733")
city2 = CityModel("Meppen", "49716")
self._db_context.execute(city2.insert_string)
user = UserModel("TestUser", city)
self._db_context.execute(user.insert_string)
async def get_users(self) -> list[UserModel]:
users = []
results = await self._db_context.select("SELECT * FROM `User`")
for result in results:
users.append(UserModel(result[1], await self.get_city_by_id(result[2]), id=result[0]))
return users
async def get_cities(self) -> list[CityModel]:
cities = []
results = await self._db_context.select("SELECT * FROM `City`")
for result in results:
cities.append(CityModel(result[1], result[2], id=result[0]))
return cities
async def get_city_by_id(self, id: int) -> CityModel:
if id is None:
return None
result = await self._db_context.select(f"SELECT * FROM `City` WHERE `Id` = {id}")
return CityModel(result[1], result[2], id=result[0])

View File

@@ -1,22 +0,0 @@
from abc import ABC, abstractmethod
from .city_model import CityModel
from .user_model import UserModel
class UserRepoABC(ABC):
@abstractmethod
def __init__(self):
pass
@abstractmethod
def get_users(self) -> list[UserModel]:
pass
@abstractmethod
def get_cities(self) -> list[CityModel]:
pass
@abstractmethod
def get_city_by_id(self, id: int) -> CityModel:
pass

View File

@@ -2,6 +2,10 @@ CREATE TABLE IF NOT EXISTS `city` (
`id` INT(30) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(64) NOT NULL,
`zip` VARCHAR(5) NOT NULL,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
editorId INT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY(`id`)
);
@@ -9,6 +13,10 @@ CREATE TABLE IF NOT EXISTS `users` (
`id` INT(30) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(64) NOT NULL,
`cityId` INT(30),
deleted BOOLEAN NOT NULL DEFAULT FALSE,
editorId INT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (`cityId`) REFERENCES city(`id`),
PRIMARY KEY(`id`)
);

View File

@@ -1,14 +1,18 @@
from cpl import auth
from cpl.application.async_startup_abc import AsyncStartupABC
from cpl.auth import permission
from cpl.auth.permission.permissions_registry import PermissionsRegistry
from cpl.core.configuration import Configuration
from cpl.core.environment import Environment
from cpl.core.log import Logger, LoggerABC
from cpl.database import mysql
from cpl.database.abc.data_access_object_abc import DataAccessObjectABC
from cpl.database.service.migration_service import MigrationService
from cpl.database.service.seeder_service import SeederService
from cpl.dependency import ServiceCollection
from custom_permissions import CustomPermissions
from model.city_dao import CityDao
from model.user_dao import UserDao
from model.user_repo import UserRepo
from model.user_repo_abc import UserRepoABC
class Startup(AsyncStartupABC):
@@ -22,14 +26,20 @@ class Startup(AsyncStartupABC):
async def configure_services(self, services: ServiceCollection, environment: Environment):
services.add_module(mysql)
services.add_module(auth)
services.add_module(permission)
services.add_transient(DataAccessObjectABC, UserDao)
services.add_transient(DataAccessObjectABC, CityDao)
services.add_singleton(UserRepoABC, UserRepo)
services.add_singleton(LoggerABC, Logger)
PermissionsRegistry.with_enum(CustomPermissions)
provider = services.build_service_provider()
migration_service: MigrationService = provider.get_service(MigrationService)
migration_service.with_directory("./scripts")
await migration_service.migrate()
seeder_service: SeederService = provider.get_service(SeederService)
await seeder_service.seed()