feat: settings, delete port validation #22

Open
ivan.dev wants to merge 3 commits from VORKOUT-31 into master
30 changed files with 147 additions and 180 deletions
Showing only changes of commit a70973032f - Show all commits

View File

@@ -1,7 +1,6 @@
import math
from datetime import datetime, timezone
from enum import Enum
from typing import Optional
from sqlalchemy import insert, select, func, or_, and_, asc, desc
from sqlalchemy.ext.asyncio import AsyncConnection
@@ -11,9 +10,7 @@ from api.schemas.account.account import User
from api.schemas.endpoints.account import all_user_adapter, AllUser, AllUserResponse, UserCreate, UserFilterDTO
async def get_user_account_page_DTO(
connection: AsyncConnection, filter_dto: UserFilterDTO
) -> Optional[AllUserResponse]:
async def get_user_account_page_DTO(connection: AsyncConnection, filter_dto: UserFilterDTO) -> AllUserResponse | None:
"""
Получает список пользователей с пагинацией, фильтрацией и сортировкой через DTO объект.
Поддерживает:
@@ -118,7 +115,7 @@ async def get_user_account_page_DTO(
)
async def get_user_by_id(connection: AsyncConnection, user_id: int) -> Optional[AllUser]:
async def get_user_by_id(connection: AsyncConnection, user_id: int) -> AllUser | None:
"""
Получает юзера по id.
"""
@@ -133,7 +130,7 @@ async def get_user_by_id(connection: AsyncConnection, user_id: int) -> Optional[
return User.model_validate(user)
async def get_user_by_login(connection: AsyncConnection, login: str) -> Optional[User]:
async def get_user_by_login(connection: AsyncConnection, login: str) -> User | None:
"""
Получает юзера по login.
"""
@@ -147,7 +144,7 @@ async def get_user_by_login(connection: AsyncConnection, login: str) -> Optional
return User.model_validate(user_data)
async def update_user_by_id(connection: AsyncConnection, update_values, user) -> Optional[User]:
async def update_user_by_id(connection: AsyncConnection, update_values, user) -> User | None:
"""
Вносит изменеия в нужное поле таблицы account_table.
"""
@@ -156,7 +153,7 @@ async def update_user_by_id(connection: AsyncConnection, update_values, user) ->
await connection.commit()
async def create_user(connection: AsyncConnection, user: UserCreate, creator_id: int) -> Optional[AllUser]:
async def create_user(connection: AsyncConnection, user: UserCreate, creator_id: int) -> AllUser | None:
"""
Создает нове поле в таблице account_table.
"""

View File

@@ -1,5 +1,3 @@
from typing import Optional
from sqlalchemy import select, update
from sqlalchemy.ext.asyncio import AsyncConnection
from enum import Enum
@@ -15,7 +13,7 @@ from api.utils.key_id_gen import KeyIdGenerator
from datetime import datetime, timezone
async def get_user(connection: AsyncConnection, login: str) -> tuple[Optional[AllUser], Optional[AccountKeyring]]:
async def get_user(connection: AsyncConnection, login: str) -> tuple[AllUser | None, AccountKeyring | None]:
query = (
select(account_table, account_keyring_table)
.join(account_keyring_table, account_table.c.id == account_keyring_table.c.owner_id)
@@ -51,7 +49,7 @@ async def get_user(connection: AsyncConnection, login: str) -> tuple[Optional[Al
return user, password
async def upgrade_old_refresh_token(connection: AsyncConnection, refresh_token) -> Optional[User]:
async def upgrade_old_refresh_token(connection: AsyncConnection, refresh_token) -> User | None:
new_status = KeyStatus.EXPIRED
update_query = (
@@ -71,7 +69,7 @@ async def upgrade_old_refresh_token(connection: AsyncConnection, refresh_token)
async def add_new_refresh_token(
connection: AsyncConnection, new_refresh_token, new_refresh_token_expires_time, user
) -> Optional[User]:
) -> User | None:
new_refresh_token = account_keyring_table.insert().values(
owner_id=user.id,
key_type=KeyType.REFRESH_TOKEN,

View File

@@ -1,6 +1,5 @@
from datetime import datetime, timedelta, timezone
from enum import Enum
from typing import Optional
from sqlalchemy import insert, select, update
from sqlalchemy.dialects.mysql import insert as mysql_insert
@@ -11,7 +10,7 @@ from api.schemas.account.account_keyring import AccountKeyring
from api.utils.hasher import hasher
async def get_key_by_id(connection: AsyncConnection, key_id: str) -> Optional[AccountKeyring]:
async def get_key_by_id(connection: AsyncConnection, key_id: str) -> AccountKeyring | None:
"""
Получает key по key_id.
"""
@@ -26,7 +25,7 @@ async def get_key_by_id(connection: AsyncConnection, key_id: str) -> Optional[Ac
return AccountKeyring.model_validate(user_data)
async def update_key_by_id(connection: AsyncConnection, update_values, key) -> Optional[AccountKeyring]:
async def update_key_by_id(connection: AsyncConnection, update_values, key) -> AccountKeyring | None:
"""
Вносит изменеия в нужное поле таблицы account_keyring_table.
"""
@@ -37,7 +36,7 @@ async def update_key_by_id(connection: AsyncConnection, update_values, key) -> O
await connection.commit()
async def create_key(connection: AsyncConnection, key: AccountKeyring, key_id: str) -> Optional[AccountKeyring]:
async def create_key(connection: AsyncConnection, key: AccountKeyring, key_id: str) -> AccountKeyring | None:
"""
Создает нове поле в таблице account_keyring_table).
"""

View File

@@ -1,4 +1,3 @@
from typing import Optional
import math
from datetime import datetime, timezone
@@ -16,7 +15,7 @@ from api.schemas.endpoints.list_events import all_list_event_adapter, AllListEve
async def get_list_events_page_DTO(
connection: AsyncConnection, filter_dto: ListEventFilterDTO
) -> Optional[AllListEventResponse]:
) -> AllListEventResponse | None:
"""
Получает список событий с фильтрацией через DTO объект.
Поддерживает:
@@ -121,7 +120,7 @@ async def get_list_events_page_DTO(
)
async def get_list_events_by_name(connection: AsyncConnection, name: str) -> Optional[ListEvent]:
async def get_list_events_by_name(connection: AsyncConnection, name: str) -> ListEvent | None:
"""
Получает list events по name.
"""
@@ -136,7 +135,7 @@ async def get_list_events_by_name(connection: AsyncConnection, name: str) -> Opt
return ListEvent.model_validate(list_events_data)
async def get_list_events_by_id(connection: AsyncConnection, id: int) -> Optional[ListEvent]:
async def get_list_events_by_id(connection: AsyncConnection, id: int) -> ListEvent | None:
"""
Получает listevent по id.
"""
@@ -162,9 +161,7 @@ async def update_list_events_by_id(connection: AsyncConnection, update_values, l
await connection.commit()
async def create_list_events(
connection: AsyncConnection, list_events: ListEvent, creator_id: int
) -> Optional[ListEvent]:
async def create_list_events(connection: AsyncConnection, list_events: ListEvent, creator_id: int) -> ListEvent | None:
"""
Создает нове поле в таблице list_events_table.
"""

View File

@@ -1,5 +1,3 @@
from typing import Optional, List
from datetime import datetime, timezone
from sqlalchemy import insert, select, desc
@@ -11,7 +9,7 @@ from orm.tables.process import ps_node_table, node_link_table
from orm.tables.process import NodeLinkStatus
async def get_last_link_name_by_node_id(connection: AsyncConnection, ps_id: int) -> Optional[str]:
async def get_last_link_name_by_node_id(connection: AsyncConnection, ps_id: int) -> str | None:
"""
Получает link_name из последней записи node_link по ps_id.
Находит все node_id в ps_node по ps_id, затем ищет связи в node_link
@@ -32,7 +30,7 @@ async def get_last_link_name_by_node_id(connection: AsyncConnection, ps_id: int)
async def get_last_node_link_by_creator_and_ps_id(
connection: AsyncConnection, creator_id: int, node_link_id: int
) -> Optional[NodeLink]:
) -> NodeLink | None:
"""
Получает последнюю созданную node_link для данного создателя и процесса.
"""
@@ -59,7 +57,7 @@ async def create_node_link_schema(
connection: AsyncConnection,
validated_link_schema,
creator_id: int,
) -> Optional[NodeLink]:
) -> NodeLink | None:
"""
Создает нове поле в таблице process_schema_table.
"""
@@ -81,7 +79,7 @@ async def create_node_link_schema(
return await get_last_node_link_by_creator_and_ps_id(connection, creator_id, validated_link_schema.from_id)
async def get_all_node_links_by_next_node_ids(connection: AsyncConnection, next_node_ids: List[int]) -> List[NodeLink]:
async def get_all_node_links_by_next_node_ids(connection: AsyncConnection, next_node_ids: list[int]) -> list[NodeLink]:
"""
Получает все активные node_link для списка next_node_id одним запросом.
"""

View File

@@ -1,4 +1,4 @@
from typing import Optional, Dict, Any
from typing import Any
import math
from datetime import datetime, timezone
@@ -19,7 +19,7 @@ from api.schemas.endpoints.process_schema import (
async def get_process_schema_page_DTO(
connection: AsyncConnection, filter_dto: ProcessSchemaFilterDTO
) -> Optional[AllProcessSchemaResponse]:
) -> AllProcessSchemaResponse | None:
"""
Получает список схем процессов с комплексной фильтрацией через DTO объект.
Поддерживает:
@@ -115,7 +115,7 @@ async def get_process_schema_page_DTO(
)
async def get_process_schema_by_id(connection: AsyncConnection, id: int) -> Optional[ProcessSchema]:
async def get_process_schema_by_id(connection: AsyncConnection, id: int) -> ProcessSchema | None:
"""
Получает process_schema по id.
"""
@@ -143,7 +143,7 @@ async def update_process_schema_by_id(connection: AsyncConnection, update_values
async def create_process_schema(
connection: AsyncConnection, creator_id: int, title: str, description: str
) -> Optional[int]:
) -> int | None:
"""
Создает новое поле в таблице process_schema_table.
"""

View File

@@ -1,4 +1,4 @@
from typing import Optional, List, Dict, Any
from typing import Any
from datetime import datetime, timezone
@@ -11,7 +11,7 @@ from api.schemas.process.ps_node import Ps_Node
from orm.tables.process import NodeStatus
async def get_ps_node_by_id(connection: AsyncConnection, id: int) -> Optional[Ps_Node]:
async def get_ps_node_by_id(connection: AsyncConnection, id: int) -> Ps_Node | None:
"""
Получает process_schema по id.
"""
@@ -28,7 +28,7 @@ async def get_ps_node_by_id(connection: AsyncConnection, id: int) -> Optional[Ps
async def get_last_ps_node_by_creator_and_ps_id(
connection: AsyncConnection, creator_id: int, ps_id: int
) -> Optional[Ps_Node]:
) -> Ps_Node | None:
"""
Получает последнюю созданную ps_node для данного создателя и процесса.
"""
@@ -48,7 +48,7 @@ async def get_last_ps_node_by_creator_and_ps_id(
return Ps_Node.model_validate(ps_node_data)
async def get_all_ps_nodes_by_ps_id(connection: AsyncConnection, ps_id: int) -> List[Ps_Node]:
async def get_all_ps_nodes_by_ps_id(connection: AsyncConnection, ps_id: int) -> list[Ps_Node]:
"""
Получает все активные ps_node для данной process_schema.
"""
@@ -67,8 +67,8 @@ async def create_ps_node_schema(
validated_schema,
node_descriptor,
creator_id: int,
settings_payload: Optional[Dict[str, Any]] = None,
) -> Optional[Ps_Node]:
settings_payload: dict[str, Any] | None = None,
) -> Ps_Node | None:
"""
Создает нове поле в таблице process_schema_table.
"""
@@ -104,7 +104,7 @@ async def check_node_connection(connection: AsyncConnection, node_id: int, next_
return result.mappings().first() is not None
async def get_nodes_for_deletion_ordered(connection: AsyncConnection, node_id: int) -> List[int]:
async def get_nodes_for_deletion_ordered(connection: AsyncConnection, node_id: int) -> list[int]:
"""
Рекурсивно находит ВСЕ дочерние узлы и возвращает их ID в правильном порядке:
от самых глубоких к корневым.
@@ -144,7 +144,7 @@ async def get_nodes_for_deletion_ordered(connection: AsyncConnection, node_id: i
return ordered_node_ids
async def delete_ps_nodes_delete_handler(connection: AsyncConnection, node_ids: List[int]) -> List[int]:
async def delete_ps_nodes_delete_handler(connection: AsyncConnection, node_ids: list[int]) -> list[int]:
"""
Очищает settings и удаляет ноды для каждого ps_id.
Возвращает список успешно удаленных ID нод.
@@ -177,7 +177,7 @@ async def delete_ps_nodes_delete_handler(connection: AsyncConnection, node_ids:
return deleted_all
async def remove_nodes_from_process_schema_settings(connection: AsyncConnection, ps_id: int, node_ids: List[int]):
async def remove_nodes_from_process_schema_settings(connection: AsyncConnection, ps_id: int, node_ids: list[int]):
"""
Удаляет ноды из поля settings в таблице process_schema по списку node_ids.
"""

View File

@@ -1,5 +1,3 @@
from typing import List, Optional
from fastapi import APIRouter, Depends, Query, status
from sqlalchemy.ext.asyncio import AsyncConnection
@@ -23,12 +21,12 @@ api_router = APIRouter(
async def get_all_account_endpoint(
page: int = Query(1, description="Page number", gt=0),
limit: int = Query(10, description="КNumber of items per page", gt=0),
search: Optional[str] = Query(None, description="Search term to filter by name or login or email"),
status_filter: Optional[List[str]] = Query(None, description="Filter by status"),
role_filter: Optional[List[str]] = Query(None, description="Filter by role"),
creator_id: Optional[int] = Query(None, description="Filter by creator id"),
order_field: Optional[str] = Query("id", description="Field to sort by"),
order_direction: Optional[str] = Query("asc", description="Sort direction (asc/desc)"),
search: str | None = Query(None, description="Search term to filter by name or login or email"),
status_filter: list[str] | None = Query(None, description="Filter by status"),
role_filter: list[str] | None = Query(None, description="Filter by role"),
creator_id: int | None = Query(None, description="Filter by creator id"),
order_field: str | None = Query("id", description="Field to sort by"),
order_direction: str | None = Query("asc", description="Sort direction (asc/desc)"),
connection: AsyncConnection = Depends(get_connection_dep),
current_user=Depends(get_current_user),
):

View File

@@ -1,5 +1,3 @@
from typing import List, Optional
from fastapi import APIRouter, Depends, Query, status
from sqlalchemy.ext.asyncio import AsyncConnection
@@ -23,12 +21,12 @@ api_router = APIRouter(
async def get_all_list_events_endpoint(
page: int = Query(1, description="Page number", gt=0),
limit: int = Query(10, description="Number of items per page", gt=0),
search: Optional[str] = Query(None, description="Search term to filter by title or name"),
order_field: Optional[str] = Query("id", description="Field to sort by"),
order_direction: Optional[str] = Query("asc", description="Sort direction (asc/desc)"),
status_filter: Optional[List[str]] = Query(None, description="Filter by status"),
state_filter: Optional[List[str]] = Query(None, description="Filter by state"),
creator_id: Optional[int] = Query(None, description="Filter by creator id"),
search: str | None = Query(None, description="Search term to filter by title or name"),
order_field: str | None = Query("id", description="Field to sort by"),
order_direction: str | None = Query("asc", description="Sort direction (asc/desc)"),
status_filter: list[str] | None = Query(None, description="Filter by status"),
state_filter: list[str] | None = Query(None, description="Filter by state"),
creator_id: int | None = Query(None, description="Filter by creator id"),
connection: AsyncConnection = Depends(get_connection_dep),
current_user=Depends(get_current_user),
):

View File

@@ -1,5 +1,3 @@
from typing import List, Optional
from fastapi import APIRouter, Depends, Query, status, HTTPException
from sqlalchemy.ext.asyncio import AsyncConnection
@@ -25,14 +23,14 @@ api_router = APIRouter(
async def get_all_process_schema_endpoint(
page: int = Query(1, description="Page number", gt=0),
limit: int = Query(10, description="Number of items per page", gt=0),
search: Optional[str] = Query(None, description="Search term to filter by title or description"),
order_field: Optional[str] = Query("id", description="Field to sort by"),
order_direction: Optional[str] = Query("asc", description="Sort direction (asc/desc)"),
status_filter: Optional[List[str]] = Query(None, description="Filter by status"),
owner_id: Optional[List[str]] = Query(None, description="Filter by owner id"),
search: str | None = Query(None, description="Search term to filter by title or description"),
order_field: str | None = Query("id", description="Field to sort by"),
order_direction: str | None = Query("asc", description="Sort direction (asc/desc)"),
status_filter: list[str] | None = Query(None, description="Filter by status"),
owner_id: list[str] | None = Query(None, description="Filter by owner id"),
show_deleted: bool = Query(False, description="Show only deleted schemas"),
connection: AsyncConnection = Depends(get_connection_dep),
creator_id: Optional[int] = Query(None, description="Filter by creator id"),
creator_id: int | None = Query(None, description="Filter by creator id"),
current_user=Depends(get_current_user),
):
if show_deleted:

View File

@@ -2,14 +2,14 @@
Обработчики ошибок для API.
"""
from typing import Optional, Dict, Any
from typing import Any
from fastapi import HTTPException
from .error_model.error_types import ServerError, AccessError, OperationError, ValidationError, ErrorType
def handle_api_error(
error_type: ErrorType, message: str, status_code: int, details: Optional[Dict[str, Any]] = None
error_type: ErrorType, message: str, status_code: int, details: dict[str, Any] | None = None
) -> HTTPException:
"""
Функция для создания HTTPException с правильной структурой ошибки.
@@ -30,25 +30,21 @@ def handle_api_error(
return HTTPException(status_code=status_code, detail=error.model_dump(mode="json"))
def create_server_error(
message: str, status_code: int = 500, details: Optional[Dict[str, Any]] = None
) -> HTTPException:
def create_server_error(message: str, status_code: int = 500, details: dict[str, Any] | None = None) -> HTTPException:
return handle_api_error(error_type=ErrorType.SERVER, message=message, status_code=status_code, details=details)
def create_access_error(
message: str, status_code: int = 403, details: Optional[Dict[str, Any]] = None
) -> HTTPException:
def create_access_error(message: str, status_code: int = 403, details: dict[str, Any] | None = None) -> HTTPException:
return handle_api_error(error_type=ErrorType.ACCESS, message=message, status_code=status_code, details=details)
def create_operation_error(
message: str, status_code: int = 400, details: Optional[Dict[str, Any]] = None
message: str, status_code: int = 400, details: dict[str, Any] | None = None
) -> HTTPException:
return handle_api_error(error_type=ErrorType.OPERATION, message=message, status_code=status_code, details=details)
def create_validation_error(
message: str, status_code: int = 422, details: Optional[Dict[str, Any]] = None
message: str, status_code: int = 422, details: dict[str, Any] | None = None
) -> HTTPException:
return handle_api_error(error_type=ErrorType.VALIDATION, message=message, status_code=status_code, details=details)

View File

@@ -3,7 +3,7 @@
"""
from enum import Enum
from typing import Optional, Dict, Any
from typing import Any
from pydantic import BaseModel
@@ -25,7 +25,7 @@ class BaseError(BaseModel):
error_type: ErrorType
message: str
details: Optional[Dict[str, Any]] = None
details: dict[str, Any] | None = None
class ServerError(BaseError):
@@ -58,4 +58,4 @@ class ValidationError(BaseError):
"""
error_type: ErrorType = ErrorType.VALIDATION
field_errors: Optional[Dict[str, str]] = None
field_errors: dict[str, str] | None = None

View File

@@ -1,5 +1,4 @@
from datetime import datetime
from typing import Optional
from orm.tables.account import AccountRole, AccountStatus
from pydantic import EmailStr, Field
@@ -8,13 +7,13 @@ from api.schemas.base import Base
class User(Base):
id: Optional[int] = None
id: int | None = None
name: str = Field(..., max_length=100)
login: str = Field(..., max_length=100)
email: Optional[EmailStr] = Field(None, max_length=100) # Электронная почта (может быть None)
bind_tenant_id: Optional[str] = Field(None, max_length=40)
email: EmailStr | None = Field(None, max_length=100) # Электронная почта (может быть None)
bind_tenant_id: str | None = Field(None, max_length=40)
role: AccountRole
meta: dict
creator_id: Optional[int] = None
creator_id: int | None = None
created_at: datetime
status: AccountStatus

View File

@@ -1,5 +1,4 @@
from datetime import datetime
from typing import Optional
from orm.tables.account import KeyStatus, KeyType
from pydantic import Field
@@ -10,8 +9,8 @@ from api.schemas.base import Base
class AccountKeyring(Base):
owner_id: int
key_type: KeyType
key_id: Optional[str] = Field(None, max_length=40)
key_id: str | None = Field(None, max_length=40)
key_value: str = Field(..., max_length=255)
created_at: datetime
expiry: Optional[datetime] = None
expiry: datetime | None = None
status: KeyStatus

View File

@@ -1,5 +1,4 @@
from datetime import datetime
from typing import Dict, List, Optional
from orm.tables.account import AccountRole, AccountStatus
from pydantic import EmailStr, Field, TypeAdapter
@@ -8,24 +7,24 @@ from api.schemas.base import Base
class UserUpdate(Base):
name: Optional[str] = Field(None, max_length=100)
login: Optional[str] = Field(None, max_length=100)
email: Optional[EmailStr] = None
password: Optional[str] = None
bind_tenant_id: Optional[str] = Field(None, max_length=40)
role: Optional[AccountRole] = None
meta: Optional[dict] = None
status: Optional[AccountStatus] = None
name: str | None = Field(None, max_length=100)
login: str | None = Field(None, max_length=100)
email: EmailStr | None = None
password: str | None = None
bind_tenant_id: str | None = Field(None, max_length=40)
role: AccountRole | None = None
meta: dict | None = None
status: AccountStatus | None = None
class UserCreate(Base):
name: str = Field(max_length=100)
login: str = Field(max_length=100)
email: Optional[EmailStr] = None
password: Optional[str] = None
bind_tenant_id: Optional[str] = Field(None, max_length=40)
email: EmailStr | None = None
password: str | None = None
bind_tenant_id: str | None = Field(None, max_length=40)
role: AccountRole
meta: Optional[dict] = None
meta: dict | None = None
status: AccountStatus
@@ -33,28 +32,28 @@ class AllUser(Base):
id: int
name: str
login: str
email: Optional[EmailStr] = None
bind_tenant_id: Optional[str] = None
email: EmailStr | None = None
bind_tenant_id: str | None = None
role: AccountRole
meta: Optional[dict] = None
creator_id: Optional[int] = None
meta: dict | None = None
creator_id: int | None = None
created_at: datetime
status: AccountStatus
class AllUserResponse(Base):
users: List[AllUser]
users: list[AllUser]
amount_count: int
amount_pages: int
current_page: int
limit: int
all_user_adapter = TypeAdapter(List[AllUser])
all_user_adapter = TypeAdapter(list[AllUser])
class UserFilterDTO(Base):
pagination: Dict[str, int]
search: Optional[str] = None
order: Optional[Dict[str, str]] = None
filters: Optional[Dict[str, List[str]]] = None
pagination: dict[str, int]
search: str | None = None
order: dict[str, str] | None = None
filters: dict[str, list[str]] | None = None

View File

@@ -1,5 +1,3 @@
from typing import Optional
from orm.tables.account import KeyStatus, KeyType
from pydantic import Field
@@ -7,7 +5,7 @@ from api.schemas.base import Base
class AccountKeyringUpdate(Base):
owner_id: Optional[int] = None
key_type: Optional[KeyType] = None
key_value: Optional[str] = Field(None, max_length=255)
status: Optional[KeyStatus] = None
owner_id: int | None = None
key_type: KeyType | None = None
key_value: str | None = Field(None, max_length=255)
status: KeyStatus | None = None

View File

@@ -1,5 +1,5 @@
from datetime import datetime
from typing import Any, Dict, List, Optional
from typing import Any
from orm.tables.events import EventState, EventStatus
from pydantic import Field, TypeAdapter
@@ -8,11 +8,11 @@ from api.schemas.base import Base
class ListEventUpdate(Base):
name: Optional[str] = Field(None, max_length=40)
title: Optional[str] = Field(None, max_length=64)
schema_: Optional[Dict[str, Any]] = Field(None, alias="schema")
state: Optional[EventState] = None
status: Optional[EventStatus] = None
name: str | None = Field(None, max_length=40)
title: str | None = Field(None, max_length=64)
schema_: dict[str, Any] | None = Field(None, alias="schema")
state: EventState | None = None
status: EventStatus | None = None
class AllListEvent(Base):
@@ -21,24 +21,24 @@ class AllListEvent(Base):
title: str
creator_id: int
created_at: datetime
schema_: Dict[str, Any] = Field(default={}, alias="schema")
schema_: dict[str, Any] = Field(default={}, alias="schema")
state: EventState
status: EventStatus
class AllListEventResponse(Base):
list_event: List[AllListEvent]
list_event: list[AllListEvent]
amount_count: int
amount_pages: int
current_page: int
limit: int
all_list_event_adapter = TypeAdapter(List[AllListEvent])
all_list_event_adapter = TypeAdapter(list[AllListEvent])
class ListEventFilterDTO(Base):
pagination: Dict[str, int]
search: Optional[str] = None
order: Optional[Dict[str, str]] = None
filters: Optional[Dict[str, List[str]]] = None
pagination: dict[str, int]
search: str | None = None
order: dict[str, str] | None = None
filters: dict[str, list[str]] | None = None

View File

@@ -1,5 +1,5 @@
from datetime import datetime
from typing import Any, Dict, List, Optional
from typing import Any
from orm.tables.process import ProcessStatus
from pydantic import Field, TypeAdapter
@@ -8,11 +8,11 @@ from api.schemas.base import Base
class ProcessSchemaUpdate(Base):
title: Optional[str] = Field(None, max_length=100)
description: Optional[str] = None
# owner_id: Optional[int] = None
settings: Optional[Dict[str, Any]] = None
status: Optional[ProcessStatus] = None
title: str | None = Field(None, max_length=100)
description: str | None = None
# owner_id: int | None = None
settings: dict[str, Any] | None = None
status: ProcessStatus | None = None
class AllProcessSchema(Base):
@@ -22,23 +22,23 @@ class AllProcessSchema(Base):
owner_id: int
creator_id: int
created_at: datetime
settings: Dict[str, Any]
settings: dict[str, Any]
status: ProcessStatus
class AllProcessSchemaResponse(Base):
process_schema: List[AllProcessSchema]
process_schema: list[AllProcessSchema]
amount_count: int
amount_pages: int
current_page: int
limit: int
all_process_schema_adapter = TypeAdapter(List[AllProcessSchema])
all_process_schema_adapter = TypeAdapter(list[AllProcessSchema])
class ProcessSchemaFilterDTO(Base):
pagination: Dict[str, int]
search: Optional[str] = None
order: Optional[Dict[str, str]] = None
filters: Optional[Dict[str, List[str]]] = None
pagination: dict[str, int]
search: str | None = None
order: dict[str, str] | None = None
filters: dict[str, list[str]] | None = None

View File

@@ -1,5 +1,5 @@
from datetime import datetime
from typing import Any, Dict
from typing import Any
from orm.tables.events import EventState, EventStatus
from pydantic import Field
@@ -13,6 +13,6 @@ class ListEvent(Base):
title: str = Field(..., max_length=64)
creator_id: int
created_at: datetime
schema_: Dict[str, Any] = Field(..., alias="schema")
schema_: dict[str, Any] = Field(..., alias="schema")
state: EventState
status: EventStatus

View File

@@ -1,5 +1,5 @@
from datetime import datetime
from typing import Any, Dict
from typing import Any
from orm.tables.process import NodeStatus
from pydantic import Field
@@ -13,7 +13,7 @@ class NodeLink(Base):
node_id: int
link_point_id: int
next_node_id: int
settings: Dict[str, Any]
settings: dict[str, Any]
creator_id: int
created_at: datetime
status: NodeStatus

View File

@@ -1,5 +1,5 @@
from datetime import datetime
from typing import Any, Dict, List
from typing import Any
from orm.tables.process import ProcessStatus
from pydantic import Field
@@ -15,10 +15,10 @@ class ProcessSchema(Base):
owner_id: int
creator_id: int
created_at: datetime
settings: Dict[str, Any]
settings: dict[str, Any]
status: ProcessStatus
class ProcessSchemaResponse(Base):
process_schema: ProcessSchema
nodes: List[Ps_NodeFrontResponse]
nodes: list[Ps_NodeFrontResponse]

View File

@@ -1,5 +1,5 @@
from datetime import datetime
from typing import Any, Dict, Optional, List
from typing import Any
from orm.tables.process import NodeStatus, NodeType
@@ -14,8 +14,8 @@ class Ps_NodeDeleteRequest(Base):
class Ps_NodeRequest(Base):
data: Dict[str, Any]
links: Dict[str, Any]
data: dict[str, Any]
links: dict[str, Any]
class Ps_Node(Base):
@@ -29,5 +29,5 @@ class Ps_Node(Base):
class Ps_NodeFrontResponse(Base):
node: Optional[Dict[str, Any]] = None
link: Optional[List[Dict[str, Any]]] = None
node: dict[str, Any] | None = None
link: list[dict[str, Any]] | None = None

View File

@@ -1,5 +1,3 @@
from typing import Optional
from fastapi import HTTPException, Request
from orm.tables.account import AccountStatus
from sqlalchemy.ext.asyncio import AsyncConnection
@@ -15,7 +13,7 @@ async def get_current_user(request: Request) -> str | HTTPException:
return request.state.current_user
async def authenticate_user(connection: AsyncConnection, username: str, password: str) -> Optional[AllUser]:
async def authenticate_user(connection: AsyncConnection, username: str, password: str) -> AllUser | None:
sql_user, sql_password = await get_user(connection, username)
if not sql_user or sql_user.status != AccountStatus.ACTIVE:

View File

@@ -1,4 +1,3 @@
from typing import Optional
from sqlalchemy.ext.asyncio import AsyncConnection
from orm.tables.account import AccountStatus
@@ -19,13 +18,13 @@ class AccountService:
def __init__(self, connection: AsyncConnection):
self.connection = connection
async def list(self, filter_dto: UserFilterDTO) -> Optional[AllUserResponse]:
async def list(self, filter_dto: UserFilterDTO) -> AllUserResponse | None:
"""
Получает список пользователей с пагинацией и фильтрацией.
"""
return await get_user_account_page_DTO(self.connection, filter_dto)
async def get(self, user_id: int) -> Optional[User]:
async def get(self, user_id: int) -> User | None:
"""
Получает пользователя по ID.
"""

View File

@@ -1,4 +1,3 @@
from typing import Optional
from sqlalchemy.ext.asyncio import AsyncConnection
from orm.tables.account import KeyStatus
@@ -15,7 +14,7 @@ class KeyringService:
def __init__(self, connection: AsyncConnection):
self.connection = connection
async def get(self, key_id: str) -> Optional[AccountKeyring]:
async def get(self, key_id: str) -> AccountKeyring | None:
"""
Получает keyring по key_id.
"""

View File

@@ -1,4 +1,3 @@
from typing import Optional
from sqlalchemy.ext.asyncio import AsyncConnection
from orm.tables.events import EventStatus
@@ -19,25 +18,25 @@ class ListEventsService:
def __init__(self, connection: AsyncConnection):
self.connection = connection
async def list(self, filter_dto: ListEventFilterDTO) -> Optional[AllListEventResponse]:
async def list(self, filter_dto: ListEventFilterDTO) -> AllListEventResponse | None:
"""
Получает список событий с пагинацией и фильтрацией.
"""
return await get_list_events_page_DTO(self.connection, filter_dto)
async def get(self, list_events_id: int) -> Optional[ListEvent]:
async def get(self, list_events_id: int) -> ListEvent | None:
"""
Получает событие по ID.
"""
return await get_list_events_by_id(self.connection, list_events_id)
async def get_by_name(self, name: str) -> Optional[ListEvent]:
async def get_by_name(self, name: str) -> ListEvent | None:
"""
Получает событие по name.
"""
return await get_list_events_by_name(self.connection, name)
async def create(self, list_events_data: ListEventUpdate, creator_id: int) -> Optional[ListEvent]:
async def create(self, list_events_data: ListEventUpdate, creator_id: int) -> ListEvent | None:
"""
Создаёт новое событие.
"""

View File

@@ -1,4 +1,4 @@
from typing import Optional, Dict, Any
from typing import Any
from sqlalchemy.ext.asyncio import AsyncConnection
from orm.tables.process import ProcessStatus
@@ -25,13 +25,13 @@ class ProcessSchemaService:
def __init__(self, connection: AsyncConnection):
self.connection = connection
async def list(self, filter_dto: ProcessSchemaFilterDTO) -> Optional[AllProcessSchemaResponse]:
async def list(self, filter_dto: ProcessSchemaFilterDTO) -> AllProcessSchemaResponse | None:
"""
Получает список схем процессов с пагинацией и фильтрацией.
"""
return await get_process_schema_page_DTO(self.connection, filter_dto)
async def get(self, process_schema_id: int) -> Optional[ProcessSchemaResponse]:
async def get(self, process_schema_id: int) -> ProcessSchemaResponse | None:
"""
Получает схему процесса по ID со всеми нодами и линками.
"""
@@ -66,7 +66,7 @@ class ProcessSchemaService:
nodes=nodes_response,
)
async def create(self, creator_id: int) -> Dict[str, Any]:
async def create(self, creator_id: int) -> dict[str, Any]:
"""
Создаёт новую схему процесса с начальной нодой LISTEN.
"""

View File

@@ -1,4 +1,3 @@
from typing import Optional
from sqlalchemy.ext.asyncio import AsyncConnection
from api.db.logic.account import get_user_by_id, get_user_by_login, update_user_by_id
@@ -11,7 +10,7 @@ class ProfileService:
def __init__(self, connection: AsyncConnection):
self.connection = connection
async def get_by_login(self, login: str) -> Optional[User]:
async def get_by_login(self, login: str) -> User | None:
"""
Получает пользователя по логину.
"""

View File

@@ -1,4 +1,4 @@
from typing import List, Dict, Any
from typing import Any
from sqlalchemy.ext.asyncio import AsyncConnection
from api.db.logic.ps_node import (
@@ -18,7 +18,7 @@ class PsNodeService:
def __init__(self, connection: AsyncConnection):
self.connection = connection
async def delete(self, next_node_id: int) -> Dict[str, List[int]]:
async def delete(self, next_node_id: int) -> dict[str, list[int]]:
"""
Удаляет ноды в правильном порядке.
"""
@@ -30,7 +30,7 @@ class PsNodeService:
}
async def create(
self, ps_node_data: Dict[str, Any], links: Dict[str, Any], creator_id: int
self, ps_node_data: dict[str, Any], links: dict[str, Any], creator_id: int
) -> Ps_NodeFrontResponse:
"""
Создаёт новую ноду с линком и обновляет настройки схемы процесса.

View File

@@ -1,6 +1,5 @@
import json
from pathlib import Path
from typing import Dict
# Путь к файлу счётчика (в корне проекта)
@@ -17,7 +16,7 @@ def get_node_counter() -> int:
"""
if not COUNTER_FILE_PATH.exists():
initial_data: Dict[str, int] = {"node_counter": 0}
initial_data: dict[str, int] = {"node_counter": 0}
with open(COUNTER_FILE_PATH, "w", encoding="utf-8") as f:
json.dump(initial_data, f, indent=2, ensure_ascii=False)
return 0
@@ -45,7 +44,7 @@ def increment_node_counter() -> int:
new_value = current_value + 1
data: Dict[str, int] = {"node_counter": new_value}
data: dict[str, int] = {"node_counter": new_value}
with open(COUNTER_FILE_PATH, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)