API - add export task when data export is requested
This commit is contained in:
@ -34,6 +34,7 @@ from fittrackee.utils import get_readable_duration
|
||||
from fittrackee.workouts.models import Sport
|
||||
|
||||
from .models import BlacklistedToken, User, UserDataExport, UserSportPreference
|
||||
from .tasks import export_data
|
||||
from .utils.controls import check_password, is_valid_email, register_controls
|
||||
from .utils.token import decode_user_token
|
||||
|
||||
@ -1735,9 +1736,10 @@ def request_user_data_export(auth_user: User) -> Union[Dict, HttpResponse]:
|
||||
if not existing_export_request.completed:
|
||||
return InvalidPayloadErrorResponse("ongoing request exists")
|
||||
|
||||
if (
|
||||
existing_export_request.created_at
|
||||
> datetime.datetime.utcnow() - datetime.timedelta(hours=24)
|
||||
export_expiration = current_app.config["DATA_EXPORT_EXPIRATION"]
|
||||
if existing_export_request.created_at > (
|
||||
datetime.datetime.utcnow()
|
||||
- datetime.timedelta(hours=export_expiration)
|
||||
):
|
||||
return InvalidPayloadErrorResponse(
|
||||
"completed request already exists"
|
||||
@ -1750,6 +1752,9 @@ def request_user_data_export(auth_user: User) -> Union[Dict, HttpResponse]:
|
||||
export_request = UserDataExport(user_id=auth_user.id)
|
||||
db.session.add(export_request)
|
||||
db.session.commit()
|
||||
|
||||
export_data.send(export_request_id=export_request.id)
|
||||
|
||||
return {"status": "success", "request": export_request.serialize()}
|
||||
except (exc.IntegrityError, exc.OperationalError, ValueError) as e:
|
||||
return handle_error_and_return_response(e, db=db)
|
||||
|
@ -1,12 +1,13 @@
|
||||
import json
|
||||
import os
|
||||
import secrets
|
||||
from typing import Dict, List, Optional, Union
|
||||
from typing import Dict, List, Optional, Tuple, Union
|
||||
from zipfile import ZipFile
|
||||
|
||||
from fittrackee import appLog, db
|
||||
from fittrackee.files import get_absolute_file_path
|
||||
|
||||
from .models import User
|
||||
from .models import User, UserDataExport
|
||||
|
||||
|
||||
class UserDataExporter:
|
||||
@ -50,7 +51,7 @@ class UserDataExporter:
|
||||
export_file.write(json_object)
|
||||
return file_path
|
||||
|
||||
def generate_archive(self) -> Optional[str]:
|
||||
def generate_archive(self) -> Tuple[Optional[str], Optional[str]]:
|
||||
try:
|
||||
user_data_file_name = self.export_data(
|
||||
self.get_user_info(), "user_data"
|
||||
@ -81,6 +82,30 @@ class UserDataExporter:
|
||||
)
|
||||
|
||||
file_exists = os.path.exists(zip_path)
|
||||
return zip_file if file_exists else None
|
||||
return (zip_path, zip_file) if file_exists else (None, None)
|
||||
except Exception:
|
||||
return None
|
||||
return None, None
|
||||
|
||||
|
||||
def export_user_data(export_request_id: int) -> None:
|
||||
export_request = UserDataExport.query.filter_by(
|
||||
id=export_request_id
|
||||
).first()
|
||||
|
||||
if not export_request:
|
||||
appLog.error(f"No export to process for id '{export_request_id}'")
|
||||
return
|
||||
|
||||
if export_request.completed:
|
||||
appLog.info(f"Export id '{export_request_id}' already processed")
|
||||
return
|
||||
|
||||
user = User.query.filter_by(id=export_request.user_id).first()
|
||||
exporter = UserDataExporter(user)
|
||||
archive_file_path, archive_file_name = exporter.generate_archive()
|
||||
|
||||
export_request.completed = True
|
||||
if archive_file_name and archive_file_path:
|
||||
export_request.file_name = archive_file_name
|
||||
export_request.file_size = os.path.getsize(archive_file_path)
|
||||
db.session.commit()
|
||||
|
7
fittrackee/users/tasks.py
Normal file
7
fittrackee/users/tasks.py
Normal file
@ -0,0 +1,7 @@
|
||||
from fittrackee import dramatiq
|
||||
from fittrackee.users.export_data import export_user_data
|
||||
|
||||
|
||||
@dramatiq.actor(queue_name='fittrackee_users_exports')
|
||||
def export_data(export_request_id: int) -> None:
|
||||
export_user_data(export_request_id)
|
Reference in New Issue
Block a user