You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
3.6 KiB
103 lines
3.6 KiB
from __future__ import annotations
|
|
|
|
from datetime import datetime, UTC
|
|
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.models.entities import Blob, FileEntry, FileVersion
|
|
|
|
|
|
class FileRepository:
|
|
def __init__(self, session: AsyncSession) -> None:
|
|
self.session = session
|
|
|
|
async def get_by_id(self, file_id: str) -> FileEntry | None:
|
|
return await self.session.get(FileEntry, file_id)
|
|
|
|
async def get_by_directory_and_name(self, directory_id: str, name: str) -> FileEntry | None:
|
|
result = await self.session.execute(
|
|
select(FileEntry).where(
|
|
FileEntry.directory_id == directory_id,
|
|
FileEntry.name == name,
|
|
FileEntry.is_deleted.is_(False),
|
|
FileEntry.deleted_at.is_(None),
|
|
)
|
|
)
|
|
return result.scalar_one_or_none()
|
|
|
|
async def list_by_directory(self, directory_id: str) -> list[FileEntry]:
|
|
result = await self.session.execute(
|
|
select(FileEntry)
|
|
.where(
|
|
FileEntry.directory_id == directory_id,
|
|
FileEntry.is_deleted.is_(False),
|
|
FileEntry.deleted_at.is_(None),
|
|
)
|
|
.order_by(FileEntry.name.asc())
|
|
)
|
|
return list(result.scalars().all())
|
|
|
|
async def list_deleted(self) -> list[FileEntry]:
|
|
result = await self.session.execute(
|
|
select(FileEntry)
|
|
.where(FileEntry.is_deleted.is_(True), FileEntry.deleted_at.is_not(None))
|
|
.order_by(FileEntry.deleted_at.desc(), FileEntry.name.asc())
|
|
)
|
|
return list(result.scalars().all())
|
|
|
|
async def list_active(self) -> list[FileEntry]:
|
|
result = await self.session.execute(
|
|
select(FileEntry)
|
|
.where(
|
|
FileEntry.is_deleted.is_(False),
|
|
FileEntry.deleted_at.is_(None),
|
|
)
|
|
.order_by(FileEntry.created_at.asc())
|
|
)
|
|
return list(result.scalars().all())
|
|
|
|
async def create_file_graph(
|
|
self,
|
|
file_entry: FileEntry,
|
|
file_version: FileVersion,
|
|
blob: Blob,
|
|
) -> FileEntry:
|
|
self.session.add(file_entry)
|
|
self.session.add(file_version)
|
|
await self.session.flush()
|
|
self.session.add(blob)
|
|
await self.session.flush()
|
|
await self.session.refresh(file_entry)
|
|
return file_entry
|
|
|
|
async def get_primary_blob_for_file(self, file_id: str) -> Blob | None:
|
|
result = await self.session.execute(
|
|
select(Blob)
|
|
.join(FileVersion, Blob.file_version_id == FileVersion.id)
|
|
.join(FileEntry, FileVersion.id == FileEntry.current_version_id)
|
|
.where(FileEntry.id == file_id, Blob.blob_index == 0)
|
|
)
|
|
return result.scalar_one_or_none()
|
|
|
|
async def get_blob_by_id(self, blob_id: str) -> Blob | None:
|
|
return await self.session.get(Blob, blob_id)
|
|
|
|
async def soft_delete(self, file_entry: FileEntry) -> FileEntry:
|
|
file_entry.is_deleted = True
|
|
file_entry.deleted_at = datetime.now(UTC)
|
|
await self.session.flush()
|
|
await self.session.refresh(file_entry)
|
|
return file_entry
|
|
|
|
async def restore(self, file_entry: FileEntry) -> FileEntry:
|
|
file_entry.is_deleted = False
|
|
file_entry.deleted_at = None
|
|
await self.session.flush()
|
|
await self.session.refresh(file_entry)
|
|
return file_entry
|
|
|
|
async def save(self, file_entry: FileEntry) -> FileEntry:
|
|
await self.session.flush()
|
|
await self.session.refresh(file_entry)
|
|
return file_entry
|
|
|