diff --git a/docker-compose.yml b/docker-compose.yml index 596ae85..f234c89 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,7 +9,7 @@ services: #- POSTGRES_PASSWORD_FILE=/run/secrets/db-password - POSTGRES_PASSWORD=kontor healthcheck: - test: ["CMD-SHELL", "pg_isready", "-U", "kontor"] + test: ["CMD-SHELL", "pg_isready -U kontor"] interval: 1s timeout: 5s retries: 10 @@ -43,7 +43,7 @@ services: volumes: - mariadb-storage:/var/lib/mysql:rw kontor: - image: kontor:0.2.0-SNAPSHOT + image: kontor:0.1.0 restart: unless-stopped networks: - database @@ -54,7 +54,7 @@ services: postgres: condition: service_healthy kontor-api: - image: kontor-api:0.2.0-SNAPSHOT + image: kontor-api:0.1.0 restart: unless-stopped networks: - database diff --git a/kontor-api/.coverage b/kontor-api/.coverage deleted file mode 100644 index 44d6ca2..0000000 Binary files a/kontor-api/.coverage and /dev/null differ diff --git a/kontor-api/.gitignore b/kontor-api/.gitignore index 4c49bd7..3373a70 100644 --- a/kontor-api/.gitignore +++ b/kontor-api/.gitignore @@ -1 +1,2 @@ .env +.coverage diff --git a/kontor-api/Makefile b/kontor-api/Makefile index 2f20ba6..fa81df3 100644 --- a/kontor-api/Makefile +++ b/kontor-api/Makefile @@ -4,7 +4,7 @@ clean: find . -name '*.py[co]' -delete test: - DB_HOST=localhost uv run pytest -v --cov --cov-report=term --cov-report=html:coverage-report + DB_SERVER=localhost uv run pytest -v --cov --cov-report=term --cov-report=html:coverage-report docker: clean docker build --target=production -t kontor-api:0.2.0-SNAPSHOT . diff --git a/kontor-api/pyproject.toml b/kontor-api/pyproject.toml index 19fae94..672f36b 100644 --- a/kontor-api/pyproject.toml +++ b/kontor-api/pyproject.toml @@ -22,5 +22,6 @@ dependencies = [ "python-jose>=3.4.0", "python-multipart>=0.0.20", "natsort>=8.4.0", - "psycopg2>=2.9.10", + "psycopg2-binary>=2.9.10", + "pytest-cov>=6.1.1", ] diff --git a/kontor-api/src/apis/base.py b/kontor-api/src/apis/base.py index e969691..6c92e7f 100644 --- a/kontor-api/src/apis/base.py +++ b/kontor-api/src/apis/base.py @@ -3,6 +3,6 @@ from fastapi import APIRouter from src.apis.version1 import comic, media, tysc api_router = APIRouter(prefix="/api") -api_router.include_router(comic.router, prefix="/comics", tags=["comics"]) -api_router.include_router(media.router, prefix="/media", tags=["media"]) -api_router.include_router(tysc.router, prefix="/tysc", tags=["tysc"]) +api_router.include_router(comic.router, tags=["comics"]) +api_router.include_router(media.router, tags=["media"]) +api_router.include_router(tysc.router, tags=["tysc"]) diff --git a/kontor-api/src/core/config.py b/kontor-api/src/core/config.py index 6f8a4cf..a5e36c1 100644 --- a/kontor-api/src/core/config.py +++ b/kontor-api/src/core/config.py @@ -13,7 +13,7 @@ class Settings: DB_USER: str = os.getenv("DB_USER", "kontor") DB_PASSWORD: str = os.getenv("DB_PASSWORD", "kontor") - DB_SERVER: str = os.getenv("DB_SERVER", "mariadb") + DB_SERVER: str = os.getenv("DB_SERVER", "postgres") DB_PORT: str = os.getenv("DB_PORT", 5432) DB_DBNAME: str = os.getenv("DB_DBNAME", "kontor") DATABASE_URL: str = f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_SERVER}:{DB_PORT}/{DB_DBNAME}" diff --git a/kontor-api/src/db/models/admin.py b/kontor-api/src/db/models/admin.py index e16b0e0..caecff8 100644 --- a/kontor-api/src/db/models/admin.py +++ b/kontor-api/src/db/models/admin.py @@ -1,7 +1,6 @@ from datetime import datetime -from sqlalchemy import Column, ForeignKey, Integer, String -from sqlalchemy.dialects.mysql import BIT +from sqlalchemy import Column, ForeignKey, Integer, String, Boolean from sqlalchemy.orm import relationship, mapped_column, Mapped from src.db.models.base import Base, BaseMixin @@ -14,7 +13,7 @@ class Profile(Base, BaseMixin): user_name = Column(String(255), nullable=False) email = Column(String(255)) password = Column(String(255)) - enabled = Column(BIT(1)) + enabled = Column(Boolean) assignments = relationship("Assignment") tokens = relationship("Token") @@ -34,7 +33,7 @@ class Token(Base, BaseMixin): token = Column(String(255), nullable=False, unique=True) name = Column(String(255)) last_used_date: Mapped[datetime] = mapped_column() - enabled = Column(BIT(1)) + enabled = Column(Boolean) profile_id = Column(String(255), ForeignKey("profile.id"), nullable=False) profile = relationship("Profile", back_populates="tokens") @@ -56,7 +55,7 @@ class Assignment(Base, BaseMixin): class ModuleData(Base, BaseMixin): __tablename__ = "module_data" module_name = Column(String(255), nullable=False) - import_data = Column(BIT(1)) + import_data = Column(Boolean) class MailAccount(Base, BaseMixin): @@ -66,7 +65,7 @@ class MailAccount(Base, BaseMixin): protocol = Column(String(255)) user_name = Column(String(255)) password = Column(String(255)) - start_tls = Column(BIT(1)) + start_tls = Column(Boolean) class Mail(Base, BaseMixin): diff --git a/kontor-api/src/db/models/base.py b/kontor-api/src/db/models/base.py index 4a354e7..5ef8183 100644 --- a/kontor-api/src/db/models/base.py +++ b/kontor-api/src/db/models/base.py @@ -1,8 +1,7 @@ import uuid from datetime import datetime -from sqlalchemy import func, Column, String -from sqlalchemy.dialects.mysql import BIT +from sqlalchemy import func, Column, String, Boolean from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column @@ -25,7 +24,7 @@ class BaseVideoMixin: cloud_link = Column(String(255)) file_name = Column(String(255)) path = Column(String(255)) - review = Column(BIT(1)) + review = Column(Boolean) title = Column(String(255)) url = Column(String(255), unique=True) - should_download = Column(BIT(1)) + should_download = Column(Boolean) diff --git a/kontor-api/src/db/models/comic.py b/kontor-api/src/db/models/comic.py index 423ad7c..35962f3 100644 --- a/kontor-api/src/db/models/comic.py +++ b/kontor-api/src/db/models/comic.py @@ -1,7 +1,6 @@ from typing import Dict, List from natsort import natsorted -from sqlalchemy import Column, ForeignKey, Integer, String -from sqlalchemy.dialects.mysql import BIT +from sqlalchemy import Column, ForeignKey, Integer, String, Boolean from sqlalchemy.orm import relationship from src.db.models.base import Base, BaseMixin @@ -24,8 +23,8 @@ class Comic(Base, BaseMixin): title = Column(String(length=255), unique=True) publisher_id = Column(String, ForeignKey('publisher.id'), nullable=False) publisher = relationship("Publisher", back_populates="comics") - current_order = Column(BIT(1)) - completed = Column(BIT(1)) + current_order = Column(Boolean) + completed = Column(Boolean) issues = relationship("Issue", order_by="Issue.issue_number") story_arcs = relationship("StoryArc") trade_paperbacks = relationship("TradePaperback") @@ -81,8 +80,8 @@ class StoryArc(Base, BaseMixin): class Issue(Base, BaseMixin): __tablename__ = "issue" issue_number = Column(String(255)) - in_stock = Column(BIT(1)) - is_read = Column(BIT(1)) + in_stock = Column(Boolean) + is_read = Column(Boolean) comic_id = Column(String, ForeignKey("comic.id"), nullable=False) comic = relationship("Comic", back_populates="issues") volume_id = Column(String, ForeignKey("volume.id"), nullable=True) diff --git a/kontor-api/src/db/models/database.py b/kontor-api/src/db/models/database.py index 0d5998b..9a69627 100644 --- a/kontor-api/src/db/models/database.py +++ b/kontor-api/src/db/models/database.py @@ -13,7 +13,7 @@ from sqlalchemy.orm import sessionmaker from src.db.models.tysc import Card, CardSet, Rooster, Team, FieldPosition, Player, Vendor, Sport from src.db.models.comic import Issue, TradePaperback, StoryArc, Volume, ComicWork, Artist, Comic, Publisher, WorkType from src.db.models.bookshelf import ArticleAuthor, BookAuthor, BookshelfPublisher, Article, Book, Author -from src.db.models.admin import Mail, MailAccount, ModuleData, Role, User, Token, AuthorizationMatrix +from src.db.models.admin import Mail, MailAccount, ModuleData, Token, Assignment, Permission, Profile from src.db.models.metadata import MetaDataTable, MetaDataColumn from src.db.models.media import MediaVideo, MediaArticle, MediaFile, MediaActor, MediaActorFile @@ -79,10 +79,10 @@ class KontorDB: self.registry[MediaVideo.__tablename__] = MediaVideo self.registry[MetaDataColumn.__tablename__] = MetaDataColumn self.registry[MetaDataTable.__tablename__] = MetaDataTable - self.registry[AuthorizationMatrix.__tablename__] = AuthorizationMatrix + self.registry[Assignment.__tablename__] = Assignment self.registry[Token.__tablename__] = Token - self.registry[User.__tablename__] = User - self.registry[Role.__tablename__] = Role + self.registry[Profile.__tablename__] = Profile + self.registry[Permission.__tablename__] = Permission self.registry[ModuleData.__tablename__] = ModuleData self.registry[MailAccount.__tablename__] = MailAccount self.registry[Mail.__tablename__] = Mail diff --git a/kontor-api/src/db/models/media.py b/kontor-api/src/db/models/media.py index 4c0b21a..2b19aa6 100644 --- a/kontor-api/src/db/models/media.py +++ b/kontor-api/src/db/models/media.py @@ -6,8 +6,7 @@ from pathlib import Path import requests from bs4 import BeautifulSoup -from sqlalchemy import Column, String, ForeignKey -from sqlalchemy.dialects.mysql import BIT +from sqlalchemy import Column, String, ForeignKey, Boolean from sqlalchemy.orm import relationship from src.db.models.base import Base, BaseMixin, BaseVideoMixin @@ -30,10 +29,10 @@ class MediaFile(Base, BaseMixin, BaseVideoMixin): soup = BeautifulSoup(r.content, "html.parser") title = soup.title.string self.title = title - self.review = 0 + self.review = False except: self.title = None - self.review = 1 + self.review = True self.last_modified_date = datetime.now() def download_file(self, download_dir: str, dl_tool: str): @@ -45,12 +44,12 @@ class MediaFile(Base, BaseMixin, BaseVideoMixin): lines_list = output.splitlines() file_name = self.__parse_output__(lines_list) if file_name is None: - self.review = 1 - self.should_download = 1 + self.review = True + self.should_download = True self.file_name = None else: download_file = Path(file_name) - self.should_download = 0 + self.should_download = False self.file_name = download_file.name self.cloud_link = str(download_file.absolute()) self.last_modified_date = datetime.now() @@ -85,7 +84,7 @@ class MediaActorFile(Base, BaseMixin): class MediaArticle(Base, BaseMixin): __tablename__ = 'media_article' - review = Column(BIT(1)) + review = Column(Boolean) title = Column(String(255)) url = Column(String(255), unique=True) @@ -95,7 +94,7 @@ class MediaVideo(Base, BaseMixin): cloud_link = Column(String(255)) file_name = Column(String(255)) path = Column(String(255)) - review = Column(BIT(1)) + review = Column(Boolean) title = Column(String(255)) url = Column(String(255), unique=True) - should_download = Column(BIT(1)) + should_download = Column(Boolean) diff --git a/kontor-api/src/db/models/metadata.py b/kontor-api/src/db/models/metadata.py index 081c3af..131f325 100644 --- a/kontor-api/src/db/models/metadata.py +++ b/kontor-api/src/db/models/metadata.py @@ -1,5 +1,4 @@ -from sqlalchemy import Column, String, ForeignKey, Integer -from sqlalchemy.dialects.mysql import BIT +from sqlalchemy import Column, String, ForeignKey, Integer, Boolean from sqlalchemy.orm import relationship from src.db.models.base import Base, BaseMixin @@ -28,8 +27,8 @@ class MetaDataColumn(Base, BaseMixin): table = relationship("MetaDataTable", back_populates="table_columns") column_label = Column(String(255)) filter_label = Column(String(255)) - is_shown = Column(BIT(1)) - show_filter = Column(BIT(1)) + is_shown = Column(Boolean) + show_filter = Column(Boolean) ref_column = Column(String, nullable=True) def __repr__(self): diff --git a/kontor-api/src/db/models/tysc.py b/kontor-api/src/db/models/tysc.py index dae0417..d3c391d 100644 --- a/kontor-api/src/db/models/tysc.py +++ b/kontor-api/src/db/models/tysc.py @@ -1,5 +1,4 @@ -from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint -from sqlalchemy.dialects.mysql import BIT +from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Boolean from sqlalchemy.orm import relationship from src.db.models.base import Base, BaseMixin @@ -78,8 +77,8 @@ class CardSet(Base, BaseMixin): UniqueConstraint("name", "vendor_id"), ) name = Column(String(255), index=True) - parallel_set = Column(BIT(1)) - insert_set = Column(BIT(1)) + parallel_set = Column(Boolean) + insert_set = Column(Boolean) vendor_id = Column(String, ForeignKey("vendor.id"), nullable=False, index=True) vendor = relationship("Vendor", back_populates="card_sets") cards = relationship("Card") diff --git a/kontor-api/src/schema/comics/comic.py b/kontor-api/src/schema/comics/comic.py index feec39d..1c7f548 100644 --- a/kontor-api/src/schema/comics/comic.py +++ b/kontor-api/src/schema/comics/comic.py @@ -46,8 +46,8 @@ def get_comic_details(comic: Comic) -> ComicDetailsResponse | None: id=comic.id, created=str(comic.created_date), title=comic.title, - completed=(comic.completed == 1), - current_order=(comic.current_order == 1), + completed=comic.completed, + current_order=comic.current_order, publisher=comic.publisher.name, volumes=volumes, works=works diff --git a/kontor-api/src/schema/media/file.py b/kontor-api/src/schema/media/file.py index 2c468e8..44f6b4f 100644 --- a/kontor-api/src/schema/media/file.py +++ b/kontor-api/src/schema/media/file.py @@ -23,8 +23,8 @@ def get_file_details(mediafile: MediaFile) -> MediaFileResponse | None: file_name=mediafile.file_name, cloud_link=mediafile.cloud_link, url=str(mediafile.url), - review=(mediafile.review == 1), - should_download=(mediafile.should_download == 1)) + review=mediafile.review, + should_download=mediafile.should_download) #print(f"id: {mediafile.id}: review: {response.review} <- {mediafile.review}") #print(f"id: {mediafile.id}: download: {response.should_download} <- {mediafile.should_download}") return response @@ -35,11 +35,5 @@ def set_file(model: MediaFileResponse, mediafile: MediaFile) -> None: mediafile.url = model.url mediafile.title = model.title mediafile.last_modified_date = datetime.now() - if model.review: - mediafile.review = 1 - else: - mediafile.review = 0 - if model.should_download: - mediafile.should_download = 1 - else: - mediafile.should_download = 0 + mediafile.review = model.review + mediafile.should_download = model.should_download diff --git a/kontor-api/src/templates/components/check.html b/kontor-api/src/templates/components/check.html index b2b6263..41bf98c 100644 --- a/kontor-api/src/templates/components/check.html +++ b/kontor-api/src/templates/components/check.html @@ -1,4 +1,4 @@ -{% if check == 1 %} +{% if check %} {% else %} diff --git a/kontor-api/tests/test_main.py b/kontor-api/tests/test_main.py index 850d509..829f499 100644 --- a/kontor-api/tests/test_main.py +++ b/kontor-api/tests/test_main.py @@ -1,15 +1,15 @@ from fastapi.testclient import TestClient import pytest -from src.main import app +from src.main import kontor @pytest.fixture(name="client") def client_fixture(): - client = TestClient(app) + client = TestClient(kontor) yield client def test_get_artists(client: TestClient): - response = client.get("/comic/artists") + response = client.get("/api/comic/artists") assert response.status_code == 200 assert len(response.json()) == 5 diff --git a/kontor-api/uv.lock b/kontor-api/uv.lock index 1a9777f..2383d42 100644 --- a/kontor-api/uv.lock +++ b/kontor-api/uv.lock @@ -89,6 +89,35 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload_time = "2022-10-25T02:36:20.889Z" }, ] +[[package]] +name = "coverage" +version = "7.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/4f/2251e65033ed2ce1e68f00f91a0294e0f80c80ae8c3ebbe2f12828c4cd53/coverage-7.8.0.tar.gz", hash = "sha256:7a3d62b3b03b4b6fd41a085f3574874cf946cb4604d2b4d3e8dca8cd570ca501", size = 811872, upload_time = "2025-03-30T20:36:45.376Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f3/21/87e9b97b568e223f3438d93072479c2f36cc9b3f6b9f7094b9d50232acc0/coverage-7.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ac46d0c2dd5820ce93943a501ac5f6548ea81594777ca585bf002aa8854cacd", size = 211708, upload_time = "2025-03-30T20:35:47.417Z" }, + { url = "https://files.pythonhosted.org/packages/75/be/882d08b28a0d19c9c4c2e8a1c6ebe1f79c9c839eb46d4fca3bd3b34562b9/coverage-7.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:771eb7587a0563ca5bb6f622b9ed7f9d07bd08900f7589b4febff05f469bea00", size = 211981, upload_time = "2025-03-30T20:35:49.002Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1d/ce99612ebd58082fbe3f8c66f6d8d5694976c76a0d474503fa70633ec77f/coverage-7.8.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42421e04069fb2cbcbca5a696c4050b84a43b05392679d4068acbe65449b5c64", size = 245495, upload_time = "2025-03-30T20:35:51.073Z" }, + { url = "https://files.pythonhosted.org/packages/dc/8d/6115abe97df98db6b2bd76aae395fcc941d039a7acd25f741312ced9a78f/coverage-7.8.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:554fec1199d93ab30adaa751db68acec2b41c5602ac944bb19187cb9a41a8067", size = 242538, upload_time = "2025-03-30T20:35:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/cb/74/2f8cc196643b15bc096d60e073691dadb3dca48418f08bc78dd6e899383e/coverage-7.8.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aaeb00761f985007b38cf463b1d160a14a22c34eb3f6a39d9ad6fc27cb73008", size = 244561, upload_time = "2025-03-30T20:35:54.658Z" }, + { url = "https://files.pythonhosted.org/packages/22/70/c10c77cd77970ac965734fe3419f2c98665f6e982744a9bfb0e749d298f4/coverage-7.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:581a40c7b94921fffd6457ffe532259813fc68eb2bdda60fa8cc343414ce3733", size = 244633, upload_time = "2025-03-30T20:35:56.221Z" }, + { url = "https://files.pythonhosted.org/packages/38/5a/4f7569d946a07c952688debee18c2bb9ab24f88027e3d71fd25dbc2f9dca/coverage-7.8.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f319bae0321bc838e205bf9e5bc28f0a3165f30c203b610f17ab5552cff90323", size = 242712, upload_time = "2025-03-30T20:35:57.801Z" }, + { url = "https://files.pythonhosted.org/packages/bb/a1/03a43b33f50475a632a91ea8c127f7e35e53786dbe6781c25f19fd5a65f8/coverage-7.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:04bfec25a8ef1c5f41f5e7e5c842f6b615599ca8ba8391ec33a9290d9d2db3a3", size = 244000, upload_time = "2025-03-30T20:35:59.378Z" }, + { url = "https://files.pythonhosted.org/packages/6a/89/ab6c43b1788a3128e4d1b7b54214548dcad75a621f9d277b14d16a80d8a1/coverage-7.8.0-cp313-cp313-win32.whl", hash = "sha256:dd19608788b50eed889e13a5d71d832edc34fc9dfce606f66e8f9f917eef910d", size = 214195, upload_time = "2025-03-30T20:36:01.005Z" }, + { url = "https://files.pythonhosted.org/packages/12/12/6bf5f9a8b063d116bac536a7fb594fc35cb04981654cccb4bbfea5dcdfa0/coverage-7.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:a9abbccd778d98e9c7e85038e35e91e67f5b520776781d9a1e2ee9d400869487", size = 214998, upload_time = "2025-03-30T20:36:03.006Z" }, + { url = "https://files.pythonhosted.org/packages/2a/e6/1e9df74ef7a1c983a9c7443dac8aac37a46f1939ae3499424622e72a6f78/coverage-7.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:18c5ae6d061ad5b3e7eef4363fb27a0576012a7447af48be6c75b88494c6cf25", size = 212541, upload_time = "2025-03-30T20:36:04.638Z" }, + { url = "https://files.pythonhosted.org/packages/04/51/c32174edb7ee49744e2e81c4b1414ac9df3dacfcb5b5f273b7f285ad43f6/coverage-7.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:95aa6ae391a22bbbce1b77ddac846c98c5473de0372ba5c463480043a07bff42", size = 212767, upload_time = "2025-03-30T20:36:06.503Z" }, + { url = "https://files.pythonhosted.org/packages/e9/8f/f454cbdb5212f13f29d4a7983db69169f1937e869a5142bce983ded52162/coverage-7.8.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e013b07ba1c748dacc2a80e69a46286ff145935f260eb8c72df7185bf048f502", size = 256997, upload_time = "2025-03-30T20:36:08.137Z" }, + { url = "https://files.pythonhosted.org/packages/e6/74/2bf9e78b321216d6ee90a81e5c22f912fc428442c830c4077b4a071db66f/coverage-7.8.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d766a4f0e5aa1ba056ec3496243150698dc0481902e2b8559314368717be82b1", size = 252708, upload_time = "2025-03-30T20:36:09.781Z" }, + { url = "https://files.pythonhosted.org/packages/92/4d/50d7eb1e9a6062bee6e2f92e78b0998848a972e9afad349b6cdde6fa9e32/coverage-7.8.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad80e6b4a0c3cb6f10f29ae4c60e991f424e6b14219d46f1e7d442b938ee68a4", size = 255046, upload_time = "2025-03-30T20:36:11.409Z" }, + { url = "https://files.pythonhosted.org/packages/40/9e/71fb4e7402a07c4198ab44fc564d09d7d0ffca46a9fb7b0a7b929e7641bd/coverage-7.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b87eb6fc9e1bb8f98892a2458781348fa37e6925f35bb6ceb9d4afd54ba36c73", size = 256139, upload_time = "2025-03-30T20:36:13.86Z" }, + { url = "https://files.pythonhosted.org/packages/49/1a/78d37f7a42b5beff027e807c2843185961fdae7fe23aad5a4837c93f9d25/coverage-7.8.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d1ba00ae33be84066cfbe7361d4e04dec78445b2b88bdb734d0d1cbab916025a", size = 254307, upload_time = "2025-03-30T20:36:16.074Z" }, + { url = "https://files.pythonhosted.org/packages/58/e9/8fb8e0ff6bef5e170ee19d59ca694f9001b2ec085dc99b4f65c128bb3f9a/coverage-7.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f3c38e4e5ccbdc9198aecc766cedbb134b2d89bf64533973678dfcf07effd883", size = 255116, upload_time = "2025-03-30T20:36:18.033Z" }, + { url = "https://files.pythonhosted.org/packages/56/b0/d968ecdbe6fe0a863de7169bbe9e8a476868959f3af24981f6a10d2b6924/coverage-7.8.0-cp313-cp313t-win32.whl", hash = "sha256:379fe315e206b14e21db5240f89dc0774bdd3e25c3c58c2c733c99eca96f1ada", size = 214909, upload_time = "2025-03-30T20:36:19.644Z" }, + { url = "https://files.pythonhosted.org/packages/87/e9/d6b7ef9fecf42dfb418d93544af47c940aa83056c49e6021a564aafbc91f/coverage-7.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2e4b6b87bb0c846a9315e3ab4be2d52fac905100565f4b92f02c445c8799e257", size = 216068, upload_time = "2025-03-30T20:36:21.282Z" }, + { url = "https://files.pythonhosted.org/packages/59/f1/4da7717f0063a222db253e7121bd6a56f6fb1ba439dcc36659088793347c/coverage-7.8.0-py3-none-any.whl", hash = "sha256:dbf364b4c5e7bae9250528167dfe40219b62e2d573c854d74be213e1e52069f7", size = 203435, upload_time = "2025-03-30T20:36:43.61Z" }, +] + [[package]] name = "dnspython" version = "2.7.0" @@ -287,8 +316,9 @@ dependencies = [ { name = "natsort" }, { name = "pathlib" }, { name = "platformdirs" }, - { name = "psycopg2" }, + { name = "psycopg2-binary" }, { name = "pytest" }, + { name = "pytest-cov" }, { name = "python-dotenv" }, { name = "python-jose" }, { name = "python-multipart" }, @@ -307,8 +337,9 @@ requires-dist = [ { name = "natsort", specifier = ">=8.4.0" }, { name = "pathlib", specifier = ">=1.0.1" }, { name = "platformdirs", specifier = ">=4.3.7" }, - { name = "psycopg2", specifier = ">=2.9.10" }, + { name = "psycopg2-binary", specifier = ">=2.9.10" }, { name = "pytest", specifier = "==7.4.0" }, + { name = "pytest-cov", specifier = ">=6.1.1" }, { name = "python-dotenv", specifier = ">=1.1.0" }, { name = "python-jose", specifier = ">=3.4.0" }, { name = "python-multipart", specifier = ">=0.0.20" }, @@ -426,12 +457,22 @@ wheels = [ ] [[package]] -name = "psycopg2" +name = "psycopg2-binary" version = "2.9.10" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/62/51/2007ea29e605957a17ac6357115d0c1a1b60c8c984951c19419b3474cdfd/psycopg2-2.9.10.tar.gz", hash = "sha256:12ec0b40b0273f95296233e8750441339298e6a572f7039da5b260e3c8b60e11", size = 385672, upload_time = "2024-10-16T11:24:54.832Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cb/0e/bdc8274dc0585090b4e3432267d7be4dfbfd8971c0fa59167c711105a6bf/psycopg2-binary-2.9.10.tar.gz", hash = "sha256:4b3df0e6990aa98acda57d983942eff13d824135fe2250e6522edaa782a06de2", size = 385764, upload_time = "2024-10-16T11:24:58.126Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/49/a6cfc94a9c483b1fa401fbcb23aca7892f60c7269c5ffa2ac408364f80dc/psycopg2-2.9.10-cp313-cp313-win_amd64.whl", hash = "sha256:91fd603a2155da8d0cfcdbf8ab24a2d54bca72795b90d2a3ed2b6da8d979dee2", size = 2569060, upload_time = "2025-01-04T20:09:15.28Z" }, + { url = "https://files.pythonhosted.org/packages/3e/30/d41d3ba765609c0763505d565c4d12d8f3c79793f0d0f044ff5a28bf395b/psycopg2_binary-2.9.10-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:26540d4a9a4e2b096f1ff9cce51253d0504dca5a85872c7f7be23be5a53eb18d", size = 3044699, upload_time = "2024-10-16T11:21:42.841Z" }, + { url = "https://files.pythonhosted.org/packages/35/44/257ddadec7ef04536ba71af6bc6a75ec05c5343004a7ec93006bee66c0bc/psycopg2_binary-2.9.10-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e217ce4d37667df0bc1c397fdcd8de5e81018ef305aed9415c3b093faaeb10fb", size = 3275245, upload_time = "2024-10-16T11:21:51.989Z" }, + { url = "https://files.pythonhosted.org/packages/1b/11/48ea1cd11de67f9efd7262085588790a95d9dfcd9b8a687d46caf7305c1a/psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:245159e7ab20a71d989da00f280ca57da7641fa2cdcf71749c193cea540a74f7", size = 2851631, upload_time = "2024-10-16T11:21:57.584Z" }, + { url = "https://files.pythonhosted.org/packages/62/e0/62ce5ee650e6c86719d621a761fe4bc846ab9eff8c1f12b1ed5741bf1c9b/psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c4ded1a24b20021ebe677b7b08ad10bf09aac197d6943bfe6fec70ac4e4690d", size = 3082140, upload_time = "2024-10-16T11:22:02.005Z" }, + { url = "https://files.pythonhosted.org/packages/27/ce/63f946c098611f7be234c0dd7cb1ad68b0b5744d34f68062bb3c5aa510c8/psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3abb691ff9e57d4a93355f60d4f4c1dd2d68326c968e7db17ea96df3c023ef73", size = 3264762, upload_time = "2024-10-16T11:22:06.412Z" }, + { url = "https://files.pythonhosted.org/packages/43/25/c603cd81402e69edf7daa59b1602bd41eb9859e2824b8c0855d748366ac9/psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8608c078134f0b3cbd9f89b34bd60a943b23fd33cc5f065e8d5f840061bd0673", size = 3020967, upload_time = "2024-10-16T11:22:11.583Z" }, + { url = "https://files.pythonhosted.org/packages/5f/d6/8708d8c6fca531057fa170cdde8df870e8b6a9b136e82b361c65e42b841e/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:230eeae2d71594103cd5b93fd29d1ace6420d0b86f4778739cb1a5a32f607d1f", size = 2872326, upload_time = "2024-10-16T11:22:16.406Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ac/5b1ea50fc08a9df82de7e1771537557f07c2632231bbab652c7e22597908/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:bb89f0a835bcfc1d42ccd5f41f04870c1b936d8507c6df12b7737febc40f0909", size = 2822712, upload_time = "2024-10-16T11:22:21.366Z" }, + { url = "https://files.pythonhosted.org/packages/c4/fc/504d4503b2abc4570fac3ca56eb8fed5e437bf9c9ef13f36b6621db8ef00/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f0c2d907a1e102526dd2986df638343388b94c33860ff3bbe1384130828714b1", size = 2920155, upload_time = "2024-10-16T11:22:25.684Z" }, + { url = "https://files.pythonhosted.org/packages/b2/d1/323581e9273ad2c0dbd1902f3fb50c441da86e894b6e25a73c3fda32c57e/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f8157bed2f51db683f31306aa497311b560f2265998122abe1dce6428bd86567", size = 2959356, upload_time = "2024-10-16T11:22:30.562Z" }, + { url = "https://files.pythonhosted.org/packages/08/50/d13ea0a054189ae1bc21af1d85b6f8bb9bbc5572991055d70ad9006fe2d6/psycopg2_binary-2.9.10-cp313-cp313-win_amd64.whl", hash = "sha256:27422aa5f11fbcd9b18da48373eb67081243662f9b46e6fd07c3eb46e4535142", size = 2569224, upload_time = "2025-01-04T20:09:19.234Z" }, ] [[package]] @@ -510,6 +551,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/33/b2/741130cbcf2bbfa852ed95a60dc311c9e232c7ed25bac3d9b8880a8df4ae/pytest-7.4.0-py3-none-any.whl", hash = "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32", size = 323580, upload_time = "2023-06-23T11:17:25.738Z" }, ] +[[package]] +name = "pytest-cov" +version = "6.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "coverage" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/25/69/5f1e57f6c5a39f81411b550027bf72842c4567ff5fd572bed1edc9e4b5d9/pytest_cov-6.1.1.tar.gz", hash = "sha256:46935f7aaefba760e716c2ebfbe1c216240b9592966e7da99ea8292d4d3e2a0a", size = 66857, upload_time = "2025-04-05T14:07:51.592Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/28/d0/def53b4a790cfb21483016430ed828f64830dd981ebe1089971cd10cab25/pytest_cov-6.1.1-py3-none-any.whl", hash = "sha256:bddf29ed2d0ab6f4df17b4c55b0a657287db8684af9c42ea546b21b1041b3dde", size = 23841, upload_time = "2025-04-05T14:07:49.641Z" }, +] + [[package]] name = "python-dotenv" version = "1.1.0" diff --git a/kontor-scripts/config.py b/kontor-scripts/config.py index bf65cd5..6e06702 100644 --- a/kontor-scripts/config.py +++ b/kontor-scripts/config.py @@ -3,6 +3,7 @@ Setup database connections """ import sqlite3 import mariadb +import psycopg2 import logging.config from platformdirs import PlatformDirs from pathlib import Path @@ -24,7 +25,8 @@ def get_database_cursors(log, config: str): password=db_config['mariadb']['password'], database=db_config['mariadb']['database'] ) - return sqlite_conn, mariadb_conn + postgres_conn = psycopg2.connect(f"host={db_config['postgres']['host']} port={db_config['postgres']['port']} user={db_config['postgres']['user']} password={db_config['postgres']['password']} dbname={db_config['postgres']['']}") + return sqlite_conn, mariadb_conn, postgres_conn def create_tables(sqlite_conn, logger, recreate_db, scripts): diff --git a/kontor-scripts/json_to_postgres.py b/kontor-scripts/json_to_postgres.py new file mode 100644 index 0000000..e5b1240 --- /dev/null +++ b/kontor-scripts/json_to_postgres.py @@ -0,0 +1,59 @@ +""" +copy data from JSON to Postgres +""" +from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter +from pathlib import Path +from config import get_logger, get_database_cursors +import json +import psycopg2 +from psycopg2.sql import SQL + +parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter) +parser.add_argument('--verbose', '-v', action='count', default=0) +parser.add_argument('--config', '-c', default='kontor-docker') +parser.add_argument('--file', '-f', default='~/.sync/media/data.json') +args = parser.parse_args() + +def copy_data(postgres_conn, data_file: Path, log): + postgres_cursor = postgres_conn.cursor() + import_file = Path(data_file) + if not import_file.exists(): + log.info(f"File {data_file} does not exist. Do nothing.") + return + log.info("read json file") + with open(data_file, 'r') as json_file: + json_load = json.load(json_file) + for table in json_load: + log.info(f"{table}: {len(json_load[table])}") + # result[table] = import_table(table, json_load[table]) + truncate_statement = 'TRUNCATE {}'.format(table) + #log.info(f"truncate: {truncate_statement}") + postgres_cursor.execute("SET FOREIGN_KEY_CHECKS = 0") + postgres_cursor.execute(truncate_statement) + items = json_load[table] + for item in items: + #log.info(f"item: {item}") + values = [] + columns = [] + for (key, value) in item.items(): + columns.append(key) + values.append(value) + row = tuple(values) + log.info(f"values: {row}") + insert_statement = 'INSERT INTO {}({}) VALUES({})'.format(table, ', '.join(columns), ', '.join(['%s']*len(columns))) + #log.info(f"statement: {insert_statement}") + postgres_cursor.execute(SQL(insert_statement), row) + try: + postgres_conn.commit() + except psycopg2.Error as error: + log.info('insert failed with %s', error) + + +if __name__ == '__main__': + logger = get_logger(args.verbose, args.config) + logger.info('kontor.json_to_postgres started') + _, _, p_conn = get_database_cursors(logger, args.config) + copy_data(p_conn, args.file, logger) + p_conn.close() + logger.info('kontor.json_to_postgres finished') + diff --git a/kontor-spring/Dockerfile b/kontor-spring/Dockerfile index d4f3463..1cfd701 100644 --- a/kontor-spring/Dockerfile +++ b/kontor-spring/Dockerfile @@ -1,5 +1,5 @@ FROM alpine/java:21-jdk WORKDIR / -ADD build/libs/kontor-spring-0.1.0-SNAPSHOT.jar app.jar +ADD build/libs/kontor-spring-0.2.0-SNAPSHOT.jar app.jar EXPOSE 8000 CMD ["java", "-jar", "-Dspring.profiles.active=prod", "-Dvaadin.productionMode=true", "app.jar"] diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/data/AuthorizationMatrix.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/data/AuthorizationMatrix.java deleted file mode 100644 index 26b5ebb..0000000 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/data/AuthorizationMatrix.java +++ /dev/null @@ -1,35 +0,0 @@ -package de.thpeetz.kontor.admin.data; - -import de.thpeetz.kontor.common.data.AbstractEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.validation.constraints.NotNull; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; - -@Getter -@Setter -@Entity -public class AuthorizationMatrix extends AbstractEntity { - - @ManyToOne - @JoinColumn(name = "user_id") - @NotNull - private User user; - - @ManyToOne - @JoinColumn(name = "role_id") - @NotNull - private Role role; - - @Override - public String toString() { - final StringBuffer sb = new StringBuffer("AuthorizationMatrix{"); - sb.append("user=").append(user.getUserName()); - sb.append(", role=").append(role.getName()); - sb.append('}'); - return sb.toString(); - } -} diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/data/Role.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/data/Role.java deleted file mode 100644 index 5ad81c2..0000000 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/data/Role.java +++ /dev/null @@ -1,30 +0,0 @@ -package de.thpeetz.kontor.admin.data; - -import java.util.List; - -import de.thpeetz.kontor.common.data.AbstractEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.OneToMany; -import jakarta.validation.constraints.NotEmpty; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import lombok.extern.slf4j.Slf4j; - -import javax.annotation.Nullable; - -@Slf4j -@Getter -@Setter -@ToString -@Entity -public class Role extends AbstractEntity { - - @NotEmpty - private String name; - - @OneToMany(fetch = FetchType.EAGER, mappedBy = "role") - @Nullable - private List matrix; -} diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/data/User.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/data/User.java deleted file mode 100644 index ec16233..0000000 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/data/User.java +++ /dev/null @@ -1,62 +0,0 @@ -package de.thpeetz.kontor.admin.data; - -import de.thpeetz.kontor.common.data.AbstractEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.Index; -import jakarta.persistence.OneToMany; -import jakarta.persistence.Table; -import jakarta.persistence.UniqueConstraint; -import jakarta.validation.constraints.NotEmpty; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import lombok.extern.slf4j.Slf4j; - -import javax.annotation.Nullable; -import java.util.LinkedList; -import java.util.List; - -@Slf4j -@Getter -@Setter -@ToString -@Entity -@Table(indexes = @Index(columnList = "userName"), uniqueConstraints = @UniqueConstraint(columnNames = {"userName"})) -public class User extends AbstractEntity { - - private String firstName; - - private String lastName; - - @NotEmpty - private String userName; - - private String email; - - private String password; - - private boolean enabled; - - @OneToMany(fetch = FetchType.EAGER, mappedBy = "user") - @Nullable - private List matrix = new LinkedList<>(); - - @OneToMany(fetch = FetchType.EAGER, mappedBy = "user") - @Nullable - private List tokens = new LinkedList<>(); - - public String getFullName() { - StringBuilder fullNamBuilder = new StringBuilder(); - if (firstName != null) { - fullNamBuilder.append(firstName); - } - if (lastName != null) { - if (fullNamBuilder.length() > 0) { - fullNamBuilder.append(" "); - } - fullNamBuilder.append(lastName); - } - return fullNamBuilder.toString(); - } -} diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/AuthorizationMatrixRepository.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/AuthorizationMatrixRepository.java deleted file mode 100644 index 3e5c30c..0000000 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/AuthorizationMatrixRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package de.thpeetz.kontor.admin.repository; - -import java.util.List; - -import de.thpeetz.kontor.admin.data.AuthorizationMatrix; -import de.thpeetz.kontor.admin.data.Role; -import de.thpeetz.kontor.admin.data.User; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface AuthorizationMatrixRepository extends JpaRepository { - - List findByUser(User user); - - List findByRole(Role role); -} diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/RoleRepository.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/RoleRepository.java deleted file mode 100644 index 0d1b466..0000000 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/RoleRepository.java +++ /dev/null @@ -1,19 +0,0 @@ -package de.thpeetz.kontor.admin.repository; - -import java.util.List; - -import de.thpeetz.kontor.admin.data.Role; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -public interface RoleRepository extends JpaRepository { - - @Query("select r from Role r " + - "where lower(r.name) like lower(concat('%', :searchTerm, '%')) ") - List search(@Param("searchTerm") String searchTerm); - - @Query("select r from Role r " + - "where lower(r.name) like lower(:name) ") - Role findByName(@Param("name") String name); -} diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/UserRepository.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/UserRepository.java deleted file mode 100644 index c8c20f3..0000000 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/repository/UserRepository.java +++ /dev/null @@ -1,17 +0,0 @@ -package de.thpeetz.kontor.admin.repository; - -import java.util.List; - -import de.thpeetz.kontor.admin.data.User; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -public interface UserRepository extends JpaRepository { - - @Query("select u from User u " + - "where lower(u.lastName) like lower(concat('%', :searchTerm, '%')) ") - List search(@Param("searchTerm") String searchTerm); - - User findByUserName(String userName); -} diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/services/KontorUserDetailsService.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/services/KontorUserDetailsService.java index 52fc79a..21f76ac 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/services/KontorUserDetailsService.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/services/KontorUserDetailsService.java @@ -1,7 +1,11 @@ package de.thpeetz.kontor.admin.services; -import de.thpeetz.kontor.admin.data.*; -import de.thpeetz.kontor.admin.repository.*; +import de.thpeetz.kontor.admin.data.Assignment; +import de.thpeetz.kontor.admin.data.Profile; +import de.thpeetz.kontor.admin.data.Permission; +import de.thpeetz.kontor.admin.repository.AssignmentRepository; +import de.thpeetz.kontor.admin.repository.ProfileRepository; +import de.thpeetz.kontor.admin.repository.PermissionRepository; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; @@ -21,7 +25,7 @@ import java.util.stream.Collectors; @Service("userDetailsService") public class KontorUserDetailsService implements UserDetailsService { - private static SecureRandom random = new SecureRandom(); + private static final SecureRandom random = new SecureRandom(); @Autowired private ProfileRepository profileRepository; diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AuthorizationForm.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AuthorizationForm.java deleted file mode 100644 index da593f8..0000000 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AuthorizationForm.java +++ /dev/null @@ -1,112 +0,0 @@ -package de.thpeetz.kontor.admin.views; - -import java.util.List; - -import com.vaadin.flow.component.ComponentEvent; -import com.vaadin.flow.component.ComponentEventListener; -import com.vaadin.flow.component.Key; -import com.vaadin.flow.component.button.Button; -import com.vaadin.flow.component.button.ButtonVariant; -import com.vaadin.flow.component.combobox.ComboBox; -import com.vaadin.flow.component.formlayout.FormLayout; -import com.vaadin.flow.component.orderedlayout.HorizontalLayout; -import com.vaadin.flow.data.binder.BeanValidationBinder; -import com.vaadin.flow.data.binder.Binder; - -import de.thpeetz.kontor.admin.data.AuthorizationMatrix; -import de.thpeetz.kontor.admin.data.Role; -import de.thpeetz.kontor.admin.data.User; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public class AuthorizationForm extends FormLayout { - - ComboBox user = new ComboBox<>("User"); - ComboBox role = new ComboBox<>("Role"); - - Button save = new Button("Save"); - Button delete = new Button("Delete"); - Button close = new Button("Cancel"); - - Binder binder = new BeanValidationBinder<>(AuthorizationMatrix.class); - - public AuthorizationForm(List users, List roles) { - addClassName("authorizationmatrix-form"); - binder.bindInstanceFields(this); - - user.setItems(users); - user.setItemLabelGenerator(User::getUserName); - role.setItems(roles); - role.setItemLabelGenerator(Role::getName); - add(user, role, createButtonsLayout()); - } - - private HorizontalLayout createButtonsLayout() { - save.addThemeVariants(ButtonVariant.LUMO_PRIMARY); - delete.addThemeVariants(ButtonVariant.LUMO_ERROR); - close.addThemeVariants(ButtonVariant.LUMO_TERTIARY); - - save.addClickShortcut(Key.ENTER); - close.addClickShortcut(Key.ESCAPE); - - save.addClickListener(event -> validateAndSave()); - delete.addClickListener(event -> fireEvent(new DeleteEvent(this, binder.getBean()))); - close.addClickListener(event -> fireEvent(new CloseEvent(this))); - - binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid())); - return new HorizontalLayout(save, delete, close); - } - - private void validateAndSave() { - if (binder.isValid()) { - fireEvent(new SaveEvent(this, binder.getBean())); - } - } - - public void setAuthorizationMatrix(AuthorizationMatrix authorizationMatrix) { - binder.setBean(authorizationMatrix); - } - - public abstract static class AuthorizationFormEvent extends ComponentEvent { - private AuthorizationMatrix authorizationMatrix; - - protected AuthorizationFormEvent(AuthorizationForm source, AuthorizationMatrix authorizationMatrix) { - super(source, false); - this.authorizationMatrix = authorizationMatrix; - } - - public AuthorizationMatrix getAuthorizationMatrix() { - return authorizationMatrix; - } - } - - public static class SaveEvent extends AuthorizationFormEvent { - SaveEvent(AuthorizationForm source, AuthorizationMatrix authorizationMatrix) { - super(source, authorizationMatrix); - } - } - - public static class DeleteEvent extends AuthorizationFormEvent { - DeleteEvent(AuthorizationForm source, AuthorizationMatrix authorizationMatrix) { - super(source, authorizationMatrix); - } - } - - public static class CloseEvent extends AuthorizationFormEvent { - CloseEvent(AuthorizationForm source) { - super(source, null); - } - } - - public void addDeleteListener(ComponentEventListener listener) { - addListener(DeleteEvent.class, listener); - } - - public void addSaveListener(ComponentEventListener listener) { - addListener(SaveEvent.class, listener); - } - - public void addCloseListener(ComponentEventListener listener) { - addListener(CloseEvent.class, listener); - } -} diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AuthorizationView.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AuthorizationView.java deleted file mode 100644 index 435ae8f..0000000 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/AuthorizationView.java +++ /dev/null @@ -1,114 +0,0 @@ -package de.thpeetz.kontor.admin.views; - -import org.springframework.context.annotation.Scope; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.button.Button; -import com.vaadin.flow.component.grid.Grid; -import com.vaadin.flow.component.orderedlayout.HorizontalLayout; -import com.vaadin.flow.component.orderedlayout.VerticalLayout; - -import com.vaadin.flow.router.PageTitle; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.spring.annotation.SpringComponent; - -import de.thpeetz.kontor.admin.AdminConstants; -import de.thpeetz.kontor.admin.data.AuthorizationMatrix; -import de.thpeetz.kontor.admin.services.AdminService; -import de.thpeetz.kontor.common.views.MainLayout; -import jakarta.annotation.security.RolesAllowed; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -@SpringComponent -@Scope("prototype") -@RolesAllowed("ROLE_ADMIN") -@Route(value = AdminConstants.AUTHORIZATION_ROUTE, layout = MainLayout.class) -@PageTitle("Authorization | Admin | Kontor") -public class AuthorizationView extends VerticalLayout { - - Grid grid = new Grid<>(AuthorizationMatrix.class); - AuthorizationForm form; - AdminService service; - - public AuthorizationView(AdminService service) { - this.service = service; - addClassName("authoriaztionmatrix-view"); - setSizeFull(); - configureGrid(); - configureForm(); - - add(getToolbar(), getContent()); - updateList(); - } - - private void configureGrid() { - grid.addClassName("authorizationmatrix-grid"); - grid.setSizeFull(); - grid.setColumns("user.userName", "role.name"); - grid.getColumns().forEach(col -> col.setAutoWidth(true)); - grid.asSingleSelect().addValueChangeListener(event -> editAuthorizationMatrix(event.getValue())); - } - - private void configureForm() { - form = new AuthorizationForm(service.findAllUsers(), service.findAllRoles()); - form.setWidth("25em"); - form.addSaveListener(this::saveAuthorizationMatrix); - form.addDeleteListener(this::deleteAuthorizationMatrix); - form.addCloseListener(e -> closeEditor()); - } - - private void saveAuthorizationMatrix(AuthorizationForm.SaveEvent event) { - AuthorizationMatrix authorizationMatrix = event.getAuthorizationMatrix(); - service.saveAuthorizationMatrix(authorizationMatrix); - updateList(); - closeEditor(); - } - - private void deleteAuthorizationMatrix(AuthorizationForm.DeleteEvent event) { - service.deleteAuthorizationMatrix(event.getAuthorizationMatrix()); - updateList(); - closeEditor(); - } - - private Component getContent() { - HorizontalLayout content = new HorizontalLayout(grid, form); - content.setFlexGrow(2, grid); - content.setFlexGrow(1, form); - content.addClassName("content"); - content.setSizeFull(); - return content; - } - - private HorizontalLayout getToolbar() { - Button addAuthorizationMaxtrixButton = new Button("Add permssion", click -> addAuthorizationMatrix()); - HorizontalLayout toolbar = new HorizontalLayout(addAuthorizationMaxtrixButton); - toolbar.addClassName("toolbar"); - return toolbar; - } - - public void editAuthorizationMatrix(AuthorizationMatrix authorizationMatrix) { - if (authorizationMatrix == null) { - closeEditor(); - } else { - form.setAuthorizationMatrix(authorizationMatrix); - form.setVisible(true); - addClassName("editing"); - } - } - - public void closeEditor() { - form.setAuthorizationMatrix(null); - form.setVisible(false); - removeClassName("editing"); - } - - private void addAuthorizationMatrix() { - grid.asSingleSelect().clear(); - editAuthorizationMatrix(new AuthorizationMatrix()); - } - - private void updateList() { - grid.setItems(service.findAllAuthorizationMatrices()); - } -} diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/RoleForm.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/RoleForm.java deleted file mode 100644 index 671d0f5..0000000 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/RoleForm.java +++ /dev/null @@ -1,102 +0,0 @@ -package de.thpeetz.kontor.admin.views; - -import com.vaadin.flow.component.ComponentEvent; -import com.vaadin.flow.component.ComponentEventListener; -import com.vaadin.flow.component.Key; -import com.vaadin.flow.component.button.Button; -import com.vaadin.flow.component.button.ButtonVariant; -import com.vaadin.flow.component.formlayout.FormLayout; -import com.vaadin.flow.component.orderedlayout.HorizontalLayout; -import com.vaadin.flow.component.textfield.TextField; -import com.vaadin.flow.data.binder.BeanValidationBinder; -import com.vaadin.flow.data.binder.Binder; - -import de.thpeetz.kontor.admin.data.Role; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public class RoleForm extends FormLayout { - - TextField name = new TextField("Role name"); - - Button save = new Button("Save"); - Button delete = new Button("Delete"); - Button close = new Button("Cancel"); - - Binder binder = new BeanValidationBinder<>(Role.class); - - public RoleForm() { - addClassName("role-form"); - binder.bindInstanceFields(this); - add(name, createButtonsLayout()); - } - - private HorizontalLayout createButtonsLayout() { - save.addThemeVariants(ButtonVariant.LUMO_PRIMARY); - delete.addThemeVariants(ButtonVariant.LUMO_ERROR); - close.addThemeVariants(ButtonVariant.LUMO_TERTIARY); - - save.addClickShortcut(Key.ENTER); - close.addClickShortcut(Key.ESCAPE); - - save.addClickListener(event -> validateAndSave()); - delete.addClickListener(event -> fireEvent(new DeleteEvent(this, binder.getBean()))); - close.addClickListener(event -> fireEvent(new CloseEvent(this))); - - binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid())); - return new HorizontalLayout(save, delete, close); - } - - private void validateAndSave() { - if (binder.isValid()) { - fireEvent(new SaveEvent(this, binder.getBean())); - } - } - - public void setRole(Role role) { - binder.setBean(role); - } - - public abstract static class RoleFormEvent extends ComponentEvent { - private Role role; - - protected RoleFormEvent(RoleForm source, Role role) { - super(source, false); - this.role = role; - } - - public Role getRole() { - return role; - } - } - - public static class SaveEvent extends RoleFormEvent { - SaveEvent(RoleForm source, Role role) { - super(source, role); - } - } - - public static class DeleteEvent extends RoleFormEvent { - DeleteEvent(RoleForm source, Role role) { - super(source, role); - } - } - - public static class CloseEvent extends RoleFormEvent { - CloseEvent(RoleForm source) { - super(source, null); - } - } - - public void addDeleteListener(ComponentEventListener listener) { - addListener(DeleteEvent.class, listener); - } - - public void addSaveListener(ComponentEventListener listener) { - addListener(SaveEvent.class, listener); - } - - public void addCloseListener(ComponentEventListener listener) { - addListener(CloseEvent.class, listener); - } -} diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/RoleView.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/RoleView.java deleted file mode 100644 index 1f13c9a..0000000 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/RoleView.java +++ /dev/null @@ -1,118 +0,0 @@ -package de.thpeetz.kontor.admin.views; - -import org.springframework.context.annotation.Scope; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.button.Button; -import com.vaadin.flow.component.grid.Grid; -import com.vaadin.flow.component.orderedlayout.HorizontalLayout; -import com.vaadin.flow.component.orderedlayout.VerticalLayout; -import com.vaadin.flow.component.textfield.TextField; -import com.vaadin.flow.data.value.ValueChangeMode; -import com.vaadin.flow.router.PageTitle; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.spring.annotation.SpringComponent; - -import de.thpeetz.kontor.admin.AdminConstants; -import de.thpeetz.kontor.admin.data.Role; -import de.thpeetz.kontor.admin.services.AdminService; -import de.thpeetz.kontor.common.views.MainLayout; -import jakarta.annotation.security.RolesAllowed; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -@SpringComponent -@Scope("prototype") -@RolesAllowed("ROLE_ADMIN") -@Route(value = AdminConstants.ROLE_ROUTE, layout = MainLayout.class) -@PageTitle("Rollen | Admin | Kontor") -public class RoleView extends VerticalLayout { - Grid grid = new Grid<>(Role.class); - TextField filterText = new TextField(); - RoleForm form; - AdminService service; - - public RoleView(AdminService service) { - this.service = service; - addClassName("user-view"); - setSizeFull(); - configureGrid(); - configureForm(); - - add(getToolbar(), getContent()); - updateList(); - } - - private void configureGrid() { - grid.addClassName("user-grid"); - grid.setSizeFull(); - grid.setColumns("name"); - grid.getColumns().forEach(col -> col.setAutoWidth(true)); - grid.asSingleSelect().addValueChangeListener(event -> editRole(event.getValue())); - } - - private void configureForm() { - form = new RoleForm(); - form.setWidth("25em"); - form.addSaveListener(this::saveRole); - form.addDeleteListener(this::deleteRole); - form.addCloseListener(e -> closeEditor()); - } - - private void saveRole(RoleForm.SaveEvent event) { - service.saveRole(event.getRole()); - updateList(); - closeEditor(); - } - - private void deleteRole(RoleForm.DeleteEvent event) { - service.deleteRole(event.getRole()); - updateList(); - closeEditor(); - } - - private Component getContent() { - HorizontalLayout content = new HorizontalLayout(grid, form); - content.setFlexGrow(2, grid); - content.setFlexGrow(1, form); - content.addClassName("content"); - content.setSizeFull(); - return content; - } - - private HorizontalLayout getToolbar() { - filterText.setPlaceholder("Filter by user name..."); - filterText.setClearButtonVisible(true); - filterText.setValueChangeMode(ValueChangeMode.LAZY); - filterText.addValueChangeListener(e -> updateList()); - Button addUserButton = new Button("Add user", click -> addUser()); - HorizontalLayout toolbar = new HorizontalLayout(filterText, addUserButton); - toolbar.addClassName("toolbar"); - return toolbar; - } - - public void editRole(Role role) { - if (role == null) { - closeEditor(); - } else { - form.setRole(role); - form.setVisible(true); - addClassName("editing"); - } - } - - public void closeEditor() { - form.setRole(null); - form.setVisible(false); - removeClassName("editing"); - } - - private void addUser() { - grid.asSingleSelect().clear(); - editRole(new Role()); - } - - private void updateList() { - grid.setItems(service.findAllRoles(filterText.getValue())); - } -} diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/UserForm.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/UserForm.java deleted file mode 100644 index 21298f3..0000000 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/UserForm.java +++ /dev/null @@ -1,143 +0,0 @@ -package de.thpeetz.kontor.admin.views; - -import com.vaadin.flow.component.ComponentEvent; -import com.vaadin.flow.component.ComponentEventListener; -import com.vaadin.flow.component.Key; -import com.vaadin.flow.component.button.Button; -import com.vaadin.flow.component.button.ButtonVariant; -import com.vaadin.flow.component.checkbox.Checkbox; -import com.vaadin.flow.component.checkbox.CheckboxGroup; -import com.vaadin.flow.component.checkbox.CheckboxGroupVariant; -import com.vaadin.flow.component.formlayout.FormLayout; -import com.vaadin.flow.component.orderedlayout.HorizontalLayout; -import com.vaadin.flow.component.textfield.EmailField; -import com.vaadin.flow.component.textfield.PasswordField; -import com.vaadin.flow.component.textfield.TextField; -import com.vaadin.flow.data.binder.BeanValidationBinder; -import com.vaadin.flow.data.binder.Binder; -import de.thpeetz.kontor.admin.data.Role; -import de.thpeetz.kontor.admin.data.User; -import lombok.extern.slf4j.Slf4j; - -import java.util.List; - -@Slf4j -public class UserForm extends FormLayout { - - TextField userName = new TextField("User name"); - PasswordField password = new PasswordField("Password"); - EmailField email = new EmailField("Email"); - TextField firstName = new TextField("First name"); - TextField lastName = new TextField("Last name"); - Checkbox enabled = new Checkbox("Enabled"); - String originalPassword; - - CheckboxGroup permissions = new CheckboxGroup<>("Permissions"); - - Button save = new Button("Save"); - Button delete = new Button("Delete"); - Button close = new Button("Cancel"); - - Binder binder = new BeanValidationBinder<>(User.class); - - public UserForm() { - addClassName("user-form"); - binder.bindInstanceFields(this); - add(userName, password, email, firstName, lastName, enabled, configurePermissionsGroup(), createButtonsLayout()); - } - - private CheckboxGroup configurePermissionsGroup() { - permissions.addThemeVariants(CheckboxGroupVariant.LUMO_VERTICAL); - permissions.setItemLabelGenerator(Role::getName); - permissions.addValueChangeListener(event -> { - log.debug("permissions changed: {}", event); - }); - return permissions; - } - - private HorizontalLayout createButtonsLayout() { - save.addThemeVariants(ButtonVariant.LUMO_PRIMARY); - delete.addThemeVariants(ButtonVariant.LUMO_ERROR); - close.addThemeVariants(ButtonVariant.LUMO_TERTIARY); - - save.addClickShortcut(Key.ENTER); - close.addClickShortcut(Key.ESCAPE); - - save.addClickListener(event -> validateAndSave()); - delete.addClickListener(event -> fireEvent(new DeleteEvent(this, binder.getBean()))); - close.addClickListener(event -> fireEvent(new CloseEvent(this))); - - binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid())); - return new HorizontalLayout(save, delete, close); - } - - private void validateAndSave() { - if (binder.isValid()) { - fireEvent(new SaveEvent(this, binder.getBean())); - } - } - - public void setUser(User user) { - binder.setBean(user); - //log.debug("UserForm.setUser: {}", user); - if (user != null) { - this.originalPassword = user.getPassword(); - } else { - this.originalPassword = null; - } - } - - public void setRoles(List roles, User user) { - permissions.setItems(roles); - user.getMatrix().stream().forEach(authorizationMatrix -> { - permissions.select(authorizationMatrix.getRole()); - }); - } - - public boolean hasPasswordChanged(User user) { - return !originalPassword.equals(user.getPassword()); - } - - public abstract static class UserFormEvent extends ComponentEvent { - private User user; - - protected UserFormEvent(UserForm source, User user) { - super(source, false); - this.user = user; - } - - public User getUser() { - return user; - } - } - - public static class SaveEvent extends UserFormEvent { - SaveEvent(UserForm source, User user) { - super(source, user); - } - } - - public static class DeleteEvent extends UserFormEvent { - DeleteEvent(UserForm source, User user) { - super(source, user); - } - } - - public static class CloseEvent extends UserFormEvent { - CloseEvent(UserForm source) { - super(source, null); - } - } - - public void addDeleteListener(ComponentEventListener listener) { - addListener(DeleteEvent.class, listener); - } - - public void addSaveListener(ComponentEventListener listener) { - addListener(SaveEvent.class, listener); - } - - public void addCloseListener(ComponentEventListener listener) { - addListener(CloseEvent.class, listener); - } -} diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/UserView.java b/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/UserView.java deleted file mode 100644 index 9f981ec..0000000 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/admin/views/UserView.java +++ /dev/null @@ -1,135 +0,0 @@ -package de.thpeetz.kontor.admin.views; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.button.Button; -import com.vaadin.flow.component.grid.Grid; -import com.vaadin.flow.component.orderedlayout.HorizontalLayout; -import com.vaadin.flow.component.orderedlayout.VerticalLayout; -import com.vaadin.flow.component.textfield.TextField; -import com.vaadin.flow.data.value.ValueChangeMode; -import com.vaadin.flow.router.PageTitle; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.spring.annotation.SpringComponent; -import de.thpeetz.kontor.admin.data.Role; -import de.thpeetz.kontor.admin.data.User; -import de.thpeetz.kontor.admin.services.KontorUserDetailsService; -import de.thpeetz.kontor.common.views.MainLayout; -import jakarta.annotation.security.RolesAllowed; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Scope; -import org.springframework.security.crypto.password.PasswordEncoder; - -import java.util.List; -import java.util.stream.Collectors; - -@Slf4j -@SpringComponent -@Scope("prototype") -@RolesAllowed("ROLE_ADMIN") -@Route(value = "admin/user", layout = MainLayout.class) -@PageTitle("User | Admin | Kontor") -public class UserView extends VerticalLayout { - - Grid grid = new Grid<>(User.class); - TextField filterText = new TextField(); - UserForm form; - KontorUserDetailsService service; - - @Autowired - PasswordEncoder passwordEncoder; - - public UserView(KontorUserDetailsService service) { - this.service = service; - addClassName("user-view"); - setSizeFull(); - configureGrid(); - configureForm(); - - add(getToolbar(), getContent()); - updateList(); - } - - private void configureGrid() { - grid.addClassName("user-grid"); - grid.setSizeFull(); - grid.setColumns("userName", "email", "firstName", "lastName", "enabled"); - grid.getColumns().forEach(col -> col.setAutoWidth(true)); - grid.asSingleSelect().addValueChangeListener(event -> editUser(event.getValue())); - } - - private void configureForm() { - form = new UserForm(); - form.setWidth("25em"); - form.setVisible(false); - form.addSaveListener(this::saveUser); - form.addDeleteListener(this::deleteUser); - form.addCloseListener(e -> closeEditor()); - } - - private void saveUser(UserForm.SaveEvent event) { - User user = event.getUser(); - log.debug("UserView.saveUser: {}", user); - List permissions = form.permissions.getSelectedItems().stream().collect(Collectors.toList()); - log.info("selected permissions: {}", permissions); - if (form.hasPasswordChanged(user)) { - user.setPassword(passwordEncoder.encode(user.getPassword())); - log.debug("password changed for user {}", user); - } - service.saveUser(user, permissions); - updateList(); - closeEditor(); - } - - private void deleteUser(UserForm.DeleteEvent event) { - service.deleteUser(event.getUser()); - updateList(); - closeEditor(); - } - - private Component getContent() { - HorizontalLayout content = new HorizontalLayout(grid, form); - content.setFlexGrow(2, grid); - content.setFlexGrow(1, form); - content.addClassName("content"); - content.setSizeFull(); - return content; - } - - private HorizontalLayout getToolbar() { - filterText.setPlaceholder("Filter by user name..."); - filterText.setClearButtonVisible(true); - filterText.setValueChangeMode(ValueChangeMode.LAZY); - filterText.addValueChangeListener(e -> updateList()); - Button addUserButton = new Button("Add user", click -> addUser()); - HorizontalLayout toolbar = new HorizontalLayout(filterText, addUserButton); - toolbar.addClassName("toolbar"); - return toolbar; - } - - public void editUser(User user) { - if (user == null) { - closeEditor(); - } else { - form.setUser(user); - form.setRoles(service.findAllRoles(), user); - form.setVisible(true); - addClassName("editing"); - } - } - - public void closeEditor() { - form.setUser(null); - form.setVisible(false); - removeClassName("editing"); - } - - private void addUser() { - grid.asSingleSelect().clear(); - editUser(new User()); - } - - private void updateList() { - grid.setItems(service.findAllUsers(filterText.getValue())); - } -} diff --git a/kontor-spring/src/main/resources/application.yml b/kontor-spring/src/main/resources/application.yml index 998c19b..c4abf9b 100644 --- a/kontor-spring/src/main/resources/application.yml +++ b/kontor-spring/src/main/resources/application.yml @@ -11,10 +11,10 @@ spring: hibernate: ddl-auto: update #ddl-auto: create-drop - show-sql: true + show-sql: false properties: hibernate: - dialect: org.hibernate.dialect.PostgreSQLDialect + #dialect: org.hibernate.dialect.PostgreSQLDialect sql: init: mode: never