mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Feature: documents trash aka soft delete (#6944)
This commit is contained in:
		| @@ -62,7 +62,7 @@ def paths_check(app_configs, **kwargs): | ||||
|  | ||||
|     return ( | ||||
|         path_check("PAPERLESS_DATA_DIR", settings.DATA_DIR) | ||||
|         + path_check("PAPERLESS_TRASH_DIR", settings.TRASH_DIR) | ||||
|         + path_check("PAPERLESS_EMPTY_TRASH_DIR", settings.EMPTY_TRASH_DIR) | ||||
|         + path_check("PAPERLESS_MEDIA_ROOT", settings.MEDIA_ROOT) | ||||
|         + path_check("PAPERLESS_CONSUMPTION_DIR", settings.CONSUMPTION_DIR) | ||||
|     ) | ||||
|   | ||||
| @@ -207,6 +207,17 @@ def _parse_beat_schedule() -> dict: | ||||
|                 "expires": ((7.0 * 24.0) - 1.0) * 60.0 * 60.0, | ||||
|             }, | ||||
|         }, | ||||
|         { | ||||
|             "name": "Empty trash", | ||||
|             "env_key": "PAPERLESS_EMPTY_TRASH_TASK_CRON", | ||||
|             # Default daily at 01:00 | ||||
|             "env_default": "0 1 * * *", | ||||
|             "task": "documents.tasks.empty_trash", | ||||
|             "options": { | ||||
|                 # 1 hour before default schedule sends again | ||||
|                 "expires": 23.0 * 60.0 * 60.0, | ||||
|             }, | ||||
|         }, | ||||
|     ] | ||||
|     for task in tasks: | ||||
|         # Either get the environment setting or use the default | ||||
| @@ -250,7 +261,11 @@ DATA_DIR = __get_path("PAPERLESS_DATA_DIR", BASE_DIR.parent / "data") | ||||
|  | ||||
| NLTK_DIR = __get_path("PAPERLESS_NLTK_DIR", "/usr/share/nltk_data") | ||||
|  | ||||
| TRASH_DIR = os.getenv("PAPERLESS_TRASH_DIR") | ||||
| # Check deprecated setting first | ||||
| EMPTY_TRASH_DIR = os.getenv( | ||||
|     "PAPERLESS_TRASH_DIR", | ||||
|     os.getenv("PAPERLESS_EMPTY_TRASH_DIR"), | ||||
| ) | ||||
|  | ||||
| # Lock file for synchronizing changes to the MEDIA directory across multiple | ||||
| # threads. | ||||
| @@ -1148,3 +1163,9 @@ EMAIL_SUBJECT_PREFIX: Final[str] = "[Paperless-ngx] " | ||||
| if DEBUG:  # pragma: no cover | ||||
|     EMAIL_BACKEND = "django.core.mail.backends.filebased.EmailBackend" | ||||
|     EMAIL_FILE_PATH = BASE_DIR / "sent_emails" | ||||
|  | ||||
|  | ||||
| ############################################################################### | ||||
| # Soft Delete | ||||
| ############################################################################### | ||||
| EMPTY_TRASH_DELAY = max(__get_int("PAPERLESS_EMPTY_TRASH_DELAY", 30), 1) | ||||
|   | ||||
| @@ -156,6 +156,7 @@ class TestCeleryScheduleParsing(TestCase): | ||||
|     CLASSIFIER_EXPIRE_TIME = 59.0 * 60.0 | ||||
|     INDEX_EXPIRE_TIME = 23.0 * 60.0 * 60.0 | ||||
|     SANITY_EXPIRE_TIME = ((7.0 * 24.0) - 1.0) * 60.0 * 60.0 | ||||
|     EMPTY_TRASH_EXPIRE_TIME = 23.0 * 60.0 * 60.0 | ||||
|  | ||||
|     def test_schedule_configuration_default(self): | ||||
|         """ | ||||
| @@ -190,6 +191,11 @@ class TestCeleryScheduleParsing(TestCase): | ||||
|                     "schedule": crontab(minute=30, hour=0, day_of_week="sun"), | ||||
|                     "options": {"expires": self.SANITY_EXPIRE_TIME}, | ||||
|                 }, | ||||
|                 "Empty trash": { | ||||
|                     "task": "documents.tasks.empty_trash", | ||||
|                     "schedule": crontab(minute=0, hour="1"), | ||||
|                     "options": {"expires": self.EMPTY_TRASH_EXPIRE_TIME}, | ||||
|                 }, | ||||
|             }, | ||||
|             schedule, | ||||
|         ) | ||||
| @@ -232,6 +238,11 @@ class TestCeleryScheduleParsing(TestCase): | ||||
|                     "schedule": crontab(minute=30, hour=0, day_of_week="sun"), | ||||
|                     "options": {"expires": self.SANITY_EXPIRE_TIME}, | ||||
|                 }, | ||||
|                 "Empty trash": { | ||||
|                     "task": "documents.tasks.empty_trash", | ||||
|                     "schedule": crontab(minute=0, hour="1"), | ||||
|                     "options": {"expires": self.EMPTY_TRASH_EXPIRE_TIME}, | ||||
|                 }, | ||||
|             }, | ||||
|             schedule, | ||||
|         ) | ||||
| @@ -266,6 +277,11 @@ class TestCeleryScheduleParsing(TestCase): | ||||
|                     "schedule": crontab(minute=30, hour=0, day_of_week="sun"), | ||||
|                     "options": {"expires": self.SANITY_EXPIRE_TIME}, | ||||
|                 }, | ||||
|                 "Empty trash": { | ||||
|                     "task": "documents.tasks.empty_trash", | ||||
|                     "schedule": crontab(minute=0, hour="1"), | ||||
|                     "options": {"expires": self.EMPTY_TRASH_EXPIRE_TIME}, | ||||
|                 }, | ||||
|             }, | ||||
|             schedule, | ||||
|         ) | ||||
| @@ -286,6 +302,7 @@ class TestCeleryScheduleParsing(TestCase): | ||||
|                 "PAPERLESS_TRAIN_TASK_CRON": "disable", | ||||
|                 "PAPERLESS_SANITY_TASK_CRON": "disable", | ||||
|                 "PAPERLESS_INDEX_TASK_CRON": "disable", | ||||
|                 "PAPERLESS_EMPTY_TRASH_TASK_CRON": "disable", | ||||
|             }, | ||||
|         ): | ||||
|             schedule = _parse_beat_schedule() | ||||
|   | ||||
| @@ -36,6 +36,7 @@ from documents.views import StoragePathViewSet | ||||
| from documents.views import SystemStatusView | ||||
| from documents.views import TagViewSet | ||||
| from documents.views import TasksViewSet | ||||
| from documents.views import TrashView | ||||
| from documents.views import UiSettingsView | ||||
| from documents.views import UnifiedSearchViewSet | ||||
| from documents.views import WorkflowActionViewSet | ||||
| @@ -159,6 +160,11 @@ urlpatterns = [ | ||||
|                     SystemStatusView.as_view(), | ||||
|                     name="system_status", | ||||
|                 ), | ||||
|                 re_path( | ||||
|                     "^trash/", | ||||
|                     TrashView.as_view(), | ||||
|                     name="trash", | ||||
|                 ), | ||||
|                 *api_router.urls, | ||||
|             ], | ||||
|         ), | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 shamoon
					shamoon