2023-09-20 10:35:37 +03:00
|
|
|
from uuid import UUID
|
|
|
|
|
|
|
|
from fastapi import APIRouter, Depends, Query
|
|
|
|
from logger import get_logger
|
2023-11-14 16:31:02 +03:00
|
|
|
from middlewares.auth import AuthBearer, get_current_user
|
2023-11-15 15:17:51 +03:00
|
|
|
from models import Brain
|
|
|
|
from modules.user.entity.user_identity import UserIdentity
|
2023-09-22 17:06:04 +03:00
|
|
|
from repository.files.delete_file import delete_file_from_storage
|
2023-09-20 10:35:37 +03:00
|
|
|
from repository.files.generate_file_signed_url import generate_file_signed_url
|
2023-09-22 17:06:04 +03:00
|
|
|
from repository.knowledge.get_all_knowledge import get_all_knowledge
|
|
|
|
from repository.knowledge.get_knowledge import get_knowledge
|
|
|
|
from repository.knowledge.remove_knowledge import remove_knowledge
|
2023-09-20 10:35:37 +03:00
|
|
|
from routes.authorizations.brain_authorization import (
|
|
|
|
RoleEnum,
|
|
|
|
has_brain_authorization,
|
|
|
|
validate_brain_authorization,
|
|
|
|
)
|
|
|
|
|
|
|
|
knowledge_router = APIRouter()
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
@knowledge_router.get(
|
2023-09-25 13:13:48 +03:00
|
|
|
"/knowledge", dependencies=[Depends(AuthBearer())], tags=["Knowledge"]
|
2023-09-20 10:35:37 +03:00
|
|
|
)
|
|
|
|
async def list_knowledge_in_brain_endpoint(
|
|
|
|
brain_id: UUID = Query(..., description="The ID of the brain"),
|
|
|
|
current_user: UserIdentity = Depends(get_current_user),
|
|
|
|
):
|
|
|
|
"""
|
|
|
|
Retrieve and list all the knowledge in a brain.
|
|
|
|
"""
|
|
|
|
|
|
|
|
validate_brain_authorization(brain_id=brain_id, user_id=current_user.id)
|
|
|
|
|
2023-09-22 17:06:04 +03:00
|
|
|
knowledges = get_all_knowledge(brain_id)
|
Fixes string formatting when logging knowledge table (#1691)
# Description
```
======================================================================
backend-core | --- Logging error ---
backend-core | Traceback (most recent call last):
backend-core | File "/usr/local/lib/python3.11/logging/__init__.py", line 1110, in emit
backend-core | msg = self.format(record)
backend-core | ^^^^^^^^^^^^^^^^^^^
backend-core | File "/usr/local/lib/python3.11/logging/__init__.py", line 953, in format
backend-core | return fmt.format(record)
backend-core | ^^^^^^^^^^^^^^^^^^
backend-core | File "/usr/local/lib/python3.11/logging/__init__.py", line 687, in format
backend-core | record.message = record.getMessage()
backend-core | ^^^^^^^^^^^^^^^^^^^
backend-core | File "/usr/local/lib/python3.11/logging/__init__.py", line 377, in getMessage
backend-core | msg = msg % self.args
backend-core | ~~~~^~~~~~~~~~~
backend-core | TypeError: not all arguments converted during string formatting
backend-core | Call stack:
backend-core | File "<string>", line 1, in <module>
backend-core | File "/usr/local/lib/python3.11/multiprocessing/spawn.py", line 122, in spawn_main
backend-core | exitcode = _main(fd, parent_sentinel)
backend-core | File "/usr/local/lib/python3.11/multiprocessing/spawn.py", line 135, in _main
backend-core | return self._bootstrap(parent_sentinel)
backend-core | File "/usr/local/lib/python3.11/multiprocessing/process.py", line 314, in _bootstrap
backend-core | self.run()
backend-core | File "/usr/local/lib/python3.11/multiprocessing/process.py", line 108, in run
backend-core | self._target(*self._args, **self._kwargs)
backend-core | File "/usr/local/lib/python3.11/site-packages/uvicorn/_subprocess.py", line 76, in subprocess_started
backend-core | target(sockets=sockets)
backend-core | File "/usr/local/lib/python3.11/site-packages/uvicorn/server.py", line 61, in run
backend-core | return asyncio.run(self.serve(sockets=sockets))
backend-core | File "/usr/local/lib/python3.11/asyncio/runners.py", line 190, in run
backend-core | return runner.run(main)
backend-core | File "/usr/local/lib/python3.11/asyncio/runners.py", line 118, in run
backend-core | return self._loop.run_until_complete(task)
backend-core | File "/usr/local/lib/python3.11/asyncio/base_events.py", line 640, in run_until_complete
backend-core | self.run_forever()
backend-core | File "/usr/local/lib/python3.11/asyncio/base_events.py", line 607, in run_forever
backend-core | self._run_once()
backend-core | File "/usr/local/lib/python3.11/asyncio/base_events.py", line 1922, in _run_once
backend-core | handle._run()
backend-core | File "/usr/local/lib/python3.11/asyncio/events.py", line 80, in _run
backend-core | self._context.run(self._callback, *self._args)
backend-core | File "/usr/local/lib/python3.11/site-packages/uvicorn/protocols/http/h11_impl.py", line 428, in run_asgi
backend-core | result = await app( # type: ignore[func-returns-value]
backend-core | File "/usr/local/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
backend-core | return await self.app(scope, receive, send)
backend-core | File "/usr/local/lib/python3.11/site-packages/fastapi/applications.py", line 276, in __call__
backend-core | await super().__call__(scope, receive, send)
backend-core | File "/usr/local/lib/python3.11/site-packages/starlette/applications.py", line 122, in __call__
backend-core | await self.middleware_stack(scope, receive, send)
backend-core | File "/usr/local/lib/python3.11/site-packages/starlette/middleware/errors.py", line 162, in __call__
backend-core | await self.app(scope, receive, _send)
backend-core | File "/usr/local/lib/python3.11/site-packages/starlette/middleware/cors.py", line 91, in __call__
backend-core | await self.simple_response(scope, receive, send, request_headers=headers)
backend-core | File "/usr/local/lib/python3.11/site-packages/starlette/middleware/cors.py", line 146, in simple_response
backend-core | await self.app(scope, receive, send)
backend-core | File "/usr/local/lib/python3.11/site-packages/starlette/middleware/exceptions.py", line 68, in __call__
backend-core | await self.app(scope, receive, sender)
backend-core | File "/usr/local/lib/python3.11/site-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
backend-core | await self.app(scope, receive, send)
backend-core | File "/usr/local/lib/python3.11/site-packages/starlette/routing.py", line 718, in __call__
backend-core | await route.handle(scope, receive, send)
backend-core | File "/usr/local/lib/python3.11/site-packages/starlette/routing.py", line 276, in handle
backend-core | await self.app(scope, receive, send)
backend-core | File "/usr/local/lib/python3.11/site-packages/starlette/routing.py", line 66, in app
backend-core | response = await func(request)
backend-core | File "/usr/local/lib/python3.11/site-packages/fastapi/routing.py", line 237, in app
backend-core | raw_response = await run_endpoint_function(
backend-core | File "/usr/local/lib/python3.11/site-packages/fastapi/routing.py", line 163, in run_endpoint_function
backend-core | return await dependant.call(**values)
backend-core | File "/code/routes/knowledge_routes.py", line 37, in list_knowledge_in_brain_endpoint
backend-core | logger.info("List of knowledge from knowledge table", knowledges)
backend-core | Message: 'List of knowledge from knowledge table'
backend-core | Arguments: ([Knowledge(id=UUID('b5ae6a25-1e8e-4fb5-a0c1-0039a8318ec3'), brain_id=UUID('7af64537-61cb-48e1-b3d1-c700d748b373'), file_name='Cradle to Cradle Criteria for the built environmen.pdf', url=None, extension='.pdf'), Knowledge(id=UUID('efb7ad5a-a13e-46f3-a580-4c574710ad15'), brain_id=UUID('7af64537-61cb-48e1-b3d1-c700d748b373'), file_name='GEG_2023_gebaeudeenergiegesetz_kompakt_und_praktisch.pdf', url=None, extension='.pdf'), Knowledge(id=UUID('9442f898-0fbe-46d2-b6ae-a726d62717bd'), brain_id=UUID('7af64537-61cb-48e1-b3d1-c700d748b373'), file_name='dgnb-kriterienkatalog-gebaeude-neubau-version-2023-auflage-2.pdf', url=None, extension='.pdf')],)
======================================================================
```
## Checklist before requesting a review
Please delete options that are not relevant.
- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented hard-to-understand areas
- [x] I have ideally added tests that prove my fix is effective or that
my feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged
2023-11-23 19:25:57 +03:00
|
|
|
logger.info(f"List of knowledge from knowledge table: {knowledges}")
|
2023-09-20 10:35:37 +03:00
|
|
|
|
2023-09-22 17:06:04 +03:00
|
|
|
return {"knowledges": knowledges}
|
2023-09-20 10:35:37 +03:00
|
|
|
|
|
|
|
|
|
|
|
@knowledge_router.delete(
|
2023-09-25 13:13:48 +03:00
|
|
|
"/knowledge/{knowledge_id}",
|
2023-09-20 10:35:37 +03:00
|
|
|
dependencies=[
|
|
|
|
Depends(AuthBearer()),
|
|
|
|
Depends(has_brain_authorization(RoleEnum.Owner)),
|
|
|
|
],
|
|
|
|
tags=["Knowledge"],
|
|
|
|
)
|
|
|
|
async def delete_endpoint(
|
2023-09-22 17:06:04 +03:00
|
|
|
knowledge_id: UUID,
|
2023-09-20 10:35:37 +03:00
|
|
|
current_user: UserIdentity = Depends(get_current_user),
|
|
|
|
brain_id: UUID = Query(..., description="The ID of the brain"),
|
|
|
|
):
|
|
|
|
"""
|
2023-09-22 17:06:04 +03:00
|
|
|
Delete a specific knowledge from a brain.
|
2023-09-20 10:35:37 +03:00
|
|
|
"""
|
|
|
|
|
|
|
|
validate_brain_authorization(brain_id=brain_id, user_id=current_user.id)
|
|
|
|
|
|
|
|
brain = Brain(id=brain_id)
|
2023-09-22 17:06:04 +03:00
|
|
|
|
|
|
|
knowledge = get_knowledge(knowledge_id)
|
|
|
|
file_name = knowledge.file_name if knowledge.file_name else knowledge.url
|
|
|
|
remove_knowledge(knowledge_id)
|
|
|
|
|
|
|
|
if knowledge.file_name:
|
|
|
|
delete_file_from_storage(f"{brain_id}/{knowledge.file_name}")
|
|
|
|
brain.delete_file_from_brain(knowledge.file_name)
|
|
|
|
elif knowledge.url:
|
|
|
|
brain.delete_file_from_brain(knowledge.url)
|
2023-09-20 10:35:37 +03:00
|
|
|
|
|
|
|
return {
|
|
|
|
"message": f"{file_name} of brain {brain_id} has been deleted by user {current_user.email}."
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@knowledge_router.get(
|
2023-09-22 17:06:04 +03:00
|
|
|
"/knowledge/{knowledge_id}/signed_download_url",
|
2023-09-20 10:35:37 +03:00
|
|
|
dependencies=[Depends(AuthBearer())],
|
|
|
|
tags=["Knowledge"],
|
|
|
|
)
|
|
|
|
async def generate_signed_url_endpoint(
|
2023-09-22 17:06:04 +03:00
|
|
|
knowledge_id: UUID,
|
|
|
|
current_user: UserIdentity = Depends(get_current_user),
|
2023-09-20 10:35:37 +03:00
|
|
|
):
|
|
|
|
"""
|
|
|
|
Generate a signed url to download the file from storage.
|
|
|
|
"""
|
|
|
|
|
2023-09-22 17:06:04 +03:00
|
|
|
knowledge = get_knowledge(knowledge_id)
|
2023-09-20 10:35:37 +03:00
|
|
|
|
2023-09-22 17:06:04 +03:00
|
|
|
validate_brain_authorization(brain_id=knowledge.brain_id, user_id=current_user.id)
|
2023-09-20 10:35:37 +03:00
|
|
|
|
2023-09-22 17:06:04 +03:00
|
|
|
if knowledge.file_name == None:
|
|
|
|
raise Exception(f"Knowledge {knowledge_id} has no file_name associated with it")
|
2023-09-20 10:35:37 +03:00
|
|
|
|
2023-09-22 17:06:04 +03:00
|
|
|
file_path_in_storage = f"{knowledge.brain_id}/{knowledge.file_name}"
|
2023-09-20 10:35:37 +03:00
|
|
|
|
|
|
|
file_signed_url = generate_file_signed_url(file_path_in_storage)
|
|
|
|
|
|
|
|
return file_signed_url
|