From 9a4c263390589addd59bdf60acba13c42477a095 Mon Sep 17 00:00:00 2001 From: Henry Ruhs Date: Thu, 3 Sep 2026 10:57:33 +0200 Subject: [PATCH] asset record based deletion (#1228) * asset record based deletion * fix order * delete assets on session destroy * fix style * guard delete via file system check * guard delete via file system check * adjust responses a bit --- facefusion/apis/asset_store.py | 18 +- facefusion/apis/core.py | 7 +- facefusion/apis/endpoints/assets.py | 114 +++++----- facefusion/apis/endpoints/session.py | 28 ++- facefusion/apis/endpoints/state.py | 7 +- tests/test_api_assets.py | 311 +++++++++++++++------------ tests/test_api_session.py | 46 +++- 7 files changed, 321 insertions(+), 210 deletions(-) diff --git a/facefusion/apis/asset_store.py b/facefusion/apis/asset_store.py index 9be7ad47..204fc0d1 100644 --- a/facefusion/apis/asset_store.py +++ b/facefusion/apis/asset_store.py @@ -1,6 +1,6 @@ import uuid from datetime import datetime, timedelta -from typing import List, Optional, cast +from typing import Optional, cast from facefusion.apis.asset_helper import detect_media_type_by_path, extract_image_metadata from facefusion.ffprobe import extract_audio_metadata, extract_video_metadata @@ -80,11 +80,19 @@ def get_asset(session_id : SessionId, asset_id : AssetId) -> Optional[AudioAsset return None -def delete_assets(session_id : SessionId, asset_ids : List[AssetId]) -> None: +def delete_asset(session_id : SessionId, asset_id : AssetId) -> None: if session_id in ASSET_STORE: - for asset_id in asset_ids: - if asset_id in ASSET_STORE.get(session_id): - del ASSET_STORE[session_id][asset_id] + if asset_id in ASSET_STORE.get(session_id): + del ASSET_STORE[session_id][asset_id] + + if ASSET_STORE.get(session_id) == {}: + del ASSET_STORE[session_id] + return None + + +def delete_assets(session_id : SessionId) -> None: + if session_id in ASSET_STORE: + del ASSET_STORE[session_id] return None diff --git a/facefusion/apis/core.py b/facefusion/apis/core.py index 7c2037e8..0e3a5aea 100644 --- a/facefusion/apis/core.py +++ b/facefusion/apis/core.py @@ -7,7 +7,7 @@ from starlette.middleware.cors import CORSMiddleware from starlette.routing import Route, WebSocketRoute from facefusion import content_analyser -from facefusion.apis.endpoints.assets import delete_assets, get_asset, get_assets, upload_asset +from facefusion.apis.endpoints.assets import delete_asset, delete_assets, get_asset, get_assets, upload_assets from facefusion.apis.endpoints.capabilities import get_capabilities from facefusion.apis.endpoints.jobs import create_job, create_step, delete_job, delete_jobs, delete_step, get_job, get_jobs, update_job, update_jobs from facefusion.apis.endpoints.metrics import get_metrics, websocket_metrics @@ -42,9 +42,10 @@ def create_api() -> Starlette: Route('/state', get_state, methods = [ 'GET' ], middleware = [ session_guard ]), Route('/state', set_state, methods = [ 'PUT' ], middleware = [ session_guard ]), Route('/assets', get_assets, methods = [ 'GET' ], middleware = [ session_guard ]), - Route('/assets', upload_asset, methods = [ 'POST' ], middleware = [ session_guard ]), - Route('/assets/{asset_id}', get_asset, methods = [ 'GET' ], middleware = [ session_guard ]), + Route('/assets', upload_assets, methods = [ 'POST' ], middleware = [ session_guard ]), Route('/assets', delete_assets, methods = [ 'DELETE' ], middleware = [ session_guard ]), + Route('/assets/{asset_id}', get_asset, methods = [ 'GET' ], middleware = [ session_guard ]), + Route('/assets/{asset_id}', delete_asset, methods = [ 'DELETE' ], middleware = [ session_guard ]), Route('/capabilities', get_capabilities, methods = [ 'GET' ]), Route('/metrics', get_metrics, methods = [ 'GET' ], middleware = [ session_guard ]), Route('/stream', post_stream, methods = [ 'POST' ], middleware = [ session_guard ]), diff --git a/facefusion/apis/endpoints/assets.py b/facefusion/apis/endpoints/assets.py index 26a6fbf8..fadcf74c 100644 --- a/facefusion/apis/endpoints/assets.py +++ b/facefusion/apis/endpoints/assets.py @@ -5,7 +5,7 @@ from starlette.requests import Request from starlette.responses import FileResponse, JSONResponse, Response from starlette.status import HTTP_200_OK, HTTP_201_CREATED, HTTP_400_BAD_REQUEST, HTTP_404_NOT_FOUND, HTTP_415_UNSUPPORTED_MEDIA_TYPE -from facefusion import session_context, session_manager +from facefusion import session_context, session_manager, translator from facefusion.apis import asset_store from facefusion.apis.asset_helper import capture_asset_faces, capture_asset_frames, save_asset_files, validate_asset_files from facefusion.apis.session_helper import extract_access_token @@ -13,43 +13,6 @@ from facefusion.filesystem import remove_file from facefusion.vision import is_vision_frames, to_strip_buffer -async def upload_asset(request : Request) -> Response: - access_token = extract_access_token(request.scope) - session_id = session_manager.find_session_id(access_token) - asset_type = request.query_params.get('type') - - if session_id and asset_type in [ 'source', 'target' ]: - session_context.set_session_id(session_id) - - form = await request.form() - upload_files = form.getlist('file') - - if upload_files and validate_asset_files(upload_files): - asset_paths = await save_asset_files(upload_files) - - if asset_paths: - asset_ids : List[str] = [] - - for asset_path in asset_paths: - asset = asset_store.create_asset(session_id, asset_type, asset_path) - - if asset: - asset_id = asset.get('id') - - if asset_id: - asset_ids.append(asset_id) - - if asset_ids: - return JSONResponse( - { - 'asset_ids': asset_ids - }, status_code = HTTP_201_CREATED) - - return Response(status_code = HTTP_415_UNSUPPORTED_MEDIA_TYPE) - - return Response(status_code = HTTP_400_BAD_REQUEST) - - async def get_assets(request : Request) -> Response: access_token = extract_access_token(request.scope) session_id = session_manager.find_session_id(access_token) @@ -78,7 +41,10 @@ async def get_assets(request : Request) -> Response: 'assets': assets }, status_code = HTTP_200_OK) - return Response(status_code = HTTP_400_BAD_REQUEST) + return JSONResponse( + { + 'message': translator.get('something_went_wrong', 'facefusion.apis') + }, status_code = HTTP_404_NOT_FOUND) async def get_asset(request : Request) -> Response: @@ -125,28 +91,80 @@ async def get_asset(request : Request) -> Response: 'metadata': asset.get('metadata') }, status_code = HTTP_200_OK) - return Response(status_code = HTTP_404_NOT_FOUND) + return JSONResponse( + { + 'message': translator.get('something_went_wrong', 'facefusion.apis') + }, status_code = HTTP_404_NOT_FOUND) + + +async def upload_assets(request : Request) -> Response: + access_token = extract_access_token(request.scope) + session_id = session_manager.find_session_id(access_token) + asset_type = request.query_params.get('type') + + if session_id and asset_type in [ 'source', 'target' ]: + session_context.set_session_id(session_id) + + form = await request.form() + upload_files = form.getlist('file') + + if upload_files and validate_asset_files(upload_files): + asset_paths = await save_asset_files(upload_files) + + if asset_paths: + asset_ids : List[str] = [] + + for asset_path in asset_paths: + asset = asset_store.create_asset(session_id, asset_type, asset_path) + + if asset: + asset_id = asset.get('id') + + if asset_id: + asset_ids.append(asset_id) + + if asset_ids: + return JSONResponse( + { + 'asset_ids': asset_ids + }, status_code = HTTP_201_CREATED) + + return Response(status_code = HTTP_415_UNSUPPORTED_MEDIA_TYPE) + + return Response(status_code = HTTP_400_BAD_REQUEST) async def delete_assets(request : Request) -> Response: access_token = extract_access_token(request.scope) session_id = session_manager.find_session_id(access_token) - body = await request.json() - asset_ids = body.get('asset_ids') - if session_id and asset_ids: + if session_id: asset_set = asset_store.get_assets(session_id) + asset_ids : List[str] = [] if asset_set: + for asset in asset_set.values(): + if remove_file(asset.get('path')): + asset_ids.append(asset.get('id')) for asset_id in asset_ids: - if asset_id in asset_set: - asset = asset_set.get(asset_id) + asset_store.delete_asset(session_id, asset_id) - if asset: - remove_file(asset.get('path')) + return Response(status_code = HTTP_200_OK) - asset_store.delete_assets(session_id, asset_ids) + return Response(status_code = HTTP_404_NOT_FOUND) + + +async def delete_asset(request : Request) -> Response: + access_token = extract_access_token(request.scope) + session_id = session_manager.find_session_id(access_token) + asset_id = request.path_params.get('asset_id') + + if session_id and asset_id: + asset = asset_store.get_asset(session_id, asset_id) + + if asset and remove_file(asset.get('path')): + asset_store.delete_asset(session_id, asset_id) return Response(status_code = HTTP_200_OK) return Response(status_code = HTTP_404_NOT_FOUND) diff --git a/facefusion/apis/endpoints/session.py b/facefusion/apis/endpoints/session.py index 4936a2b5..68c5c65b 100644 --- a/facefusion/apis/endpoints/session.py +++ b/facefusion/apis/endpoints/session.py @@ -3,10 +3,12 @@ import secrets from starlette.requests import Request from starlette.responses import JSONResponse -from starlette.status import HTTP_200_OK, HTTP_201_CREATED, HTTP_401_UNAUTHORIZED +from starlette.status import HTTP_200_OK, HTTP_201_CREATED, HTTP_401_UNAUTHORIZED, HTTP_404_NOT_FOUND -from facefusion import session_context, session_manager, translator +from facefusion import session_context, session_manager, state_manager, translator +from facefusion.apis import asset_store from facefusion.apis.session_helper import extract_access_token +from facefusion.filesystem import remove_directory async def create_session(request : Request) -> JSONResponse: @@ -67,9 +69,25 @@ async def refresh_session(request : Request) -> JSONResponse: async def destroy_session(request : Request) -> JSONResponse: access_token = extract_access_token(request.scope) session_id = session_manager.find_session_id(access_token) - session_manager.clear_session(session_id) + + if session_id: + session_context.set_session_id(session_id) + + if remove_directory(state_manager.get_temp_path()): + asset_store.delete_assets(session_id) + session_manager.clear_session(session_id) + + return JSONResponse( + { + 'message': translator.get('ok', 'facefusion.apis') + }, status_code = HTTP_200_OK) + + return JSONResponse( + { + 'message': translator.get('something_went_wrong', 'facefusion.apis') + }, status_code = HTTP_404_NOT_FOUND) return JSONResponse( { - 'message': translator.get('ok', 'facefusion.apis') - }, status_code = HTTP_200_OK) + 'message': translator.get('something_went_wrong', 'facefusion.apis') + }, status_code = HTTP_401_UNAUTHORIZED) diff --git a/facefusion/apis/endpoints/state.py b/facefusion/apis/endpoints/state.py index 6ac5463f..1a1a1c5a 100644 --- a/facefusion/apis/endpoints/state.py +++ b/facefusion/apis/endpoints/state.py @@ -1,5 +1,5 @@ from starlette.requests import Request -from starlette.responses import JSONResponse +from starlette.responses import JSONResponse, Response from starlette.status import HTTP_200_OK, HTTP_400_BAD_REQUEST, HTTP_404_NOT_FOUND, HTTP_422_UNPROCESSABLE_CONTENT from facefusion import args_helper, capability_store, session_manager, state_manager, translator @@ -12,7 +12,7 @@ async def get_state(request : Request) -> JSONResponse: return JSONResponse(state_manager.collect_state(api_args), status_code = HTTP_200_OK) -async def set_state(request : Request) -> JSONResponse: +async def set_state(request : Request) -> Response: __api_args__ = {} action = request.query_params.get('action') @@ -33,6 +33,7 @@ async def set_state(request : Request) -> JSONResponse: { 'message': translator.get('invalid_state_key', 'facefusion.apis') }, status_code = HTTP_400_BAD_REQUEST) + __api_args__[key] = value if __api_args__: @@ -43,7 +44,7 @@ async def set_state(request : Request) -> JSONResponse: __api_args__ = args_helper.extract_api_args(state_manager.get_state()) return JSONResponse(state_manager.collect_state(__api_args__), status_code = HTTP_200_OK) - return JSONResponse({}, status_code = HTTP_422_UNPROCESSABLE_CONTENT) + return Response(status_code = HTTP_422_UNPROCESSABLE_CONTENT) async def select_source(request : Request) -> JSONResponse: diff --git a/tests/test_api_assets.py b/tests/test_api_assets.py index 4f2ffc2f..bf90bfb7 100644 --- a/tests/test_api_assets.py +++ b/tests/test_api_assets.py @@ -1,3 +1,4 @@ +import os import tempfile from typing import Iterator @@ -47,98 +48,105 @@ def test_client() -> Iterator[TestClient]: yield test_client -def test_upload_asset(test_client : TestClient) -> None: +def test_upload_assets(test_client : TestClient) -> None: upload_response = test_client.post('/assets?type=source') assert upload_response.status_code == 401 - create_session_response = test_client.post('/session', json = - { - 'client_version': metadata.get('version') - }) - create_session_body = create_session_response.json() - access_token = create_session_body.get('access_token') - session_id = session_manager.find_session_id(access_token) - source_path = get_test_example_file('source.jpg') target_image_path = get_test_example_file('target-240p.jpg') target_video_path = get_test_example_file('target-240p.mp4') - - with open(source_path, 'rb') as source_file: - upload_response = test_client.post('/assets?type=source', headers = - { - 'Authorization': 'Bearer ' + access_token - }, files = - [ - ('file', ('source.jpg', source_file.read(), 'image/jpeg')) - ]) - asset_ids = upload_response.json().get('asset_ids') - asset = asset_store.get_asset(session_id, asset_ids[0]) - - assert asset.get('media') == 'image' - assert asset.get('type') == 'source' - assert asset.get('format') == 'jpeg' - assert upload_response.status_code == 201 - - with open(target_image_path, 'rb') as target_image_file, open(target_video_path, 'rb') as target_video_file: - upload_response = test_client.post('/assets?type=target', headers = - { - 'Authorization': 'Bearer ' + access_token - }, files = - [ - ('file', ('target-240p.jpg', target_image_file.read(), 'image/jpeg')), - ('file', ('target-240p.mp4', target_video_file.read(), 'video/mp4')) - ]) - asset_ids = upload_response.json().get('asset_ids') - - assert asset_store.get_asset(session_id, asset_ids[0]).get('media') == 'image' - assert asset_store.get_asset(session_id, asset_ids[0]).get('type') == 'target' - assert asset_store.get_asset(session_id, asset_ids[0]).get('format') == 'jpeg' - assert asset_store.get_asset(session_id, asset_ids[1]).get('media') == 'video' - assert asset_store.get_asset(session_id, asset_ids[1]).get('type') == 'target' - assert asset_store.get_asset(session_id, asset_ids[1]).get('format') == 'mp4' - assert upload_response.status_code == 201 - audio_path = get_test_example_file('source.mp3') - with open(audio_path, 'rb') as audio_file: + for security_strategy in [ 'strict', 'moderate' ]: + state_manager.init_item('api_security_strategy', security_strategy) + + create_session_response = test_client.post('/session', json = + { + 'client_version': metadata.get('version') + }) + create_session_body = create_session_response.json() + access_token = create_session_body.get('access_token') + session_id = session_manager.find_session_id(access_token) + + with open(source_path, 'rb') as source_file: + upload_response = test_client.post('/assets?type=source', headers = + { + 'Authorization': 'Bearer ' + access_token + }, files = + [ + ('file', ('source.jpg', source_file.read(), 'image/jpeg')) + ]) + + asset_ids = upload_response.json().get('asset_ids') + asset = asset_store.get_asset(session_id, asset_ids[0]) + + assert asset.get('media') == 'image' + assert asset.get('type') == 'source' + assert asset.get('format') == 'jpeg' + assert upload_response.status_code == 201 + + with open(target_image_path, 'rb') as target_image_file, open(target_video_path, 'rb') as target_video_file: + upload_response = test_client.post('/assets?type=target', headers = + { + 'Authorization': 'Bearer ' + access_token + }, files = + [ + ('file', ('target-240p.jpg', target_image_file.read(), 'image/jpeg')), + ('file', ('target-240p.mp4', target_video_file.read(), 'video/mp4')) + ]) + + asset_ids = upload_response.json().get('asset_ids') + + assert asset_store.get_asset(session_id, asset_ids[0]).get('media') == 'image' + assert asset_store.get_asset(session_id, asset_ids[0]).get('type') == 'target' + assert asset_store.get_asset(session_id, asset_ids[0]).get('format') == 'jpeg' + assert asset_store.get_asset(session_id, asset_ids[1]).get('media') == 'video' + assert asset_store.get_asset(session_id, asset_ids[1]).get('type') == 'target' + assert asset_store.get_asset(session_id, asset_ids[1]).get('format') == 'mp4' + assert upload_response.status_code == 201 + + with open(audio_path, 'rb') as audio_file: + upload_response = test_client.post('/assets?type=source', headers = + { + 'Authorization': 'Bearer ' + access_token + }, files = + [ + ('file', ('source.mp3', audio_file.read(), 'audio/mpeg')) + ]) + + asset_ids = upload_response.json().get('asset_ids') + asset = asset_store.get_asset(session_id, asset_ids[0]) + + assert asset.get('media') == 'audio' + assert asset.get('type') == 'source' + assert upload_response.status_code == 201 + + upload_response = test_client.post('/assets?type=invalid', headers = + { + 'Authorization': 'Bearer ' + access_token + }) + + assert upload_response.status_code == 400 + + upload_response = test_client.post('/assets?type=source', headers = + { + 'Authorization': 'Bearer ' + access_token + }) + + assert upload_response.status_code == 400 + upload_response = test_client.post('/assets?type=source', headers = { 'Authorization': 'Bearer ' + access_token }, files = - [ - ('file', ('source.mp3', audio_file.read(), 'audio/mpeg')) - ]) - asset_ids = upload_response.json().get('asset_ids') - asset = asset_store.get_asset(session_id, asset_ids[0]) + { + 'file': ('invalid.txt', 'invalid'.encode(), 'text/plain') + }) - assert asset.get('media') == 'audio' - assert asset.get('type') == 'source' - assert upload_response.status_code == 201 + assert upload_response.status_code == 415 - upload_response = test_client.post('/assets?type=invalid', headers = - { - 'Authorization': 'Bearer ' + access_token - }) - - assert upload_response.status_code == 400 - - upload_response = test_client.post('/assets?type=source', headers = - { - 'Authorization': 'Bearer ' + access_token - }) - - assert upload_response.status_code == 400 - - upload_response = test_client.post('/assets?type=source', headers = - { - 'Authorization': 'Bearer ' + access_token - }, files = - { - 'file': ('invalid.txt', 'invalid'.encode(), 'text/plain') - }) - - assert upload_response.status_code == 415 + state_manager.init_item('api_security_strategy', 'strict') def test_get_assets(test_client : TestClient) -> None: @@ -223,6 +231,7 @@ def test_get_asset(test_client : TestClient) -> None: [ ('file', ('source.jpg', source_file.read(), 'image/jpeg')) ]) + asset_ids = upload_response.json().get('asset_ids') second_session_response = test_client.post('/session', json = @@ -264,18 +273,35 @@ def test_delete_assets(test_client : TestClient) -> None: session_id = session_manager.find_session_id(access_token) source_path = get_test_example_file('source.jpg') + target_image_path = get_test_example_file('target-240p.jpg') + target_video_path = get_test_example_file('target-240p.mp4') with open(source_path, 'rb') as source_file: - upload_response = test_client.post('/assets?type=source', headers = + test_client.post('/assets?type=source', headers = { 'Authorization': 'Bearer ' + access_token }, files = [ ('file', ('source.jpg', source_file.read(), 'image/jpeg')) ]) - asset_ids = upload_response.json().get('asset_ids') - assert asset_store.get_asset(session_id, asset_ids[0]) + with open(target_image_path, 'rb') as target_image_file, open(target_video_path, 'rb') as target_video_file: + test_client.post('/assets?type=target', headers = + { + 'Authorization': 'Bearer ' + access_token + }, files = + [ + ('file', ('target-240p.jpg', target_image_file.read(), 'image/jpeg')), + ('file', ('target-240p.mp4', target_video_file.read(), 'video/mp4')) + ]) + + asset_paths = [] + + for asset in asset_store.get_assets(session_id).values(): + asset_paths.append(asset.get('path')) + + for asset_path in asset_paths: + assert os.path.exists(asset_path) is True second_session_response = test_client.post('/session', json = { @@ -287,76 +313,77 @@ def test_delete_assets(test_client : TestClient) -> None: delete_response = test_client.request('DELETE', '/assets', headers = { 'Authorization': 'Bearer ' + second_access_token - }, json = - { - 'asset_ids': asset_ids - }) - - assert delete_response.status_code == 404 - - delete_response = test_client.request('DELETE', '/assets', headers = - { - 'Authorization': 'Bearer ' + access_token - }, json = - { - 'asset_ids': asset_ids }) assert delete_response.status_code == 200 + for asset_path in asset_paths: + assert os.path.exists(asset_path) is True + delete_response = test_client.request('DELETE', '/assets', headers = { 'Authorization': 'Bearer ' + access_token - }, json = + }) + + assert asset_store.get_assets(session_id) is None + assert delete_response.status_code == 200 + + for asset_path in asset_paths: + assert os.path.exists(asset_path) is False + + +def test_delete_asset(test_client : TestClient) -> None: + create_session_response = test_client.post('/session', json = { - 'asset_ids': asset_ids + 'client_version': metadata.get('version') + }) + create_session_body = create_session_response.json() + access_token = create_session_body.get('access_token') + session_id = session_manager.find_session_id(access_token) + + source_path = get_test_example_file('source.jpg') + + with open(source_path, 'rb') as source_file: + upload_response = test_client.post('/assets?type=source', headers = + { + 'Authorization': 'Bearer ' + access_token + }, files = + [ + ('file', ('source.jpg', source_file.read(), 'image/jpeg')) + ]) + + asset_ids = upload_response.json().get('asset_ids') + asset_path = asset_store.get_asset(session_id, asset_ids[0]).get('path') + + assert os.path.exists(asset_path) is True + + second_session_response = test_client.post('/session', json = + { + 'client_version': metadata.get('version') + }) + second_session_body = second_session_response.json() + second_access_token = second_session_body.get('access_token') + + delete_response = test_client.request('DELETE', '/assets/' + asset_ids[0], headers = + { + 'Authorization': 'Bearer ' + second_access_token + }) + + assert os.path.exists(asset_path) is True + assert delete_response.status_code == 404 + + delete_response = test_client.request('DELETE', '/assets/' + asset_ids[0], headers = + { + 'Authorization': 'Bearer ' + access_token + }) + + assert os.path.exists(asset_path) is False + assert asset_store.get_asset(session_id, asset_ids[0]) is None + assert delete_response.status_code == 200 + + delete_response = test_client.request('DELETE', '/assets/' + asset_ids[0], headers = + { + 'Authorization': 'Bearer ' + access_token }) assert delete_response.status_code == 404 - - -def test_upload_asset_security_strategies(test_client : TestClient) -> None: - source_path = get_test_example_file('source.jpg') - target_image_path = get_test_example_file('target-240p.jpg') - target_video_path = get_test_example_file('target-240p.mp4') - - for strategy in [ 'strict', 'moderate' ]: - state_manager.init_item('api_security_strategy', strategy) - - create_session_response = test_client.post('/session', json = - { - 'client_version': metadata.get('version') - }) - access_token = create_session_response.json().get('access_token') - session_id = session_manager.find_session_id(access_token) - - with open(source_path, 'rb') as source_file: - source_upload_response = test_client.post('/assets?type=source', headers = - { - 'Authorization': 'Bearer ' + access_token - }, files = - [ - ('file', ('source.jpg', source_file.read(), 'image/jpeg')) - ]) - - with open(target_image_path, 'rb') as target_image_file, open(target_video_path, 'rb') as target_video_file: - target_upload_response = test_client.post('/assets?type=target', headers = - { - 'Authorization': 'Bearer ' + access_token - }, files = - [ - ('file', ('target-240p.jpg', target_image_file.read(), 'image/jpeg')), - ('file', ('target-240p.mp4', target_video_file.read(), 'video/mp4')) - ]) - - assert source_upload_response.status_code == 201 - assert target_upload_response.status_code == 201 - - source_asset_id = source_upload_response.json().get('asset_ids')[0] - target_asset_ids = target_upload_response.json().get('asset_ids') - - assert asset_store.get_asset(session_id, source_asset_id).get('media') == 'image' - assert asset_store.get_asset(session_id, target_asset_ids[0]).get('media') == 'image' - assert asset_store.get_asset(session_id, target_asset_ids[1]).get('media') == 'video' - - state_manager.init_item('api_security_strategy', 'strict') diff --git a/tests/test_api_session.py b/tests/test_api_session.py index e533a1cc..54396d7c 100644 --- a/tests/test_api_session.py +++ b/tests/test_api_session.py @@ -1,18 +1,33 @@ import os +import tempfile from datetime import timedelta from typing import Iterator import pytest from starlette.testclient import TestClient -from facefusion import metadata, session_manager +from facefusion import metadata, process_manager, session_manager, state_manager +from facefusion.apis import asset_store from facefusion.apis.core import create_api +from facefusion.download import conditional_download from facefusion.types import Session +from .assert_helper import get_test_example_file, get_test_examples_directory + + +@pytest.fixture(scope = 'module', autouse = True) +def before_all() -> None: + process_manager.start() + conditional_download(get_test_examples_directory(), + [ + 'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/source.jpg' + ]) @pytest.fixture(scope = 'function', autouse = True) def before_each() -> None: + state_manager.init_item('temp_path', tempfile.gettempdir()) session_manager.SESSIONS.clear() + asset_store.clear() @pytest.fixture(scope = 'module') @@ -161,6 +176,23 @@ def test_destroy_session(test_client : TestClient) -> None: 'client_version': metadata.get('version') }) create_session_body = create_session_response.json() + access_token = create_session_body.get('access_token') + session_id = session_manager.find_session_id(access_token) + source_path = get_test_example_file('source.jpg') + + with open(source_path, 'rb') as source_file: + test_client.post('/assets?type=source', headers = + { + 'Authorization': 'Bearer ' + access_token + }, files = + [ + ('file', ('source.jpg', source_file.read(), 'image/jpeg')) + ]) + + asset_paths = [] + + for asset in asset_store.get_assets(session_id).values(): + asset_paths.append(asset.get('path')) delete_session_response = test_client.delete('/session', headers = { @@ -169,11 +201,17 @@ def test_destroy_session(test_client : TestClient) -> None: assert delete_session_response.status_code == 401 + for asset_path in asset_paths: + assert os.path.exists(asset_path) is True + delete_session_response = test_client.delete('/session', headers = { - 'Authorization': 'Bearer ' + create_session_body.get('access_token') + 'Authorization': 'Bearer ' + access_token }) - assert session_manager.find_session_id(create_session_body.get('access_token')) is None - + assert session_manager.find_session_id(access_token) is None + assert asset_store.get_assets(session_id) is None assert delete_session_response.status_code == 200 + + for asset_path in asset_paths: + assert os.path.exists(asset_path) is False