|
|
|
@@ -0,0 +1,629 @@
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import uuid
|
|
|
|
|
|
|
|
|
|
from fastapi import APIRouter, Depends, File, Form, Header, Request, Response, UploadFile, status
|
|
|
|
|
from fastapi.responses import FileResponse
|
|
|
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
|
|
|
|
|
|
from app.core.deps import get_current_user, get_db_session, require_api_permission
|
|
|
|
|
from app.schemas.collaboration import (
|
|
|
|
|
CollaborationCallbackPayload,
|
|
|
|
|
CollaborationCandidateRead,
|
|
|
|
|
CollaborationEditorConfigRead,
|
|
|
|
|
CollaborationEditRequestRead,
|
|
|
|
|
CollaborationEditRequestResolve,
|
|
|
|
|
CollaborationExportRecord,
|
|
|
|
|
CollaborationFileCreate,
|
|
|
|
|
CollaborationFileRead,
|
|
|
|
|
CollaborationFileUpdate,
|
|
|
|
|
CollaborationFolderCreate,
|
|
|
|
|
CollaborationFolderRead,
|
|
|
|
|
CollaborationFolderUpdate,
|
|
|
|
|
CollaborationMemberRead,
|
|
|
|
|
CollaborationMemberUpsert,
|
|
|
|
|
CollaborationOwnershipTransferRequest,
|
|
|
|
|
CollaborationPublicEditorConfigRequest,
|
|
|
|
|
CollaborationPublicShareMetadata,
|
|
|
|
|
CollaborationRestoreRequest,
|
|
|
|
|
CollaborationRevisionCopyRequest,
|
|
|
|
|
CollaborationRevisionRead,
|
|
|
|
|
CollaborationRevisionUpdate,
|
|
|
|
|
CollaborationShareAccessGrant,
|
|
|
|
|
CollaborationShareLinkRead,
|
|
|
|
|
CollaborationShareLinkUpdate,
|
|
|
|
|
CollaborationSharePasswordRequest,
|
|
|
|
|
)
|
|
|
|
|
from app.schemas.onlyoffice import OnlyOfficePreviewConfigRead
|
|
|
|
|
from app.services import collaboration_service, collaboration_share_service, onlyoffice_collaboration_service, onlyoffice_service
|
|
|
|
|
|
|
|
|
|
router = APIRouter()
|
|
|
|
|
public_router = APIRouter()
|
|
|
|
|
internal_router = APIRouter(include_in_schema=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get(
|
|
|
|
|
"/folders",
|
|
|
|
|
response_model=list[CollaborationFolderRead],
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def list_folders(study_id: uuid.UUID, db: AsyncSession = Depends(get_db_session)):
|
|
|
|
|
return await collaboration_service.list_folders(db, study_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post(
|
|
|
|
|
"/folders",
|
|
|
|
|
response_model=CollaborationFolderRead,
|
|
|
|
|
status_code=status.HTTP_201_CREATED,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:manage"))],
|
|
|
|
|
)
|
|
|
|
|
async def create_folder(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
payload: CollaborationFolderCreate,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
return await collaboration_service.create_folder(db, study_id, payload, current_user)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.patch(
|
|
|
|
|
"/folders/{folder_id}",
|
|
|
|
|
response_model=CollaborationFolderRead,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:manage"))],
|
|
|
|
|
)
|
|
|
|
|
async def update_folder(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
folder_id: uuid.UUID,
|
|
|
|
|
payload: CollaborationFolderUpdate,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
):
|
|
|
|
|
return await collaboration_service.update_folder(db, study_id, folder_id, payload)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.delete(
|
|
|
|
|
"/folders/{folder_id}",
|
|
|
|
|
status_code=status.HTTP_204_NO_CONTENT,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:manage"))],
|
|
|
|
|
)
|
|
|
|
|
async def delete_folder(study_id: uuid.UUID, folder_id: uuid.UUID, db: AsyncSession = Depends(get_db_session)):
|
|
|
|
|
await collaboration_service.delete_folder(db, study_id, folder_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get(
|
|
|
|
|
"/files",
|
|
|
|
|
response_model=list[CollaborationFileRead],
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def list_files(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
folder_id: uuid.UUID | None = None,
|
|
|
|
|
keyword: str | None = None,
|
|
|
|
|
deleted: bool = False,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
return await collaboration_service.list_files(
|
|
|
|
|
db, study_id, current_user, folder_id=folder_id, keyword=keyword, deleted=deleted
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post(
|
|
|
|
|
"/files",
|
|
|
|
|
response_model=CollaborationFileRead,
|
|
|
|
|
status_code=status.HTTP_201_CREATED,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:create"))],
|
|
|
|
|
)
|
|
|
|
|
async def create_file(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
payload: CollaborationFileCreate,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.create_blank_file(db, study_id, payload, current_user)
|
|
|
|
|
return await collaboration_service.file_read(db, item, current_user)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post(
|
|
|
|
|
"/files/import",
|
|
|
|
|
response_model=CollaborationFileRead,
|
|
|
|
|
status_code=status.HTTP_201_CREATED,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:create"))],
|
|
|
|
|
)
|
|
|
|
|
async def import_file(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file: UploadFile = File(...),
|
|
|
|
|
folder_id: uuid.UUID | None = Form(None),
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.import_file(db, study_id, folder_id, file, current_user)
|
|
|
|
|
return await collaboration_service.file_read(db, item, current_user)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post(
|
|
|
|
|
"/files/{file_id}/copy",
|
|
|
|
|
response_model=CollaborationFileRead,
|
|
|
|
|
status_code=status.HTTP_201_CREATED,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:create"))],
|
|
|
|
|
)
|
|
|
|
|
async def copy_file(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
source = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
item = await collaboration_service.copy_file(db, source, current_user)
|
|
|
|
|
return await collaboration_service.file_read(db, item, current_user)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get(
|
|
|
|
|
"/files/{file_id}",
|
|
|
|
|
response_model=CollaborationFileRead,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def get_file(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
return await collaboration_service.file_read(db, item, current_user)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get(
|
|
|
|
|
"/files/{file_id}/download",
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def download_file(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
revision = await collaboration_service.prepare_download(db, item, current_user)
|
|
|
|
|
return FileResponse(
|
|
|
|
|
path=revision.file_uri,
|
|
|
|
|
media_type=revision.mime_type,
|
|
|
|
|
filename=item.title,
|
|
|
|
|
content_disposition_type="attachment",
|
|
|
|
|
headers={"Cache-Control": "no-store"},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.patch(
|
|
|
|
|
"/files/{file_id}",
|
|
|
|
|
response_model=CollaborationFileRead,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def update_file(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
payload: CollaborationFileUpdate,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
item = await collaboration_service.update_file(db, item, payload, current_user)
|
|
|
|
|
return await collaboration_service.file_read(db, item, current_user)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.delete(
|
|
|
|
|
"/files/{file_id}",
|
|
|
|
|
status_code=status.HTTP_204_NO_CONTENT,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def trash_file(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
await collaboration_service.move_to_trash(db, item, current_user)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post(
|
|
|
|
|
"/files/{file_id}/restore",
|
|
|
|
|
response_model=CollaborationFileRead,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def restore_file(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id, include_deleted=True)
|
|
|
|
|
item = await collaboration_service.restore_file(db, item, current_user)
|
|
|
|
|
return await collaboration_service.file_read(db, item, current_user)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get(
|
|
|
|
|
"/files/{file_id}/members",
|
|
|
|
|
response_model=list[CollaborationMemberRead],
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def list_members(study_id: uuid.UUID, file_id: uuid.UUID, db: AsyncSession = Depends(get_db_session)):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
return await collaboration_service.list_members(db, item)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.put(
|
|
|
|
|
"/files/{file_id}/members",
|
|
|
|
|
response_model=CollaborationMemberRead,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def upsert_member(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
payload: CollaborationMemberUpsert,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
return await collaboration_service.upsert_member(db, item, payload, current_user)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.delete(
|
|
|
|
|
"/files/{file_id}/members/{user_id}",
|
|
|
|
|
status_code=status.HTTP_204_NO_CONTENT,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def remove_member(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
user_id: uuid.UUID,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
await collaboration_service.remove_member(db, item, user_id, current_user)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post(
|
|
|
|
|
"/files/{file_id}/edit-requests",
|
|
|
|
|
response_model=CollaborationEditRequestRead,
|
|
|
|
|
status_code=status.HTTP_201_CREATED,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def create_edit_request(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
return await collaboration_service.create_edit_request(db, item, current_user)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get(
|
|
|
|
|
"/files/{file_id}/edit-requests",
|
|
|
|
|
response_model=list[CollaborationEditRequestRead],
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def list_edit_requests(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
pending_only: bool = True,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
return await collaboration_service.list_edit_requests(db, item, current_user, pending_only=pending_only)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post(
|
|
|
|
|
"/files/{file_id}/edit-requests/{request_id}/resolve",
|
|
|
|
|
response_model=CollaborationEditRequestRead,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def resolve_edit_request(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
request_id: uuid.UUID,
|
|
|
|
|
payload: CollaborationEditRequestResolve,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
return await collaboration_service.resolve_edit_request(db, item, request_id, payload, current_user)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post(
|
|
|
|
|
"/files/{file_id}/transfer-ownership",
|
|
|
|
|
response_model=CollaborationFileRead,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def transfer_ownership(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
payload: CollaborationOwnershipTransferRequest,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
item = await collaboration_service.transfer_ownership(db, item, payload, current_user)
|
|
|
|
|
return await collaboration_service.file_read(db, item, current_user)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get(
|
|
|
|
|
"/files/{file_id}/share-link",
|
|
|
|
|
response_model=CollaborationShareLinkRead,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def get_share_link(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
response: Response,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
result = await collaboration_share_service.get_share_link(db, item, current_user)
|
|
|
|
|
response.headers["Cache-Control"] = "no-store"
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.put(
|
|
|
|
|
"/files/{file_id}/share-link",
|
|
|
|
|
response_model=CollaborationShareLinkRead,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def update_share_link(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
payload: CollaborationShareLinkUpdate,
|
|
|
|
|
response: Response,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
result = await collaboration_share_service.update_share_link(db, item, payload, current_user)
|
|
|
|
|
response.headers["Cache-Control"] = "no-store"
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get(
|
|
|
|
|
"/member-candidates",
|
|
|
|
|
response_model=list[CollaborationCandidateRead],
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def list_member_candidates(study_id: uuid.UUID, db: AsyncSession = Depends(get_db_session)):
|
|
|
|
|
return await collaboration_service.list_candidates(db, study_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get(
|
|
|
|
|
"/files/{file_id}/revisions",
|
|
|
|
|
response_model=list[CollaborationRevisionRead],
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def list_revisions(study_id: uuid.UUID, file_id: uuid.UUID, db: AsyncSession = Depends(get_db_session)):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
return await collaboration_service.list_revisions(db, item)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.patch(
|
|
|
|
|
"/files/{file_id}/revisions/{revision_id}",
|
|
|
|
|
response_model=CollaborationRevisionRead,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def update_revision(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
revision_id: uuid.UUID,
|
|
|
|
|
payload: CollaborationRevisionUpdate,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
return await collaboration_service.update_revision(db, item, revision_id, payload, current_user)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.delete(
|
|
|
|
|
"/files/{file_id}/revisions/{revision_id}",
|
|
|
|
|
status_code=status.HTTP_204_NO_CONTENT,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def delete_revision(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
revision_id: uuid.UUID,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
await collaboration_service.delete_revision(db, item, revision_id, current_user)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post(
|
|
|
|
|
"/files/{file_id}/revisions/{revision_id}/copy",
|
|
|
|
|
response_model=CollaborationFileRead,
|
|
|
|
|
status_code=status.HTTP_201_CREATED,
|
|
|
|
|
dependencies=[
|
|
|
|
|
Depends(require_api_permission("collaboration:create")),
|
|
|
|
|
Depends(require_api_permission("collaboration:read")),
|
|
|
|
|
],
|
|
|
|
|
)
|
|
|
|
|
async def copy_revision(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
revision_id: uuid.UUID,
|
|
|
|
|
payload: CollaborationRevisionCopyRequest,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
copied = await collaboration_service.copy_revision(db, item, revision_id, payload, current_user)
|
|
|
|
|
return await collaboration_service.file_read(db, copied, current_user)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get(
|
|
|
|
|
"/files/{file_id}/revisions/{revision_id}/preview-config",
|
|
|
|
|
response_model=OnlyOfficePreviewConfigRead,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def get_revision_preview_config(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
revision_id: uuid.UUID,
|
|
|
|
|
response: Response,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
revision = await collaboration_service.prepare_revision_preview(db, item, revision_id, current_user)
|
|
|
|
|
await onlyoffice_service.ensure_onlyoffice_available()
|
|
|
|
|
result = onlyoffice_service.build_preview_config(
|
|
|
|
|
resource_type="collaboration_revision",
|
|
|
|
|
resource_id=revision.id,
|
|
|
|
|
file_name=item.title,
|
|
|
|
|
file_hash=revision.file_hash,
|
|
|
|
|
user_id=current_user.id,
|
|
|
|
|
user_name=current_user.full_name,
|
|
|
|
|
)
|
|
|
|
|
response.headers["Cache-Control"] = "no-store"
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post(
|
|
|
|
|
"/files/{file_id}/revisions/{revision_id}/restore",
|
|
|
|
|
response_model=CollaborationRevisionRead,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def restore_revision(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
revision_id: uuid.UUID,
|
|
|
|
|
payload: CollaborationRestoreRequest,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
return await collaboration_service.restore_revision(
|
|
|
|
|
db, item, revision_id, current_user, payload.change_summary
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get(
|
|
|
|
|
"/files/{file_id}/editor-config",
|
|
|
|
|
response_model=CollaborationEditorConfigRead,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def get_editor_config(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
response: Response,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
result = await onlyoffice_collaboration_service.build_editor_config(db, item, current_user)
|
|
|
|
|
response.headers["Cache-Control"] = "no-store"
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post(
|
|
|
|
|
"/files/{file_id}/exports",
|
|
|
|
|
status_code=status.HTTP_204_NO_CONTENT,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def record_export(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
payload: CollaborationExportRecord,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
await collaboration_service.record_export(db, item, current_user, payload.file_type)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post(
|
|
|
|
|
"/files/{file_id}/downloads",
|
|
|
|
|
status_code=status.HTTP_204_NO_CONTENT,
|
|
|
|
|
dependencies=[Depends(require_api_permission("collaboration:read"))],
|
|
|
|
|
)
|
|
|
|
|
async def record_download(
|
|
|
|
|
study_id: uuid.UUID,
|
|
|
|
|
file_id: uuid.UUID,
|
|
|
|
|
payload: CollaborationExportRecord,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
current_user=Depends(get_current_user),
|
|
|
|
|
):
|
|
|
|
|
item = await collaboration_service.get_file_or_404(db, study_id, file_id)
|
|
|
|
|
await collaboration_service.record_download(db, item, current_user, payload.file_type)
|
|
|
|
|
return Response(status_code=status.HTTP_204_NO_CONTENT)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@public_router.get("/metadata", response_model=CollaborationPublicShareMetadata)
|
|
|
|
|
async def get_public_share_metadata(
|
|
|
|
|
response: Response,
|
|
|
|
|
x_ctms_share_token: str | None = Header(default=None, alias="X-CTMS-Share-Token"),
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
):
|
|
|
|
|
result = await collaboration_share_service.public_metadata(db, x_ctms_share_token)
|
|
|
|
|
response.headers["Cache-Control"] = "no-store"
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@public_router.post("/access", response_model=CollaborationShareAccessGrant)
|
|
|
|
|
async def verify_public_share_password(
|
|
|
|
|
payload: CollaborationSharePasswordRequest,
|
|
|
|
|
response: Response,
|
|
|
|
|
x_ctms_share_token: str | None = Header(default=None, alias="X-CTMS-Share-Token"),
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
):
|
|
|
|
|
result = await collaboration_share_service.verify_share_password(
|
|
|
|
|
db, x_ctms_share_token, payload.password
|
|
|
|
|
)
|
|
|
|
|
response.headers["Cache-Control"] = "no-store"
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@public_router.post("/editor-config", response_model=CollaborationEditorConfigRead)
|
|
|
|
|
async def get_public_share_editor_config(
|
|
|
|
|
payload: CollaborationPublicEditorConfigRequest,
|
|
|
|
|
response: Response,
|
|
|
|
|
x_ctms_share_token: str | None = Header(default=None, alias="X-CTMS-Share-Token"),
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
):
|
|
|
|
|
link, item = await collaboration_share_service.resolve_active_share(db, x_ctms_share_token)
|
|
|
|
|
collaboration_share_service.validate_access_grant(link, payload.access_token)
|
|
|
|
|
result = await onlyoffice_collaboration_service.build_shared_editor_config(
|
|
|
|
|
db,
|
|
|
|
|
item,
|
|
|
|
|
link,
|
|
|
|
|
client_id=payload.client_id,
|
|
|
|
|
display_name=payload.display_name,
|
|
|
|
|
)
|
|
|
|
|
response.headers["Cache-Control"] = "no-store"
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@internal_router.get("/internal/onlyoffice/collaboration/sessions/{session_id}/content")
|
|
|
|
|
async def get_session_content(session_id: uuid.UUID, request: Request, db: AsyncSession = Depends(get_db_session)):
|
|
|
|
|
revision, item = await onlyoffice_collaboration_service.get_session_content(
|
|
|
|
|
db, session_id, request.headers.get("AuthorizationJwt")
|
|
|
|
|
)
|
|
|
|
|
return FileResponse(
|
|
|
|
|
path=revision.file_uri,
|
|
|
|
|
media_type=revision.mime_type,
|
|
|
|
|
filename=item.title,
|
|
|
|
|
content_disposition_type="inline",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@internal_router.post("/internal/onlyoffice/collaboration/sessions/{session_id}/callback")
|
|
|
|
|
async def collaboration_callback(
|
|
|
|
|
session_id: uuid.UUID,
|
|
|
|
|
payload: CollaborationCallbackPayload,
|
|
|
|
|
request: Request,
|
|
|
|
|
db: AsyncSession = Depends(get_db_session),
|
|
|
|
|
):
|
|
|
|
|
onlyoffice_collaboration_service.validate_callback_token(
|
|
|
|
|
request.headers.get("AuthorizationJwt"), payload
|
|
|
|
|
)
|
|
|
|
|
return await onlyoffice_collaboration_service.process_callback(db, session_id, payload)
|