Fix API regressions and refresh project docs
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import hashlib
|
||||
import secrets
|
||||
from datetime import datetime
|
||||
from sqlalchemy import String, Boolean, DateTime
|
||||
from sqlalchemy import Boolean, String
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
from app.core.database import Base
|
||||
|
||||
@@ -24,3 +25,20 @@ class ApiKeyModel(Base):
|
||||
def generate_key() -> str:
|
||||
"""Генерация безопасного случайного токена."""
|
||||
return secrets.token_urlsafe(32)
|
||||
|
||||
@staticmethod
|
||||
def public_id_for(key: str) -> str:
|
||||
"""
|
||||
Возвращает безопасный публичный идентификатор ключа.
|
||||
Его можно отдавать клиенту и использовать в операциях revoke/activate
|
||||
вместо самого секрета.
|
||||
"""
|
||||
return hashlib.sha256(key.encode("utf-8")).hexdigest()[:16]
|
||||
|
||||
@property
|
||||
def public_id(self) -> str:
|
||||
return self.public_id_for(self.key)
|
||||
|
||||
@property
|
||||
def preview(self) -> str:
|
||||
return f"{self.key[:6]}...{self.key[-4:]}"
|
||||
|
||||
@@ -1,13 +1,29 @@
|
||||
from sqlalchemy import Column, Integer, String, Boolean, ForeignKey, JSON
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import Boolean, Integer, JSON, String
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.core.database import Base
|
||||
|
||||
|
||||
class ScheduleTask(Base):
|
||||
"""
|
||||
Персистентная метадата пользовательских расписаний.
|
||||
|
||||
APScheduler остаётся рантайм-движком исполнения, а эта таблица служит
|
||||
источником истины для CRUD, восстановления и миграции задач.
|
||||
"""
|
||||
|
||||
__tablename__ = "schedules"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
device_id = Column(Integer, ForeignKey("devices.id"), nullable=False)
|
||||
task_type = Column(String) # 'once', 'daily', 'cron'
|
||||
action_params = Column(JSON) # {'state': True, 'dimming': 50}
|
||||
is_active = Column(Boolean, default=True)
|
||||
job_id = Column(String, unique=True) # ID задачи в APScheduler
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
job_id: Mapped[str] = mapped_column(String, unique=True, index=True)
|
||||
trigger_type: Mapped[str] = mapped_column(String) # once | cron
|
||||
target_id: Mapped[str] = mapped_column(String)
|
||||
target_type: Mapped[str] = mapped_column(String) # group | device
|
||||
trigger_args: Mapped[dict] = mapped_column(JSON)
|
||||
action_params: Mapped[dict] = mapped_column(JSON)
|
||||
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
created_at: Mapped[str] = mapped_column(
|
||||
String, default=lambda: datetime.now().isoformat()
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user