Revert "Add user-linked API tokens and issuance flow"

This commit is contained in:
Egor
2025-10-08 01:23:38 +03:00
committed by GitHub
parent bdceb9c3cf
commit 5a8aeadcd9
11 changed files with 11 additions and 448 deletions

View File

@@ -6,7 +6,6 @@ from typing import Iterable, List, Optional
from sqlalchemy import select, update
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
from app.database.models import WebApiToken
@@ -15,12 +14,8 @@ async def list_tokens(
db: AsyncSession,
*,
include_inactive: bool = False,
user_id: Optional[int] = None,
) -> List[WebApiToken]:
query = select(WebApiToken).options(selectinload(WebApiToken.user))
if user_id is not None:
query = query.where(WebApiToken.user_id == user_id)
query = select(WebApiToken)
if not include_inactive:
query = query.where(WebApiToken.is_active.is_(True))
@@ -32,20 +27,12 @@ async def list_tokens(
async def get_token_by_id(db: AsyncSession, token_id: int) -> Optional[WebApiToken]:
query = (
select(WebApiToken)
.options(selectinload(WebApiToken.user))
.where(WebApiToken.id == token_id)
)
result = await db.execute(query)
return result.scalar_one_or_none()
return await db.get(WebApiToken, token_id)
async def get_token_by_hash(db: AsyncSession, token_hash: str) -> Optional[WebApiToken]:
query = (
select(WebApiToken)
.options(selectinload(WebApiToken.user))
.where(WebApiToken.token_hash == token_hash)
query = select(WebApiToken).where(
WebApiToken.token_hash == token_hash
)
result = await db.execute(query)
return result.scalar_one_or_none()
@@ -60,10 +47,8 @@ async def create_token(
description: Optional[str] = None,
expires_at: Optional[datetime] = None,
created_by: Optional[str] = None,
user_id: Optional[int] = None,
) -> WebApiToken:
token = WebApiToken(
user_id=user_id,
name=name,
token_hash=token_hash,
token_prefix=token_prefix,

View File

@@ -387,7 +387,6 @@ class User(Base):
referral_earnings = relationship("ReferralEarning", foreign_keys="ReferralEarning.user_id", back_populates="user")
discount_offers = relationship("DiscountOffer", back_populates="user")
promo_offer_logs = relationship("PromoOfferLog", back_populates="user")
web_api_tokens = relationship("WebApiToken", back_populates="user")
lifetime_used_traffic_bytes = Column(BigInteger, default=0)
auto_promo_group_assigned = Column(Boolean, nullable=False, default=False)
auto_promo_group_threshold_kopeks = Column(BigInteger, nullable=False, default=0)
@@ -1239,7 +1238,6 @@ class WebApiToken(Base):
__tablename__ = "web_api_tokens"
id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"), nullable=True, index=True)
name = Column(String(255), nullable=False)
token_hash = Column(String(128), nullable=False, unique=True, index=True)
token_prefix = Column(String(32), nullable=False, index=True)
@@ -1251,7 +1249,6 @@ class WebApiToken(Base):
last_used_ip = Column(String(64), nullable=True)
is_active = Column(Boolean, default=True, nullable=False)
created_by = Column(String(255), nullable=True)
user = relationship("User", back_populates="web_api_tokens")
def __repr__(self) -> str:
status = "active" if self.is_active else "revoked"

View File

@@ -2434,7 +2434,6 @@ async def create_web_api_tokens_table() -> bool:
create_sql = """
CREATE TABLE web_api_tokens (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NULL,
name VARCHAR(255) NOT NULL,
token_hash VARCHAR(128) NOT NULL UNIQUE,
token_prefix VARCHAR(32) NOT NULL,
@@ -2445,19 +2444,16 @@ async def create_web_api_tokens_table() -> bool:
last_used_at DATETIME NULL,
last_used_ip VARCHAR(64) NULL,
is_active BOOLEAN NOT NULL DEFAULT 1,
created_by VARCHAR(255) NULL,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
created_by VARCHAR(255) NULL
);
CREATE INDEX idx_web_api_tokens_active ON web_api_tokens(is_active);
CREATE INDEX idx_web_api_tokens_prefix ON web_api_tokens(token_prefix);
CREATE INDEX idx_web_api_tokens_last_used ON web_api_tokens(last_used_at);
CREATE INDEX ix_web_api_tokens_user_id ON web_api_tokens(user_id);
"""
elif db_type == "postgresql":
create_sql = """
CREATE TABLE web_api_tokens (
id SERIAL PRIMARY KEY,
user_id INTEGER NULL,
name VARCHAR(255) NOT NULL,
token_hash VARCHAR(128) NOT NULL UNIQUE,
token_prefix VARCHAR(32) NOT NULL,
@@ -2468,19 +2464,16 @@ async def create_web_api_tokens_table() -> bool:
last_used_at TIMESTAMP NULL,
last_used_ip VARCHAR(64) NULL,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_by VARCHAR(255) NULL,
CONSTRAINT fk_web_api_tokens_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
created_by VARCHAR(255) NULL
);
CREATE INDEX idx_web_api_tokens_active ON web_api_tokens(is_active);
CREATE INDEX idx_web_api_tokens_prefix ON web_api_tokens(token_prefix);
CREATE INDEX idx_web_api_tokens_last_used ON web_api_tokens(last_used_at);
CREATE INDEX ix_web_api_tokens_user_id ON web_api_tokens(user_id);
"""
else:
create_sql = """
CREATE TABLE web_api_tokens (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NULL,
name VARCHAR(255) NOT NULL,
token_hash VARCHAR(128) NOT NULL UNIQUE,
token_prefix VARCHAR(32) NOT NULL,
@@ -2491,8 +2484,7 @@ async def create_web_api_tokens_table() -> bool:
last_used_at TIMESTAMP NULL,
last_used_ip VARCHAR(64) NULL,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_by VARCHAR(255) NULL,
CONSTRAINT fk_web_api_tokens_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
created_by VARCHAR(255) NULL
) ENGINE=InnoDB;
CREATE INDEX idx_web_api_tokens_active ON web_api_tokens(is_active);
CREATE INDEX idx_web_api_tokens_prefix ON web_api_tokens(token_prefix);
@@ -2508,71 +2500,6 @@ async def create_web_api_tokens_table() -> bool:
return False
async def ensure_web_api_tokens_user_column() -> bool:
column_exists = await check_column_exists("web_api_tokens", "user_id")
index_name = "ix_web_api_tokens_user_id"
constraint_name = "fk_web_api_tokens_user_id"
try:
async with engine.begin() as conn:
db_type = await get_database_type()
if not column_exists:
if db_type == "sqlite":
await conn.execute(text("ALTER TABLE web_api_tokens ADD COLUMN user_id INTEGER"))
elif db_type == "postgresql":
await conn.execute(text("ALTER TABLE web_api_tokens ADD COLUMN user_id INTEGER"))
elif db_type == "mysql":
await conn.execute(text("ALTER TABLE web_api_tokens ADD COLUMN user_id INT NULL"))
else:
logger.error(f"Неподдерживаемый тип БД для web_api_tokens.user_id: {db_type}")
return False
logger.info("Добавлена колонка web_api_tokens.user_id")
if db_type in {"postgresql", "mysql"}:
constraint_exists = await check_constraint_exists("web_api_tokens", constraint_name)
if not constraint_exists:
try:
await conn.execute(
text(
"ALTER TABLE web_api_tokens "
"ADD CONSTRAINT fk_web_api_tokens_user_id "
"FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL"
)
)
logger.info("Добавлено ограничение fk_web_api_tokens_user_id")
except Exception as constraint_error:
logger.warning(
"Не удалось создать ограничение fk_web_api_tokens_user_id: %s",
constraint_error,
)
index_exists = await check_index_exists("web_api_tokens", index_name)
if not index_exists:
try:
async with engine.begin() as conn:
db_type = await get_database_type()
if db_type == "sqlite":
await conn.execute(
text("CREATE INDEX IF NOT EXISTS ix_web_api_tokens_user_id ON web_api_tokens(user_id)")
)
elif db_type == "postgresql":
await conn.execute(
text("CREATE INDEX IF NOT EXISTS ix_web_api_tokens_user_id ON web_api_tokens(user_id)")
)
elif db_type == "mysql":
await conn.execute(text("CREATE INDEX ix_web_api_tokens_user_id ON web_api_tokens(user_id)"))
logger.info("Создан индекс ix_web_api_tokens_user_id")
except Exception as index_error:
logger.warning(f"Не удалось создать индекс ix_web_api_tokens_user_id: {index_error}")
return True
except Exception as error:
logger.error(f"Ошибка обновления web_api_tokens.user_id: {error}")
return False
async def create_privacy_policies_table() -> bool:
table_exists = await check_table_exists("privacy_policies")
if table_exists:
@@ -2872,7 +2799,6 @@ async def run_universal_migration():
web_api_tokens_ready = await create_web_api_tokens_table()
if web_api_tokens_ready:
logger.info("✅ Таблица web_api_tokens готова")
await ensure_web_api_tokens_user_column()
else:
logger.warning("⚠️ Проблемы с таблицей web_api_tokens")