Skip to content

Commit 089e70b

Browse files
committed
Added: basic structure for parent doc db class (#15)
1 parent 3485008 commit 089e70b

File tree

1 file changed

+135
-20
lines changed

1 file changed

+135
-20
lines changed

libreforms_fastapi/utils/document_database.py

+135-20
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,111 @@
1-
import os, shutil
1+
import os, shutil, json
22
from datetime import datetime
33
from tinydb import TinyDB, Query
4+
from abc import ABC, abstractmethod
45

56
class CollectionDoesNotExist(Exception):
67
"""Exception raised when attempting to access a collection that does not exist."""
78
def __init__(self, form_name):
89
message = f"The collection '{form_name}' does not exist."
910
super().__init__(message)
1011

11-
class ManageTinyDB:
12-
def __init__(self, config: dict, db_path: str = "instance/"):
12+
class ManageDocumentDB(ABC):
13+
def __init__(self, config: dict):
1314
self.config = config
15+
16+
# Here we'll set metadata field names
17+
self.is_deleted_field = "_is_deleted"
18+
self.created_at_field = "_created_at"
19+
self.last_modified_field = "_last_modified"
20+
self.ip_address_field = "_ip_address"
21+
self.created_by_field = "_created_by"
22+
self.signature_field = "_signature"
23+
self.last_editor_field = "_last_editor"
24+
self.approved_field = "_approved"
25+
self.approved_by_field = "_approved_by"
26+
self.approval_signature_field = "_approval_signature"
27+
28+
# Finally we'll initialize the database instances
29+
self._initialize_database_collections()
30+
31+
@abstractmethod
32+
def _initialize_database_collections(self):
33+
"""Establishes database instances / collections for each form."""
34+
pass
35+
36+
@abstractmethod
37+
def _check_form_exists(self, form_name:str):
38+
"""Checks if the form exists in the configuration."""
39+
pass
40+
41+
@abstractmethod
42+
def create_document(self, form_name:str, json_data):
43+
"""Adds an entry to the specified form's database."""
44+
pass
45+
46+
@abstractmethod
47+
def update_document(self, form_name:str, json_data, metadata={}):
48+
"""Updates existing form in specified form's database."""
49+
pass
50+
51+
@abstractmethod
52+
def sign_document(self, form_name:str, json_data, metadata={}):
53+
"""Manage signatures existing form in specified form's database."""
54+
pass
55+
56+
@abstractmethod
57+
def approve_document(self, form_name:str, json_data, metadata={}):
58+
"""Manage approval for existing form in specified form's database."""
59+
pass
60+
61+
@abstractmethod
62+
def search_documents(self, form_name:str, search_query, exclude_deleted=True):
63+
"""Searches for entries that match the search query."""
64+
pass
65+
66+
@abstractmethod
67+
def delete_document(self, form_name:str, search_query, permanent:bool=False):
68+
"""Deletes entries that match the search query, permanently or soft delete."""
69+
pass
70+
71+
@abstractmethod
72+
def get_all_documents(self, form_name:str, exclude_deleted=True):
73+
"""Retrieves all entries from the specified form's database."""
74+
pass
75+
76+
@abstractmethod
77+
def get_one_document(self, form_name:str, search_query, exclude_deleted=True):
78+
"""Retrieves a single entry that matches the search query."""
79+
pass
80+
81+
@abstractmethod
82+
def restore_document(self, form_name:str, search_query):
83+
"""Restores soft deleted entries that match the search query."""
84+
pass
85+
86+
@abstractmethod
87+
def backup_database(self, form_name:str):
88+
"""Creates a backup of the specified form's database."""
89+
pass
90+
91+
@abstractmethod
92+
def restore_database_from_backup(self, form_name:str, backup_filename:str, backup_before_overwriting:bool=True):
93+
"""Restores the specified form's database from its backup."""
94+
pass
95+
96+
97+
class ManageTinyDB(ManageDocumentDB):
98+
def __init__(self, config: dict, db_path: str = "instance/"):
1499
self.db_path = db_path
15100
os.makedirs(self.db_path, exist_ok=True)
16101

102+
super().__init__(config)
17103

18104
# Here we create a Query object to ship with the class
19105
self.Form = Query()
20106

21-
# Here we'll set metadata field names
22-
self.is_deleted_field = "_is_deleted"
23-
24-
# Finally we'll initialize the database instances
25-
self._initialize_database_instances()
26107

27-
def _initialize_database_instances(self):
108+
def _initialize_database_collections(self):
28109
"""Establishes database instances for each form."""
29110
# Initialize databases
30111
self.databases = {}
@@ -35,26 +116,60 @@ def _get_db_path(self, form_name:str):
35116
"""Constructs a file path for the given form's database."""
36117
return os.path.join(self.db_path, f"{form_name}.json")
37118

38-
def _check_form_exists(self, form_name):
119+
def _check_form_exists(self, form_name:str):
39120
"""Checks if the form exists in the configuration."""
40121
if form_name not in self.config:
41122
raise CollectionDoesNotExist(form_name)
42123

43-
def add_entry(self, form_name:str, entry):
44-
"""Adds an entry to the specified form's database."""
124+
def create_document(self, form_name:str, json_data, metadata={}):
125+
"""Adds json data to the specified form's database."""
45126
self._check_form_exists(form_name)
46-
document_id = self.databases[form_name].insert(entry)
127+
128+
current_timestamp = datetime.now()
129+
130+
# data_dict = json.loads(json_data)
131+
data_dict = {
132+
"data": json_data,
133+
"metadata": {
134+
self.is_deleted_field: metadata.get(self.is_deleted_field, False),
135+
self.created_at_field: metadata.get(self.created_at_field, current_timestamp.isoformat()),
136+
self.last_modified_field: metadata.get(self.last_modified_field, current_timestamp.isoformat()),
137+
self.ip_address_field: metadata.get(self.ip_address_field, None),
138+
self.created_by_field: metadata.get(self.created_by_field, None),
139+
self.signature_field: metadata.get(self.signature_field, None),
140+
self.last_editor_field: metadata.get(self.last_editor_field, None),
141+
self.approved_field: metadata.get(self.approved_field, None),
142+
self.approved_by_field: metadata.get(self.approved_by_field, None),
143+
self.approval_signature_field: metadata.get(self.approval_signature_field, None),
144+
}
145+
}
146+
147+
document_id = self.databases[form_name].insert(data_dict)
47148

48149
return document_id
49150

50-
def search_entries(self, form_name:str, search_query, exclude_deleted=True):
151+
def update_document(self, form_name:str, json_data, metadata={}):
152+
"""Updates existing form in specified form's database."""
153+
pass
154+
155+
def sign_document(self, form_name:str, json_data, metadata={}):
156+
"""Manage signatures existing form in specified form's database."""
157+
pass
158+
159+
160+
def approve_document(self, form_name:str, json_data, metadata={}):
161+
"""Manage approval for existing form in specified form's database."""
162+
pass
163+
164+
165+
def search_documents(self, form_name:str, search_query, exclude_deleted=True):
51166
"""Searches for entries that match the search query."""
52167
self._check_form_exists(form_name)
53168
if exclude_deleted:
54169
search_query &= Query()[self.is_deleted_field] == False
55170
return self.databases[form_name].search(search_query)
56171

57-
def delete_entry(self, form_name:str, search_query, permanent=False):
172+
def delete_document(self, form_name:str, search_query, permanent:bool=False):
58173
"""Deletes entries that match the search query, permanently or soft delete."""
59174
self._check_form_exists(form_name)
60175
if permanent:
@@ -64,22 +179,22 @@ def delete_entry(self, form_name:str, search_query, permanent=False):
64179
for doc_id in [d.doc_id for d in self.databases[form_name].search(search_query)]:
65180
self.databases[form_name].update({self.is_deleted_field: True}, doc_ids=[doc_id])
66181

67-
def get_all_entries(self, form_name:str, exclude_deleted=True):
182+
def get_all_documents(self, form_name:str, exclude_deleted=True):
68183
"""Retrieves all entries from the specified form's database."""
69184
self._check_form_exists(form_name)
70185
if exclude_deleted:
71186
return self.databases[form_name].search(Query()[self.is_deleted_field] == False)
72187
else:
73188
return self.databases[form_name].all()
74189

75-
def get_one_entry(self, form_name:str, search_query, exclude_deleted=True):
190+
def get_one_document(self, form_name:str, search_query, exclude_deleted=True):
76191
"""Retrieves a single entry that matches the search query."""
77192
self._check_form_exists(form_name)
78193
if exclude_deleted:
79194
search_query &= Query()[self.is_deleted_field] == False
80195
return self.databases[form_name].get(search_query)
81196

82-
def restore_entry(self, form_name:str, search_query):
197+
def restore_document(self, form_name:str, search_query):
83198
"""Restores soft deleted entries that match the search query."""
84199
self._check_form_exists(form_name)
85200
for doc_id in [d.doc_id for d in self.databases[form_name].search(search_query)]:
@@ -120,7 +235,7 @@ def restore_database_from_backup(self, form_name:str, backup_filename:str, backu
120235
raise FileNotFoundError("Backup file does not exist.")
121236

122237
# Reinitialize the databse instances
123-
self._initialize_database_instances()
238+
self._initialize_database_collections()
124239

125-
class ManageMongoDB:
240+
class ManageMongoDB(ManageDocumentDB):
126241
pass

0 commit comments

Comments
 (0)