feat: settings, delete port validation #22
@@ -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.
|
||||
"""
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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).
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
|
||||
@@ -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 одним запросом.
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
|
||||
@@ -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),
|
||||
):
|
||||
|
||||
@@ -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),
|
||||
):
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
ivan.dev marked this conversation as resolved
Outdated
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
|
||||
@@ -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:
|
||||
"""
|
||||
Создаёт новое событие.
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
|
||||
@@ -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:
|
||||
"""
|
||||
Получает пользователя по логину.
|
||||
"""
|
||||
|
||||
@@ -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:
|
||||
"""
|
||||
Создаёт новую ноду с линком и обновляет настройки схемы процесса.
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user
Вроде же на не старом питоне сидим, зачем тут deprecated тайпинги? Хотя, судя по всему, это не в одном месте проекта имеется.