75 lines
3.0 KiB
Python
75 lines
3.0 KiB
Python
|
import os
|
||
|
import time
|
||
|
from pathlib import Path
|
||
|
from fastapi import APIRouter, Depends, HTTPException, Request, UploadFile, status
|
||
|
from fastapi.responses import StreamingResponse
|
||
|
from sqlalchemy import and_, insert, select, update
|
||
|
|
||
|
from materia import db
|
||
|
from materia.api.state import ConfigState, DatabaseState
|
||
|
from materia.api.middleware import JwtMiddleware
|
||
|
from materia.config import Config
|
||
|
from materia.api import schema
|
||
|
|
||
|
|
||
|
router = APIRouter(tags = ["directory"])
|
||
|
|
||
|
@router.post("/directory", dependencies = [Depends(JwtMiddleware())])
|
||
|
async def create(request: Request, path: Path = Path(), config: ConfigState = Depends(), database: DatabaseState = Depends()):
|
||
|
user = request.state.user
|
||
|
repository_path = Config.data_dir() / "repository" / user.login_name.lower()
|
||
|
blacklist = [os.sep, ".", "..", "*"]
|
||
|
directory_path = Path(os.sep.join(filter(lambda part: part not in blacklist, path.parts)))
|
||
|
|
||
|
async with database.session() as session:
|
||
|
session.add(user)
|
||
|
await session.refresh(user, attribute_names = ["repository"])
|
||
|
|
||
|
current_directory = None
|
||
|
current_path = Path()
|
||
|
directory = None
|
||
|
|
||
|
for part in directory_path.parts:
|
||
|
if not (directory := (await session
|
||
|
.scalars(select(db.Directory)
|
||
|
.where(and_(db.Directory.name == part, db.Directory.path == str(current_path))))
|
||
|
).first()):
|
||
|
directory = db.Directory(
|
||
|
repository_id = user.repository.id,
|
||
|
parent_id = current_directory.id if current_directory else None,
|
||
|
name = part,
|
||
|
path = str(current_path)
|
||
|
)
|
||
|
session.add(directory)
|
||
|
|
||
|
current_directory = directory
|
||
|
current_path /= part
|
||
|
|
||
|
try:
|
||
|
(repository_path / directory_path).mkdir(parents = True, exist_ok = True)
|
||
|
except OSError:
|
||
|
raise HTTPException(status.HTTP_500_INTERNAL_SERVER_ERROR, "Failed to created a directory")
|
||
|
|
||
|
await session.commit()
|
||
|
|
||
|
@router.get("/directory", dependencies = [Depends(JwtMiddleware())])
|
||
|
async def info(request: Request, repository_id: int, path: Path, config: ConfigState = Depends(), database: DatabaseState = Depends()):
|
||
|
async with database.session() as session:
|
||
|
if directory := (await session
|
||
|
.scalars(select(db.Directory)
|
||
|
.where(and_(db.Directory.repository_id == repository_id, db.Directory.name == path.name, db.Directory.path == path.parent))
|
||
|
)).first():
|
||
|
await session.refresh(directory, attribute_names = ["files"])
|
||
|
return schema.DirectoryInfo(
|
||
|
id = directory.id,
|
||
|
created_at = directory.created_unix,
|
||
|
updated_at = directory.updated_unix,
|
||
|
name = directory.name,
|
||
|
path = directory.path,
|
||
|
is_public = directory.is_public,
|
||
|
used = sum([ file.size for file in directory.files ])
|
||
|
)
|
||
|
|
||
|
else:
|
||
|
raise HTTPException(status.HTTP_404_NOT_FOUND, "Repository is not found")
|