## /ctk_extender/windows/layout/login.py
import customtkinter as ctk
from typing import Any
from ...layout import Layout, register_layout
from ...components import LoginForm
from ...widget import PackStrategy, GeometryStrategy, FormSubmittedEvent, FormReadyEvent
from ...notification import InAppNotificationController
from ...event import on_event, EventController
from ...window import WindowController
from ..notification import ErrorNotification, SuccessNotification
from EJIO.user import UserFacade
from EJIO.user.err import (
UserSessionNotFoundError,
UserNotFoundError,
IncorrectPasswordError,
InvalidCredentialsError
)
from EJIO.utils import _
__all__ = [
'LoginLayout',
]
[документация]
@register_layout("main_window:builtins.login")
class LoginLayout(Layout):
def __init__(
self,
parent: ctk.CTk | ctk.CTkToplevel | Any,
geometry: GeometryStrategy | None = None
) -> None:
self._form: LoginForm | None = None
super().__init__(parent, geometry)
[документация]
def on_show(self) -> None:
try:
UserFacade.initialize()
user = UserFacade.authenticate()
self.parent.after(100, lambda: self._execute_autologin_transition(user))
return
except (UserSessionNotFoundError, UserNotFoundError):
pass
card = ctk.CTkFrame(
self.ctk_instance,
width=340,
height=290,
fg_color=("#F1F5F9", "#1E293B"),
border_width=1,
border_color="#334155",
corner_radius=12
)
card.place(relx=0.5, rely=0.5, anchor="center")
card.pack_propagate(False)
ctk.CTkLabel(
card,
text=f"{_("ctk_extender.builtins.layout.login.authorisation")}",
font=("Arial", 16, "bold")
).pack(pady=(15, 10))
# Монтируем форму
self._form = LoginForm(
parent=card,
geometry=PackStrategy(fill="both", expand=True, padx=25, pady=(0, 15))
)
self._children.append(self._form)
@classmethod
def _execute_autologin_transition(cls, user: Any) -> None:
"""Внутренний изолированный воркер безопасного транзакционного авто-входа."""
try:
WindowController.get_active("main_window").switch_layout("main_layout")
InAppNotificationController.push(
SuccessNotification,
position="top_right",
duration=3.0,
message=f"{_('ctk_extender.builtins.layout.login.success_msg')}, {user.name}!"
)
except Exception as e:
from loguru import logger
logger.critical(f"Auto-authorization transition error: {e}")
[документация]
def build(self) -> ctk.CTkFrame:
base_canvas = super().build()
base_canvas.configure(fg_color="transparent")
return base_canvas
@on_event(FormSubmittedEvent, predicate=lambda e: e.sender.__class__.__name__ == "LoginForm")
def _on_form_submitted(self, event: FormSubmittedEvent) -> None:
"""Слушатель стандартного события отправки форм."""
form_data = event.data
login = form_data.get("login", "").strip()
password = form_data.get("password", "")
remember_me = bool(form_data.get("remember_me", False))
try:
user = UserFacade.authenticate(login, password, remember_me=remember_me)
WindowController.get_active("main_window").switch_layout("main_layout")
InAppNotificationController.push(
notification_cls=SuccessNotification,
position="top_right",
duration=3.0,
message=f"{_("ctk_extender.builtins.layout.login.success_msg")}, {user.name}!",
)
except InvalidCredentialsError:
self._process_error(_("ctk_extender.builtins.layout.login.credentials_err"))
except UserNotFoundError:
self._process_error(_("ctk_extender.builtins.layout.login.user_not_found_err"))
except IncorrectPasswordError:
self._process_error(_("ctk_extender.builtins.layout.login.incorrect_password_err"))
except Exception:
self._process_error(_("ctk_extender.builtins.layout.login.unexpected_err"))
def _process_error(self, message: str) -> None:
InAppNotificationController.push(
notification_cls=ErrorNotification,
position="top_right",
duration=3.0,
message=message,
)
try:
auth_form = self._form
if auth_form is not None:
EventController.emit(FormReadyEvent(target_form=auth_form))
except Exception:
pass
[документация]
def destroy(self) -> None:
self._form = None
super().destroy()