Skip to content

Commit

Permalink
Added: restore API path (#63)
Browse files Browse the repository at this point in the history
  • Loading branch information
signebedi committed Mar 25, 2024
1 parent 9a601c0 commit 6781928
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 11 deletions.
87 changes: 86 additions & 1 deletion libreforms_fastapi/app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@
CollectionDoesNotExist,
DocumentDoesNotExist,
DocumentIsDeleted,
InsufficientPermissions
InsufficientPermissions,
DocumentIsNotDeleted,
)

from libreforms_fastapi.utils.pydantic_models import (
Expand Down Expand Up @@ -753,6 +754,90 @@ async def api_form_delete(form_name: str, document_id:str, background_tasks: Bac
}


@app.patch("/api/form/restore/{form_name}/{document_id}", dependencies=[Depends(api_key_auth)])
async def api_form_restore(form_name: str, document_id:str, background_tasks: BackgroundTasks, request: Request, session: SessionLocal = Depends(get_db), key: str = Depends(X_API_KEY)):

if form_name not in get_form_names():
raise HTTPException(status_code=404, detail=f"Form '{form_name}' not found")

# Ugh, I'd like to find a more efficient way to get the user data. But alas, that
# the sqlalchemy-signing table is not optimized alongside the user model...
user = session.query(User).filter_by(api_key=key).first()

# Here we validate the user groups permit this level of access to the form
try:
user.validate_permission(form_name=form_name, required_permission="update_own")
# print("\n\n\nUser has valid permissions\n\n\n")
except Exception as e:
raise HTTPException(status_code=403, detail=f"{e}")

# Here, if the user is not able to see other user's data, then we denote the constraint.
try:
user.validate_permission(form_name=form_name, required_permission="update_all")
limit_query_to = False
except Exception as e:
limit_query_to = user.username

metadata={
DocumentDatabase.last_editor_field: user.username,
}

# Add the remote addr host if enabled
if config.COLLECT_USAGE_STATISTICS:
metadata[DocumentDatabase.ip_address_field] = request.client.host

try:
# Process the request as needed
success = DocumentDatabase.delete_document(
form_name=form_name,
document_id=document_id,
metadata=metadata,
restore=True,
)

# Unlike other methods, like get_one_document or fuzzy_search_documents, this method raises exceptions when
# it fails to ensure the user knows their operation was not successful.
except DocumentDoesNotExist as e:
raise HTTPException(status_code=404, detail=f"{e}")

except DocumentIsNotDeleted as e:
raise HTTPException(status_code=200, detail=f"{e}")

except InsufficientPermissions as e:
raise HTTPException(status_code=403, detail=f"{e}")


# Send email
if config.SMTP_ENABLED:
background_tasks.add_task(
mailer.send_mail,
subject="Form Submitted",
content=document_id,
to_address=user.email,
)


# Write this query to the TransactionLog
if config.COLLECT_USAGE_STATISTICS:

endpoint = request.url.path
remote_addr = request.client.host

background_tasks.add_task(
write_api_call_to_transaction_log,
api_key=key,
endpoint=endpoint,
remote_addr=remote_addr,
query_params={},
)

return {
"message": "Form successfully restored",
"document_id": document_id,
}



# Search forms
@app.get("/api/form/search/{form_name}")
async def api_form_search(form_name: str, background_tasks: BackgroundTasks, request: Request, session: SessionLocal = Depends(get_db), key: str = Depends(X_API_KEY), search_term: str = Query(None, title="Search Term")):
Expand Down
20 changes: 10 additions & 10 deletions libreforms_fastapi/utils/document_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,10 +273,10 @@ def get_one_document(self, form_name:str, search_query, exclude_deleted:bool=Tru
"""Retrieves a single entry that matches the search query."""
pass

@abstractmethod
def restore_document(self, form_name:str, search_query):
"""Restores soft deleted entries that match the search query."""
pass
# @abstractmethod
# def restore_document(self, form_name:str, search_query):
# """Restores soft deleted entries that match the search query."""
# pass

@abstractmethod
def backup_collection(self, form_name:str):
Expand Down Expand Up @@ -628,13 +628,13 @@ def get_one_document(self, form_name:str, document_id:str, limit_users:Union[boo

return document

def restore_document(self, form_name:str, search_query):
"""Restores soft deleted entries that match the search query."""
self._check_form_exists(form_name)
for doc_id in [d.doc_id for d in self.databases[form_name].search(search_query)]:
self.databases[form_name].update({self.is_deleted_field: False}, doc_ids=[doc_id])
# def restore_document(self, form_name:str, search_query):
# """Restores soft deleted entries that match the search query."""
# self._check_form_exists(form_name)
# for doc_id in [d.doc_id for d in self.databases[form_name].search(search_query)]:
# self.databases[form_name].update({self.is_deleted_field: False}, doc_ids=[doc_id])

# Placeholder for logger
# # Placeholder for logger

def backup_collection(self, form_name:str):
"""Creates a backup of the specified form's database."""
Expand Down

0 comments on commit 6781928

Please sign in to comment.