cognee 0.3.3__py3-none-any.whl → 0.3.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. cognee/api/v1/cloud/routers/get_checks_router.py +1 -1
  2. cognee/api/v1/cognify/cognify.py +44 -7
  3. cognee/api/v1/cognify/routers/get_cognify_router.py +2 -1
  4. cognee/api/v1/prune/prune.py +2 -2
  5. cognee/api/v1/search/search.py +1 -1
  6. cognee/api/v1/sync/sync.py +16 -5
  7. cognee/base_config.py +19 -1
  8. cognee/eval_framework/corpus_builder/task_getters/get_default_tasks_by_indices.py +2 -2
  9. cognee/infrastructure/databases/graph/kuzu/remote_kuzu_adapter.py +4 -1
  10. cognee/infrastructure/databases/relational/ModelBase.py +2 -1
  11. cognee/infrastructure/databases/vector/chromadb/ChromaDBAdapter.py +2 -6
  12. cognee/infrastructure/databases/vector/embeddings/OllamaEmbeddingEngine.py +6 -5
  13. cognee/infrastructure/files/storage/LocalFileStorage.py +50 -0
  14. cognee/infrastructure/files/storage/S3FileStorage.py +56 -9
  15. cognee/infrastructure/files/storage/StorageManager.py +18 -0
  16. cognee/infrastructure/files/utils/get_file_metadata.py +6 -1
  17. cognee/infrastructure/llm/structured_output_framework/litellm_instructor/llm/anthropic/adapter.py +4 -2
  18. cognee/modules/cloud/operations/check_api_key.py +4 -1
  19. cognee/modules/data/deletion/prune_system.py +5 -1
  20. cognee/modules/data/methods/create_authorized_dataset.py +9 -0
  21. cognee/modules/data/methods/get_authorized_dataset.py +1 -1
  22. cognee/modules/data/methods/get_authorized_dataset_by_name.py +11 -0
  23. cognee/modules/graph/utils/expand_with_nodes_and_edges.py +22 -8
  24. cognee/modules/graph/utils/retrieve_existing_edges.py +0 -2
  25. cognee/modules/notebooks/methods/create_notebook.py +34 -0
  26. cognee/modules/notebooks/methods/get_notebooks.py +27 -1
  27. cognee/modules/notebooks/models/Notebook.py +206 -1
  28. cognee/modules/observability/get_observe.py +14 -0
  29. cognee/modules/observability/observers.py +1 -0
  30. cognee/modules/ontology/base_ontology_resolver.py +42 -0
  31. cognee/modules/ontology/get_default_ontology_resolver.py +41 -0
  32. cognee/modules/ontology/matching_strategies.py +53 -0
  33. cognee/modules/ontology/models.py +20 -0
  34. cognee/modules/ontology/ontology_config.py +24 -0
  35. cognee/modules/ontology/ontology_env_config.py +45 -0
  36. cognee/modules/ontology/rdf_xml/{OntologyResolver.py → RDFLibOntologyResolver.py} +20 -28
  37. cognee/modules/pipelines/layers/resolve_authorized_user_dataset.py +13 -0
  38. cognee/modules/pipelines/layers/resolve_authorized_user_datasets.py +1 -1
  39. cognee/modules/pipelines/models/PipelineRunInfo.py +7 -2
  40. cognee/modules/retrieval/temporal_retriever.py +2 -2
  41. cognee/modules/search/methods/get_search_type_tools.py +7 -0
  42. cognee/modules/search/methods/search.py +12 -13
  43. cognee/modules/search/utils/prepare_search_result.py +28 -6
  44. cognee/modules/search/utils/transform_context_to_graph.py +1 -1
  45. cognee/modules/search/utils/transform_insights_to_graph.py +28 -0
  46. cognee/modules/users/methods/create_user.py +4 -24
  47. cognee/modules/users/permissions/methods/authorized_give_permission_on_datasets.py +12 -0
  48. cognee/modules/users/permissions/methods/check_permission_on_dataset.py +11 -0
  49. cognee/modules/users/permissions/methods/get_all_user_permission_datasets.py +19 -2
  50. cognee/modules/users/permissions/methods/get_document_ids_for_user.py +10 -0
  51. cognee/modules/users/permissions/methods/get_principal.py +9 -0
  52. cognee/modules/users/permissions/methods/get_principal_datasets.py +11 -0
  53. cognee/modules/users/permissions/methods/get_role.py +10 -0
  54. cognee/modules/users/permissions/methods/get_specific_user_permission_datasets.py +3 -3
  55. cognee/modules/users/permissions/methods/get_tenant.py +9 -0
  56. cognee/modules/users/permissions/methods/give_default_permission_to_role.py +9 -0
  57. cognee/modules/users/permissions/methods/give_default_permission_to_tenant.py +9 -0
  58. cognee/modules/users/permissions/methods/give_default_permission_to_user.py +9 -0
  59. cognee/modules/users/permissions/methods/give_permission_on_dataset.py +10 -0
  60. cognee/modules/users/roles/methods/add_user_to_role.py +11 -0
  61. cognee/modules/users/roles/methods/create_role.py +10 -0
  62. cognee/modules/users/tenants/methods/add_user_to_tenant.py +12 -0
  63. cognee/modules/users/tenants/methods/create_tenant.py +10 -0
  64. cognee/root_dir.py +5 -0
  65. cognee/shared/cache.py +346 -0
  66. cognee/shared/utils.py +12 -0
  67. cognee/tasks/graph/extract_graph_from_data.py +53 -10
  68. cognee/tasks/graph/extract_graph_from_data_v2.py +16 -4
  69. cognee/tasks/ingestion/save_data_item_to_storage.py +1 -0
  70. cognee/tasks/temporal_graph/models.py +11 -6
  71. cognee/tests/cli_tests/cli_unit_tests/test_cli_main.py +5 -5
  72. cognee/tests/test_cognee_server_start.py +4 -4
  73. cognee/tests/test_temporal_graph.py +6 -34
  74. cognee/tests/unit/modules/ontology/test_ontology_adapter.py +330 -13
  75. cognee/tests/unit/modules/users/test_tutorial_notebook_creation.py +399 -0
  76. {cognee-0.3.3.dist-info → cognee-0.3.4.dist-info}/METADATA +11 -8
  77. {cognee-0.3.3.dist-info → cognee-0.3.4.dist-info}/RECORD +81 -73
  78. cognee/modules/notebooks/methods/create_tutorial_notebook.py +0 -92
  79. {cognee-0.3.3.dist-info → cognee-0.3.4.dist-info}/WHEEL +0 -0
  80. {cognee-0.3.3.dist-info → cognee-0.3.4.dist-info}/entry_points.txt +0 -0
  81. {cognee-0.3.3.dist-info → cognee-0.3.4.dist-info}/licenses/LICENSE +0 -0
  82. {cognee-0.3.3.dist-info → cognee-0.3.4.dist-info}/licenses/NOTICE.md +0 -0
@@ -10,31 +10,26 @@ from cognee.modules.ontology.exceptions import (
10
10
  FindClosestMatchError,
11
11
  GetSubgraphError,
12
12
  )
13
+ from cognee.modules.ontology.base_ontology_resolver import BaseOntologyResolver
14
+ from cognee.modules.ontology.models import AttachedOntologyNode
15
+ from cognee.modules.ontology.matching_strategies import MatchingStrategy, FuzzyMatchingStrategy
13
16
 
14
17
  logger = get_logger("OntologyAdapter")
15
18
 
16
19
 
17
- class AttachedOntologyNode:
18
- """Lightweight wrapper to be able to parse any ontology solution and generalize cognee interface."""
20
+ class RDFLibOntologyResolver(BaseOntologyResolver):
21
+ """RDFLib-based ontology resolver implementation.
19
22
 
20
- def __init__(self, uri: URIRef, category: str):
21
- self.uri = uri
22
- self.name = self._extract_name(uri)
23
- self.category = category
23
+ This implementation uses RDFLib to parse and work with RDF/OWL ontology files.
24
+ It provides fuzzy matching and subgraph extraction capabilities for ontology entities.
25
+ """
24
26
 
25
- @staticmethod
26
- def _extract_name(uri: URIRef) -> str:
27
- uri_str = str(uri)
28
- if "#" in uri_str:
29
- return uri_str.split("#")[-1]
30
- return uri_str.rstrip("/").split("/")[-1]
31
-
32
- def __repr__(self):
33
- return f"AttachedOntologyNode(name={self.name}, category={self.category})"
34
-
35
-
36
- class OntologyResolver:
37
- def __init__(self, ontology_file: Optional[str] = None):
27
+ def __init__(
28
+ self,
29
+ ontology_file: Optional[str] = None,
30
+ matching_strategy: Optional[MatchingStrategy] = None,
31
+ ) -> None:
32
+ super().__init__(matching_strategy)
38
33
  self.ontology_file = ontology_file
39
34
  try:
40
35
  if ontology_file and os.path.exists(ontology_file):
@@ -60,7 +55,7 @@ class OntologyResolver:
60
55
  name = uri_str.rstrip("/").split("/")[-1]
61
56
  return name.lower().replace(" ", "_").strip()
62
57
 
63
- def build_lookup(self):
58
+ def build_lookup(self) -> None:
64
59
  try:
65
60
  classes: Dict[str, URIRef] = {}
66
61
  individuals: Dict[str, URIRef] = {}
@@ -97,7 +92,7 @@ class OntologyResolver:
97
92
  logger.error("Failed to build lookup dictionary: %s", str(e))
98
93
  raise RuntimeError("Lookup build failed") from e
99
94
 
100
- def refresh_lookup(self):
95
+ def refresh_lookup(self) -> None:
101
96
  self.build_lookup()
102
97
  logger.info("Ontology lookup refreshed.")
103
98
 
@@ -105,13 +100,8 @@ class OntologyResolver:
105
100
  try:
106
101
  normalized_name = name.lower().replace(" ", "_").strip()
107
102
  possible_matches = list(self.lookup.get(category, {}).keys())
108
- if normalized_name in possible_matches:
109
- return normalized_name
110
103
 
111
- best_match = difflib.get_close_matches(
112
- normalized_name, possible_matches, n=1, cutoff=0.8
113
- )
114
- return best_match[0] if best_match else None
104
+ return self.matching_strategy.find_match(normalized_name, possible_matches)
115
105
  except Exception as e:
116
106
  logger.error("Error in find_closest_match: %s", str(e))
117
107
  raise FindClosestMatchError() from e
@@ -125,7 +115,9 @@ class OntologyResolver:
125
115
 
126
116
  def get_subgraph(
127
117
  self, node_name: str, node_type: str = "individuals", directed: bool = True
128
- ) -> Tuple[List[Any], List[Tuple[str, str, str]], Optional[Any]]:
118
+ ) -> Tuple[
119
+ List[AttachedOntologyNode], List[Tuple[str, str, str]], Optional[AttachedOntologyNode]
120
+ ]:
129
121
  nodes_set = set()
130
122
  edges: List[Tuple[str, str, str]] = []
131
123
  visited = set()
@@ -11,6 +11,19 @@ from cognee.modules.data.methods import (
11
11
 
12
12
 
13
13
  async def resolve_authorized_user_dataset(dataset_id: UUID, dataset_name: str, user: User):
14
+ """
15
+ Function handles creation and dataset authorization if dataset already exist for Cognee.
16
+ Verifies that provided user has necessary permission for provided Dataset.
17
+ If Dataset does not exist creates the Dataset and gives permission for the user creating the dataset.
18
+
19
+ Args:
20
+ dataset_id: Id of the dataset.
21
+ dataset_name: Name of the dataset.
22
+ user: Cognee User request is being processed for, if None default user will be used.
23
+
24
+ Returns:
25
+ Tuple[User, Dataset]: A tuple containing the user and the authorized dataset.
26
+ """
14
27
  if not user:
15
28
  user = await get_default_user()
16
29
 
@@ -25,7 +25,7 @@ async def resolve_authorized_user_datasets(
25
25
  datasets: Dataset names or Dataset UUID (in case Datasets already exist)
26
26
 
27
27
  Returns:
28
-
28
+ Tuple[User, List[Dataset]]: A tuple containing the user and the list of authorized datasets.
29
29
  """
30
30
  # If no user is provided use default user
31
31
  if user is None:
@@ -1,6 +1,7 @@
1
- from typing import Any, Optional
1
+ from typing import Any, Optional, List, Union
2
2
  from uuid import UUID
3
3
  from pydantic import BaseModel
4
+ from cognee.modules.data.models.Data import Data
4
5
 
5
6
 
6
7
  class PipelineRunInfo(BaseModel):
@@ -8,11 +9,15 @@ class PipelineRunInfo(BaseModel):
8
9
  pipeline_run_id: UUID
9
10
  dataset_id: UUID
10
11
  dataset_name: str
11
- payload: Optional[Any] = None
12
+ # Data must be mentioned in typing to allow custom encoders for Data to be activated
13
+ payload: Optional[Union[Any, List[Data]]] = None
12
14
  data_ingestion_info: Optional[list] = None
13
15
 
14
16
  model_config = {
15
17
  "arbitrary_types_allowed": True,
18
+ "from_attributes": True,
19
+ # Add custom encoding handler for Data ORM model
20
+ "json_encoders": {Data: lambda d: d.to_json()},
16
21
  }
17
22
 
18
23
 
@@ -113,7 +113,7 @@ class TemporalRetriever(GraphCompletionRetriever):
113
113
  logger.info(
114
114
  "No timestamps identified based on the query, performing retrieval using triplet search on events and entities."
115
115
  )
116
- triplets = await self.get_context(query)
116
+ triplets = await self.get_triplets(query)
117
117
  return await self.resolve_edges_to_text(triplets)
118
118
 
119
119
  if ids:
@@ -122,7 +122,7 @@ class TemporalRetriever(GraphCompletionRetriever):
122
122
  logger.info(
123
123
  "No events identified based on timestamp filtering, performing retrieval using triplet search on events and entities."
124
124
  )
125
- triplets = await self.get_context(query)
125
+ triplets = await self.get_triplets(query)
126
126
  return await self.resolve_edges_to_text(triplets)
127
127
 
128
128
  vector_engine = get_vector_engine()
@@ -1,3 +1,4 @@
1
+ import os
1
2
  from typing import Callable, List, Optional, Type
2
3
 
3
4
  from cognee.modules.engine.models.node_set import NodeSet
@@ -160,6 +161,12 @@ async def get_search_type_tools(
160
161
  if query_type is SearchType.FEELING_LUCKY:
161
162
  query_type = await select_search_type(query_text)
162
163
 
164
+ if (
165
+ query_type in [SearchType.CYPHER, SearchType.NATURAL_LANGUAGE]
166
+ and os.getenv("ALLOW_CYPHER_QUERY", "true").lower() == "false"
167
+ ):
168
+ raise UnsupportedSearchTypeError("Cypher query search types are disabled.")
169
+
163
170
  search_type_tools = search_tasks.get(query_type)
164
171
 
165
172
  if not search_type_tools:
@@ -136,12 +136,19 @@ async def search(
136
136
  if os.getenv("ENABLE_BACKEND_ACCESS_CONTROL", "false").lower() == "true":
137
137
  return_value = []
138
138
  for search_result in search_results:
139
- result, context, datasets = search_result
139
+ prepared_search_results = await prepare_search_result(search_result)
140
+
141
+ result = prepared_search_results["result"]
142
+ graphs = prepared_search_results["graphs"]
143
+ context = prepared_search_results["context"]
144
+ datasets = prepared_search_results["datasets"]
145
+
140
146
  return_value.append(
141
147
  {
142
- "search_result": result,
148
+ "search_result": [result] if result else None,
143
149
  "dataset_id": datasets[0].id,
144
150
  "dataset_name": datasets[0].name,
151
+ "graphs": graphs,
145
152
  }
146
153
  )
147
154
  return return_value
@@ -155,14 +162,6 @@ async def search(
155
162
  return return_value[0]
156
163
  else:
157
164
  return return_value
158
- # return [
159
- # SearchResult(
160
- # search_result=result,
161
- # dataset_id=datasets[min(index, len(datasets) - 1)].id if datasets else None,
162
- # dataset_name=datasets[min(index, len(datasets) - 1)].name if datasets else None,
163
- # )
164
- # for index, (result, _, datasets) in enumerate(search_results)
165
- # ]
166
165
 
167
166
 
168
167
  async def authorized_search(
@@ -208,11 +207,11 @@ async def authorized_search(
208
207
  context = {}
209
208
  datasets: List[Dataset] = []
210
209
 
211
- for _, search_context, datasets in search_responses:
212
- for dataset in datasets:
210
+ for _, search_context, search_datasets in search_responses:
211
+ for dataset in search_datasets:
213
212
  context[str(dataset.id)] = search_context
214
213
 
215
- datasets.extend(datasets)
214
+ datasets.extend(search_datasets)
216
215
 
217
216
  specific_search_tools = await get_search_type_tools(
218
217
  query_type=query_type,
@@ -1,8 +1,11 @@
1
1
  from typing import List, cast
2
+ from uuid import uuid5, NAMESPACE_OID
2
3
 
3
4
  from cognee.modules.graph.utils import resolve_edges_to_text
4
5
  from cognee.modules.graph.cognee_graph.CogneeGraphElements import Edge
6
+ from cognee.modules.search.types.SearchResult import SearchResultDataset
5
7
  from cognee.modules.search.utils.transform_context_to_graph import transform_context_to_graph
8
+ from cognee.modules.search.utils.transform_insights_to_graph import transform_insights_to_graph
6
9
 
7
10
 
8
11
  async def prepare_search_result(search_result):
@@ -12,29 +15,48 @@ async def prepare_search_result(search_result):
12
15
  result_graph = None
13
16
  context_texts = {}
14
17
 
15
- if isinstance(context, List) and len(context) > 0 and isinstance(context[0], Edge):
18
+ if isinstance(datasets, list) and len(datasets) == 0:
19
+ datasets = [
20
+ SearchResultDataset(
21
+ id=uuid5(NAMESPACE_OID, "*"),
22
+ name="all available datasets",
23
+ )
24
+ ]
25
+
26
+ if (
27
+ isinstance(context, List)
28
+ and len(context) > 0
29
+ and isinstance(context[0], tuple)
30
+ and context[0][1].get("relationship_name")
31
+ ):
32
+ context_graph = transform_insights_to_graph(context)
33
+ graphs = {
34
+ ", ".join([dataset.name for dataset in datasets]): context_graph,
35
+ }
36
+ results = None
37
+ elif isinstance(context, List) and len(context) > 0 and isinstance(context[0], Edge):
16
38
  context_graph = transform_context_to_graph(context)
17
39
 
18
40
  graphs = {
19
- "*": context_graph,
41
+ ", ".join([dataset.name for dataset in datasets]): context_graph,
20
42
  }
21
43
  context_texts = {
22
- "*": await resolve_edges_to_text(context),
44
+ ", ".join([dataset.name for dataset in datasets]): await resolve_edges_to_text(context),
23
45
  }
24
46
  elif isinstance(context, str):
25
47
  context_texts = {
26
- "*": context,
48
+ ", ".join([dataset.name for dataset in datasets]): context,
27
49
  }
28
50
  elif isinstance(context, List) and len(context) > 0 and isinstance(context[0], str):
29
51
  context_texts = {
30
- "*": "\n".join(cast(List[str], context)),
52
+ ", ".join([dataset.name for dataset in datasets]): "\n".join(cast(List[str], context)),
31
53
  }
32
54
 
33
55
  if isinstance(results, List) and len(results) > 0 and isinstance(results[0], Edge):
34
56
  result_graph = transform_context_to_graph(results)
35
57
 
36
58
  return {
37
- "result": result_graph or results[0] if len(results) == 1 else results,
59
+ "result": result_graph or results[0] if results and len(results) == 1 else results,
38
60
  "graphs": graphs,
39
61
  "context": context_texts,
40
62
  "datasets": datasets,
@@ -14,7 +14,7 @@ def transform_context_to_graph(context: List[Edge]):
14
14
  if "name" in triplet.node1.attributes
15
15
  else triplet.node1.id,
16
16
  "type": triplet.node1.attributes["type"],
17
- "attributes": triplet.node2.attributes,
17
+ "attributes": triplet.node1.attributes,
18
18
  }
19
19
  nodes[triplet.node2.id] = {
20
20
  "id": triplet.node2.id,
@@ -0,0 +1,28 @@
1
+ from typing import Dict, List, Tuple
2
+
3
+
4
+ def transform_insights_to_graph(context: List[Tuple[Dict, Dict, Dict]]):
5
+ nodes = {}
6
+ edges = {}
7
+
8
+ for triplet in context:
9
+ nodes[triplet[0]["id"]] = {
10
+ "id": triplet[0]["id"],
11
+ "label": triplet[0]["name"] if "name" in triplet[0] else triplet[0]["id"],
12
+ "type": triplet[0]["type"],
13
+ }
14
+ nodes[triplet[2]["id"]] = {
15
+ "id": triplet[2]["id"],
16
+ "label": triplet[2]["name"] if "name" in triplet[2] else triplet[2]["id"],
17
+ "type": triplet[2]["type"],
18
+ }
19
+ edges[f"{triplet[0]['id']}_{triplet[1]['relationship_name']}_{triplet[2]['id']}"] = {
20
+ "source": triplet[0]["id"],
21
+ "target": triplet[2]["id"],
22
+ "label": triplet[1]["relationship_name"],
23
+ }
24
+
25
+ return {
26
+ "nodes": list(nodes.values()),
27
+ "edges": list(edges.values()),
28
+ }
@@ -1,9 +1,10 @@
1
- from uuid import uuid4
1
+ from uuid import UUID, uuid4
2
2
  from fastapi_users.exceptions import UserAlreadyExists
3
+ from sqlalchemy.ext.asyncio import AsyncSession
3
4
 
4
5
  from cognee.infrastructure.databases.relational import get_relational_engine
5
- from cognee.modules.notebooks.methods import create_notebook
6
- from cognee.modules.notebooks.models.Notebook import NotebookCell
6
+ from cognee.modules.notebooks.models.Notebook import Notebook
7
+ from cognee.modules.notebooks.methods.create_notebook import _create_tutorial_notebook
7
8
  from cognee.modules.users.exceptions import TenantNotFoundError
8
9
  from cognee.modules.users.get_user_manager import get_user_manager_context
9
10
  from cognee.modules.users.get_user_db import get_user_db_context
@@ -60,27 +61,6 @@ async def create_user(
60
61
  if auto_login:
61
62
  await session.refresh(user)
62
63
 
63
- await create_notebook(
64
- user_id=user.id,
65
- notebook_name="Welcome to cognee 🧠",
66
- cells=[
67
- NotebookCell(
68
- id=uuid4(),
69
- name="Welcome",
70
- content="Cognee is your toolkit for turning text into a structured knowledge graph, optionally enhanced by ontologies, and then querying it with advanced retrieval techniques. This notebook will guide you through a simple example.",
71
- type="markdown",
72
- ),
73
- NotebookCell(
74
- id=uuid4(),
75
- name="Example",
76
- content="",
77
- type="code",
78
- ),
79
- ],
80
- deletable=False,
81
- session=session,
82
- )
83
-
84
64
  return user
85
65
  except UserAlreadyExists as error:
86
66
  print(f"User {email} already exists")
@@ -9,6 +9,18 @@ from uuid import UUID
9
9
  async def authorized_give_permission_on_datasets(
10
10
  principal_id: UUID, dataset_ids: Union[List[UUID], UUID], permission_name: str, owner_id: UUID
11
11
  ):
12
+ """
13
+ Give permission to certain datasets to a user.
14
+ The request owner must have the necessary permission to share the datasets.
15
+ Args:
16
+ principal_id: Id of user to whom datasets are shared
17
+ dataset_ids: Ids of datasets to share
18
+ permission_name: Name of permission to give
19
+ owner_id: Id of the request owner
20
+
21
+ Returns:
22
+ None
23
+ """
12
24
  # If only a single dataset UUID is provided transform it to a list
13
25
  if not isinstance(dataset_ids, list):
14
26
  dataset_ids = [dataset_ids]
@@ -10,6 +10,17 @@ logger = get_logger()
10
10
 
11
11
 
12
12
  async def check_permission_on_dataset(user: User, permission_type: str, dataset_id: UUID):
13
+ """
14
+ Check if a user has a specific permission on a dataset.
15
+ Args:
16
+ user: User whose permission is checked
17
+ permission_type: Type of permission to check
18
+ dataset_id: Id of the dataset
19
+
20
+ Returns:
21
+ None
22
+
23
+ """
13
24
  if user is None:
14
25
  user = await get_default_user()
15
26
 
@@ -1,3 +1,5 @@
1
+ from types import SimpleNamespace
2
+
1
3
  from cognee.shared.logging_utils import get_logger
2
4
 
3
5
  from ...models.User import User
@@ -9,6 +11,16 @@ logger = get_logger()
9
11
 
10
12
 
11
13
  async def get_all_user_permission_datasets(user: User, permission_type: str) -> list[Dataset]:
14
+ """
15
+ Return a list of datasets the user has permission for.
16
+ If the user is part of a tenant, return datasets his roles have permission for.
17
+ Args:
18
+ user
19
+ permission_type
20
+
21
+ Returns:
22
+ list[Dataset]: List of datasets user has permission for
23
+ """
12
24
  datasets = list()
13
25
  # Get all datasets User has explicit access to
14
26
  datasets.extend(await get_principal_datasets(user, permission_type))
@@ -17,9 +29,14 @@ async def get_all_user_permission_datasets(user: User, permission_type: str) ->
17
29
  # Get all datasets all tenants have access to
18
30
  tenant = await get_tenant(user.tenant_id)
19
31
  datasets.extend(await get_principal_datasets(tenant, permission_type))
32
+
20
33
  # Get all datasets Users roles have access to
21
- for role_name in user.roles:
22
- role = await get_role(user.tenant_id, role_name)
34
+ if isinstance(user, SimpleNamespace):
35
+ # If simple namespace use roles defined in user
36
+ roles = user.roles
37
+ else:
38
+ roles = await user.awaitable_attrs.roles
39
+ for role in roles:
23
40
  datasets.extend(await get_principal_datasets(role, permission_type))
24
41
 
25
42
  # Deduplicate datasets with same ID
@@ -8,6 +8,16 @@ from ...models import ACL, Permission
8
8
 
9
9
 
10
10
  async def get_document_ids_for_user(user_id: UUID, datasets: list[str] = None) -> list[str]:
11
+ """
12
+ Return a list of documents ids for which the user has read permission.
13
+ If datasets are specified, return only documents from those datasets.
14
+ Args:
15
+ user_id: Id of the user
16
+ datasets: List of datasets
17
+
18
+ Returns:
19
+ list[str]: List of documents for which the user has read permission
20
+ """
11
21
  db_engine = get_relational_engine()
12
22
 
13
23
  async with db_engine.get_async_session() as session:
@@ -6,6 +6,15 @@ from ...models.Principal import Principal
6
6
 
7
7
 
8
8
  async def get_principal(principal_id: UUID):
9
+ """
10
+ Return information about a user based on their id
11
+ Args:
12
+ principal_id: Id of the user
13
+
14
+ Returns:
15
+ principal: Information about the user (principal)
16
+
17
+ """
9
18
  db_engine = get_relational_engine()
10
19
 
11
20
  async with db_engine.get_async_session() as session:
@@ -9,6 +9,17 @@ from ...models.ACL import ACL
9
9
 
10
10
 
11
11
  async def get_principal_datasets(principal: Principal, permission_type: str) -> list[Dataset]:
12
+ """
13
+ Return a list of datasets for which the user (principal) has a certain permission.
14
+ Args:
15
+ principal: Information about the user
16
+ permission_type: Type of permission
17
+
18
+ Returns:
19
+ list[Dataset]: List of datasets for which the user (principal)
20
+ has the permission (permission_type).
21
+
22
+ """
12
23
  db_engine = get_relational_engine()
13
24
 
14
25
  async with db_engine.get_async_session() as session:
@@ -9,6 +9,16 @@ from ...models.Role import Role
9
9
 
10
10
 
11
11
  async def get_role(tenant_id: UUID, role_name: str):
12
+ """
13
+ Return the role with the name role_name of the given tenant.
14
+ Args:
15
+ tenant_id: Id of the given tenant
16
+ role_name: Name of the role
17
+
18
+ Returns
19
+ The role for the given tenant.
20
+
21
+ """
12
22
  db_engine = get_relational_engine()
13
23
 
14
24
  async with db_engine.get_async_session() as session:
@@ -15,9 +15,9 @@ async def get_specific_user_permission_datasets(
15
15
  Return a list of datasets user has given permission for. If a list of datasets is provided,
16
16
  verify for which datasets user has appropriate permission for and return list of datasets he has permission for.
17
17
  Args:
18
- user_id:
19
- permission_type:
20
- dataset_ids:
18
+ user_id: Id of the user.
19
+ permission_type: Type of the permission.
20
+ dataset_ids: Ids of the provided datasets
21
21
 
22
22
  Returns:
23
23
  list[Dataset]: List of datasets user has permission for
@@ -8,6 +8,15 @@ from ...models.Tenant import Tenant
8
8
 
9
9
 
10
10
  async def get_tenant(tenant_id: UUID):
11
+ """
12
+ Return information about the tenant based on the given id.
13
+ Args:
14
+ tenant_id: Id of the given tenant
15
+
16
+ Returns
17
+ Information about the given tenant.
18
+
19
+ """
11
20
  db_engine = get_relational_engine()
12
21
 
13
22
  async with db_engine.get_async_session() as session:
@@ -16,6 +16,15 @@ from cognee.modules.users.models import (
16
16
 
17
17
 
18
18
  async def give_default_permission_to_role(role_id: UUID, permission_name: str):
19
+ """
20
+ Give the permission with given name to the role with the given id as a default permission.
21
+ Args:
22
+ role_id: Id of the role
23
+ permission_name: Name of the permission
24
+
25
+ Returns:
26
+ None
27
+ """
19
28
  db_engine = get_relational_engine()
20
29
 
21
30
  async with db_engine.get_async_session() as session:
@@ -16,6 +16,15 @@ from cognee.modules.users.models import (
16
16
 
17
17
 
18
18
  async def give_default_permission_to_tenant(tenant_id: UUID, permission_name: str):
19
+ """
20
+ Give the permission with given name to the tenant with the given id as a default permission.
21
+ Args:
22
+ tenant_id: Id of the tenant
23
+ permission_name: Name of the permission
24
+
25
+ Returns:
26
+ None
27
+ """
19
28
  db_engine = get_relational_engine()
20
29
  async with db_engine.get_async_session() as session:
21
30
  tenant = (
@@ -16,6 +16,15 @@ from cognee.modules.users.models import (
16
16
 
17
17
 
18
18
  async def give_default_permission_to_user(user_id: UUID, permission_name: str):
19
+ """
20
+ Give the permission with given name to the user with the given id as a default permission.
21
+ Args:
22
+ user_id: Id of the tenant
23
+ permission_name: Name of the permission
24
+
25
+ Returns:
26
+ None
27
+ """
19
28
  db_engine = get_relational_engine()
20
29
  async with db_engine.get_async_session() as session:
21
30
  user = (await session.execute(select(User).where(User.id == user_id))).scalars().first()
@@ -24,6 +24,16 @@ async def give_permission_on_dataset(
24
24
  dataset_id: UUID,
25
25
  permission_name: str,
26
26
  ):
27
+ """
28
+ Give a specific permission on a dataset to a user.
29
+ Args:
30
+ principal: User who is being given the permission on the dataset
31
+ dataset_id: Id of the dataset
32
+ permission_name: Name of permission to give
33
+
34
+ Returns:
35
+ None
36
+ """
27
37
  db_engine = get_relational_engine()
28
38
 
29
39
  async with db_engine.get_async_session() as session:
@@ -21,6 +21,17 @@ from cognee.modules.users.models import (
21
21
 
22
22
 
23
23
  async def add_user_to_role(user_id: UUID, role_id: UUID, owner_id: UUID):
24
+ """
25
+ Add a user with the given id to the role with the given id.
26
+ Args:
27
+ user_id: Id of the user.
28
+ role_id: Id of the role.
29
+ owner_id: Id of the request owner.
30
+
31
+ Returns:
32
+ None
33
+
34
+ """
24
35
  db_engine = get_relational_engine()
25
36
  async with db_engine.get_async_session() as session:
26
37
  user = (await session.execute(select(User).where(User.id == user_id))).scalars().first()