mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-17 02:49:12 +00:00
Run black on utils
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
from uuid import UUID
|
||||
from fastapi import APIRouter, Depends, UploadFile, HTTPException
|
||||
from fastapi import APIRouter, Depends, UploadFile, HTTPException
|
||||
from fastapi.responses import FileResponse
|
||||
|
||||
from security.secure import get_current_active_user
|
||||
@@ -46,38 +46,40 @@ router = APIRouter(route_class=LoggingRoute)
|
||||
@router.get("/bcf/3.0/projects", tags=["projects_get"])
|
||||
def projects_get(current_user: User = Depends(get_current_active_user)) -> List[ProjectGET]:
|
||||
projects_response = bcf_db.get_projects(current_user)
|
||||
bcf_db.debug(endpoint='projects_get',
|
||||
request={},
|
||||
response={count: value.dict() for count, value in enumerate(projects_response)})
|
||||
bcf_db.debug(
|
||||
endpoint="projects_get",
|
||||
request={},
|
||||
response={count: value.dict() for count, value in enumerate(projects_response)},
|
||||
)
|
||||
return projects_response
|
||||
|
||||
|
||||
@router.get("/bcf/3.0/projects/{project_id}", tags=["project_get"])
|
||||
def project_get(project_id: UUID, current_user: User = Depends(get_current_active_user)) -> ProjectGET:
|
||||
project_response = bcf_db.get_project(project_id, current_user)
|
||||
bcf_db.debug(endpoint='project_get',
|
||||
request={'project_id': project_id},
|
||||
response=project_response.dict())
|
||||
bcf_db.debug(endpoint="project_get", request={"project_id": project_id}, response=project_response.dict())
|
||||
return project_response
|
||||
|
||||
|
||||
@router.put("/bcf/3.0/projects/{project_id}", tags=["project_put"], status_code=200)
|
||||
def project_put(project_id: UUID, project_request: ProjectPUT,
|
||||
current_user: User = Depends(get_current_active_user)) -> ProjectGET:
|
||||
def project_put(
|
||||
project_id: UUID, project_request: ProjectPUT, current_user: User = Depends(get_current_active_user)
|
||||
) -> ProjectGET:
|
||||
project_response = bcf_db.put_project(project_id, project_request, current_user)
|
||||
bcf_db.debug(endpoint='project_put',
|
||||
request={'project_id': project_id, 'project_request': project_request},
|
||||
response=project_response.dict())
|
||||
bcf_db.debug(
|
||||
endpoint="project_put",
|
||||
request={"project_id": project_id, "project_request": project_request},
|
||||
response=project_response.dict(),
|
||||
)
|
||||
return project_response
|
||||
|
||||
|
||||
@router.get("/bcf/3.0/projects/{project_id}/extensions", tags=["project_extensions_get"])
|
||||
def project_extensions_get(project_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> ExtensionsGET:
|
||||
def project_extensions_get(project_id: UUID, current_user: User = Depends(get_current_active_user)) -> ExtensionsGET:
|
||||
extensions_response = bcf_db.get_project_extensions(project_id, current_user)
|
||||
bcf_db.debug(endpoint='project_extensions_get',
|
||||
request={'project_id': project_id},
|
||||
response=extensions_response.dict())
|
||||
bcf_db.debug(
|
||||
endpoint="project_extensions_get", request={"project_id": project_id}, response=extensions_response.dict()
|
||||
)
|
||||
return extensions_response
|
||||
|
||||
|
||||
@@ -86,62 +88,68 @@ def project_extensions_get(project_id: UUID,
|
||||
#
|
||||
# Topics
|
||||
|
||||
|
||||
@router.get("/bcf/3.0/projects/{project_id}/topics", tags=["topics_get"])
|
||||
def topics_get(project_id: str,
|
||||
current_user: User = Depends(get_current_active_user)) -> List[TopicGET]:
|
||||
def topics_get(project_id: str, current_user: User = Depends(get_current_active_user)) -> List[TopicGET]:
|
||||
topics_response = bcf_db.get_topics(project_id, current_user)
|
||||
bcf_db.debug(endpoint='topics_get',
|
||||
request={'project_id': project_id},
|
||||
response={count: value.dict() for count, value in enumerate(topics_response)})
|
||||
bcf_db.debug(
|
||||
endpoint="topics_get",
|
||||
request={"project_id": project_id},
|
||||
response={count: value.dict() for count, value in enumerate(topics_response)},
|
||||
)
|
||||
return topics_response
|
||||
|
||||
|
||||
@router.post("/bcf/3.0/projects/{project_id}/topics", tags=["topic_post"], status_code=201)
|
||||
def topic_post(project_id: UUID, topic_request: TopicPOST,
|
||||
current_user: User = Depends(get_current_active_user)) -> TopicGET:
|
||||
def topic_post(
|
||||
project_id: UUID, topic_request: TopicPOST, current_user: User = Depends(get_current_active_user)
|
||||
) -> TopicGET:
|
||||
topic_response = bcf_db.post_topic(project_id, topic_request, current_user)
|
||||
if topic_response is None:
|
||||
raise HTTPException(status_code=400, detail="Could not create topic.")
|
||||
bcf_db.debug(endpoint='topic_post',
|
||||
request={'project_id': project_id, 'topic_request': topic_request.dict()},
|
||||
response=topic_response.dict())
|
||||
bcf_db.debug(
|
||||
endpoint="topic_post",
|
||||
request={"project_id": project_id, "topic_request": topic_request.dict()},
|
||||
response=topic_response.dict(),
|
||||
)
|
||||
return topic_response
|
||||
|
||||
|
||||
# Implemented
|
||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}", tags=["topic_get"])
|
||||
def topic_get(project_id: UUID, topic_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> TopicGET:
|
||||
def topic_get(project_id: UUID, topic_id: UUID, current_user: User = Depends(get_current_active_user)) -> TopicGET:
|
||||
topic_response = bcf_db.get_topic(project_id, topic_id, current_user)
|
||||
if topic_response is None:
|
||||
raise HTTPException(status_code=404, detail="Item not found.")
|
||||
bcf_db.debug(endpoint='topic_get',
|
||||
request={'project_id': project_id, 'topic_id': topic_id},
|
||||
response=topic_response.dict())
|
||||
bcf_db.debug(
|
||||
endpoint="topic_get", request={"project_id": project_id, "topic_id": topic_id}, response=topic_response.dict()
|
||||
)
|
||||
return topic_response
|
||||
|
||||
|
||||
# Implemented
|
||||
@router.put("/bcf/3.0/projects/{project_id}/topics/{topic_id}", tags=["topic_put"], status_code=200)
|
||||
def topic_put(project_id: UUID, topic_id: UUID, topic_request: TopicPUT,
|
||||
current_user: User = Depends(get_current_active_user)) -> TopicGET:
|
||||
def topic_put(
|
||||
project_id: UUID, topic_id: UUID, topic_request: TopicPUT, current_user: User = Depends(get_current_active_user)
|
||||
) -> TopicGET:
|
||||
topic_response = bcf_db.put_topic(project_id, topic_id, topic_request, current_user)
|
||||
bcf_db.debug(endpoint='topic_put',
|
||||
request={'project_id': project_id, 'topic_id': topic_id, 'topic_request': topic_request.dict()},
|
||||
response=topic_response.dict())
|
||||
bcf_db.debug(
|
||||
endpoint="topic_put",
|
||||
request={"project_id": project_id, "topic_id": topic_id, "topic_request": topic_request.dict()},
|
||||
response=topic_response.dict(),
|
||||
)
|
||||
return topic_response
|
||||
|
||||
|
||||
# Implemented
|
||||
@router.delete("/bcf/3.0/projects/{project_id}/topics/{topic_id}", tags=["topic_delete"], status_code=200)
|
||||
def topic_delete(project_id: UUID, topic_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> int:
|
||||
def topic_delete(project_id: UUID, topic_id: UUID, current_user: User = Depends(get_current_active_user)) -> int:
|
||||
topic_response = bcf_db.delete_topic(project_id, topic_id, current_user)
|
||||
if topic_response is None:
|
||||
raise HTTPException(status_code=404, detail="Item not found.")
|
||||
bcf_db.debug(endpoint='topic_delete',
|
||||
request={'project_id': project_id, 'topic_id': topic_id},
|
||||
response={topic_response})
|
||||
bcf_db.debug(
|
||||
endpoint="topic_delete", request={"project_id": project_id, "topic_id": topic_id}, response={topic_response}
|
||||
)
|
||||
return topic_response
|
||||
|
||||
|
||||
@@ -153,25 +161,31 @@ def topic_delete(project_id: UUID, topic_id: UUID,
|
||||
|
||||
# Implemented
|
||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/snippet", tags=["bim_snippet_get"])
|
||||
def bim_snippet_get(project_id: UUID, topic_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> BimSnippet:
|
||||
def bim_snippet_get(
|
||||
project_id: UUID, topic_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||
) -> BimSnippet:
|
||||
bim_snippet_response = bcf_db.get_bim_snippet(project_id, topic_id, current_user)
|
||||
if bim_snippet_response is None:
|
||||
raise HTTPException(status_code=404, detail="Item not found.")
|
||||
bcf_db.debug(endpoint='bim_snippet_get',
|
||||
request={'project_id': project_id, 'topic_id': topic_id},
|
||||
response=bim_snippet_response.dict())
|
||||
bcf_db.debug(
|
||||
endpoint="bim_snippet_get",
|
||||
request={"project_id": project_id, "topic_id": topic_id},
|
||||
response=bim_snippet_response.dict(),
|
||||
)
|
||||
return bim_snippet_response
|
||||
|
||||
|
||||
# Implemented
|
||||
@router.put("/bcf/3.0/projects/{project_id}/topics/{topic_id}/snippet", tags=["bim_snippet_put"], status_code=200)
|
||||
def bim_snippet_put(project_id: UUID, topic_id: UUID, snippet: BimSnippet,
|
||||
current_user: User = Depends(get_current_active_user)) -> BimSnippet:
|
||||
def bim_snippet_put(
|
||||
project_id: UUID, topic_id: UUID, snippet: BimSnippet, current_user: User = Depends(get_current_active_user)
|
||||
) -> BimSnippet:
|
||||
bim_snippet_response = bcf_db.put_bim_snippet(project_id, topic_id, snippet, current_user)
|
||||
bcf_db.debug(endpoint='bim_snippet_put',
|
||||
request={'project_id': project_id, 'topic_id': topic_id, 'snippet': snippet.dict()},
|
||||
response=bim_snippet_response.dict())
|
||||
bcf_db.debug(
|
||||
endpoint="bim_snippet_put",
|
||||
request={"project_id": project_id, "topic_id": topic_id, "snippet": snippet.dict()},
|
||||
response=bim_snippet_response.dict(),
|
||||
)
|
||||
return bim_snippet_response
|
||||
|
||||
|
||||
@@ -182,36 +196,45 @@ def bim_snippet_put(project_id: UUID, topic_id: UUID, snippet: BimSnippet,
|
||||
|
||||
|
||||
@router.get("/bcf/3.0/projects/{project_id}/files_information", tags=["files_information_get"])
|
||||
def files_information_get(project_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> List[ProjectFileInformation]:
|
||||
def files_information_get(
|
||||
project_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||
) -> List[ProjectFileInformation]:
|
||||
files_information_response = bcf_db.get_files_information(project_id, current_user)
|
||||
bcf_db.debug(endpoint='files_information_get',
|
||||
request={'project_id': project_id},
|
||||
response={count: value.dict() for count, value in enumerate(files_information_response)})
|
||||
bcf_db.debug(
|
||||
endpoint="files_information_get",
|
||||
request={"project_id": project_id},
|
||||
response={count: value.dict() for count, value in enumerate(files_information_response)},
|
||||
)
|
||||
return files_information_response
|
||||
|
||||
|
||||
# Implemented
|
||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/files", tags=["files_get"])
|
||||
def files_get(project_id: UUID, topic_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> List[FileGET]:
|
||||
def files_get(project_id: UUID, topic_id: UUID, current_user: User = Depends(get_current_active_user)) -> List[FileGET]:
|
||||
files_response = bcf_db.get_files(project_id, topic_id, current_user)
|
||||
bcf_db.debug(endpoint='files_get',
|
||||
request={'project_id': project_id, 'topic_id': topic_id},
|
||||
response={count: value.dict() for count, value in enumerate(files_response)})
|
||||
bcf_db.debug(
|
||||
endpoint="files_get",
|
||||
request={"project_id": project_id, "topic_id": topic_id},
|
||||
response={count: value.dict() for count, value in enumerate(files_response)},
|
||||
)
|
||||
return files_response
|
||||
|
||||
|
||||
# request body file = FilePUT
|
||||
@router.put("/bcf/3.0/projects/{project_id}/topics/{topic_id}/files", tags=["files_put"], status_code=200)
|
||||
def files_put(project_id: UUID, topic_id: UUID, files: List[FilePUT],
|
||||
current_user: User = Depends(get_current_active_user)) -> List[FileGET]:
|
||||
def files_put(
|
||||
project_id: UUID, topic_id: UUID, files: List[FilePUT], current_user: User = Depends(get_current_active_user)
|
||||
) -> List[FileGET]:
|
||||
files_response = bcf_db.put_files(project_id, topic_id, files, current_user)
|
||||
bcf_db.debug(endpoint='files_put',
|
||||
request={'project_id': project_id,
|
||||
'topic_id': topic_id,
|
||||
'files': {count: value.dict() for count, value in enumerate(files)}},
|
||||
response={count: value.dict() for count, value in enumerate(files_response)})
|
||||
bcf_db.debug(
|
||||
endpoint="files_put",
|
||||
request={
|
||||
"project_id": project_id,
|
||||
"topic_id": topic_id,
|
||||
"files": {count: value.dict() for count, value in enumerate(files)},
|
||||
},
|
||||
response={count: value.dict() for count, value in enumerate(files_response)},
|
||||
)
|
||||
return files_response
|
||||
|
||||
|
||||
@@ -222,58 +245,80 @@ def files_put(project_id: UUID, topic_id: UUID, files: List[FilePUT],
|
||||
|
||||
|
||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments", tags=["comments_get"])
|
||||
def comments_get(project_id: UUID, topic_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> List[CommentGET]:
|
||||
def comments_get(
|
||||
project_id: UUID, topic_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||
) -> List[CommentGET]:
|
||||
comments_response = bcf_db.get_comments(project_id, topic_id, current_user)
|
||||
bcf_db.debug(endpoint='comments_get',
|
||||
request={'project_id': project_id, 'topic_id': topic_id},
|
||||
response={count: value.dict() for count, value in enumerate(comments_response)})
|
||||
bcf_db.debug(
|
||||
endpoint="comments_get",
|
||||
request={"project_id": project_id, "topic_id": topic_id},
|
||||
response={count: value.dict() for count, value in enumerate(comments_response)},
|
||||
)
|
||||
return comments_response
|
||||
|
||||
|
||||
# request body comment = CommentPOST
|
||||
@router.post("/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments", tags=["comment_post"], status_code=201)
|
||||
def comment_post(project_id: UUID, topic_id: UUID, comment: CommentPOST,
|
||||
current_user: User = Depends(get_current_active_user)) -> CommentGET:
|
||||
def comment_post(
|
||||
project_id: UUID, topic_id: UUID, comment: CommentPOST, current_user: User = Depends(get_current_active_user)
|
||||
) -> CommentGET:
|
||||
comment_response = bcf_db.post_comment(project_id, topic_id, comment, current_user)
|
||||
bcf_db.debug(endpoint='comment_post',
|
||||
request={'project_id': project_id, 'topic_id': topic_id, 'comment': comment},
|
||||
response=comment_response.dict())
|
||||
bcf_db.debug(
|
||||
endpoint="comment_post",
|
||||
request={"project_id": project_id, "topic_id": topic_id, "comment": comment},
|
||||
response=comment_response.dict(),
|
||||
)
|
||||
return comment_response
|
||||
|
||||
|
||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments/{comment_id}", tags=["comment_get"])
|
||||
def comment_get(project_id: UUID, topic_id: UUID, comment_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> CommentGET:
|
||||
def comment_get(
|
||||
project_id: UUID, topic_id: UUID, comment_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||
) -> CommentGET:
|
||||
comment_response = bcf_db.get_comment(project_id, topic_id, comment_id, current_user)
|
||||
bcf_db.debug(endpoint='comment_get',
|
||||
request={'project_id': project_id, 'topic_id': topic_id, 'comment_id': comment_id},
|
||||
response=comment_response.dict())
|
||||
bcf_db.debug(
|
||||
endpoint="comment_get",
|
||||
request={"project_id": project_id, "topic_id": topic_id, "comment_id": comment_id},
|
||||
response=comment_response.dict(),
|
||||
)
|
||||
return comment_response
|
||||
|
||||
|
||||
# request body comment = CommentPUT
|
||||
@router.put("/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments/{comment_id}", tags=["comment_put"], status_code=200)
|
||||
def comment_put(project_id: UUID, topic_id: UUID, comment_id: UUID, comment: CommentPUT,
|
||||
current_user: User = Depends(get_current_active_user)) -> CommentGET:
|
||||
@router.put(
|
||||
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments/{comment_id}", tags=["comment_put"], status_code=200
|
||||
)
|
||||
def comment_put(
|
||||
project_id: UUID,
|
||||
topic_id: UUID,
|
||||
comment_id: UUID,
|
||||
comment: CommentPUT,
|
||||
current_user: User = Depends(get_current_active_user),
|
||||
) -> CommentGET:
|
||||
comment_response = bcf_db.put_comment(project_id, topic_id, comment_id, comment, current_user)
|
||||
bcf_db.debug(endpoint='comment_put',
|
||||
request={'project_id': project_id, 'topic_id': topic_id, 'comment': comment},
|
||||
response=comment_response.dict())
|
||||
bcf_db.debug(
|
||||
endpoint="comment_put",
|
||||
request={"project_id": project_id, "topic_id": topic_id, "comment": comment},
|
||||
response=comment_response.dict(),
|
||||
)
|
||||
return comment_response
|
||||
|
||||
|
||||
# Implemented
|
||||
@router.delete("/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments/{comment_id}",
|
||||
tags=["comment_delete"], status_code=200)
|
||||
def comment_delete(project_id: UUID, topic_id: UUID, comment_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> int:
|
||||
@router.delete(
|
||||
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments/{comment_id}", tags=["comment_delete"], status_code=200
|
||||
)
|
||||
def comment_delete(
|
||||
project_id: UUID, topic_id: UUID, comment_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||
) -> int:
|
||||
comment_response = bcf_db.delete_comment(project_id, topic_id, comment_id, current_user)
|
||||
if comment_response is None:
|
||||
raise HTTPException(status_code=404, detail="Item not found.")
|
||||
bcf_db.debug(endpoint='comment_delete',
|
||||
request={'project_id': project_id, 'topic_id': topic_id, 'comment_id': comment_id},
|
||||
response={comment_response})
|
||||
bcf_db.debug(
|
||||
endpoint="comment_delete",
|
||||
request={"project_id": project_id, "topic_id": topic_id, "comment_id": comment_id},
|
||||
response={comment_response},
|
||||
)
|
||||
return comment_response
|
||||
|
||||
|
||||
@@ -284,113 +329,160 @@ def comment_delete(project_id: UUID, topic_id: UUID, comment_id: UUID,
|
||||
|
||||
|
||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints", tags=["viewpoints_get"])
|
||||
def viewpoints_get(project_id: UUID, topic_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> List[ViewpointGET]:
|
||||
def viewpoints_get(
|
||||
project_id: UUID, topic_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||
) -> List[ViewpointGET]:
|
||||
viewpoints_response = bcf_db.get_viewpoints(project_id, topic_id, current_user)
|
||||
bcf_db.debug(endpoint='viewpoints_get',
|
||||
request={'project_id': project_id, 'topic_id': topic_id},
|
||||
response={count: value.dict() for count, value in enumerate(viewpoints_response)})
|
||||
bcf_db.debug(
|
||||
endpoint="viewpoints_get",
|
||||
request={"project_id": project_id, "topic_id": topic_id},
|
||||
response={count: value.dict() for count, value in enumerate(viewpoints_response)},
|
||||
)
|
||||
return viewpoints_response
|
||||
|
||||
|
||||
# request body viewpoint = viewpointPOST
|
||||
@router.post("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints", tags=["viewpoint_post"], status_code=201)
|
||||
def viewpoint_post(project_id: UUID, topic_id: UUID, viewpoint: ViewpointPOST,
|
||||
current_user: User = Depends(get_current_active_user)) -> ViewpointGET:
|
||||
def viewpoint_post(
|
||||
project_id: UUID, topic_id: UUID, viewpoint: ViewpointPOST, current_user: User = Depends(get_current_active_user)
|
||||
) -> ViewpointGET:
|
||||
viewpoint_response = bcf_db.post_viewpoint(project_id, topic_id, viewpoint, current_user)
|
||||
bcf_db.debug(endpoint='viewpoint_post',
|
||||
request={'project_id': project_id, 'topic_id': topic_id, 'viewpoint': viewpoint.dict()},
|
||||
response=viewpoint_response.dict())
|
||||
bcf_db.debug(
|
||||
endpoint="viewpoint_post",
|
||||
request={"project_id": project_id, "topic_id": topic_id, "viewpoint": viewpoint.dict()},
|
||||
response=viewpoint_response.dict(),
|
||||
)
|
||||
return viewpoint_response
|
||||
|
||||
|
||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}", tags=["viewpoint_get"])
|
||||
def viewpoint_get(project_id: UUID, topic_id: UUID, viewpoint_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> ViewpointGET:
|
||||
def viewpoint_get(
|
||||
project_id: UUID, topic_id: UUID, viewpoint_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||
) -> ViewpointGET:
|
||||
viewpoint_response = bcf_db.get_viewpoint(project_id, topic_id, viewpoint_id, current_user)
|
||||
bcf_db.debug(endpoint='viewpoint_get',
|
||||
request={'project_id': project_id, 'topic_id': topic_id, 'viewpoint_id': viewpoint_id},
|
||||
response=viewpoint_response.dict())
|
||||
bcf_db.debug(
|
||||
endpoint="viewpoint_get",
|
||||
request={"project_id": project_id, "topic_id": topic_id, "viewpoint_id": viewpoint_id},
|
||||
response=viewpoint_response.dict(),
|
||||
)
|
||||
return viewpoint_response
|
||||
|
||||
|
||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/snapshot",
|
||||
tags=["viewpoint_snapshot_get"])
|
||||
async def viewpoint_snapshot_get(project_id: UUID, topic_id: UUID, viewpoint_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> FileResponse:
|
||||
@router.get(
|
||||
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/snapshot",
|
||||
tags=["viewpoint_snapshot_get"],
|
||||
)
|
||||
async def viewpoint_snapshot_get(
|
||||
project_id: UUID, topic_id: UUID, viewpoint_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||
) -> FileResponse:
|
||||
viewpoint_snapshot_response = bcf_db.get_viewpoint_snapshot(project_id, topic_id, viewpoint_id, current_user)
|
||||
bcf_db.debug(endpoint='viewpoint_snapshot_get',
|
||||
request={'project_id': project_id, 'topic_id': topic_id, 'viewpoint_id': viewpoint_id},
|
||||
response=viewpoint_snapshot_response)
|
||||
snapshot_name = 'snapshot_' + str(viewpoint_id)
|
||||
file_ending = '.' + viewpoint_snapshot_response.split('/', 2)[1]
|
||||
snapshot_path = 'data/snapshots/' + snapshot_name + file_ending
|
||||
bcf_db.debug(
|
||||
endpoint="viewpoint_snapshot_get",
|
||||
request={"project_id": project_id, "topic_id": topic_id, "viewpoint_id": viewpoint_id},
|
||||
response=viewpoint_snapshot_response,
|
||||
)
|
||||
snapshot_name = "snapshot_" + str(viewpoint_id)
|
||||
file_ending = "." + viewpoint_snapshot_response.split("/", 2)[1]
|
||||
snapshot_path = "data/snapshots/" + snapshot_name + file_ending
|
||||
snapshot_type = viewpoint_snapshot_response
|
||||
return FileResponse(path=snapshot_path,
|
||||
media_type=snapshot_type)
|
||||
return FileResponse(path=snapshot_path, media_type=snapshot_type)
|
||||
|
||||
|
||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/bitmaps/{bitmap_id}",
|
||||
tags=["viewpoint_bitmap_get"])
|
||||
async def viewpoint_bitmap_get(project_id: UUID, topic_id: UUID, viewpoint_id: UUID, bitmap_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> FileResponse:
|
||||
@router.get(
|
||||
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/bitmaps/{bitmap_id}",
|
||||
tags=["viewpoint_bitmap_get"],
|
||||
)
|
||||
async def viewpoint_bitmap_get(
|
||||
project_id: UUID,
|
||||
topic_id: UUID,
|
||||
viewpoint_id: UUID,
|
||||
bitmap_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user),
|
||||
) -> FileResponse:
|
||||
viewpoint_bitmap_response = bcf_db.get_viewpoint_bitmap(project_id, topic_id, viewpoint_id, bitmap_id, current_user)
|
||||
bcf_db.debug(endpoint='viewpoint_bitmap_get',
|
||||
request={'project_id': project_id, 'topic_id': topic_id,
|
||||
'viewpoint_id': viewpoint_id, 'bitmap_id': bitmap_id},
|
||||
response=viewpoint_bitmap_response.dict())
|
||||
bitmap_name = 'bitmap_' + str(viewpoint_id)
|
||||
file_ending = '.' + viewpoint_bitmap_response['bitmap_type'].split('/', 2)[1]
|
||||
bitmap_path = 'data/bitmaps/' + bitmap_name + file_ending
|
||||
bitmap_type = viewpoint_bitmap_response['bitmap_type']
|
||||
return FileResponse(path=bitmap_path,
|
||||
media_type=bitmap_type)
|
||||
bcf_db.debug(
|
||||
endpoint="viewpoint_bitmap_get",
|
||||
request={"project_id": project_id, "topic_id": topic_id, "viewpoint_id": viewpoint_id, "bitmap_id": bitmap_id},
|
||||
response=viewpoint_bitmap_response.dict(),
|
||||
)
|
||||
bitmap_name = "bitmap_" + str(viewpoint_id)
|
||||
file_ending = "." + viewpoint_bitmap_response["bitmap_type"].split("/", 2)[1]
|
||||
bitmap_path = "data/bitmaps/" + bitmap_name + file_ending
|
||||
bitmap_type = viewpoint_bitmap_response["bitmap_type"]
|
||||
return FileResponse(path=bitmap_path, media_type=bitmap_type)
|
||||
|
||||
|
||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/coloring",
|
||||
tags=["viewpoint_colored_components_get"])
|
||||
def viewpoint_colored_components_get(project_id: UUID, topic_id: UUID, viewpoint_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> ColoringGET:
|
||||
viewpoint_colored_components_response = bcf_db.get_viewpoint_colored_components(project_id, topic_id, viewpoint_id, current_user)
|
||||
bcf_db.debug(endpoint='viewpoint_colored_components_get',
|
||||
request={'project_id': project_id, 'topic_id': topic_id, 'viewpoint_id': viewpoint_id},
|
||||
response=viewpoint_colored_components_response.dict())
|
||||
@router.get(
|
||||
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/coloring",
|
||||
tags=["viewpoint_colored_components_get"],
|
||||
)
|
||||
def viewpoint_colored_components_get(
|
||||
project_id: UUID, topic_id: UUID, viewpoint_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||
) -> ColoringGET:
|
||||
viewpoint_colored_components_response = bcf_db.get_viewpoint_colored_components(
|
||||
project_id, topic_id, viewpoint_id, current_user
|
||||
)
|
||||
bcf_db.debug(
|
||||
endpoint="viewpoint_colored_components_get",
|
||||
request={"project_id": project_id, "topic_id": topic_id, "viewpoint_id": viewpoint_id},
|
||||
response=viewpoint_colored_components_response.dict(),
|
||||
)
|
||||
return viewpoint_colored_components_response
|
||||
|
||||
|
||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/selection",
|
||||
tags=["viewpoint_selected_components_get"])
|
||||
def viewpoint_selected_components_get(project_id: UUID, topic_id: UUID, viewpoint_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> SelectionGET:
|
||||
viewpoint_selected_components_response = bcf_db.get_viewpoint_selected_components(project_id, topic_id, viewpoint_id, current_user)
|
||||
bcf_db.debug(endpoint='viewpoint_selected_components_get',
|
||||
request={'project_id': project_id, 'topic_id': topic_id, 'viewpoint_id': viewpoint_id},
|
||||
response=viewpoint_selected_components_response.dict())
|
||||
@router.get(
|
||||
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/selection",
|
||||
tags=["viewpoint_selected_components_get"],
|
||||
)
|
||||
def viewpoint_selected_components_get(
|
||||
project_id: UUID, topic_id: UUID, viewpoint_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||
) -> SelectionGET:
|
||||
viewpoint_selected_components_response = bcf_db.get_viewpoint_selected_components(
|
||||
project_id, topic_id, viewpoint_id, current_user
|
||||
)
|
||||
bcf_db.debug(
|
||||
endpoint="viewpoint_selected_components_get",
|
||||
request={"project_id": project_id, "topic_id": topic_id, "viewpoint_id": viewpoint_id},
|
||||
response=viewpoint_selected_components_response.dict(),
|
||||
)
|
||||
return viewpoint_selected_components_response
|
||||
|
||||
|
||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/visibility",
|
||||
tags=["viewpoint_components_visibility_get"])
|
||||
def viewpoint_components_visibility_get(project_id: UUID, topic_id: UUID, viewpoint_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> VisibilityGET:
|
||||
viewpoint_components_visibility_response = bcf_db.get_viewpoint_components_visibility(project_id, topic_id, viewpoint_id, current_user)
|
||||
bcf_db.debug(endpoint='viewpoint_components_visibility_get',
|
||||
request={'project_id': project_id, 'topic_id': topic_id, 'viewpoint_id': viewpoint_id},
|
||||
response=viewpoint_components_visibility_response.dict())
|
||||
@router.get(
|
||||
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/visibility",
|
||||
tags=["viewpoint_components_visibility_get"],
|
||||
)
|
||||
def viewpoint_components_visibility_get(
|
||||
project_id: UUID, topic_id: UUID, viewpoint_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||
) -> VisibilityGET:
|
||||
viewpoint_components_visibility_response = bcf_db.get_viewpoint_components_visibility(
|
||||
project_id, topic_id, viewpoint_id, current_user
|
||||
)
|
||||
bcf_db.debug(
|
||||
endpoint="viewpoint_components_visibility_get",
|
||||
request={"project_id": project_id, "topic_id": topic_id, "viewpoint_id": viewpoint_id},
|
||||
response=viewpoint_components_visibility_response.dict(),
|
||||
)
|
||||
return viewpoint_components_visibility_response
|
||||
|
||||
|
||||
# Implemented
|
||||
@router.delete("/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}",
|
||||
tags=["viewpoint_delete"], status_code=200)
|
||||
def viewpoint_delete(project_id: UUID, topic_id: UUID, viewpoint_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> int:
|
||||
@router.delete(
|
||||
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}",
|
||||
tags=["viewpoint_delete"],
|
||||
status_code=200,
|
||||
)
|
||||
def viewpoint_delete(
|
||||
project_id: UUID, topic_id: UUID, viewpoint_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||
) -> int:
|
||||
viewpoint_response = bcf_db.delete_viewpoint(project_id, topic_id, viewpoint_id, current_user)
|
||||
if viewpoint_response is None:
|
||||
raise HTTPException(status_code=404, detail="Item not found.")
|
||||
bcf_db.debug(endpoint='viewpoint_delete',
|
||||
request={'project_id': project_id, 'topic_id': topic_id, 'viewpoint_id': viewpoint_id},
|
||||
response={viewpoint_response})
|
||||
bcf_db.debug(
|
||||
endpoint="viewpoint_delete",
|
||||
request={"project_id": project_id, "topic_id": topic_id, "viewpoint_id": viewpoint_id},
|
||||
response={viewpoint_response},
|
||||
)
|
||||
return viewpoint_response
|
||||
|
||||
|
||||
@@ -401,24 +493,38 @@ def viewpoint_delete(project_id: UUID, topic_id: UUID, viewpoint_id: UUID,
|
||||
|
||||
|
||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/related_topics", tags=["related_topics_get"])
|
||||
def related_topics_get(project_id: UUID, topic_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> List[RelatedTopicGET]:
|
||||
def related_topics_get(
|
||||
project_id: UUID, topic_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||
) -> List[RelatedTopicGET]:
|
||||
related_topics_response = bcf_db.get_related_topics(project_id, topic_id, current_user)
|
||||
bcf_db.debug(endpoint='related_topics_get',
|
||||
request={'project_id': project_id, 'topic_id': topic_id},
|
||||
response={count: value.dict() for count, value in enumerate(related_topics_response)})
|
||||
bcf_db.debug(
|
||||
endpoint="related_topics_get",
|
||||
request={"project_id": project_id, "topic_id": topic_id},
|
||||
response={count: value.dict() for count, value in enumerate(related_topics_response)},
|
||||
)
|
||||
return related_topics_response
|
||||
|
||||
|
||||
# request body related_topic = RelatedTopicPUT
|
||||
@router.put("/bcf/3.0/projects/{project_id}/topics/{topic_id}/related_topics", tags=["related_topics_put"], status_code=200)
|
||||
def related_topics_put(project_id: UUID, topic_id: UUID, related_topics: List[RelatedTopicPUT],
|
||||
current_user: User = Depends(get_current_active_user)) -> List[RelatedTopicGET]:
|
||||
@router.put(
|
||||
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/related_topics", tags=["related_topics_put"], status_code=200
|
||||
)
|
||||
def related_topics_put(
|
||||
project_id: UUID,
|
||||
topic_id: UUID,
|
||||
related_topics: List[RelatedTopicPUT],
|
||||
current_user: User = Depends(get_current_active_user),
|
||||
) -> List[RelatedTopicGET]:
|
||||
related_topics_response = bcf_db.put_related_topics(project_id, topic_id, related_topics, current_user)
|
||||
bcf_db.debug(endpoint='related_topics_put',
|
||||
request={'project_id': project_id, 'topic_id': topic_id,
|
||||
'related_topics': {count: value.dict() for count, value in enumerate(related_topics)}},
|
||||
response={count: value.dict() for count, value in enumerate(related_topics_response)})
|
||||
bcf_db.debug(
|
||||
endpoint="related_topics_put",
|
||||
request={
|
||||
"project_id": project_id,
|
||||
"topic_id": topic_id,
|
||||
"related_topics": {count: value.dict() for count, value in enumerate(related_topics)},
|
||||
},
|
||||
response={count: value.dict() for count, value in enumerate(related_topics_response)},
|
||||
)
|
||||
return related_topics_response
|
||||
|
||||
|
||||
@@ -428,51 +534,70 @@ def related_topics_put(project_id: UUID, topic_id: UUID, related_topics: List[Re
|
||||
# Document references <- from topic
|
||||
|
||||
|
||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/document_references",
|
||||
tags=["topic_document_references_get"])
|
||||
def topic_document_references_get(project_id: UUID, topic_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> List[DocumentReferenceGET]:
|
||||
@router.get(
|
||||
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/document_references", tags=["topic_document_references_get"]
|
||||
)
|
||||
def topic_document_references_get(
|
||||
project_id: UUID, topic_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||
) -> List[DocumentReferenceGET]:
|
||||
topic_document_references_response = bcf_db.get_topic_document_references(project_id, topic_id, current_user)
|
||||
bcf_db.debug(endpoint='topic_document_references_get',
|
||||
request={'project_id': project_id, 'topic_id': topic_id},
|
||||
response={count: value.dict() for count, value in enumerate(topic_document_references_response)})
|
||||
bcf_db.debug(
|
||||
endpoint="topic_document_references_get",
|
||||
request={"project_id": project_id, "topic_id": topic_id},
|
||||
response={count: value.dict() for count, value in enumerate(topic_document_references_response)},
|
||||
)
|
||||
return topic_document_references_response
|
||||
|
||||
|
||||
# request body document_reference = DocumentReferencePOST
|
||||
@router.post("/bcf/3.0/projects/{project_id}/topics/{topic_id}/document_references",
|
||||
tags=["topic_document_references_post"],
|
||||
status_code=201)
|
||||
def topic_document_reference_post(project_id: UUID, topic_id: UUID, document_reference: DocumentReferencePOST,
|
||||
current_user: User = Depends(get_current_active_user)) -> DocumentReferenceGET:
|
||||
topic_document_references_response = bcf_db.post_topic_document_references(project_id,
|
||||
topic_id,
|
||||
document_reference,
|
||||
current_user)
|
||||
bcf_db.debug(endpoint='topic_document_references_post',
|
||||
request={'project_id': project_id, 'topic_id': topic_id, 'document_reference': document_reference},
|
||||
response={count: value.dict() for count, value in enumerate(topic_document_references_response)})
|
||||
@router.post(
|
||||
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/document_references",
|
||||
tags=["topic_document_references_post"],
|
||||
status_code=201,
|
||||
)
|
||||
def topic_document_reference_post(
|
||||
project_id: UUID,
|
||||
topic_id: UUID,
|
||||
document_reference: DocumentReferencePOST,
|
||||
current_user: User = Depends(get_current_active_user),
|
||||
) -> DocumentReferenceGET:
|
||||
topic_document_references_response = bcf_db.post_topic_document_references(
|
||||
project_id, topic_id, document_reference, current_user
|
||||
)
|
||||
bcf_db.debug(
|
||||
endpoint="topic_document_references_post",
|
||||
request={"project_id": project_id, "topic_id": topic_id, "document_reference": document_reference},
|
||||
response={count: value.dict() for count, value in enumerate(topic_document_references_response)},
|
||||
)
|
||||
return topic_document_references_response
|
||||
|
||||
|
||||
# request body document_reference = DocumentReferencePUT
|
||||
@router.put("/bcf/3.0/projects/{project_id}/topics/{topic_id}/document_references/{reference_id}",
|
||||
tags=["topic_document_references_put"],
|
||||
status_code=200)
|
||||
def topic_document_references_put(project_id: UUID, topic_id: UUID, reference_id: UUID,
|
||||
document_reference: DocumentReferencePUT,
|
||||
current_user: User = Depends(get_current_active_user)) -> DocumentReferenceGET:
|
||||
topic_document_references_response = bcf_db.put_topic_document_references(project_id,
|
||||
topic_id,
|
||||
reference_id,
|
||||
document_reference,
|
||||
current_user)
|
||||
bcf_db.debug(endpoint='topic_document_references_put',
|
||||
request={'project_id': project_id,
|
||||
'topic_id': topic_id,
|
||||
'reference_id': reference_id,
|
||||
'document_reference': document_reference.dict()},
|
||||
response={count: value.dict() for count, value in enumerate(topic_document_references_response)})
|
||||
@router.put(
|
||||
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/document_references/{reference_id}",
|
||||
tags=["topic_document_references_put"],
|
||||
status_code=200,
|
||||
)
|
||||
def topic_document_references_put(
|
||||
project_id: UUID,
|
||||
topic_id: UUID,
|
||||
reference_id: UUID,
|
||||
document_reference: DocumentReferencePUT,
|
||||
current_user: User = Depends(get_current_active_user),
|
||||
) -> DocumentReferenceGET:
|
||||
topic_document_references_response = bcf_db.put_topic_document_references(
|
||||
project_id, topic_id, reference_id, document_reference, current_user
|
||||
)
|
||||
bcf_db.debug(
|
||||
endpoint="topic_document_references_put",
|
||||
request={
|
||||
"project_id": project_id,
|
||||
"topic_id": topic_id,
|
||||
"reference_id": reference_id,
|
||||
"document_reference": document_reference.dict(),
|
||||
},
|
||||
response={count: value.dict() for count, value in enumerate(topic_document_references_response)},
|
||||
)
|
||||
return topic_document_references_response
|
||||
|
||||
|
||||
@@ -485,30 +610,34 @@ def topic_document_references_put(project_id: UUID, topic_id: UUID, reference_id
|
||||
@router.get("/bcf/3.0/projects/{project_id}/documents", tags=["documents_get"])
|
||||
def documents_get(project_id: UUID, current_user: User = Depends(get_current_active_user)) -> List[DocumentGET]:
|
||||
documents_response = bcf_db.get_documents(project_id, current_user)
|
||||
bcf_db.debug(endpoint='documents_get',
|
||||
request={'project_id': project_id},
|
||||
response={count: value.dict() for count, value in enumerate(documents_response)})
|
||||
bcf_db.debug(
|
||||
endpoint="documents_get",
|
||||
request={"project_id": project_id},
|
||||
response={count: value.dict() for count, value in enumerate(documents_response)},
|
||||
)
|
||||
return documents_response
|
||||
|
||||
|
||||
# request body file = UploadFile
|
||||
@router.post("/bcf/3.0/projects/{project_id}/documents", tags=["document_post"], status_code=201)
|
||||
async def document_post(project_id: UUID, file: UploadFile,
|
||||
current_user: User = Depends(get_current_active_user)) -> DocumentGET:
|
||||
async def document_post(
|
||||
project_id: UUID, file: UploadFile, current_user: User = Depends(get_current_active_user)
|
||||
) -> DocumentGET:
|
||||
document_response = bcf_db.post_document(project_id, file, current_user)
|
||||
bcf_db.debug(endpoint='document_post',
|
||||
request={'project_id': project_id},
|
||||
response=document_response.dict())
|
||||
bcf_db.debug(endpoint="document_post", request={"project_id": project_id}, response=document_response.dict())
|
||||
return document_response
|
||||
|
||||
|
||||
@router.get("/bcf/3.0/projects/{project_id}/documents/{document_id}", tags=["document_get"])
|
||||
def document_get(project_id: UUID, document_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> DocumentGET:
|
||||
def document_get(
|
||||
project_id: UUID, document_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||
) -> DocumentGET:
|
||||
document_response = bcf_db.get_document(project_id, document_id, current_user)
|
||||
bcf_db.debug(endpoint='document_get',
|
||||
request={'project_id': project_id, 'document_id': document_id},
|
||||
response=document_response.dict())
|
||||
bcf_db.debug(
|
||||
endpoint="document_get",
|
||||
request={"project_id": project_id, "document_id": document_id},
|
||||
response=document_response.dict(),
|
||||
)
|
||||
return document_response
|
||||
|
||||
|
||||
@@ -520,22 +649,26 @@ def document_get(project_id: UUID, document_id: UUID,
|
||||
|
||||
# ...
|
||||
@router.get("/bcf/3.0/projects/{project_id}/topics/events", tags=["topics_events_get"])
|
||||
def topics_events_get(project_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> List[TopicEventGET]:
|
||||
def topics_events_get(project_id: UUID, current_user: User = Depends(get_current_active_user)) -> List[TopicEventGET]:
|
||||
topic_events_response = bcf_db.get_topics_events(project_id, current_user)
|
||||
bcf_db.debug(endpoint='topics_events_get',
|
||||
request={'project_id': project_id},
|
||||
response={count: value.dict() for count, value in enumerate(topic_events_response)})
|
||||
bcf_db.debug(
|
||||
endpoint="topics_events_get",
|
||||
request={"project_id": project_id},
|
||||
response={count: value.dict() for count, value in enumerate(topic_events_response)},
|
||||
)
|
||||
return topic_events_response
|
||||
|
||||
|
||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/events", tags=["topic_events_get"])
|
||||
def topic_events_get(project_id: UUID, topic_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> List[TopicEventGET]:
|
||||
def topic_events_get(
|
||||
project_id: UUID, topic_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||
) -> List[TopicEventGET]:
|
||||
topic_events_response = bcf_db.get_topic_events(project_id, topic_id, current_user)
|
||||
bcf_db.debug(endpoint='topic_events_get',
|
||||
request={'project_id': project_id, 'topic_id': topic_id},
|
||||
response={count: value.dict() for count, value in enumerate(topic_events_response)})
|
||||
bcf_db.debug(
|
||||
endpoint="topic_events_get",
|
||||
request={"project_id": project_id, "topic_id": topic_id},
|
||||
response={count: value.dict() for count, value in enumerate(topic_events_response)},
|
||||
)
|
||||
return topic_events_response
|
||||
|
||||
|
||||
@@ -546,21 +679,28 @@ def topic_events_get(project_id: UUID, topic_id: UUID,
|
||||
|
||||
|
||||
@router.get("/bcf/3.0/projects/{project_id}/topics/comments/events", tags=["comments_events_get"])
|
||||
def comments_events_get(project_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> List[CommentEventGET]:
|
||||
def comments_events_get(
|
||||
project_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||
) -> List[CommentEventGET]:
|
||||
comments_events_response = bcf_db.get_comments_events(project_id, current_user)
|
||||
bcf_db.debug(endpoint='comments_events_get',
|
||||
request={'project_id': project_id},
|
||||
response={count: value.dict() for count, value in enumerate(comments_events_response)})
|
||||
bcf_db.debug(
|
||||
endpoint="comments_events_get",
|
||||
request={"project_id": project_id},
|
||||
response={count: value.dict() for count, value in enumerate(comments_events_response)},
|
||||
)
|
||||
return comments_events_response
|
||||
|
||||
|
||||
@router.get("/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments/{comment_id}/events",
|
||||
tags=["comment_events_get"])
|
||||
def comment_events_get(project_id: UUID, topic_id: UUID, comment_id: UUID,
|
||||
current_user: User = Depends(get_current_active_user)) -> List[CommentEventGET]:
|
||||
@router.get(
|
||||
"/bcf/3.0/projects/{project_id}/topics/{topic_id}/comments/{comment_id}/events", tags=["comment_events_get"]
|
||||
)
|
||||
def comment_events_get(
|
||||
project_id: UUID, topic_id: UUID, comment_id: UUID, current_user: User = Depends(get_current_active_user)
|
||||
) -> List[CommentEventGET]:
|
||||
comment_events_response = bcf_db.get_comment_events(project_id, topic_id, comment_id, current_user)
|
||||
bcf_db.debug(endpoint='comment_events_get',
|
||||
request={'project_id': project_id, 'topic_id': topic_id, 'comment_id': comment_id},
|
||||
response={count: value.dict() for count, value in enumerate(comment_events_response)})
|
||||
bcf_db.debug(
|
||||
endpoint="comment_events_get",
|
||||
request={"project_id": project_id, "topic_id": topic_id, "comment_id": comment_id},
|
||||
response={count: value.dict() for count, value in enumerate(comment_events_response)},
|
||||
)
|
||||
return comment_events_response
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
import collections
|
||||
import os
|
||||
import shutil
|
||||
@@ -6,7 +5,7 @@ import traceback
|
||||
import sys
|
||||
|
||||
from fastapi import HTTPException, status, APIRouter, Request, Depends
|
||||
from fastapi import UploadFile, Form
|
||||
from fastapi import UploadFile, Form
|
||||
from fastapi.responses import FileResponse, HTMLResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
@@ -87,12 +86,15 @@ templates = Jinja2Templates(directory="templates")
|
||||
|
||||
|
||||
@router.post("/documents/1.0/upload-documents", tags=[""])
|
||||
def upload_documents_post(upload_documents: UploadDocuments,
|
||||
current_user: User = Depends(get_current_active_user)) -> DocumentUploadSessionInitialization:
|
||||
def upload_documents_post(
|
||||
upload_documents: UploadDocuments, current_user: User = Depends(get_current_active_user)
|
||||
) -> DocumentUploadSessionInitialization:
|
||||
post_upload_documents_response = doc_db.post_upload_documents(upload_documents, current_user)
|
||||
doc_db.debug(endpoint='upload_documents_post',
|
||||
request={'upload_documents': upload_documents},
|
||||
response=post_upload_documents_response.dict())
|
||||
doc_db.debug(
|
||||
endpoint="upload_documents_post",
|
||||
request={"upload_documents": upload_documents},
|
||||
response=post_upload_documents_response.dict(),
|
||||
)
|
||||
return post_upload_documents_response
|
||||
|
||||
|
||||
@@ -101,20 +103,23 @@ def upload_documents_post(upload_documents: UploadDocuments,
|
||||
def upload_documents_get(request: Request, upload_session: UUID):
|
||||
|
||||
data_for_upload_documents = doc_db.get_data_for_upload_documents(upload_session)
|
||||
print('Data for site: ', data_for_upload_documents)
|
||||
print("Data for site: ", data_for_upload_documents)
|
||||
|
||||
return templates.TemplateResponse(
|
||||
'upload_files.html',
|
||||
{'request': request,
|
||||
'upload_session': upload_session,
|
||||
'username': data_for_upload_documents.current_user.username,
|
||||
'email': data_for_upload_documents.current_user.email,
|
||||
'full_name': data_for_upload_documents.current_user.full_name,
|
||||
'server_context': data_for_upload_documents.server_context,
|
||||
'callback_url': data_for_upload_documents.callback.url,
|
||||
'callback_expires_in': data_for_upload_documents.callback.expires_in,
|
||||
'documents': data_for_upload_documents.documents,
|
||||
'projects': data_for_upload_documents.projects})
|
||||
"upload_files.html",
|
||||
{
|
||||
"request": request,
|
||||
"upload_session": upload_session,
|
||||
"username": data_for_upload_documents.current_user.username,
|
||||
"email": data_for_upload_documents.current_user.email,
|
||||
"full_name": data_for_upload_documents.current_user.full_name,
|
||||
"server_context": data_for_upload_documents.server_context,
|
||||
"callback_url": data_for_upload_documents.callback.url,
|
||||
"callback_expires_in": data_for_upload_documents.callback.expires_in,
|
||||
"documents": data_for_upload_documents.documents,
|
||||
"projects": data_for_upload_documents.projects,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@router.post("/documents/1.0/save-metadata-for-documents", tags=[""])
|
||||
@@ -127,29 +132,29 @@ async def save_metadata_for_documents_post(request: Request) -> list:
|
||||
print(form_data_json)
|
||||
|
||||
documents = collections.defaultdict(dict)
|
||||
names = ('session_file_id', 'document', 'title', 'version_number', 'filename')
|
||||
names = ("session_file_id", "document", "title", "version_number", "filename")
|
||||
|
||||
for whole_form_key, value in form_data_json.items():
|
||||
if whole_form_key.startswith(names):
|
||||
start_form_key, document_id = whole_form_key.split("@", 1)
|
||||
print('New field: ', start_form_key, ' for document id: ', document_id)
|
||||
print("New field: ", start_form_key, " for document id: ", document_id)
|
||||
documents[document_id][start_form_key] = value
|
||||
|
||||
print("Documents: ")
|
||||
print(documents)
|
||||
|
||||
username = form_data_json['username']
|
||||
upload_session = form_data_json['upload_session']
|
||||
server_context = form_data_json['server_context']
|
||||
callback_url = form_data_json['callback_url']
|
||||
callback_expires_in = form_data_json['callback_expires_in']
|
||||
project = form_data_json['project']
|
||||
username = form_data_json["username"]
|
||||
upload_session = form_data_json["upload_session"]
|
||||
server_context = form_data_json["server_context"]
|
||||
callback_url = form_data_json["callback_url"]
|
||||
callback_expires_in = form_data_json["callback_expires_in"]
|
||||
project = form_data_json["project"]
|
||||
|
||||
documents_saved = list()
|
||||
|
||||
for key in documents:
|
||||
try:
|
||||
documents[key]['project'] = project
|
||||
documents[key]["project"] = project
|
||||
document = DocumentMetadata(**documents[key])
|
||||
save_metadata_response = doc_db.save_metadata_for_documents(document, upload_session, username)
|
||||
documents_saved.append(save_metadata_response)
|
||||
@@ -157,9 +162,11 @@ async def save_metadata_for_documents_post(request: Request) -> list:
|
||||
print(e)
|
||||
continue
|
||||
|
||||
doc_db.debug(endpoint='save_metadata_for_documents_post',
|
||||
request={'documents': documents},
|
||||
response={'response': documents_saved})
|
||||
doc_db.debug(
|
||||
endpoint="save_metadata_for_documents_post",
|
||||
request={"documents": documents},
|
||||
response={"response": documents_saved},
|
||||
)
|
||||
|
||||
return documents_saved
|
||||
|
||||
@@ -167,22 +174,30 @@ async def save_metadata_for_documents_post(request: Request) -> list:
|
||||
# http://localhost:8080/cde-callback-example?upload_documents_url=
|
||||
# https%3A%2F%2Fcde.example.com%2Fupload-instructions%3Fupload_session%3Dee56b8f3-8f93-4819-976e-46a45a5a996f
|
||||
|
||||
|
||||
@router.post("/documents/1.0/upload-instructions", tags=[""])
|
||||
def upload_instructions(session_id: str, server_context: str, upload_files: UploadFileDetails,
|
||||
current_user: User = Depends(get_current_active_user)) -> DocumentsToUpload:
|
||||
def upload_instructions(
|
||||
session_id: str,
|
||||
server_context: str,
|
||||
upload_files: UploadFileDetails,
|
||||
current_user: User = Depends(get_current_active_user),
|
||||
) -> DocumentsToUpload:
|
||||
documents_to_upload_model = DocumentsToUpload()
|
||||
documents_to_upload_model.server_context = server_context
|
||||
documents_to_upload_model.documents_to_upload = list()
|
||||
for upload_file in upload_files.files:
|
||||
get_upload_instructions_response = doc_db.get_upload_instructions(session_id, server_context, upload_file, current_user)
|
||||
doc_db.debug(endpoint='upload_instructions',
|
||||
request={'session_id': session_id,
|
||||
'server_context': server_context,
|
||||
'document': upload_file},
|
||||
response=get_upload_instructions_response.dict())
|
||||
get_upload_instructions_response = doc_db.get_upload_instructions(
|
||||
session_id, server_context, upload_file, current_user
|
||||
)
|
||||
doc_db.debug(
|
||||
endpoint="upload_instructions",
|
||||
request={"session_id": session_id, "server_context": server_context, "document": upload_file},
|
||||
response=get_upload_instructions_response.dict(),
|
||||
)
|
||||
documents_to_upload_model.documents_to_upload.append(get_upload_instructions_response)
|
||||
return documents_to_upload_model
|
||||
|
||||
|
||||
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
|
||||
# summary: 'Upload a single file part'
|
||||
#
|
||||
@@ -206,8 +221,7 @@ def upload_instructions(session_id: str, server_context: str, upload_files: Uplo
|
||||
|
||||
|
||||
@router.post("/documents/1.0/upload-part/{part_id}", tags=[""])
|
||||
async def upload_part(part_id: str, request: Request,
|
||||
current_user: User = Depends(get_current_active_user)):
|
||||
async def upload_part(part_id: str, request: Request, current_user: User = Depends(get_current_active_user)):
|
||||
|
||||
# file_name = doc_db.safe_path(part_id)
|
||||
file_name = part_id
|
||||
@@ -222,33 +236,31 @@ async def upload_part(part_id: str, request: Request,
|
||||
|
||||
# try to receive the uploaded part
|
||||
try:
|
||||
print('File contents: ', request_body)
|
||||
print("File contents: ", request_body)
|
||||
|
||||
# use document_id instead as dir_name
|
||||
# dir_name = doc_db.safe_path(document.document_id)
|
||||
dir_name = document.document_id
|
||||
|
||||
path = './data/document_parts/' + dir_name + '/'
|
||||
path = "./data/document_parts/" + dir_name + "/"
|
||||
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
|
||||
with open(path + file_name, 'wb') as f:
|
||||
with open(path + file_name, "wb") as f:
|
||||
f.write(request_body)
|
||||
|
||||
except Exception:
|
||||
print('Error uploading file')
|
||||
print("Error uploading file")
|
||||
print(traceback.format_exc())
|
||||
print('Error uploading file')
|
||||
print("Error uploading file")
|
||||
print(sys.exc_info()[2])
|
||||
|
||||
finally:
|
||||
# We will write to the database, information about part successfully uploaded.
|
||||
doc_db.mark_part_as_uploaded(part_id, current_user)
|
||||
|
||||
doc_db.debug(endpoint='upload-part',
|
||||
request={'part_id': part_id},
|
||||
response={'uploaded': True})
|
||||
doc_db.debug(endpoint="upload-part", request={"part_id": part_id}, response={"uploaded": True})
|
||||
|
||||
return {"message": f"Successfully uploaded part {file_name}"}
|
||||
|
||||
@@ -269,9 +281,11 @@ async def upload_part(part_id: str, request: Request,
|
||||
# /server-provided-path-document-upload-cancellation
|
||||
# description: This operation should be called to cancel the upload
|
||||
|
||||
|
||||
@router.post("/documents/1.0/upload-completion", tags=[""])
|
||||
def upload_completion(upload_session: str,
|
||||
current_user: User = Depends(get_current_active_user)) -> Union[DocumentVersion, bool]:
|
||||
def upload_completion(
|
||||
upload_session: str, current_user: User = Depends(get_current_active_user)
|
||||
) -> Union[DocumentVersion, bool]:
|
||||
|
||||
# check if all parts really are marked as uploaded in database
|
||||
# retrieve document_id, file_type, file_ending, and parts_id (in order)
|
||||
@@ -280,23 +294,23 @@ def upload_completion(upload_session: str,
|
||||
raise HTTPException(status_code=400, detail="All parts not uploaded.")
|
||||
|
||||
parts = doc_db.retrieve_uploaded_parts(upload_session, current_user)
|
||||
print('Number of parts: ' + str(len(parts)))
|
||||
print("Number of parts: " + str(len(parts)))
|
||||
document = doc_db.get_document_from_session(upload_session, current_user)
|
||||
|
||||
# check if all parts really are uploaded to document_id-dir
|
||||
document_name = doc_db.safe_path(document.document_id)
|
||||
|
||||
path = './data/document_parts/' + document_name + '/'
|
||||
path = "./data/document_parts/" + document_name + "/"
|
||||
|
||||
for part in parts:
|
||||
part = doc_db.safe_path(part)
|
||||
print('Checking for part ' + part + ' in dir ' + path)
|
||||
print("Checking for part " + part + " in dir " + path)
|
||||
|
||||
if not os.path.isfile(path + part):
|
||||
print(part + ' is not in dir ' + path)
|
||||
print(part + " is not in dir " + path)
|
||||
raise HTTPException(status_code=400, detail="All parts not in dir.")
|
||||
else:
|
||||
print(part + ' is in dir ' + path)
|
||||
print(part + " is in dir " + path)
|
||||
|
||||
# merge parts to a new temporary document
|
||||
temp_doc_path = path
|
||||
@@ -304,14 +318,14 @@ def upload_completion(upload_session: str,
|
||||
if not os.path.exists(temp_doc_path):
|
||||
os.makedirs(temp_doc_path)
|
||||
|
||||
new_doc_path = './data/documents/'
|
||||
new_doc_path = "./data/documents/"
|
||||
new_doc_path_name = new_doc_path + document.file_description.name
|
||||
|
||||
# Read parts and write to temp doc.
|
||||
with open(temp_doc_file_name, 'ab') as temp_doc:
|
||||
with open(temp_doc_file_name, "ab") as temp_doc:
|
||||
for part in parts:
|
||||
part = doc_db.safe_path(part)
|
||||
with open(temp_doc_path + part, 'rb') as part_doc:
|
||||
with open(temp_doc_path + part, "rb") as part_doc:
|
||||
temp_doc.write(part_doc.read())
|
||||
|
||||
# move document to new location in documents dir
|
||||
@@ -329,13 +343,12 @@ def upload_completion(upload_session: str,
|
||||
# get DocumentVersion
|
||||
document = doc_db.get_document_version(document.document_id, document.version_index, current_user)
|
||||
|
||||
doc_db.debug(endpoint='upload_completion',
|
||||
request={'upload_session': upload_session},
|
||||
response=document.dict())
|
||||
doc_db.debug(endpoint="upload_completion", request={"upload_session": upload_session}, response=document.dict())
|
||||
return document
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
|
||||
# summary: 'Cancel the upload of a single file'
|
||||
#
|
||||
@@ -355,14 +368,14 @@ def upload_cancellation(upload_session: str, current_user: User = Depends(get_cu
|
||||
|
||||
# clean temp dir
|
||||
document_name = doc_db.safe_path(document.document_id)
|
||||
path = './data/document_parts/' + document_name + '/'
|
||||
path = "./data/document_parts/" + document_name + "/"
|
||||
shutil.rmtree(path)
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
finally:
|
||||
print('Upload cancellation complete.')
|
||||
print("Upload cancellation complete.")
|
||||
|
||||
return
|
||||
|
||||
@@ -399,17 +412,17 @@ def upload_cancellation(upload_session: str, current_user: User = Depends(get_cu
|
||||
# that has been flagged to have a new version in the response.
|
||||
#
|
||||
|
||||
|
||||
@router.post("/documents/1.0/document-versions", tags=[""])
|
||||
def document_versions_post(document_ids: List[UUID],
|
||||
current_user: User = Depends(get_current_active_user)) -> List[DocumentVersion]:
|
||||
def document_versions_post(
|
||||
document_ids: List[UUID], current_user: User = Depends(get_current_active_user)
|
||||
) -> List[DocumentVersion]:
|
||||
|
||||
document_versions = list()
|
||||
for document_id in document_ids:
|
||||
document_versions.append(doc_db.get_document_version(document_id, 1, current_user))
|
||||
|
||||
doc_db.debug(endpoint='document_versions_post',
|
||||
request={document_ids},
|
||||
response={document_versions})
|
||||
doc_db.debug(endpoint="document_versions_post", request={document_ids}, response={document_versions})
|
||||
|
||||
return document_versions
|
||||
|
||||
@@ -460,12 +473,15 @@ def document_versions_post(document_ids: List[UUID],
|
||||
|
||||
|
||||
@router.post("/documents/1.0/select-documents", tags=[""])
|
||||
def select_documents_post(select_documents: SelectDocuments,
|
||||
current_user: User = Depends(get_current_active_user)) -> DocumentDiscoverySessionInitialization:
|
||||
def select_documents_post(
|
||||
select_documents: SelectDocuments, current_user: User = Depends(get_current_active_user)
|
||||
) -> DocumentDiscoverySessionInitialization:
|
||||
post_select_documents_response = doc_db.post_select_documents(select_documents, current_user)
|
||||
doc_db.debug(endpoint='select_documents_post',
|
||||
request={'select_documents': select_documents},
|
||||
response=post_select_documents_response.dict())
|
||||
doc_db.debug(
|
||||
endpoint="select_documents_post",
|
||||
request={"select_documents": select_documents},
|
||||
response=post_select_documents_response.dict(),
|
||||
)
|
||||
print("Returns ", post_select_documents_response)
|
||||
return post_select_documents_response
|
||||
|
||||
@@ -490,19 +506,22 @@ def select_documents_post(select_documents: SelectDocuments,
|
||||
|
||||
# documents/1.0/document-selection?selection_session=7cf3dd70-c880-4fb1-9897-f60472959533
|
||||
|
||||
|
||||
@router.get("/documents/1.0/document-selection", tags=[""], response_class=HTMLResponse)
|
||||
def selected_documents_get(request: Request,
|
||||
selection_session: UUID):
|
||||
def selected_documents_get(request: Request, selection_session: UUID):
|
||||
data_for_document_selection = doc_db.get_data_for_document_selection(selection_session)
|
||||
return templates.TemplateResponse(
|
||||
'select_files.html',
|
||||
{'request': request,
|
||||
'selection_session': selection_session,
|
||||
'current_user': data_for_document_selection.current_user,
|
||||
'server_context': data_for_document_selection.server_context,
|
||||
'callback_url': data_for_document_selection.callback.url,
|
||||
'callback_expires_in': data_for_document_selection.callback.expires_in,
|
||||
'projects': data_for_document_selection.projects})
|
||||
"select_files.html",
|
||||
{
|
||||
"request": request,
|
||||
"selection_session": selection_session,
|
||||
"current_user": data_for_document_selection.current_user,
|
||||
"server_context": data_for_document_selection.server_context,
|
||||
"callback_url": data_for_document_selection.callback.url,
|
||||
"callback_expires_in": data_for_document_selection.callback.expires_in,
|
||||
"projects": data_for_document_selection.projects,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@router.post("/documents/1.0/mark-documents-as-selected", tags=[""])
|
||||
@@ -516,45 +535,52 @@ async def mark_documents_as_selected_post(request: Request) -> DocumentsMarkedAs
|
||||
|
||||
documents = list()
|
||||
for key, value in form_data_json.items():
|
||||
if 'document_' in key:
|
||||
if "document_" in key:
|
||||
document_id = key.split("ocument_", 1)[1]
|
||||
documents.append(document_id)
|
||||
|
||||
print("Sends ", documents)
|
||||
|
||||
get_selected_response = doc_db.post_mark_documents_as_selected(documents, form_data_json['selection_session'])
|
||||
doc_db.debug(endpoint='mark_some_documents_as_selected_post',
|
||||
request={'documents': documents,
|
||||
'form_data_json[selection_session]': form_data_json['selection_session']},
|
||||
response=get_selected_response.dict())
|
||||
get_selected_response = doc_db.post_mark_documents_as_selected(documents, form_data_json["selection_session"])
|
||||
doc_db.debug(
|
||||
endpoint="mark_some_documents_as_selected_post",
|
||||
request={"documents": documents, "form_data_json[selection_session]": form_data_json["selection_session"]},
|
||||
response=get_selected_response.dict(),
|
||||
)
|
||||
|
||||
return get_selected_response
|
||||
|
||||
|
||||
@router.get("/documents/1.0/download-instructions", tags=[""])
|
||||
def download_instructions(session_id: UUID, server_context: str,
|
||||
current_user: User = Depends(get_current_active_user)) -> SelectedDocuments:
|
||||
def download_instructions(
|
||||
session_id: UUID, server_context: str, current_user: User = Depends(get_current_active_user)
|
||||
) -> SelectedDocuments:
|
||||
get_download_instructions_response = doc_db.get_download_instructions(session_id, server_context, current_user)
|
||||
doc_db.debug(endpoint='download_instructions',
|
||||
request={'session_id': session_id,
|
||||
'server_context': server_context},
|
||||
response=get_download_instructions_response.dict())
|
||||
doc_db.debug(
|
||||
endpoint="download_instructions",
|
||||
request={"session_id": session_id, "server_context": server_context},
|
||||
response=get_download_instructions_response.dict(),
|
||||
)
|
||||
return get_download_instructions_response
|
||||
|
||||
|
||||
# download links
|
||||
|
||||
|
||||
@router.get("/documents/1.0/document/{document_id}/version/{version_index}", tags=[""])
|
||||
def document_version(document_id: str, version_index: int,
|
||||
current_user: User = Depends(get_current_active_user)) -> DocumentVersion:
|
||||
def document_version(
|
||||
document_id: str, version_index: int, current_user: User = Depends(get_current_active_user)
|
||||
) -> DocumentVersion:
|
||||
# This endpoint returns the document version model itself.
|
||||
get_document_version = doc_db.get_document_version(document_id, version_index, current_user)
|
||||
doc_db.debug(endpoint='document_version',
|
||||
request={'document_id': document_id,
|
||||
'version_index': version_index},
|
||||
response=get_document_version.dict())
|
||||
doc_db.debug(
|
||||
endpoint="document_version",
|
||||
request={"document_id": document_id, "version_index": version_index},
|
||||
response=get_document_version.dict(),
|
||||
)
|
||||
return get_document_version
|
||||
|
||||
|
||||
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
|
||||
# summary: 'Get document metadata for a single document'
|
||||
#
|
||||
@@ -573,16 +599,21 @@ def document_version(document_id: str, version_index: int,
|
||||
|
||||
|
||||
@router.get("/documents/1.0/document/{document_id}/version/{version_index}/metadata", tags=[""])
|
||||
def document_version_metadata(document_id: str, version_index: int,
|
||||
current_user: User = Depends(get_current_active_user)) -> DocumentMetadataEntries:
|
||||
def document_version_metadata(
|
||||
document_id: str, version_index: int, current_user: User = Depends(get_current_active_user)
|
||||
) -> DocumentMetadataEntries:
|
||||
# The metadata for document versions is a list of key-value pairs
|
||||
get_document_version_metadata_result = doc_db.get_document_version_metadata(document_id, version_index, current_user)
|
||||
doc_db.debug(endpoint='document_version',
|
||||
request={'document_id': document_id,
|
||||
'version_index': version_index},
|
||||
response=get_document_version_metadata_result.dict())
|
||||
get_document_version_metadata_result = doc_db.get_document_version_metadata(
|
||||
document_id, version_index, current_user
|
||||
)
|
||||
doc_db.debug(
|
||||
endpoint="document_version",
|
||||
request={"document_id": document_id, "version_index": version_index},
|
||||
response=get_document_version_metadata_result.dict(),
|
||||
)
|
||||
return get_document_version_metadata_result
|
||||
|
||||
|
||||
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
|
||||
# summary: 'Download the document'
|
||||
#
|
||||
@@ -601,47 +632,48 @@ def document_version_metadata(document_id: str, version_index: int,
|
||||
|
||||
|
||||
@router.get("/documents/1.0/document/{document_id}/version/{version_index}/download", tags=[""])
|
||||
def document_version_download(document_id: str, version_index: int,
|
||||
current_user: User = Depends(get_current_active_user)) -> FileResponse:
|
||||
def document_version_download(
|
||||
document_id: str, version_index: int, current_user: User = Depends(get_current_active_user)
|
||||
) -> FileResponse:
|
||||
# The url to download the binary content of this document version.
|
||||
# May either directly return the result or redirect to a storage provider
|
||||
keep_characters = (' ', '.', '_', '-')
|
||||
keep_characters = (" ", ".", "_", "-")
|
||||
document_id = "".join(c for c in document_id if c.isalnum() or c in keep_characters).rstrip()
|
||||
file_location = './data/documents/' + document_id + '.ifc'
|
||||
return FileResponse(file_location,
|
||||
media_type='application/x-step',
|
||||
filename='6dbd4d52-14db-11ee-be56-0242ac120002.ifc')
|
||||
file_location = "./data/documents/" + document_id + ".ifc"
|
||||
return FileResponse(
|
||||
file_location, media_type="application/x-step", filename="6dbd4d52-14db-11ee-be56-0242ac120002.ifc"
|
||||
)
|
||||
|
||||
|
||||
@router.get("/documents/1.0/document/{document_id}/version/{version_index}/versions", tags=[""])
|
||||
def document_versions(document_id: str, version_index: int,
|
||||
current_user: User = Depends(get_current_active_user)) -> DocumentVersions:
|
||||
def document_versions(
|
||||
document_id: str, version_index: int, current_user: User = Depends(get_current_active_user)
|
||||
) -> DocumentVersions:
|
||||
# This url returns a list of all document versions for the parent document.
|
||||
# The client can use this URL to monitor for new document versions
|
||||
get_document_versions_result = doc_db.get_document_versions(document_id, current_user)
|
||||
doc_db.debug(endpoint='document_version',
|
||||
request={'document_id': document_id},
|
||||
response=get_document_versions_result.dict())
|
||||
doc_db.debug(
|
||||
endpoint="document_version", request={"document_id": document_id}, response=get_document_versions_result.dict()
|
||||
)
|
||||
return get_document_versions_result
|
||||
|
||||
|
||||
@router.get("/documents/1.0/document/{document_id}/version/{version_index}/details", tags=[""],
|
||||
response_class=HTMLResponse)
|
||||
def document_version_details(request: Request,
|
||||
document_id: str,
|
||||
version_index: int,
|
||||
current_user: User = Depends(get_current_active_user)):
|
||||
@router.get(
|
||||
"/documents/1.0/document/{document_id}/version/{version_index}/details", tags=[""], response_class=HTMLResponse
|
||||
)
|
||||
def document_version_details(
|
||||
request: Request, document_id: str, version_index: int, current_user: User = Depends(get_current_active_user)
|
||||
):
|
||||
# This url returns a list of all document versions for the parent document.
|
||||
# The client can use this URL to monitor for new document versions
|
||||
details = doc_db.get_document_version(document_id, version_index, current_user)
|
||||
doc_db.debug(endpoint='document_version',
|
||||
request={'document_id': document_id,
|
||||
'version_index': version_index},
|
||||
response=details.dict())
|
||||
return templates.TemplateResponse(
|
||||
'document_details.html',
|
||||
{'request': request,
|
||||
'details': details})
|
||||
doc_db.debug(
|
||||
endpoint="document_version",
|
||||
request={"document_id": document_id, "version_index": version_index},
|
||||
response=details.dict(),
|
||||
)
|
||||
return templates.TemplateResponse("document_details.html", {"request": request, "details": details})
|
||||
|
||||
|
||||
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
|
||||
# summary: 'Get the versions of a single document'
|
||||
@@ -699,7 +731,9 @@ def document_version_details(request: Request,
|
||||
|
||||
|
||||
@router.post("/documents/1.0/upload_file_to_project", tags=[""])
|
||||
async def upload_documents_post(file: UploadFile, project: str = Form(...), selection_session: str = Form(...)) -> Document:
|
||||
async def upload_documents_post(
|
||||
file: UploadFile, project: str = Form(...), selection_session: str = Form(...)
|
||||
) -> Document:
|
||||
|
||||
# Get the file size (in bytes)
|
||||
file.file.seek(0, 2)
|
||||
@@ -713,49 +747,46 @@ async def upload_documents_post(file: UploadFile, project: str = Form(...), sele
|
||||
|
||||
# Find file name ending and create new storage file name
|
||||
if file.filename.lower().endswith(tuple(file_types)):
|
||||
file_ending = file.filename.split('.')[-1].lower()
|
||||
name = document_id + '.' + file_ending
|
||||
file_ending = file.filename.split(".")[-1].lower()
|
||||
name = document_id + "." + file_ending
|
||||
else:
|
||||
file_ending = ''
|
||||
file_ending = ""
|
||||
name = document_id
|
||||
|
||||
# Get mime type and file type
|
||||
mime_type = ''
|
||||
file_type = ''
|
||||
mime_type = ""
|
||||
file_type = ""
|
||||
if hasattr(file_types, file_ending):
|
||||
mime_type = file_types[file_ending]['mime_type']
|
||||
file_type = file_types[file_ending]['file_type']
|
||||
mime_type = file_types[file_ending]["mime_type"]
|
||||
file_type = file_types[file_ending]["file_type"]
|
||||
|
||||
# Create document data
|
||||
document_version_dict = {
|
||||
'document_id': document_id,
|
||||
'session_file_id': '',
|
||||
'version_index': 1,
|
||||
'version_number': '1',
|
||||
'creation_date': doc_db.timestamp(),
|
||||
'title': file.filename,
|
||||
'original_file_name': file.filename,
|
||||
'file_ending': file_ending,
|
||||
'mime_type': mime_type,
|
||||
'file_type': file_type,
|
||||
'project': project,
|
||||
'file_description': {
|
||||
'name': name,
|
||||
'size_in_bytes': file_size
|
||||
}
|
||||
"document_id": document_id,
|
||||
"session_file_id": "",
|
||||
"version_index": 1,
|
||||
"version_number": "1",
|
||||
"creation_date": doc_db.timestamp(),
|
||||
"title": file.filename,
|
||||
"original_file_name": file.filename,
|
||||
"file_ending": file_ending,
|
||||
"mime_type": mime_type,
|
||||
"file_type": file_type,
|
||||
"project": project,
|
||||
"file_description": {"name": name, "size_in_bytes": file_size},
|
||||
}
|
||||
|
||||
document_version_model = Document(**document_version_dict)
|
||||
|
||||
# Save file to disc
|
||||
upload_directory = './data/documents/'
|
||||
upload_directory = "./data/documents/"
|
||||
destination_path = os.path.join(upload_directory, name)
|
||||
with open(destination_path, 'wb') as buffer:
|
||||
with open(destination_path, "wb") as buffer:
|
||||
shutil.copyfileobj(file.file, buffer)
|
||||
|
||||
# create database record
|
||||
inserted_document = doc_db.create_node_for_uploaded_file(selection_session, project, document_version_model)
|
||||
print('Created node for document id: ' + str(inserted_document.document_id))
|
||||
print("Created node for document id: " + str(inserted_document.document_id))
|
||||
doc_db.create_ifc_graph_for_document(inserted_document.document_id)
|
||||
|
||||
# return document version of database record
|
||||
|
||||
@@ -28,11 +28,10 @@ authorization_code = None
|
||||
templates = Jinja2Templates(directory="templates")
|
||||
|
||||
clients = {
|
||||
os.environ['KONTROLL_CLIENT_ID']:
|
||||
{
|
||||
'name': os.environ['KONTROLL_CLIENT_NAME'],
|
||||
'secret': secrets['kontroll_client_secret']
|
||||
}
|
||||
os.environ["KONTROLL_CLIENT_ID"]: {
|
||||
"name": os.environ["KONTROLL_CLIENT_NAME"],
|
||||
"secret": secrets["kontroll_client_secret"],
|
||||
}
|
||||
}
|
||||
|
||||
# ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
|
||||
@@ -60,21 +59,25 @@ clients = {
|
||||
@router.get("/foundation/versions", tags=["api_versions_get"])
|
||||
def api_versions_get():
|
||||
return {
|
||||
"versions": [{
|
||||
"api_id": "foundation",
|
||||
"version_id": "1.0",
|
||||
"detailed_version": "https://github.com/BuildingSMART/foundation-API/tree/release_1_0"
|
||||
}, {
|
||||
"api_id": "bcf",
|
||||
"version_id": "3.0",
|
||||
"detailed_version": "https://github.com/buildingSMART/BCF-API/tree/release_3_0",
|
||||
"api_base_url": os.environ['KONTROLL_BASE_URL'] + "bcf/3.0"
|
||||
}, {
|
||||
"api_id": "documents",
|
||||
"version_id": "1.0",
|
||||
"detailed_version": "https://github.com/buildingSMART/documents-API/tree/release_1_0",
|
||||
"api_base_url": os.environ['KONTROLL_BASE_URL'] + "documents/1.0"
|
||||
}]
|
||||
"versions": [
|
||||
{
|
||||
"api_id": "foundation",
|
||||
"version_id": "1.0",
|
||||
"detailed_version": "https://github.com/BuildingSMART/foundation-API/tree/release_1_0",
|
||||
},
|
||||
{
|
||||
"api_id": "bcf",
|
||||
"version_id": "3.0",
|
||||
"detailed_version": "https://github.com/buildingSMART/BCF-API/tree/release_3_0",
|
||||
"api_base_url": os.environ["KONTROLL_BASE_URL"] + "bcf/3.0",
|
||||
},
|
||||
{
|
||||
"api_id": "documents",
|
||||
"version_id": "1.0",
|
||||
"detailed_version": "https://github.com/buildingSMART/documents-API/tree/release_1_0",
|
||||
"api_base_url": os.environ["KONTROLL_BASE_URL"] + "documents/1.0",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -95,18 +98,15 @@ def api_versions_get():
|
||||
# is not supported by the server.
|
||||
|
||||
|
||||
@router.get("/foundation/1.0/auth",
|
||||
tags=["foundation_auth_get"])
|
||||
@router.get("/foundation/1.0/auth", tags=["foundation_auth_get"])
|
||||
def authentication_get():
|
||||
|
||||
return_variable = {
|
||||
"oauth2_auth_url": os.environ['KONTROLL_BASE_URL'] + "foundation/oauth2/auth",
|
||||
"oauth2_token_url": os.environ['KONTROLL_BASE_URL'] + "foundation/oauth2/token",
|
||||
"oauth2_auth_url": os.environ["KONTROLL_BASE_URL"] + "foundation/oauth2/auth",
|
||||
"oauth2_token_url": os.environ["KONTROLL_BASE_URL"] + "foundation/oauth2/token",
|
||||
# "oauth2_dynamic_client_reg_url": os.environ['KONTROLL_BASE_URL'] + "foundation/oauth2/reg",
|
||||
"http_basic_supported": True,
|
||||
"supported_oauth2_flows": [
|
||||
"authorization_code_grant"
|
||||
]
|
||||
"supported_oauth2_flows": ["authorization_code_grant"],
|
||||
}
|
||||
print(return_variable)
|
||||
return return_variable
|
||||
@@ -135,23 +135,25 @@ def authentication_get():
|
||||
|
||||
|
||||
@router.get("/foundation/oauth2/auth", response_class=HTMLResponse)
|
||||
def authorization(request: Request,
|
||||
response_type: str,
|
||||
client_id: str,
|
||||
state: str,
|
||||
scope: str,
|
||||
redirect_uri: str,
|
||||
):
|
||||
def authorization(
|
||||
request: Request,
|
||||
response_type: str,
|
||||
client_id: str,
|
||||
state: str,
|
||||
scope: str,
|
||||
redirect_uri: str,
|
||||
):
|
||||
|
||||
client_name = clients[client_id]['name']
|
||||
client_name = clients[client_id]["name"]
|
||||
|
||||
print(f"Response type: {response_type}, "
|
||||
f"Client_id: {client_id}, "
|
||||
f"Client_name: {client_name}, "
|
||||
f"State: {state}, "
|
||||
f"Scope: {scope},"
|
||||
f"Redirect_URI: {redirect_uri}."
|
||||
)
|
||||
print(
|
||||
f"Response type: {response_type}, "
|
||||
f"Client_id: {client_id}, "
|
||||
f"Client_name: {client_name}, "
|
||||
f"State: {state}, "
|
||||
f"Scope: {scope},"
|
||||
f"Redirect_URI: {redirect_uri}."
|
||||
)
|
||||
|
||||
# 3. Solibri sends the user to oauth2_auth_url with the following parameters:
|
||||
# response_type=code, client_id=solibri_test_001, state=..., redirect_uri=uri, scope=...
|
||||
@@ -159,38 +161,41 @@ def authorization(request: Request,
|
||||
|
||||
return templates.TemplateResponse(
|
||||
"login.html",
|
||||
{"request": request,
|
||||
"response_type": response_type,
|
||||
"client_id": client_id,
|
||||
"client_name": client_name,
|
||||
"state": state,
|
||||
"scope": scope,
|
||||
"redirect_uri": redirect_uri,
|
||||
})
|
||||
{
|
||||
"request": request,
|
||||
"response_type": response_type,
|
||||
"client_id": client_id,
|
||||
"client_name": client_name,
|
||||
"state": state,
|
||||
"scope": scope,
|
||||
"redirect_uri": redirect_uri,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@router.get("/foundation/oauth2/code")
|
||||
def code(username: str,
|
||||
password: str,
|
||||
response_type: str,
|
||||
client_id,
|
||||
client_name,
|
||||
state: str,
|
||||
redirect_uri: str,
|
||||
scope: str = ''
|
||||
):
|
||||
def code(
|
||||
username: str,
|
||||
password: str,
|
||||
response_type: str,
|
||||
client_id,
|
||||
client_name,
|
||||
state: str,
|
||||
redirect_uri: str,
|
||||
scope: str = "",
|
||||
):
|
||||
|
||||
global oauth2_state
|
||||
oauth2_state = state
|
||||
|
||||
print('Username: ' + username + '. Password: ' + password)
|
||||
print("Username: " + username + ". Password: " + password)
|
||||
user = authenticate_user(username, password)
|
||||
|
||||
if not user:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Incorrect username or password",
|
||||
headers={"WWW-Authenticate": "Bearer"}
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
# The user is signed in, now the main purpose of this function is to generate the authorization code.
|
||||
@@ -242,36 +247,35 @@ def code(username: str,
|
||||
# POST https://example.com/foundation/oauth2/token?grant_type=authorization_code&code=<your_authorization_code>
|
||||
|
||||
|
||||
@router.post("/foundation/oauth2/token",
|
||||
tags=["login_for_access_token_post"],
|
||||
status_code=201)
|
||||
@router.post("/foundation/oauth2/token", tags=["login_for_access_token_post"], status_code=201)
|
||||
def login_for_access_token(
|
||||
grant_type: Optional[str] = Form(None),
|
||||
refresh_token: Optional[str] = Form(None),
|
||||
code: Optional[str] = Form(None),
|
||||
credentials: HTTPBasicCredentials = Depends(http_basic)):
|
||||
grant_type: Optional[str] = Form(None),
|
||||
refresh_token: Optional[str] = Form(None),
|
||||
code: Optional[str] = Form(None),
|
||||
credentials: HTTPBasicCredentials = Depends(http_basic),
|
||||
):
|
||||
|
||||
print('grant_type: ', grant_type)
|
||||
print('refresh_token: ', refresh_token)
|
||||
print('code: ', code)
|
||||
print('credentials: ', credentials)
|
||||
print("grant_type: ", grant_type)
|
||||
print("refresh_token: ", refresh_token)
|
||||
print("code: ", code)
|
||||
print("credentials: ", credentials)
|
||||
|
||||
# The API should check that the credentials (client_id and client_secret) are correct
|
||||
# credentials.username contains the client_id
|
||||
# credentials.password contains the client_secret
|
||||
if credentials.username not in clients or credentials.password != clients[credentials.username]['secret']:
|
||||
if credentials.username not in clients or credentials.password != clients[credentials.username]["secret"]:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Incorrect client_id or client_secret",
|
||||
)
|
||||
|
||||
if grant_type == 'authorization_code':
|
||||
if grant_type == "authorization_code":
|
||||
# use authorization code,
|
||||
# create access token and refresh token,
|
||||
# delete authorization code
|
||||
user_info = foundation_db.use_authorization_code(code)
|
||||
|
||||
elif grant_type == 'refresh_token':
|
||||
elif grant_type == "refresh_token":
|
||||
# use refresh token to get access token
|
||||
# delete old access token and old refresh token
|
||||
# create new access token and a new refresh token
|
||||
@@ -279,8 +283,8 @@ def login_for_access_token(
|
||||
user_info = foundation_db.use_refresh_token(refresh_token)
|
||||
|
||||
user_info.token_type = "Bearer"
|
||||
user_info.expires_in = int(os.environ['SECURITY_ACCESS_TOKEN_EXPIRE_SECONDS'])
|
||||
print('user_info: ', user_info)
|
||||
user_info.expires_in = int(os.environ["SECURITY_ACCESS_TOKEN_EXPIRE_SECONDS"])
|
||||
print("user_info: ", user_info)
|
||||
return user_info
|
||||
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import httpx
|
||||
|
||||
|
||||
def log_info(req_body, res_body, route_url):
|
||||
logging.info('request:' + route_url + ':' + str(req_body))
|
||||
logging.info('response:' + route_url + ':' + str(res_body))
|
||||
logging.info("request:" + route_url + ":" + str(req_body))
|
||||
logging.info("response:" + route_url + ":" + str(res_body))
|
||||
|
||||
|
||||
class LoggingRoute(APIRoute):
|
||||
@@ -22,21 +22,26 @@ class LoggingRoute(APIRoute):
|
||||
response = await original_route_handler(request)
|
||||
route_url = str(request.url)
|
||||
if isinstance(response, StreamingResponse):
|
||||
res_body = b''
|
||||
res_body = b""
|
||||
async for item in response.body_iterator:
|
||||
res_body += item
|
||||
task = BackgroundTask(log_info, req_body, res_body, route_url)
|
||||
return Response(content=res_body, status_code=response.status_code,
|
||||
headers=dict(response.headers), media_type=response.media_type, background=task)
|
||||
return Response(
|
||||
content=res_body,
|
||||
status_code=response.status_code,
|
||||
headers=dict(response.headers),
|
||||
media_type=response.media_type,
|
||||
background=task,
|
||||
)
|
||||
else:
|
||||
if hasattr(response, 'body'):
|
||||
if hasattr(response, "body"):
|
||||
res_body = response.body
|
||||
else:
|
||||
res_body = {'no response': True}
|
||||
res_body = {"no response": True}
|
||||
response.background = BackgroundTask(log_info, req_body, res_body, route_url)
|
||||
return response
|
||||
|
||||
return custom_route_handler
|
||||
|
||||
|
||||
logging.basicConfig(filename='logs/info.log', level=logging.DEBUG)
|
||||
logging.basicConfig(filename="logs/info.log", level=logging.DEBUG)
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
|
||||
import collections
|
||||
import os
|
||||
import traceback
|
||||
import sys
|
||||
|
||||
from fastapi import APIRouter, Request, Depends
|
||||
from fastapi import APIRouter, Request, Depends
|
||||
from fastapi.responses import FileResponse, HTMLResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
@@ -30,13 +29,17 @@ templates = Jinja2Templates(directory="templates")
|
||||
# UPLOAD FLOW
|
||||
################################################################
|
||||
|
||||
|
||||
@router.post("/user/1.0/upload-documents", tags=[""])
|
||||
def upload_documents_post(upload_documents: UploadDocuments,
|
||||
current_user: User = Depends(get_current_active_user)) -> DocumentUploadSessionInitialization:
|
||||
def upload_documents_post(
|
||||
upload_documents: UploadDocuments, current_user: User = Depends(get_current_active_user)
|
||||
) -> DocumentUploadSessionInitialization:
|
||||
post_upload_documents_response = doc_db.post_upload_documents(upload_documents, current_user)
|
||||
doc_db.debug(endpoint='upload_documents_post',
|
||||
request={'upload_documents': upload_documents},
|
||||
response=post_upload_documents_response.dict())
|
||||
doc_db.debug(
|
||||
endpoint="upload_documents_post",
|
||||
request={"upload_documents": upload_documents},
|
||||
response=post_upload_documents_response.dict(),
|
||||
)
|
||||
return post_upload_documents_response
|
||||
|
||||
|
||||
@@ -45,20 +48,23 @@ def upload_documents_post(upload_documents: UploadDocuments,
|
||||
def upload_documents_get(request: Request, upload_session: UUID):
|
||||
|
||||
data_for_upload_documents = doc_db.get_data_for_upload_documents(upload_session)
|
||||
print('Data for site: ', data_for_upload_documents)
|
||||
print("Data for site: ", data_for_upload_documents)
|
||||
|
||||
return templates.TemplateResponse(
|
||||
'upload_files.html',
|
||||
{'request': request,
|
||||
'upload_session': upload_session,
|
||||
'username': data_for_upload_documents.current_user.username,
|
||||
'email': data_for_upload_documents.current_user.email,
|
||||
'full_name': data_for_upload_documents.current_user.full_name,
|
||||
'server_context': data_for_upload_documents.server_context,
|
||||
'callback_url': data_for_upload_documents.callback.url,
|
||||
'callback_expires_in': data_for_upload_documents.callback.expires_in,
|
||||
'documents': data_for_upload_documents.documents,
|
||||
'projects': data_for_upload_documents.projects})
|
||||
"upload_files.html",
|
||||
{
|
||||
"request": request,
|
||||
"upload_session": upload_session,
|
||||
"username": data_for_upload_documents.current_user.username,
|
||||
"email": data_for_upload_documents.current_user.email,
|
||||
"full_name": data_for_upload_documents.current_user.full_name,
|
||||
"server_context": data_for_upload_documents.server_context,
|
||||
"callback_url": data_for_upload_documents.callback.url,
|
||||
"callback_expires_in": data_for_upload_documents.callback.expires_in,
|
||||
"documents": data_for_upload_documents.documents,
|
||||
"projects": data_for_upload_documents.projects,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@router.post("/user/1.0/save-metadata-for-documents", tags=[""])
|
||||
@@ -71,29 +77,29 @@ async def save_metadata_for_documents_post(request: Request) -> list:
|
||||
print(form_data_json)
|
||||
|
||||
documents = collections.defaultdict(dict)
|
||||
names = ('session_file_id', 'document', 'title', 'version_number', 'filename')
|
||||
names = ("session_file_id", "document", "title", "version_number", "filename")
|
||||
|
||||
for whole_form_key, value in form_data_json.items():
|
||||
if whole_form_key.startswith(names):
|
||||
start_form_key, document_id = whole_form_key.split("@", 1)
|
||||
print('New field: ', start_form_key, ' for document id: ', document_id)
|
||||
print("New field: ", start_form_key, " for document id: ", document_id)
|
||||
documents[document_id][start_form_key] = value
|
||||
|
||||
print("Documents: ")
|
||||
print(documents)
|
||||
|
||||
username = form_data_json['username']
|
||||
upload_session = form_data_json['upload_session']
|
||||
server_context = form_data_json['server_context']
|
||||
callback_url = form_data_json['callback_url']
|
||||
callback_expires_in = form_data_json['callback_expires_in']
|
||||
project = form_data_json['project']
|
||||
username = form_data_json["username"]
|
||||
upload_session = form_data_json["upload_session"]
|
||||
server_context = form_data_json["server_context"]
|
||||
callback_url = form_data_json["callback_url"]
|
||||
callback_expires_in = form_data_json["callback_expires_in"]
|
||||
project = form_data_json["project"]
|
||||
|
||||
documents_saved = list()
|
||||
|
||||
for key in documents:
|
||||
try:
|
||||
documents[key]['project'] = project
|
||||
documents[key]["project"] = project
|
||||
document = DocumentMetadata(**documents[key])
|
||||
save_metadata_response = doc_db.save_metadata_for_documents(document, upload_session, username)
|
||||
documents_saved.append(save_metadata_response)
|
||||
@@ -101,9 +107,11 @@ async def save_metadata_for_documents_post(request: Request) -> list:
|
||||
print(e)
|
||||
continue
|
||||
|
||||
doc_db.debug(endpoint='save_metadata_for_documents_post',
|
||||
request={'documents': documents},
|
||||
response={'response': documents_saved})
|
||||
doc_db.debug(
|
||||
endpoint="save_metadata_for_documents_post",
|
||||
request={"documents": documents},
|
||||
response={"response": documents_saved},
|
||||
)
|
||||
|
||||
return documents_saved
|
||||
|
||||
@@ -113,8 +121,7 @@ async def save_metadata_for_documents_post(request: Request) -> list:
|
||||
|
||||
|
||||
@router.post("/user/1.0/upload-part/{part_id}", tags=[""])
|
||||
async def upload_part(part_id: str, request: Request,
|
||||
current_user: User = Depends(get_current_active_user)):
|
||||
async def upload_part(part_id: str, request: Request, current_user: User = Depends(get_current_active_user)):
|
||||
|
||||
# file_name = doc_db.safe_path(part_id)
|
||||
file_name = part_id
|
||||
@@ -129,33 +136,31 @@ async def upload_part(part_id: str, request: Request,
|
||||
|
||||
# try to receive the uploaded part
|
||||
try:
|
||||
print('File contents: ', request_body)
|
||||
print("File contents: ", request_body)
|
||||
|
||||
# use document_id instead as dir_name
|
||||
# dir_name = doc_db.safe_path(document.document_id)
|
||||
dir_name = document.document_id
|
||||
|
||||
path = './data/document_parts/' + dir_name + '/'
|
||||
path = "./data/document_parts/" + dir_name + "/"
|
||||
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
|
||||
with open(path + file_name, 'wb') as f:
|
||||
with open(path + file_name, "wb") as f:
|
||||
f.write(request_body)
|
||||
|
||||
except Exception:
|
||||
print('Error uploading file')
|
||||
print("Error uploading file")
|
||||
print(traceback.format_exc())
|
||||
print('Error uploading file')
|
||||
print("Error uploading file")
|
||||
print(sys.exc_info()[2])
|
||||
|
||||
finally:
|
||||
# We will write to the database, information about part successfully uploaded.
|
||||
doc_db.mark_part_as_uploaded(part_id, current_user)
|
||||
|
||||
doc_db.debug(endpoint='upload-part',
|
||||
request={'part_id': part_id},
|
||||
response={'uploaded': True})
|
||||
doc_db.debug(endpoint="upload-part", request={"part_id": part_id}, response={"uploaded": True})
|
||||
|
||||
return {"message": f"Successfully uploaded part {file_name}"}
|
||||
|
||||
@@ -166,13 +171,14 @@ async def upload_part(part_id: str, request: Request,
|
||||
|
||||
|
||||
@router.get("/user/1.0/document/{document_id}/version/{version_index}/download", tags=[""])
|
||||
def document_version_download(document_id: str, version_index: int,
|
||||
current_user: User = Depends(get_current_active_user)) -> FileResponse:
|
||||
def document_version_download(
|
||||
document_id: str, version_index: int, current_user: User = Depends(get_current_active_user)
|
||||
) -> FileResponse:
|
||||
# The url to download the binary content of this document version.
|
||||
# May either directly return the result or redirect to a storage provider
|
||||
keep_characters = (' ', '.', '_', '-')
|
||||
keep_characters = (" ", ".", "_", "-")
|
||||
document_id = "".join(c for c in document_id if c.isalnum() or c in keep_characters).rstrip()
|
||||
file_location = './data/documents/' + document_id + '.ifc'
|
||||
return FileResponse(file_location,
|
||||
media_type='application/x-step',
|
||||
filename='6dbd4d52-14db-11ee-be56-0242ac120002.ifc')
|
||||
file_location = "./data/documents/" + document_id + ".ifc"
|
||||
return FileResponse(
|
||||
file_location, media_type="application/x-step", filename="6dbd4d52-14db-11ee-be56-0242ac120002.ifc"
|
||||
)
|
||||
|
||||
@@ -18,9 +18,9 @@ get_secrets()
|
||||
# otherwise the environment variable will have a value of neo4j://kontroll_neo4j:27687
|
||||
# kontroll_neo4j is the docker-compose network.
|
||||
|
||||
driver = GraphDatabase.driver(os.environ['NEO4J_URI'],
|
||||
auth=(os.environ['NEO4J_USER'],
|
||||
os.environ['NEO4J_INITIAL_PASSWORD']))
|
||||
driver = GraphDatabase.driver(
|
||||
os.environ["NEO4J_URI"], auth=(os.environ["NEO4J_USER"], os.environ["NEO4J_INITIAL_PASSWORD"])
|
||||
)
|
||||
|
||||
# initial password should be changed to secret password
|
||||
|
||||
@@ -33,33 +33,38 @@ class MyDB:
|
||||
|
||||
def __init__(self, object_driver):
|
||||
self.driver = object_driver
|
||||
self.database = 'neo4j'
|
||||
self.database = "neo4j"
|
||||
|
||||
@staticmethod
|
||||
def timestamp():
|
||||
return datetime.now(timezone.utc).isoformat(sep='T', timespec='milliseconds')
|
||||
return datetime.now(timezone.utc).isoformat(sep="T", timespec="milliseconds")
|
||||
|
||||
@staticmethod
|
||||
def bcf_time(any_datetime):
|
||||
if isinstance(any_datetime, type('str')):
|
||||
if isinstance(any_datetime, type("str")):
|
||||
datetime_any = parser.parse(any_datetime).astimezone(pytz.utc)
|
||||
elif isinstance(any_datetime, type(datetime.now())):
|
||||
datetime_any = any_datetime.astimezone(pytz.utc)
|
||||
else:
|
||||
return False
|
||||
string_date = datetime_any.isoformat(sep='T', timespec='milliseconds')
|
||||
string_date = datetime_any.isoformat(sep="T", timespec="milliseconds")
|
||||
return str(string_date)
|
||||
|
||||
@staticmethod
|
||||
def safe_path(path_name):
|
||||
safe_path_name = ''.join(x for x in path_name if x.isalnum() or '-')
|
||||
safe_path_name = "".join(x for x in path_name if x.isalnum() or "-")
|
||||
return safe_path_name
|
||||
|
||||
@staticmethod
|
||||
def debug(endpoint: str, request, response):
|
||||
print("\n\n\nEndpoint: ", jsonpickle.dumps(endpoint),
|
||||
"\nRequest: ", jsonpickle.dumps(request),
|
||||
"\nResponse: ", jsonpickle.dumps(response))
|
||||
print(
|
||||
"\n\n\nEndpoint: ",
|
||||
jsonpickle.dumps(endpoint),
|
||||
"\nRequest: ",
|
||||
jsonpickle.dumps(request),
|
||||
"\nResponse: ",
|
||||
jsonpickle.dumps(response),
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def node_to_json(node):
|
||||
@@ -89,11 +94,12 @@ class MyDB:
|
||||
cypher_file = open(cypher_file_path, "r")
|
||||
cypher_data = cypher_file.read()
|
||||
cypher_file.close()
|
||||
cypher_statements = cypher_data.split(';')
|
||||
cypher_statements = cypher_data.split(";")
|
||||
cypher_statements.pop()
|
||||
for cypher_statement in cypher_statements:
|
||||
tx.run(cypher_statement)
|
||||
return
|
||||
|
||||
with self.driver.session() as session:
|
||||
return session.execute_write(initialize_db_work)
|
||||
|
||||
@@ -113,8 +119,10 @@ class MyDB:
|
||||
user_dict = self.node_to_json(user_node)
|
||||
user = UserInDB(**user_dict)
|
||||
return user
|
||||
|
||||
with self.driver.session() as session:
|
||||
return session.execute_read(get_user_work, username_work=username)
|
||||
|
||||
|
||||
db = MyDB(driver)
|
||||
db.initialize_db()
|
||||
|
||||
@@ -28,24 +28,24 @@ from py2neo import Graph
|
||||
def create_pure_node_from_ifc_entity(ifc_entity, ifc_file, hierarchy=True):
|
||||
node = Node()
|
||||
if ifc_entity.id() != 0:
|
||||
node['id'] = ifc_entity.id()
|
||||
node["id"] = ifc_entity.id()
|
||||
else:
|
||||
node['id'] = str(uuid4())
|
||||
node['name'] = ifc_entity.is_a()
|
||||
node["id"] = str(uuid4())
|
||||
node["name"] = ifc_entity.is_a()
|
||||
if hierarchy:
|
||||
for label in ifc_file.wrapped_data.types_with_super():
|
||||
if ifc_entity.is_a(label):
|
||||
node.add_label(label)
|
||||
else:
|
||||
node.add_label(ifc_entity.is_a())
|
||||
attributes_type = ['ENTITY INSTANCE', 'AGGREGATE OF ENTITY INSTANCE', 'DERIVED']
|
||||
attributes_type = ["ENTITY INSTANCE", "AGGREGATE OF ENTITY INSTANCE", "DERIVED"]
|
||||
for i in range(ifc_entity.__len__()):
|
||||
if not ifc_entity.wrapped_data.get_argument_type(i) in attributes_type:
|
||||
name = ifc_entity.wrapped_data.get_argument_name(i)
|
||||
name_value = ifc_entity.wrapped_data.get_argument(i)
|
||||
node[name]= name_value
|
||||
node.__primarylabel__ = 'Root'
|
||||
node.__primarykey__ = 'id'
|
||||
node[name] = name_value
|
||||
node.__primarylabel__ = "Root"
|
||||
node.__primarykey__ = "id"
|
||||
return node
|
||||
|
||||
|
||||
@@ -55,14 +55,14 @@ def create_graph_from_ifc_entity_all(graph, ifc_entity, ifc_file):
|
||||
graph.merge(node)
|
||||
for i in range(ifc_entity.__len__()):
|
||||
if ifc_entity[i]:
|
||||
if ifc_entity.wrapped_data.get_argument_type(i) == 'ENTITY INSTANCE':
|
||||
if ifc_entity[i].is_a() in ['IfcOwnerHistory'] and ifc_entity.is_a() != 'IfcProject':
|
||||
if ifc_entity.wrapped_data.get_argument_type(i) == "ENTITY INSTANCE":
|
||||
if ifc_entity[i].is_a() in ["IfcOwnerHistory"] and ifc_entity.is_a() != "IfcProject":
|
||||
continue
|
||||
else:
|
||||
sub_node = create_pure_node_from_ifc_entity(ifc_entity[i], ifc_file)
|
||||
REL = Relationship(node, ifc_entity.wrapped_data.get_argument_name(i), sub_node)
|
||||
graph.merge(REL)
|
||||
elif ifc_entity.wrapped_data.get_argument_type(i) == 'AGGREGATE OF ENTITY INSTANCE':
|
||||
elif ifc_entity.wrapped_data.get_argument_type(i) == "AGGREGATE OF ENTITY INSTANCE":
|
||||
for sub_entity in ifc_entity[i]:
|
||||
sub_node = create_pure_node_from_ifc_entity(sub_entity, ifc_file)
|
||||
REL = Relationship(node, ifc_entity.wrapped_data.get_argument_name(i), sub_node)
|
||||
@@ -83,7 +83,7 @@ def create_full_graph(graph, ifc_file):
|
||||
length = len(ifc_file.wrapped_data.entity_names())
|
||||
for entity_id in ifc_file.wrapped_data.entity_names():
|
||||
entity = ifc_file.by_id(entity_id)
|
||||
print(idx, '/', length, entity)
|
||||
print(idx, "/", length, entity)
|
||||
create_graph_from_ifc_entity_all(graph, entity, ifc_file)
|
||||
idx += 1
|
||||
return
|
||||
|
||||
@@ -13,79 +13,110 @@ endpoint_metadata = [
|
||||
{"name": "authentication_get", "description": "/authentication"},
|
||||
{"name": "login_for_access_token_post", "description": "/foundation/oauth2/token"},
|
||||
{"name": "current_user_get", "description": "/foundation/1.0/current-user"},
|
||||
{"name": "projects_get",
|
||||
"description": "Retrieve a collection of projects that the currently logged on user has access to."},
|
||||
{"name": "project_get",
|
||||
"description": "Retrieve a specific project. The top level data container is known as the BCF project, "
|
||||
"with a UUID and a project name attribute."},
|
||||
{"name": "project_put",
|
||||
"description": "Modify a specific project. This operation is only possible when the server returns the update "
|
||||
"flag in the Project authorization."},
|
||||
{"name": "project_extensions_get",
|
||||
"description": "Retrieve a specific projects extensions. Project extensions are used to define possible values "
|
||||
"that can be used in topics and comments, for example topic labels and priorities. They may "
|
||||
"change during the course of a project. The most recent extensions state which values are valid "
|
||||
"at a given moment for newly created topics and comments."},
|
||||
{"name": "topics_get",
|
||||
"description": "Retrieve a collection of topics related to a project (default sort order is creation_date)."},
|
||||
{"name": "topic_post",
|
||||
"description": "Add a new topic. The BCF project contains zero or more topics. Each topic represents a model "
|
||||
"issue. A topic will have a UUID, a title, description, priority, stage, labels (similar to "
|
||||
"tags), creation date / author, due date, and assigned to. If modified, it may contain the "
|
||||
"modification date and author."},
|
||||
{
|
||||
"name": "projects_get",
|
||||
"description": "Retrieve a collection of projects that the currently logged on user has access to.",
|
||||
},
|
||||
{
|
||||
"name": "project_get",
|
||||
"description": "Retrieve a specific project. The top level data container is known as the BCF project, "
|
||||
"with a UUID and a project name attribute.",
|
||||
},
|
||||
{
|
||||
"name": "project_put",
|
||||
"description": "Modify a specific project. This operation is only possible when the server returns the update "
|
||||
"flag in the Project authorization.",
|
||||
},
|
||||
{
|
||||
"name": "project_extensions_get",
|
||||
"description": "Retrieve a specific projects extensions. Project extensions are used to define possible values "
|
||||
"that can be used in topics and comments, for example topic labels and priorities. They may "
|
||||
"change during the course of a project. The most recent extensions state which values are valid "
|
||||
"at a given moment for newly created topics and comments.",
|
||||
},
|
||||
{
|
||||
"name": "topics_get",
|
||||
"description": "Retrieve a collection of topics related to a project (default sort order is creation_date).",
|
||||
},
|
||||
{
|
||||
"name": "topic_post",
|
||||
"description": "Add a new topic. The BCF project contains zero or more topics. Each topic represents a model "
|
||||
"issue. A topic will have a UUID, a title, description, priority, stage, labels (similar to "
|
||||
"tags), creation date / author, due date, and assigned to. If modified, it may contain the "
|
||||
"modification date and author.",
|
||||
},
|
||||
{"name": "topic_get", "description": "Retrieve a specific topic."},
|
||||
{"name": "topic_put", "description": "Modify a specific topic, description similar to POST."},
|
||||
{"name": "bim_snippet_get",
|
||||
"description": "Retrieves a topics BIM-Snippet as binary file. BIM snippet has been in BCF specification since "
|
||||
"the very beginning, but is has never been used. Snippets have originally been added to provide "
|
||||
"for 'changes in IFC'. To get this really working in a CDE environment changes to the IFC format "
|
||||
"is necessary."},
|
||||
{"name": "bim_snippet_put",
|
||||
"description": "Puts a new BIM Snippet binary file to a topic. If this is used, the parent topics BIM Snippet "
|
||||
"property is_external must be set to false and the reference must be the file name with "
|
||||
"extension."},
|
||||
{
|
||||
"name": "bim_snippet_get",
|
||||
"description": "Retrieves a topics BIM-Snippet as binary file. BIM snippet has been in BCF specification since "
|
||||
"the very beginning, but is has never been used. Snippets have originally been added to provide "
|
||||
"for 'changes in IFC'. To get this really working in a CDE environment changes to the IFC format "
|
||||
"is necessary.",
|
||||
},
|
||||
{
|
||||
"name": "bim_snippet_put",
|
||||
"description": "Puts a new BIM Snippet binary file to a topic. If this is used, the parent topics BIM Snippet "
|
||||
"property is_external must be set to false and the reference must be the file name with "
|
||||
"extension.",
|
||||
},
|
||||
{"name": "files_get", "description": "Retrieve a collection of file references as topic header."},
|
||||
{"name": "files_put", "description": "Update a collection of file references on the topic header."},
|
||||
{"name": "comments_get",
|
||||
"description": "Retrieve a collection of all comments related to a topic (default ordering is date)."},
|
||||
{
|
||||
"name": "comments_get",
|
||||
"description": "Retrieve a collection of all comments related to a topic (default ordering is date).",
|
||||
},
|
||||
{"name": "comment_post", "description": "Add a new comment to a topic."},
|
||||
{"name": "comment_put", "description": "Update a single comment, description similar to POST."},
|
||||
{"name": "comment_get", "description": "Get a single comment."},
|
||||
{"name": "viewpoints_get", "description": "Retrieve a collection of all viewpoints related to a topic."},
|
||||
{"name": "viewpoint_post",
|
||||
"description": "Add a new viewpoint. Viewpoints are immutable, meaning that they should never change. "
|
||||
"Requirements for different visualizations should be handled by creating new viewpoint elements."},
|
||||
{
|
||||
"name": "viewpoint_post",
|
||||
"description": "Add a new viewpoint. Viewpoints are immutable, meaning that they should never change. "
|
||||
"Requirements for different visualizations should be handled by creating new viewpoint elements.",
|
||||
},
|
||||
{"name": "viewpoint_get", "description": "Retrieve a specific viewpoint."},
|
||||
{"name": "viewpoint_selected_components_get",
|
||||
"description": "Retrieve a collection of all selected components in a viewpoint."},
|
||||
{"name": "viewpoint_colored_components_get",
|
||||
"description": "Retrieve a collection of all colored components in a viewpoint."},
|
||||
{
|
||||
"name": "viewpoint_selected_components_get",
|
||||
"description": "Retrieve a collection of all selected components in a viewpoint.",
|
||||
},
|
||||
{
|
||||
"name": "viewpoint_colored_components_get",
|
||||
"description": "Retrieve a collection of all colored components in a viewpoint.",
|
||||
},
|
||||
{"name": "viewpoint_components_visibility_get", "description": "Retrieve visibility of components in a viewpoint."},
|
||||
{"name": "viewpoint_snapshot_get", "description": "Retrieve a specific viewpoints bitmap image file (png or jpg)."},
|
||||
{"name": "related_topics_get", "description": "Retrieve a collection of all related topics to a topic."},
|
||||
{"name": "related_topics_put", "description": "Add or update a collection of all related topics to a topic."},
|
||||
{"name": "topic_document_references_get",
|
||||
"description": "Retrieve a collection of all document references to a topic."},
|
||||
{
|
||||
"name": "topic_document_references_get",
|
||||
"description": "Retrieve a collection of all document references to a topic.",
|
||||
},
|
||||
{"name": "topic_document_references_post", "description": "Add or update document references to a topic."},
|
||||
{"name": "topic_document_references_put", "description": "Add or update document references to a topic."},
|
||||
{"name": "documents_get", "description": "Retrieve a collection of all documents uploaded to a project."},
|
||||
{"name": "document_post", "description": "Upload a document (binary file) to a project."},
|
||||
{"name": "document_get", "description": "Retrieves a document as binary file."},
|
||||
{"name": "topics_events_get",
|
||||
"description": "Retrieve a collection of topic events related to a project (default sort order is date)."},
|
||||
{"name": "topic_events_get",
|
||||
"description": "Retrieve a collection of topic events related to a project (default sort order is date)."},
|
||||
{"name": "comments_events_get",
|
||||
"description": "Retrieve a collection of comment events related to a project (default sort order is date)."},
|
||||
{"name": "comment_events_get",
|
||||
"description": "Retrieve a collection of comment events related to a comment (default sort order is date)."}
|
||||
{
|
||||
"name": "topics_events_get",
|
||||
"description": "Retrieve a collection of topic events related to a project (default sort order is date).",
|
||||
},
|
||||
{
|
||||
"name": "topic_events_get",
|
||||
"description": "Retrieve a collection of topic events related to a project (default sort order is date).",
|
||||
},
|
||||
{
|
||||
"name": "comments_events_get",
|
||||
"description": "Retrieve a collection of comment events related to a project (default sort order is date).",
|
||||
},
|
||||
{
|
||||
"name": "comment_events_get",
|
||||
"description": "Retrieve a collection of comment events related to a comment (default sort order is date).",
|
||||
},
|
||||
]
|
||||
|
||||
app = FastAPI(
|
||||
title="Kontroll API",
|
||||
description="Implementering av BCF API 3.0",
|
||||
version="0.0.1",
|
||||
openapi_tags=endpoint_metadata
|
||||
title="Kontroll API", description="Implementering av BCF API 3.0", version="0.0.1", openapi_tags=endpoint_metadata
|
||||
)
|
||||
|
||||
# Configure app to accept requests from anywhere
|
||||
@@ -98,23 +129,21 @@ app.add_middleware(
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
app.include_router(foundation.router, prefix='')
|
||||
app.include_router(bcf.router, prefix='')
|
||||
app.include_router(documents.router, prefix='')
|
||||
app.include_router(foundation.router, prefix="")
|
||||
app.include_router(bcf.router, prefix="")
|
||||
app.include_router(documents.router, prefix="")
|
||||
|
||||
templates = Jinja2Templates(directory="templates")
|
||||
|
||||
|
||||
@app.get("/", response_class=HTMLResponse)
|
||||
def index(request: Request):
|
||||
return templates.TemplateResponse(
|
||||
"index.html",
|
||||
{"request": request})
|
||||
return templates.TemplateResponse("index.html", {"request": request})
|
||||
|
||||
|
||||
favicon_path = 'favicon.ico'
|
||||
favicon_path = "favicon.ico"
|
||||
|
||||
|
||||
@app.get('/favicon.ico', include_in_schema=False)
|
||||
@app.get("/favicon.ico", include_in_schema=False)
|
||||
async def favicon():
|
||||
return FileResponse(favicon_path)
|
||||
|
||||
@@ -55,13 +55,13 @@ class ClippingPlane(BaseModel):
|
||||
|
||||
|
||||
class SnapshotType(Enum):
|
||||
jpg = 'jpg'
|
||||
png = 'png'
|
||||
jpg = "jpg"
|
||||
png = "png"
|
||||
|
||||
|
||||
class BitmapType(Enum):
|
||||
jpg = 'jpg'
|
||||
png = 'png'
|
||||
jpg = "jpg"
|
||||
png = "png"
|
||||
|
||||
|
||||
class Component(BaseModel):
|
||||
|
||||
@@ -2,9 +2,9 @@ from models.bcf_common import *
|
||||
|
||||
|
||||
class ProjectAction(Enum):
|
||||
update = 'update'
|
||||
createTopic = 'createTopic'
|
||||
createDocument = 'createDocument'
|
||||
update = "update"
|
||||
createTopic = "createTopic"
|
||||
createDocument = "createDocument"
|
||||
|
||||
|
||||
class ProjectGETAuthorization(BaseModel):
|
||||
@@ -18,19 +18,19 @@ class ProjectGET(BaseModel):
|
||||
|
||||
|
||||
class TopicAction(Enum):
|
||||
update = 'update'
|
||||
updateBimSnippet = 'updateBimSnippet'
|
||||
updateRelatedTopics = 'updateRelatedTopics'
|
||||
updateDocumentReferences = 'updateDocumentReferences'
|
||||
updateFiles = 'updateFiles'
|
||||
createComment = 'createComment'
|
||||
createViewpoint = 'createViewpoint'
|
||||
delete = 'delete'
|
||||
update = "update"
|
||||
updateBimSnippet = "updateBimSnippet"
|
||||
updateRelatedTopics = "updateRelatedTopics"
|
||||
updateDocumentReferences = "updateDocumentReferences"
|
||||
updateFiles = "updateFiles"
|
||||
createComment = "createComment"
|
||||
createViewpoint = "createViewpoint"
|
||||
delete = "delete"
|
||||
|
||||
|
||||
class CommentAction(Enum):
|
||||
update = 'update'
|
||||
delete = 'delete'
|
||||
update = "update"
|
||||
delete = "delete"
|
||||
|
||||
|
||||
class ExtensionsGET(BaseModel):
|
||||
@@ -123,7 +123,7 @@ class SnapshotGET(BaseModel):
|
||||
|
||||
|
||||
class ViewpointAction(Enum):
|
||||
delete = 'delete'
|
||||
delete = "delete"
|
||||
|
||||
|
||||
class ViewpointGETAuthorization(BaseModel):
|
||||
@@ -174,6 +174,8 @@ class TopicEventGET(BaseModel):
|
||||
topic_guid: str
|
||||
date: str
|
||||
author: str
|
||||
|
||||
|
||||
# actions: Optional[List[EventAction]] = Field(None, min_items=1)
|
||||
|
||||
|
||||
@@ -182,6 +184,8 @@ class CommentEventGET(BaseModel):
|
||||
topic_guid: str
|
||||
date: str
|
||||
author: str
|
||||
|
||||
|
||||
# actions: Optional[List[EventAction]] = Field(None, min_items=1)
|
||||
|
||||
|
||||
|
||||
@@ -10,12 +10,10 @@ from typing import List, Optional
|
||||
|
||||
class CallbackLink(BaseModel):
|
||||
url: constr(min_length=1) = Field(
|
||||
description='The server will web-browser-redirect to this URL once the user has completed selecting '
|
||||
'documents or entering document metadata on the CDE'
|
||||
)
|
||||
expires_in: int = Field(
|
||||
description='The expiry period for the URL, in seconds'
|
||||
description="The server will web-browser-redirect to this URL once the user has completed selecting "
|
||||
"documents or entering document metadata on the CDE"
|
||||
)
|
||||
expires_in: int = Field(description="The expiry period for the URL, in seconds")
|
||||
|
||||
|
||||
# ---- RESPONSE MODELS ---- #
|
||||
@@ -35,62 +33,52 @@ class DocumentVersionLinks(BaseModel):
|
||||
|
||||
class FileDescription(BaseModel):
|
||||
name: constr(min_length=1) = Field(
|
||||
description='The name of the document version file on the server. The files are named by '
|
||||
'document_id.file_ending',
|
||||
example='908e1cd4-2e09-11ee-be56-0242ac120002.ifc'
|
||||
)
|
||||
size_in_bytes: int = Field(
|
||||
description='The size of the file in bytes',
|
||||
example='124563'
|
||||
description="The name of the document version file on the server. The files are named by "
|
||||
"document_id.file_ending",
|
||||
example="908e1cd4-2e09-11ee-be56-0242ac120002.ifc",
|
||||
)
|
||||
size_in_bytes: int = Field(description="The size of the file in bytes", example="124563")
|
||||
|
||||
|
||||
class Document(BaseModel):
|
||||
document_id: constr(min_length=1) = Field(
|
||||
description='A machine readable identifier that can be used to uniquely identify this version in future calls '
|
||||
'UUID is used - see `Query` section',
|
||||
example='908e1cd4-2e09-11ee-be56-0242ac120002'
|
||||
description="A machine readable identifier that can be used to uniquely identify this version in future calls "
|
||||
"UUID is used - see `Query` section",
|
||||
example="908e1cd4-2e09-11ee-be56-0242ac120002",
|
||||
)
|
||||
session_file_id: Optional[str] = Field(
|
||||
description='A machine readable identifier that can be used to uniquely the file '
|
||||
'during the upload session, UUID is used',
|
||||
example='908e1cd4-2e09-11ee-be56-0242ac120002'
|
||||
description="A machine readable identifier that can be used to uniquely the file "
|
||||
"during the upload session, UUID is used",
|
||||
example="908e1cd4-2e09-11ee-be56-0242ac120002",
|
||||
)
|
||||
version_index: int = Field(
|
||||
description='A machine readable sequence number of the version of the document. The sequence must be ordered, '
|
||||
'so that newer versions have higher values than previous ones. Each version index must be unique '
|
||||
'for that document, but there may be gaps in the sequence',
|
||||
example='12'
|
||||
description="A machine readable sequence number of the version of the document. The sequence must be ordered, "
|
||||
"so that newer versions have higher values than previous ones. Each version index must be unique "
|
||||
"for that document, but there may be gaps in the sequence",
|
||||
example="12",
|
||||
)
|
||||
version_number: Optional[constr(min_length=1)] = Field(
|
||||
description='A human readable version number. This is not expected to be in any specific format across CDEs '
|
||||
'and may hold any value',
|
||||
example='V2.0-larger'
|
||||
description="A human readable version number. This is not expected to be in any specific format across CDEs "
|
||||
"and may hold any value",
|
||||
example="V2.0-larger",
|
||||
)
|
||||
creation_date: str = Field(
|
||||
description='The creation date of the document revision',
|
||||
example='2016-04-28T16:31:12.270+02:00'
|
||||
description="The creation date of the document revision", example="2016-04-28T16:31:12.270+02:00"
|
||||
)
|
||||
title: Optional[constr(min_length=1)] = Field(
|
||||
description='A human readable code or identifier. Metadata entered by user in CDE.',
|
||||
example='Large garage'
|
||||
description="A human readable code or identifier. Metadata entered by user in CDE.", example="Large garage"
|
||||
)
|
||||
original_file_name: Optional[str] = Field(
|
||||
description='The full name of the file as sent to the API',
|
||||
example='First_floor_vent.ifc')
|
||||
file_ending: Optional[str] = Field(
|
||||
description='The ending of the file name, including the dot',
|
||||
example='.ifc')
|
||||
mime_type: Optional[str] = Field(
|
||||
description='The mime type identifier',
|
||||
example='application/x-step')
|
||||
file_type: Optional[str] = Field(
|
||||
description='The full name of the file type',
|
||||
example='STEP Physical File (SPF)')
|
||||
description="The full name of the file as sent to the API", example="First_floor_vent.ifc"
|
||||
)
|
||||
file_ending: Optional[str] = Field(description="The ending of the file name, including the dot", example=".ifc")
|
||||
mime_type: Optional[str] = Field(description="The mime type identifier", example="application/x-step")
|
||||
file_type: Optional[str] = Field(description="The full name of the file type", example="STEP Physical File (SPF)")
|
||||
project: Optional[str] = Field(
|
||||
description='The project to which the document will belong once it has been uploaded,'
|
||||
'this information is added as metadata by the user in the CDE',
|
||||
example='908e1cd4-2e09-11ee-be56-0242ac120003')
|
||||
description="The project to which the document will belong once it has been uploaded,"
|
||||
"this information is added as metadata by the user in the CDE",
|
||||
example="908e1cd4-2e09-11ee-be56-0242ac120003",
|
||||
)
|
||||
file_description: FileDescription
|
||||
parts: Optional[List[str]]
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ class ProjectOnly(BaseModel):
|
||||
class DataForUploadDocuments(BaseModel):
|
||||
server_context: Optional[str] = Field(
|
||||
description="A CDE controlled identifier recording the user's context on the CDE. For example which project "
|
||||
'and folder the user was on. If the client provides the `server_context` in subsequent calls then '
|
||||
'the CDE will attemp to load the UI at the same place.'
|
||||
"and folder the user was on. If the client provides the `server_context` in subsequent calls then "
|
||||
"the CDE will attemp to load the UI at the same place."
|
||||
)
|
||||
documents: List[FileToUpload]
|
||||
callback: Optional[CallbackLink]
|
||||
@@ -32,25 +32,24 @@ class DataForUploadDocuments(BaseModel):
|
||||
|
||||
# ---- DOWNLOAD MODELS ----
|
||||
|
||||
|
||||
class DocumentMetadataEntries(BaseModel):
|
||||
metadata: List[DocumentMetadataEntry] = Field(
|
||||
description='An array of metadata entries'
|
||||
)
|
||||
metadata: List[DocumentMetadataEntry] = Field(description="An array of metadata entries")
|
||||
|
||||
|
||||
class Project(BaseModel):
|
||||
project_id: str
|
||||
name: str
|
||||
documents: Optional[List[Document]] = Field(
|
||||
description='An array containing all the documents selected by the user'
|
||||
description="An array containing all the documents selected by the user"
|
||||
)
|
||||
|
||||
|
||||
class DataForDocumentSelection(BaseModel):
|
||||
server_context: Optional[str] = Field(
|
||||
description="A CDE controlled identifier recording the user's context on the CDE. For example which project "
|
||||
'and folder the user was on. If the client provides the `server_context` in subsequent calls then '
|
||||
'the CDE will attemp to load the UI at the same place.'
|
||||
"and folder the user was on. If the client provides the `server_context` in subsequent calls then "
|
||||
"the CDE will attemp to load the UI at the same place."
|
||||
)
|
||||
projects: List[Project]
|
||||
callback: Optional[CallbackLink]
|
||||
@@ -61,24 +60,8 @@ class DataForDocumentSelection(BaseModel):
|
||||
|
||||
|
||||
file_types = {
|
||||
'smc': {
|
||||
'file_type': 'Solibri Model Checker',
|
||||
'file_ending': '.smc',
|
||||
'mime_type': 'application/octet-stream'
|
||||
},
|
||||
'ifc': {
|
||||
'file_type': 'STEP Physical File',
|
||||
'file_ending': '.ifc',
|
||||
'mime_type': 'application/x-step'
|
||||
},
|
||||
'ifczip': {
|
||||
'file_type': 'ZIP of a STEP Physical File',
|
||||
'file_ending': '.ifcZIP',
|
||||
'mime_type': 'application/zip'
|
||||
},
|
||||
'pdf': {
|
||||
'file_type': 'Adobe Portable Document Format',
|
||||
'file_ending': '.pdf',
|
||||
'mime_type': 'application/pdf'
|
||||
}
|
||||
"smc": {"file_type": "Solibri Model Checker", "file_ending": ".smc", "mime_type": "application/octet-stream"},
|
||||
"ifc": {"file_type": "STEP Physical File", "file_ending": ".ifc", "mime_type": "application/x-step"},
|
||||
"ifczip": {"file_type": "ZIP of a STEP Physical File", "file_ending": ".ifcZIP", "mime_type": "application/zip"},
|
||||
"pdf": {"file_type": "Adobe Portable Document Format", "file_ending": ".pdf", "mime_type": "application/pdf"},
|
||||
}
|
||||
|
||||
@@ -13,15 +13,15 @@ from models.documents_common import CallbackLink
|
||||
|
||||
class FileToUpload(BaseModel):
|
||||
file_name: constr(min_length=1) = Field(
|
||||
description='The CDE UI will display this value to the User when entering document metadata. This is the '
|
||||
'original name of the file. This attribute is the same as the name attribute in a document model.'
|
||||
description="The CDE UI will display this value to the User when entering document metadata. This is the "
|
||||
"original name of the file. This attribute is the same as the name attribute in a document model."
|
||||
)
|
||||
session_file_id: constr(min_length=1) = Field(
|
||||
description='This is a client provided id to differentiate between multiple files that are being uploaded in '
|
||||
'the same session'
|
||||
description="This is a client provided id to differentiate between multiple files that are being uploaded in "
|
||||
"the same session"
|
||||
)
|
||||
document_id: Optional[constr(min_length=1)] = Field(
|
||||
description='When present, indicates that this upload is a new version of an existing document'
|
||||
description="When present, indicates that this upload is a new version of an existing document"
|
||||
)
|
||||
|
||||
|
||||
@@ -29,19 +29,17 @@ class UploadDocuments(BaseModel):
|
||||
callback: CallbackLink
|
||||
server_context: Optional[str] = Field(
|
||||
description="A CDE controlled identifier recording the user's context on the CDE. For example which project "
|
||||
'and folder the user was on. If the client provides the `server_context` in subsequent calls then '
|
||||
'the CDE will attemp to load the UI at the same place.'
|
||||
"and folder the user was on. If the client provides the `server_context` in subsequent calls then "
|
||||
"the CDE will attemp to load the UI at the same place."
|
||||
)
|
||||
files: List[FileToUpload]
|
||||
|
||||
|
||||
class UploadFileDetail(BaseModel):
|
||||
size_in_bytes: int = Field(
|
||||
description='The uploaded file size'
|
||||
)
|
||||
size_in_bytes: int = Field(description="The uploaded file size")
|
||||
session_file_id: constr(min_length=1) = Field(
|
||||
description='This is a client provided id to differentiate between multiple files that are being uploaded in '
|
||||
'the same session'
|
||||
description="This is a client provided id to differentiate between multiple files that are being uploaded in "
|
||||
"the same session"
|
||||
)
|
||||
|
||||
|
||||
@@ -56,37 +54,31 @@ class SelectDocuments(BaseModel):
|
||||
callback: CallbackLink
|
||||
server_context: Optional[str] = Field(
|
||||
description="A CDE controlled identifier recording the user's context on the CDE. For example which project "
|
||||
'and folder the user was on. If the client provides the `server_context` in subsequent calls then '
|
||||
'the CDE will attemp to load the UI at the same place.'
|
||||
"and folder the user was on. If the client provides the `server_context` in subsequent calls then "
|
||||
"the CDE will attemp to load the UI at the same place."
|
||||
)
|
||||
supported_file_extensions: Optional[List[str]] = Field(
|
||||
description='The client may optionally provide an array of accepted file extensions that should be opened '
|
||||
'during this flow. The CDE server UI should make an attempt to only show files matching these '
|
||||
'extensions to the user for the download selection or help the user in selecting the desired '
|
||||
'files. However, the server does not have to guarantee that only files matching the extensions '
|
||||
'will be selected. The extensions here must contain the dot separator.',
|
||||
example=['.ifc', '.ifczip']
|
||||
description="The client may optionally provide an array of accepted file extensions that should be opened "
|
||||
"during this flow. The CDE server UI should make an attempt to only show files matching these "
|
||||
"extensions to the user for the download selection or help the user in selecting the desired "
|
||||
"files. However, the server does not have to guarantee that only files matching the extensions "
|
||||
"will be selected. The extensions here must contain the dot separator.",
|
||||
example=[".ifc", ".ifczip"],
|
||||
)
|
||||
|
||||
|
||||
class DataType(Enum):
|
||||
string = 'string'
|
||||
boolean = 'boolean'
|
||||
date_time = 'date-time'
|
||||
date = 'date'
|
||||
integer32 = 'integer32'
|
||||
integer64 = 'integer64'
|
||||
number = 'number'
|
||||
url = 'url'
|
||||
string = "string"
|
||||
boolean = "boolean"
|
||||
date_time = "date-time"
|
||||
date = "date"
|
||||
integer32 = "integer32"
|
||||
integer64 = "integer64"
|
||||
number = "number"
|
||||
url = "url"
|
||||
|
||||
|
||||
class DocumentMetadataEntry(BaseModel):
|
||||
name: constr(min_length=1) = Field(
|
||||
description='The name of the metadata property'
|
||||
)
|
||||
value: List[constr(min_length=1)] = Field(
|
||||
description='The value of the metadata property, can be a list'
|
||||
)
|
||||
data_type: DataType = Field(
|
||||
description='The data type of the items in the value array'
|
||||
)
|
||||
name: constr(min_length=1) = Field(description="The name of the metadata property")
|
||||
value: List[constr(min_length=1)] = Field(description="The value of the metadata property, can be a list")
|
||||
data_type: DataType = Field(description="The data type of the items in the value array")
|
||||
|
||||
@@ -13,20 +13,18 @@ from models.documents_common import DocumentVersion, LinkData
|
||||
|
||||
class DocumentUploadSessionInitialization(BaseModel):
|
||||
upload_ui_url: constr(min_length=1) = Field(
|
||||
description='A CDE UI URL for the client to open in a local browser. The user would enter document metadata '
|
||||
'directly in the CDE'
|
||||
)
|
||||
expires_in: int = Field(
|
||||
description='`upload_ui_url` expiry in seconds'
|
||||
description="A CDE UI URL for the client to open in a local browser. The user would enter document metadata "
|
||||
"directly in the CDE"
|
||||
)
|
||||
expires_in: int = Field(description="`upload_ui_url` expiry in seconds")
|
||||
max_size_in_bytes: int = Field(
|
||||
description='The maximum file size supported by the CDE. Attempts to upload a larger file will fail'
|
||||
description="The maximum file size supported by the CDE. Attempts to upload a larger file will fail"
|
||||
)
|
||||
|
||||
|
||||
class HttpMethod(Enum):
|
||||
POST = 'POST'
|
||||
PUT = 'PUT'
|
||||
POST = "POST"
|
||||
PUT = "PUT"
|
||||
|
||||
|
||||
class HeaderValue(BaseModel):
|
||||
@@ -40,12 +38,12 @@ class Headers(BaseModel):
|
||||
|
||||
class MultipartFormData(BaseModel):
|
||||
prefix: str = Field(
|
||||
description='This is a server provided value. Its value must be prefixed to the binary content body when '
|
||||
'uploading this part'
|
||||
description="This is a server provided value. Its value must be prefixed to the binary content body when "
|
||||
"uploading this part"
|
||||
)
|
||||
suffix: str = Field(
|
||||
description='This is a server provided value. Its value must be suffixed to the binary content body when '
|
||||
'uploading this part. Typically, this is the end boundary for a multipart/form-data request'
|
||||
description="This is a server provided value. Its value must be suffixed to the binary content body when "
|
||||
"uploading this part. Typically, this is the end boundary for a multipart/form-data request"
|
||||
)
|
||||
|
||||
|
||||
@@ -54,26 +52,22 @@ class UploadFilePartInstruction(BaseModel):
|
||||
http_method: HttpMethod
|
||||
additional_headers: Optional[Headers] = None
|
||||
include_authorization: Optional[bool] = Field(
|
||||
description='Whether or not to include the authorization request header in the file upload request. '
|
||||
'Including the authorization header with some cloud storage providers might fail the request'
|
||||
description="Whether or not to include the authorization request header in the file upload request. "
|
||||
"Including the authorization header with some cloud storage providers might fail the request"
|
||||
)
|
||||
multipart_form_data: Optional[MultipartFormData] = None
|
||||
content_range_start: int = Field(
|
||||
description='The inclusive, zero index based start for this part'
|
||||
)
|
||||
content_range_end: int = Field(
|
||||
description='The inclusive, zero index based end for this part'
|
||||
)
|
||||
content_range_start: int = Field(description="The inclusive, zero index based start for this part")
|
||||
content_range_end: int = Field(description="The inclusive, zero index based end for this part")
|
||||
|
||||
|
||||
class DocumentToUpload(BaseModel):
|
||||
session_file_id: constr(min_length=1) = Field(
|
||||
description='A client-provided identifier that allows matching the specification with the correct file on the '
|
||||
"user's machine"
|
||||
description="A client-provided identifier that allows matching the specification with the correct file on the "
|
||||
"user's machine"
|
||||
)
|
||||
upload_file_parts: List[UploadFilePartInstruction] = Field(
|
||||
description='An array of request specifications detailing how to split the file to parts and upload each part '
|
||||
'to the CDE'
|
||||
description="An array of request specifications detailing how to split the file to parts and upload each part "
|
||||
"to the CDE"
|
||||
# min_length=1,
|
||||
)
|
||||
upload_completion: LinkData
|
||||
@@ -83,8 +77,8 @@ class DocumentToUpload(BaseModel):
|
||||
class DocumentsToUpload(BaseModel):
|
||||
server_context: Optional[str] = Field(
|
||||
description="A CDE controlled identifier recording the user's context on the CDE. For example which project "
|
||||
'and folder the user was on. If the client provides the `server_context` in subsequent calls then '
|
||||
'the CDE will attemp to load the UI at the same place.'
|
||||
"and folder the user was on. If the client provides the `server_context` in subsequent calls then "
|
||||
"the CDE will attemp to load the UI at the same place."
|
||||
)
|
||||
documents_to_upload: Optional[List[DocumentToUpload]]
|
||||
|
||||
@@ -94,12 +88,10 @@ class DocumentsToUpload(BaseModel):
|
||||
|
||||
class DocumentDiscoverySessionInitialization(BaseModel):
|
||||
select_documents_url: constr(min_length=1) = Field(
|
||||
description='A CDE UI URL for the client to open in a local browser. The user would search and select '
|
||||
'documents directly in the CDE'
|
||||
)
|
||||
expires_in: int = Field(
|
||||
description='`select_documents_url` expiry in seconds'
|
||||
description="A CDE UI URL for the client to open in a local browser. The user would search and select "
|
||||
"documents directly in the CDE"
|
||||
)
|
||||
expires_in: int = Field(description="`select_documents_url` expiry in seconds")
|
||||
|
||||
|
||||
class DocumentsMarkedAsSelected(BaseModel):
|
||||
@@ -109,29 +101,25 @@ class DocumentsMarkedAsSelected(BaseModel):
|
||||
class SelectedDocuments(BaseModel):
|
||||
server_context: Optional[str] = Field(
|
||||
description="A CDE controlled identifier recording the user's context on the CDE. For example which project "
|
||||
'and folder the user was on. If the client provides the `server_context` in subsequent calls then '
|
||||
'the CDE will attemp to load the UI at the same place.'
|
||||
)
|
||||
documents: List[DocumentVersion] = Field(
|
||||
description='An array containing all the documents selected by the user'
|
||||
"and folder the user was on. If the client provides the `server_context` in subsequent calls then "
|
||||
"the CDE will attemp to load the UI at the same place."
|
||||
)
|
||||
documents: List[DocumentVersion] = Field(description="An array containing all the documents selected by the user")
|
||||
|
||||
|
||||
class DocumentMetadata(BaseModel):
|
||||
session_file_id: constr(min_length=1) = Field(
|
||||
description='This is a client provided id to differentiate between multiple files that are being uploaded in '
|
||||
'the same session'
|
||||
description="This is a client provided id to differentiate between multiple files that are being uploaded in "
|
||||
"the same session"
|
||||
)
|
||||
document_id: Optional[constr(min_length=1)] = Field(
|
||||
description='When present, indicates that this upload is a new version of an existing document'
|
||||
description="When present, indicates that this upload is a new version of an existing document"
|
||||
)
|
||||
version_number: constr(min_length=1) = Field(
|
||||
description='A human readable version number. This is not expected to be in any specific format across CDEs '
|
||||
'and may hold any value'
|
||||
)
|
||||
title: constr(min_length=1) = Field(
|
||||
description='A human readable code or identifier'
|
||||
description="A human readable version number. This is not expected to be in any specific format across CDEs "
|
||||
"and may hold any value"
|
||||
)
|
||||
title: constr(min_length=1) = Field(description="A human readable code or identifier")
|
||||
project: Optional[str]
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,41 +25,42 @@ class DOCDB(MyDB):
|
||||
|
||||
def document_node_to_model(self, document_node):
|
||||
document_json = self.node_to_json(document_node)
|
||||
document_json['creation_date'] = self.bcf_time(document_json['creation_date'])
|
||||
document_json['file_description'] = {
|
||||
'name': document_json.pop('name', '<no name>'),
|
||||
'size_in_bytes': document_json.pop('size_in_bytes', 0)
|
||||
document_json["creation_date"] = self.bcf_time(document_json["creation_date"])
|
||||
document_json["file_description"] = {
|
||||
"name": document_json.pop("name", "<no name>"),
|
||||
"size_in_bytes": document_json.pop("size_in_bytes", 0),
|
||||
}
|
||||
document_json['links'] = self.document_version_links(document_json)
|
||||
document_json["links"] = self.document_version_links(document_json)
|
||||
return DocumentVersion(**document_json)
|
||||
|
||||
def get_document(self, document_id, version_index=False):
|
||||
def get_document_work(tx) -> Union[Document, bool]:
|
||||
|
||||
if version_index is None or version_index is False or not isinstance(version_index, int):
|
||||
version_index_criteria = ''
|
||||
version_index_criteria = ""
|
||||
else:
|
||||
version_index_criteria = 'AND d.version_index = $version_index'
|
||||
version_index_criteria = "AND d.version_index = $version_index"
|
||||
|
||||
cypher = """
|
||||
cypher = (
|
||||
"""
|
||||
MATCH (d:Document)
|
||||
WHERE d.document_id = $document_id
|
||||
%s
|
||||
RETURN d AS document
|
||||
ORDER by d.version_index DESC
|
||||
LIMIT 1
|
||||
""" % version_index_criteria
|
||||
"""
|
||||
% version_index_criteria
|
||||
)
|
||||
|
||||
result = tx.run(cypher,
|
||||
document_id=document_id,
|
||||
version_index=version_index)
|
||||
result = tx.run(cypher, document_id=document_id, version_index=version_index)
|
||||
|
||||
first = result.single()
|
||||
if first is None:
|
||||
print('There were no such document version.')
|
||||
print("There were no such document version.")
|
||||
return False
|
||||
|
||||
document_node = first.get('document')
|
||||
document_node = first.get("document")
|
||||
return self.document_node_to_model(document_node)
|
||||
|
||||
with self.driver.session() as session:
|
||||
@@ -88,21 +89,23 @@ class DOCDB(MyDB):
|
||||
d.name = $name,
|
||||
d.size_in_bytes = $size_in_bytes
|
||||
"""
|
||||
result = tx.run(cypher,
|
||||
selection_session=selection_session,
|
||||
project=project,
|
||||
document_id=document_version.document_id,
|
||||
session_file_id=document_version.session_file_id,
|
||||
version_index=document_version.version_index,
|
||||
version_number=document_version.version_number,
|
||||
creation_date=document_version.creation_date,
|
||||
title=document_version.title,
|
||||
original_file_name=document_version.original_file_name,
|
||||
file_ending=document_version.file_ending,
|
||||
mime_type=document_version.mime_type,
|
||||
file_type=document_version.file_type,
|
||||
name=document_version.file_description.name,
|
||||
size_in_bytes=document_version.file_description.size_in_bytes)
|
||||
result = tx.run(
|
||||
cypher,
|
||||
selection_session=selection_session,
|
||||
project=project,
|
||||
document_id=document_version.document_id,
|
||||
session_file_id=document_version.session_file_id,
|
||||
version_index=document_version.version_index,
|
||||
version_number=document_version.version_number,
|
||||
creation_date=document_version.creation_date,
|
||||
title=document_version.title,
|
||||
original_file_name=document_version.original_file_name,
|
||||
file_ending=document_version.file_ending,
|
||||
mime_type=document_version.mime_type,
|
||||
file_type=document_version.file_type,
|
||||
name=document_version.file_description.name,
|
||||
size_in_bytes=document_version.file_description.size_in_bytes,
|
||||
)
|
||||
|
||||
summary = result.consume()
|
||||
if summary.counters.nodes_created < 1:
|
||||
@@ -122,10 +125,10 @@ class DOCDB(MyDB):
|
||||
|
||||
first = result.single()
|
||||
if first is None:
|
||||
print('There were no such document version.')
|
||||
print("There were no such document version.")
|
||||
return False
|
||||
|
||||
document_node = first.get('document')
|
||||
document_node = first.get("document")
|
||||
return self.document_node_to_model(document_node)
|
||||
|
||||
with self.driver.session() as session:
|
||||
@@ -134,20 +137,21 @@ class DOCDB(MyDB):
|
||||
|
||||
def create_ifc_graph_for_document(self, document_id):
|
||||
document = self.get_document(document_id)
|
||||
my_ifc_file = ifcopenshell.open('./data/documents/' + document.file_description.name)
|
||||
my_graph = Graph(os.environ['NEO4J_URI'], auth=(os.environ['NEO4J_USER'], os.environ['NEO4J_INITIAL_PASSWORD']))
|
||||
my_ifc_file = ifcopenshell.open("./data/documents/" + document.file_description.name)
|
||||
my_graph = Graph(os.environ["NEO4J_URI"], auth=(os.environ["NEO4J_USER"], os.environ["NEO4J_INITIAL_PASSWORD"]))
|
||||
create_full_graph(my_graph, my_ifc_file)
|
||||
|
||||
# ---- UPLOAD FUNCTIONS ----
|
||||
|
||||
def post_upload_documents(self, upload_documents: UploadDocuments,
|
||||
current_user: User) -> DocumentUploadSessionInitialization:
|
||||
def post_upload_documents(
|
||||
self, upload_documents: UploadDocuments, current_user: User
|
||||
) -> DocumentUploadSessionInitialization:
|
||||
def post_upload_documents_work(tx) -> DocumentUploadSessionInitialization:
|
||||
|
||||
session_uuid = str(uuid4())
|
||||
session_callback_timedelta = int(upload_documents.callback.expires_in)
|
||||
session_url_validity_timedelta = 10 + int(os.environ['SESSION_URL_VALIDITY_SECONDS'])
|
||||
if not hasattr(upload_documents, 'server_context') or not upload_documents.server_context:
|
||||
session_url_validity_timedelta = 10 + int(os.environ["SESSION_URL_VALIDITY_SECONDS"])
|
||||
if not hasattr(upload_documents, "server_context") or not upload_documents.server_context:
|
||||
upload_documents.server_context = False
|
||||
|
||||
cypher = """
|
||||
@@ -165,13 +169,15 @@ class DOCDB(MyDB):
|
||||
s.session_callback_timedelta = $session_callback_timedelta
|
||||
"""
|
||||
|
||||
result = tx.run(cypher,
|
||||
username=current_user.username,
|
||||
session_callback_timedelta=session_callback_timedelta,
|
||||
session_url_timedelta=session_url_validity_timedelta,
|
||||
server_context=upload_documents.server_context,
|
||||
upload_session=session_uuid,
|
||||
callback=upload_documents.callback.url)
|
||||
result = tx.run(
|
||||
cypher,
|
||||
username=current_user.username,
|
||||
session_callback_timedelta=session_callback_timedelta,
|
||||
session_url_timedelta=session_url_validity_timedelta,
|
||||
server_context=upload_documents.server_context,
|
||||
upload_session=session_uuid,
|
||||
callback=upload_documents.callback.url,
|
||||
)
|
||||
|
||||
summary = result.consume()
|
||||
if summary.counters.nodes_created < 2:
|
||||
@@ -197,54 +203,60 @@ class DOCDB(MyDB):
|
||||
d.file_type = $file_type
|
||||
"""
|
||||
|
||||
if not hasattr(file, 'document_id') or not file.document_id:
|
||||
if not hasattr(file, "document_id") or not file.document_id:
|
||||
# When document_id is present, this indicates that
|
||||
# this upload is a new version of an existing document.
|
||||
# When not present, we create a new uuid as new document_id.
|
||||
file.document_id = doc_db.new_uuid()
|
||||
|
||||
if file.file_name.lower().endswith(tuple(file_types)):
|
||||
file_ending = file.file_name.split('.')[-1].lower()
|
||||
name = file.document_id + '.' + file_ending
|
||||
file_ending = file.file_name.split(".")[-1].lower()
|
||||
name = file.document_id + "." + file_ending
|
||||
else:
|
||||
file_ending = ''
|
||||
file_ending = ""
|
||||
name = file.document_id
|
||||
|
||||
print('File ending: ', file_ending)
|
||||
print("File ending: ", file_ending)
|
||||
|
||||
mime_type = ''
|
||||
file_type = ''
|
||||
mime_type = ""
|
||||
file_type = ""
|
||||
|
||||
if hasattr(file_types, file_ending):
|
||||
|
||||
print('We have this file ending in dict: ', file_ending)
|
||||
print("We have this file ending in dict: ", file_ending)
|
||||
|
||||
mime_type = file_types[file_ending]['mime_type']
|
||||
file_type = file_types[file_ending]['file_type']
|
||||
mime_type = file_types[file_ending]["mime_type"]
|
||||
file_type = file_types[file_ending]["file_type"]
|
||||
|
||||
result = tx.run(cypher,
|
||||
username=current_user.username,
|
||||
upload_session=session_uuid,
|
||||
session_callback_timedelta=session_callback_timedelta,
|
||||
original_file_name=file.file_name,
|
||||
name=name,
|
||||
session_file_id=file.session_file_id,
|
||||
document_id=file.document_id,
|
||||
creation_date=doc_db.timestamp(),
|
||||
file_ending=file_ending,
|
||||
mime_type=mime_type,
|
||||
file_type=file_type)
|
||||
result = tx.run(
|
||||
cypher,
|
||||
username=current_user.username,
|
||||
upload_session=session_uuid,
|
||||
session_callback_timedelta=session_callback_timedelta,
|
||||
original_file_name=file.file_name,
|
||||
name=name,
|
||||
session_file_id=file.session_file_id,
|
||||
document_id=file.document_id,
|
||||
creation_date=doc_db.timestamp(),
|
||||
file_ending=file_ending,
|
||||
mime_type=mime_type,
|
||||
file_type=file_type,
|
||||
)
|
||||
|
||||
summary = result.consume()
|
||||
if summary.counters.nodes_created < 1:
|
||||
raise HTTPException(status_code=400, detail="Document node was not created.")
|
||||
|
||||
session_init = DocumentUploadSessionInitialization(**{
|
||||
'upload_ui_url': os.environ['KONTROLL_BASE_URL'] + 'documents/1.0/' \
|
||||
+ "document-upload?upload_session=" + session_uuid,
|
||||
'expires_in': os.environ['SESSION_URL_VALIDITY_SECONDS'],
|
||||
'max_size_in_bytes': os.environ['SESSION_MAX_FILE_SIZE_BYTES'],
|
||||
})
|
||||
session_init = DocumentUploadSessionInitialization(
|
||||
**{
|
||||
"upload_ui_url": os.environ["KONTROLL_BASE_URL"]
|
||||
+ "documents/1.0/"
|
||||
+ "document-upload?upload_session="
|
||||
+ session_uuid,
|
||||
"expires_in": os.environ["SESSION_URL_VALIDITY_SECONDS"],
|
||||
"max_size_in_bytes": os.environ["SESSION_MAX_FILE_SIZE_BYTES"],
|
||||
}
|
||||
)
|
||||
|
||||
return session_init
|
||||
|
||||
@@ -261,15 +273,14 @@ class DOCDB(MyDB):
|
||||
WHERE us.upload_session = $upload_session
|
||||
RETURN d AS document
|
||||
"""
|
||||
results = tx.run(cypher,
|
||||
upload_session=str(upload_session))
|
||||
results = tx.run(cypher, upload_session=str(upload_session))
|
||||
document_list = list()
|
||||
for result in results:
|
||||
document_json = self.node_to_json(result.get('document'))
|
||||
document_json = self.node_to_json(result.get("document"))
|
||||
file_to_upload = {
|
||||
'file_name': document_json['original_file_name'],
|
||||
'session_file_id': document_json['session_file_id'],
|
||||
'document_id': document_json['document_id']
|
||||
"file_name": document_json["original_file_name"],
|
||||
"session_file_id": document_json["session_file_id"],
|
||||
"document_id": document_json["document_id"],
|
||||
}
|
||||
document_model = FileToUpload(**file_to_upload)
|
||||
document_list.append(document_model)
|
||||
@@ -280,16 +291,15 @@ class DOCDB(MyDB):
|
||||
WHERE us.upload_session = $upload_session
|
||||
RETURN p AS project
|
||||
"""
|
||||
results = tx.run(cypher,
|
||||
upload_session=str(upload_session))
|
||||
results = tx.run(cypher, upload_session=str(upload_session))
|
||||
project_list = list()
|
||||
for result in results:
|
||||
project_json = self.node_to_json(result.get('project'))
|
||||
project_json = self.node_to_json(result.get("project"))
|
||||
project = {
|
||||
'project_id': project_json['project_id'],
|
||||
'name': project_json['name'],
|
||||
"project_id": project_json["project_id"],
|
||||
"name": project_json["name"],
|
||||
}
|
||||
print('Project: ', project)
|
||||
print("Project: ", project)
|
||||
project_list.append(project)
|
||||
|
||||
# to get the user and some session data
|
||||
@@ -302,31 +312,30 @@ class DOCDB(MyDB):
|
||||
us.session_callback_timedelta AS session_callback_timedelta,
|
||||
u AS user
|
||||
"""
|
||||
result = tx.run(cypher,
|
||||
upload_session=str(upload_session))
|
||||
result = tx.run(cypher, upload_session=str(upload_session))
|
||||
|
||||
first = result.single()
|
||||
if first is None:
|
||||
raise HTTPException(status_code=401, detail="No session or link.")
|
||||
|
||||
user_node = first.get('user')
|
||||
user_node = first.get("user")
|
||||
user_dict = self.node_to_json(user_node)
|
||||
|
||||
for_upload_documents_dict = dict()
|
||||
for_upload_documents_dict['server_context'] = first.get('server_context')
|
||||
for_upload_documents_dict["server_context"] = first.get("server_context")
|
||||
|
||||
callback_link = dict()
|
||||
callback_link['url'] = first.get('callback')
|
||||
callback_link['expires_in'] = first.get('session_callback_timedelta')
|
||||
callback_link["url"] = first.get("callback")
|
||||
callback_link["expires_in"] = first.get("session_callback_timedelta")
|
||||
|
||||
for_upload_documents_dict['callback'] = callback_link
|
||||
for_upload_documents_dict['documents'] = document_list
|
||||
print('Project list: ', project_list)
|
||||
for_upload_documents_dict["callback"] = callback_link
|
||||
for_upload_documents_dict["documents"] = document_list
|
||||
print("Project list: ", project_list)
|
||||
|
||||
for_upload_documents_dict['projects'] = project_list
|
||||
for_upload_documents_dict['current_user'] = user_dict
|
||||
for_upload_documents_dict["projects"] = project_list
|
||||
for_upload_documents_dict["current_user"] = user_dict
|
||||
|
||||
print('Documents list:', document_list)
|
||||
print("Documents list:", document_list)
|
||||
|
||||
for_upload_documents_model = DataForUploadDocuments(**for_upload_documents_dict)
|
||||
|
||||
@@ -348,14 +357,16 @@ class DOCDB(MyDB):
|
||||
d.title = $title,
|
||||
d.project = $project
|
||||
"""
|
||||
result = tx.run(cypher,
|
||||
username=username,
|
||||
upload_session=upload_session,
|
||||
session_file_id=document.session_file_id,
|
||||
version_number=document.version_number,
|
||||
version_index=False,
|
||||
title=document.title,
|
||||
project=document.project)
|
||||
result = tx.run(
|
||||
cypher,
|
||||
username=username,
|
||||
upload_session=upload_session,
|
||||
session_file_id=document.session_file_id,
|
||||
version_number=document.version_number,
|
||||
version_index=False,
|
||||
title=document.title,
|
||||
project=document.project,
|
||||
)
|
||||
|
||||
summary = result.consume()
|
||||
if summary.counters.properties_set < 4:
|
||||
@@ -376,11 +387,13 @@ class DOCDB(MyDB):
|
||||
SET
|
||||
d.size_in_bytes = $size_in_bytes
|
||||
"""
|
||||
result = tx.run(cypher,
|
||||
username=user.username,
|
||||
upload_session=upload_session,
|
||||
session_file_id=document.session_file_id,
|
||||
size_in_bytes=document.size_in_bytes)
|
||||
result = tx.run(
|
||||
cypher,
|
||||
username=user.username,
|
||||
upload_session=upload_session,
|
||||
session_file_id=document.session_file_id,
|
||||
size_in_bytes=document.size_in_bytes,
|
||||
)
|
||||
summary = result.consume()
|
||||
if summary.counters.properties_set < 1:
|
||||
raise HTTPException(status_code=400, detail="Property was not set.")
|
||||
@@ -390,18 +403,20 @@ class DOCDB(MyDB):
|
||||
session.execute_write(update_file_size_work)
|
||||
|
||||
# link creation
|
||||
base_url = os.environ['KONTROLL_BASE_URL'] + 'documents/1.0/'
|
||||
upload_session_url = '?upload_session=' + upload_session
|
||||
upload_complete_url = base_url + 'upload-completion' + upload_session_url
|
||||
upload_cancellation_url = base_url + 'upload-cancellation' + upload_session_url
|
||||
upload_completion = LinkData(**{'url': upload_complete_url})
|
||||
upload_cancellation = LinkData(**{'url': upload_cancellation_url})
|
||||
document_to_upload_model = DocumentToUpload(**{
|
||||
'session_file_id': document.session_file_id,
|
||||
'upload_file_parts': list(),
|
||||
'upload_completion': upload_completion,
|
||||
'upload_cancellation': upload_cancellation
|
||||
})
|
||||
base_url = os.environ["KONTROLL_BASE_URL"] + "documents/1.0/"
|
||||
upload_session_url = "?upload_session=" + upload_session
|
||||
upload_complete_url = base_url + "upload-completion" + upload_session_url
|
||||
upload_cancellation_url = base_url + "upload-cancellation" + upload_session_url
|
||||
upload_completion = LinkData(**{"url": upload_complete_url})
|
||||
upload_cancellation = LinkData(**{"url": upload_cancellation_url})
|
||||
document_to_upload_model = DocumentToUpload(
|
||||
**{
|
||||
"session_file_id": document.session_file_id,
|
||||
"upload_file_parts": list(),
|
||||
"upload_completion": upload_completion,
|
||||
"upload_cancellation": upload_cancellation,
|
||||
}
|
||||
)
|
||||
|
||||
def add_part_work(tx) -> UUID:
|
||||
cypher = """
|
||||
@@ -416,15 +431,17 @@ class DOCDB(MyDB):
|
||||
p.content_range_end = $content_range_end,
|
||||
p.content_length = $content_length
|
||||
"""
|
||||
result = tx.run(cypher,
|
||||
username=user.username,
|
||||
upload_session=upload_session,
|
||||
session_file_id=document.session_file_id,
|
||||
part_number=part_number,
|
||||
part_uuid=str(upload_part_uuid),
|
||||
content_range_start=content_range_start,
|
||||
content_range_end=content_range_end,
|
||||
content_length=content_length)
|
||||
result = tx.run(
|
||||
cypher,
|
||||
username=user.username,
|
||||
upload_session=upload_session,
|
||||
session_file_id=document.session_file_id,
|
||||
part_number=part_number,
|
||||
part_uuid=str(upload_part_uuid),
|
||||
content_range_start=content_range_start,
|
||||
content_range_end=content_range_end,
|
||||
content_length=content_length,
|
||||
)
|
||||
|
||||
summary = result.consume()
|
||||
if summary.counters.nodes_created != 1:
|
||||
@@ -432,7 +449,7 @@ class DOCDB(MyDB):
|
||||
return upload_part_uuid
|
||||
|
||||
# calculate the number of file parts to send
|
||||
number_of_parts = math.ceil(int(document.size_in_bytes) / int(os.environ['SESSION_MAX_FILE_SIZE_BYTES']))
|
||||
number_of_parts = math.ceil(int(document.size_in_bytes) / int(os.environ["SESSION_MAX_FILE_SIZE_BYTES"]))
|
||||
part_length = math.ceil(int(document.size_in_bytes) / number_of_parts)
|
||||
for part_number in range(number_of_parts):
|
||||
content_range_start = part_number * part_length
|
||||
@@ -441,23 +458,18 @@ class DOCDB(MyDB):
|
||||
content_range_end = document.size_in_bytes - 1
|
||||
content_length = content_range_end - content_range_start + 1
|
||||
upload_part_uuid = uuid4()
|
||||
upload_part_url = 'upload-part/' + str(upload_part_uuid)
|
||||
additional_headers = {
|
||||
'values': [
|
||||
{
|
||||
'name': 'Content-Length',
|
||||
'value': content_length
|
||||
}
|
||||
]
|
||||
}
|
||||
part_instruction = UploadFilePartInstruction(**{
|
||||
'url': base_url + upload_part_url,
|
||||
'http_method': 'POST',
|
||||
'additional_headers': additional_headers,
|
||||
'include_authorization': True,
|
||||
'content_range_start': content_range_start,
|
||||
'content_range_end': content_range_end
|
||||
})
|
||||
upload_part_url = "upload-part/" + str(upload_part_uuid)
|
||||
additional_headers = {"values": [{"name": "Content-Length", "value": content_length}]}
|
||||
part_instruction = UploadFilePartInstruction(
|
||||
**{
|
||||
"url": base_url + upload_part_url,
|
||||
"http_method": "POST",
|
||||
"additional_headers": additional_headers,
|
||||
"include_authorization": True,
|
||||
"content_range_start": content_range_start,
|
||||
"content_range_end": content_range_end,
|
||||
}
|
||||
)
|
||||
|
||||
with self.driver.session() as session:
|
||||
added_part = session.execute_write(add_part_work)
|
||||
@@ -476,19 +488,17 @@ class DOCDB(MyDB):
|
||||
RETURN d AS document
|
||||
"""
|
||||
|
||||
result = tx.run(cypher,
|
||||
username=current_user.username,
|
||||
part_id=part_id)
|
||||
result = tx.run(cypher, username=current_user.username, part_id=part_id)
|
||||
|
||||
first = result.single()
|
||||
if first is None:
|
||||
print('There were no parts in graph!')
|
||||
print("There were no parts in graph!")
|
||||
return False
|
||||
|
||||
document_node = first.get('document')
|
||||
document_node = first.get("document")
|
||||
document = self.document_node_to_model(document_node)
|
||||
|
||||
print('User had this part ' + part_id + ' in document id: ' + document.document_id)
|
||||
print("User had this part " + part_id + " in document id: " + document.document_id)
|
||||
return document
|
||||
|
||||
with self.driver.session() as session:
|
||||
@@ -503,9 +513,7 @@ class DOCDB(MyDB):
|
||||
SET p.uploaded = True
|
||||
"""
|
||||
|
||||
result = tx.run(cypher,
|
||||
username=current_user.username,
|
||||
part_id=part_id)
|
||||
result = tx.run(cypher, username=current_user.username, part_id=part_id)
|
||||
|
||||
summary = result.consume()
|
||||
if summary.counters.properties_set < 1:
|
||||
@@ -526,26 +534,24 @@ class DOCDB(MyDB):
|
||||
RETURN count(p) as parts
|
||||
"""
|
||||
|
||||
result = tx.run(cypher,
|
||||
username=current_user.username,
|
||||
upload_session=upload_session)
|
||||
result = tx.run(cypher, username=current_user.username, upload_session=upload_session)
|
||||
|
||||
first = result.single()
|
||||
if first is None:
|
||||
return False
|
||||
|
||||
number_of_parts = first.get('parts')
|
||||
number_of_parts = first.get("parts")
|
||||
|
||||
print('There are number of parts not uploaded: ', number_of_parts)
|
||||
print("There are number of parts not uploaded: ", number_of_parts)
|
||||
|
||||
if number_of_parts > 0:
|
||||
raise HTTPException(status_code=400, detail="All parts not uploaded.")
|
||||
else:
|
||||
return True
|
||||
|
||||
with self.driver.session() as session:
|
||||
return session.execute_read(check_uploaded_parts_work)
|
||||
|
||||
|
||||
def retrieve_uploaded_parts(self, upload_session: str, current_user: User) -> list:
|
||||
def retrieve_uploaded_parts_work(tx) -> list:
|
||||
cypher = """
|
||||
@@ -556,14 +562,12 @@ class DOCDB(MyDB):
|
||||
RETURN p as part
|
||||
ORDER BY part.number
|
||||
"""
|
||||
results = tx.run(cypher,
|
||||
username=current_user.username,
|
||||
upload_session=upload_session)
|
||||
results = tx.run(cypher, username=current_user.username, upload_session=upload_session)
|
||||
|
||||
parts_list = list()
|
||||
for result in results:
|
||||
part_json = self.node_to_json(result.get("part"))
|
||||
parts_list.append(part_json['uuid'])
|
||||
parts_list.append(part_json["uuid"])
|
||||
return parts_list
|
||||
|
||||
with self.driver.session() as session:
|
||||
@@ -579,12 +583,10 @@ class DOCDB(MyDB):
|
||||
RETURN d AS document
|
||||
"""
|
||||
|
||||
result = tx.run(cypher,
|
||||
username=current_user.username,
|
||||
upload_session=upload_session)
|
||||
result = tx.run(cypher, username=current_user.username, upload_session=upload_session)
|
||||
|
||||
first = result.single()
|
||||
document_node = first.get('document')
|
||||
document_node = first.get("document")
|
||||
return self.document_node_to_model(document_node)
|
||||
|
||||
with self.driver.session() as session:
|
||||
@@ -604,10 +606,7 @@ class DOCDB(MyDB):
|
||||
DELETE r2
|
||||
CREATE (proj)-[r4:CONTAINS]->(d)
|
||||
"""
|
||||
result = tx.run(cypher,
|
||||
username=current_user.username,
|
||||
upload_session=upload_session,
|
||||
project=project)
|
||||
result = tx.run(cypher, username=current_user.username, upload_session=upload_session, project=project)
|
||||
|
||||
summary = result.consume()
|
||||
if summary.counters.nodes_deleted < 1:
|
||||
@@ -627,15 +626,13 @@ class DOCDB(MyDB):
|
||||
AND us.upload_session = $upload_session
|
||||
RETURN d as document
|
||||
"""
|
||||
result = tx.run(cypher,
|
||||
username=current_user.username,
|
||||
upload_session=upload_session)
|
||||
result = tx.run(cypher, username=current_user.username, upload_session=upload_session)
|
||||
|
||||
first = result.single()
|
||||
if first is None:
|
||||
return False
|
||||
|
||||
document_node = first.get('document')
|
||||
document_node = first.get("document")
|
||||
return self.document_node_to_model(document_node)
|
||||
|
||||
def upload_cancellation_work(tx) -> bool:
|
||||
@@ -645,9 +642,7 @@ class DOCDB(MyDB):
|
||||
AND us.upload_session = $upload_session
|
||||
DETACH DELETE us, d, p
|
||||
"""
|
||||
result = tx.run(cypher,
|
||||
username=current_user.username,
|
||||
upload_session=upload_session)
|
||||
result = tx.run(cypher, username=current_user.username, upload_session=upload_session)
|
||||
|
||||
summary = result.consume()
|
||||
if summary.counters.nodes_deleted < 1:
|
||||
@@ -662,14 +657,15 @@ class DOCDB(MyDB):
|
||||
|
||||
# ---- DOWNLOAD FUNCTIONS ----
|
||||
|
||||
def post_select_documents(self, select_documents: SelectDocuments,
|
||||
current_user: User) -> DocumentDiscoverySessionInitialization:
|
||||
def post_select_documents(
|
||||
self, select_documents: SelectDocuments, current_user: User
|
||||
) -> DocumentDiscoverySessionInitialization:
|
||||
def post_select_documents_work(tx) -> DocumentDiscoverySessionInitialization:
|
||||
|
||||
session_uuid = str(uuid4())
|
||||
session_callback_timedelta = int(select_documents.callback.expires_in)
|
||||
session_url_validity_timedelta = 10 + int(os.environ['SESSION_URL_VALIDITY_SECONDS'])
|
||||
if not hasattr(select_documents, 'server_context') or not select_documents.server_context:
|
||||
session_url_validity_timedelta = 10 + int(os.environ["SESSION_URL_VALIDITY_SECONDS"])
|
||||
if not hasattr(select_documents, "server_context") or not select_documents.server_context:
|
||||
select_documents.server_context = str(uuid4())
|
||||
|
||||
cypher = """
|
||||
@@ -687,22 +683,28 @@ class DOCDB(MyDB):
|
||||
s.session_callback_timedelta = $session_callback_timedelta
|
||||
"""
|
||||
|
||||
result = tx.run(cypher,
|
||||
username=current_user.username,
|
||||
session_callback_timedelta=session_callback_timedelta,
|
||||
session_url_timedelta=session_url_validity_timedelta,
|
||||
server_context=select_documents.server_context,
|
||||
selection_session=str(session_uuid),
|
||||
callback=select_documents.callback.url)
|
||||
result = tx.run(
|
||||
cypher,
|
||||
username=current_user.username,
|
||||
session_callback_timedelta=session_callback_timedelta,
|
||||
session_url_timedelta=session_url_validity_timedelta,
|
||||
server_context=select_documents.server_context,
|
||||
selection_session=str(session_uuid),
|
||||
callback=select_documents.callback.url,
|
||||
)
|
||||
|
||||
summary = result.consume()
|
||||
if summary.counters.nodes_created < 2:
|
||||
raise HTTPException(status_code=400, detail="Session or link node was not created.")
|
||||
|
||||
session_init_dict = dict()
|
||||
session_init_dict['select_documents_url'] = os.environ['KONTROLL_BASE_URL'] + 'documents/1.0/' \
|
||||
+ "document-selection?selection_session=" + session_uuid
|
||||
session_init_dict['expires_in'] = os.environ['SESSION_URL_VALIDITY_SECONDS']
|
||||
session_init_dict["select_documents_url"] = (
|
||||
os.environ["KONTROLL_BASE_URL"]
|
||||
+ "documents/1.0/"
|
||||
+ "document-selection?selection_session="
|
||||
+ session_uuid
|
||||
)
|
||||
session_init_dict["expires_in"] = os.environ["SESSION_URL_VALIDITY_SECONDS"]
|
||||
session_init_model = DocumentDiscoverySessionInitialization(**session_init_dict)
|
||||
|
||||
return session_init_model
|
||||
@@ -719,13 +721,12 @@ class DOCDB(MyDB):
|
||||
RETURN p AS project
|
||||
ORDER BY project.name
|
||||
"""
|
||||
project_results = tx.run(cypher,
|
||||
selection_session=str(selection_session))
|
||||
project_results = tx.run(cypher, selection_session=str(selection_session))
|
||||
|
||||
project_list = list()
|
||||
for project_result in project_results:
|
||||
project_json = self.node_to_json(project_result.get('project'))
|
||||
project_json['documents'] = list()
|
||||
project_json = self.node_to_json(project_result.get("project"))
|
||||
project_json["documents"] = list()
|
||||
project_model = Project(**project_json)
|
||||
|
||||
# to get the documents
|
||||
@@ -736,12 +737,12 @@ class DOCDB(MyDB):
|
||||
RETURN d AS document
|
||||
ORDER BY d.title, d.version_index
|
||||
"""
|
||||
document_results = tx.run(cypher,
|
||||
selection_session=str(selection_session),
|
||||
project_id=str(project_model.project_id))
|
||||
document_results = tx.run(
|
||||
cypher, selection_session=str(selection_session), project_id=str(project_model.project_id)
|
||||
)
|
||||
|
||||
for document_result in document_results:
|
||||
document_node = document_result.get('document')
|
||||
document_node = document_result.get("document")
|
||||
document_model = self.document_node_to_model(document_node)
|
||||
project_model.documents.append(document_model)
|
||||
|
||||
@@ -758,8 +759,7 @@ class DOCDB(MyDB):
|
||||
u AS user
|
||||
"""
|
||||
|
||||
result = tx.run(cypher,
|
||||
selection_session=str(selection_session))
|
||||
result = tx.run(cypher, selection_session=str(selection_session))
|
||||
|
||||
first = result.single()
|
||||
if first is None:
|
||||
@@ -769,26 +769,28 @@ class DOCDB(MyDB):
|
||||
user_dict = self.node_to_json(user_node)
|
||||
|
||||
for_document_selection_dict = dict()
|
||||
for_document_selection_dict['server_context'] = first.get('server_context')
|
||||
for_document_selection_dict["server_context"] = first.get("server_context")
|
||||
|
||||
callback_link = dict()
|
||||
callback_link['url'] = first.get('callback')
|
||||
callback_link['expires_in'] = first.get('session_callback_timedelta')
|
||||
callback_link["url"] = first.get("callback")
|
||||
callback_link["expires_in"] = first.get("session_callback_timedelta")
|
||||
|
||||
for_document_selection_dict['callback'] = callback_link
|
||||
for_document_selection_dict['projects'] = project_list
|
||||
for_document_selection_dict['current_user'] = user_dict
|
||||
for_document_selection_dict["callback"] = callback_link
|
||||
for_document_selection_dict["projects"] = project_list
|
||||
for_document_selection_dict["current_user"] = user_dict
|
||||
|
||||
for_document_selection_model = DataForDocumentSelection(**for_document_selection_dict)
|
||||
|
||||
print('Data for document selection: ', for_document_selection_dict)
|
||||
print("Data for document selection: ", for_document_selection_dict)
|
||||
|
||||
return for_document_selection_model
|
||||
|
||||
with self.driver.session() as session:
|
||||
return session.execute_read(get_data_for_document_selection_work)
|
||||
|
||||
def post_mark_documents_as_selected(self, all_documents: list, selection_session: UUID) -> DocumentsMarkedAsSelected:
|
||||
def post_mark_documents_as_selected(
|
||||
self, all_documents: list, selection_session: UUID
|
||||
) -> DocumentsMarkedAsSelected:
|
||||
|
||||
def mark_documents_as_selected_work(tx) -> DocumentsMarkedAsSelected:
|
||||
cypher = """
|
||||
@@ -798,12 +800,10 @@ class DOCDB(MyDB):
|
||||
MERGE (ss)-[r5:SELECTED]->(d)
|
||||
"""
|
||||
|
||||
selected_documents_model = DocumentsMarkedAsSelected(**{'documents': list()})
|
||||
selected_documents_model = DocumentsMarkedAsSelected(**{"documents": list()})
|
||||
|
||||
for document in all_documents:
|
||||
result = tx.run(cypher,
|
||||
selection_session=str(selection_session),
|
||||
document_id=str(document))
|
||||
result = tx.run(cypher, selection_session=str(selection_session), document_id=str(document))
|
||||
|
||||
summary = result.consume()
|
||||
|
||||
@@ -817,16 +817,20 @@ class DOCDB(MyDB):
|
||||
|
||||
@staticmethod
|
||||
def document_version_links(document_json):
|
||||
document_id = document_json['document_id']
|
||||
version_index = document_json['version_index']
|
||||
base = os.environ['KONTROLL_BASE_URL'] + "documents/1.0/document/" + document_id + "/version/" + str(version_index)
|
||||
return DocumentVersionLinks(**{
|
||||
'document_version': LinkData(**{'url': base}),
|
||||
'document_version_metadata': LinkData(**{'url': base + "/metadata"}),
|
||||
'document_version_download': LinkData(**{'url': base + "/download"}),
|
||||
'document_versions': LinkData(**{'url': base + "/versions"}),
|
||||
'document_details': LinkData(**{'url': base + "/details"})
|
||||
})
|
||||
document_id = document_json["document_id"]
|
||||
version_index = document_json["version_index"]
|
||||
base = (
|
||||
os.environ["KONTROLL_BASE_URL"] + "documents/1.0/document/" + document_id + "/version/" + str(version_index)
|
||||
)
|
||||
return DocumentVersionLinks(
|
||||
**{
|
||||
"document_version": LinkData(**{"url": base}),
|
||||
"document_version_metadata": LinkData(**{"url": base + "/metadata"}),
|
||||
"document_version_download": LinkData(**{"url": base + "/download"}),
|
||||
"document_versions": LinkData(**{"url": base + "/versions"}),
|
||||
"document_details": LinkData(**{"url": base + "/details"}),
|
||||
}
|
||||
)
|
||||
|
||||
def get_download_instructions(self, session_id: UUID, server_context: str, current_user: User) -> SelectedDocuments:
|
||||
def get_download_instructions_work(tx) -> SelectedDocuments:
|
||||
@@ -839,18 +843,16 @@ class DOCDB(MyDB):
|
||||
|
||||
document_list = list()
|
||||
for result in results:
|
||||
document_node = result.get('document')
|
||||
document_node = result.get("document")
|
||||
document_model = self.document_node_to_model(document_node)
|
||||
document_list.append(document_model)
|
||||
|
||||
selected_documents = SelectedDocuments(**{'server_context': server_context,
|
||||
'documents': document_list})
|
||||
selected_documents = SelectedDocuments(**{"server_context": server_context, "documents": document_list})
|
||||
return selected_documents
|
||||
|
||||
with self.driver.session() as session:
|
||||
return session.execute_read(get_download_instructions_work)
|
||||
|
||||
|
||||
def get_upload_documents(self, upload_session: UUID, current_user: User) -> UploadDocuments:
|
||||
def get_upload_documents_work(tx) -> UploadDocuments:
|
||||
cypher = """
|
||||
@@ -860,12 +862,10 @@ class DOCDB(MyDB):
|
||||
AND us.upload_session = $upload_session
|
||||
RETURN d AS document
|
||||
"""
|
||||
results = tx.run(cypher,
|
||||
username=current_user.username,
|
||||
upload_session=upload_session)
|
||||
results = tx.run(cypher, username=current_user.username, upload_session=upload_session)
|
||||
file_list = list()
|
||||
for result in results:
|
||||
file_json = self.node_to_json(result.get('document'))
|
||||
file_json = self.node_to_json(result.get("document"))
|
||||
file_model = FileToUpload(**file_json)
|
||||
file_list.append(file_model)
|
||||
|
||||
@@ -878,16 +878,14 @@ class DOCDB(MyDB):
|
||||
us.callback AS callback,
|
||||
us.session_callback_timedelta
|
||||
"""
|
||||
result = tx.run(cypher,
|
||||
username=current_user.username,
|
||||
upload_session=upload_session)
|
||||
result = tx.run(cypher, username=current_user.username, upload_session=upload_session)
|
||||
|
||||
callback = result.get('callback')
|
||||
session_callback_timedelta = result.get('session_callback_timedelta')
|
||||
callback = result.get("callback")
|
||||
session_callback_timedelta = result.get("session_callback_timedelta")
|
||||
|
||||
upload_documents = UploadDocuments()
|
||||
upload_documents.server_context = result.get('server_context')
|
||||
upload_documents.callback.url = result.get('callback')
|
||||
upload_documents.server_context = result.get("server_context")
|
||||
upload_documents.callback.url = result.get("callback")
|
||||
upload_documents.callback.expires_in = 3500 # difference between now and timedelta
|
||||
upload_documents.files = file_list
|
||||
|
||||
@@ -896,16 +894,18 @@ class DOCDB(MyDB):
|
||||
with self.driver.session() as session:
|
||||
return session.execute_read(get_upload_documents_work)
|
||||
|
||||
def get_document_version(self, document_id: UUID, version_index: int,
|
||||
current_user: User) -> Union[DocumentVersion, bool]:
|
||||
def get_document_version(
|
||||
self, document_id: UUID, version_index: int, current_user: User
|
||||
) -> Union[DocumentVersion, bool]:
|
||||
def get_document_version_work(tx) -> Union[DocumentVersion, bool]:
|
||||
|
||||
if version_index is None or version_index is False or not isinstance(version_index, int):
|
||||
version_index_criteria = 'AND d.version_index = $version_index'
|
||||
version_index_criteria = "AND d.version_index = $version_index"
|
||||
else:
|
||||
version_index_criteria = ''
|
||||
version_index_criteria = ""
|
||||
|
||||
cypher = """
|
||||
cypher = (
|
||||
"""
|
||||
MATCH (u:User)-[r3:HAS_ACTIONS_ON]->(p:Project)-[r4:CONTAINS]->(d:Document)
|
||||
WHERE u.username = $username
|
||||
AND d.document_id = $document_id
|
||||
@@ -913,19 +913,20 @@ class DOCDB(MyDB):
|
||||
RETURN d AS document
|
||||
ORDER by d.version_index DESC
|
||||
LIMIT 1
|
||||
""" % version_index_criteria
|
||||
"""
|
||||
% version_index_criteria
|
||||
)
|
||||
|
||||
result = tx.run(cypher,
|
||||
username=current_user.username,
|
||||
document_id=document_id,
|
||||
version_index=version_index)
|
||||
result = tx.run(
|
||||
cypher, username=current_user.username, document_id=document_id, version_index=version_index
|
||||
)
|
||||
|
||||
first = result.single()
|
||||
if first is None:
|
||||
print('There were no such document version.')
|
||||
print("There were no such document version.")
|
||||
return False
|
||||
|
||||
document_node = first.get('document')
|
||||
document_node = first.get("document")
|
||||
return self.document_node_to_model(document_node)
|
||||
|
||||
with self.driver.session() as session:
|
||||
@@ -935,11 +936,12 @@ class DOCDB(MyDB):
|
||||
def get_document_version_metadata_work(tx) -> DocumentMetadataEntries:
|
||||
|
||||
if version_index is None or version_index is False or not isinstance(version_index, int):
|
||||
version_index_criteria = 'AND d.version_index = $version_index'
|
||||
version_index_criteria = "AND d.version_index = $version_index"
|
||||
else:
|
||||
version_index_criteria = ''
|
||||
version_index_criteria = ""
|
||||
|
||||
cypher = """
|
||||
cypher = (
|
||||
"""
|
||||
MATCH (u:User)-[r3:HAS_ACTIONS_ON]->(p:Project)-[r4:CONTAINS]->(d:Document)
|
||||
WHERE u.username = $username
|
||||
AND d.document_id = $document_id
|
||||
@@ -947,32 +949,34 @@ class DOCDB(MyDB):
|
||||
RETURN d AS document
|
||||
ORDER by d.version_index DESC
|
||||
LIMIT 1
|
||||
""" % version_index_criteria
|
||||
"""
|
||||
% version_index_criteria
|
||||
)
|
||||
|
||||
result = tx.run(cypher,
|
||||
username=current_user.username,
|
||||
document_id=document_id,
|
||||
version_index=version_index)
|
||||
result = tx.run(
|
||||
cypher, username=current_user.username, document_id=document_id, version_index=version_index
|
||||
)
|
||||
|
||||
first = result.single()
|
||||
if first is None:
|
||||
print('There were no such document version.')
|
||||
print("There were no such document version.")
|
||||
return False
|
||||
|
||||
document_json = self.node_to_json(first.get('document'))
|
||||
document_json['creation_date'] = self.bcf_time(document_json['creation_date'])
|
||||
metadata = ['title', 'version_number', 'creation_date']
|
||||
document_json = self.node_to_json(first.get("document"))
|
||||
document_json["creation_date"] = self.bcf_time(document_json["creation_date"])
|
||||
metadata = ["title", "version_number", "creation_date"]
|
||||
entries = list()
|
||||
for each_metadata in metadata:
|
||||
each_metadata_text = each_metadata.replace('_', ' ')
|
||||
each_metadata_text = each_metadata.replace("_", " ")
|
||||
each_metadata_text = each_metadata_text.capitalize()
|
||||
entry = {
|
||||
'name': each_metadata_text,
|
||||
'value': [document_json[each_metadata]],
|
||||
'data_type': DataType.string
|
||||
"name": each_metadata_text,
|
||||
"value": [document_json[each_metadata]],
|
||||
"data_type": DataType.string,
|
||||
}
|
||||
entries.append(entry)
|
||||
return DocumentMetadataEntries(**{'metadata': entries})
|
||||
return DocumentMetadataEntries(**{"metadata": entries})
|
||||
|
||||
with self.driver.session() as session:
|
||||
return session.execute_read(get_document_version_metadata_work)
|
||||
|
||||
@@ -984,15 +988,14 @@ class DOCDB(MyDB):
|
||||
AND d.document_id = $document_id
|
||||
RETURN d AS document
|
||||
"""
|
||||
results = tx.run(cypher,
|
||||
username=current_user.username,
|
||||
document_id=document_id)
|
||||
document_versions = DocumentVersions({'documents': list()})
|
||||
results = tx.run(cypher, username=current_user.username, document_id=document_id)
|
||||
document_versions = DocumentVersions({"documents": list()})
|
||||
for result in results:
|
||||
document_json = self.node_to_json(result.get('document'))
|
||||
document_version = self.get_document_version(document_id, document_json['version_index'], current_user)
|
||||
document_json = self.node_to_json(result.get("document"))
|
||||
document_version = self.get_document_version(document_id, document_json["version_index"], current_user)
|
||||
document_versions.documents.append(document_version)
|
||||
return document_versions
|
||||
|
||||
with self.driver.session() as session:
|
||||
return session.execute_read(get_document_versions_work)
|
||||
|
||||
|
||||
@@ -36,11 +36,13 @@ class FoundationDB(MyDB):
|
||||
CALL apoc.ttl.expireIn(ac, $time_delta, 's')
|
||||
RETURN ac AS authorization_code
|
||||
"""
|
||||
result = tx.run(cypher,
|
||||
username=username,
|
||||
authorization_code=authorization_code,
|
||||
scope=scope,
|
||||
time_delta=int(os.environ['SECURITY_AUTHORIZATION_CODE_EXPIRE_SECONDS']))
|
||||
result = tx.run(
|
||||
cypher,
|
||||
username=username,
|
||||
authorization_code=authorization_code,
|
||||
scope=scope,
|
||||
time_delta=int(os.environ["SECURITY_AUTHORIZATION_CODE_EXPIRE_SECONDS"]),
|
||||
)
|
||||
summary = result.consume()
|
||||
if summary.counters.nodes_created < 1:
|
||||
raise HTTPException(status_code=400, detail="Authorization code was not created.")
|
||||
@@ -58,14 +60,13 @@ class FoundationDB(MyDB):
|
||||
RETURN
|
||||
username, scope
|
||||
"""
|
||||
result = tx.run(cypher,
|
||||
authorization_code=authorization_code)
|
||||
result = tx.run(cypher, authorization_code=authorization_code)
|
||||
first = result.single()
|
||||
if first is None:
|
||||
raise HTTPException(status_code=404, detail="Authorization code not found.")
|
||||
authorized_user = TokenData()
|
||||
authorized_user.username = first.get("username")
|
||||
authorized_user.scopes = first.get("scope").split(' ')
|
||||
authorized_user.scopes = first.get("scope").split(" ")
|
||||
return authorized_user
|
||||
|
||||
with self.driver.session() as session:
|
||||
@@ -73,11 +74,11 @@ class FoundationDB(MyDB):
|
||||
|
||||
token_info = TokenInfo()
|
||||
token_info.access_token = create_access_token(
|
||||
user_info.dict(),
|
||||
timedelta(seconds=int(os.environ['SECURITY_ACCESS_TOKEN_EXPIRE_SECONDS'])))
|
||||
user_info.dict(), timedelta(seconds=int(os.environ["SECURITY_ACCESS_TOKEN_EXPIRE_SECONDS"]))
|
||||
)
|
||||
token_info.refresh_token = create_access_token(
|
||||
user_info.dict(),
|
||||
timedelta(seconds=int(os.environ['SECURITY_REFRESH_TOKEN_EXPIRE_SECONDS'])))
|
||||
user_info.dict(), timedelta(seconds=int(os.environ["SECURITY_REFRESH_TOKEN_EXPIRE_SECONDS"]))
|
||||
)
|
||||
|
||||
def add_tokens_and_delete_code_work(tx) -> bool:
|
||||
cypher = """
|
||||
@@ -92,13 +93,15 @@ class FoundationDB(MyDB):
|
||||
SET t3.value = $refresh_token
|
||||
SET t3.hash = $refresh_token_hash
|
||||
"""
|
||||
result = tx.run(cypher,
|
||||
authorization_code=authorization_code,
|
||||
username=user_info.username,
|
||||
access_token=token_info.access_token,
|
||||
access_token_hash=hashlib.md5(token_info.access_token.encode('utf-8')).hexdigest(),
|
||||
refresh_token=token_info.refresh_token,
|
||||
refresh_token_hash=hashlib.md5(token_info.refresh_token.encode('utf-8')).hexdigest())
|
||||
result = tx.run(
|
||||
cypher,
|
||||
authorization_code=authorization_code,
|
||||
username=user_info.username,
|
||||
access_token=token_info.access_token,
|
||||
access_token_hash=hashlib.md5(token_info.access_token.encode("utf-8")).hexdigest(),
|
||||
refresh_token=token_info.refresh_token,
|
||||
refresh_token_hash=hashlib.md5(token_info.refresh_token.encode("utf-8")).hexdigest(),
|
||||
)
|
||||
|
||||
summary = result.consume()
|
||||
if summary.counters.nodes_created < 1 or summary.counters.nodes_deleted < 1:
|
||||
@@ -119,24 +122,25 @@ class FoundationDB(MyDB):
|
||||
RETURN
|
||||
at.value AS access_token
|
||||
"""
|
||||
refresh_token_payload = jwt.decode(refresh_token,
|
||||
secrets['security_secret_key'],
|
||||
algorithms=[os.environ['SECURITY_ALGORITHM']])
|
||||
refresh_token_payload = jwt.decode(
|
||||
refresh_token, secrets["security_secret_key"], algorithms=[os.environ["SECURITY_ALGORITHM"]]
|
||||
)
|
||||
username_from_refresh_token: str = refresh_token_payload.get("username")
|
||||
print('refresh_token_username: ', username_from_refresh_token)
|
||||
result = tx.run(cypher,
|
||||
username=username_from_refresh_token,
|
||||
refresh_token_hash=hashlib.md5(refresh_token.encode('utf-8')).hexdigest()
|
||||
)
|
||||
print("refresh_token_username: ", username_from_refresh_token)
|
||||
result = tx.run(
|
||||
cypher,
|
||||
username=username_from_refresh_token,
|
||||
refresh_token_hash=hashlib.md5(refresh_token.encode("utf-8")).hexdigest(),
|
||||
)
|
||||
first = result.single()
|
||||
if first is None:
|
||||
raise HTTPException(status_code=404, detail="Access token not found.")
|
||||
token_info = TokenInfo()
|
||||
token_info.access_token = first.get("access_token")
|
||||
token_info.refresh_token = refresh_token
|
||||
access_token_payload = jwt.decode(token_info.access_token,
|
||||
secrets['security_secret_key'],
|
||||
algorithms=[os.environ['SECURITY_ALGORITHM']])
|
||||
access_token_payload = jwt.decode(
|
||||
token_info.access_token, secrets["security_secret_key"], algorithms=[os.environ["SECURITY_ALGORITHM"]]
|
||||
)
|
||||
username_from_access_token: str = access_token_payload.get("username")
|
||||
if username_from_access_token is None:
|
||||
raise credentials_exception
|
||||
@@ -148,11 +152,11 @@ class FoundationDB(MyDB):
|
||||
got_token_data, got_token_info = session.execute_read(use_refresh_to_get_access_work)
|
||||
new_token_info = TokenInfo()
|
||||
new_token_info.access_token = create_access_token(
|
||||
got_token_data.dict(),
|
||||
timedelta(seconds=int(os.environ['SECURITY_ACCESS_TOKEN_EXPIRE_SECONDS'])))
|
||||
got_token_data.dict(), timedelta(seconds=int(os.environ["SECURITY_ACCESS_TOKEN_EXPIRE_SECONDS"]))
|
||||
)
|
||||
new_token_info.refresh_token = create_access_token(
|
||||
got_token_data.dict(),
|
||||
timedelta(seconds=int(os.environ['SECURITY_REFRESH_TOKEN_EXPIRE_SECONDS'])))
|
||||
got_token_data.dict(), timedelta(seconds=int(os.environ["SECURITY_REFRESH_TOKEN_EXPIRE_SECONDS"]))
|
||||
)
|
||||
|
||||
def update_tokens_work(tx) -> bool:
|
||||
cypher = """
|
||||
@@ -168,12 +172,14 @@ class FoundationDB(MyDB):
|
||||
rt.hash = $refresh_token_hash,
|
||||
at.hash = $access_token_hash
|
||||
"""
|
||||
result = tx.run(cypher,
|
||||
username=got_token_data.username,
|
||||
access_token=new_token_info.access_token,
|
||||
refresh_token=new_token_info.refresh_token,
|
||||
access_token_hash=hashlib.md5(new_token_info.access_token.encode('utf-8')).hexdigest(),
|
||||
refresh_token_hash=hashlib.md5(new_token_info.refresh_token.encode('utf-8')).hexdigest())
|
||||
result = tx.run(
|
||||
cypher,
|
||||
username=got_token_data.username,
|
||||
access_token=new_token_info.access_token,
|
||||
refresh_token=new_token_info.refresh_token,
|
||||
access_token_hash=hashlib.md5(new_token_info.access_token.encode("utf-8")).hexdigest(),
|
||||
refresh_token_hash=hashlib.md5(new_token_info.refresh_token.encode("utf-8")).hexdigest(),
|
||||
)
|
||||
summary = result.consume()
|
||||
if summary.counters.nodes_created < 2 or summary.counters.nodes_deleted < 2:
|
||||
raise HTTPException(status_code=400, detail="Tokens were not deleted and created.")
|
||||
@@ -183,4 +189,5 @@ class FoundationDB(MyDB):
|
||||
session.execute_write(update_tokens_work)
|
||||
return new_token_info
|
||||
|
||||
|
||||
foundation_db = FoundationDB(driver)
|
||||
|
||||
@@ -3,8 +3,8 @@ from glob import glob
|
||||
|
||||
def get_secrets():
|
||||
secrets = dict()
|
||||
for var in glob('/run/secrets/*'):
|
||||
k = var.split('/')[-1]
|
||||
v = open(var).read().rstrip('\n')
|
||||
for var in glob("/run/secrets/*"):
|
||||
k = var.split("/")[-1]
|
||||
v = open(var).read().rstrip("\n")
|
||||
secrets[k] = v
|
||||
return secrets
|
||||
|
||||
@@ -16,25 +16,20 @@ from security.secrets import get_secrets
|
||||
secrets = get_secrets()
|
||||
|
||||
# password context
|
||||
crypt_context = CryptContext(
|
||||
schemes=["bcrypt"],
|
||||
deprecated="auto")
|
||||
crypt_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
||||
|
||||
oauth2_scheme = OAuth2AuthorizationCodeBearer(
|
||||
authorizationUrl='foundation/oauth2/auth',
|
||||
tokenUrl='foundation/oauth2/token',
|
||||
scopes={
|
||||
'test': 'Full access, but only test data.',
|
||||
'user': 'Normal user access.',
|
||||
'admin': 'Full access to all.'
|
||||
})
|
||||
authorizationUrl="foundation/oauth2/auth",
|
||||
tokenUrl="foundation/oauth2/token",
|
||||
scopes={"test": "Full access, but only test data.", "user": "Normal user access.", "admin": "Full access to all."},
|
||||
)
|
||||
|
||||
|
||||
credentials_exception = HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Could not validate credentials",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Could not validate credentials",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
|
||||
def create_access_token(data: dict, expires_delta: timedelta | None = None):
|
||||
@@ -44,7 +39,7 @@ def create_access_token(data: dict, expires_delta: timedelta | None = None):
|
||||
else:
|
||||
expire = datetime.utcnow() + timedelta(minutes=15)
|
||||
payload.update({"expires": str(expire)})
|
||||
encoded_jwt = jwt.encode(payload, secrets['security_secret_key'], algorithm=os.environ['SECURITY_ALGORITHM'])
|
||||
encoded_jwt = jwt.encode(payload, secrets["security_secret_key"], algorithm=os.environ["SECURITY_ALGORITHM"])
|
||||
return encoded_jwt
|
||||
|
||||
|
||||
@@ -79,20 +74,18 @@ async def get_current_user(security_scopes: SecurityScopes, token: str = Depends
|
||||
print(authenticate_value)
|
||||
|
||||
try:
|
||||
print('Token: ', token)
|
||||
payload = jwt.decode(token,
|
||||
secrets['security_secret_key'],
|
||||
algorithms=[os.environ['SECURITY_ALGORITHM']])
|
||||
print("Token: ", token)
|
||||
payload = jwt.decode(token, secrets["security_secret_key"], algorithms=[os.environ["SECURITY_ALGORITHM"]])
|
||||
username_from_token: str = payload.get("username")
|
||||
print('Token username: ', username_from_token)
|
||||
print("Token username: ", username_from_token)
|
||||
if username_from_token is None:
|
||||
raise credentials_exception
|
||||
token_scopes = payload.get("scopes", [])
|
||||
print('Token scopes: ', token_scopes)
|
||||
print("Token scopes: ", token_scopes)
|
||||
token_data = TokenData(scopes=token_scopes, username=username_from_token)
|
||||
|
||||
except JWTError:
|
||||
print('JWTError')
|
||||
print("JWTError")
|
||||
raise credentials_exception
|
||||
|
||||
user = db.get_user(username=token_data.username)
|
||||
|
||||
Reference in New Issue
Block a user