초기 커밋
This commit is contained in:
0
app/repositories/__init__.py
Normal file
0
app/repositories/__init__.py
Normal file
44
app/repositories/analytics_repo.py
Normal file
44
app/repositories/analytics_repo.py
Normal file
@@ -0,0 +1,44 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from app.models.mongodb.analytics_result import AnalyticsResult
|
||||
|
||||
|
||||
class AnalyticsRepository:
|
||||
async def create(self, result: AnalyticsResult) -> AnalyticsResult:
|
||||
return await result.insert()
|
||||
|
||||
async def get_by_type(
|
||||
self,
|
||||
analysis_type: str,
|
||||
device_id: str | None = None,
|
||||
skip: int = 0,
|
||||
limit: int = 20,
|
||||
) -> list[AnalyticsResult]:
|
||||
query: dict = {"analysis_type": analysis_type}
|
||||
if device_id:
|
||||
query["device_id"] = device_id
|
||||
return await (
|
||||
AnalyticsResult.find(query)
|
||||
.sort("-created_at")
|
||||
.skip(skip)
|
||||
.limit(limit)
|
||||
.to_list()
|
||||
)
|
||||
|
||||
async def get_by_period(
|
||||
self,
|
||||
analysis_type: str,
|
||||
start: datetime,
|
||||
end: datetime,
|
||||
device_id: str | None = None,
|
||||
) -> list[AnalyticsResult]:
|
||||
query: dict = {
|
||||
"analysis_type": analysis_type,
|
||||
"period_start": {"$gte": start},
|
||||
"period_end": {"$lte": end},
|
||||
}
|
||||
if device_id:
|
||||
query["device_id"] = device_id
|
||||
return await AnalyticsResult.find(query).sort("-created_at").to_list()
|
||||
50
app/repositories/auth_repo.py
Normal file
50
app/repositories/auth_repo.py
Normal file
@@ -0,0 +1,50 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.models.mariadb.auth import OAuthAccount, RefreshToken
|
||||
from app.repositories.base import BaseRepository
|
||||
|
||||
|
||||
class AuthRepository(BaseRepository[RefreshToken]):
|
||||
def __init__(self, session: AsyncSession):
|
||||
super().__init__(RefreshToken, session)
|
||||
|
||||
async def get_by_token(self, token: str) -> RefreshToken | None:
|
||||
stmt = select(RefreshToken).where(
|
||||
RefreshToken.token == token,
|
||||
RefreshToken.is_revoked == False, # noqa: E712
|
||||
RefreshToken.expires_at > datetime.utcnow(),
|
||||
)
|
||||
result = await self.session.execute(stmt)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
async def revoke_all_for_user(self, user_id: int) -> None:
|
||||
stmt = select(RefreshToken).where(
|
||||
RefreshToken.user_id == user_id,
|
||||
RefreshToken.is_revoked == False, # noqa: E712
|
||||
)
|
||||
result = await self.session.execute(stmt)
|
||||
for token in result.scalars().all():
|
||||
token.is_revoked = True
|
||||
self.session.add(token)
|
||||
await self.session.flush()
|
||||
|
||||
async def get_oauth_account(
|
||||
self, provider: str, provider_user_id: str
|
||||
) -> OAuthAccount | None:
|
||||
stmt = select(OAuthAccount).where(
|
||||
OAuthAccount.provider == provider,
|
||||
OAuthAccount.provider_user_id == provider_user_id,
|
||||
)
|
||||
result = await self.session.execute(stmt)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
async def create_oauth_account(self, account: OAuthAccount) -> OAuthAccount:
|
||||
self.session.add(account)
|
||||
await self.session.flush()
|
||||
await self.session.refresh(account)
|
||||
return account
|
||||
58
app/repositories/base.py
Normal file
58
app/repositories/base.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Generic, Sequence, TypeVar
|
||||
|
||||
from sqlalchemy import func, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlmodel import SQLModel
|
||||
|
||||
T = TypeVar("T", bound=SQLModel)
|
||||
|
||||
|
||||
class BaseRepository(Generic[T]):
|
||||
def __init__(self, model: type[T], session: AsyncSession):
|
||||
self.model = model
|
||||
self.session = session
|
||||
|
||||
async def get_by_id(self, id: int) -> T | None:
|
||||
return await self.session.get(self.model, id)
|
||||
|
||||
async def get_all(
|
||||
self, *, skip: int = 0, limit: int = 100, filters: dict | None = None
|
||||
) -> Sequence[T]:
|
||||
stmt = select(self.model)
|
||||
if filters:
|
||||
for key, value in filters.items():
|
||||
if hasattr(self.model, key):
|
||||
stmt = stmt.where(getattr(self.model, key) == value)
|
||||
stmt = stmt.offset(skip).limit(limit)
|
||||
result = await self.session.execute(stmt)
|
||||
return result.scalars().all()
|
||||
|
||||
async def count(self, filters: dict | None = None) -> int:
|
||||
stmt = select(func.count()).select_from(self.model)
|
||||
if filters:
|
||||
for key, value in filters.items():
|
||||
if hasattr(self.model, key):
|
||||
stmt = stmt.where(getattr(self.model, key) == value)
|
||||
result = await self.session.execute(stmt)
|
||||
return result.scalar_one()
|
||||
|
||||
async def create(self, obj: T) -> T:
|
||||
self.session.add(obj)
|
||||
await self.session.flush()
|
||||
await self.session.refresh(obj)
|
||||
return obj
|
||||
|
||||
async def update(self, obj: T, data: dict) -> T:
|
||||
for key, value in data.items():
|
||||
if value is not None and hasattr(obj, key):
|
||||
setattr(obj, key, value)
|
||||
self.session.add(obj)
|
||||
await self.session.flush()
|
||||
await self.session.refresh(obj)
|
||||
return obj
|
||||
|
||||
async def delete(self, obj: T) -> None:
|
||||
await self.session.delete(obj)
|
||||
await self.session.flush()
|
||||
40
app/repositories/device_log_repo.py
Normal file
40
app/repositories/device_log_repo.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from app.models.mongodb.device_log import DeviceLog
|
||||
|
||||
|
||||
class DeviceLogRepository:
|
||||
async def create(self, log: DeviceLog) -> DeviceLog:
|
||||
return await log.insert()
|
||||
|
||||
async def get_by_device(
|
||||
self,
|
||||
device_id: str,
|
||||
event_type: str | None = None,
|
||||
since: datetime | None = None,
|
||||
skip: int = 0,
|
||||
limit: int = 100,
|
||||
) -> list[DeviceLog]:
|
||||
query: dict = {"device_id": device_id}
|
||||
if event_type:
|
||||
query["event_type"] = event_type
|
||||
if since:
|
||||
query["timestamp"] = {"$gte": since}
|
||||
|
||||
return await (
|
||||
DeviceLog.find(query)
|
||||
.sort("-timestamp")
|
||||
.skip(skip)
|
||||
.limit(limit)
|
||||
.to_list()
|
||||
)
|
||||
|
||||
async def count_by_device(
|
||||
self, device_id: str, event_type: str | None = None
|
||||
) -> int:
|
||||
query: dict = {"device_id": device_id}
|
||||
if event_type:
|
||||
query["event_type"] = event_type
|
||||
return await DeviceLog.find(query).count()
|
||||
47
app/repositories/device_repo.py
Normal file
47
app/repositories/device_repo.py
Normal file
@@ -0,0 +1,47 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.models.mariadb.device import Device, DeviceGroup
|
||||
from app.repositories.base import BaseRepository
|
||||
|
||||
|
||||
class DeviceRepository(BaseRepository[Device]):
|
||||
def __init__(self, session: AsyncSession):
|
||||
super().__init__(Device, session)
|
||||
|
||||
async def get_by_uid(self, device_uid: str) -> Device | None:
|
||||
stmt = select(Device).where(Device.device_uid == device_uid, Device.is_deleted == False) # noqa: E712
|
||||
result = await self.session.execute(stmt)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
async def get_by_owner(self, owner_id: int, skip: int = 0, limit: int = 100) -> list[Device]:
|
||||
stmt = (
|
||||
select(Device)
|
||||
.where(Device.owner_id == owner_id, Device.is_deleted == False) # noqa: E712
|
||||
.offset(skip)
|
||||
.limit(limit)
|
||||
)
|
||||
result = await self.session.execute(stmt)
|
||||
return list(result.scalars().all())
|
||||
|
||||
async def get_by_group(self, group_id: int, skip: int = 0, limit: int = 100) -> list[Device]:
|
||||
stmt = (
|
||||
select(Device)
|
||||
.where(Device.group_id == group_id, Device.is_deleted == False) # noqa: E712
|
||||
.offset(skip)
|
||||
.limit(limit)
|
||||
)
|
||||
result = await self.session.execute(stmt)
|
||||
return list(result.scalars().all())
|
||||
|
||||
|
||||
class DeviceGroupRepository(BaseRepository[DeviceGroup]):
|
||||
def __init__(self, session: AsyncSession):
|
||||
super().__init__(DeviceGroup, session)
|
||||
|
||||
async def get_by_name(self, name: str) -> DeviceGroup | None:
|
||||
stmt = select(DeviceGroup).where(DeviceGroup.name == name)
|
||||
result = await self.session.execute(stmt)
|
||||
return result.scalar_one_or_none()
|
||||
36
app/repositories/monitoring_repo.py
Normal file
36
app/repositories/monitoring_repo.py
Normal file
@@ -0,0 +1,36 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.models.mariadb.monitoring import Alert, AlertRule
|
||||
from app.repositories.base import BaseRepository
|
||||
|
||||
|
||||
class AlertRuleRepository(BaseRepository[AlertRule]):
|
||||
def __init__(self, session: AsyncSession):
|
||||
super().__init__(AlertRule, session)
|
||||
|
||||
async def get_enabled_rules(self) -> list[AlertRule]:
|
||||
stmt = select(AlertRule).where(AlertRule.is_enabled == True) # noqa: E712
|
||||
result = await self.session.execute(stmt)
|
||||
return list(result.scalars().all())
|
||||
|
||||
|
||||
class AlertRepository(BaseRepository[Alert]):
|
||||
def __init__(self, session: AsyncSession):
|
||||
super().__init__(Alert, session)
|
||||
|
||||
async def get_unacknowledged(self, skip: int = 0, limit: int = 50) -> list[Alert]:
|
||||
stmt = (
|
||||
select(Alert)
|
||||
.where(Alert.is_acknowledged == False) # noqa: E712
|
||||
.order_by(Alert.created_at.desc())
|
||||
.offset(skip)
|
||||
.limit(limit)
|
||||
)
|
||||
result = await self.session.execute(stmt)
|
||||
return list(result.scalars().all())
|
||||
|
||||
async def count_active(self) -> int:
|
||||
return await self.count(filters={"is_acknowledged": False})
|
||||
44
app/repositories/user_repo.py
Normal file
44
app/repositories/user_repo.py
Normal file
@@ -0,0 +1,44 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.orm import selectinload
|
||||
|
||||
from app.models.mariadb.user import User, UserProfile
|
||||
from app.repositories.base import BaseRepository
|
||||
|
||||
|
||||
class UserRepository(BaseRepository[User]):
|
||||
def __init__(self, session: AsyncSession):
|
||||
super().__init__(User, session)
|
||||
|
||||
async def get_by_email(self, email: str) -> User | None:
|
||||
stmt = select(User).where(User.email == email)
|
||||
result = await self.session.execute(stmt)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
async def get_with_profile(self, user_id: int) -> User | None:
|
||||
stmt = (
|
||||
select(User)
|
||||
.options(selectinload(User.profile))
|
||||
.where(User.id == user_id)
|
||||
)
|
||||
result = await self.session.execute(stmt)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
async def create_with_profile(
|
||||
self, user: User, full_name: str = "", phone: str = "", organization: str = ""
|
||||
) -> User:
|
||||
self.session.add(user)
|
||||
await self.session.flush()
|
||||
|
||||
profile = UserProfile(
|
||||
user_id=user.id, # type: ignore[arg-type]
|
||||
full_name=full_name,
|
||||
phone=phone,
|
||||
organization=organization,
|
||||
)
|
||||
self.session.add(profile)
|
||||
await self.session.flush()
|
||||
await self.session.refresh(user)
|
||||
return user
|
||||
Reference in New Issue
Block a user